98 lines
3.5 KiB
JavaScript
98 lines
3.5 KiB
JavaScript
'use strict';
|
|
|
|
const ufo = require('ufo');
|
|
const vue = require('vue');
|
|
|
|
function normalizeSiteConfig(config) {
|
|
if (typeof config.indexable !== "undefined")
|
|
config.indexable = String(config.indexable) !== "false";
|
|
if (typeof config.trailingSlash !== "undefined" && !config.trailingSlash)
|
|
config.trailingSlash = String(config.trailingSlash) !== "false";
|
|
if (config.url && !ufo.hasProtocol(config.url, { acceptRelative: true, strict: false }))
|
|
config.url = ufo.withHttps(config.url);
|
|
const keys = Object.keys(config).sort((a, b) => a.localeCompare(b));
|
|
const newConfig = {};
|
|
for (const k of keys)
|
|
newConfig[k] = config[k];
|
|
return newConfig;
|
|
}
|
|
function validateSiteConfigStack(stack) {
|
|
const resolved = normalizeSiteConfig(stack.get({
|
|
// we need the context
|
|
debug: true
|
|
}));
|
|
const errors = [];
|
|
if (resolved.url) {
|
|
const val = resolved.url;
|
|
const context = resolved._context?.url || "unknown";
|
|
const url = ufo.parseURL(val);
|
|
if (!url.host)
|
|
errors.push(`url "${val}" from ${context} is not absolute`);
|
|
else if (url.pathname && url.pathname !== "/")
|
|
errors.push(`url "${val}" from ${context} should not contain a path`);
|
|
else if (url.hash)
|
|
errors.push(`url "${val}" from ${context} should not contain a hash`);
|
|
else if (Object.keys(ufo.getQuery(val)).length > 0)
|
|
errors.push(`url "${val}" from ${context} should not contain a query`);
|
|
else if (url.host === "localhost")
|
|
errors.push(`url "${val}" from ${context} should not be localhost`);
|
|
}
|
|
return errors;
|
|
}
|
|
function createSiteConfigStack(options) {
|
|
const debug = options?.debug || false;
|
|
const stack = [];
|
|
function push(input) {
|
|
if (!input || typeof input !== "object" || Object.keys(input).length === 0)
|
|
return;
|
|
if (!input._context && debug) {
|
|
let lastFunctionName = new Error("tmp").stack?.split("\n")[2].split(" ")[5];
|
|
if (lastFunctionName?.includes("/"))
|
|
lastFunctionName = "anonymous";
|
|
input._context = lastFunctionName;
|
|
}
|
|
const entry = {};
|
|
for (const k in input) {
|
|
const val = input[k];
|
|
if (typeof val !== "undefined" && val !== "")
|
|
entry[k] = val;
|
|
}
|
|
if (Object.keys(entry).filter((k) => !k.startsWith("_")).length > 0)
|
|
stack.push(entry);
|
|
}
|
|
function get(options2) {
|
|
const siteConfig = {};
|
|
if (options2?.debug)
|
|
siteConfig._context = {};
|
|
for (const o in stack.sort((a, b) => (a._priority || 0) - (b._priority || 0))) {
|
|
for (const k in stack[o]) {
|
|
const key = k;
|
|
const val = options2?.resolveRefs ? vue.toValue(stack[o][k]) : stack[o][k];
|
|
if (!k.startsWith("_") && typeof val !== "undefined") {
|
|
siteConfig[k] = val;
|
|
if (options2?.debug)
|
|
siteConfig._context[key] = stack[o]._context?.[key] || stack[o]._context || "anonymous";
|
|
}
|
|
}
|
|
}
|
|
return options2?.skipNormalize ? siteConfig : normalizeSiteConfig(siteConfig);
|
|
}
|
|
return {
|
|
stack,
|
|
push,
|
|
get
|
|
};
|
|
}
|
|
|
|
function envSiteConfig(env) {
|
|
return Object.fromEntries(Object.entries(env).filter(([k]) => k.startsWith("NUXT_SITE_") || k.startsWith("NUXT_PUBLIC_SITE_")).map(([k, v]) => [
|
|
k.replace(/^NUXT_(PUBLIC_)?SITE_/, "").split("_").map((s, i) => i === 0 ? s.toLowerCase() : s[0].toUpperCase() + s.slice(1).toLowerCase()).join(""),
|
|
v
|
|
]));
|
|
}
|
|
|
|
exports.createSiteConfigStack = createSiteConfigStack;
|
|
exports.envSiteConfig = envSiteConfig;
|
|
exports.normalizeSiteConfig = normalizeSiteConfig;
|
|
exports.validateSiteConfigStack = validateSiteConfigStack;
|