const _ = require('lodash'); const common = require('../../lib/common'); const _private = {}; _private.validateRoutes = function validateRoutes(routes) { _.each(routes, (routingTypeObject, routingTypeObjectKey) => { // CASE: we hard-require trailing slashes for the index route if (!routingTypeObjectKey.match(/\/$/)) { throw new common.errors.ValidationError({ message: common.i18n.t('errors.services.settings.yaml.validate', { at: routingTypeObjectKey, reason: 'A trailing slash is required.' }) }); } // CASE: we hard-require leading slashes for the index route if (!routingTypeObjectKey.match(/^\//)) { throw new common.errors.ValidationError({ message: common.i18n.t('errors.services.settings.yaml.validate', { at: routingTypeObjectKey, reason: 'A leading slash is required.' }) }); } // CASE: you define /about/: if (!routingTypeObject) { throw new common.errors.ValidationError({ message: common.i18n.t('errors.services.settings.yaml.validate', { at: routingTypeObjectKey, reason: 'Please define a permalink route.' }), help: 'e.g. permalink: /{slug}/' }); } }); return routes; }; _private.validateCollections = function validateCollections(collections) { _.each(collections, (routingTypeObject, routingTypeObjectKey) => { // CASE: we hard-require trailing slashes for the collection index route if (!routingTypeObjectKey.match(/\/$/)) { throw new common.errors.ValidationError({ message: common.i18n.t('errors.services.settings.yaml.validate', { at: routingTypeObjectKey, reason: 'A trailing slash is required.' }) }); } // CASE: we hard-require leading slashes for the collection index route if (!routingTypeObjectKey.match(/^\//)) { throw new common.errors.ValidationError({ message: common.i18n.t('errors.services.settings.yaml.validate', { at: routingTypeObjectKey, reason: 'A leading slash is required.' }) }); } if (!routingTypeObject.hasOwnProperty('permalink')) { throw new common.errors.ValidationError({ message: common.i18n.t('errors.services.settings.yaml.validate', { at: routingTypeObjectKey, reason: 'Please define a permalink route.' }), help: 'e.g. permalink: /{slug}/' }); } // CASE: validate permalink key if (routingTypeObject.hasOwnProperty('permalink')) { if (!routingTypeObject.permalink) { throw new common.errors.ValidationError({ message: common.i18n.t('errors.services.settings.yaml.validate', { at: routingTypeObjectKey, reason: 'Please define a permalink route.' }), help: 'e.g. permalink: /{slug}/' }); } // CASE: we hard-require trailing slashes for the value/permalink route if (!routingTypeObject.permalink.match(/\/$/) && !routingTypeObject.permalink.match(/globals\.permalinks/)) { throw new common.errors.ValidationError({ message: common.i18n.t('errors.services.settings.yaml.validate', { at: routingTypeObject.permalink, reason: 'A trailing slash is required.' }) }); } // CASE: we hard-require leading slashes for the value/permalink route if (!routingTypeObject.permalink.match(/^\//) && !routingTypeObject.permalink.match(/globals\.permalinks/)) { throw new common.errors.ValidationError({ message: common.i18n.t('errors.services.settings.yaml.validate', { at: routingTypeObject.permalink, reason: 'A leading slash is required.' }) }); } // CASE: notation /:slug/ or /:primary_author/ is not allowed. We only accept /{{...}}/. if (routingTypeObject.permalink && routingTypeObject.permalink.match(/\/\:\w+/)) { throw new common.errors.ValidationError({ message: common.i18n.t('errors.services.settings.yaml.validate', { at: routingTypeObject.permalink, reason: 'Please use the following notation e.g. /{slug}/.' }) }); } // CASE: transform {.*} into :\w+ notation. This notation is our internal notation e.g. see permalink // replacement in our UrlService utility. if (routingTypeObject.permalink.match(/{.*}/)) { routingTypeObject.permalink = routingTypeObject.permalink.replace(/{(\w+)}/g, ':$1'); } } }); return collections; }; _private.validateTaxonomies = function validateTaxonomies(taxonomies) { _.each(taxonomies, (routingTypeObject, routingTypeObjectKey) => { if (!routingTypeObject) { throw new common.errors.ValidationError({ message: common.i18n.t('errors.services.settings.yaml.validate', { at: routingTypeObjectKey, reason: 'Please define a taxonomy permalink route.' }), help: 'e.g. tag: /tag/{slug}/' }); } // CASE: we hard-require trailing slashes for the taxonomie permalink route if (!routingTypeObject.match(/\/$/)) { throw new common.errors.ValidationError({ message: common.i18n.t('errors.services.settings.yaml.validate', { at: routingTypeObject, reason: 'A trailing slash is required.' }) }); } // CASE: we hard-require leading slashes for the value/permalink route if (!routingTypeObject.match(/^\//)) { throw new common.errors.ValidationError({ message: common.i18n.t('errors.services.settings.yaml.validate', { at: routingTypeObject, reason: 'A leading slash is required.' }) }); } // CASE: notation /:slug/ or /:primary_author/ is not allowed. We only accept /{{...}}/. if (routingTypeObject && routingTypeObject.match(/\/\:\w+/)) { throw new common.errors.ValidationError({ message: common.i18n.t('errors.services.settings.yaml.validate', { at: routingTypeObject, reason: 'Please use the following notation e.g. /{slug}/.' }) }); } // CASE: transform {.*} into :\w+ notation. This notation is our internal notation e.g. see permalink // replacement in our UrlService utility. if (routingTypeObject && routingTypeObject.match(/{.*}/)) { routingTypeObject = routingTypeObject.replace(/{(\w+)}/g, ':$1'); taxonomies[routingTypeObjectKey] = routingTypeObject; } }); return taxonomies; }; /** * Validate and sanitize the routing object. */ module.exports = function validate(object) { if (!object) { object = {}; } if (!object.routes) { object.routes = {}; } if (!object.collections) { object.collections = {}; } if (!object.taxonomies) { object.taxonomies = {}; } object.routes = _private.validateRoutes(object.routes); object.collections = _private.validateCollections(object.collections); object.taxonomies = _private.validateTaxonomies(object.taxonomies); return object; };