@netlify/content-engine
Version:
186 lines • 8.34 kB
JavaScript
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
;