Ghost/core/frontend/helpers/navigation.js
Hannah Wolfe 22e13acd65 Updated var declarations to const/let and no lists
- All var declarations are now const or let as per ES6
- All comma-separated lists / chained declarations are now one declaration per line
- This is for clarity/readability but also made running the var-to-const/let switch smoother
- ESLint rules updated to match

How this was done:

- npm install -g jscodeshift
- git clone https://github.com/cpojer/js-codemod.git
- git clone git@github.com:TryGhost/Ghost.git shallow-ghost
- cd shallow-ghost
- jscodeshift -t ../js-codemod/transforms/unchain-variables.js . -v=2
- jscodeshift -t ../js-codemod/transforms/no-vars.js . -v=2
- yarn
- yarn test
- yarn lint / fix various lint errors (almost all indent) by opening files and saving in vscode
- grunt test-regression
- sorted!
2020-04-29 16:51:13 +01:00

82 lines
2.7 KiB
JavaScript

// ### Navigation Helper
// `{{navigation}}`
// Outputs navigation menu of static urls
const {SafeString, i18n, errors, templates, hbs} = require('../services/proxy');
const {slugify} = require('@tryghost/string');
const _ = require('lodash');
const createFrame = hbs.handlebars.createFrame;
module.exports = function navigation(options) {
options = options || {};
options.hash = options.hash || {};
options.data = options.data || {};
const key = options.hash.type && options.hash.type === 'secondary' ? 'secondary_navigation' : 'navigation';
options.hash.isSecondary = options.hash.type && options.hash.type === 'secondary';
delete options.hash.type;
const navigationData = options.data.site[key];
const currentUrl = options.data.root.relativeUrl;
const self = this;
let output;
if (!_.isObject(navigationData) || _.isFunction(navigationData)) {
throw new errors.IncorrectUsageError({
message: i18n.t('warnings.helpers.navigation.invalidData')
});
}
if (navigationData.filter(function (e) {
return (_.isUndefined(e.label) || _.isUndefined(e.url));
}).length > 0) {
throw new errors.IncorrectUsageError({
message: i18n.t('warnings.helpers.navigation.valuesMustBeDefined')
});
}
// check for non-null string values
if (navigationData.filter(function (e) {
return ((!_.isNull(e.label) && !_.isString(e.label)) ||
(!_.isNull(e.url) && !_.isString(e.url)));
}).length > 0) {
throw new errors.IncorrectUsageError({
message: i18n.t('warnings.helpers.navigation.valuesMustBeString')
});
}
// strips trailing slashes and compares urls
function _isCurrentUrl(href, currentUrl) {
if (!currentUrl) {
return false;
}
const strippedHref = href.replace(/\/+$/, '');
const strippedCurrentUrl = currentUrl.replace(/\/+$/, '');
return strippedHref === strippedCurrentUrl;
}
// {{navigation}} should no-op if no data passed in
if (navigationData.length === 0) {
return new SafeString('');
}
output = navigationData.map(function (e) {
const out = {};
out.current = _isCurrentUrl(e.url, currentUrl);
out.label = e.label;
out.slug = slugify(e.label);
out.url = e.url;
out.secure = self.secure;
return out;
});
// CASE: The navigation helper should have access to the navigation items at the top level.
this.navigation = output;
// CASE: The navigation helper will forward attributes passed to it.
_.merge(this, options.hash);
const data = createFrame(options.data);
return templates.execute('navigation', this, {data});
};