UNPKG

@netlify/content-engine

Version:
186 lines 8.34 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.loadThemes = loadThemes; const create_require_from_path_1 = require("../../core-utils/create-require-from-path"); const path = __importStar(require("path")); const merge_gatsby_config_1 = require("../../utils/merge-gatsby-config"); const lodash_uniqwith_1 = __importDefault(require("lodash.uniqwith")); const lodash_isequal_1 = __importDefault(require("lodash.isequal")); const prefer_default_1 = require("../prefer-default"); const get_config_file_1 = require("../get-config-file"); const resolve_plugin_1 = require("../load-plugins/resolve-plugin"); const reporter_1 = __importDefault(require("../../reporter")); // get the gatsby-config file for a theme const resolveTheme = async (themeSpec, configFileThatDeclaredTheme, isMainConfig = false, rootDir) => { const themeName = typeof themeSpec === `string` ? themeSpec : themeSpec.resolve; let themeDir; try { const scopedRequire = (0, create_require_from_path_1.createRequireFromPath)(`${rootDir}/:internal:`); // theme is an node-resolvable module themeDir = path.dirname(scopedRequire.resolve(themeName)); } catch (e) { let pathToLocalTheme; // only try to look for local theme in main site // local themes nested in other themes is potential source of problems: // because those are not hosted by npm, there is potential for multiple // local themes with same name that do different things and name being // main identifier that Gatsby uses right now, it's safer not to support it for now. if (isMainConfig) { pathToLocalTheme = path.join(rootDir, `plugins`, themeName); // is a local plugin OR it doesn't exist try { const { resolve } = (0, resolve_plugin_1.resolvePlugin)(themeName, rootDir); themeDir = resolve; } catch (localErr) { reporter_1.default.panic(`Failed to resolve ${themeName}`, localErr); } } if (!themeDir) { const nodeResolutionPaths = module.paths.map((p) => path.join(p, themeName)); reporter_1.default.panic({ id: `10226`, context: { themeName, configFilePath: configFileThatDeclaredTheme, pathToLocalTheme, nodeResolutionPaths, }, }); } } const { configModule, configFilePath } = await (0, get_config_file_1.getConfigFile)(themeDir, `gatsby-config`); const theme = (0, prefer_default_1.preferDefault)(configModule); // if theme is a function, call it with the themeConfig const themeConfig = typeof theme === `function` ? theme(typeof themeSpec === `string` ? {} : themeSpec.options) : theme; return { themeName, themeConfig, themeSpec, themeDir, parentDir: rootDir, configFilePath, }; }; // single iteration of a recursive function that resolve parent themes // It's recursive because we support child themes declaring parents and // have to resolve all the way `up the tree` of parent/children relationships // // Theoretically, there could be an infinite loop here but in practice there is // no use case for a loop so I expect that to only happen if someone is very // off track and creating their own set of themes const processTheme = async ({ themeName, themeConfig, themeSpec, themeDir, configFilePath }, { rootDir }) => { const themesList = themeConfig?.plugins; // Gatsby themes don't have to specify a gatsby-config.js (they might only use gatsby-node, etc) // in this case they're technically plugins, but we should support it anyway // because we can't guarantee which files theme creators create first if (themeConfig && themesList) { const result = []; // for every parent theme a theme defines, resolve the parent's // gatsby config and return it in order [parentA, parentB, child] for (const spec of themesList) { const themeObj = await resolveTheme(spec, configFilePath, false, themeDir); result.push(await processTheme(themeObj, { rootDir: themeDir })); } const flat = result.flat(); flat.push({ themeName, themeConfig, themeSpec, themeDir, parentDir: rootDir, }); return flat; } else { // if a theme doesn't define additional themes, return the original theme return Promise.resolve([ { themeName, themeConfig, themeSpec, themeDir, parentDir: rootDir }, ]); } }; function normalizePluginEntry(plugin, parentDir) { return { resolve: typeof plugin === `string` ? plugin : plugin.resolve, options: typeof plugin === `string` ? {} : plugin.options || {}, parentDir, }; } async function loadThemes(config, { configFilePath, rootDir }) { const themesA = []; for (const plugin of config?.plugins || []) { if ((typeof plugin !== `string` && plugin?.resolve === `default-site-plugin`) || plugin === `default-site-plugin`) { continue; } const themeObj = await resolveTheme(plugin, configFilePath, true, rootDir); themesA.push(await processTheme(themeObj, { rootDir })); } const themesAFlat = themesA.flat(); let newConfig = {}; // map over each theme, adding the theme itself to the plugins // list in the config for the theme. This enables the usage of // gatsby-node, etc in themes. for (const { themeName, themeConfig = {}, themeSpec, themeDir, parentDir, } of themesAFlat) { /** * themes resolve to a gatsby-config, so here we merge all of the configs * into a single config, making sure to maintain the order in which * they were defined so that later configs, like the user's site and * children, can override functionality in earlier themes. */ newConfig = (0, merge_gatsby_config_1.mergeGatsbyConfig)({ ...themeConfig, plugins: [ ...(themeConfig.plugins || []).map((plugin) => normalizePluginEntry(plugin, themeDir)), // theme plugin is last so it's gatsby-node, etc can override it's declared plugins, like a normal site. { resolve: themeName, options: typeof themeSpec === `string` ? {} : themeSpec.options, parentDir, }, ], }, newConfig); } const mergedConfig = (0, merge_gatsby_config_1.mergeGatsbyConfig)(newConfig, { ...config, plugins: [ ...(config.plugins || []).map((plugin) => normalizePluginEntry(plugin, rootDir)), ], }); mergedConfig.plugins = (0, lodash_uniqwith_1.default)(mergedConfig.plugins, lodash_isequal_1.default); return { config: mergedConfig, themes: themesAFlat, }; } //# sourceMappingURL=index.js.map