UNPKG

phenomic

Version:

Modern website generator based on the React and Webpack ecosystem.

169 lines (130 loc) 5.71 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _reactRouter = require("react-router"); var _chalk = require("chalk"); var _chalk2 = _interopRequireDefault(_chalk); var _urlJoin = require("url-join"); var _urlJoin2 = _interopRequireDefault(_urlJoin); var _arrayUnique = require("../../_utils/array-unique"); var _arrayUnique2 = _interopRequireDefault(_arrayUnique); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } var defaultConsole = console.log; var flattenRoute = function flattenRoute(route) { // @todo remove the default route.path, user should use IndexRoute instead? var routesUrls = route.path ? [route.path] : []; if (route.indexRoute) { routesUrls.push(route.path); } if (route.childRoutes) { var root = route.path; route.childRoutes.forEach(function (route) { routesUrls = [].concat(_toConsumableArray(routesUrls), _toConsumableArray(flattenRoute(route).map(function (r) { return root ? (0, _urlJoin2.default)(root, r) : r; }))); }); } return routesUrls; }; // only simple types will be accepted // array<string | number> | string | number // other will be skipped var paramsListFromCollection = function paramsListFromCollection(collection) { var params = {}; collection.forEach(function (item) { if (!item.head) { return; } Object.keys(item.head).forEach(function (key) { // array<string | number> if (Array.isArray(item.head[key]) && item.head[key].length && (typeof item.head[key][0] === "string" || typeof item.head[key][0] === "number")) { var k = key // categories => category .replace(/ies$/, "y") // tags => tag .replace(/s$/, ""); if (!params[k]) { params[k] = []; } params[k] = [].concat(_toConsumableArray(params[k]), _toConsumableArray(item.head[key])); } // string, number if (typeof item.head[key] === "string" || typeof item.head[key] === "number") { if (!params[key]) { params[key] = []; } params[key].push(item.head[key]); } }); }); params.splat = collection.map(function (item) { return item.__url; }); return params; }; var createUrlsFromParamsReplacementInUrl = function createUrlsFromParamsReplacementInUrl(url, params, log) { // don't compute anything if url doesn't seems to have dynamic parameters // react-router url params are like ``:that`` (or splat *) if (url.indexOf(":") === -1 && url.indexOf("*") === -1) { return [url]; } var urls = []; var possibleErrorEnd = "parameter for path \"" + url + "\""; var missingKeys = []; var nonMissingKeys = []; Object.keys(params).forEach(function (paramName) { params[paramName].forEach(function (paramValue) { var urlParams = _defineProperty({}, paramName, paramValue); try { var hydratedUrl = (0, _reactRouter.formatPattern)(url, urlParams); urls.push(hydratedUrl); nonMissingKeys.push(paramName); } catch (e) { // log(paramName, e.message) var matches = e.message.match(/Missing \"(.*)\" parameter for path/); if (matches && matches[1]) { missingKeys.push(matches[1]); } if (e.message.indexOf("Missing") === 0 && e.message.lastIndexOf(possibleErrorEnd) === e.message.length - possibleErrorEnd.length - 1) { throw e; } } }); }); nonMissingKeys = (0, _arrayUnique2.default)(nonMissingKeys); missingKeys = (0, _arrayUnique2.default)(missingKeys).filter(function (key) { return nonMissingKeys.indexOf(key) === -1; }); if (missingKeys.length) { log("⚠️ " + _chalk2.default.red("It looks like some parameters can't be mapped to create routes: ", missingKeys.map(function (key) { return ":" + key; }).join(", "))); } // @todo improve the algorithm to avoid duplicates, // we will probably get better perfs return (0, _arrayUnique2.default)(urls.sort()); }; var hydrateRoutesUrls = function hydrateRoutesUrls(routesUrls, collection, log) { var paramsList = paramsListFromCollection(collection); return routesUrls.reduce(function (acc, url) { return [].concat(_toConsumableArray(acc), _toConsumableArray(createUrlsFromParamsReplacementInUrl(url, paramsList, log))); }, []); }; exports.default = function (routes, collection) { var log = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : defaultConsole; var flattenedRoutes = (0, _arrayUnique2.default)((0, _reactRouter.createRoutes)(routes).reduce(function (acc, r) { return [].concat(_toConsumableArray(acc), _toConsumableArray(flattenRoute(r))); }, [])); if (flattenedRoutes.filter(function (url) { return url.indexOf("*") > -1; }).length > 1) { throw new Error("Phenomic can only handle one splat (*) in react-router routes. \n" + "You must use only one splat. If you have a specific need, do not " + "hesitate to open an issue at " + "https://github.com/MoOx/phenomic/issues/new"); } var normalizedRoutes = flattenedRoutes.map(function (route) { return "/" + route.replace(/^\/+/, "").replace(/\/+$/, ""); }); return hydrateRoutesUrls(normalizedRoutes, collection, log); };