2025-09-05 14:59:21 +08:00

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;