7750 lines
249 KiB
JavaScript
7750 lines
249 KiB
JavaScript
import process from 'node:process';globalThis._importMeta_={url:import.meta.url,env:process.env};import { tmpdir } from 'node:os';
|
|
import { Server } from 'node:http';
|
|
import { resolve as resolve$1, dirname, join } from 'node:path';
|
|
import nodeCrypto from 'node:crypto';
|
|
import { parentPort, threadId } from 'node:worker_threads';
|
|
import { defineEventHandler, handleCacheHeaders, splitCookiesString, createEvent, fetchWithEvent, isEvent, eventHandler, setHeaders, sendRedirect, proxyRequest, getRequestHeader, setResponseHeaders, setResponseStatus, send, getRequestHeaders, setResponseHeader, appendResponseHeader, getRequestURL, getResponseHeader, getResponseStatus, createError, getRequestHost, getRequestProtocol, getQuery as getQuery$1, removeResponseHeader, setHeader, getCookie, getHeader, readBody, createApp, createRouter as createRouter$1, toNodeListener, lazyEventHandler, getRouterParam, getResponseStatusText } from 'file://D:/claude-project/web7-published/node_modules/h3/dist/index.mjs';
|
|
import { escapeHtml } from 'file://D:/claude-project/web7-published/node_modules/@vue/shared/dist/shared.cjs.js';
|
|
import _RemarkEmoji from 'file://D:/claude-project/web7-published/node_modules/remark-emoji/index.js';
|
|
import { createRenderer, getRequestDependencies, getPreloadLinks, getPrefetchLinks } from 'file://D:/claude-project/web7-published/node_modules/vue-bundle-renderer/dist/runtime.mjs';
|
|
import { stringify, uneval } from 'file://D:/claude-project/web7-published/node_modules/devalue/index.js';
|
|
import { createHead as createHead$1, propsToString, renderSSRHead } from 'file://D:/claude-project/web7-published/node_modules/nuxt/node_modules/unhead/dist/server.mjs';
|
|
import defu, { defuFn, defu as defu$1, createDefu } from 'file://D:/claude-project/web7-published/node_modules/defu/dist/defu.mjs';
|
|
import { toRouteMatcher, createRouter } from 'file://D:/claude-project/web7-published/node_modules/radix3/dist/index.mjs';
|
|
import consola, { consola as consola$1, createConsola } from 'file://D:/claude-project/web7-published/node_modules/consola/dist/index.mjs';
|
|
import { klona } from 'file://D:/claude-project/web7-published/node_modules/klona/dist/index.mjs';
|
|
import destr, { destr as destr$1 } from 'file://D:/claude-project/web7-published/node_modules/destr/dist/index.mjs';
|
|
import { snakeCase, kebabCase, pascalCase, camelCase } from 'file://D:/claude-project/web7-published/node_modules/scule/dist/index.mjs';
|
|
import { createHooks } from 'file://D:/claude-project/web7-published/node_modules/hookable/dist/index.mjs';
|
|
import { createFetch, Headers as Headers$1 } from 'file://D:/claude-project/web7-published/node_modules/ofetch/dist/node.mjs';
|
|
import { fetchNodeRequestHandler, callNodeRequestHandler } from 'file://D:/claude-project/web7-published/node_modules/node-mock-http/dist/index.mjs';
|
|
import { createStorage, prefixStorage } from 'file://D:/claude-project/web7-published/node_modules/unstorage/dist/index.mjs';
|
|
import unstorage_47drivers_47fs from 'file://D:/claude-project/web7-published/node_modules/unstorage/drivers/fs.mjs';
|
|
import { digest } from 'file://D:/claude-project/web7-published/node_modules/nitropack/node_modules/ohash/dist/index.mjs';
|
|
import { readFile } from 'node:fs/promises';
|
|
import { ErrorParser } from 'file://D:/claude-project/web7-published/node_modules/youch-core/build/index.js';
|
|
import { Youch } from 'file://D:/claude-project/web7-published/node_modules/nitropack/node_modules/youch/build/index.js';
|
|
import { SourceMapConsumer } from 'file://D:/claude-project/web7-published/node_modules/nitropack/node_modules/source-map/source-map.js';
|
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
import { getContext } from 'file://D:/claude-project/web7-published/node_modules/unctx/dist/index.mjs';
|
|
import { captureRawStackTrace, parseRawStackTrace } from 'file://D:/claude-project/web7-published/node_modules/errx/dist/index.js';
|
|
import { isVNode, toValue, isRef } from 'file://D:/claude-project/web7-published/node_modules/vue/index.mjs';
|
|
import devalue from 'file://D:/claude-project/web7-published/node_modules/@nuxt/devalue/dist/devalue.mjs';
|
|
import { promises } from 'node:fs';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { dirname as dirname$1, resolve as resolve$2, extname } from 'file://D:/claude-project/web7-published/node_modules/pathe/dist/index.mjs';
|
|
import { hash as hash$1 } from 'file://D:/claude-project/web7-published/node_modules/ohash/dist/index.mjs';
|
|
import { unified } from 'file://D:/claude-project/web7-published/node_modules/unified/index.js';
|
|
import { toString as toString$1 } from 'file://D:/claude-project/web7-published/node_modules/mdast-util-to-string/index.js';
|
|
import { postprocess, preprocess } from 'file://D:/claude-project/web7-published/node_modules/micromark/dev/index.js';
|
|
import { stringifyPosition } from 'file://D:/claude-project/web7-published/node_modules/unist-util-stringify-position/index.js';
|
|
import { markdownLineEnding, markdownSpace } from 'file://D:/claude-project/web7-published/node_modules/micromark-util-character/dev/index.js';
|
|
import { push, splice } from 'file://D:/claude-project/web7-published/node_modules/micromark-util-chunked/dev/index.js';
|
|
import { resolveAll } from 'file://D:/claude-project/web7-published/node_modules/micromark-util-resolve-all/index.js';
|
|
import { normalizeUri } from 'file://D:/claude-project/web7-published/node_modules/micromark-util-sanitize-uri/dev/index.js';
|
|
import slugify from 'file://D:/claude-project/web7-published/node_modules/slugify/slugify.js';
|
|
import remarkParse from 'file://D:/claude-project/web7-published/node_modules/remark-parse/index.js';
|
|
import remark2rehype from 'file://D:/claude-project/web7-published/node_modules/remark-rehype/index.js';
|
|
import remarkMDC, { parseFrontMatter } from 'file://D:/claude-project/web7-published/node_modules/remark-mdc/dist/index.mjs';
|
|
import remarkGFM from 'file://D:/claude-project/web7-published/node_modules/remark-gfm/index.js';
|
|
import rehypeExternalLinks from 'file://D:/claude-project/web7-published/node_modules/rehype-external-links/index.js';
|
|
import rehypeSortAttributeValues from 'file://D:/claude-project/web7-published/node_modules/rehype-sort-attribute-values/index.js';
|
|
import rehypeSortAttributes from 'file://D:/claude-project/web7-published/node_modules/rehype-sort-attributes/index.js';
|
|
import rehypeRaw from 'file://D:/claude-project/web7-published/node_modules/rehype-raw/index.js';
|
|
import { detab } from 'file://D:/claude-project/web7-published/node_modules/detab/index.js';
|
|
import { toString } from 'file://D:/claude-project/web7-published/node_modules/hast-util-to-string/index.js';
|
|
import Slugger from 'file://D:/claude-project/web7-published/node_modules/github-slugger/index.js';
|
|
import { DeprecationsPlugin, PromisesPlugin, TemplateParamsPlugin, AliasSortingPlugin } from 'file://D:/claude-project/web7-published/node_modules/nuxt/node_modules/unhead/dist/plugins.mjs';
|
|
import { renderToString } from 'file://D:/claude-project/web7-published/node_modules/vue/server-renderer/index.mjs';
|
|
import { walkResolver } from 'file://D:/claude-project/web7-published/node_modules/nuxt/node_modules/unhead/dist/utils.mjs';
|
|
|
|
const HASH_RE = /#/g;
|
|
const AMPERSAND_RE = /&/g;
|
|
const SLASH_RE = /\//g;
|
|
const EQUAL_RE = /=/g;
|
|
const IM_RE = /\?/g;
|
|
const PLUS_RE = /\+/g;
|
|
const ENC_CARET_RE = /%5e/gi;
|
|
const ENC_BACKTICK_RE = /%60/gi;
|
|
const ENC_PIPE_RE = /%7c/gi;
|
|
const ENC_SPACE_RE = /%20/gi;
|
|
const ENC_SLASH_RE = /%2f/gi;
|
|
const ENC_ENC_SLASH_RE = /%252f/gi;
|
|
function encode(text) {
|
|
return encodeURI("" + text).replace(ENC_PIPE_RE, "|");
|
|
}
|
|
function encodeQueryValue(input) {
|
|
return encode(typeof input === "string" ? input : JSON.stringify(input)).replace(PLUS_RE, "%2B").replace(ENC_SPACE_RE, "+").replace(HASH_RE, "%23").replace(AMPERSAND_RE, "%26").replace(ENC_BACKTICK_RE, "`").replace(ENC_CARET_RE, "^").replace(SLASH_RE, "%2F");
|
|
}
|
|
function encodeQueryKey(text) {
|
|
return encodeQueryValue(text).replace(EQUAL_RE, "%3D");
|
|
}
|
|
function encodePath(text) {
|
|
return encode(text).replace(HASH_RE, "%23").replace(IM_RE, "%3F").replace(ENC_ENC_SLASH_RE, "%2F").replace(AMPERSAND_RE, "%26").replace(PLUS_RE, "%2B");
|
|
}
|
|
function decode(text = "") {
|
|
try {
|
|
return decodeURIComponent("" + text);
|
|
} catch {
|
|
return "" + text;
|
|
}
|
|
}
|
|
function decodePath(text) {
|
|
return decode(text.replace(ENC_SLASH_RE, "%252F"));
|
|
}
|
|
function decodeQueryKey(text) {
|
|
return decode(text.replace(PLUS_RE, " "));
|
|
}
|
|
function decodeQueryValue(text) {
|
|
return decode(text.replace(PLUS_RE, " "));
|
|
}
|
|
|
|
function parseQuery(parametersString = "") {
|
|
const object = /* @__PURE__ */ Object.create(null);
|
|
if (parametersString[0] === "?") {
|
|
parametersString = parametersString.slice(1);
|
|
}
|
|
for (const parameter of parametersString.split("&")) {
|
|
const s = parameter.match(/([^=]+)=?(.*)/) || [];
|
|
if (s.length < 2) {
|
|
continue;
|
|
}
|
|
const key = decodeQueryKey(s[1]);
|
|
if (key === "__proto__" || key === "constructor") {
|
|
continue;
|
|
}
|
|
const value = decodeQueryValue(s[2] || "");
|
|
if (object[key] === void 0) {
|
|
object[key] = value;
|
|
} else if (Array.isArray(object[key])) {
|
|
object[key].push(value);
|
|
} else {
|
|
object[key] = [object[key], value];
|
|
}
|
|
}
|
|
return object;
|
|
}
|
|
function encodeQueryItem(key, value) {
|
|
if (typeof value === "number" || typeof value === "boolean") {
|
|
value = String(value);
|
|
}
|
|
if (!value) {
|
|
return encodeQueryKey(key);
|
|
}
|
|
if (Array.isArray(value)) {
|
|
return value.map(
|
|
(_value) => `${encodeQueryKey(key)}=${encodeQueryValue(_value)}`
|
|
).join("&");
|
|
}
|
|
return `${encodeQueryKey(key)}=${encodeQueryValue(value)}`;
|
|
}
|
|
function stringifyQuery(query) {
|
|
return Object.keys(query).filter((k) => query[k] !== void 0).map((k) => encodeQueryItem(k, query[k])).filter(Boolean).join("&");
|
|
}
|
|
|
|
const PROTOCOL_STRICT_REGEX = /^[\s\w\0+.-]{2,}:([/\\]{1,2})/;
|
|
const PROTOCOL_REGEX = /^[\s\w\0+.-]{2,}:([/\\]{2})?/;
|
|
const PROTOCOL_RELATIVE_REGEX = /^([/\\]\s*){2,}[^/\\]/;
|
|
const JOIN_LEADING_SLASH_RE = /^\.?\//;
|
|
function isRelative(inputString) {
|
|
return ["./", "../"].some((string_) => inputString.startsWith(string_));
|
|
}
|
|
function hasProtocol(inputString, opts = {}) {
|
|
if (typeof opts === "boolean") {
|
|
opts = { acceptRelative: opts };
|
|
}
|
|
if (opts.strict) {
|
|
return PROTOCOL_STRICT_REGEX.test(inputString);
|
|
}
|
|
return PROTOCOL_REGEX.test(inputString) || (opts.acceptRelative ? PROTOCOL_RELATIVE_REGEX.test(inputString) : false);
|
|
}
|
|
function hasTrailingSlash(input = "", respectQueryAndFragment) {
|
|
{
|
|
return input.endsWith("/");
|
|
}
|
|
}
|
|
function withoutTrailingSlash(input = "", respectQueryAndFragment) {
|
|
{
|
|
return (hasTrailingSlash(input) ? input.slice(0, -1) : input) || "/";
|
|
}
|
|
}
|
|
function withTrailingSlash(input = "", respectQueryAndFragment) {
|
|
{
|
|
return input.endsWith("/") ? input : input + "/";
|
|
}
|
|
}
|
|
function hasLeadingSlash(input = "") {
|
|
return input.startsWith("/");
|
|
}
|
|
function withoutLeadingSlash(input = "") {
|
|
return (hasLeadingSlash(input) ? input.slice(1) : input) || "/";
|
|
}
|
|
function withLeadingSlash(input = "") {
|
|
return hasLeadingSlash(input) ? input : "/" + input;
|
|
}
|
|
function withBase(input, base) {
|
|
if (isEmptyURL(base) || hasProtocol(input)) {
|
|
return input;
|
|
}
|
|
const _base = withoutTrailingSlash(base);
|
|
if (input.startsWith(_base)) {
|
|
return input;
|
|
}
|
|
return joinURL(_base, input);
|
|
}
|
|
function withoutBase(input, base) {
|
|
if (isEmptyURL(base)) {
|
|
return input;
|
|
}
|
|
const _base = withoutTrailingSlash(base);
|
|
if (!input.startsWith(_base)) {
|
|
return input;
|
|
}
|
|
const trimmed = input.slice(_base.length);
|
|
return trimmed[0] === "/" ? trimmed : "/" + trimmed;
|
|
}
|
|
function withQuery(input, query) {
|
|
const parsed = parseURL(input);
|
|
const mergedQuery = { ...parseQuery(parsed.search), ...query };
|
|
parsed.search = stringifyQuery(mergedQuery);
|
|
return stringifyParsedURL(parsed);
|
|
}
|
|
function getQuery(input) {
|
|
return parseQuery(parseURL(input).search);
|
|
}
|
|
function isEmptyURL(url) {
|
|
return !url || url === "/";
|
|
}
|
|
function isNonEmptyURL(url) {
|
|
return url && url !== "/";
|
|
}
|
|
function joinURL(base, ...input) {
|
|
let url = base || "";
|
|
for (const segment of input.filter((url2) => isNonEmptyURL(url2))) {
|
|
if (url) {
|
|
const _segment = segment.replace(JOIN_LEADING_SLASH_RE, "");
|
|
url = withTrailingSlash(url) + _segment;
|
|
} else {
|
|
url = segment;
|
|
}
|
|
}
|
|
return url;
|
|
}
|
|
function joinRelativeURL(..._input) {
|
|
const JOIN_SEGMENT_SPLIT_RE = /\/(?!\/)/;
|
|
const input = _input.filter(Boolean);
|
|
const segments = [];
|
|
let segmentsDepth = 0;
|
|
for (const i of input) {
|
|
if (!i || i === "/") {
|
|
continue;
|
|
}
|
|
for (const [sindex, s] of i.split(JOIN_SEGMENT_SPLIT_RE).entries()) {
|
|
if (!s || s === ".") {
|
|
continue;
|
|
}
|
|
if (s === "..") {
|
|
if (segments.length === 1 && hasProtocol(segments[0])) {
|
|
continue;
|
|
}
|
|
segments.pop();
|
|
segmentsDepth--;
|
|
continue;
|
|
}
|
|
if (sindex === 1 && segments[segments.length - 1]?.endsWith(":/")) {
|
|
segments[segments.length - 1] += "/" + s;
|
|
continue;
|
|
}
|
|
segments.push(s);
|
|
segmentsDepth++;
|
|
}
|
|
}
|
|
let url = segments.join("/");
|
|
if (segmentsDepth >= 0) {
|
|
if (input[0]?.startsWith("/") && !url.startsWith("/")) {
|
|
url = "/" + url;
|
|
} else if (input[0]?.startsWith("./") && !url.startsWith("./")) {
|
|
url = "./" + url;
|
|
}
|
|
} else {
|
|
url = "../".repeat(-1 * segmentsDepth) + url;
|
|
}
|
|
if (input[input.length - 1]?.endsWith("/") && !url.endsWith("/")) {
|
|
url += "/";
|
|
}
|
|
return url;
|
|
}
|
|
function withHttps(input) {
|
|
return withProtocol(input, "https://");
|
|
}
|
|
function withoutProtocol(input) {
|
|
return withProtocol(input, "");
|
|
}
|
|
function withProtocol(input, protocol) {
|
|
let match = input.match(PROTOCOL_REGEX);
|
|
if (!match) {
|
|
match = input.match(/^\/{2,}/);
|
|
}
|
|
if (!match) {
|
|
return protocol + input;
|
|
}
|
|
return protocol + input.slice(match[0].length);
|
|
}
|
|
|
|
const protocolRelative = Symbol.for("ufo:protocolRelative");
|
|
function parseURL(input = "", defaultProto) {
|
|
const _specialProtoMatch = input.match(
|
|
/^[\s\0]*(blob:|data:|javascript:|vbscript:)(.*)/i
|
|
);
|
|
if (_specialProtoMatch) {
|
|
const [, _proto, _pathname = ""] = _specialProtoMatch;
|
|
return {
|
|
protocol: _proto.toLowerCase(),
|
|
pathname: _pathname,
|
|
href: _proto + _pathname,
|
|
auth: "",
|
|
host: "",
|
|
search: "",
|
|
hash: ""
|
|
};
|
|
}
|
|
if (!hasProtocol(input, { acceptRelative: true })) {
|
|
return defaultProto ? parseURL(defaultProto + input) : parsePath(input);
|
|
}
|
|
const [, protocol = "", auth, hostAndPath = ""] = input.replace(/\\/g, "/").match(/^[\s\0]*([\w+.-]{2,}:)?\/\/([^/@]+@)?(.*)/) || [];
|
|
let [, host = "", path = ""] = hostAndPath.match(/([^#/?]*)(.*)?/) || [];
|
|
if (protocol === "file:") {
|
|
path = path.replace(/\/(?=[A-Za-z]:)/, "");
|
|
}
|
|
const { pathname, search, hash } = parsePath(path);
|
|
return {
|
|
protocol: protocol.toLowerCase(),
|
|
auth: auth ? auth.slice(0, Math.max(0, auth.length - 1)) : "",
|
|
host,
|
|
pathname,
|
|
search,
|
|
hash,
|
|
[protocolRelative]: !protocol
|
|
};
|
|
}
|
|
function parsePath(input = "") {
|
|
const [pathname = "", search = "", hash = ""] = (input.match(/([^#?]*)(\?[^#]*)?(#.*)?/) || []).splice(1);
|
|
return {
|
|
pathname,
|
|
search,
|
|
hash
|
|
};
|
|
}
|
|
function stringifyParsedURL(parsed) {
|
|
const pathname = parsed.pathname || "";
|
|
const search = parsed.search ? (parsed.search.startsWith("?") ? "" : "?") + parsed.search : "";
|
|
const hash = parsed.hash || "";
|
|
const auth = parsed.auth ? parsed.auth + "@" : "";
|
|
const host = parsed.host || "";
|
|
const proto = parsed.protocol || parsed[protocolRelative] ? (parsed.protocol || "") + "//" : "";
|
|
return proto + auth + host + pathname + search + hash;
|
|
}
|
|
|
|
const serverAssets = [{"baseName":"server","dir":"D:/claude-project/web7-published/server/assets"}];
|
|
|
|
const assets$1 = createStorage();
|
|
|
|
for (const asset of serverAssets) {
|
|
assets$1.mount(asset.baseName, unstorage_47drivers_47fs({ base: asset.dir, ignore: (asset?.ignore || []) }));
|
|
}
|
|
|
|
const storage$1 = createStorage({});
|
|
|
|
storage$1.mount('/assets', assets$1);
|
|
|
|
storage$1.mount('root', unstorage_47drivers_47fs({"driver":"fs","readOnly":true,"base":"D:/claude-project/web7-published","watchOptions":{"ignored":[null]}}));
|
|
storage$1.mount('src', unstorage_47drivers_47fs({"driver":"fs","readOnly":true,"base":"D:/claude-project/web7-published/server","watchOptions":{"ignored":[null]}}));
|
|
storage$1.mount('content:source:content', unstorage_47drivers_47fs({"name":"content:source:content","driver":"fs","base":"D:/claude-project/web7-published/content"}));
|
|
storage$1.mount('cache:content', unstorage_47drivers_47fs({"driver":"fs","base":"D:/claude-project/web7-published/.nuxt/content-cache"}));
|
|
storage$1.mount('build', unstorage_47drivers_47fs({"driver":"fs","readOnly":false,"base":"D:/claude-project/web7-published/.nuxt"}));
|
|
storage$1.mount('cache', unstorage_47drivers_47fs({"driver":"fs","readOnly":false,"base":"D:/claude-project/web7-published/.nuxt/cache"}));
|
|
storage$1.mount('data', unstorage_47drivers_47fs({"driver":"fs","base":"D:/claude-project/web7-published/.data/kv"}));
|
|
|
|
function useStorage(base = "") {
|
|
return base ? prefixStorage(storage$1, base) : storage$1;
|
|
}
|
|
|
|
const Hasher = /* @__PURE__ */ (() => {
|
|
class Hasher2 {
|
|
buff = "";
|
|
#context = /* @__PURE__ */ new Map();
|
|
write(str) {
|
|
this.buff += str;
|
|
}
|
|
dispatch(value) {
|
|
const type = value === null ? "null" : typeof value;
|
|
return this[type](value);
|
|
}
|
|
object(object) {
|
|
if (object && typeof object.toJSON === "function") {
|
|
return this.object(object.toJSON());
|
|
}
|
|
const objString = Object.prototype.toString.call(object);
|
|
let objType = "";
|
|
const objectLength = objString.length;
|
|
objType = objectLength < 10 ? "unknown:[" + objString + "]" : objString.slice(8, objectLength - 1);
|
|
objType = objType.toLowerCase();
|
|
let objectNumber = null;
|
|
if ((objectNumber = this.#context.get(object)) === void 0) {
|
|
this.#context.set(object, this.#context.size);
|
|
} else {
|
|
return this.dispatch("[CIRCULAR:" + objectNumber + "]");
|
|
}
|
|
if (typeof Buffer !== "undefined" && Buffer.isBuffer && Buffer.isBuffer(object)) {
|
|
this.write("buffer:");
|
|
return this.write(object.toString("utf8"));
|
|
}
|
|
if (objType !== "object" && objType !== "function" && objType !== "asyncfunction") {
|
|
if (this[objType]) {
|
|
this[objType](object);
|
|
} else {
|
|
this.unknown(object, objType);
|
|
}
|
|
} else {
|
|
const keys = Object.keys(object).sort();
|
|
const extraKeys = [];
|
|
this.write("object:" + (keys.length + extraKeys.length) + ":");
|
|
const dispatchForKey = (key) => {
|
|
this.dispatch(key);
|
|
this.write(":");
|
|
this.dispatch(object[key]);
|
|
this.write(",");
|
|
};
|
|
for (const key of keys) {
|
|
dispatchForKey(key);
|
|
}
|
|
for (const key of extraKeys) {
|
|
dispatchForKey(key);
|
|
}
|
|
}
|
|
}
|
|
array(arr, unordered) {
|
|
unordered = unordered === void 0 ? false : unordered;
|
|
this.write("array:" + arr.length + ":");
|
|
if (!unordered || arr.length <= 1) {
|
|
for (const entry of arr) {
|
|
this.dispatch(entry);
|
|
}
|
|
return;
|
|
}
|
|
const contextAdditions = /* @__PURE__ */ new Map();
|
|
const entries = arr.map((entry) => {
|
|
const hasher = new Hasher2();
|
|
hasher.dispatch(entry);
|
|
for (const [key, value] of hasher.#context) {
|
|
contextAdditions.set(key, value);
|
|
}
|
|
return hasher.toString();
|
|
});
|
|
this.#context = contextAdditions;
|
|
entries.sort();
|
|
return this.array(entries, false);
|
|
}
|
|
date(date) {
|
|
return this.write("date:" + date.toJSON());
|
|
}
|
|
symbol(sym) {
|
|
return this.write("symbol:" + sym.toString());
|
|
}
|
|
unknown(value, type) {
|
|
this.write(type);
|
|
if (!value) {
|
|
return;
|
|
}
|
|
this.write(":");
|
|
if (value && typeof value.entries === "function") {
|
|
return this.array(
|
|
[...value.entries()],
|
|
true
|
|
/* ordered */
|
|
);
|
|
}
|
|
}
|
|
error(err) {
|
|
return this.write("error:" + err.toString());
|
|
}
|
|
boolean(bool) {
|
|
return this.write("bool:" + bool);
|
|
}
|
|
string(string) {
|
|
this.write("string:" + string.length + ":");
|
|
this.write(string);
|
|
}
|
|
function(fn) {
|
|
this.write("fn:");
|
|
if (isNativeFunction(fn)) {
|
|
this.dispatch("[native]");
|
|
} else {
|
|
this.dispatch(fn.toString());
|
|
}
|
|
}
|
|
number(number) {
|
|
return this.write("number:" + number);
|
|
}
|
|
null() {
|
|
return this.write("Null");
|
|
}
|
|
undefined() {
|
|
return this.write("Undefined");
|
|
}
|
|
regexp(regex) {
|
|
return this.write("regex:" + regex.toString());
|
|
}
|
|
arraybuffer(arr) {
|
|
this.write("arraybuffer:");
|
|
return this.dispatch(new Uint8Array(arr));
|
|
}
|
|
url(url) {
|
|
return this.write("url:" + url.toString());
|
|
}
|
|
map(map) {
|
|
this.write("map:");
|
|
const arr = [...map];
|
|
return this.array(arr, false);
|
|
}
|
|
set(set) {
|
|
this.write("set:");
|
|
const arr = [...set];
|
|
return this.array(arr, false);
|
|
}
|
|
bigint(number) {
|
|
return this.write("bigint:" + number.toString());
|
|
}
|
|
}
|
|
for (const type of [
|
|
"uint8array",
|
|
"uint8clampedarray",
|
|
"unt8array",
|
|
"uint16array",
|
|
"unt16array",
|
|
"uint32array",
|
|
"unt32array",
|
|
"float32array",
|
|
"float64array"
|
|
]) {
|
|
Hasher2.prototype[type] = function(arr) {
|
|
this.write(type + ":");
|
|
return this.array([...arr], false);
|
|
};
|
|
}
|
|
function isNativeFunction(f) {
|
|
if (typeof f !== "function") {
|
|
return false;
|
|
}
|
|
return Function.prototype.toString.call(f).slice(
|
|
-15
|
|
/* "[native code] }".length */
|
|
) === "[native code] }";
|
|
}
|
|
return Hasher2;
|
|
})();
|
|
function serialize(object) {
|
|
const hasher = new Hasher();
|
|
hasher.dispatch(object);
|
|
return hasher.buff;
|
|
}
|
|
function hash(value) {
|
|
return digest(typeof value === "string" ? value : serialize(value)).replace(/[-_]/g, "").slice(0, 10);
|
|
}
|
|
|
|
function defaultCacheOptions() {
|
|
return {
|
|
name: "_",
|
|
base: "/cache",
|
|
swr: true,
|
|
maxAge: 1
|
|
};
|
|
}
|
|
function defineCachedFunction(fn, opts = {}) {
|
|
opts = { ...defaultCacheOptions(), ...opts };
|
|
const pending = {};
|
|
const group = opts.group || "nitro/functions";
|
|
const name = opts.name || fn.name || "_";
|
|
const integrity = opts.integrity || hash([fn, opts]);
|
|
const validate = opts.validate || ((entry) => entry.value !== void 0);
|
|
async function get(key, resolver, shouldInvalidateCache, event) {
|
|
const cacheKey = [opts.base, group, name, key + ".json"].filter(Boolean).join(":").replace(/:\/$/, ":index");
|
|
let entry = await useStorage().getItem(cacheKey).catch((error) => {
|
|
console.error(`[cache] Cache read error.`, error);
|
|
useNitroApp().captureError(error, { event, tags: ["cache"] });
|
|
}) || {};
|
|
if (typeof entry !== "object") {
|
|
entry = {};
|
|
const error = new Error("Malformed data read from cache.");
|
|
console.error("[cache]", error);
|
|
useNitroApp().captureError(error, { event, tags: ["cache"] });
|
|
}
|
|
const ttl = (opts.maxAge ?? 0) * 1e3;
|
|
if (ttl) {
|
|
entry.expires = Date.now() + ttl;
|
|
}
|
|
const expired = shouldInvalidateCache || entry.integrity !== integrity || ttl && Date.now() - (entry.mtime || 0) > ttl || validate(entry) === false;
|
|
const _resolve = async () => {
|
|
const isPending = pending[key];
|
|
if (!isPending) {
|
|
if (entry.value !== void 0 && (opts.staleMaxAge || 0) >= 0 && opts.swr === false) {
|
|
entry.value = void 0;
|
|
entry.integrity = void 0;
|
|
entry.mtime = void 0;
|
|
entry.expires = void 0;
|
|
}
|
|
pending[key] = Promise.resolve(resolver());
|
|
}
|
|
try {
|
|
entry.value = await pending[key];
|
|
} catch (error) {
|
|
if (!isPending) {
|
|
delete pending[key];
|
|
}
|
|
throw error;
|
|
}
|
|
if (!isPending) {
|
|
entry.mtime = Date.now();
|
|
entry.integrity = integrity;
|
|
delete pending[key];
|
|
if (validate(entry) !== false) {
|
|
let setOpts;
|
|
if (opts.maxAge && !opts.swr) {
|
|
setOpts = { ttl: opts.maxAge };
|
|
}
|
|
const promise = useStorage().setItem(cacheKey, entry, setOpts).catch((error) => {
|
|
console.error(`[cache] Cache write error.`, error);
|
|
useNitroApp().captureError(error, { event, tags: ["cache"] });
|
|
});
|
|
if (event?.waitUntil) {
|
|
event.waitUntil(promise);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
const _resolvePromise = expired ? _resolve() : Promise.resolve();
|
|
if (entry.value === void 0) {
|
|
await _resolvePromise;
|
|
} else if (expired && event && event.waitUntil) {
|
|
event.waitUntil(_resolvePromise);
|
|
}
|
|
if (opts.swr && validate(entry) !== false) {
|
|
_resolvePromise.catch((error) => {
|
|
console.error(`[cache] SWR handler error.`, error);
|
|
useNitroApp().captureError(error, { event, tags: ["cache"] });
|
|
});
|
|
return entry;
|
|
}
|
|
return _resolvePromise.then(() => entry);
|
|
}
|
|
return async (...args) => {
|
|
const shouldBypassCache = await opts.shouldBypassCache?.(...args);
|
|
if (shouldBypassCache) {
|
|
return fn(...args);
|
|
}
|
|
const key = await (opts.getKey || getKey)(...args);
|
|
const shouldInvalidateCache = await opts.shouldInvalidateCache?.(...args);
|
|
const entry = await get(
|
|
key,
|
|
() => fn(...args),
|
|
shouldInvalidateCache,
|
|
args[0] && isEvent(args[0]) ? args[0] : void 0
|
|
);
|
|
let value = entry.value;
|
|
if (opts.transform) {
|
|
value = await opts.transform(entry, ...args) || value;
|
|
}
|
|
return value;
|
|
};
|
|
}
|
|
function cachedFunction(fn, opts = {}) {
|
|
return defineCachedFunction(fn, opts);
|
|
}
|
|
function getKey(...args) {
|
|
return args.length > 0 ? hash(args) : "";
|
|
}
|
|
function escapeKey(key) {
|
|
return String(key).replace(/\W/g, "");
|
|
}
|
|
function defineCachedEventHandler(handler, opts = defaultCacheOptions()) {
|
|
const variableHeaderNames = (opts.varies || []).filter(Boolean).map((h) => h.toLowerCase()).sort();
|
|
const _opts = {
|
|
...opts,
|
|
getKey: async (event) => {
|
|
const customKey = await opts.getKey?.(event);
|
|
if (customKey) {
|
|
return escapeKey(customKey);
|
|
}
|
|
const _path = event.node.req.originalUrl || event.node.req.url || event.path;
|
|
let _pathname;
|
|
try {
|
|
_pathname = escapeKey(decodeURI(parseURL(_path).pathname)).slice(0, 16) || "index";
|
|
} catch {
|
|
_pathname = "-";
|
|
}
|
|
const _hashedPath = `${_pathname}.${hash(_path)}`;
|
|
const _headers = variableHeaderNames.map((header) => [header, event.node.req.headers[header]]).map(([name, value]) => `${escapeKey(name)}.${hash(value)}`);
|
|
return [_hashedPath, ..._headers].join(":");
|
|
},
|
|
validate: (entry) => {
|
|
if (!entry.value) {
|
|
return false;
|
|
}
|
|
if (entry.value.code >= 400) {
|
|
return false;
|
|
}
|
|
if (entry.value.body === void 0) {
|
|
return false;
|
|
}
|
|
if (entry.value.headers.etag === "undefined" || entry.value.headers["last-modified"] === "undefined") {
|
|
return false;
|
|
}
|
|
return true;
|
|
},
|
|
group: opts.group || "nitro/handlers",
|
|
integrity: opts.integrity || hash([handler, opts])
|
|
};
|
|
const _cachedHandler = cachedFunction(
|
|
async (incomingEvent) => {
|
|
const variableHeaders = {};
|
|
for (const header of variableHeaderNames) {
|
|
const value = incomingEvent.node.req.headers[header];
|
|
if (value !== void 0) {
|
|
variableHeaders[header] = value;
|
|
}
|
|
}
|
|
const reqProxy = cloneWithProxy(incomingEvent.node.req, {
|
|
headers: variableHeaders
|
|
});
|
|
const resHeaders = {};
|
|
let _resSendBody;
|
|
const resProxy = cloneWithProxy(incomingEvent.node.res, {
|
|
statusCode: 200,
|
|
writableEnded: false,
|
|
writableFinished: false,
|
|
headersSent: false,
|
|
closed: false,
|
|
getHeader(name) {
|
|
return resHeaders[name];
|
|
},
|
|
setHeader(name, value) {
|
|
resHeaders[name] = value;
|
|
return this;
|
|
},
|
|
getHeaderNames() {
|
|
return Object.keys(resHeaders);
|
|
},
|
|
hasHeader(name) {
|
|
return name in resHeaders;
|
|
},
|
|
removeHeader(name) {
|
|
delete resHeaders[name];
|
|
},
|
|
getHeaders() {
|
|
return resHeaders;
|
|
},
|
|
end(chunk, arg2, arg3) {
|
|
if (typeof chunk === "string") {
|
|
_resSendBody = chunk;
|
|
}
|
|
if (typeof arg2 === "function") {
|
|
arg2();
|
|
}
|
|
if (typeof arg3 === "function") {
|
|
arg3();
|
|
}
|
|
return this;
|
|
},
|
|
write(chunk, arg2, arg3) {
|
|
if (typeof chunk === "string") {
|
|
_resSendBody = chunk;
|
|
}
|
|
if (typeof arg2 === "function") {
|
|
arg2(void 0);
|
|
}
|
|
if (typeof arg3 === "function") {
|
|
arg3();
|
|
}
|
|
return true;
|
|
},
|
|
writeHead(statusCode, headers2) {
|
|
this.statusCode = statusCode;
|
|
if (headers2) {
|
|
if (Array.isArray(headers2) || typeof headers2 === "string") {
|
|
throw new TypeError("Raw headers is not supported.");
|
|
}
|
|
for (const header in headers2) {
|
|
const value = headers2[header];
|
|
if (value !== void 0) {
|
|
this.setHeader(
|
|
header,
|
|
value
|
|
);
|
|
}
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
});
|
|
const event = createEvent(reqProxy, resProxy);
|
|
event.fetch = (url, fetchOptions) => fetchWithEvent(event, url, fetchOptions, {
|
|
fetch: useNitroApp().localFetch
|
|
});
|
|
event.$fetch = (url, fetchOptions) => fetchWithEvent(event, url, fetchOptions, {
|
|
fetch: globalThis.$fetch
|
|
});
|
|
event.waitUntil = incomingEvent.waitUntil;
|
|
event.context = incomingEvent.context;
|
|
event.context.cache = {
|
|
options: _opts
|
|
};
|
|
const body = await handler(event) || _resSendBody;
|
|
const headers = event.node.res.getHeaders();
|
|
headers.etag = String(
|
|
headers.Etag || headers.etag || `W/"${hash(body)}"`
|
|
);
|
|
headers["last-modified"] = String(
|
|
headers["Last-Modified"] || headers["last-modified"] || (/* @__PURE__ */ new Date()).toUTCString()
|
|
);
|
|
const cacheControl = [];
|
|
if (opts.swr) {
|
|
if (opts.maxAge) {
|
|
cacheControl.push(`s-maxage=${opts.maxAge}`);
|
|
}
|
|
if (opts.staleMaxAge) {
|
|
cacheControl.push(`stale-while-revalidate=${opts.staleMaxAge}`);
|
|
} else {
|
|
cacheControl.push("stale-while-revalidate");
|
|
}
|
|
} else if (opts.maxAge) {
|
|
cacheControl.push(`max-age=${opts.maxAge}`);
|
|
}
|
|
if (cacheControl.length > 0) {
|
|
headers["cache-control"] = cacheControl.join(", ");
|
|
}
|
|
const cacheEntry = {
|
|
code: event.node.res.statusCode,
|
|
headers,
|
|
body
|
|
};
|
|
return cacheEntry;
|
|
},
|
|
_opts
|
|
);
|
|
return defineEventHandler(async (event) => {
|
|
if (opts.headersOnly) {
|
|
if (handleCacheHeaders(event, { maxAge: opts.maxAge })) {
|
|
return;
|
|
}
|
|
return handler(event);
|
|
}
|
|
const response = await _cachedHandler(
|
|
event
|
|
);
|
|
if (event.node.res.headersSent || event.node.res.writableEnded) {
|
|
return response.body;
|
|
}
|
|
if (handleCacheHeaders(event, {
|
|
modifiedTime: new Date(response.headers["last-modified"]),
|
|
etag: response.headers.etag,
|
|
maxAge: opts.maxAge
|
|
})) {
|
|
return;
|
|
}
|
|
event.node.res.statusCode = response.code;
|
|
for (const name in response.headers) {
|
|
const value = response.headers[name];
|
|
if (name === "set-cookie") {
|
|
event.node.res.appendHeader(
|
|
name,
|
|
splitCookiesString(value)
|
|
);
|
|
} else {
|
|
if (value !== void 0) {
|
|
event.node.res.setHeader(name, value);
|
|
}
|
|
}
|
|
}
|
|
return response.body;
|
|
});
|
|
}
|
|
function cloneWithProxy(obj, overrides) {
|
|
return new Proxy(obj, {
|
|
get(target, property, receiver) {
|
|
if (property in overrides) {
|
|
return overrides[property];
|
|
}
|
|
return Reflect.get(target, property, receiver);
|
|
},
|
|
set(target, property, value, receiver) {
|
|
if (property in overrides) {
|
|
overrides[property] = value;
|
|
return true;
|
|
}
|
|
return Reflect.set(target, property, value, receiver);
|
|
}
|
|
});
|
|
}
|
|
const cachedEventHandler = defineCachedEventHandler;
|
|
|
|
const inlineAppConfig = {
|
|
"nuxt": {}
|
|
};
|
|
|
|
|
|
|
|
const appConfig = defuFn(inlineAppConfig);
|
|
|
|
function getEnv(key, opts) {
|
|
const envKey = snakeCase(key).toUpperCase();
|
|
return destr(
|
|
process.env[opts.prefix + envKey] ?? process.env[opts.altPrefix + envKey]
|
|
);
|
|
}
|
|
function _isObject(input) {
|
|
return typeof input === "object" && !Array.isArray(input);
|
|
}
|
|
function applyEnv(obj, opts, parentKey = "") {
|
|
for (const key in obj) {
|
|
const subKey = parentKey ? `${parentKey}_${key}` : key;
|
|
const envValue = getEnv(subKey, opts);
|
|
if (_isObject(obj[key])) {
|
|
if (_isObject(envValue)) {
|
|
obj[key] = { ...obj[key], ...envValue };
|
|
applyEnv(obj[key], opts, subKey);
|
|
} else if (envValue === void 0) {
|
|
applyEnv(obj[key], opts, subKey);
|
|
} else {
|
|
obj[key] = envValue ?? obj[key];
|
|
}
|
|
} else {
|
|
obj[key] = envValue ?? obj[key];
|
|
}
|
|
if (opts.envExpansion && typeof obj[key] === "string") {
|
|
obj[key] = _expandFromEnv(obj[key]);
|
|
}
|
|
}
|
|
return obj;
|
|
}
|
|
const envExpandRx = /\{\{([^{}]*)\}\}/g;
|
|
function _expandFromEnv(value) {
|
|
return value.replace(envExpandRx, (match, key) => {
|
|
return process.env[key] || match;
|
|
});
|
|
}
|
|
|
|
const _inlineRuntimeConfig = {
|
|
"app": {
|
|
"baseURL": "/",
|
|
"buildId": "dev",
|
|
"buildAssetsDir": "/_nuxt/",
|
|
"cdnURL": ""
|
|
},
|
|
"nitro": {
|
|
"envPrefix": "NUXT_",
|
|
"routeRules": {
|
|
"/__nuxt_error": {
|
|
"cache": false
|
|
},
|
|
"/sitemap.xsl": {
|
|
"headers": {
|
|
"Content-Type": "application/xslt+xml"
|
|
}
|
|
},
|
|
"/sitemap.xml": {
|
|
"redirect": {
|
|
"to": "/sitemap_index.xml",
|
|
"statusCode": 307
|
|
}
|
|
},
|
|
"/sitemap_index.xml": {
|
|
"headers": {
|
|
"Content-Type": "text/xml; charset=UTF-8",
|
|
"Cache-Control": "public, max-age=600, must-revalidate",
|
|
"X-Sitemap-Prerendered": "2025-09-11T03:36:06.648Z"
|
|
}
|
|
},
|
|
"/__sitemap__/index.xml": {
|
|
"headers": {
|
|
"Content-Type": "text/xml; charset=UTF-8",
|
|
"Cache-Control": "public, max-age=600, must-revalidate",
|
|
"X-Sitemap-Prerendered": "2025-09-11T03:36:06.648Z"
|
|
}
|
|
},
|
|
"/index-sitemap.xml": {
|
|
"redirect": {
|
|
"to": "/__sitemap__/index.xml",
|
|
"statusCode": 307
|
|
}
|
|
},
|
|
"/__sitemap__/en.xml": {
|
|
"headers": {
|
|
"Content-Type": "text/xml; charset=UTF-8",
|
|
"Cache-Control": "public, max-age=600, must-revalidate",
|
|
"X-Sitemap-Prerendered": "2025-09-11T03:36:06.648Z"
|
|
}
|
|
},
|
|
"/en-sitemap.xml": {
|
|
"redirect": {
|
|
"to": "/__sitemap__/en.xml",
|
|
"statusCode": 307
|
|
}
|
|
},
|
|
"/__sitemap__/zh.xml": {
|
|
"headers": {
|
|
"Content-Type": "text/xml; charset=UTF-8",
|
|
"Cache-Control": "public, max-age=600, must-revalidate",
|
|
"X-Sitemap-Prerendered": "2025-09-11T03:36:06.648Z"
|
|
}
|
|
},
|
|
"/zh-sitemap.xml": {
|
|
"redirect": {
|
|
"to": "/__sitemap__/zh.xml",
|
|
"statusCode": 307
|
|
}
|
|
},
|
|
"/__sitemap__/zh-hant.xml": {
|
|
"headers": {
|
|
"Content-Type": "text/xml; charset=UTF-8",
|
|
"Cache-Control": "public, max-age=600, must-revalidate",
|
|
"X-Sitemap-Prerendered": "2025-09-11T03:36:06.648Z"
|
|
}
|
|
},
|
|
"/zh-hant-sitemap.xml": {
|
|
"redirect": {
|
|
"to": "/__sitemap__/zh-hant.xml",
|
|
"statusCode": 307
|
|
}
|
|
},
|
|
"/_nuxt/builds/meta/**": {
|
|
"headers": {
|
|
"cache-control": "public, max-age=31536000, immutable"
|
|
}
|
|
},
|
|
"/_nuxt/builds/**": {
|
|
"headers": {
|
|
"cache-control": "public, max-age=1, immutable"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"public": {
|
|
"i18n": {
|
|
"baseUrl": "",
|
|
"defaultLocale": "en",
|
|
"defaultDirection": "ltr",
|
|
"strategy": "prefix_except_default",
|
|
"lazy": true,
|
|
"rootRedirect": "",
|
|
"routesNameSeparator": "___",
|
|
"defaultLocaleRouteNameSuffix": "default",
|
|
"skipSettingLocaleOnNavigate": false,
|
|
"differentDomains": false,
|
|
"trailingSlash": false,
|
|
"configLocales": [
|
|
{
|
|
"code": "en",
|
|
"name": "English",
|
|
"files": [
|
|
"D:/claude-project/web7-published/locales/en.json"
|
|
]
|
|
},
|
|
{
|
|
"code": "zh",
|
|
"name": "简体中文",
|
|
"files": [
|
|
"D:/claude-project/web7-published/locales/zh.json"
|
|
]
|
|
},
|
|
{
|
|
"code": "zh-hant",
|
|
"name": "繁體中文",
|
|
"files": [
|
|
"D:/claude-project/web7-published/locales/zh-hant.json"
|
|
]
|
|
}
|
|
],
|
|
"locales": {
|
|
"en": {
|
|
"domain": ""
|
|
},
|
|
"zh": {
|
|
"domain": ""
|
|
},
|
|
"zh-hant": {
|
|
"domain": ""
|
|
}
|
|
},
|
|
"detectBrowserLanguage": {
|
|
"alwaysRedirect": false,
|
|
"cookieCrossOrigin": false,
|
|
"cookieDomain": "",
|
|
"cookieKey": "i18n_redirected",
|
|
"cookieSecure": false,
|
|
"fallbackLocale": "",
|
|
"redirectOn": "root",
|
|
"useCookie": true
|
|
},
|
|
"experimental": {
|
|
"localeDetector": "",
|
|
"switchLocalePathLinkSSR": false,
|
|
"autoImportTranslationFunctions": false
|
|
},
|
|
"multiDomainLocales": false
|
|
},
|
|
"mdc": {
|
|
"components": {
|
|
"prose": true,
|
|
"map": {
|
|
"p": "prose-p",
|
|
"a": "prose-a",
|
|
"blockquote": "prose-blockquote",
|
|
"code-inline": "prose-code-inline",
|
|
"code": "ProseCodeInline",
|
|
"em": "prose-em",
|
|
"h1": "prose-h1",
|
|
"h2": "prose-h2",
|
|
"h3": "prose-h3",
|
|
"h4": "prose-h4",
|
|
"h5": "prose-h5",
|
|
"h6": "prose-h6",
|
|
"hr": "prose-hr",
|
|
"img": "prose-img",
|
|
"ul": "prose-ul",
|
|
"ol": "prose-ol",
|
|
"li": "prose-li",
|
|
"strong": "prose-strong",
|
|
"table": "prose-table",
|
|
"thead": "prose-thead",
|
|
"tbody": "prose-tbody",
|
|
"td": "prose-td",
|
|
"th": "prose-th",
|
|
"tr": "prose-tr"
|
|
}
|
|
},
|
|
"headings": {
|
|
"anchorLinks": {
|
|
"h1": false,
|
|
"h2": true,
|
|
"h3": true,
|
|
"h4": true,
|
|
"h5": false,
|
|
"h6": false
|
|
}
|
|
}
|
|
},
|
|
"content": {
|
|
"locales": [],
|
|
"defaultLocale": "",
|
|
"integrity": "",
|
|
"experimental": {
|
|
"stripQueryParameters": false,
|
|
"advanceQuery": false,
|
|
"clientDB": false
|
|
},
|
|
"respectPathCase": false,
|
|
"api": {
|
|
"baseURL": "/api/_content"
|
|
},
|
|
"navigation": {
|
|
"fields": []
|
|
},
|
|
"tags": {
|
|
"p": "prose-p",
|
|
"a": "prose-a",
|
|
"blockquote": "prose-blockquote",
|
|
"code-inline": "prose-code-inline",
|
|
"code": "ProseCodeInline",
|
|
"em": "prose-em",
|
|
"h1": "prose-h1",
|
|
"h2": "prose-h2",
|
|
"h3": "prose-h3",
|
|
"h4": "prose-h4",
|
|
"h5": "prose-h5",
|
|
"h6": "prose-h6",
|
|
"hr": "prose-hr",
|
|
"img": "prose-img",
|
|
"ul": "prose-ul",
|
|
"ol": "prose-ol",
|
|
"li": "prose-li",
|
|
"strong": "prose-strong",
|
|
"table": "prose-table",
|
|
"thead": "prose-thead",
|
|
"tbody": "prose-tbody",
|
|
"td": "prose-td",
|
|
"th": "prose-th",
|
|
"tr": "prose-tr"
|
|
},
|
|
"highlight": false,
|
|
"wsUrl": "ws://localhost:4000/",
|
|
"documentDriven": false,
|
|
"host": "",
|
|
"trailingSlash": false,
|
|
"search": "",
|
|
"contentHead": true,
|
|
"anchorLinks": {
|
|
"depth": 4,
|
|
"exclude": [
|
|
1
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"content": {
|
|
"cacheVersion": 2,
|
|
"cacheIntegrity": "dLYeSFVwsx",
|
|
"transformers": [],
|
|
"base": "",
|
|
"api": {
|
|
"baseURL": "/api/_content"
|
|
},
|
|
"watch": {
|
|
"ws": {
|
|
"port": {
|
|
"port": 4000,
|
|
"portRange": [
|
|
4000,
|
|
4040
|
|
]
|
|
},
|
|
"hostname": "localhost",
|
|
"showURL": false
|
|
}
|
|
},
|
|
"sources": {},
|
|
"ignores": [],
|
|
"locales": [],
|
|
"defaultLocale": "",
|
|
"highlight": false,
|
|
"markdown": {
|
|
"tags": {
|
|
"p": "prose-p",
|
|
"a": "prose-a",
|
|
"blockquote": "prose-blockquote",
|
|
"code-inline": "prose-code-inline",
|
|
"code": "ProseCodeInline",
|
|
"em": "prose-em",
|
|
"h1": "prose-h1",
|
|
"h2": "prose-h2",
|
|
"h3": "prose-h3",
|
|
"h4": "prose-h4",
|
|
"h5": "prose-h5",
|
|
"h6": "prose-h6",
|
|
"hr": "prose-hr",
|
|
"img": "prose-img",
|
|
"ul": "prose-ul",
|
|
"ol": "prose-ol",
|
|
"li": "prose-li",
|
|
"strong": "prose-strong",
|
|
"table": "prose-table",
|
|
"thead": "prose-thead",
|
|
"tbody": "prose-tbody",
|
|
"td": "prose-td",
|
|
"th": "prose-th",
|
|
"tr": "prose-tr"
|
|
},
|
|
"anchorLinks": {
|
|
"depth": 4,
|
|
"exclude": [
|
|
1
|
|
]
|
|
},
|
|
"remarkPlugins": {},
|
|
"rehypePlugins": {}
|
|
},
|
|
"yaml": {},
|
|
"csv": {
|
|
"delimeter": ",",
|
|
"json": true
|
|
},
|
|
"navigation": {
|
|
"fields": []
|
|
},
|
|
"contentHead": true,
|
|
"documentDriven": false,
|
|
"respectPathCase": false,
|
|
"experimental": {
|
|
"clientDB": false,
|
|
"cacheContents": true,
|
|
"stripQueryParameters": false,
|
|
"advanceQuery": false,
|
|
"search": ""
|
|
}
|
|
},
|
|
"sitemap": {
|
|
"isI18nMapped": true,
|
|
"sitemapName": "sitemap.xml",
|
|
"isMultiSitemap": true,
|
|
"excludeAppSources": [],
|
|
"cacheMaxAgeSeconds": 0,
|
|
"autoLastmod": false,
|
|
"defaultSitemapsChunkSize": 1000,
|
|
"minify": false,
|
|
"sortEntries": true,
|
|
"debug": false,
|
|
"discoverImages": true,
|
|
"discoverVideos": true,
|
|
"sitemapsPathPrefix": "/__sitemap__/",
|
|
"isNuxtContentDocumentDriven": false,
|
|
"xsl": "/__sitemap__/style.xsl",
|
|
"xslTips": true,
|
|
"xslColumns": [
|
|
{
|
|
"label": "URL",
|
|
"width": "50%"
|
|
},
|
|
{
|
|
"label": "Images",
|
|
"width": "25%",
|
|
"select": "count(image:image)"
|
|
},
|
|
{
|
|
"label": "Last Updated",
|
|
"width": "25%",
|
|
"select": "concat(substring(sitemap:lastmod,0,11),concat(' ', substring(sitemap:lastmod,12,5)),concat(' ', substring(sitemap:lastmod,20,6)))"
|
|
}
|
|
],
|
|
"credits": true,
|
|
"version": "6.1.5",
|
|
"sitemaps": {
|
|
"index": {
|
|
"sitemapName": "index",
|
|
"_route": "sitemap_index.xml",
|
|
"sitemaps": [],
|
|
"include": [],
|
|
"exclude": []
|
|
},
|
|
"en": {
|
|
"include": [],
|
|
"exclude": [
|
|
"/_nuxt/**",
|
|
"/_**"
|
|
],
|
|
"includeAppSources": true,
|
|
"sitemapName": "en",
|
|
"_route": "/__sitemap__/en.xml",
|
|
"_hasSourceChunk": false
|
|
},
|
|
"zh": {
|
|
"include": [],
|
|
"exclude": [
|
|
"/_nuxt/**",
|
|
"/_**"
|
|
],
|
|
"includeAppSources": true,
|
|
"sitemapName": "zh",
|
|
"_route": "/__sitemap__/zh.xml",
|
|
"_hasSourceChunk": false
|
|
},
|
|
"zh-hant": {
|
|
"include": [],
|
|
"exclude": [
|
|
"/_nuxt/**",
|
|
"/_**"
|
|
],
|
|
"includeAppSources": true,
|
|
"sitemapName": "zh-hant",
|
|
"_route": "/__sitemap__/zh-hant.xml",
|
|
"_hasSourceChunk": false
|
|
}
|
|
},
|
|
"autoI18n": {
|
|
"differentDomains": false,
|
|
"defaultLocale": "en",
|
|
"locales": [
|
|
{
|
|
"code": "en",
|
|
"name": "English",
|
|
"_hreflang": "en",
|
|
"_sitemap": "en"
|
|
},
|
|
{
|
|
"code": "zh",
|
|
"name": "简体中文",
|
|
"_hreflang": "zh",
|
|
"_sitemap": "zh"
|
|
},
|
|
{
|
|
"code": "zh-hant",
|
|
"name": "繁體中文",
|
|
"_hreflang": "zh-hant",
|
|
"_sitemap": "zh-hant"
|
|
}
|
|
],
|
|
"strategy": "prefix_except_default"
|
|
}
|
|
},
|
|
"nuxt-site-config": {
|
|
"stack": [
|
|
{
|
|
"_context": "system",
|
|
"_priority": -15,
|
|
"name": "web7-published",
|
|
"env": "development"
|
|
},
|
|
{
|
|
"_context": "package.json",
|
|
"_priority": -10,
|
|
"name": "cloudproxy-pro"
|
|
},
|
|
{
|
|
"_context": "@nuxtjs/i18n",
|
|
"defaultLocale": "en"
|
|
}
|
|
],
|
|
"version": "2.2.21",
|
|
"debug": false
|
|
},
|
|
"nuxt-robots": {
|
|
"version": "4.1.11",
|
|
"usingNuxtContent": true,
|
|
"debug": false,
|
|
"credits": true,
|
|
"groups": [
|
|
{
|
|
"comment": [],
|
|
"disallow": [],
|
|
"allow": [
|
|
"/",
|
|
"/zh/",
|
|
"/zh-hant/"
|
|
],
|
|
"userAgent": [
|
|
"*"
|
|
],
|
|
"_indexable": true,
|
|
"_rules": [
|
|
{
|
|
"pattern": "/",
|
|
"allow": true
|
|
},
|
|
{
|
|
"pattern": "/zh/",
|
|
"allow": true
|
|
},
|
|
{
|
|
"pattern": "/zh-hant/",
|
|
"allow": true
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"sitemap": [
|
|
"https://cloudproxy-pro.com/sitemap.xml",
|
|
"/sitemap_index.xml"
|
|
],
|
|
"header": true,
|
|
"robotsEnabledValue": "index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1",
|
|
"robotsDisabledValue": "noindex, nofollow",
|
|
"cacheControl": "max-age=14400, must-revalidate"
|
|
},
|
|
"nuxt-simple-robots": {
|
|
"version": "4.1.11",
|
|
"usingNuxtContent": true,
|
|
"debug": false,
|
|
"credits": true,
|
|
"groups": [
|
|
{
|
|
"comment": [],
|
|
"disallow": [],
|
|
"allow": [
|
|
"/",
|
|
"/zh/",
|
|
"/zh-hant/"
|
|
],
|
|
"userAgent": [
|
|
"*"
|
|
],
|
|
"_indexable": true,
|
|
"_rules": [
|
|
{
|
|
"pattern": "/",
|
|
"allow": true
|
|
},
|
|
{
|
|
"pattern": "/zh/",
|
|
"allow": true
|
|
},
|
|
{
|
|
"pattern": "/zh-hant/",
|
|
"allow": true
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"sitemap": [
|
|
"https://cloudproxy-pro.com/sitemap.xml",
|
|
"/sitemap_index.xml"
|
|
],
|
|
"header": true,
|
|
"robotsEnabledValue": "index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1",
|
|
"robotsDisabledValue": "noindex, nofollow",
|
|
"cacheControl": "max-age=14400, must-revalidate"
|
|
}
|
|
};
|
|
const envOptions = {
|
|
prefix: "NITRO_",
|
|
altPrefix: _inlineRuntimeConfig.nitro.envPrefix ?? process.env.NITRO_ENV_PREFIX ?? "_",
|
|
envExpansion: _inlineRuntimeConfig.nitro.envExpansion ?? process.env.NITRO_ENV_EXPANSION ?? false
|
|
};
|
|
const _sharedRuntimeConfig = _deepFreeze(
|
|
applyEnv(klona(_inlineRuntimeConfig), envOptions)
|
|
);
|
|
function useRuntimeConfig(event) {
|
|
if (!event) {
|
|
return _sharedRuntimeConfig;
|
|
}
|
|
if (event.context.nitro.runtimeConfig) {
|
|
return event.context.nitro.runtimeConfig;
|
|
}
|
|
const runtimeConfig = klona(_inlineRuntimeConfig);
|
|
applyEnv(runtimeConfig, envOptions);
|
|
event.context.nitro.runtimeConfig = runtimeConfig;
|
|
return runtimeConfig;
|
|
}
|
|
const _sharedAppConfig = _deepFreeze(klona(appConfig));
|
|
function useAppConfig(event) {
|
|
if (!event) {
|
|
return _sharedAppConfig;
|
|
}
|
|
if (event.context.nitro.appConfig) {
|
|
return event.context.nitro.appConfig;
|
|
}
|
|
const appConfig$1 = klona(appConfig);
|
|
event.context.nitro.appConfig = appConfig$1;
|
|
return appConfig$1;
|
|
}
|
|
function _deepFreeze(object) {
|
|
const propNames = Object.getOwnPropertyNames(object);
|
|
for (const name of propNames) {
|
|
const value = object[name];
|
|
if (value && typeof value === "object") {
|
|
_deepFreeze(value);
|
|
}
|
|
}
|
|
return Object.freeze(object);
|
|
}
|
|
new Proxy(/* @__PURE__ */ Object.create(null), {
|
|
get: (_, prop) => {
|
|
console.warn(
|
|
"Please use `useRuntimeConfig()` instead of accessing config directly."
|
|
);
|
|
const runtimeConfig = useRuntimeConfig();
|
|
if (prop in runtimeConfig) {
|
|
return runtimeConfig[prop];
|
|
}
|
|
return void 0;
|
|
}
|
|
});
|
|
|
|
const config = useRuntimeConfig();
|
|
const _routeRulesMatcher = toRouteMatcher(
|
|
createRouter({ routes: config.nitro.routeRules })
|
|
);
|
|
function createRouteRulesHandler(ctx) {
|
|
return eventHandler((event) => {
|
|
const routeRules = getRouteRules(event);
|
|
if (routeRules.headers) {
|
|
setHeaders(event, routeRules.headers);
|
|
}
|
|
if (routeRules.redirect) {
|
|
let target = routeRules.redirect.to;
|
|
if (target.endsWith("/**")) {
|
|
let targetPath = event.path;
|
|
const strpBase = routeRules.redirect._redirectStripBase;
|
|
if (strpBase) {
|
|
targetPath = withoutBase(targetPath, strpBase);
|
|
}
|
|
target = joinURL(target.slice(0, -3), targetPath);
|
|
} else if (event.path.includes("?")) {
|
|
const query = getQuery(event.path);
|
|
target = withQuery(target, query);
|
|
}
|
|
return sendRedirect(event, target, routeRules.redirect.statusCode);
|
|
}
|
|
if (routeRules.proxy) {
|
|
let target = routeRules.proxy.to;
|
|
if (target.endsWith("/**")) {
|
|
let targetPath = event.path;
|
|
const strpBase = routeRules.proxy._proxyStripBase;
|
|
if (strpBase) {
|
|
targetPath = withoutBase(targetPath, strpBase);
|
|
}
|
|
target = joinURL(target.slice(0, -3), targetPath);
|
|
} else if (event.path.includes("?")) {
|
|
const query = getQuery(event.path);
|
|
target = withQuery(target, query);
|
|
}
|
|
return proxyRequest(event, target, {
|
|
fetch: ctx.localFetch,
|
|
...routeRules.proxy
|
|
});
|
|
}
|
|
});
|
|
}
|
|
function getRouteRules(event) {
|
|
event.context._nitro = event.context._nitro || {};
|
|
if (!event.context._nitro.routeRules) {
|
|
event.context._nitro.routeRules = getRouteRulesForPath(
|
|
withoutBase(event.path.split("?")[0], useRuntimeConfig().app.baseURL)
|
|
);
|
|
}
|
|
return event.context._nitro.routeRules;
|
|
}
|
|
function getRouteRulesForPath(path) {
|
|
return defu({}, ..._routeRulesMatcher.matchAll(path).reverse());
|
|
}
|
|
|
|
function _captureError(error, type) {
|
|
console.error(`[${type}]`, error);
|
|
useNitroApp().captureError(error, { tags: [type] });
|
|
}
|
|
function trapUnhandledNodeErrors() {
|
|
process.on(
|
|
"unhandledRejection",
|
|
(error) => _captureError(error, "unhandledRejection")
|
|
);
|
|
process.on(
|
|
"uncaughtException",
|
|
(error) => _captureError(error, "uncaughtException")
|
|
);
|
|
}
|
|
function joinHeaders(value) {
|
|
return Array.isArray(value) ? value.join(", ") : String(value);
|
|
}
|
|
function normalizeFetchResponse(response) {
|
|
if (!response.headers.has("set-cookie")) {
|
|
return response;
|
|
}
|
|
return new Response(response.body, {
|
|
status: response.status,
|
|
statusText: response.statusText,
|
|
headers: normalizeCookieHeaders(response.headers)
|
|
});
|
|
}
|
|
function normalizeCookieHeader(header = "") {
|
|
return splitCookiesString(joinHeaders(header));
|
|
}
|
|
function normalizeCookieHeaders(headers) {
|
|
const outgoingHeaders = new Headers();
|
|
for (const [name, header] of headers) {
|
|
if (name === "set-cookie") {
|
|
for (const cookie of normalizeCookieHeader(header)) {
|
|
outgoingHeaders.append("set-cookie", cookie);
|
|
}
|
|
} else {
|
|
outgoingHeaders.set(name, joinHeaders(header));
|
|
}
|
|
}
|
|
return outgoingHeaders;
|
|
}
|
|
|
|
function isJsonRequest(event) {
|
|
if (hasReqHeader(event, "accept", "text/html")) {
|
|
return false;
|
|
}
|
|
return hasReqHeader(event, "accept", "application/json") || hasReqHeader(event, "user-agent", "curl/") || hasReqHeader(event, "user-agent", "httpie/") || hasReqHeader(event, "sec-fetch-mode", "cors") || event.path.startsWith("/api/") || event.path.endsWith(".json");
|
|
}
|
|
function hasReqHeader(event, name, includes) {
|
|
const value = getRequestHeader(event, name);
|
|
return value && typeof value === "string" && value.toLowerCase().includes(includes);
|
|
}
|
|
|
|
const errorHandler$0 = (async function errorhandler(error, event, { defaultHandler }) {
|
|
if (event.handled || isJsonRequest(event)) {
|
|
return;
|
|
}
|
|
const defaultRes = await defaultHandler(error, event, { json: true });
|
|
const statusCode = error.statusCode || 500;
|
|
if (statusCode === 404 && defaultRes.status === 302) {
|
|
setResponseHeaders(event, defaultRes.headers);
|
|
setResponseStatus(event, defaultRes.status, defaultRes.statusText);
|
|
return send(event, JSON.stringify(defaultRes.body, null, 2));
|
|
}
|
|
if (typeof defaultRes.body !== "string" && Array.isArray(defaultRes.body.stack)) {
|
|
defaultRes.body.stack = defaultRes.body.stack.join("\n");
|
|
}
|
|
const errorObject = defaultRes.body;
|
|
const url = new URL(errorObject.url);
|
|
errorObject.url = withoutBase(url.pathname, useRuntimeConfig(event).app.baseURL) + url.search + url.hash;
|
|
errorObject.message ||= "Server Error";
|
|
errorObject.data ||= error.data;
|
|
errorObject.statusMessage ||= error.statusMessage;
|
|
delete defaultRes.headers["content-type"];
|
|
delete defaultRes.headers["content-security-policy"];
|
|
setResponseHeaders(event, defaultRes.headers);
|
|
const reqHeaders = getRequestHeaders(event);
|
|
const isRenderingError = event.path.startsWith("/__nuxt_error") || !!reqHeaders["x-nuxt-error"];
|
|
const res = isRenderingError ? null : await useNitroApp().localFetch(
|
|
withQuery(joinURL(useRuntimeConfig(event).app.baseURL, "/__nuxt_error"), errorObject),
|
|
{
|
|
headers: { ...reqHeaders, "x-nuxt-error": "true" },
|
|
redirect: "manual"
|
|
}
|
|
).catch(() => null);
|
|
if (event.handled) {
|
|
return;
|
|
}
|
|
if (!res) {
|
|
const { template } = await Promise.resolve().then(function () { return errorDev; }) ;
|
|
{
|
|
errorObject.description = errorObject.message;
|
|
}
|
|
setResponseHeader(event, "Content-Type", "text/html;charset=UTF-8");
|
|
return send(event, template(errorObject));
|
|
}
|
|
const html = await res.text();
|
|
for (const [header, value] of res.headers.entries()) {
|
|
if (header === "set-cookie") {
|
|
appendResponseHeader(event, header, value);
|
|
continue;
|
|
}
|
|
setResponseHeader(event, header, value);
|
|
}
|
|
setResponseStatus(event, res.status && res.status !== 200 ? res.status : defaultRes.status, res.statusText || defaultRes.statusText);
|
|
return send(event, html);
|
|
});
|
|
|
|
function defineNitroErrorHandler(handler) {
|
|
return handler;
|
|
}
|
|
|
|
const errorHandler$1 = defineNitroErrorHandler(
|
|
async function defaultNitroErrorHandler(error, event) {
|
|
const res = await defaultHandler(error, event);
|
|
if (!event.node?.res.headersSent) {
|
|
setResponseHeaders(event, res.headers);
|
|
}
|
|
setResponseStatus(event, res.status, res.statusText);
|
|
return send(
|
|
event,
|
|
typeof res.body === "string" ? res.body : JSON.stringify(res.body, null, 2)
|
|
);
|
|
}
|
|
);
|
|
async function defaultHandler(error, event, opts) {
|
|
const isSensitive = error.unhandled || error.fatal;
|
|
const statusCode = error.statusCode || 500;
|
|
const statusMessage = error.statusMessage || "Server Error";
|
|
const url = getRequestURL(event, { xForwardedHost: true, xForwardedProto: true });
|
|
if (statusCode === 404) {
|
|
const baseURL = "/";
|
|
if (/^\/[^/]/.test(baseURL) && !url.pathname.startsWith(baseURL)) {
|
|
const redirectTo = `${baseURL}${url.pathname.slice(1)}${url.search}`;
|
|
return {
|
|
status: 302,
|
|
statusText: "Found",
|
|
headers: { location: redirectTo },
|
|
body: `Redirecting...`
|
|
};
|
|
}
|
|
}
|
|
await loadStackTrace(error).catch(consola.error);
|
|
const youch = new Youch();
|
|
if (isSensitive && !opts?.silent) {
|
|
const tags = [error.unhandled && "[unhandled]", error.fatal && "[fatal]"].filter(Boolean).join(" ");
|
|
const ansiError = await (await youch.toANSI(error)).replaceAll(process.cwd(), ".");
|
|
consola.error(
|
|
`[request error] ${tags} [${event.method}] ${url}
|
|
|
|
`,
|
|
ansiError
|
|
);
|
|
}
|
|
const useJSON = opts?.json || !getRequestHeader(event, "accept")?.includes("text/html");
|
|
const headers = {
|
|
"content-type": useJSON ? "application/json" : "text/html",
|
|
// Prevent browser from guessing the MIME types of resources.
|
|
"x-content-type-options": "nosniff",
|
|
// Prevent error page from being embedded in an iframe
|
|
"x-frame-options": "DENY",
|
|
// Prevent browsers from sending the Referer header
|
|
"referrer-policy": "no-referrer",
|
|
// Disable the execution of any js
|
|
"content-security-policy": "script-src 'self' 'unsafe-inline'; object-src 'none'; base-uri 'self';"
|
|
};
|
|
if (statusCode === 404 || !getResponseHeader(event, "cache-control")) {
|
|
headers["cache-control"] = "no-cache";
|
|
}
|
|
const body = useJSON ? {
|
|
error: true,
|
|
url,
|
|
statusCode,
|
|
statusMessage,
|
|
message: error.message,
|
|
data: error.data,
|
|
stack: error.stack?.split("\n").map((line) => line.trim())
|
|
} : await youch.toHTML(error, {
|
|
request: {
|
|
url: url.href,
|
|
method: event.method,
|
|
headers: getRequestHeaders(event)
|
|
}
|
|
});
|
|
return {
|
|
status: statusCode,
|
|
statusText: statusMessage,
|
|
headers,
|
|
body
|
|
};
|
|
}
|
|
async function loadStackTrace(error) {
|
|
if (!(error instanceof Error)) {
|
|
return;
|
|
}
|
|
const parsed = await new ErrorParser().defineSourceLoader(sourceLoader).parse(error);
|
|
const stack = error.message + "\n" + parsed.frames.map((frame) => fmtFrame(frame)).join("\n");
|
|
Object.defineProperty(error, "stack", { value: stack });
|
|
if (error.cause) {
|
|
await loadStackTrace(error.cause).catch(consola.error);
|
|
}
|
|
}
|
|
async function sourceLoader(frame) {
|
|
if (!frame.fileName || frame.fileType !== "fs" || frame.type === "native") {
|
|
return;
|
|
}
|
|
if (frame.type === "app") {
|
|
const rawSourceMap = await readFile(`${frame.fileName}.map`, "utf8").catch(() => {
|
|
});
|
|
if (rawSourceMap) {
|
|
const consumer = await new SourceMapConsumer(rawSourceMap);
|
|
const originalPosition = consumer.originalPositionFor({ line: frame.lineNumber, column: frame.columnNumber });
|
|
if (originalPosition.source && originalPosition.line) {
|
|
frame.fileName = resolve$1(dirname(frame.fileName), originalPosition.source);
|
|
frame.lineNumber = originalPosition.line;
|
|
frame.columnNumber = originalPosition.column || 0;
|
|
}
|
|
}
|
|
}
|
|
const contents = await readFile(frame.fileName, "utf8").catch(() => {
|
|
});
|
|
return contents ? { contents } : void 0;
|
|
}
|
|
function fmtFrame(frame) {
|
|
if (frame.type === "native") {
|
|
return frame.raw;
|
|
}
|
|
const src = `${frame.fileName || ""}:${frame.lineNumber}:${frame.columnNumber})`;
|
|
return frame.functionName ? `at ${frame.functionName} (${src}` : `at ${src}`;
|
|
}
|
|
|
|
const errorHandlers = [errorHandler$0, errorHandler$1];
|
|
|
|
async function errorHandler(error, event) {
|
|
for (const handler of errorHandlers) {
|
|
try {
|
|
await handler(error, event, { defaultHandler });
|
|
if (event.handled) {
|
|
return; // Response handled
|
|
}
|
|
} catch(error) {
|
|
// Handler itself thrown, log and continue
|
|
console.error(error);
|
|
}
|
|
}
|
|
// H3 will handle fallback
|
|
}
|
|
|
|
const script = `
|
|
if (!window.__NUXT_DEVTOOLS_TIME_METRIC__) {
|
|
Object.defineProperty(window, '__NUXT_DEVTOOLS_TIME_METRIC__', {
|
|
value: {},
|
|
enumerable: false,
|
|
configurable: true,
|
|
})
|
|
}
|
|
window.__NUXT_DEVTOOLS_TIME_METRIC__.appInit = Date.now()
|
|
`;
|
|
|
|
const _Px1ClibNtxFQj_wR9GjpwPYcmv6EwgjdSGwWhS0BBxk = (function(nitro) {
|
|
nitro.hooks.hook("render:html", (htmlContext) => {
|
|
htmlContext.head.push(`<script>${script}<\/script>`);
|
|
});
|
|
});
|
|
|
|
const rootDir = "D:/claude-project/web7-published";
|
|
|
|
const appHead = {"meta":[{"name":"viewport","content":"width=device-width, initial-scale=1"},{"charset":"utf-8"}],"link":[{"rel":"icon","type":"image/x-icon","href":"/favicon.ico"}],"style":[],"script":[{"id":"chatway","async":true,"src":"https://cdn.chatway.app/widget.js?id=FgIgGSxRD2i8"}],"noscript":[],"htmlAttrs":{"lang":"en"}};
|
|
|
|
const appRootTag = "div";
|
|
|
|
const appRootAttrs = {"id":"__nuxt"};
|
|
|
|
const appTeleportTag = "div";
|
|
|
|
const appTeleportAttrs = {"id":"teleports"};
|
|
|
|
const appId = "nuxt-app";
|
|
|
|
const devReducers = {
|
|
VNode: (data) => isVNode(data) ? { type: data.type, props: data.props } : void 0,
|
|
URL: (data) => data instanceof URL ? data.toString() : void 0
|
|
};
|
|
const asyncContext = getContext("nuxt-dev", { asyncContext: true, AsyncLocalStorage });
|
|
const _k4wlVec50Ea8cnXaqFijClJkLDTh1LE23pu07KSWvoA = (nitroApp) => {
|
|
const handler = nitroApp.h3App.handler;
|
|
nitroApp.h3App.handler = (event) => {
|
|
return asyncContext.callAsync({ logs: [], event }, () => handler(event));
|
|
};
|
|
onConsoleLog((_log) => {
|
|
const ctx = asyncContext.tryUse();
|
|
if (!ctx) {
|
|
return;
|
|
}
|
|
const rawStack = captureRawStackTrace();
|
|
if (!rawStack || rawStack.includes("runtime/vite-node.mjs")) {
|
|
return;
|
|
}
|
|
const trace = [];
|
|
let filename = "";
|
|
for (const entry of parseRawStackTrace(rawStack)) {
|
|
if (entry.source === globalThis._importMeta_.url) {
|
|
continue;
|
|
}
|
|
if (EXCLUDE_TRACE_RE.test(entry.source)) {
|
|
continue;
|
|
}
|
|
filename ||= entry.source.replace(withTrailingSlash(rootDir), "");
|
|
trace.push({
|
|
...entry,
|
|
source: entry.source.startsWith("file://") ? entry.source.replace("file://", "") : entry.source
|
|
});
|
|
}
|
|
const log = {
|
|
..._log,
|
|
// Pass along filename to allow the client to display more info about where log comes from
|
|
filename,
|
|
// Clean up file names in stack trace
|
|
stack: trace
|
|
};
|
|
ctx.logs.push(log);
|
|
});
|
|
nitroApp.hooks.hook("afterResponse", () => {
|
|
const ctx = asyncContext.tryUse();
|
|
if (!ctx) {
|
|
return;
|
|
}
|
|
return nitroApp.hooks.callHook("dev:ssr-logs", { logs: ctx.logs, path: ctx.event.path });
|
|
});
|
|
nitroApp.hooks.hook("render:html", (htmlContext) => {
|
|
const ctx = asyncContext.tryUse();
|
|
if (!ctx) {
|
|
return;
|
|
}
|
|
try {
|
|
const reducers = Object.assign(/* @__PURE__ */ Object.create(null), devReducers, ctx.event.context._payloadReducers);
|
|
htmlContext.bodyAppend.unshift(`<script type="application/json" data-nuxt-logs="${appId}">${stringify(ctx.logs, reducers)}<\/script>`);
|
|
} catch (e) {
|
|
const shortError = e instanceof Error && "toString" in e ? ` Received \`${e.toString()}\`.` : "";
|
|
console.warn(`[nuxt] Failed to stringify dev server logs.${shortError} You can define your own reducer/reviver for rich types following the instructions in https://nuxt.com/docs/api/composables/use-nuxt-app#payload.`);
|
|
}
|
|
});
|
|
};
|
|
const EXCLUDE_TRACE_RE = /\/node_modules\/(?:.*\/)?(?:nuxt|nuxt-nightly|nuxt-edge|nuxt3|consola|@vue)\/|core\/runtime\/nitro/;
|
|
function onConsoleLog(callback) {
|
|
consola$1.addReporter({
|
|
log(logObj) {
|
|
callback(logObj);
|
|
}
|
|
});
|
|
consola$1.wrapConsole();
|
|
}
|
|
|
|
function defineNitroPlugin(def) {
|
|
return def;
|
|
}
|
|
|
|
function defineRenderHandler(render) {
|
|
const runtimeConfig = useRuntimeConfig();
|
|
return eventHandler(async (event) => {
|
|
const nitroApp = useNitroApp();
|
|
const ctx = { event, render, response: void 0 };
|
|
await nitroApp.hooks.callHook("render:before", ctx);
|
|
if (!ctx.response) {
|
|
if (event.path === `${runtimeConfig.app.baseURL}favicon.ico`) {
|
|
setResponseHeader(event, "Content-Type", "image/x-icon");
|
|
return send(
|
|
event,
|
|
"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
|
|
);
|
|
}
|
|
ctx.response = await ctx.render(event);
|
|
if (!ctx.response) {
|
|
const _currentStatus = getResponseStatus(event);
|
|
setResponseStatus(event, _currentStatus === 200 ? 500 : _currentStatus);
|
|
return send(
|
|
event,
|
|
"No response returned from render handler: " + event.path
|
|
);
|
|
}
|
|
}
|
|
await nitroApp.hooks.callHook("render:response", ctx.response, ctx);
|
|
if (ctx.response.headers) {
|
|
setResponseHeaders(event, ctx.response.headers);
|
|
}
|
|
if (ctx.response.statusCode || ctx.response.statusMessage) {
|
|
setResponseStatus(
|
|
event,
|
|
ctx.response.statusCode,
|
|
ctx.response.statusMessage
|
|
);
|
|
}
|
|
return ctx.response.body;
|
|
});
|
|
}
|
|
|
|
const scheduledTasks = false;
|
|
|
|
const tasks = {
|
|
|
|
};
|
|
|
|
const __runningTasks__ = {};
|
|
async function runTask(name, {
|
|
payload = {},
|
|
context = {}
|
|
} = {}) {
|
|
if (__runningTasks__[name]) {
|
|
return __runningTasks__[name];
|
|
}
|
|
if (!(name in tasks)) {
|
|
throw createError({
|
|
message: `Task \`${name}\` is not available!`,
|
|
statusCode: 404
|
|
});
|
|
}
|
|
if (!tasks[name].resolve) {
|
|
throw createError({
|
|
message: `Task \`${name}\` is not implemented!`,
|
|
statusCode: 501
|
|
});
|
|
}
|
|
const handler = await tasks[name].resolve();
|
|
const taskEvent = { name, payload, context };
|
|
__runningTasks__[name] = handler.run(taskEvent);
|
|
try {
|
|
const res = await __runningTasks__[name];
|
|
return res;
|
|
} finally {
|
|
delete __runningTasks__[name];
|
|
}
|
|
}
|
|
|
|
function buildAssetsDir() {
|
|
return useRuntimeConfig().app.buildAssetsDir;
|
|
}
|
|
function buildAssetsURL(...path) {
|
|
return joinRelativeURL(publicAssetsURL(), buildAssetsDir(), ...path);
|
|
}
|
|
function publicAssetsURL(...path) {
|
|
const app = useRuntimeConfig().app;
|
|
const publicBase = app.cdnURL || app.baseURL;
|
|
return path.length ? joinRelativeURL(publicBase, ...path) : publicBase;
|
|
}
|
|
|
|
function isTag(vnode, tag) {
|
|
if (vnode.type === tag) {
|
|
return true;
|
|
}
|
|
if (typeof vnode.type === "object" && vnode.type.tag === tag) {
|
|
return true;
|
|
}
|
|
if (vnode.tag === tag) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
function isText(vnode) {
|
|
return isTag(vnode, "text") || isTag(vnode, Symbol.for("v-txt"));
|
|
}
|
|
function nodeChildren(node) {
|
|
if (Array.isArray(node.children) || typeof node.children === "string") {
|
|
return node.children;
|
|
}
|
|
if (typeof node.children?.default === "function") {
|
|
return node.children.default();
|
|
}
|
|
return [];
|
|
}
|
|
function nodeTextContent(node) {
|
|
if (!node) {
|
|
return "";
|
|
}
|
|
if (Array.isArray(node)) {
|
|
return node.map(nodeTextContent).join("");
|
|
}
|
|
if (isText(node)) {
|
|
return node.children || node.value || "";
|
|
}
|
|
const children = nodeChildren(node);
|
|
if (Array.isArray(children)) {
|
|
return children.map(nodeTextContent).filter(Boolean).join("");
|
|
}
|
|
return "";
|
|
}
|
|
|
|
const useProcessorPlugins = async (processor, plugins = {}) => {
|
|
const toUse = Object.entries(plugins).filter((p) => p[1] !== false);
|
|
for (const plugin of toUse) {
|
|
const instance = plugin[1].instance || await import(
|
|
/* @vite-ignore */
|
|
plugin[0]
|
|
).then((m) => m.default || m);
|
|
processor.use(instance, plugin[1].options);
|
|
}
|
|
};
|
|
|
|
function emphasis(state, node) {
|
|
const result = {
|
|
type: "element",
|
|
tagName: "em",
|
|
properties: node.attributes || {},
|
|
children: state.all(node)
|
|
};
|
|
state.patch(node, result);
|
|
return state.applyData(node, result);
|
|
}
|
|
|
|
function parseThematicBlock(lang) {
|
|
if (!lang?.trim()) {
|
|
return {
|
|
language: void 0,
|
|
highlights: void 0,
|
|
filename: void 0,
|
|
meta: void 0
|
|
};
|
|
}
|
|
const languageMatches = lang.replace(/[{|[](.+)/, "").match(/^[^ \t]+(?=[ \t]|$)/);
|
|
const highlightTokensMatches = lang.match(/\{([^}]*)\}/);
|
|
const filenameMatches = lang.match(/\[((\\\]|[^\]])*)\]/);
|
|
const meta = lang.replace(languageMatches?.[0] ?? "", "").replace(highlightTokensMatches?.[0] ?? "", "").replace(filenameMatches?.[0] ?? "", "").trim();
|
|
return {
|
|
language: languageMatches?.[0] || void 0,
|
|
highlights: parseHighlightedLines(highlightTokensMatches?.[1] || void 0),
|
|
// https://github.com/nuxt/content/pull/2169
|
|
filename: filenameMatches?.[1].replace(/\\\]/g, "]") || void 0,
|
|
meta
|
|
};
|
|
}
|
|
function parseHighlightedLines(lines) {
|
|
const lineArray = String(lines || "").split(",").filter(Boolean).flatMap((line) => {
|
|
const [start, end] = line.trim().split("-").map((a) => Number(a.trim()));
|
|
return Array.from({ length: (end || start) - start + 1 }).map((_, i) => start + i);
|
|
});
|
|
return lineArray.length ? lineArray : void 0;
|
|
}
|
|
const TAG_NAME_REGEXP = /^<\/?([\w-]+)(\s[^>]*?)?\/?>/;
|
|
function getTagName(value) {
|
|
const result = String(value).match(TAG_NAME_REGEXP);
|
|
return result && result[1];
|
|
}
|
|
|
|
const code = (state, node) => {
|
|
const lang = (node.lang || "") + " " + (node.meta || "");
|
|
const { language, highlights, filename, meta } = parseThematicBlock(lang);
|
|
const value = node.value ? detab(node.value + "\n") : "";
|
|
let result = {
|
|
type: "element",
|
|
tagName: "code",
|
|
properties: { __ignoreMap: "" },
|
|
children: [{ type: "text", value }]
|
|
};
|
|
if (meta) {
|
|
result.data = {
|
|
meta
|
|
};
|
|
}
|
|
state.patch(node, result);
|
|
result = state.applyData(node, result);
|
|
const properties = {
|
|
language,
|
|
filename,
|
|
highlights,
|
|
meta,
|
|
code: value
|
|
};
|
|
if (language) {
|
|
properties.className = ["language-" + language];
|
|
}
|
|
result = { type: "element", tagName: "pre", properties, children: [result] };
|
|
state.patch(node, result);
|
|
return result;
|
|
};
|
|
|
|
function html(state, node) {
|
|
const tagName = getTagName(node.value);
|
|
if (tagName && /[A-Z]/.test(tagName)) {
|
|
node.value = node.value.replace(tagName, kebabCase(tagName));
|
|
}
|
|
if (state.dangerous || state.options?.allowDangerousHtml) {
|
|
const result = { type: "raw", value: node.value };
|
|
state.patch(node, result);
|
|
return state.applyData(node, result);
|
|
}
|
|
return void 0;
|
|
}
|
|
|
|
function link$1(state, node) {
|
|
const properties = {
|
|
...node.attributes || {},
|
|
href: normalizeUri(node.url)
|
|
};
|
|
if (node.title !== null && node.title !== void 0) {
|
|
properties.title = node.title;
|
|
}
|
|
const result = {
|
|
type: "element",
|
|
tagName: "a",
|
|
properties,
|
|
children: state.all(node)
|
|
};
|
|
state.patch(node, result);
|
|
return state.applyData(node, result);
|
|
}
|
|
|
|
function list(state, node) {
|
|
const properties = {};
|
|
const results = state.all(node);
|
|
let index = -1;
|
|
if (typeof node.start === "number" && node.start !== 1) {
|
|
properties.start = node.start;
|
|
}
|
|
while (++index < results.length) {
|
|
const child = results[index];
|
|
if (child.type === "element" && child.tagName === "li" && child.properties && Array.isArray(child.properties.className) && child.properties.className.includes("task-list-item")) {
|
|
properties.className = ["contains-task-list"];
|
|
break;
|
|
}
|
|
}
|
|
if ((node.children || []).some((child) => typeof child.checked === "boolean")) {
|
|
properties.className = ["contains-task-list"];
|
|
}
|
|
const result = {
|
|
type: "element",
|
|
tagName: node.ordered ? "ol" : "ul",
|
|
properties,
|
|
children: state.wrap(results, true)
|
|
};
|
|
state.patch(node, result);
|
|
return state.applyData(node, result);
|
|
}
|
|
|
|
const htmlTags = [
|
|
"a",
|
|
"abbr",
|
|
"address",
|
|
"area",
|
|
"article",
|
|
"aside",
|
|
"audio",
|
|
"b",
|
|
"base",
|
|
"bdi",
|
|
"bdo",
|
|
"blockquote",
|
|
"body",
|
|
"br",
|
|
"button",
|
|
"canvas",
|
|
"caption",
|
|
"cite",
|
|
"code",
|
|
"col",
|
|
"colgroup",
|
|
"data",
|
|
"datalist",
|
|
"dd",
|
|
"del",
|
|
"details",
|
|
"dfn",
|
|
"dialog",
|
|
"div",
|
|
"dl",
|
|
"dt",
|
|
"em",
|
|
"embed",
|
|
"fieldset",
|
|
"figcaption",
|
|
"figure",
|
|
"footer",
|
|
"form",
|
|
"h1",
|
|
"h2",
|
|
"h3",
|
|
"h4",
|
|
"h5",
|
|
"h6",
|
|
"head",
|
|
"header",
|
|
"hgroup",
|
|
"hr",
|
|
"html",
|
|
"i",
|
|
"iframe",
|
|
"img",
|
|
"input",
|
|
"ins",
|
|
"kbd",
|
|
"label",
|
|
"legend",
|
|
"li",
|
|
"link",
|
|
"main",
|
|
"map",
|
|
"mark",
|
|
"math",
|
|
"menu",
|
|
"menuitem",
|
|
"meta",
|
|
"meter",
|
|
"nav",
|
|
"noscript",
|
|
"object",
|
|
"ol",
|
|
"optgroup",
|
|
"option",
|
|
"output",
|
|
"p",
|
|
"param",
|
|
"picture",
|
|
"pre",
|
|
"progress",
|
|
"q",
|
|
"rb",
|
|
"rp",
|
|
"rt",
|
|
"rtc",
|
|
"ruby",
|
|
"s",
|
|
"samp",
|
|
"script",
|
|
"section",
|
|
"select",
|
|
"slot",
|
|
"small",
|
|
"source",
|
|
"span",
|
|
"strong",
|
|
"style",
|
|
"sub",
|
|
"summary",
|
|
"sup",
|
|
"svg",
|
|
"table",
|
|
"tbody",
|
|
"td",
|
|
"template",
|
|
"textarea",
|
|
"tfoot",
|
|
"th",
|
|
"thead",
|
|
"time",
|
|
"title",
|
|
"tr",
|
|
"track",
|
|
"u",
|
|
"ul",
|
|
"var",
|
|
"video",
|
|
"wbr"
|
|
];
|
|
|
|
function paragraph(state, node) {
|
|
if (node.children && node.children[0] && node.children[0].type === "html") {
|
|
const tagName = kebabCase(getTagName(node.children[0].value) || "div");
|
|
if (!htmlTags.includes(tagName)) {
|
|
return state.all(node);
|
|
}
|
|
}
|
|
const result = {
|
|
type: "element",
|
|
tagName: "p",
|
|
properties: {},
|
|
children: state.all(node)
|
|
};
|
|
state.patch(node, result);
|
|
return state.applyData(node, result);
|
|
}
|
|
|
|
function image(state, node) {
|
|
const properties = { ...node.attributes, src: normalizeUri(node.url) };
|
|
if (node.alt !== null && node.alt !== void 0) {
|
|
properties.alt = node.alt;
|
|
}
|
|
if (node.title !== null && node.title !== void 0) {
|
|
properties.title = node.title;
|
|
}
|
|
const result = { type: "element", tagName: "img", properties, children: [] };
|
|
state.patch(node, result);
|
|
return state.applyData(node, result);
|
|
}
|
|
|
|
function strong(state, node) {
|
|
const result = {
|
|
type: "element",
|
|
tagName: "strong",
|
|
properties: node.attributes || {},
|
|
children: state.all(node)
|
|
};
|
|
state.patch(node, result);
|
|
return state.applyData(node, result);
|
|
}
|
|
|
|
function inlineCode(state, node) {
|
|
const language = node.attributes?.language || node.attributes?.lang;
|
|
const text = { type: "text", value: node.value.replace(/\r?\n|\r/g, " ") };
|
|
state.patch(node, text);
|
|
const result = {
|
|
type: "element",
|
|
tagName: "code",
|
|
properties: node.attributes || {},
|
|
children: [text]
|
|
};
|
|
const classes = (result.properties.class || "").split(" ");
|
|
delete result.properties.class;
|
|
if (language) {
|
|
result.properties.language = language;
|
|
delete result.properties.lang;
|
|
classes.push("language-" + language);
|
|
}
|
|
result.properties.className = classes.join(" ");
|
|
state.patch(node, result);
|
|
return state.applyData(node, result);
|
|
}
|
|
|
|
function containerComponent(state, node) {
|
|
const result = {
|
|
type: "element",
|
|
tagName: node.name,
|
|
properties: {
|
|
...node.attributes,
|
|
...node.data?.hProperties
|
|
},
|
|
children: state.all(node)
|
|
};
|
|
state.patch(node, result);
|
|
result.attributes = node.attributes;
|
|
result.fmAttributes = node.fmAttributes;
|
|
return result;
|
|
}
|
|
|
|
const handlers$1 = {
|
|
emphasis,
|
|
code,
|
|
link: link$1,
|
|
paragraph,
|
|
html,
|
|
list,
|
|
image,
|
|
strong,
|
|
inlineCode,
|
|
containerComponent
|
|
};
|
|
|
|
const defaults = {
|
|
remark: {
|
|
plugins: {
|
|
"remark-mdc": {
|
|
instance: remarkMDC
|
|
},
|
|
"remark-gfm": {
|
|
instance: remarkGFM
|
|
}
|
|
}
|
|
},
|
|
rehype: {
|
|
options: {
|
|
handlers: handlers$1,
|
|
allowDangerousHtml: true
|
|
},
|
|
plugins: {
|
|
"rehype-external-links": {
|
|
instance: rehypeExternalLinks
|
|
},
|
|
"rehype-sort-attribute-values": {
|
|
instance: rehypeSortAttributeValues
|
|
},
|
|
"rehype-sort-attributes": {
|
|
instance: rehypeSortAttributes
|
|
},
|
|
"rehype-raw": {
|
|
instance: rehypeRaw,
|
|
options: {
|
|
passThrough: ["element"]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
highlight: false,
|
|
toc: {
|
|
searchDepth: 2,
|
|
depth: 2
|
|
}
|
|
};
|
|
|
|
function flattenNodeText(node) {
|
|
if (node.type === "comment") {
|
|
return "";
|
|
}
|
|
if (node.type === "text") {
|
|
return node.value || "";
|
|
} else {
|
|
return (node.children || []).reduce((text, child) => {
|
|
return text.concat(flattenNodeText(child));
|
|
}, "");
|
|
}
|
|
}
|
|
function flattenNode(node, maxDepth = 2, _depth = 0) {
|
|
if (!Array.isArray(node.children) || _depth === maxDepth) {
|
|
return [node];
|
|
}
|
|
return [
|
|
node,
|
|
...node.children.reduce((acc, child) => acc.concat(flattenNode(child, maxDepth, _depth + 1)), [])
|
|
];
|
|
}
|
|
|
|
const TOC_TAGS = ["h2", "h3", "h4", "h5", "h6"];
|
|
const TOC_TAGS_DEPTH = TOC_TAGS.reduce((tags, tag) => {
|
|
tags[tag] = Number(tag.charAt(tag.length - 1));
|
|
return tags;
|
|
}, {});
|
|
const getHeaderDepth = (node) => TOC_TAGS_DEPTH[node.tag];
|
|
const getTocTags = (depth) => {
|
|
if (depth < 1 || depth > 5) {
|
|
console.log(`\`toc.depth\` is set to ${depth}. It should be a number between 1 and 5. `);
|
|
depth = 1;
|
|
}
|
|
return TOC_TAGS.slice(0, depth);
|
|
};
|
|
function nestHeaders(headers) {
|
|
if (headers.length <= 1) {
|
|
return headers;
|
|
}
|
|
const toc = [];
|
|
let parent;
|
|
headers.forEach((header) => {
|
|
if (!parent || header.depth <= parent.depth) {
|
|
header.children = [];
|
|
parent = header;
|
|
toc.push(header);
|
|
} else {
|
|
parent.children.push(header);
|
|
}
|
|
});
|
|
toc.forEach((header) => {
|
|
if (header.children?.length) {
|
|
header.children = nestHeaders(header.children);
|
|
} else {
|
|
delete header.children;
|
|
}
|
|
});
|
|
return toc;
|
|
}
|
|
function generateFlatToc(body, options) {
|
|
const { searchDepth, depth, title = "" } = options;
|
|
const tags = getTocTags(depth);
|
|
const headers = flattenNode(body, searchDepth).filter((node) => tags.includes(node.tag || ""));
|
|
const links = headers.map((node) => ({
|
|
id: node.props?.id,
|
|
depth: getHeaderDepth(node),
|
|
text: flattenNodeText(node)
|
|
}));
|
|
return {
|
|
title,
|
|
searchDepth,
|
|
depth,
|
|
links
|
|
};
|
|
}
|
|
function generateToc(body, options) {
|
|
const toc = generateFlatToc(body, options);
|
|
toc.links = nestHeaders(toc.links);
|
|
return toc;
|
|
}
|
|
|
|
const unsafeLinkPrefix = [
|
|
"javascript:",
|
|
"data:text/html",
|
|
"vbscript:",
|
|
"data:text/javascript",
|
|
"data:text/vbscript",
|
|
"data:text/css",
|
|
"data:text/plain",
|
|
"data:text/xml"
|
|
];
|
|
const validateProp = (attribute, value) => {
|
|
if (attribute.startsWith("on")) {
|
|
return false;
|
|
}
|
|
if (attribute === "href" || attribute === "src") {
|
|
return !unsafeLinkPrefix.some((prefix) => value.toLowerCase().startsWith(prefix));
|
|
}
|
|
return true;
|
|
};
|
|
const validateProps = (type, props) => {
|
|
if (!props) {
|
|
return {};
|
|
}
|
|
props = Object.fromEntries(
|
|
Object.entries(props).filter(([name, value]) => {
|
|
const isValid = validateProp(name, value);
|
|
if (!isValid) {
|
|
console.warn(`[@nuxtjs/mdc] removing unsafe attribute: ${name}="${value}"`);
|
|
}
|
|
return isValid;
|
|
})
|
|
);
|
|
if (type === "pre") {
|
|
if (typeof props.highlights === "string") {
|
|
props.highlights = props.highlights.split(" ").map((i) => Number.parseInt(i));
|
|
}
|
|
}
|
|
return props;
|
|
};
|
|
|
|
function compileHast(options = {}) {
|
|
const slugs = new Slugger();
|
|
function compileToJSON(node, parent) {
|
|
if (node.type === "root") {
|
|
return {
|
|
type: "root",
|
|
children: node.children.map((child) => compileToJSON(child, node)).filter(Boolean)
|
|
};
|
|
}
|
|
if (node.type === "element") {
|
|
if (node.tagName === "p" && node.children.every((child) => child.type === "text" && /^\s*$/.test(child.value))) {
|
|
return null;
|
|
}
|
|
if (node.tagName === "li") {
|
|
let hasPreviousParagraph = false;
|
|
node.children = node.children?.flatMap((child) => {
|
|
if (child.type === "element" && child.tagName === "p") {
|
|
if (hasPreviousParagraph) {
|
|
child.children.unshift({
|
|
type: "element",
|
|
tagName: "br",
|
|
properties: {},
|
|
children: []
|
|
});
|
|
}
|
|
hasPreviousParagraph = true;
|
|
return child.children;
|
|
}
|
|
return child;
|
|
});
|
|
}
|
|
if (node.tagName?.match(/^h\d$/)) {
|
|
node.properties = node.properties || {};
|
|
node.properties.id = String(node.properties?.id || slugs.slug(toString(node))).replace(/-+/g, "-").replace(/^-|-$/g, "").replace(/^(\d)/, "_$1");
|
|
}
|
|
if (node.tagName === "component-slot") {
|
|
node.tagName = "template";
|
|
}
|
|
const children = (node.tagName === "template" && node.content?.children.length ? node.content.children : node.children).map((child) => compileToJSON(child, node)).filter(Boolean);
|
|
return {
|
|
type: "element",
|
|
tag: node.tagName,
|
|
props: validateProps(node.tagName, node.properties),
|
|
children
|
|
};
|
|
}
|
|
if (node.type === "text") {
|
|
if (!/^\n+$/.test(node.value || "") || parent?.properties?.emptyLinePlaceholder) {
|
|
return {
|
|
type: "text",
|
|
value: node.value
|
|
};
|
|
}
|
|
}
|
|
if (options.keepComments && node.type === "comment") {
|
|
return {
|
|
type: "comment",
|
|
value: node.value
|
|
};
|
|
}
|
|
return null;
|
|
}
|
|
this.Compiler = (tree) => {
|
|
const body = compileToJSON(tree);
|
|
let excerpt = void 0;
|
|
const excerptIndex = tree.children.findIndex((node) => node.type === "comment" && node.value?.trim() === "more");
|
|
if (excerptIndex !== -1) {
|
|
excerpt = compileToJSON({
|
|
type: "root",
|
|
children: tree.children.slice(0, excerptIndex)
|
|
});
|
|
if (excerpt.children.find((node) => node.type === "element" && node.tag === "pre")) {
|
|
const lastChild = body.children[body.children.length - 1];
|
|
if (lastChild.type === "element" && lastChild.tag === "style") {
|
|
excerpt.children.push(lastChild);
|
|
}
|
|
}
|
|
}
|
|
body.children = (body.children || []).filter((child) => child.type !== "text");
|
|
return {
|
|
body,
|
|
excerpt
|
|
};
|
|
};
|
|
}
|
|
|
|
let moduleOptions;
|
|
let generatedMdcConfigs;
|
|
const createMarkdownParser = async (inlineOptions = {}) => {
|
|
if (!moduleOptions) {
|
|
moduleOptions = await Promise.resolve().then(function () { return mdcImports; }).catch(() => ({}));
|
|
}
|
|
if (!generatedMdcConfigs) {
|
|
generatedMdcConfigs = await Promise.resolve().then(function () { return mdcConfigs; }).then((r) => r.getMdcConfigs()).catch(() => []);
|
|
}
|
|
const mdcConfigs$1 = [
|
|
...generatedMdcConfigs || [],
|
|
...inlineOptions.configs || []
|
|
];
|
|
if (inlineOptions.highlight != null && inlineOptions.highlight != false && inlineOptions.highlight.highlighter !== void 0 && typeof inlineOptions.highlight.highlighter !== "function") {
|
|
console.warn("[@nuxtjs/mdc] `highlighter` passed to `parseMarkdown` is should be a function, but got " + JSON.stringify(inlineOptions.highlight.highlighter) + ", ignored.");
|
|
inlineOptions = {
|
|
...inlineOptions,
|
|
highlight: {
|
|
...inlineOptions.highlight
|
|
}
|
|
};
|
|
delete inlineOptions.highlight.highlighter;
|
|
}
|
|
const options = defu$1(inlineOptions, {
|
|
remark: { plugins: moduleOptions?.remarkPlugins },
|
|
rehype: { plugins: moduleOptions?.rehypePlugins },
|
|
highlight: moduleOptions?.highlight
|
|
}, defaults);
|
|
if (options.rehype?.plugins?.highlight) {
|
|
options.rehype.plugins.highlight.options = {
|
|
...options.rehype.plugins.highlight.options || {},
|
|
...options.highlight || {}
|
|
};
|
|
}
|
|
let processor = unified();
|
|
for (const config of mdcConfigs$1) {
|
|
processor = await config.unified?.pre?.(processor) || processor;
|
|
}
|
|
processor.use(remarkParse);
|
|
for (const config of mdcConfigs$1) {
|
|
processor = await config.unified?.remark?.(processor) || processor;
|
|
}
|
|
await useProcessorPlugins(processor, options.remark?.plugins);
|
|
processor.use(remark2rehype, options.rehype?.options);
|
|
for (const config of mdcConfigs$1) {
|
|
processor = await config.unified?.rehype?.(processor) || processor;
|
|
}
|
|
await useProcessorPlugins(processor, options.rehype?.plugins);
|
|
processor.use(compileHast, options);
|
|
for (const config of mdcConfigs$1) {
|
|
processor = await config.unified?.post?.(processor) || processor;
|
|
}
|
|
return async function parse(md, { fileOptions } = {}) {
|
|
const { content, data: frontmatter } = await parseFrontMatter(md);
|
|
const processedFile = await processor.process({ ...fileOptions, value: content, data: frontmatter });
|
|
const result = processedFile.result;
|
|
const data = Object.assign(
|
|
contentHeading(result.body),
|
|
frontmatter,
|
|
processedFile?.data || {}
|
|
);
|
|
let toc;
|
|
if (data.toc !== false) {
|
|
const tocOption = defu$1(data.toc || {}, options.toc);
|
|
toc = generateToc(result.body, tocOption);
|
|
}
|
|
return {
|
|
data,
|
|
body: result.body,
|
|
excerpt: result.excerpt,
|
|
toc
|
|
};
|
|
};
|
|
};
|
|
const parseMarkdown = async (md, markdownParserOptions = {}, parseOptions = {}) => {
|
|
const parser = await createMarkdownParser(markdownParserOptions);
|
|
return parser(md, parseOptions);
|
|
};
|
|
function contentHeading(body) {
|
|
let title = "";
|
|
let description = "";
|
|
const children = body.children.filter((node) => node.type === "element" && node.tag !== "hr");
|
|
if (children.length && children[0].tag === "h1") {
|
|
const node = children.shift();
|
|
title = nodeTextContent(node);
|
|
}
|
|
if (children.length && children[0].tag === "p") {
|
|
const node = children.shift();
|
|
description = nodeTextContent(node);
|
|
}
|
|
return {
|
|
title,
|
|
description
|
|
};
|
|
}
|
|
|
|
function getSiteIndexable(e) {
|
|
const { env, indexable } = useSiteConfig(e);
|
|
if (typeof indexable !== "undefined")
|
|
return String(indexable) === "true";
|
|
return env === "production";
|
|
}
|
|
|
|
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 && !hasProtocol(config.url, { acceptRelative: true, strict: false }))
|
|
config.url = 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 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 ? 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
|
|
]));
|
|
}
|
|
|
|
function useNitroOrigin(e) {
|
|
const cert = process.env.NITRO_SSL_CERT;
|
|
const key = process.env.NITRO_SSL_KEY;
|
|
let host = process.env.NITRO_HOST || process.env.HOST || false;
|
|
let port = false;
|
|
port = process.env.NITRO_PORT || process.env.PORT || "3000";
|
|
let protocol = cert && key || false ? "https" : "http";
|
|
if (process.env.__NUXT_DEV__) {
|
|
const origin = JSON.parse(process.env.__NUXT_DEV__).proxy.url;
|
|
host = withoutProtocol(origin);
|
|
protocol = origin.includes("https") ? "https" : "http";
|
|
} else if (process.env.NUXT_VITE_NODE_OPTIONS) {
|
|
const origin = JSON.parse(process.env.NUXT_VITE_NODE_OPTIONS).baseURL.replace("/__nuxt_vite_node__", "");
|
|
host = withoutProtocol(origin);
|
|
protocol = origin.includes("https") ? "https" : "http";
|
|
} else {
|
|
host = getRequestHost(e, { xForwardedHost: true }) || host;
|
|
protocol = getRequestProtocol(e, { xForwardedProto: true }) || protocol;
|
|
}
|
|
if (typeof host === "string" && host.includes(":")) {
|
|
port = host.split(":").pop();
|
|
host = host.split(":")[0];
|
|
}
|
|
port = port ? `:${port}` : "";
|
|
return withTrailingSlash(`${protocol}://${host}${port}`);
|
|
}
|
|
|
|
function useSiteConfig(e, _options) {
|
|
e.context.siteConfig = e.context.siteConfig || createSiteConfigStack();
|
|
const options = defu$1(_options, useRuntimeConfig(e)["nuxt-site-config"], { debug: false });
|
|
return e.context.siteConfig.get(options);
|
|
}
|
|
|
|
function resolveSitePath(pathOrUrl, options) {
|
|
let path = pathOrUrl;
|
|
if (hasProtocol(pathOrUrl, { strict: false, acceptRelative: true })) {
|
|
const parsed = parseURL(pathOrUrl);
|
|
path = parsed.pathname;
|
|
}
|
|
const base = withLeadingSlash(options.base || "/");
|
|
if (base !== "/" && path.startsWith(base)) {
|
|
path = path.slice(base.length);
|
|
}
|
|
let origin = withoutTrailingSlash(options.absolute ? options.siteUrl : "");
|
|
if (base !== "/" && origin.endsWith(base)) {
|
|
origin = origin.slice(0, origin.indexOf(base));
|
|
}
|
|
const baseWithOrigin = options.withBase ? withBase(base, origin || "/") : origin;
|
|
const resolvedUrl = withBase(path, baseWithOrigin);
|
|
return path === "/" && !options.withBase ? withTrailingSlash(resolvedUrl) : fixSlashes(options.trailingSlash, resolvedUrl);
|
|
}
|
|
function isPathFile(path) {
|
|
const lastSegment = path.split("/").pop();
|
|
return !!(lastSegment || path).match(/\.[0-9a-z]+$/i)?.[0];
|
|
}
|
|
function fixSlashes(trailingSlash, pathOrUrl) {
|
|
const $url = parseURL(pathOrUrl);
|
|
if (isPathFile($url.pathname))
|
|
return pathOrUrl;
|
|
const fixedPath = trailingSlash ? withTrailingSlash($url.pathname) : withoutTrailingSlash($url.pathname);
|
|
return `${$url.protocol ? `${$url.protocol}//` : ""}${$url.host || ""}${fixedPath}${$url.search || ""}${$url.hash || ""}`;
|
|
}
|
|
|
|
function createSitePathResolver(e, options = {}) {
|
|
const siteConfig = useSiteConfig(e);
|
|
const nitroOrigin = useNitroOrigin(e);
|
|
const nuxtBase = useRuntimeConfig(e).app.baseURL || "/";
|
|
return (path) => {
|
|
return resolveSitePath(path, {
|
|
...options,
|
|
siteUrl: options.canonical !== false || false ? siteConfig.url : nitroOrigin,
|
|
trailingSlash: siteConfig.trailingSlash,
|
|
base: nuxtBase
|
|
});
|
|
};
|
|
}
|
|
function withSiteUrl(e, path, options = {}) {
|
|
const siteConfig = e.context.siteConfig?.get();
|
|
let siteUrl = e.context.siteConfigNitroOrigin;
|
|
if ((options.canonical !== false || false) && siteConfig.url)
|
|
siteUrl = siteConfig.url;
|
|
return resolveSitePath(path, {
|
|
absolute: true,
|
|
siteUrl,
|
|
trailingSlash: siteConfig.trailingSlash,
|
|
base: e.context.nitro.baseURL,
|
|
withBase: options.withBase
|
|
});
|
|
}
|
|
|
|
function matches(pattern, path) {
|
|
const pathLength = path.length;
|
|
const patternLength = pattern.length;
|
|
const matchingLengths = Array.from({ length: pathLength + 1 }).fill(0);
|
|
let numMatchingLengths = 1;
|
|
let p = 0;
|
|
while (p < patternLength) {
|
|
if (pattern[p] === "$" && p + 1 === patternLength) {
|
|
return matchingLengths[numMatchingLengths - 1] === pathLength;
|
|
}
|
|
if (pattern[p] === "*") {
|
|
numMatchingLengths = pathLength - matchingLengths[0] + 1;
|
|
for (let i = 1; i < numMatchingLengths; i++) {
|
|
matchingLengths[i] = matchingLengths[i - 1] + 1;
|
|
}
|
|
} else {
|
|
let numMatches = 0;
|
|
for (let i = 0; i < numMatchingLengths; i++) {
|
|
const matchLength = matchingLengths[i];
|
|
if (matchLength < pathLength && path[matchLength] === pattern[p]) {
|
|
matchingLengths[numMatches++] = matchLength + 1;
|
|
}
|
|
}
|
|
if (numMatches === 0) {
|
|
return false;
|
|
}
|
|
numMatchingLengths = numMatches;
|
|
}
|
|
p++;
|
|
}
|
|
return true;
|
|
}
|
|
function matchPathToRule(path, _rules) {
|
|
let matchedRule = null;
|
|
const rules = _rules.filter(Boolean);
|
|
const rulesLength = rules.length;
|
|
let i = 0;
|
|
while (i < rulesLength) {
|
|
const rule = rules[i];
|
|
if (!matches(rule.pattern, path)) {
|
|
i++;
|
|
continue;
|
|
}
|
|
if (!matchedRule || rule.pattern.length > matchedRule.pattern.length) {
|
|
matchedRule = rule;
|
|
} else if (rule.pattern.length === matchedRule.pattern.length && rule.allow && !matchedRule.allow) {
|
|
matchedRule = rule;
|
|
}
|
|
i++;
|
|
}
|
|
return matchedRule;
|
|
}
|
|
function asArray(v) {
|
|
return typeof v === "undefined" ? [] : Array.isArray(v) ? v : [v];
|
|
}
|
|
function generateRobotsTxt({ groups, sitemaps }) {
|
|
const lines = [];
|
|
for (const group of groups) {
|
|
for (const comment of group.comment || [])
|
|
lines.push(`# ${comment}`);
|
|
for (const userAgent of group.userAgent || ["*"])
|
|
lines.push(`User-agent: ${userAgent}`);
|
|
for (const allow of group.allow || [])
|
|
lines.push(`Allow: ${allow}`);
|
|
for (const disallow of group.disallow || [])
|
|
lines.push(`Disallow: ${disallow}`);
|
|
for (const cleanParam of group.cleanParam || [])
|
|
lines.push(`Clean-param: ${cleanParam}`);
|
|
lines.push("");
|
|
}
|
|
for (const sitemap of sitemaps)
|
|
lines.push(`Sitemap: ${sitemap}`);
|
|
return lines.join("\n");
|
|
}
|
|
createDefu((obj, key, value) => {
|
|
if (Array.isArray(obj[key]) && Array.isArray(value))
|
|
obj[key] = Array.from(/* @__PURE__ */ new Set([...obj[key], ...value]));
|
|
return obj[key];
|
|
});
|
|
function normaliseRobotsRouteRule(config) {
|
|
let allow;
|
|
if (typeof config.robots === "boolean")
|
|
allow = config.robots;
|
|
else if (typeof config.robots === "object" && typeof config.robots.indexable !== "undefined")
|
|
allow = config.robots.indexable;
|
|
else if (typeof config.index !== "undefined")
|
|
allow = config.index;
|
|
let rule;
|
|
if (typeof config.robots === "object" && typeof config.robots.rule !== "undefined")
|
|
rule = config.robots.rule;
|
|
else if (typeof config.robots === "string")
|
|
rule = config.robots;
|
|
if (rule && !allow)
|
|
allow = rule !== "none" && !rule.includes("noindex");
|
|
if (typeof allow === "undefined" && typeof rule === "undefined")
|
|
return;
|
|
return {
|
|
allow,
|
|
rule
|
|
};
|
|
}
|
|
|
|
function withoutQuery$1(path) {
|
|
return path.split("?")[0];
|
|
}
|
|
function createNitroRouteRuleMatcher$1() {
|
|
const { nitro, app } = useRuntimeConfig();
|
|
const _routeRulesMatcher = toRouteMatcher(
|
|
createRouter({
|
|
routes: Object.fromEntries(
|
|
Object.entries(nitro?.routeRules || {}).map(([path, rules]) => [withoutTrailingSlash(path), rules])
|
|
)
|
|
})
|
|
);
|
|
return (path) => {
|
|
return defu$1({}, ..._routeRulesMatcher.matchAll(
|
|
// radix3 does not support trailing slashes
|
|
withoutBase(withoutTrailingSlash(withoutQuery$1(path)), app.baseURL)
|
|
).reverse());
|
|
};
|
|
}
|
|
|
|
function getSiteRobotConfig(e) {
|
|
const query = getQuery$1(e);
|
|
const hints = [];
|
|
const { groups, debug } = useRuntimeConfig(e)["nuxt-robots"];
|
|
let indexable = getSiteIndexable(e);
|
|
const queryIndexableEnabled = String(query.mockProductionEnv) === "true" || query.mockProductionEnv === "";
|
|
{
|
|
const { _context } = useSiteConfig(e, { debug: debug || true });
|
|
if (queryIndexableEnabled) {
|
|
indexable = true;
|
|
hints.push("You are mocking a production enviroment with ?mockProductionEnv query.");
|
|
} else if (!indexable && _context.indexable === "nuxt-robots:config") {
|
|
hints.push("You are blocking indexing with your Nuxt Robots config.");
|
|
} else if (!queryIndexableEnabled && !_context.indexable) {
|
|
hints.push(`Indexing is blocked in development. You can mock a production environment with ?mockProductionEnv query.`);
|
|
} else if (!indexable && !queryIndexableEnabled) {
|
|
hints.push(`Indexing is blocked by site config set by ${_context.indexable}.`);
|
|
} else if (indexable && !queryIndexableEnabled) {
|
|
hints.push(`Indexing is enabled from ${_context.indexable}.`);
|
|
}
|
|
}
|
|
if (groups.some((g) => g.userAgent.includes("*") && g.disallow.includes("/"))) {
|
|
indexable = false;
|
|
hints.push("You are blocking all user agents with a wildcard `Disallow /`.");
|
|
} else if (groups.some((g) => g.disallow.includes("/"))) {
|
|
hints.push("You are blocking specific user agents with `Disallow /`.");
|
|
}
|
|
return { indexable, hints };
|
|
}
|
|
|
|
function getPathRobotConfig(e, options) {
|
|
const { robotsDisabledValue, robotsEnabledValue, usingNuxtContent } = useRuntimeConfig()["nuxt-robots"];
|
|
if (!options?.skipSiteIndexable) {
|
|
if (!getSiteRobotConfig(e).indexable) {
|
|
return {
|
|
rule: robotsDisabledValue,
|
|
indexable: false
|
|
};
|
|
}
|
|
}
|
|
const path = options?.path || e.path;
|
|
let userAgent = options?.userAgent;
|
|
if (!userAgent) {
|
|
try {
|
|
userAgent = getRequestHeader(e, "User-Agent");
|
|
} catch {
|
|
}
|
|
}
|
|
const nitroApp = useNitroApp();
|
|
const groups = [
|
|
// run explicit user agent matching first
|
|
...nitroApp._robots.ctx.groups.filter((g) => {
|
|
if (userAgent) {
|
|
return g.userAgent.some((ua) => ua.toLowerCase().includes(userAgent.toLowerCase()));
|
|
}
|
|
return false;
|
|
}),
|
|
// run wildcard matches second
|
|
...nitroApp._robots.ctx.groups.filter((g) => g.userAgent.includes("*"))
|
|
];
|
|
for (const group of groups) {
|
|
if (!group._indexable) {
|
|
return {
|
|
indexable: false,
|
|
rule: robotsDisabledValue,
|
|
debug: {
|
|
source: "/robots.txt",
|
|
line: `Disallow: /`
|
|
}
|
|
};
|
|
}
|
|
const robotsTxtRule = matchPathToRule(path, group._rules);
|
|
if (robotsTxtRule) {
|
|
if (!robotsTxtRule.allow) {
|
|
return {
|
|
indexable: false,
|
|
rule: robotsDisabledValue,
|
|
debug: {
|
|
source: "/robots.txt",
|
|
line: `Disallow: ${robotsTxtRule.pattern}`
|
|
}
|
|
};
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (usingNuxtContent && nitroApp._robots?.nuxtContentUrls?.has(withoutTrailingSlash(path))) {
|
|
return {
|
|
indexable: false,
|
|
rule: robotsDisabledValue,
|
|
debug: {
|
|
source: "Nuxt Content"
|
|
}
|
|
};
|
|
}
|
|
nitroApp._robotsRuleMactcher = nitroApp._robotsRuleMactcher || createNitroRouteRuleMatcher$1();
|
|
const routeRules = normaliseRobotsRouteRule(nitroApp._robotsRuleMactcher(path));
|
|
if (routeRules && (routeRules.allow || routeRules.rule)) {
|
|
return {
|
|
indexable: routeRules.allow,
|
|
rule: routeRules.rule || (routeRules.allow ? robotsEnabledValue : robotsDisabledValue),
|
|
debug: {
|
|
source: "Route Rules"
|
|
}
|
|
};
|
|
}
|
|
return {
|
|
indexable: true,
|
|
rule: robotsEnabledValue
|
|
};
|
|
}
|
|
|
|
const _NiES8qY_0hBisDMb2AoYMTCDWgBFhKO8oXfn16F_7LM = defineNitroPlugin(async (nitro) => {
|
|
const { cleanCachedContents } = await Promise.resolve().then(function () { return storage; });
|
|
const storage$1 = useStorage();
|
|
const unwatch = await storage$1.watch(async (event, key) => {
|
|
if (key.startsWith("content:source")) {
|
|
cleanCachedContents();
|
|
}
|
|
});
|
|
nitro.hooks.hook("close", async () => {
|
|
if (typeof unwatch === "function") {
|
|
await unwatch();
|
|
}
|
|
});
|
|
});
|
|
|
|
const _ab8cASQgvalDCJBeUa0iDF2czIVwbckekekbYmKWVRQ = defineNitroPlugin(async (nitroApp) => {
|
|
nitroApp.hooks.hook("render:html", async (ctx, { event }) => {
|
|
const routeOptions = getRouteRules(event);
|
|
const isIsland = process.env.NUXT_COMPONENT_ISLANDS && event.path.startsWith("/__nuxt_island");
|
|
event.path;
|
|
const noSSR = event.context.nuxt?.noSSR || routeOptions.ssr === false && !isIsland || (false);
|
|
if (noSSR) {
|
|
const siteConfig = Object.fromEntries(
|
|
Object.entries(useSiteConfig(event)).map(([k, v]) => [k, toValue(v)])
|
|
);
|
|
ctx.body.push(`<script>window.__NUXT_SITE_CONFIG__=${devalue(siteConfig)}<\/script>`);
|
|
}
|
|
});
|
|
});
|
|
|
|
const logger$1 = createConsola({
|
|
defaults: {
|
|
tag: "@nuxt/sitemap"
|
|
}
|
|
});
|
|
const merger = createDefu((obj, key, value) => {
|
|
if (Array.isArray(obj[key]) && Array.isArray(value))
|
|
obj[key] = Array.from(/* @__PURE__ */ new Set([...obj[key], ...value]));
|
|
return obj[key];
|
|
});
|
|
function mergeOnKey(arr, key) {
|
|
const res = {};
|
|
arr.forEach((item) => {
|
|
const k = item[key];
|
|
res[k] = merger(item, res[k] || {});
|
|
});
|
|
return Object.values(res);
|
|
}
|
|
function splitForLocales(path, locales) {
|
|
const prefix = withLeadingSlash(path).split("/")[1];
|
|
if (locales.includes(prefix))
|
|
return [prefix, path.replace(`/${prefix}`, "")];
|
|
return [null, path];
|
|
}
|
|
const StringifiedRegExpPattern = /\/(.*?)\/([gimsuy]*)$/;
|
|
function normalizeRuntimeFilters(input) {
|
|
return (input || []).map((rule) => {
|
|
if (rule instanceof RegExp || typeof rule === "string")
|
|
return rule;
|
|
const match = rule.regex.match(StringifiedRegExpPattern);
|
|
if (match)
|
|
return new RegExp(match[1], match[2]);
|
|
return false;
|
|
}).filter(Boolean);
|
|
}
|
|
function createPathFilter(options = {}) {
|
|
const urlFilter = createFilter(options);
|
|
return (loc) => {
|
|
let path = loc;
|
|
try {
|
|
path = parseURL(loc).pathname;
|
|
} catch {
|
|
return false;
|
|
}
|
|
return urlFilter(path);
|
|
};
|
|
}
|
|
function createFilter(options = {}) {
|
|
const include = options.include || [];
|
|
const exclude = options.exclude || [];
|
|
if (include.length === 0 && exclude.length === 0)
|
|
return () => true;
|
|
return function(path) {
|
|
for (const v of [{ rules: exclude, result: false }, { rules: include, result: true }]) {
|
|
const regexRules = v.rules.filter((r) => r instanceof RegExp);
|
|
if (regexRules.some((r) => r.test(path)))
|
|
return v.result;
|
|
const stringRules = v.rules.filter((r) => typeof r === "string");
|
|
if (stringRules.length > 0) {
|
|
const routes = {};
|
|
for (const r of stringRules) {
|
|
if (r === path)
|
|
return v.result;
|
|
routes[r] = true;
|
|
}
|
|
const routeRulesMatcher = toRouteMatcher(createRouter({ routes, strictTrailingSlash: false }));
|
|
if (routeRulesMatcher.matchAll(path).length > 0)
|
|
return Boolean(v.result);
|
|
}
|
|
}
|
|
return include.length === 0;
|
|
};
|
|
}
|
|
|
|
function useSimpleSitemapRuntimeConfig(e) {
|
|
const clone = JSON.parse(JSON.stringify(useRuntimeConfig(e).sitemap));
|
|
for (const k in clone.sitemaps) {
|
|
const sitemap = clone.sitemaps[k];
|
|
sitemap.include = normalizeRuntimeFilters(sitemap.include);
|
|
sitemap.exclude = normalizeRuntimeFilters(sitemap.exclude);
|
|
clone.sitemaps[k] = sitemap;
|
|
}
|
|
return Object.freeze(clone);
|
|
}
|
|
|
|
const _KCkM2buKk3bJ90icJb94qM1GeExsanGphru95mbknRQ = defineNitroPlugin((nitroApp) => {
|
|
const { discoverImages, discoverVideos, isNuxtContentDocumentDriven } = useSimpleSitemapRuntimeConfig();
|
|
nitroApp.hooks.hook("content:file:afterParse", async (content) => {
|
|
const validExtensions = ["md", "mdx"];
|
|
if (content.sitemap === false || content._draft || !validExtensions.includes(content._extension) || content._partial || content.indexable === false || content.index === false)
|
|
return;
|
|
let images = [];
|
|
if (discoverImages) {
|
|
images = content.body?.children?.filter(
|
|
(c) => c.tag && c.props?.src && ["image", "img", "nuxtimg", "nuxt-img"].includes(c.tag.toLowerCase())
|
|
).map((i) => ({ loc: i.props.src })) || [];
|
|
}
|
|
let videos = [];
|
|
if (discoverVideos) {
|
|
videos = content.body?.children?.filter(
|
|
(c) => c.tag && c.props?.src && ["video"].includes(c.tag.toLowerCase())
|
|
).map((i) => ({ content_loc: i.props.src })) || [];
|
|
}
|
|
const sitemapConfig = typeof content.sitemap === "object" ? content.sitemap : {};
|
|
const lastmod = content.modifiedAt || content.updatedAt;
|
|
const defaults = {};
|
|
if (isNuxtContentDocumentDriven)
|
|
defaults.loc = content._path;
|
|
if (content.path)
|
|
defaults.loc = content.path;
|
|
if (images.length > 0)
|
|
defaults.images = images;
|
|
if (videos.length > 0)
|
|
defaults.videos = videos;
|
|
if (lastmod)
|
|
defaults.lastmod = lastmod;
|
|
const definition = defu$1(sitemapConfig, defaults);
|
|
if (!definition.loc) {
|
|
if (content.path && content.path && content.path.startsWith("/"))
|
|
definition.loc = content.path;
|
|
if (Object.keys(sitemapConfig).length > 0 && true)
|
|
console.warn(`[@nuxtjs/content] The @nuxt/content file \`${content._path}\` is missing a sitemap \`loc\`.`);
|
|
}
|
|
content.sitemap = definition;
|
|
if (!definition.loc)
|
|
delete content.sitemap;
|
|
return content;
|
|
});
|
|
});
|
|
|
|
const logger = createConsola({
|
|
defaults: { tag: "@nuxtjs/robots" }
|
|
});
|
|
|
|
async function resolveRobotsTxtContext(e, nitro = useNitroApp()) {
|
|
const { groups, sitemap: sitemaps } = useRuntimeConfig(e)["nuxt-robots"];
|
|
const generateRobotsTxtCtx = {
|
|
event: e,
|
|
context: e ? "robots.txt" : "init",
|
|
...JSON.parse(JSON.stringify({ groups, sitemaps }))
|
|
};
|
|
await nitro.hooks.callHook("robots:config", generateRobotsTxtCtx);
|
|
nitro._robots.ctx = generateRobotsTxtCtx;
|
|
return generateRobotsTxtCtx;
|
|
}
|
|
|
|
const _7SMrIYXukGtlsSfVIZ1Uj7eoIYs7a55Sl9RDgzohvQ = defineNitroPlugin(async (nitroApp) => {
|
|
const { usingNuxtContent, robotsDisabledValue } = useRuntimeConfig()["nuxt-robots"];
|
|
nitroApp._robots = {};
|
|
await resolveRobotsTxtContext(void 0, nitroApp);
|
|
const nuxtContentUrls = /* @__PURE__ */ new Set();
|
|
if (usingNuxtContent) {
|
|
let urls;
|
|
try {
|
|
urls = await (await nitroApp.localFetch("/__robots__/nuxt-content.json", {})).json();
|
|
} catch (e) {
|
|
logger.error("Failed to read robot rules from content files.", e);
|
|
}
|
|
if (urls && Array.isArray(urls) && urls.length) {
|
|
urls.forEach((url) => nuxtContentUrls.add(withoutTrailingSlash(url)));
|
|
}
|
|
}
|
|
if (nuxtContentUrls.size) {
|
|
nitroApp._robots.nuxtContentUrls = nuxtContentUrls;
|
|
}
|
|
});
|
|
|
|
const plugins = [
|
|
_Px1ClibNtxFQj_wR9GjpwPYcmv6EwgjdSGwWhS0BBxk,
|
|
_k4wlVec50Ea8cnXaqFijClJkLDTh1LE23pu07KSWvoA,
|
|
_NiES8qY_0hBisDMb2AoYMTCDWgBFhKO8oXfn16F_7LM,
|
|
_ab8cASQgvalDCJBeUa0iDF2czIVwbckekekbYmKWVRQ,
|
|
_KCkM2buKk3bJ90icJb94qM1GeExsanGphru95mbknRQ,
|
|
_7SMrIYXukGtlsSfVIZ1Uj7eoIYs7a55Sl9RDgzohvQ
|
|
];
|
|
|
|
const assets = {};
|
|
|
|
function readAsset (id) {
|
|
const serverDir = dirname$1(fileURLToPath(globalThis._importMeta_.url));
|
|
return promises.readFile(resolve$2(serverDir, assets[id].path))
|
|
}
|
|
|
|
const publicAssetBases = {"/_nuxt/builds/meta/":{"maxAge":31536000},"/_nuxt/builds/":{"maxAge":1}};
|
|
|
|
function isPublicAssetURL(id = '') {
|
|
if (assets[id]) {
|
|
return true
|
|
}
|
|
for (const base in publicAssetBases) {
|
|
if (id.startsWith(base)) { return true }
|
|
}
|
|
return false
|
|
}
|
|
|
|
function getAsset (id) {
|
|
return assets[id]
|
|
}
|
|
|
|
const METHODS = /* @__PURE__ */ new Set(["HEAD", "GET"]);
|
|
const EncodingMap = { gzip: ".gz", br: ".br" };
|
|
const _pThBIC = eventHandler((event) => {
|
|
if (event.method && !METHODS.has(event.method)) {
|
|
return;
|
|
}
|
|
let id = decodePath(
|
|
withLeadingSlash(withoutTrailingSlash(parseURL(event.path).pathname))
|
|
);
|
|
let asset;
|
|
const encodingHeader = String(
|
|
getRequestHeader(event, "accept-encoding") || ""
|
|
);
|
|
const encodings = [
|
|
...encodingHeader.split(",").map((e) => EncodingMap[e.trim()]).filter(Boolean).sort(),
|
|
""
|
|
];
|
|
if (encodings.length > 1) {
|
|
appendResponseHeader(event, "Vary", "Accept-Encoding");
|
|
}
|
|
for (const encoding of encodings) {
|
|
for (const _id of [id + encoding, joinURL(id, "index.html" + encoding)]) {
|
|
const _asset = getAsset(_id);
|
|
if (_asset) {
|
|
asset = _asset;
|
|
id = _id;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!asset) {
|
|
if (isPublicAssetURL(id)) {
|
|
removeResponseHeader(event, "Cache-Control");
|
|
throw createError({ statusCode: 404 });
|
|
}
|
|
return;
|
|
}
|
|
const ifNotMatch = getRequestHeader(event, "if-none-match") === asset.etag;
|
|
if (ifNotMatch) {
|
|
setResponseStatus(event, 304, "Not Modified");
|
|
return "";
|
|
}
|
|
const ifModifiedSinceH = getRequestHeader(event, "if-modified-since");
|
|
const mtimeDate = new Date(asset.mtime);
|
|
if (ifModifiedSinceH && asset.mtime && new Date(ifModifiedSinceH) >= mtimeDate) {
|
|
setResponseStatus(event, 304, "Not Modified");
|
|
return "";
|
|
}
|
|
if (asset.type && !getResponseHeader(event, "Content-Type")) {
|
|
setResponseHeader(event, "Content-Type", asset.type);
|
|
}
|
|
if (asset.etag && !getResponseHeader(event, "ETag")) {
|
|
setResponseHeader(event, "ETag", asset.etag);
|
|
}
|
|
if (asset.mtime && !getResponseHeader(event, "Last-Modified")) {
|
|
setResponseHeader(event, "Last-Modified", mtimeDate.toUTCString());
|
|
}
|
|
if (asset.encoding && !getResponseHeader(event, "Content-Encoding")) {
|
|
setResponseHeader(event, "Content-Encoding", asset.encoding);
|
|
}
|
|
if (asset.size > 0 && !getResponseHeader(event, "Content-Length")) {
|
|
setResponseHeader(event, "Content-Length", asset.size);
|
|
}
|
|
return readAsset(id);
|
|
});
|
|
|
|
const _3U292r = defineEventHandler(async (e) => {
|
|
if (e.context.siteConfig)
|
|
return;
|
|
const runtimeConfig = useRuntimeConfig(e);
|
|
const config = runtimeConfig["nuxt-site-config"];
|
|
const nitroApp = useNitroApp();
|
|
const siteConfig = createSiteConfigStack({
|
|
debug: config.debug
|
|
});
|
|
const appConfig = useAppConfig(e);
|
|
const nitroOrigin = useNitroOrigin(e);
|
|
e.context.siteConfigNitroOrigin = nitroOrigin;
|
|
{
|
|
siteConfig.push({
|
|
_context: "nitro:init",
|
|
_priority: -4,
|
|
url: nitroOrigin
|
|
});
|
|
}
|
|
siteConfig.push({
|
|
_context: "runtimeEnv",
|
|
_priority: 0,
|
|
...runtimeConfig.site || {},
|
|
...runtimeConfig.public.site || {},
|
|
// @ts-expect-error untyped
|
|
...envSiteConfig(globalThis._importMeta_.env)
|
|
// just in-case, shouldn't be needed
|
|
});
|
|
const buildStack = config.stack || [];
|
|
buildStack.forEach((c) => siteConfig.push(c));
|
|
if (appConfig.site) {
|
|
siteConfig.push({
|
|
_priority: -2,
|
|
_context: "app:config",
|
|
...appConfig.site
|
|
});
|
|
}
|
|
if (e.context._nitro.routeRules.site) {
|
|
siteConfig.push({
|
|
_context: "route-rules",
|
|
...e.context._nitro.routeRules.site
|
|
});
|
|
}
|
|
const ctx = { siteConfig, event: e };
|
|
await nitroApp.hooks.callHook("site-config:init", ctx);
|
|
e.context.siteConfig = ctx.siteConfig;
|
|
});
|
|
|
|
const _GlKRyj = defineEventHandler(async (e) => {
|
|
const siteConfig = useSiteConfig(e);
|
|
const nitroOrigin = useNitroOrigin(e);
|
|
const runtimeConfig = useRuntimeConfig(e);
|
|
const stack = e.context.siteConfig.stack;
|
|
setHeader(e, "Content-Type", "application/json");
|
|
return {
|
|
config: siteConfig,
|
|
stack,
|
|
nitroOrigin,
|
|
version: runtimeConfig["nuxt-site-config"].version
|
|
};
|
|
});
|
|
|
|
const get = (obj, path) => path.split(".").reduce((acc, part) => acc && acc[part], obj);
|
|
const _pick = (obj, condition) => Object.keys(obj).filter(condition).reduce((newObj, key) => Object.assign(newObj, { [key]: obj[key] }), {});
|
|
const omit = (keys) => (obj) => keys && keys.length ? _pick(obj, (key) => !keys.includes(key)) : obj;
|
|
const apply = (fn) => (data) => Array.isArray(data) ? data.map((item) => fn(item)) : fn(data);
|
|
const detectProperties = (keys) => {
|
|
const prefixes = [];
|
|
const properties = [];
|
|
for (const key of keys) {
|
|
if (["$", "_"].includes(key)) {
|
|
prefixes.push(key);
|
|
} else {
|
|
properties.push(key);
|
|
}
|
|
}
|
|
return { prefixes, properties };
|
|
};
|
|
const withoutKeys = (keys = []) => (obj) => {
|
|
if (keys.length === 0 || !obj) {
|
|
return obj;
|
|
}
|
|
const { prefixes, properties } = detectProperties(keys);
|
|
return _pick(obj, (key) => !properties.includes(key) && !prefixes.includes(key[0]));
|
|
};
|
|
const withKeys = (keys = []) => (obj) => {
|
|
if (keys.length === 0 || !obj) {
|
|
return obj;
|
|
}
|
|
const { prefixes, properties } = detectProperties(keys);
|
|
return _pick(obj, (key) => properties.includes(key) || prefixes.includes(key[0]));
|
|
};
|
|
const sortList = (data, params) => {
|
|
const comperable = new Intl.Collator(params.$locale, {
|
|
numeric: params.$numeric,
|
|
caseFirst: params.$caseFirst,
|
|
sensitivity: params.$sensitivity
|
|
});
|
|
const keys = Object.keys(params).filter((key) => !key.startsWith("$"));
|
|
for (const key of keys) {
|
|
data = data.sort((a, b) => {
|
|
const values = [get(a, key), get(b, key)].map((value) => {
|
|
if (value === null) {
|
|
return void 0;
|
|
}
|
|
if (value instanceof Date) {
|
|
return value.toISOString();
|
|
}
|
|
return value;
|
|
});
|
|
if (params[key] === -1) {
|
|
values.reverse();
|
|
}
|
|
return comperable.compare(values[0], values[1]);
|
|
});
|
|
}
|
|
return data;
|
|
};
|
|
const assertArray = (value, message = "Expected an array") => {
|
|
if (!Array.isArray(value)) {
|
|
throw new TypeError(message);
|
|
}
|
|
};
|
|
const ensureArray = (value) => {
|
|
return Array.isArray(value) ? value : [void 0, null].includes(value) ? [] : [value];
|
|
};
|
|
|
|
const arrayParams = ["sort", "where", "only", "without"];
|
|
function createQuery(fetcher, opts = {}) {
|
|
const queryParams = {};
|
|
for (const key of Object.keys(opts.initialParams || {})) {
|
|
queryParams[key] = arrayParams.includes(key) ? ensureArray(opts.initialParams[key]) : opts.initialParams[key];
|
|
}
|
|
const $set = (key, fn = (v) => v) => {
|
|
return (...values) => {
|
|
queryParams[key] = fn(...values);
|
|
return query;
|
|
};
|
|
};
|
|
const resolveResult = (result) => {
|
|
if (opts.legacy) {
|
|
if (result?.surround) {
|
|
return result.surround;
|
|
}
|
|
if (!result) {
|
|
return result;
|
|
}
|
|
if (result?.dirConfig) {
|
|
result.result = {
|
|
_path: result.dirConfig?._path,
|
|
...result.result,
|
|
_dir: result.dirConfig
|
|
};
|
|
}
|
|
return result?._path || Array.isArray(result) || !Object.prototype.hasOwnProperty.call(result, "result") ? result : result?.result;
|
|
}
|
|
return result;
|
|
};
|
|
const query = {
|
|
params: () => ({
|
|
...queryParams,
|
|
...queryParams.where ? { where: [...ensureArray(queryParams.where)] } : {},
|
|
...queryParams.sort ? { sort: [...ensureArray(queryParams.sort)] } : {}
|
|
}),
|
|
only: $set("only", ensureArray),
|
|
without: $set("without", ensureArray),
|
|
where: $set("where", (q) => [...ensureArray(queryParams.where), ...ensureArray(q)]),
|
|
sort: $set("sort", (sort) => [...ensureArray(queryParams.sort), ...ensureArray(sort)]),
|
|
limit: $set("limit", (v) => parseInt(String(v), 10)),
|
|
skip: $set("skip", (v) => parseInt(String(v), 10)),
|
|
// find
|
|
find: () => fetcher(query).then(resolveResult),
|
|
findOne: () => fetcher($set("first")(true)).then(resolveResult),
|
|
count: () => fetcher($set("count")(true)).then(resolveResult),
|
|
// locale
|
|
locale: (_locale) => query.where({ _locale }),
|
|
withSurround: $set("surround", (surroundQuery, options) => ({ query: surroundQuery, ...options })),
|
|
withDirConfig: () => $set("dirConfig")(true)
|
|
};
|
|
if (opts.legacy) {
|
|
query.findSurround = (surroundQuery, options) => {
|
|
return query.withSurround(surroundQuery, options).find().then(resolveResult);
|
|
};
|
|
return query;
|
|
}
|
|
return query;
|
|
}
|
|
|
|
const defineTransformer = (transformer) => {
|
|
return transformer;
|
|
};
|
|
|
|
function createTokenizer(parser, initialize, from) {
|
|
let point = Object.assign(
|
|
{
|
|
line: 1,
|
|
column: 1,
|
|
offset: 0
|
|
},
|
|
{
|
|
_index: 0,
|
|
_bufferIndex: -1
|
|
}
|
|
);
|
|
const columnStart = {};
|
|
const resolveAllConstructs = [];
|
|
let chunks = [];
|
|
let stack = [];
|
|
const effects = {
|
|
consume,
|
|
enter,
|
|
exit,
|
|
attempt: constructFactory(onsuccessfulconstruct),
|
|
check: constructFactory(onsuccessfulcheck),
|
|
interrupt: constructFactory(onsuccessfulcheck, {
|
|
interrupt: true
|
|
})
|
|
};
|
|
const context = {
|
|
previous: null,
|
|
code: null,
|
|
containerState: {},
|
|
events: [],
|
|
parser,
|
|
sliceStream,
|
|
sliceSerialize,
|
|
now,
|
|
defineSkip,
|
|
write
|
|
};
|
|
let state = initialize.tokenize.call(context, effects);
|
|
if (initialize.resolveAll) {
|
|
resolveAllConstructs.push(initialize);
|
|
}
|
|
return context;
|
|
function write(slice) {
|
|
chunks = push(chunks, slice);
|
|
main();
|
|
if (chunks[chunks.length - 1] !== null) {
|
|
return [];
|
|
}
|
|
addResult(initialize, 0);
|
|
context.events = resolveAll(resolveAllConstructs, context.events, context);
|
|
return context.events;
|
|
}
|
|
function sliceSerialize(token, expandTabs) {
|
|
return serializeChunks(sliceStream(token), expandTabs);
|
|
}
|
|
function sliceStream(token) {
|
|
return sliceChunks(chunks, token);
|
|
}
|
|
function now() {
|
|
return Object.assign({}, point);
|
|
}
|
|
function defineSkip(value) {
|
|
columnStart[value.line] = value.column;
|
|
accountForPotentialSkip();
|
|
}
|
|
function main() {
|
|
let chunkIndex;
|
|
while (point._index < chunks.length) {
|
|
const chunk = chunks[point._index];
|
|
if (typeof chunk === "string") {
|
|
chunkIndex = point._index;
|
|
if (point._bufferIndex < 0) {
|
|
point._bufferIndex = 0;
|
|
}
|
|
while (point._index === chunkIndex && point._bufferIndex < chunk.length) {
|
|
go(chunk.charCodeAt(point._bufferIndex));
|
|
}
|
|
} else {
|
|
go(chunk);
|
|
}
|
|
}
|
|
}
|
|
function go(code) {
|
|
state = state(code);
|
|
}
|
|
function consume(code) {
|
|
if (markdownLineEnding(code)) {
|
|
point.line++;
|
|
point.column = 1;
|
|
point.offset += code === -3 ? 2 : 1;
|
|
accountForPotentialSkip();
|
|
} else if (code !== -1) {
|
|
point.column++;
|
|
point.offset++;
|
|
}
|
|
if (point._bufferIndex < 0) {
|
|
point._index++;
|
|
} else {
|
|
point._bufferIndex++;
|
|
if (point._bufferIndex === chunks[point._index].length) {
|
|
point._bufferIndex = -1;
|
|
point._index++;
|
|
}
|
|
}
|
|
context.previous = code;
|
|
}
|
|
function enter(type, fields) {
|
|
const token = fields || {};
|
|
token.type = type;
|
|
token.start = now();
|
|
context.events.push(["enter", token, context]);
|
|
stack.push(token);
|
|
return token;
|
|
}
|
|
function exit(type) {
|
|
const token = stack.pop();
|
|
token.end = now();
|
|
context.events.push(["exit", token, context]);
|
|
return token;
|
|
}
|
|
function onsuccessfulconstruct(construct, info) {
|
|
addResult(construct, info.from);
|
|
}
|
|
function onsuccessfulcheck(_, info) {
|
|
info.restore();
|
|
}
|
|
function constructFactory(onreturn, fields) {
|
|
return hook;
|
|
function hook(constructs, returnState, bogusState) {
|
|
let listOfConstructs;
|
|
let constructIndex;
|
|
let currentConstruct;
|
|
let info;
|
|
return Array.isArray(constructs) ? (
|
|
/* c8 ignore next 1 */
|
|
handleListOfConstructs(constructs)
|
|
) : "tokenize" in constructs ? handleListOfConstructs([constructs]) : handleMapOfConstructs(constructs);
|
|
function handleMapOfConstructs(map) {
|
|
return start;
|
|
function start(code) {
|
|
const def = code !== null && map[code];
|
|
const all = code !== null && map.null;
|
|
const list = [
|
|
// To do: add more extension tests.
|
|
/* c8 ignore next 2 */
|
|
...Array.isArray(def) ? def : def ? [def] : [],
|
|
...Array.isArray(all) ? all : all ? [all] : []
|
|
];
|
|
return handleListOfConstructs(list)(code);
|
|
}
|
|
}
|
|
function handleListOfConstructs(list) {
|
|
listOfConstructs = list;
|
|
constructIndex = 0;
|
|
if (list.length === 0) {
|
|
return bogusState;
|
|
}
|
|
return handleConstruct(list[constructIndex]);
|
|
}
|
|
function handleConstruct(construct) {
|
|
return start;
|
|
function start(code) {
|
|
info = store();
|
|
currentConstruct = construct;
|
|
if (!construct.partial) {
|
|
context.currentConstruct = construct;
|
|
}
|
|
if (construct.name && context.parser.constructs.disable.null.includes(construct.name)) {
|
|
return nok();
|
|
}
|
|
return construct.tokenize.call(
|
|
// If we do have fields, create an object w/ `context` as its
|
|
// prototype.
|
|
// This allows a “live binding”, which is needed for `interrupt`.
|
|
fields ? Object.assign(Object.create(context), fields) : context,
|
|
effects,
|
|
ok,
|
|
nok
|
|
)(code);
|
|
}
|
|
}
|
|
function ok(code) {
|
|
onreturn(currentConstruct, info);
|
|
return returnState;
|
|
}
|
|
function nok(code) {
|
|
info.restore();
|
|
if (++constructIndex < listOfConstructs.length) {
|
|
return handleConstruct(listOfConstructs[constructIndex]);
|
|
}
|
|
return bogusState;
|
|
}
|
|
}
|
|
}
|
|
function addResult(construct, from2) {
|
|
if (construct.resolveAll && !resolveAllConstructs.includes(construct)) {
|
|
resolveAllConstructs.push(construct);
|
|
}
|
|
if (construct.resolve) {
|
|
splice(
|
|
context.events,
|
|
from2,
|
|
context.events.length - from2,
|
|
construct.resolve(context.events.slice(from2), context)
|
|
);
|
|
}
|
|
if (construct.resolveTo) {
|
|
context.events = construct.resolveTo(context.events, context);
|
|
}
|
|
}
|
|
function store() {
|
|
const startPoint = now();
|
|
const startPrevious = context.previous;
|
|
const startCurrentConstruct = context.currentConstruct;
|
|
const startEventsIndex = context.events.length;
|
|
const startStack = Array.from(stack);
|
|
return {
|
|
restore,
|
|
from: startEventsIndex
|
|
};
|
|
function restore() {
|
|
point = startPoint;
|
|
context.previous = startPrevious;
|
|
context.currentConstruct = startCurrentConstruct;
|
|
context.events.length = startEventsIndex;
|
|
stack = startStack;
|
|
accountForPotentialSkip();
|
|
}
|
|
}
|
|
function accountForPotentialSkip() {
|
|
if (point.line in columnStart && point.column < 2) {
|
|
point.column = columnStart[point.line];
|
|
point.offset += columnStart[point.line] - 1;
|
|
}
|
|
}
|
|
}
|
|
function sliceChunks(chunks, token) {
|
|
const startIndex = token.start._index;
|
|
const startBufferIndex = token.start._bufferIndex;
|
|
const endIndex = token.end._index;
|
|
const endBufferIndex = token.end._bufferIndex;
|
|
let view;
|
|
if (startIndex === endIndex) {
|
|
view = [chunks[startIndex].slice(startBufferIndex, endBufferIndex)];
|
|
} else {
|
|
view = chunks.slice(startIndex, endIndex);
|
|
if (startBufferIndex > -1) {
|
|
view[0] = view[0].slice(startBufferIndex);
|
|
}
|
|
if (endBufferIndex > 0) {
|
|
view.push(chunks[endIndex].slice(0, endBufferIndex));
|
|
}
|
|
}
|
|
return view;
|
|
}
|
|
function serializeChunks(chunks, expandTabs) {
|
|
let index = -1;
|
|
const result = [];
|
|
let atTab;
|
|
while (++index < chunks.length) {
|
|
const chunk = chunks[index];
|
|
let value;
|
|
if (typeof chunk === "string") {
|
|
value = chunk;
|
|
} else
|
|
switch (chunk) {
|
|
case -5: {
|
|
value = "\r";
|
|
break;
|
|
}
|
|
case -4: {
|
|
value = "\n";
|
|
break;
|
|
}
|
|
case -3: {
|
|
value = "\r\n";
|
|
break;
|
|
}
|
|
case -2: {
|
|
value = expandTabs ? " " : " ";
|
|
break;
|
|
}
|
|
case -1: {
|
|
if (!expandTabs && atTab) continue;
|
|
value = " ";
|
|
break;
|
|
}
|
|
default: {
|
|
value = String.fromCharCode(chunk);
|
|
}
|
|
}
|
|
atTab = chunk === -2;
|
|
result.push(value);
|
|
}
|
|
return result.join("");
|
|
}
|
|
|
|
function initializeDocument(effects) {
|
|
const self = this;
|
|
const delimiter = (this.parser.delimiter || ",").charCodeAt(0);
|
|
return enterRow;
|
|
function enterRow(code) {
|
|
return effects.attempt(
|
|
{ tokenize: attemptLastLine },
|
|
(code2) => {
|
|
effects.consume(code2);
|
|
return enterRow;
|
|
},
|
|
(code2) => {
|
|
effects.enter("row");
|
|
return enterColumn(code2);
|
|
}
|
|
)(code);
|
|
}
|
|
function enterColumn(code) {
|
|
effects.enter("column");
|
|
return content(code);
|
|
}
|
|
function content(code) {
|
|
if (code === null) {
|
|
effects.exit("column");
|
|
effects.exit("row");
|
|
effects.consume(code);
|
|
return content;
|
|
}
|
|
if (code === 34) {
|
|
return quotedData(code);
|
|
}
|
|
if (code === delimiter) {
|
|
if (self.previous === delimiter || markdownLineEnding(self.previous) || self.previous === null) {
|
|
effects.enter("data");
|
|
effects.exit("data");
|
|
}
|
|
effects.exit("column");
|
|
effects.enter("columnSeparator");
|
|
effects.consume(code);
|
|
effects.exit("columnSeparator");
|
|
effects.enter("column");
|
|
return content;
|
|
}
|
|
if (markdownLineEnding(code)) {
|
|
effects.exit("column");
|
|
effects.enter("newline");
|
|
effects.consume(code);
|
|
effects.exit("newline");
|
|
effects.exit("row");
|
|
return enterRow;
|
|
}
|
|
return data(code);
|
|
}
|
|
function data(code) {
|
|
effects.enter("data");
|
|
return dataChunk(code);
|
|
}
|
|
function dataChunk(code) {
|
|
if (code === null || markdownLineEnding(code) || code === delimiter) {
|
|
effects.exit("data");
|
|
return content(code);
|
|
}
|
|
if (code === 92) {
|
|
return escapeCharacter(code);
|
|
}
|
|
effects.consume(code);
|
|
return dataChunk;
|
|
}
|
|
function escapeCharacter(code) {
|
|
effects.consume(code);
|
|
return function(code2) {
|
|
effects.consume(code2);
|
|
return content;
|
|
};
|
|
}
|
|
function quotedData(code) {
|
|
effects.enter("quotedData");
|
|
effects.enter("quotedDataChunk");
|
|
effects.consume(code);
|
|
return quotedDataChunk;
|
|
}
|
|
function quotedDataChunk(code) {
|
|
if (code === 92) {
|
|
return escapeCharacter(code);
|
|
}
|
|
if (code === 34) {
|
|
return effects.attempt(
|
|
{ tokenize: attemptDoubleQuote },
|
|
(code2) => {
|
|
effects.exit("quotedDataChunk");
|
|
effects.enter("quotedDataChunk");
|
|
return quotedDataChunk(code2);
|
|
},
|
|
(code2) => {
|
|
effects.consume(code2);
|
|
effects.exit("quotedDataChunk");
|
|
effects.exit("quotedData");
|
|
return content;
|
|
}
|
|
)(code);
|
|
}
|
|
effects.consume(code);
|
|
return quotedDataChunk;
|
|
}
|
|
}
|
|
function attemptDoubleQuote(effects, ok, nok) {
|
|
return startSequence;
|
|
function startSequence(code) {
|
|
if (code !== 34) {
|
|
return nok(code);
|
|
}
|
|
effects.enter("quoteFence");
|
|
effects.consume(code);
|
|
return sequence;
|
|
}
|
|
function sequence(code) {
|
|
if (code !== 34) {
|
|
return nok(code);
|
|
}
|
|
effects.consume(code);
|
|
effects.exit("quoteFence");
|
|
return (code2) => ok(code2);
|
|
}
|
|
}
|
|
function attemptLastLine(effects, ok, nok) {
|
|
return enterLine;
|
|
function enterLine(code) {
|
|
if (!markdownSpace(code) && code !== null) {
|
|
return nok(code);
|
|
}
|
|
effects.enter("emptyLine");
|
|
return continueLine(code);
|
|
}
|
|
function continueLine(code) {
|
|
if (markdownSpace(code)) {
|
|
effects.consume(code);
|
|
return continueLine;
|
|
}
|
|
if (code === null) {
|
|
effects.exit("emptyLine");
|
|
return ok(code);
|
|
}
|
|
return nok(code);
|
|
}
|
|
}
|
|
const parse = (options) => {
|
|
return createTokenizer(
|
|
{ ...options },
|
|
{ tokenize: initializeDocument });
|
|
};
|
|
|
|
const own = {}.hasOwnProperty;
|
|
const initialPoint = {
|
|
line: 1,
|
|
column: 1,
|
|
offset: 0
|
|
};
|
|
const fromCSV = function(value, encoding, options) {
|
|
if (typeof encoding !== "string") {
|
|
options = encoding;
|
|
encoding = void 0;
|
|
}
|
|
return compiler()(
|
|
postprocess(
|
|
parse(options).write(preprocess()(value, encoding, true))
|
|
)
|
|
);
|
|
};
|
|
function compiler() {
|
|
const config = {
|
|
enter: {
|
|
column: opener(openColumn),
|
|
row: opener(openRow),
|
|
data: onenterdata,
|
|
quotedData: onenterdata
|
|
},
|
|
exit: {
|
|
row: closer(),
|
|
column: closer(),
|
|
data: onexitdata,
|
|
quotedData: onexitQuotedData
|
|
}
|
|
};
|
|
return compile;
|
|
function compile(events) {
|
|
const tree = {
|
|
type: "root",
|
|
children: []
|
|
};
|
|
const stack = [tree];
|
|
const tokenStack = [];
|
|
const context = {
|
|
stack,
|
|
tokenStack,
|
|
config,
|
|
enter,
|
|
exit,
|
|
resume
|
|
};
|
|
let index = -1;
|
|
while (++index < events.length) {
|
|
const handler = config[events[index][0]];
|
|
if (own.call(handler, events[index][1].type)) {
|
|
handler[events[index][1].type].call(
|
|
Object.assign(
|
|
{
|
|
sliceSerialize: events[index][2].sliceSerialize
|
|
},
|
|
context
|
|
),
|
|
events[index][1]
|
|
);
|
|
}
|
|
}
|
|
if (tokenStack.length > 0) {
|
|
const tail = tokenStack[tokenStack.length - 1];
|
|
const handler = tail[1] || defaultOnError;
|
|
handler.call(context, void 0, tail[0]);
|
|
}
|
|
tree.position = {
|
|
start: point(
|
|
events.length > 0 ? events[0][1].start : initialPoint
|
|
),
|
|
end: point(
|
|
events.length > 0 ? events[events.length - 2][1].end : initialPoint
|
|
)
|
|
};
|
|
return tree;
|
|
}
|
|
function point(d) {
|
|
return {
|
|
line: d.line,
|
|
column: d.column,
|
|
offset: d.offset
|
|
};
|
|
}
|
|
function opener(create, and) {
|
|
return open;
|
|
function open(token) {
|
|
enter.call(this, create(token), token);
|
|
}
|
|
}
|
|
function enter(node, token, errorHandler) {
|
|
const parent = this.stack[this.stack.length - 1];
|
|
parent.children.push(node);
|
|
this.stack.push(node);
|
|
this.tokenStack.push([token, errorHandler]);
|
|
node.position = {
|
|
start: point(token.start)
|
|
};
|
|
return node;
|
|
}
|
|
function closer(and) {
|
|
return close;
|
|
function close(token) {
|
|
exit.call(this, token);
|
|
}
|
|
}
|
|
function exit(token, onExitError) {
|
|
const node = this.stack.pop();
|
|
const open = this.tokenStack.pop();
|
|
if (!open) {
|
|
throw new Error(
|
|
"Cannot close `" + token.type + "` (" + stringifyPosition({
|
|
start: token.start,
|
|
end: token.end
|
|
}) + "): it\u2019s not open"
|
|
);
|
|
} else if (open[0].type !== token.type) {
|
|
if (onExitError) {
|
|
onExitError.call(this, token, open[0]);
|
|
} else {
|
|
const handler = open[1] || defaultOnError;
|
|
handler.call(this, token, open[0]);
|
|
}
|
|
}
|
|
node.position.end = point(token.end);
|
|
return node;
|
|
}
|
|
function resume() {
|
|
return toString$1(this.stack.pop());
|
|
}
|
|
function onenterdata(token) {
|
|
const parent = this.stack[this.stack.length - 1];
|
|
let tail = parent.children[parent.children.length - 1];
|
|
if (!tail || tail.type !== "text") {
|
|
tail = text();
|
|
tail.position = {
|
|
start: point(token.start)
|
|
};
|
|
parent.children.push(tail);
|
|
}
|
|
this.stack.push(tail);
|
|
}
|
|
function onexitdata(token) {
|
|
const tail = this.stack.pop();
|
|
tail.value += this.sliceSerialize(token).trim().replace(/""/g, '"');
|
|
tail.position.end = point(token.end);
|
|
}
|
|
function onexitQuotedData(token) {
|
|
const tail = this.stack.pop();
|
|
const value = this.sliceSerialize(token);
|
|
tail.value += this.sliceSerialize(token).trim().substring(1, value.length - 1).replace(/""/g, '"');
|
|
tail.position.end = point(token.end);
|
|
}
|
|
function text() {
|
|
return {
|
|
type: "text",
|
|
value: ""
|
|
};
|
|
}
|
|
function openColumn() {
|
|
return {
|
|
type: "column",
|
|
children: []
|
|
};
|
|
}
|
|
function openRow() {
|
|
return {
|
|
type: "row",
|
|
children: []
|
|
};
|
|
}
|
|
}
|
|
function defaultOnError(left, right) {
|
|
if (left) {
|
|
throw new Error(
|
|
"Cannot close `" + left.type + "` (" + stringifyPosition({
|
|
start: left.start,
|
|
end: left.end
|
|
}) + "): a different token (`" + right.type + "`, " + stringifyPosition({
|
|
start: right.start,
|
|
end: right.end
|
|
}) + ") is open"
|
|
);
|
|
} else {
|
|
throw new Error(
|
|
"Cannot close document, a token (`" + right.type + "`, " + stringifyPosition({
|
|
start: right.start,
|
|
end: right.end
|
|
}) + ") is still open"
|
|
);
|
|
}
|
|
}
|
|
|
|
function csvParse(options) {
|
|
const parser = (doc) => {
|
|
return fromCSV(doc, options);
|
|
};
|
|
Object.assign(this, { Parser: parser });
|
|
const toJsonObject = (tree) => {
|
|
const [header, ...rows] = tree.children;
|
|
const columns = header.children.map((col) => col.children[0].value);
|
|
const data = rows.map((row) => {
|
|
return row.children.reduce((acc, col, i) => {
|
|
acc[String(columns[i])] = col.children[0]?.value;
|
|
return acc;
|
|
}, {});
|
|
});
|
|
return data;
|
|
};
|
|
const toJsonArray = (tree) => {
|
|
const data = tree.children.map((row) => {
|
|
return row.children.map((col) => col.children[0]?.value);
|
|
});
|
|
return data;
|
|
};
|
|
const compiler = (doc) => {
|
|
if (options.json) {
|
|
return toJsonObject(doc);
|
|
}
|
|
return toJsonArray(doc);
|
|
};
|
|
Object.assign(this, { Compiler: compiler });
|
|
}
|
|
const csv = defineTransformer({
|
|
name: "csv",
|
|
extensions: [".csv"],
|
|
parse: async (_id, content, options = {}) => {
|
|
const stream = unified().use(csvParse, {
|
|
delimiter: ",",
|
|
json: true,
|
|
...options
|
|
});
|
|
const { result } = await stream.process(content);
|
|
return {
|
|
_id,
|
|
_type: "csv",
|
|
body: result
|
|
};
|
|
}
|
|
});
|
|
|
|
const SEMVER_REGEX = /^(\d+)(\.\d+)*(\.x)?$/;
|
|
const describeId = (id) => {
|
|
const [_source, ...parts] = id.split(":");
|
|
const [, basename, _extension] = parts[parts.length - 1]?.match(/(.*)\.([^.]+)$/) || [];
|
|
if (basename) {
|
|
parts[parts.length - 1] = basename;
|
|
}
|
|
const _path = (parts || []).join("/");
|
|
return {
|
|
_source,
|
|
_path,
|
|
_extension,
|
|
_file: _extension ? `${_path}.${_extension}` : _path,
|
|
_basename: basename || ""
|
|
};
|
|
};
|
|
const pathMeta = defineTransformer({
|
|
name: "path-meta",
|
|
extensions: [".*"],
|
|
transform(content, options = {}) {
|
|
const { locales = [], defaultLocale = "en", respectPathCase = false } = options;
|
|
const { _source, _file, _path, _extension, _basename } = describeId(content._id);
|
|
const parts = _path.split("/");
|
|
const _locale = locales.includes(parts[0]) ? parts.shift() : defaultLocale;
|
|
const filePath = generatePath(parts.join("/"), { respectPathCase });
|
|
return {
|
|
_path: filePath,
|
|
_dir: filePath.split("/").slice(-2)[0],
|
|
_draft: content._draft || content.draft || isDraft(_path),
|
|
_partial: isPartial(_path),
|
|
_locale,
|
|
...content,
|
|
// TODO: move title to Markdown parser
|
|
title: content.title || generateTitle(refineUrlPart(_basename)),
|
|
_source,
|
|
_file,
|
|
_stem: _path,
|
|
_extension
|
|
};
|
|
}
|
|
});
|
|
const isDraft = (path) => !!path.match(/\.draft(\/|\.|$)/);
|
|
const isPartial = (path) => path.split(/[:/]/).some((part) => part.match(/^_.*/));
|
|
const generatePath = (path, { forceLeadingSlash = true, respectPathCase = false } = {}) => {
|
|
path = path.split("/").map((part) => slugify(refineUrlPart(part), { lower: !respectPathCase })).join("/");
|
|
return forceLeadingSlash ? withLeadingSlash(withoutTrailingSlash(path)) : path;
|
|
};
|
|
const generateTitle = (path) => path.split(/[\s-]/g).map(pascalCase).join(" ");
|
|
function refineUrlPart(name) {
|
|
name = name.split(/[/:]/).pop();
|
|
if (SEMVER_REGEX.test(name)) {
|
|
return name;
|
|
}
|
|
return name.replace(/(\d+\.)?(.*)/, "$2").replace(/^index(\.draft)?$/, "").replace(/\.draft$/, "");
|
|
}
|
|
|
|
const markdown = defineTransformer({
|
|
name: "markdown",
|
|
extensions: [".md"],
|
|
parse: async (_id, content, options = {}) => {
|
|
const config = { ...options };
|
|
config.rehypePlugins = await importPlugins(config.rehypePlugins);
|
|
config.remarkPlugins = await importPlugins(config.remarkPlugins);
|
|
const highlightOptions = options.highlight ? {
|
|
...options.highlight,
|
|
// Pass only when it's an function. String values are handled by `@nuxtjs/mdc`
|
|
highlighter: typeof options.highlight?.highlighter === "function" ? options.highlight.highlighter : void 0
|
|
} : void 0;
|
|
const parsed = await parseMarkdown(content, {
|
|
...config,
|
|
highlight: highlightOptions,
|
|
remark: {
|
|
plugins: config.remarkPlugins
|
|
},
|
|
rehype: {
|
|
options: {
|
|
handlers: {
|
|
link
|
|
}
|
|
},
|
|
plugins: config.rehypePlugins
|
|
},
|
|
toc: config.toc
|
|
});
|
|
return {
|
|
...parsed.data,
|
|
excerpt: parsed.excerpt,
|
|
body: {
|
|
...parsed.body,
|
|
toc: parsed.toc
|
|
},
|
|
_type: "markdown",
|
|
_id
|
|
};
|
|
}
|
|
});
|
|
async function importPlugins(plugins = {}) {
|
|
const resolvedPlugins = {};
|
|
for (const [name, plugin] of Object.entries(plugins)) {
|
|
if (plugin) {
|
|
resolvedPlugins[name] = {
|
|
instance: plugin.instance || await import(
|
|
/* @vite-ignore */
|
|
name
|
|
).then((m) => m.default || m),
|
|
options: plugin
|
|
};
|
|
} else {
|
|
resolvedPlugins[name] = false;
|
|
}
|
|
}
|
|
return resolvedPlugins;
|
|
}
|
|
function link(state, node) {
|
|
const properties = {
|
|
...node.attributes || {},
|
|
href: normalizeUri(normalizeLink(node.url))
|
|
};
|
|
if (node.title !== null && node.title !== void 0) {
|
|
properties.title = node.title;
|
|
}
|
|
const result = {
|
|
type: "element",
|
|
tagName: "a",
|
|
properties,
|
|
children: state.all(node)
|
|
};
|
|
state.patch(node, result);
|
|
return state.applyData(node, result);
|
|
}
|
|
function normalizeLink(link2) {
|
|
const match = link2.match(/#.+$/);
|
|
const hash = match ? match[0] : "";
|
|
if (link2.replace(/#.+$/, "").endsWith(".md") && (isRelative(link2) || !/^https?/.test(link2) && !link2.startsWith("/"))) {
|
|
return generatePath(link2.replace(".md" + hash, ""), { forceLeadingSlash: false }) + hash;
|
|
} else {
|
|
return link2;
|
|
}
|
|
}
|
|
|
|
const yaml = defineTransformer({
|
|
name: "Yaml",
|
|
extensions: [".yml", ".yaml"],
|
|
parse: (_id, content) => {
|
|
const { data } = parseFrontMatter(`---
|
|
${content}
|
|
---`);
|
|
let parsed = data;
|
|
if (Array.isArray(data)) {
|
|
console.warn(`YAML array is not supported in ${_id}, moving the array into the \`body\` key`);
|
|
parsed = { body: data };
|
|
}
|
|
return {
|
|
...parsed,
|
|
_id,
|
|
_type: "yaml"
|
|
};
|
|
}
|
|
});
|
|
|
|
const json = defineTransformer({
|
|
name: "Json",
|
|
extensions: [".json", ".json5"],
|
|
parse: async (_id, content) => {
|
|
let parsed;
|
|
if (typeof content === "string") {
|
|
if (_id.endsWith("json5")) {
|
|
parsed = (await import('file://D:/claude-project/web7-published/node_modules/json5/lib/index.js').then((m) => m.default || m)).parse(content);
|
|
} else if (_id.endsWith("json")) {
|
|
parsed = destr$1(content);
|
|
}
|
|
} else {
|
|
parsed = content;
|
|
}
|
|
if (Array.isArray(parsed)) {
|
|
console.warn(`JSON array is not supported in ${_id}, moving the array into the \`body\` key`);
|
|
parsed = {
|
|
body: parsed
|
|
};
|
|
}
|
|
return {
|
|
...parsed,
|
|
_id,
|
|
_type: "json"
|
|
};
|
|
}
|
|
});
|
|
|
|
const TRANSFORMERS = [
|
|
csv,
|
|
markdown,
|
|
json,
|
|
yaml,
|
|
pathMeta
|
|
];
|
|
function getParser(ext, additionalTransformers = []) {
|
|
let parser = additionalTransformers.find((p) => ext.match(new RegExp(p.extensions.join("|"), "i")) && p.parse);
|
|
if (!parser) {
|
|
parser = TRANSFORMERS.find((p) => ext.match(new RegExp(p.extensions.join("|"), "i")) && p.parse);
|
|
}
|
|
return parser;
|
|
}
|
|
function getTransformers(ext, additionalTransformers = []) {
|
|
return [
|
|
...additionalTransformers.filter((p) => ext.match(new RegExp(p.extensions.join("|"), "i")) && p.transform),
|
|
...TRANSFORMERS.filter((p) => ext.match(new RegExp(p.extensions.join("|"), "i")) && p.transform)
|
|
];
|
|
}
|
|
async function transformContent(id, content, options = {}) {
|
|
const { transformers = [] } = options;
|
|
const file = { _id: id, body: content };
|
|
const ext = extname(id);
|
|
const parser = getParser(ext, transformers);
|
|
if (!parser) {
|
|
console.warn(`${ext} files are not supported, "${id}" falling back to raw content`);
|
|
return file;
|
|
}
|
|
const parserOptions = options[camelCase(parser.name)] || {};
|
|
const parsed = await parser.parse(file._id, file.body, parserOptions);
|
|
const matchedTransformers = getTransformers(ext, transformers);
|
|
const result = await matchedTransformers.reduce(async (prev, cur) => {
|
|
const next = await prev || parsed;
|
|
const transformOptions = options[camelCase(cur.name)];
|
|
if (transformOptions === false) {
|
|
return next;
|
|
}
|
|
return cur.transform(next, transformOptions || {});
|
|
}, Promise.resolve(parsed));
|
|
return result;
|
|
}
|
|
|
|
function makeIgnored(ignores) {
|
|
const rxAll = ["/\\.", "/-", ...ignores.filter((p) => p)].map((p) => new RegExp(p));
|
|
return function isIgnored(key) {
|
|
const path = "/" + key.replace(/:/g, "/");
|
|
return rxAll.some((rx) => rx.test(path));
|
|
};
|
|
}
|
|
|
|
function createMatch(opts = {}) {
|
|
const operators = createOperators(match, opts.operators);
|
|
function match(item, conditions) {
|
|
if (typeof conditions !== "object" || conditions instanceof RegExp) {
|
|
return operators.$eq(item, conditions);
|
|
}
|
|
return Object.keys(conditions || {}).every((key) => {
|
|
const condition = conditions[key];
|
|
if (key.startsWith("$") && operators[key]) {
|
|
const fn = operators[key];
|
|
return typeof fn === "function" ? fn(item, condition) : false;
|
|
}
|
|
return match(get(item, key), condition);
|
|
});
|
|
}
|
|
return match;
|
|
}
|
|
function createOperators(match, operators = {}) {
|
|
return {
|
|
$match: (item, condition) => match(item, condition),
|
|
/**
|
|
* Match if item equals condition
|
|
**/
|
|
$eq: (item, condition) => condition instanceof RegExp ? condition.test(item) : item === condition,
|
|
/**
|
|
* Match if item not equals condition
|
|
**/
|
|
$ne: (item, condition) => condition instanceof RegExp ? !condition.test(item) : item !== condition,
|
|
/**
|
|
* Match is condition is false
|
|
**/
|
|
$not: (item, condition) => !match(item, condition),
|
|
/**
|
|
* Match only if all of nested conditions are true
|
|
**/
|
|
$and: (item, condition) => {
|
|
assertArray(condition, "$and requires an array as condition");
|
|
return condition.every((cond) => match(item, cond));
|
|
},
|
|
/**
|
|
* Match if any of nested conditions is true
|
|
**/
|
|
$or: (item, condition) => {
|
|
assertArray(condition, "$or requires an array as condition");
|
|
return condition.some((cond) => match(item, cond));
|
|
},
|
|
/**
|
|
* Match if item is in condition array
|
|
**/
|
|
$in: (item, condition) => ensureArray(condition).some(
|
|
(cond) => Array.isArray(item) ? match(item, { $contains: cond }) : match(item, cond)
|
|
),
|
|
/**
|
|
* Match if item contains every condition or match every rule in condition array
|
|
**/
|
|
$contains: (item, condition) => {
|
|
item = Array.isArray(item) ? item : String(item);
|
|
return ensureArray(condition).every((i) => item.includes(i));
|
|
},
|
|
/**
|
|
* Ignore case contains
|
|
**/
|
|
$icontains: (item, condition) => {
|
|
if (typeof condition !== "string") {
|
|
throw new TypeError("$icontains requires a string, use $contains instead");
|
|
}
|
|
item = String(item).toLocaleLowerCase();
|
|
return ensureArray(condition).every((i) => item.includes(i.toLocaleLowerCase()));
|
|
},
|
|
/**
|
|
* Match if item contains at least one rule from condition array
|
|
*/
|
|
$containsAny: (item, condition) => {
|
|
assertArray(condition, "$containsAny requires an array as condition");
|
|
item = Array.isArray(item) ? item : String(item);
|
|
return condition.some((i) => item.includes(i));
|
|
},
|
|
/**
|
|
* Check key existence
|
|
*/
|
|
$exists: (item, condition) => condition ? typeof item !== "undefined" : typeof item === "undefined",
|
|
/**
|
|
* Match if type of item equals condition
|
|
*/
|
|
$type: (item, condition) => typeof item === String(condition),
|
|
/**
|
|
* Provides regular expression capabilities for pattern matching strings.
|
|
*/
|
|
$regex: (item, condition) => {
|
|
if (!(condition instanceof RegExp)) {
|
|
const matched = String(condition).match(/\/(.*)\/([dgimsuy]*)$/);
|
|
condition = matched?.[1] ? new RegExp(matched[1], matched[2] || "") : new RegExp(condition);
|
|
}
|
|
return condition.test(String(item || ""));
|
|
},
|
|
/**
|
|
* Check if item is less than condition
|
|
*/
|
|
$lt: (item, condition) => {
|
|
return item < condition;
|
|
},
|
|
/**
|
|
* Check if item is less than or equal to condition
|
|
*/
|
|
$lte: (item, condition) => {
|
|
return item <= condition;
|
|
},
|
|
/**
|
|
* Check if item is greater than condition
|
|
*/
|
|
$gt: (item, condition) => {
|
|
return item > condition;
|
|
},
|
|
/**
|
|
* Check if item is greater than or equal to condition
|
|
*/
|
|
$gte: (item, condition) => {
|
|
return item >= condition;
|
|
},
|
|
...operators || {}
|
|
};
|
|
}
|
|
|
|
function createPipelineFetcher(getContentsList) {
|
|
const match = createMatch();
|
|
const surround = (data, { query, before, after }) => {
|
|
const matchQuery = typeof query === "string" ? { _path: query } : query;
|
|
const index = data.findIndex((item) => match(item, matchQuery));
|
|
before = before ?? 1;
|
|
after = after ?? 1;
|
|
const slice = new Array(before + after).fill(null, 0);
|
|
return index === -1 ? slice : slice.map((_, i) => data[index - before + i + Number(i >= before)] || null);
|
|
};
|
|
const matchingPipelines = [
|
|
// Conditions
|
|
(state, params) => {
|
|
const filtered = state.result.filter((item) => ensureArray(params.where).every((matchQuery) => match(item, matchQuery)));
|
|
return {
|
|
...state,
|
|
result: filtered,
|
|
total: filtered.length
|
|
};
|
|
},
|
|
// Sort data
|
|
(state, params) => ensureArray(params.sort).forEach((options) => sortList(state.result, options)),
|
|
function fetchSurround(state, params, db) {
|
|
if (params.surround) {
|
|
let _surround = surround(state.result?.length === 1 ? db : state.result, params.surround);
|
|
_surround = apply(withoutKeys(params.without))(_surround);
|
|
_surround = apply(withKeys(params.only))(_surround);
|
|
state.surround = _surround;
|
|
}
|
|
return state;
|
|
}
|
|
];
|
|
const transformingPiples = [
|
|
// Skip first items
|
|
(state, params) => {
|
|
if (params.skip) {
|
|
return {
|
|
...state,
|
|
result: state.result.slice(params.skip),
|
|
skip: params.skip
|
|
};
|
|
}
|
|
},
|
|
// Pick first items
|
|
(state, params) => {
|
|
if (params.limit) {
|
|
return {
|
|
...state,
|
|
result: state.result.slice(0, params.limit),
|
|
limit: params.limit
|
|
};
|
|
}
|
|
},
|
|
function fetchDirConfig(state, params, db) {
|
|
if (params.dirConfig) {
|
|
const path = state.result[0]?._path || params.where?.find((w) => w._path)?._path;
|
|
if (typeof path === "string") {
|
|
const dirConfig = db.find((item) => item._path === joinURL(path, "_dir"));
|
|
if (dirConfig) {
|
|
state.dirConfig = { _path: dirConfig._path, ...withoutKeys(["_"])(dirConfig) };
|
|
}
|
|
}
|
|
}
|
|
return state;
|
|
},
|
|
// Remove unwanted fields
|
|
(state, params) => ({
|
|
...state,
|
|
result: apply(withoutKeys(params.without))(state.result)
|
|
}),
|
|
// Select only wanted fields
|
|
(state, params) => ({
|
|
...state,
|
|
result: apply(withKeys(params.only))(state.result)
|
|
})
|
|
];
|
|
return async (query) => {
|
|
const db = await getContentsList();
|
|
const params = query.params();
|
|
const result1 = {
|
|
result: db,
|
|
limit: 0,
|
|
skip: 0,
|
|
total: db.length
|
|
};
|
|
const matchedData = matchingPipelines.reduce(($data, pipe) => pipe($data, params, db) || $data, result1);
|
|
if (params.count) {
|
|
return {
|
|
result: matchedData.result.length
|
|
};
|
|
}
|
|
const result = transformingPiples.reduce(($data, pipe) => pipe($data, params, db) || $data, matchedData);
|
|
if (params.first) {
|
|
return {
|
|
...omit(["skip", "limit", "total"])(result),
|
|
result: result.result[0]
|
|
};
|
|
}
|
|
return result;
|
|
};
|
|
}
|
|
|
|
const isPreview = (event) => {
|
|
const previewToken = getQuery$1(event).previewToken || getCookie(event, "previewToken");
|
|
return !!previewToken;
|
|
};
|
|
const getPreview = (event) => {
|
|
const key = getQuery$1(event).previewToken || getCookie(event, "previewToken");
|
|
return { key };
|
|
};
|
|
|
|
async function getContentIndex(event) {
|
|
const defaultLocale = useRuntimeConfig().content.defaultLocale;
|
|
let contentIndex = await cacheStorage().getItem("content-index.json");
|
|
if (!contentIndex) {
|
|
const data = await getContentsList(event);
|
|
contentIndex = data.reduce((acc, item) => {
|
|
acc[item._path] = acc[item._path] || [];
|
|
if (item._locale === defaultLocale) {
|
|
acc[item._path].unshift(item._id);
|
|
} else {
|
|
acc[item._path].push(item._id);
|
|
}
|
|
return acc;
|
|
}, {});
|
|
await cacheStorage().setItem("content-index.json", contentIndex);
|
|
}
|
|
return contentIndex;
|
|
}
|
|
async function getIndexedContentsList(event, query) {
|
|
const params = query.params();
|
|
const path = params?.where?.find((wh) => wh._path)?._path;
|
|
if (!isPreview(event) && !params.surround && !params.dirConfig && (typeof path === "string" || path instanceof RegExp)) {
|
|
const index = await getContentIndex(event);
|
|
const keys = Object.keys(index).filter((key) => path.test ? path.test(key) : key === String(path)).flatMap((key) => index[key]);
|
|
const keyChunks = [...chunksFromArray(keys, 10)];
|
|
const contents = [];
|
|
for await (const chunk of keyChunks) {
|
|
const result = await Promise.all(chunk.map((key) => getContent(event, key)));
|
|
contents.push(...result);
|
|
}
|
|
return contents;
|
|
}
|
|
return getContentsList(event);
|
|
}
|
|
|
|
const contentIndex = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
__proto__: null,
|
|
getContentIndex: getContentIndex,
|
|
getIndexedContentsList: getIndexedContentsList
|
|
}, Symbol.toStringTag, { value: 'Module' }));
|
|
|
|
const transformers = [];
|
|
|
|
let _sourceStorage;
|
|
let _cacheStorage;
|
|
let _cacheParsedStorage;
|
|
const sourceStorage = () => {
|
|
if (!_sourceStorage) {
|
|
_sourceStorage = prefixStorage(useStorage(), "content:source");
|
|
}
|
|
return _sourceStorage;
|
|
};
|
|
const cacheStorage = () => {
|
|
if (!_cacheStorage) {
|
|
_cacheStorage = prefixStorage(useStorage(), "cache:content");
|
|
}
|
|
return _cacheStorage;
|
|
};
|
|
const cacheParsedStorage = () => {
|
|
if (!_cacheParsedStorage) {
|
|
_cacheParsedStorage = prefixStorage(useStorage(), "cache:content:parsed");
|
|
}
|
|
return _cacheParsedStorage;
|
|
};
|
|
const contentConfig = () => useRuntimeConfig().content;
|
|
const invalidKeyCharacters = `'"?#/`.split("");
|
|
const contentIgnorePredicate = (key) => {
|
|
const isIgnored = makeIgnored(contentConfig().ignores);
|
|
if (key.startsWith("preview:") || isIgnored(key)) {
|
|
return false;
|
|
}
|
|
if (invalidKeyCharacters.some((ik) => key.includes(ik))) {
|
|
console.warn(`Ignoring [${key}]. File name should not contain any of the following characters: ${invalidKeyCharacters.join(", ")}`);
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
const getContentsIds = async (event, prefix) => {
|
|
let keys = [];
|
|
const source = sourceStorage();
|
|
if (keys.length === 0) {
|
|
keys = await source.getKeys(prefix);
|
|
}
|
|
if (isPreview(event)) {
|
|
const { key } = getPreview(event);
|
|
const previewPrefix = `preview:${key}:${prefix || ""}`;
|
|
const previewKeys = await source.getKeys(previewPrefix);
|
|
if (previewKeys.length) {
|
|
const keysSet = new Set(keys);
|
|
await Promise.all(
|
|
previewKeys.map(async (key2) => {
|
|
const meta = await source.getMeta(key2);
|
|
if (meta?.__deleted) {
|
|
keysSet.delete(key2.substring(previewPrefix.length));
|
|
} else {
|
|
keysSet.add(key2.substring(previewPrefix.length));
|
|
}
|
|
})
|
|
);
|
|
keys = Array.from(keysSet);
|
|
}
|
|
}
|
|
return keys.filter(contentIgnorePredicate);
|
|
};
|
|
function* chunksFromArray(arr, n) {
|
|
for (let i = 0; i < arr.length; i += n) {
|
|
yield arr.slice(i, i + n);
|
|
}
|
|
}
|
|
let cachedContents = [];
|
|
const cleanCachedContents = () => {
|
|
cachedContents = [];
|
|
};
|
|
const getContentsList = /* @__PURE__ */ (() => {
|
|
let pendingContentsListPromise = null;
|
|
const _getContentsList = async (event, prefix) => {
|
|
const keys = await getContentsIds(event, prefix);
|
|
const keyChunks = [...chunksFromArray(keys, 10)];
|
|
const contents = [];
|
|
for (const chunk of keyChunks) {
|
|
const result = await Promise.all(chunk.map((key) => getContent(event, key)));
|
|
contents.push(...result);
|
|
}
|
|
return contents.filter((c) => c && c._path);
|
|
};
|
|
return (event, prefix) => {
|
|
if (event.context.__contentList) {
|
|
return event.context.__contentList;
|
|
}
|
|
if (cachedContents.length) {
|
|
return cachedContents;
|
|
}
|
|
if (!pendingContentsListPromise) {
|
|
pendingContentsListPromise = _getContentsList(event, prefix);
|
|
pendingContentsListPromise.then((result) => {
|
|
{
|
|
cachedContents = result;
|
|
}
|
|
event.context.__contentList = result;
|
|
pendingContentsListPromise = null;
|
|
});
|
|
}
|
|
return pendingContentsListPromise;
|
|
};
|
|
})();
|
|
const pendingPromises = {};
|
|
const getContent = async (event, id) => {
|
|
const contentId = id;
|
|
if (!contentIgnorePredicate(id)) {
|
|
return { _id: contentId, body: null };
|
|
}
|
|
const source = sourceStorage();
|
|
const cache = cacheParsedStorage();
|
|
if (isPreview(event)) {
|
|
const { key } = getPreview(event);
|
|
const previewId = `preview:${key}:${id}`;
|
|
const draft = await source.getItem(previewId);
|
|
if (draft) {
|
|
id = previewId;
|
|
}
|
|
}
|
|
const cached = await cache.getItem(id);
|
|
const config = contentConfig();
|
|
const meta = await source.getMeta(id);
|
|
const mtime = meta.mtime;
|
|
const size = meta.size || 0;
|
|
const hash = hash$1({
|
|
// Last modified time
|
|
mtime,
|
|
// File size
|
|
size,
|
|
// Add Content version to the hash, to revalidate the cache on content update
|
|
version: config.cacheVersion,
|
|
integrity: config.cacheIntegrity
|
|
});
|
|
if (cached?.hash === hash) {
|
|
return cached.parsed;
|
|
}
|
|
if (!pendingPromises[id + hash]) {
|
|
pendingPromises[id + hash] = new Promise(async (resolve) => {
|
|
const body = await source.getItem(id);
|
|
if (body === null) {
|
|
return resolve({ _id: contentId, body: null });
|
|
}
|
|
const parsed = await parseContent(contentId, body);
|
|
await cache.setItem(id, { parsed, hash }).catch(() => {
|
|
});
|
|
resolve(parsed);
|
|
delete pendingPromises[id + hash];
|
|
});
|
|
}
|
|
return pendingPromises[id + hash];
|
|
};
|
|
const parseContent = async (id, content, opts = {}) => {
|
|
const nitroApp = useNitroApp();
|
|
const config = contentConfig();
|
|
const options = defu(
|
|
opts,
|
|
{
|
|
markdown: {
|
|
...config.markdown,
|
|
highlight: config.highlight
|
|
},
|
|
csv: config.csv,
|
|
yaml: config.yaml,
|
|
transformers: transformers,
|
|
pathMeta: {
|
|
defaultLocale: config.defaultLocale,
|
|
locales: config.locales,
|
|
respectPathCase: config.respectPathCase
|
|
}
|
|
}
|
|
);
|
|
const file = { _id: id, body: typeof content === "string" ? content.replace(/\r\n|\r/g, "\n") : content };
|
|
await nitroApp.hooks.callHook("content:file:beforeParse", file);
|
|
const result = await transformContent(id, file.body, options);
|
|
await nitroApp.hooks.callHook("content:file:afterParse", result);
|
|
return result;
|
|
};
|
|
const createServerQueryFetch = (event) => (query) => {
|
|
return createPipelineFetcher(() => getIndexedContentsList(event, query))(query);
|
|
};
|
|
function serverQueryContent$1(event, query, ...pathParts) {
|
|
const { advanceQuery } = useRuntimeConfig().public.content.experimental;
|
|
const config = contentConfig();
|
|
const queryBuilder = advanceQuery ? createQuery(createServerQueryFetch(event), { initialParams: typeof query !== "string" ? query || {} : {}, legacy: false }) : createQuery(createServerQueryFetch(event), { initialParams: typeof query !== "string" ? query || {} : {}, legacy: true });
|
|
let path;
|
|
if (typeof query === "string") {
|
|
path = withLeadingSlash(joinURL(query, ...pathParts));
|
|
}
|
|
const originalParamsFn = queryBuilder.params;
|
|
queryBuilder.params = () => {
|
|
const params = originalParamsFn();
|
|
if (path) {
|
|
params.where = params.where || [];
|
|
if (params.first && (params.where || []).length === 0) {
|
|
params.where.push({ _path: withoutTrailingSlash(path) });
|
|
} else {
|
|
params.where.push({ _path: new RegExp(`^${path.replace(/[-[\]{}()*+.,^$\s/]/g, "\\$&")}`) });
|
|
}
|
|
}
|
|
if (!params.sort?.length) {
|
|
params.sort = [{ _stem: 1, $numeric: true }];
|
|
}
|
|
if (config.locales.length) {
|
|
const queryLocale = params.where?.find((w) => w._locale)?._locale;
|
|
if (!queryLocale) {
|
|
params.where = params.where || [];
|
|
params.where.push({ _locale: config.defaultLocale });
|
|
}
|
|
}
|
|
return params;
|
|
};
|
|
return queryBuilder;
|
|
}
|
|
|
|
const storage = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
__proto__: null,
|
|
cacheParsedStorage: cacheParsedStorage,
|
|
cacheStorage: cacheStorage,
|
|
chunksFromArray: chunksFromArray,
|
|
cleanCachedContents: cleanCachedContents,
|
|
createServerQueryFetch: createServerQueryFetch,
|
|
getContent: getContent,
|
|
getContentsIds: getContentsIds,
|
|
getContentsList: getContentsList,
|
|
parseContent: parseContent,
|
|
serverQueryContent: serverQueryContent$1,
|
|
sourceStorage: sourceStorage
|
|
}, Symbol.toStringTag, { value: 'Module' }));
|
|
|
|
const serverQueryContent = serverQueryContent$1;
|
|
|
|
const _yEFF8G = defineEventHandler(async (e) => {
|
|
const contentList = await serverQueryContent(e).find();
|
|
return contentList.map((c) => c.sitemap).filter(Boolean);
|
|
});
|
|
|
|
async function fetchDataSource(input, event) {
|
|
const context = typeof input.context === "string" ? { name: input.context } : input.context || { name: "fetch" };
|
|
context.tips = context.tips || [];
|
|
const url = typeof input.fetch === "string" ? input.fetch : input.fetch[0];
|
|
const options = typeof input.fetch === "string" ? {} : input.fetch[1];
|
|
const start = Date.now();
|
|
const timeout = options.timeout || 5e3;
|
|
const timeoutController = new AbortController();
|
|
const abortRequestTimeout = setTimeout(() => timeoutController.abort(), timeout);
|
|
let isHtmlResponse = false;
|
|
try {
|
|
const fetchContainer = url.startsWith("/") && event ? event : globalThis;
|
|
const urls = await fetchContainer.$fetch(url, {
|
|
...options,
|
|
responseType: "json",
|
|
signal: timeoutController.signal,
|
|
headers: defu$1(options?.headers, {
|
|
Accept: "application/json"
|
|
}, event ? { Host: getRequestHost(event, { xForwardedHost: true }) } : {}),
|
|
// @ts-expect-error untyped
|
|
onResponse({ response }) {
|
|
if (typeof response._data === "string" && response._data.startsWith("<!DOCTYPE html>"))
|
|
isHtmlResponse = true;
|
|
}
|
|
});
|
|
const timeTakenMs = Date.now() - start;
|
|
if (isHtmlResponse) {
|
|
context.tips.push("This is usually because the URL isn't correct or is throwing an error. Please check the URL");
|
|
return {
|
|
...input,
|
|
context,
|
|
urls: [],
|
|
timeTakenMs,
|
|
error: "Received HTML response instead of JSON"
|
|
};
|
|
}
|
|
return {
|
|
...input,
|
|
context,
|
|
timeTakenMs,
|
|
urls
|
|
};
|
|
} catch (_err) {
|
|
const error = _err;
|
|
if (error.message.includes("This operation was aborted"))
|
|
context.tips.push("The request has taken too long. Make sure app sources respond within 5 seconds or adjust the timeout fetch option.");
|
|
else
|
|
context.tips.push(`Response returned a status of ${error.response?.status || "unknown"}.`);
|
|
console.error("[@nuxtjs/sitemap] Failed to fetch source.", { url, error });
|
|
return {
|
|
...input,
|
|
context,
|
|
urls: [],
|
|
error: error.message
|
|
};
|
|
} finally {
|
|
if (abortRequestTimeout) {
|
|
clearTimeout(abortRequestTimeout);
|
|
}
|
|
}
|
|
}
|
|
function globalSitemapSources() {
|
|
return Promise.resolve().then(function () { return globalSources; }).then((m) => m.sources);
|
|
}
|
|
function childSitemapSources(definition) {
|
|
return definition?._hasSourceChunk ? Promise.resolve().then(function () { return childSources; }).then((m) => m.sources[definition.sitemapName] || []) : Promise.resolve([]);
|
|
}
|
|
async function resolveSitemapSources(sources, event) {
|
|
return (await Promise.all(
|
|
sources.map((source) => {
|
|
if (typeof source === "object" && "urls" in source) {
|
|
return {
|
|
timeTakenMs: 0,
|
|
...source,
|
|
urls: source.urls
|
|
};
|
|
}
|
|
if (source.fetch)
|
|
return fetchDataSource(source, event);
|
|
return {
|
|
...source,
|
|
error: "Invalid source"
|
|
};
|
|
})
|
|
)).flat();
|
|
}
|
|
|
|
const _waepPN = defineEventHandler(async (e) => {
|
|
const _runtimeConfig = useSimpleSitemapRuntimeConfig();
|
|
const { sitemaps: _sitemaps } = _runtimeConfig;
|
|
const runtimeConfig = { ..._runtimeConfig };
|
|
delete runtimeConfig.sitemaps;
|
|
const globalSources = await globalSitemapSources();
|
|
const nitroOrigin = useNitroOrigin(e);
|
|
const sitemaps = {};
|
|
for (const s of Object.keys(_sitemaps)) {
|
|
sitemaps[s] = {
|
|
..._sitemaps[s],
|
|
sources: await resolveSitemapSources(await childSitemapSources(_sitemaps[s]))
|
|
};
|
|
}
|
|
return {
|
|
nitroOrigin,
|
|
sitemaps,
|
|
runtimeConfig,
|
|
globalSources: await resolveSitemapSources(globalSources)
|
|
};
|
|
});
|
|
|
|
const _zSetAt = defineEventHandler(async (e) => {
|
|
const fixPath = createSitePathResolver(e, { absolute: false, withBase: true });
|
|
const { sitemapName: fallbackSitemapName, cacheMaxAgeSeconds, version, xslColumns, xslTips } = useSimpleSitemapRuntimeConfig();
|
|
setHeader(e, "Content-Type", "application/xslt+xml");
|
|
if (cacheMaxAgeSeconds)
|
|
setHeader(e, "Cache-Control", `public, max-age=${cacheMaxAgeSeconds}, must-revalidate`);
|
|
else
|
|
setHeader(e, "Cache-Control", `no-cache, no-store`);
|
|
const svgIcon = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="icon" style="margin-right: 4px; font-size: 25px;" width="1em" height="1em" viewBox="0 0 32 32"><path fill="#93c5fd" d="M4 26h4v4H4zm10 0h4v4h-4zm10 0h4v4h-4zm1-10h-8v-2h-2v2H7a2.002 2.002 0 0 0-2 2v6h2v-6h8v6h2v-6h8v6h2v-6a2.002 2.002 0 0 0-2-2zM9 2v10h14V2zm2 2h2v6h-2zm10 6h-6V4h6z"></path></svg>`;
|
|
const creditName = `<a href="https://github.com/nuxt-modules/sitemap" style="color: black; display: flex; align-items: center; font-weight: 500;" target="_blank" rel="noopener">${svgIcon} Nuxt Sitemap v${version}</a>`;
|
|
const { name: siteName, url: siteUrl } = useSiteConfig(e);
|
|
const referrer = getHeader(e, "Referer") || "/";
|
|
const referrerPath = parseURL(referrer).pathname;
|
|
const isNotIndexButHasIndex = referrerPath !== "/sitemap.xml" && referrerPath !== "/sitemap_index.xml" && referrerPath.endsWith(".xml");
|
|
const sitemapName = parseURL(referrer).pathname.split("/").pop()?.split("-sitemap")[0] || fallbackSitemapName;
|
|
const title = `${siteName}${sitemapName !== "sitemap.xml" ? ` - ${sitemapName === "sitemap_index.xml" ? "index" : sitemapName}` : ""}`.replace(/&/g, "&");
|
|
const canonicalQuery = getQuery(referrer).canonical;
|
|
const isShowingCanonical = typeof canonicalQuery !== "undefined" && canonicalQuery !== "false";
|
|
const conditionalTips = [
|
|
'You are looking at a <a href="https://developer.mozilla.org/en-US/docs/Web/XSLT/Transforming_XML_with_XSLT/An_Overview" style="color: #398465" target="_blank">XML stylesheet</a>. Read the <a href="https://nuxtseo.com/sitemap/guides/customising-ui" style="color: #398465" target="_blank">docs</a> to learn how to customize it. View the page source to see the raw XML.',
|
|
`URLs missing? Check Nuxt Devtools Sitemap tab (or the <a href="${withQuery("/__sitemap__/debug.json", { sitemap: sitemapName })}" style="color: #398465" target="_blank">debug endpoint</a>).`
|
|
];
|
|
if (!isShowingCanonical) {
|
|
const canonicalPreviewUrl = withQuery(referrer, { canonical: "" });
|
|
conditionalTips.push(`Your canonical site URL is <strong>${siteUrl}</strong>.`);
|
|
conditionalTips.push(`You can preview your canonical sitemap by visiting <a href="${canonicalPreviewUrl}" style="color: #398465; white-space: nowrap;">${fixPath(canonicalPreviewUrl)}?canonical</a>`);
|
|
} else {
|
|
conditionalTips.push(`You are viewing the canonical sitemap. You can switch to using the request origin: <a href="${fixPath(referrer)}" style="color: #398465; white-space: nowrap ">${fixPath(referrer)}</a>`);
|
|
}
|
|
const tips = conditionalTips.map((t) => `<li><p>${t}</p></li>`).join("\n");
|
|
const showTips = xslTips !== false;
|
|
let columns = [...xslColumns];
|
|
if (!columns.length) {
|
|
columns = [
|
|
{ label: "URL", width: "50%" },
|
|
{ label: "Images", width: "25%", select: "count(image:image)" },
|
|
{ label: "Last Updated", width: "25%", select: "concat(substring(sitemap:lastmod,0,11),concat(' ', substring(sitemap:lastmod,12,5)),concat(' ', substring(sitemap:lastmod,20,6)))" }
|
|
];
|
|
}
|
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
<xsl:stylesheet version="2.0"
|
|
xmlns:html="http://www.w3.org/TR/REC-html40"
|
|
xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"
|
|
xmlns:sitemap="http://www.sitemaps.org/schemas/sitemap/0.9"
|
|
xmlns:xhtml="http://www.w3.org/1999/xhtml"
|
|
xmlns:news="http://www.google.com/schemas/sitemap-news/0.9"
|
|
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
<xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"/>
|
|
<xsl:template match="/">
|
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
<head>
|
|
<title>XML Sitemap</title>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
|
<style type="text/css">
|
|
body {
|
|
font-family: Inter, Helvetica, Arial, sans-serif;
|
|
font-size: 14px;
|
|
color: #333;
|
|
}
|
|
|
|
table {
|
|
border: none;
|
|
border-collapse: collapse;
|
|
}
|
|
|
|
.bg-yellow-200 {
|
|
background-color: #fef9c3;
|
|
}
|
|
|
|
.p-5 {
|
|
padding: 1.25rem;
|
|
}
|
|
|
|
.rounded {
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.shadow {
|
|
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
|
|
}
|
|
|
|
#sitemap tr:nth-child(odd) td {
|
|
background-color: #f8f8f8 !important;
|
|
}
|
|
|
|
#sitemap tbody tr:hover td {
|
|
background-color: #fff;
|
|
}
|
|
|
|
#sitemap tbody tr:hover td, #sitemap tbody tr:hover td a {
|
|
color: #000;
|
|
}
|
|
|
|
.expl a {
|
|
color: #398465
|
|
font-weight: 600;
|
|
}
|
|
|
|
.expl a:visited {
|
|
color: #398465
|
|
}
|
|
|
|
a {
|
|
color: #000;
|
|
text-decoration: none;
|
|
}
|
|
|
|
a:visited {
|
|
color: #777;
|
|
}
|
|
|
|
a:hover {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
td {
|
|
font-size: 12px;
|
|
}
|
|
|
|
.text-2xl {
|
|
font-size: 2rem;
|
|
font-weight: 600;
|
|
line-height: 1.25;
|
|
}
|
|
|
|
th {
|
|
text-align: left;
|
|
padding-right: 30px;
|
|
font-size: 12px;
|
|
}
|
|
|
|
thead th {
|
|
border-bottom: 1px solid #000;
|
|
}
|
|
.fixed { position: fixed; }
|
|
.right-2 { right: 2rem; }
|
|
.top-2 { top: 2rem; }
|
|
.w-30 { width: 30rem; }
|
|
p { margin: 0; }
|
|
li { padding-bottom: 0.5rem; line-height: 1.5; }
|
|
h1 { margin: 0; }
|
|
.mb-5 { margin-bottom: 1.25rem; }
|
|
.mb-3 { margin-bottom: 0.75rem; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div style="grid-template-columns: 1fr 1fr; display: grid; margin: 3rem;">
|
|
<div>
|
|
<div id="content">
|
|
<h1 class="text-2xl mb-3">XML Sitemap</h1>
|
|
<h2>${title}</h2>
|
|
${isNotIndexButHasIndex ? `<p style="font-size: 12px; margin-bottom: 1rem;"><a href="${fixPath("/sitemap_index.xml")}">${fixPath("/sitemap_index.xml")}</a></p>` : ""}
|
|
<xsl:if test="count(sitemap:sitemapindex/sitemap:sitemap) > 0">
|
|
<p class="expl" style="margin-bottom: 1rem;">
|
|
This XML Sitemap Index file contains
|
|
<xsl:value-of select="count(sitemap:sitemapindex/sitemap:sitemap)"/> sitemaps.
|
|
</p>
|
|
<table id="sitemap" cellpadding="3">
|
|
<thead>
|
|
<tr>
|
|
<th width="75%">Sitemap</th>
|
|
<th width="25%">Last Modified</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<xsl:for-each select="sitemap:sitemapindex/sitemap:sitemap">
|
|
<xsl:variable name="sitemapURL">
|
|
<xsl:value-of select="sitemap:loc"/>
|
|
</xsl:variable>
|
|
<tr>
|
|
<td>
|
|
<a href="{$sitemapURL}">
|
|
<xsl:value-of select="sitemap:loc"/>
|
|
</a>
|
|
</td>
|
|
<td>
|
|
<xsl:value-of
|
|
select="concat(substring(sitemap:lastmod,0,11),concat(' ', substring(sitemap:lastmod,12,5)),concat(' ', substring(sitemap:lastmod,20,6)))"/>
|
|
</td>
|
|
</tr>
|
|
</xsl:for-each>
|
|
</tbody>
|
|
</table>
|
|
</xsl:if>
|
|
<xsl:if test="count(sitemap:sitemapindex/sitemap:sitemap) < 1">
|
|
<p class="expl" style="margin-bottom: 1rem;">
|
|
This XML Sitemap contains
|
|
<xsl:value-of select="count(sitemap:urlset/sitemap:url)"/> URLs.
|
|
</p>
|
|
<table id="sitemap" cellpadding="3">
|
|
<thead>
|
|
<tr>
|
|
${columns.map((c) => `<th width="${c.width}">${c.label}</th>`).join("\n")}
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<xsl:variable name="lower" select="'abcdefghijklmnopqrstuvwxyz'"/>
|
|
<xsl:variable name="upper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
|
|
<xsl:for-each select="sitemap:urlset/sitemap:url">
|
|
<tr>
|
|
<td>
|
|
<xsl:variable name="itemURL">
|
|
<xsl:value-of select="sitemap:loc"/>
|
|
</xsl:variable>
|
|
<a href="{$itemURL}">
|
|
<xsl:value-of select="sitemap:loc"/>
|
|
</a>
|
|
</td>
|
|
${columns.filter((c) => c.label !== "URL").map((c) => `<td>
|
|
<xsl:value-of select="${c.select}"/>
|
|
</td>`).join("\n")}
|
|
</tr>
|
|
</xsl:for-each>
|
|
</tbody>
|
|
</table>
|
|
</xsl:if>
|
|
</div>
|
|
</div>
|
|
${showTips ? `<div class="w-30 top-2 shadow rounded p-5 right-2" style="margin: 0 auto;"><p><strong>Sitemap Tips (development only)</strong></p><ul style="margin: 1rem; padding: 0;">${tips}</ul><p style="margin-top: 1rem;">${creditName}</p></div>` : ""}
|
|
</div>
|
|
</body>
|
|
</html>
|
|
</xsl:template>
|
|
</xsl:stylesheet>
|
|
`;
|
|
});
|
|
|
|
function withoutQuery(path) {
|
|
return path.split("?")[0];
|
|
}
|
|
function createNitroRouteRuleMatcher() {
|
|
const { nitro, app } = useRuntimeConfig();
|
|
const _routeRulesMatcher = toRouteMatcher(
|
|
createRouter({
|
|
routes: Object.fromEntries(
|
|
Object.entries(nitro?.routeRules || {}).map(([path, rules]) => [path === "/" ? path : withoutTrailingSlash(path), rules])
|
|
)
|
|
})
|
|
);
|
|
return (pathOrUrl) => {
|
|
const path = pathOrUrl[0] === "/" ? pathOrUrl : parseURL(pathOrUrl, app.baseURL).pathname;
|
|
const pathWithoutQuery = withoutQuery(path);
|
|
return defu$1({}, ..._routeRulesMatcher.matchAll(
|
|
// radix3 does not support trailing slashes
|
|
withoutBase(pathWithoutQuery === "/" ? pathWithoutQuery : withoutTrailingSlash(pathWithoutQuery), app.baseURL)
|
|
).reverse());
|
|
};
|
|
}
|
|
|
|
function resolve(s, resolvers) {
|
|
if (typeof s === "undefined" || !resolvers)
|
|
return s;
|
|
s = typeof s === "string" ? s : s.toString();
|
|
if (hasProtocol(s, { acceptRelative: true, strict: false }))
|
|
return resolvers.fixSlashes(s);
|
|
return resolvers.canonicalUrlResolver(s);
|
|
}
|
|
function removeTrailingSlash(s) {
|
|
return s.replace(/\/(\?|#|$)/, "$1");
|
|
}
|
|
function preNormalizeEntry(_e, resolvers) {
|
|
const e = typeof _e === "string" ? { loc: _e } : { ..._e };
|
|
if (e.url && !e.loc) {
|
|
e.loc = e.url;
|
|
delete e.url;
|
|
}
|
|
if (typeof e.loc !== "string") {
|
|
e.loc = "";
|
|
}
|
|
e.loc = removeTrailingSlash(e.loc);
|
|
e._abs = hasProtocol(e.loc, { acceptRelative: false, strict: false });
|
|
try {
|
|
e._path = e._abs ? parseURL(e.loc) : parsePath(e.loc);
|
|
} catch (e2) {
|
|
e2._path = null;
|
|
}
|
|
if (e._path) {
|
|
const query = parseQuery(e._path.search);
|
|
const qs = stringifyQuery(query);
|
|
e._relativeLoc = `${encodePath(e._path?.pathname)}${qs.length ? `?${qs}` : ""}`;
|
|
if (e._path.host) {
|
|
e.loc = stringifyParsedURL(e._path);
|
|
} else {
|
|
e.loc = e._relativeLoc;
|
|
}
|
|
} else {
|
|
e.loc = encodeURI(e.loc);
|
|
}
|
|
if (e.loc === "")
|
|
e.loc = `/`;
|
|
e.loc = resolve(e.loc, resolvers);
|
|
e._key = `${e._sitemap || ""}${withoutTrailingSlash(e.loc)}`;
|
|
return e;
|
|
}
|
|
function normaliseEntry(_e, defaults, resolvers) {
|
|
const e = defu$1(_e, defaults);
|
|
if (e.lastmod) {
|
|
const date = normaliseDate(e.lastmod);
|
|
if (date)
|
|
e.lastmod = date;
|
|
else
|
|
delete e.lastmod;
|
|
}
|
|
if (!e.lastmod)
|
|
delete e.lastmod;
|
|
e.loc = resolve(e.loc, resolvers);
|
|
if (e.alternatives) {
|
|
e.alternatives = mergeOnKey(e.alternatives.map((e2) => {
|
|
const a = { ...e2 };
|
|
if (typeof a.href === "string")
|
|
a.href = resolve(a.href, resolvers);
|
|
else if (typeof a.href === "object" && a.href)
|
|
a.href = resolve(a.href.href, resolvers);
|
|
return a;
|
|
}), "hreflang");
|
|
}
|
|
if (e.images) {
|
|
e.images = mergeOnKey(e.images.map((i) => {
|
|
i = { ...i };
|
|
i.loc = resolve(i.loc, resolvers);
|
|
return i;
|
|
}), "loc");
|
|
}
|
|
if (e.videos) {
|
|
e.videos = e.videos.map((v) => {
|
|
v = { ...v };
|
|
if (v.content_loc)
|
|
v.content_loc = resolve(v.content_loc, resolvers);
|
|
return v;
|
|
});
|
|
}
|
|
return e;
|
|
}
|
|
const IS_VALID_W3C_DATE = [
|
|
/(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))/,
|
|
/^\d{4}-[01]\d-[0-3]\d$/,
|
|
/^\d{4}-[01]\d$/,
|
|
/^\d{4}$/
|
|
];
|
|
function isValidW3CDate(d) {
|
|
return IS_VALID_W3C_DATE.some((r) => r.test(d));
|
|
}
|
|
function normaliseDate(d) {
|
|
if (typeof d === "string") {
|
|
if (d.includes("T")) {
|
|
const t = d.split("T")[1];
|
|
if (!t.includes("+") && !t.includes("-") && !t.includes("Z")) {
|
|
d += "Z";
|
|
}
|
|
}
|
|
if (!isValidW3CDate(d))
|
|
return false;
|
|
d = new Date(d);
|
|
d.setMilliseconds(0);
|
|
if (Number.isNaN(d.getTime()))
|
|
return false;
|
|
}
|
|
const z = (n) => `0${n}`.slice(-2);
|
|
const date = `${d.getUTCFullYear()}-${z(d.getUTCMonth() + 1)}-${z(d.getUTCDate())}`;
|
|
if (d.getUTCHours() > 0 || d.getUTCMinutes() > 0 || d.getUTCSeconds() > 0) {
|
|
return `${date}T${z(d.getUTCHours())}:${z(d.getUTCMinutes())}:${z(d.getUTCSeconds())}Z`;
|
|
}
|
|
return date;
|
|
}
|
|
|
|
function sortSitemapUrls(urls) {
|
|
return urls.sort(
|
|
(a, b) => {
|
|
const aLoc = typeof a === "string" ? a : a.loc;
|
|
const bLoc = typeof b === "string" ? b : b.loc;
|
|
return aLoc.localeCompare(bLoc, void 0, { numeric: true });
|
|
}
|
|
).sort((a, b) => {
|
|
const aLoc = (typeof a === "string" ? a : a.loc) || "";
|
|
const bLoc = (typeof b === "string" ? b : b.loc) || "";
|
|
const aSegments = aLoc.split("/").length;
|
|
const bSegments = bLoc.split("/").length;
|
|
if (aSegments > bSegments)
|
|
return 1;
|
|
if (aSegments < bSegments)
|
|
return -1;
|
|
return 0;
|
|
});
|
|
}
|
|
|
|
function resolveKey(k) {
|
|
switch (k) {
|
|
case "images":
|
|
return "image";
|
|
case "videos":
|
|
return "video";
|
|
// news & others?
|
|
case "news":
|
|
return "news";
|
|
default:
|
|
return k;
|
|
}
|
|
}
|
|
function handleObject(key, obj) {
|
|
return [
|
|
` <${key}:${key}>`,
|
|
...Object.entries(obj).map(([sk, sv]) => {
|
|
if (key === "video" && Array.isArray(sv)) {
|
|
return sv.map((v) => {
|
|
if (typeof v === "string") {
|
|
return [
|
|
` `,
|
|
`<${key}:${sk}>`,
|
|
escapeValueForXml(v),
|
|
`</${key}:${sk}>`
|
|
].join("");
|
|
}
|
|
const attributes = Object.entries(v).filter(([ssk]) => ssk !== sk).map(([ssk, ssv]) => `${ssk}="${escapeValueForXml(ssv)}"`).join(" ");
|
|
return [
|
|
` <${key}:${sk} ${attributes}>`,
|
|
// value is the same sk
|
|
v[sk],
|
|
`</${key}:${sk}>`
|
|
].join("");
|
|
}).join("\n");
|
|
}
|
|
if (typeof sv === "object") {
|
|
if (key === "video") {
|
|
const attributes = Object.entries(sv).filter(([ssk]) => ssk !== sk).map(([ssk, ssv]) => `${ssk}="${escapeValueForXml(ssv)}"`).join(" ");
|
|
return [
|
|
` <${key}:${sk} ${attributes}>`,
|
|
// value is the same sk
|
|
sv[sk],
|
|
`</${key}:${sk}>`
|
|
].join("");
|
|
}
|
|
return [
|
|
` <${key}:${sk}>`,
|
|
...Object.entries(sv).map(([ssk, ssv]) => ` <${key}:${ssk}>${escapeValueForXml(ssv)}</${key}:${ssk}>`),
|
|
` </${key}:${sk}>`
|
|
].join("\n");
|
|
}
|
|
return ` <${key}:${sk}>${escapeValueForXml(sv)}</${key}:${sk}>`;
|
|
}),
|
|
` </${key}:${key}>`
|
|
].join("\n");
|
|
}
|
|
function handleArray(key, arr) {
|
|
if (arr.length === 0)
|
|
return false;
|
|
key = resolveKey(key);
|
|
if (key === "alternatives") {
|
|
return arr.map((obj) => [
|
|
` <xhtml:link rel="alternate" ${Object.entries(obj).map(([sk, sv]) => `${sk}="${escapeValueForXml(sv)}"`).join(" ")} />`
|
|
].join("\n")).join("\n");
|
|
}
|
|
return arr.map((obj) => handleObject(key, obj)).join("\n");
|
|
}
|
|
function handleEntry(k, e) {
|
|
return Array.isArray(e[k]) ? handleArray(k, e[k]) : typeof e[k] === "object" ? handleObject(k, e[k]) : ` <${k}>${escapeValueForXml(e[k])}</${k}>`;
|
|
}
|
|
function wrapSitemapXml(input, resolvers, options) {
|
|
const xsl = options.xsl ? resolvers.relativeBaseUrlResolver(options.xsl) : false;
|
|
const credits = options.credits;
|
|
input.unshift(`<?xml version="1.0" encoding="UTF-8"?>${xsl ? `<?xml-stylesheet type="text/xsl" href="${xsl}"?>` : ""}`);
|
|
if (credits)
|
|
input.push(`<!-- XML Sitemap generated by @nuxtjs/sitemap v${options.version} at ${(/* @__PURE__ */ new Date()).toISOString()} -->`);
|
|
if (options.minify)
|
|
return input.join("").replace(/(?<!<[^>]*)\s(?![^<]*>)/g, "");
|
|
return input.join("\n");
|
|
}
|
|
function escapeValueForXml(value) {
|
|
if (value === true || value === false)
|
|
return value ? "yes" : "no";
|
|
return String(value).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
}
|
|
|
|
function resolveSitemapEntries(sitemap, sources, runtimeConfig, resolvers) {
|
|
const {
|
|
autoI18n,
|
|
isI18nMapped
|
|
} = runtimeConfig;
|
|
const filterPath = createPathFilter({
|
|
include: sitemap.include,
|
|
exclude: sitemap.exclude
|
|
});
|
|
const _urls = sources.flatMap((e) => e.urls).map((_e) => {
|
|
const e = preNormalizeEntry(_e, resolvers);
|
|
if (!e.loc || !filterPath(e.loc))
|
|
return false;
|
|
return e;
|
|
}).filter(Boolean);
|
|
let validI18nUrlsForTransform = [];
|
|
let warnIncorrectI18nTransformUsage = false;
|
|
const withoutPrefixPaths = {};
|
|
if (autoI18n && autoI18n.strategy !== "no_prefix") {
|
|
const localeCodes = autoI18n.locales.map((l) => l.code);
|
|
validI18nUrlsForTransform = _urls.map((_e, i) => {
|
|
if (_e._abs)
|
|
return false;
|
|
const split = splitForLocales(_e._relativeLoc, localeCodes);
|
|
let localeCode = split[0];
|
|
const pathWithoutPrefix = split[1];
|
|
if (!localeCode)
|
|
localeCode = autoI18n.defaultLocale;
|
|
const e = _e;
|
|
e._pathWithoutPrefix = pathWithoutPrefix;
|
|
const locale = autoI18n.locales.find((l) => l.code === localeCode);
|
|
if (!locale)
|
|
return false;
|
|
e._locale = locale;
|
|
e._index = i;
|
|
e._key = `${e._sitemap || ""}${e._path?.pathname || "/"}${e._path.search}`;
|
|
withoutPrefixPaths[pathWithoutPrefix] = withoutPrefixPaths[pathWithoutPrefix] || [];
|
|
if (!withoutPrefixPaths[pathWithoutPrefix].some((e2) => e2._locale.code === locale.code))
|
|
withoutPrefixPaths[pathWithoutPrefix].push(e);
|
|
return e;
|
|
}).filter(Boolean);
|
|
for (const e of validI18nUrlsForTransform) {
|
|
if (!e._i18nTransform && !e.alternatives?.length) {
|
|
const alternatives = withoutPrefixPaths[e._pathWithoutPrefix].map((u) => {
|
|
const entries = [];
|
|
if (u._locale.code === autoI18n.defaultLocale) {
|
|
entries.push({
|
|
href: u.loc,
|
|
hreflang: "x-default"
|
|
});
|
|
}
|
|
entries.push({
|
|
href: u.loc,
|
|
hreflang: u._locale._hreflang || autoI18n.defaultLocale
|
|
});
|
|
return entries;
|
|
}).flat().filter(Boolean);
|
|
if (alternatives.length)
|
|
e.alternatives = alternatives;
|
|
} else if (e._i18nTransform) {
|
|
delete e._i18nTransform;
|
|
if (autoI18n.strategy === "no_prefix") {
|
|
warnIncorrectI18nTransformUsage = true;
|
|
}
|
|
if (autoI18n.differentDomains) {
|
|
e.alternatives = [
|
|
{
|
|
// apply default locale domain
|
|
...autoI18n.locales.find((l) => [l.code, l.language].includes(autoI18n.defaultLocale)),
|
|
code: "x-default"
|
|
},
|
|
...autoI18n.locales.filter((l) => !!l.domain)
|
|
].map((locale) => {
|
|
return {
|
|
hreflang: locale._hreflang,
|
|
href: joinURL(withHttps(locale.domain), e._pathWithoutPrefix)
|
|
};
|
|
});
|
|
} else {
|
|
for (const l of autoI18n.locales) {
|
|
let loc = joinURL(`/${l.code}`, e._pathWithoutPrefix);
|
|
if (autoI18n.differentDomains || ["prefix_and_default", "prefix_except_default"].includes(autoI18n.strategy) && l.code === autoI18n.defaultLocale)
|
|
loc = e._pathWithoutPrefix;
|
|
const _sitemap = isI18nMapped ? l._sitemap : void 0;
|
|
const newEntry = preNormalizeEntry({
|
|
_sitemap,
|
|
...e,
|
|
_index: void 0,
|
|
_key: `${_sitemap || ""}${loc || "/"}${e._path.search}`,
|
|
_locale: l,
|
|
loc,
|
|
alternatives: [{ code: "x-default", _hreflang: "x-default" }, ...autoI18n.locales].map((locale) => {
|
|
const code = locale.code === "x-default" ? autoI18n.defaultLocale : locale.code;
|
|
const isDefault = locale.code === "x-default" || locale.code === autoI18n.defaultLocale;
|
|
let href = "";
|
|
if (autoI18n.strategy === "prefix") {
|
|
href = joinURL("/", code, e._pathWithoutPrefix);
|
|
} else if (["prefix_and_default", "prefix_except_default"].includes(autoI18n.strategy)) {
|
|
if (isDefault) {
|
|
href = e._pathWithoutPrefix;
|
|
} else {
|
|
href = joinURL("/", code, e._pathWithoutPrefix);
|
|
}
|
|
}
|
|
if (!filterPath(href))
|
|
return false;
|
|
return {
|
|
hreflang: locale._hreflang,
|
|
href
|
|
};
|
|
}).filter(Boolean)
|
|
}, resolvers);
|
|
if (e._locale.code === newEntry._locale.code) {
|
|
_urls[e._index] = newEntry;
|
|
e._index = void 0;
|
|
} else {
|
|
_urls.push(newEntry);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (isI18nMapped) {
|
|
e._sitemap = e._sitemap || e._locale._sitemap;
|
|
e._key = `${e._sitemap || ""}${e.loc || "/"}${e._path.search}`;
|
|
}
|
|
if (e._index)
|
|
_urls[e._index] = e;
|
|
}
|
|
}
|
|
if (warnIncorrectI18nTransformUsage) {
|
|
logger$1.warn("You're using _i18nTransform with the `no_prefix` strategy. This will cause issues with the sitemap. Please remove the _i18nTransform flag or change i18n strategy.");
|
|
}
|
|
return _urls;
|
|
}
|
|
async function buildSitemapUrls(sitemap, resolvers, runtimeConfig) {
|
|
const {
|
|
sitemaps,
|
|
// enhancing
|
|
autoI18n,
|
|
isI18nMapped,
|
|
isMultiSitemap,
|
|
// sorting
|
|
sortEntries,
|
|
// chunking
|
|
defaultSitemapsChunkSize
|
|
} = runtimeConfig;
|
|
const isChunking = typeof sitemaps.chunks !== "undefined" && !Number.isNaN(Number(sitemap.sitemapName));
|
|
function maybeSort(urls) {
|
|
return sortEntries ? sortSitemapUrls(urls) : urls;
|
|
}
|
|
function maybeSlice(urls) {
|
|
if (isChunking && defaultSitemapsChunkSize) {
|
|
const chunk = Number(sitemap.sitemapName);
|
|
return urls.slice(chunk * defaultSitemapsChunkSize, (chunk + 1) * defaultSitemapsChunkSize);
|
|
}
|
|
return urls;
|
|
}
|
|
if (autoI18n?.differentDomains) {
|
|
const domain = autoI18n.locales.find((e) => [e.language, e.code].includes(sitemap.sitemapName))?.domain;
|
|
if (domain) {
|
|
const _tester = resolvers.canonicalUrlResolver;
|
|
resolvers.canonicalUrlResolver = (path) => resolveSitePath(path, {
|
|
absolute: true,
|
|
withBase: false,
|
|
siteUrl: withHttps(domain),
|
|
trailingSlash: _tester("/test/").endsWith("/"),
|
|
base: "/"
|
|
});
|
|
}
|
|
}
|
|
const sources = sitemap.includeAppSources ? await globalSitemapSources() : [];
|
|
sources.push(...await childSitemapSources(sitemap));
|
|
const resolvedSources = await resolveSitemapSources(sources, resolvers.event);
|
|
const enhancedUrls = resolveSitemapEntries(sitemap, resolvedSources, { autoI18n, isI18nMapped }, resolvers);
|
|
const filteredUrls = enhancedUrls.filter((e) => {
|
|
if (isMultiSitemap && e._sitemap && sitemap.sitemapName)
|
|
return e._sitemap === sitemap.sitemapName;
|
|
return true;
|
|
});
|
|
const sortedUrls = maybeSort(filteredUrls);
|
|
return maybeSlice(sortedUrls);
|
|
}
|
|
function urlsToXml(urls, resolvers, { version, xsl, credits, minify }) {
|
|
const urlset = urls.map((e) => {
|
|
const keys = Object.keys(e).filter((k) => !k.startsWith("_"));
|
|
return [
|
|
" <url>",
|
|
keys.map((k) => handleEntry(k, e)).filter(Boolean).join("\n"),
|
|
" </url>"
|
|
].join("\n");
|
|
});
|
|
return wrapSitemapXml([
|
|
'<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd http://www.google.com/schemas/sitemap-image/1.1 http://www.google.com/schemas/sitemap-image/1.1/sitemap-image.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
|
|
urlset.join("\n"),
|
|
"</urlset>"
|
|
], resolvers, { version, xsl, credits, minify });
|
|
}
|
|
|
|
function useNitroUrlResolvers(e) {
|
|
const canonicalQuery = getQuery$1(e).canonical;
|
|
const isShowingCanonical = typeof canonicalQuery !== "undefined" && canonicalQuery !== "false";
|
|
const siteConfig = useSiteConfig(e);
|
|
return {
|
|
event: e,
|
|
fixSlashes: (path) => fixSlashes(siteConfig.trailingSlash, path),
|
|
// we need these as they depend on the nitro event
|
|
canonicalUrlResolver: createSitePathResolver(e, {
|
|
canonical: isShowingCanonical || false,
|
|
absolute: true,
|
|
withBase: true
|
|
}),
|
|
relativeBaseUrlResolver: createSitePathResolver(e, { absolute: false, withBase: true })
|
|
};
|
|
}
|
|
async function createSitemap(event, definition, runtimeConfig) {
|
|
const { sitemapName } = definition;
|
|
const nitro = useNitroApp();
|
|
const resolvers = useNitroUrlResolvers(event);
|
|
let sitemapUrls = await buildSitemapUrls(definition, resolvers, runtimeConfig);
|
|
const routeRuleMatcher = createNitroRouteRuleMatcher();
|
|
const { autoI18n } = runtimeConfig;
|
|
sitemapUrls = sitemapUrls.map((u) => {
|
|
const path = u._path?.pathname || u.loc;
|
|
if (!getPathRobotConfig(event, { path, skipSiteIndexable: true }).indexable)
|
|
return false;
|
|
let routeRules = routeRuleMatcher(path);
|
|
if (autoI18n?.locales && autoI18n?.strategy !== "no_prefix") {
|
|
const match = splitForLocales(path, autoI18n.locales.map((l) => l.code));
|
|
const pathWithoutPrefix = match[1];
|
|
if (pathWithoutPrefix && pathWithoutPrefix !== path)
|
|
routeRules = defu$1(routeRules, routeRuleMatcher(pathWithoutPrefix));
|
|
}
|
|
if (routeRules.sitemap === false)
|
|
return false;
|
|
if (typeof routeRules.index !== "undefined" && !routeRules.index || typeof routeRules.robots !== "undefined" && !routeRules.robots) {
|
|
return false;
|
|
}
|
|
const hasRobotsDisabled = Object.entries(routeRules.headers || {}).some(([name, value]) => name.toLowerCase() === "x-robots-tag" && value.toLowerCase().includes("noindex"));
|
|
if (routeRules.redirect || hasRobotsDisabled)
|
|
return false;
|
|
return routeRules.sitemap ? defu$1(u, routeRules.sitemap) : u;
|
|
}).filter(Boolean);
|
|
const resolvedCtx = {
|
|
urls: sitemapUrls,
|
|
sitemapName
|
|
};
|
|
await nitro.hooks.callHook("sitemap:resolved", resolvedCtx);
|
|
const maybeSort = (urls2) => runtimeConfig.sortEntries ? sortSitemapUrls(urls2) : urls2;
|
|
const normalizedPreDedupe = resolvedCtx.urls.map((e) => normaliseEntry(e, definition.defaults, resolvers));
|
|
const urls = maybeSort(mergeOnKey(normalizedPreDedupe, "_key").map((e) => normaliseEntry(e, definition.defaults, resolvers)));
|
|
const sitemap = urlsToXml(urls, resolvers, runtimeConfig);
|
|
const ctx = { sitemap, sitemapName };
|
|
await nitro.hooks.callHook("sitemap:output", ctx);
|
|
setHeader(event, "Content-Type", "text/xml; charset=UTF-8");
|
|
if (runtimeConfig.cacheMaxAgeSeconds)
|
|
setHeader(event, "Cache-Control", `public, max-age=${runtimeConfig.cacheMaxAgeSeconds}, must-revalidate`);
|
|
else
|
|
setHeader(event, "Cache-Control", `no-cache, no-store`);
|
|
event.context._isSitemap = true;
|
|
return ctx.sitemap;
|
|
}
|
|
|
|
const _y8wONh = defineEventHandler(async (e) => {
|
|
const runtimeConfig = useSimpleSitemapRuntimeConfig();
|
|
const { sitemaps } = runtimeConfig;
|
|
if ("index" in sitemaps) {
|
|
return sendRedirect(e, withBase("/sitemap_index.xml", useRuntimeConfig().app.baseURL), 302 );
|
|
}
|
|
return createSitemap(e, Object.values(sitemaps)[0], runtimeConfig);
|
|
});
|
|
|
|
const _X0MPH8 = defineEventHandler(async (e) => {
|
|
const nitro = useNitroApp();
|
|
const { indexable, hints } = getSiteRobotConfig(e);
|
|
const { credits, usingNuxtContent, cacheControl } = useRuntimeConfig(e)["nuxt-robots"];
|
|
let robotsTxtCtx = {
|
|
sitemaps: [],
|
|
groups: [
|
|
{
|
|
allow: [],
|
|
comment: [],
|
|
userAgent: ["*"],
|
|
disallow: ["/"]
|
|
}
|
|
]
|
|
};
|
|
if (indexable) {
|
|
robotsTxtCtx = await resolveRobotsTxtContext(e);
|
|
robotsTxtCtx.sitemaps = [...new Set(
|
|
asArray(robotsTxtCtx.sitemaps).map((s) => !s.startsWith("http") ? withSiteUrl(e, s, { withBase: true}) : s)
|
|
)];
|
|
if (usingNuxtContent) {
|
|
const contentWithRobotRules = await e.$fetch("/__robots__/nuxt-content.json", {
|
|
headers: {
|
|
Accept: "application/json"
|
|
}
|
|
});
|
|
for (const group of robotsTxtCtx.groups) {
|
|
if (group.userAgent.includes("*")) {
|
|
group.disallow.push(...contentWithRobotRules);
|
|
group.disallow = group.disallow.filter(Boolean);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
let robotsTxt = generateRobotsTxt(robotsTxtCtx);
|
|
if (hints.length) {
|
|
robotsTxt += `
|
|
# DEVELOPMENT HINTS:
|
|
# - ${hints.join("\n# - ")}
|
|
`;
|
|
}
|
|
if (credits) {
|
|
robotsTxt = [
|
|
`# START nuxt-robots (${indexable ? "indexable" : "indexing disabled"})`,
|
|
robotsTxt,
|
|
"# END nuxt-robots"
|
|
].filter(Boolean).join("\n");
|
|
}
|
|
setHeader(e, "Content-Type", "text/plain; charset=utf-8");
|
|
setHeader(e, "Cache-Control", "no-store" );
|
|
const hookCtx = { robotsTxt, e };
|
|
await nitro.hooks.callHook("robots:robots-txt", hookCtx);
|
|
return hookCtx.robotsTxt;
|
|
});
|
|
|
|
const _o5j3Ec = defineEventHandler(async (e) => {
|
|
if (e.path === "/robots.txt" || e.path.startsWith("/__") || e.path.startsWith("/api") || e.path.startsWith("/_nuxt"))
|
|
return;
|
|
const robotConfig = getPathRobotConfig(e);
|
|
const nuxtRobotsConfig = useRuntimeConfig(e)["nuxt-robots"];
|
|
if (nuxtRobotsConfig) {
|
|
const { header } = nuxtRobotsConfig;
|
|
if (header) {
|
|
setHeader(e, "X-Robots-Tag", robotConfig.rule);
|
|
}
|
|
e.context.robots = robotConfig;
|
|
}
|
|
});
|
|
|
|
const _7LGL4G = defineEventHandler(async (e) => {
|
|
const content = [];
|
|
try {
|
|
content.push(...await serverQueryContent(e).find());
|
|
} catch (e2) {
|
|
logger.error("Error querying Nuxt content", e2);
|
|
}
|
|
return content.map((c) => {
|
|
if (c._draft || c._extension !== "md" || c._partial)
|
|
return false;
|
|
if (c.path) {
|
|
if (String(c.robots) === "false" || String(c.indexable) === "false" || String(c.index) === "false")
|
|
return c.path;
|
|
}
|
|
return false;
|
|
}).filter(Boolean);
|
|
});
|
|
|
|
const _LHXw1s = defineEventHandler(async (e) => {
|
|
const runtimeConfig = useRuntimeConfig(e)["nuxt-robots"];
|
|
const { indexable, hints } = getSiteRobotConfig(e);
|
|
const siteConfig = useSiteConfig(e);
|
|
const robotsTxt = await e.$fetch("/robots.txt", {
|
|
query: getQuery$1(e)
|
|
});
|
|
return {
|
|
robotsTxt,
|
|
indexable,
|
|
hints,
|
|
runtimeConfig,
|
|
siteConfig: {
|
|
url: siteConfig.url,
|
|
env: siteConfig.env,
|
|
indexable: siteConfig.indexable
|
|
}
|
|
};
|
|
});
|
|
|
|
const _TYIwho = defineEventHandler(async (e) => {
|
|
const path = getQuery$1(e).path;
|
|
return getPathRobotConfig(e, {
|
|
path
|
|
});
|
|
});
|
|
|
|
const VueResolver = (_, value) => {
|
|
return isRef(value) ? toValue(value) : value;
|
|
};
|
|
|
|
const headSymbol = "usehead";
|
|
function vueInstall(head) {
|
|
const plugin = {
|
|
install(app) {
|
|
app.config.globalProperties.$unhead = head;
|
|
app.config.globalProperties.$head = head;
|
|
app.provide(headSymbol, head);
|
|
}
|
|
};
|
|
return plugin.install;
|
|
}
|
|
|
|
function resolveUnrefHeadInput(input) {
|
|
return walkResolver(input, VueResolver);
|
|
}
|
|
|
|
function createHead(options = {}) {
|
|
const head = createHead$1({
|
|
...options,
|
|
propResolvers: [VueResolver]
|
|
});
|
|
head.install = vueInstall(head);
|
|
return head;
|
|
}
|
|
|
|
const unheadOptions = {
|
|
disableDefaults: true,
|
|
disableCapoSorting: false,
|
|
plugins: [DeprecationsPlugin, PromisesPlugin, TemplateParamsPlugin, AliasSortingPlugin],
|
|
};
|
|
|
|
function createSSRContext(event) {
|
|
const ssrContext = {
|
|
url: event.path,
|
|
event,
|
|
runtimeConfig: useRuntimeConfig(event),
|
|
noSSR: event.context.nuxt?.noSSR || (false),
|
|
head: createHead(unheadOptions),
|
|
error: false,
|
|
nuxt: void 0,
|
|
/* NuxtApp */
|
|
payload: {},
|
|
_payloadReducers: /* @__PURE__ */ Object.create(null),
|
|
modules: /* @__PURE__ */ new Set()
|
|
};
|
|
return ssrContext;
|
|
}
|
|
function setSSRError(ssrContext, error) {
|
|
ssrContext.error = true;
|
|
ssrContext.payload = { error };
|
|
ssrContext.url = error.url;
|
|
}
|
|
|
|
const APP_ROOT_OPEN_TAG = `<${appRootTag}${propsToString(appRootAttrs)}>`;
|
|
const APP_ROOT_CLOSE_TAG = `</${appRootTag}>`;
|
|
const getServerEntry = () => import('file://D:/claude-project/web7-published/.nuxt//dist/server/server.mjs').then((r) => r.default || r);
|
|
const getClientManifest = () => import('file://D:/claude-project/web7-published/.nuxt//dist/server/client.manifest.mjs').then((r) => r.default || r).then((r) => typeof r === "function" ? r() : r);
|
|
const getSSRRenderer = lazyCachedFunction(async () => {
|
|
const manifest = await getClientManifest();
|
|
if (!manifest) {
|
|
throw new Error("client.manifest is not available");
|
|
}
|
|
const createSSRApp = await getServerEntry();
|
|
if (!createSSRApp) {
|
|
throw new Error("Server bundle is not available");
|
|
}
|
|
const options = {
|
|
manifest,
|
|
renderToString: renderToString$1,
|
|
buildAssetsURL
|
|
};
|
|
const renderer = createRenderer(createSSRApp, options);
|
|
async function renderToString$1(input, context) {
|
|
const html = await renderToString(input, context);
|
|
if (process.env.NUXT_VITE_NODE_OPTIONS) {
|
|
renderer.rendererContext.updateManifest(await getClientManifest());
|
|
}
|
|
return APP_ROOT_OPEN_TAG + html + APP_ROOT_CLOSE_TAG;
|
|
}
|
|
return renderer;
|
|
});
|
|
const getSPARenderer = lazyCachedFunction(async () => {
|
|
const manifest = await getClientManifest();
|
|
const spaTemplate = await Promise.resolve().then(function () { return _virtual__spaTemplate; }).then((r) => r.template).catch(() => "").then((r) => {
|
|
{
|
|
return APP_ROOT_OPEN_TAG + r + APP_ROOT_CLOSE_TAG;
|
|
}
|
|
});
|
|
const options = {
|
|
manifest,
|
|
renderToString: () => spaTemplate,
|
|
buildAssetsURL
|
|
};
|
|
const renderer = createRenderer(() => () => {
|
|
}, options);
|
|
const result = await renderer.renderToString({});
|
|
const renderToString = (ssrContext) => {
|
|
const config = useRuntimeConfig(ssrContext.event);
|
|
ssrContext.modules ||= /* @__PURE__ */ new Set();
|
|
ssrContext.payload.serverRendered = false;
|
|
ssrContext.config = {
|
|
public: config.public,
|
|
app: config.app
|
|
};
|
|
return Promise.resolve(result);
|
|
};
|
|
return {
|
|
rendererContext: renderer.rendererContext,
|
|
renderToString
|
|
};
|
|
});
|
|
function lazyCachedFunction(fn) {
|
|
let res = null;
|
|
return () => {
|
|
if (res === null) {
|
|
res = fn().catch((err) => {
|
|
res = null;
|
|
throw err;
|
|
});
|
|
}
|
|
return res;
|
|
};
|
|
}
|
|
function getRenderer(ssrContext) {
|
|
return ssrContext.noSSR ? getSPARenderer() : getSSRRenderer();
|
|
}
|
|
const getSSRStyles = lazyCachedFunction(() => Promise.resolve().then(function () { return styles$1; }).then((r) => r.default || r));
|
|
|
|
async function renderInlineStyles(usedModules) {
|
|
const styleMap = await getSSRStyles();
|
|
const inlinedStyles = /* @__PURE__ */ new Set();
|
|
for (const mod of usedModules) {
|
|
if (mod in styleMap && styleMap[mod]) {
|
|
for (const style of await styleMap[mod]()) {
|
|
inlinedStyles.add(style);
|
|
}
|
|
}
|
|
}
|
|
return Array.from(inlinedStyles).map((style) => ({ innerHTML: style }));
|
|
}
|
|
|
|
const ROOT_NODE_REGEX = new RegExp(`^<${appRootTag}[^>]*>([\\s\\S]*)<\\/${appRootTag}>$`);
|
|
function getServerComponentHTML(body) {
|
|
const match = body.match(ROOT_NODE_REGEX);
|
|
return match?.[1] || body;
|
|
}
|
|
const SSR_SLOT_TELEPORT_MARKER = /^uid=([^;]*);slot=(.*)$/;
|
|
const SSR_CLIENT_TELEPORT_MARKER = /^uid=([^;]*);client=(.*)$/;
|
|
const SSR_CLIENT_SLOT_MARKER = /^island-slot=([^;]*);(.*)$/;
|
|
function getSlotIslandResponse(ssrContext) {
|
|
if (!ssrContext.islandContext || !Object.keys(ssrContext.islandContext.slots).length) {
|
|
return void 0;
|
|
}
|
|
const response = {};
|
|
for (const [name, slot] of Object.entries(ssrContext.islandContext.slots)) {
|
|
response[name] = {
|
|
...slot,
|
|
fallback: ssrContext.teleports?.[`island-fallback=${name}`]
|
|
};
|
|
}
|
|
return response;
|
|
}
|
|
function getClientIslandResponse(ssrContext) {
|
|
if (!ssrContext.islandContext || !Object.keys(ssrContext.islandContext.components).length) {
|
|
return void 0;
|
|
}
|
|
const response = {};
|
|
for (const [clientUid, component] of Object.entries(ssrContext.islandContext.components)) {
|
|
const html = ssrContext.teleports?.[clientUid]?.replaceAll("<!--teleport start anchor-->", "") || "";
|
|
response[clientUid] = {
|
|
...component,
|
|
html,
|
|
slots: getComponentSlotTeleport(clientUid, ssrContext.teleports ?? {})
|
|
};
|
|
}
|
|
return response;
|
|
}
|
|
function getComponentSlotTeleport(clientUid, teleports) {
|
|
const entries = Object.entries(teleports);
|
|
const slots = {};
|
|
for (const [key, value] of entries) {
|
|
const match = key.match(SSR_CLIENT_SLOT_MARKER);
|
|
if (match) {
|
|
const [, id, slot] = match;
|
|
if (!slot || clientUid !== id) {
|
|
continue;
|
|
}
|
|
slots[slot] = value;
|
|
}
|
|
}
|
|
return slots;
|
|
}
|
|
function replaceIslandTeleports(ssrContext, html) {
|
|
const { teleports, islandContext } = ssrContext;
|
|
if (islandContext || !teleports) {
|
|
return html;
|
|
}
|
|
for (const key in teleports) {
|
|
const matchClientComp = key.match(SSR_CLIENT_TELEPORT_MARKER);
|
|
if (matchClientComp) {
|
|
const [, uid, clientId] = matchClientComp;
|
|
if (!uid || !clientId) {
|
|
continue;
|
|
}
|
|
html = html.replace(new RegExp(` data-island-uid="${uid}" data-island-component="${clientId}"[^>]*>`), (full) => {
|
|
return full + teleports[key];
|
|
});
|
|
continue;
|
|
}
|
|
const matchSlot = key.match(SSR_SLOT_TELEPORT_MARKER);
|
|
if (matchSlot) {
|
|
const [, uid, slot] = matchSlot;
|
|
if (!uid || !slot) {
|
|
continue;
|
|
}
|
|
html = html.replace(new RegExp(` data-island-uid="${uid}" data-island-slot="${slot}"[^>]*>`), (full) => {
|
|
return full + teleports[key];
|
|
});
|
|
}
|
|
}
|
|
return html;
|
|
}
|
|
|
|
const ISLAND_SUFFIX_RE = /\.json(?:\?.*)?$/;
|
|
const _SxA8c9 = defineEventHandler(async (event) => {
|
|
const nitroApp = useNitroApp();
|
|
setResponseHeaders(event, {
|
|
"content-type": "application/json;charset=utf-8",
|
|
"x-powered-by": "Nuxt"
|
|
});
|
|
const islandContext = await getIslandContext(event);
|
|
const ssrContext = {
|
|
...createSSRContext(event),
|
|
islandContext,
|
|
noSSR: false,
|
|
url: islandContext.url
|
|
};
|
|
const renderer = await getSSRRenderer();
|
|
const renderResult = await renderer.renderToString(ssrContext).catch(async (error) => {
|
|
await ssrContext.nuxt?.hooks.callHook("app:error", error);
|
|
throw error;
|
|
});
|
|
const inlinedStyles = await renderInlineStyles(ssrContext.modules ?? []);
|
|
await ssrContext.nuxt?.hooks.callHook("app:rendered", { ssrContext, renderResult });
|
|
if (inlinedStyles.length) {
|
|
ssrContext.head.push({ style: inlinedStyles });
|
|
}
|
|
{
|
|
const { styles } = getRequestDependencies(ssrContext, renderer.rendererContext);
|
|
const link = [];
|
|
for (const resource of Object.values(styles)) {
|
|
if ("inline" in getQuery(resource.file)) {
|
|
continue;
|
|
}
|
|
if (resource.file.includes("scoped") && !resource.file.includes("pages/")) {
|
|
link.push({ rel: "stylesheet", href: renderer.rendererContext.buildAssetsURL(resource.file), crossorigin: "" });
|
|
}
|
|
}
|
|
if (link.length) {
|
|
ssrContext.head.push({ link }, { mode: "server" });
|
|
}
|
|
}
|
|
const islandHead = {};
|
|
for (const entry of ssrContext.head.entries.values()) {
|
|
for (const [key, value] of Object.entries(resolveUnrefHeadInput(entry.input))) {
|
|
const currentValue = islandHead[key];
|
|
if (Array.isArray(currentValue)) {
|
|
currentValue.push(...value);
|
|
}
|
|
islandHead[key] = value;
|
|
}
|
|
}
|
|
islandHead.link ||= [];
|
|
islandHead.style ||= [];
|
|
const islandResponse = {
|
|
id: islandContext.id,
|
|
head: islandHead,
|
|
html: getServerComponentHTML(renderResult.html),
|
|
components: getClientIslandResponse(ssrContext),
|
|
slots: getSlotIslandResponse(ssrContext)
|
|
};
|
|
await nitroApp.hooks.callHook("render:island", islandResponse, { event, islandContext });
|
|
return islandResponse;
|
|
});
|
|
async function getIslandContext(event) {
|
|
let url = event.path || "";
|
|
const componentParts = url.substring("/__nuxt_island".length + 1).replace(ISLAND_SUFFIX_RE, "").split("_");
|
|
const hashId = componentParts.length > 1 ? componentParts.pop() : void 0;
|
|
const componentName = componentParts.join("_");
|
|
const context = event.method === "GET" ? getQuery$1(event) : await readBody(event);
|
|
const ctx = {
|
|
url: "/",
|
|
...context,
|
|
id: hashId,
|
|
name: componentName,
|
|
props: destr$1(context.props) || {},
|
|
slots: {},
|
|
components: {}
|
|
};
|
|
return ctx;
|
|
}
|
|
|
|
const __xvGBc = defineEventHandler(async (event) => {
|
|
const { getContentQuery } = await Promise.resolve().then(function () { return query; });
|
|
const { serverQueryContent } = await Promise.resolve().then(function () { return storage; });
|
|
const query$1 = getContentQuery(event);
|
|
const { advanceQuery } = useRuntimeConfig().public.content.experimental;
|
|
if (query$1.first) {
|
|
let contentQuery = serverQueryContent(event, query$1);
|
|
if (!advanceQuery) {
|
|
contentQuery = contentQuery.withDirConfig();
|
|
}
|
|
const content = await contentQuery.findOne();
|
|
const _result = advanceQuery ? content?.result : content;
|
|
const missing = !_result && !content?.dirConfig?.navigation?.redirect && !content?._dir?.navigation?.redirect;
|
|
if (missing) {
|
|
throw createError({
|
|
statusMessage: "Document not found!",
|
|
statusCode: 404,
|
|
data: {
|
|
description: "Could not find document for the given query.",
|
|
query: query$1
|
|
}
|
|
});
|
|
}
|
|
return content;
|
|
}
|
|
if (query$1.count) {
|
|
return serverQueryContent(event, query$1).count();
|
|
}
|
|
return serverQueryContent(event, query$1).find();
|
|
});
|
|
|
|
const _MlATf7 = defineEventHandler(async (event) => {
|
|
const { getContentIndex } = await Promise.resolve().then(function () { return contentIndex; });
|
|
const { cacheStorage, serverQueryContent } = await Promise.resolve().then(function () { return storage; });
|
|
const { content } = useRuntimeConfig();
|
|
const now = Date.now();
|
|
const contents = await serverQueryContent(event).find();
|
|
await getContentIndex(event);
|
|
const navigation = await $fetch(`${content.api.baseURL}/navigation`);
|
|
await cacheStorage().setItem("content-navigation.json", navigation);
|
|
return {
|
|
generatedAt: now,
|
|
generateTime: Date.now() - now,
|
|
contents: content.experimental.cacheContents ? contents : [],
|
|
navigation
|
|
};
|
|
});
|
|
|
|
const _QUrtTu = defineEventHandler(async (event) => {
|
|
const { getContentQuery } = await Promise.resolve().then(function () { return query; });
|
|
const { cacheStorage, serverQueryContent } = await Promise.resolve().then(function () { return storage; });
|
|
const { createNav } = await Promise.resolve().then(function () { return navigation; });
|
|
const query$1 = getContentQuery(event);
|
|
if (!isPreview(event) && Object.keys(query$1).length === 0) {
|
|
const cache = await cacheStorage().getItem("content-navigation.json");
|
|
if (cache) {
|
|
return cache;
|
|
}
|
|
}
|
|
const contents = await serverQueryContent(event, query$1).where({
|
|
/**
|
|
* Partial contents are not included in the navigation
|
|
* A partial content is a content that has `_` prefix in its path
|
|
*/
|
|
_partial: false,
|
|
/**
|
|
* Exclude any pages which have opted out of navigation via frontmatter.
|
|
*/
|
|
navigation: {
|
|
$ne: false
|
|
}
|
|
}).find();
|
|
const _locale = (query$1?.where || []).find((w) => w._locale)?._locale;
|
|
const dirConfigs = await serverQueryContent(event, _locale ? { where: [{ _locale }] } : void 0).where({ _path: /\/_dir$/i, _partial: true }).find();
|
|
const configs = (dirConfigs?.result || dirConfigs).reduce((configs2, conf) => {
|
|
if (conf.title?.toLowerCase() === "dir") {
|
|
conf.title = void 0;
|
|
}
|
|
const key = conf._path.split("/").slice(0, -1).join("/") || "/";
|
|
configs2[key] = {
|
|
...conf,
|
|
// Extract meta from body. (non MD files)
|
|
...conf.body
|
|
};
|
|
return configs2;
|
|
}, {});
|
|
return createNav(contents?.result || contents, configs);
|
|
});
|
|
|
|
const _lazy_xC2Fbg = () => Promise.resolve().then(function () { return renderer$1; });
|
|
const _lazy_gQ0rzZ = () => Promise.resolve().then(function () { return sitemap_index_xml$1; });
|
|
const _lazy_uRteeS = () => Promise.resolve().then(function () { return _sitemap__xml$1; });
|
|
|
|
const handlers = [
|
|
{ route: '', handler: _pThBIC, lazy: false, middleware: true, method: undefined },
|
|
{ route: '/__nuxt_error', handler: _lazy_xC2Fbg, lazy: true, middleware: false, method: undefined },
|
|
{ route: '', handler: _3U292r, lazy: false, middleware: true, method: undefined },
|
|
{ route: '/__site-config__/debug.json', handler: _GlKRyj, lazy: false, middleware: false, method: undefined },
|
|
{ route: '/__sitemap__/nuxt-content-urls.json', handler: _yEFF8G, lazy: false, middleware: false, method: undefined },
|
|
{ route: '/sitemap_index.xml', handler: _lazy_gQ0rzZ, lazy: true, middleware: false, method: undefined },
|
|
{ route: '/__sitemap__/**:sitemap', handler: _lazy_uRteeS, lazy: true, middleware: false, method: undefined },
|
|
{ route: '/__sitemap__/debug.json', handler: _waepPN, lazy: false, middleware: false, method: undefined },
|
|
{ route: '/__sitemap__/style.xsl', handler: _zSetAt, lazy: false, middleware: false, method: undefined },
|
|
{ route: '/sitemap.xml', handler: _y8wONh, lazy: false, middleware: false, method: undefined },
|
|
{ route: '/robots.txt', handler: _X0MPH8, lazy: false, middleware: false, method: undefined },
|
|
{ route: '', handler: _o5j3Ec, lazy: false, middleware: false, method: undefined },
|
|
{ route: '/__robots__/nuxt-content.json', handler: _7LGL4G, lazy: false, middleware: false, method: undefined },
|
|
{ route: '/__robots__/debug.json', handler: _LHXw1s, lazy: false, middleware: false, method: undefined },
|
|
{ route: '/__robots__/debug-path.json', handler: _TYIwho, lazy: false, middleware: false, method: undefined },
|
|
{ route: '/__nuxt_island/**', handler: _SxA8c9, lazy: false, middleware: false, method: undefined },
|
|
{ route: '/api/_content/query/:qid/**:params', handler: __xvGBc, lazy: false, middleware: false, method: "get" },
|
|
{ route: '/api/_content/query/:qid', handler: __xvGBc, lazy: false, middleware: false, method: "get" },
|
|
{ route: '/api/_content/query', handler: __xvGBc, lazy: false, middleware: false, method: "get" },
|
|
{ route: '/api/_content/cache.json', handler: _MlATf7, lazy: false, middleware: false, method: "get" },
|
|
{ route: '/api/_content/navigation/:qid/**:params', handler: _QUrtTu, lazy: false, middleware: false, method: "get" },
|
|
{ route: '/api/_content/navigation/:qid', handler: _QUrtTu, lazy: false, middleware: false, method: "get" },
|
|
{ route: '/api/_content/navigation', handler: _QUrtTu, lazy: false, middleware: false, method: "get" },
|
|
{ route: '/**', handler: _lazy_xC2Fbg, lazy: true, middleware: false, method: undefined }
|
|
];
|
|
|
|
function createNitroApp() {
|
|
const config = useRuntimeConfig();
|
|
const hooks = createHooks();
|
|
const captureError = (error, context = {}) => {
|
|
const promise = hooks.callHookParallel("error", error, context).catch((error_) => {
|
|
console.error("Error while capturing another error", error_);
|
|
});
|
|
if (context.event && isEvent(context.event)) {
|
|
const errors = context.event.context.nitro?.errors;
|
|
if (errors) {
|
|
errors.push({ error, context });
|
|
}
|
|
if (context.event.waitUntil) {
|
|
context.event.waitUntil(promise);
|
|
}
|
|
}
|
|
};
|
|
const h3App = createApp({
|
|
debug: destr(true),
|
|
onError: (error, event) => {
|
|
captureError(error, { event, tags: ["request"] });
|
|
return errorHandler(error, event);
|
|
},
|
|
onRequest: async (event) => {
|
|
event.context.nitro = event.context.nitro || { errors: [] };
|
|
const fetchContext = event.node.req?.__unenv__;
|
|
if (fetchContext?._platform) {
|
|
event.context = {
|
|
_platform: fetchContext?._platform,
|
|
// #3335
|
|
...fetchContext._platform,
|
|
...event.context
|
|
};
|
|
}
|
|
if (!event.context.waitUntil && fetchContext?.waitUntil) {
|
|
event.context.waitUntil = fetchContext.waitUntil;
|
|
}
|
|
event.fetch = (req, init) => fetchWithEvent(event, req, init, { fetch: localFetch });
|
|
event.$fetch = (req, init) => fetchWithEvent(event, req, init, {
|
|
fetch: $fetch
|
|
});
|
|
event.waitUntil = (promise) => {
|
|
if (!event.context.nitro._waitUntilPromises) {
|
|
event.context.nitro._waitUntilPromises = [];
|
|
}
|
|
event.context.nitro._waitUntilPromises.push(promise);
|
|
if (event.context.waitUntil) {
|
|
event.context.waitUntil(promise);
|
|
}
|
|
};
|
|
event.captureError = (error, context) => {
|
|
captureError(error, { event, ...context });
|
|
};
|
|
await nitroApp$1.hooks.callHook("request", event).catch((error) => {
|
|
captureError(error, { event, tags: ["request"] });
|
|
});
|
|
},
|
|
onBeforeResponse: async (event, response) => {
|
|
await nitroApp$1.hooks.callHook("beforeResponse", event, response).catch((error) => {
|
|
captureError(error, { event, tags: ["request", "response"] });
|
|
});
|
|
},
|
|
onAfterResponse: async (event, response) => {
|
|
await nitroApp$1.hooks.callHook("afterResponse", event, response).catch((error) => {
|
|
captureError(error, { event, tags: ["request", "response"] });
|
|
});
|
|
}
|
|
});
|
|
const router = createRouter$1({
|
|
preemptive: true
|
|
});
|
|
const nodeHandler = toNodeListener(h3App);
|
|
const localCall = (aRequest) => callNodeRequestHandler(
|
|
nodeHandler,
|
|
aRequest
|
|
);
|
|
const localFetch = (input, init) => {
|
|
if (!input.toString().startsWith("/")) {
|
|
return globalThis.fetch(input, init);
|
|
}
|
|
return fetchNodeRequestHandler(
|
|
nodeHandler,
|
|
input,
|
|
init
|
|
).then((response) => normalizeFetchResponse(response));
|
|
};
|
|
const $fetch = createFetch({
|
|
fetch: localFetch,
|
|
Headers: Headers$1,
|
|
defaults: { baseURL: config.app.baseURL }
|
|
});
|
|
globalThis.$fetch = $fetch;
|
|
h3App.use(createRouteRulesHandler({ localFetch }));
|
|
for (const h of handlers) {
|
|
let handler = h.lazy ? lazyEventHandler(h.handler) : h.handler;
|
|
if (h.middleware || !h.route) {
|
|
const middlewareBase = (config.app.baseURL + (h.route || "/")).replace(
|
|
/\/+/g,
|
|
"/"
|
|
);
|
|
h3App.use(middlewareBase, handler);
|
|
} else {
|
|
const routeRules = getRouteRulesForPath(
|
|
h.route.replace(/:\w+|\*\*/g, "_")
|
|
);
|
|
if (routeRules.cache) {
|
|
handler = cachedEventHandler(handler, {
|
|
group: "nitro/routes",
|
|
...routeRules.cache
|
|
});
|
|
}
|
|
router.use(h.route, handler, h.method);
|
|
}
|
|
}
|
|
h3App.use(config.app.baseURL, router.handler);
|
|
const app = {
|
|
hooks,
|
|
h3App,
|
|
router,
|
|
localCall,
|
|
localFetch,
|
|
captureError
|
|
};
|
|
return app;
|
|
}
|
|
function runNitroPlugins(nitroApp2) {
|
|
for (const plugin of plugins) {
|
|
try {
|
|
plugin(nitroApp2);
|
|
} catch (error) {
|
|
nitroApp2.captureError(error, { tags: ["plugin"] });
|
|
throw error;
|
|
}
|
|
}
|
|
}
|
|
const nitroApp$1 = createNitroApp();
|
|
function useNitroApp() {
|
|
return nitroApp$1;
|
|
}
|
|
runNitroPlugins(nitroApp$1);
|
|
|
|
if (!globalThis.crypto) {
|
|
globalThis.crypto = nodeCrypto;
|
|
}
|
|
const { NITRO_NO_UNIX_SOCKET, NITRO_DEV_WORKER_ID } = process.env;
|
|
trapUnhandledNodeErrors();
|
|
parentPort?.on("message", (msg) => {
|
|
if (msg && msg.event === "shutdown") {
|
|
shutdown();
|
|
}
|
|
});
|
|
const nitroApp = useNitroApp();
|
|
const server = new Server(toNodeListener(nitroApp.h3App));
|
|
let listener;
|
|
listen().catch(() => listen(
|
|
true
|
|
/* use random port */
|
|
)).catch((error) => {
|
|
console.error("Dev worker failed to listen:", error);
|
|
return shutdown();
|
|
});
|
|
nitroApp.router.get(
|
|
"/_nitro/tasks",
|
|
defineEventHandler(async (event) => {
|
|
const _tasks = await Promise.all(
|
|
Object.entries(tasks).map(async ([name, task]) => {
|
|
const _task = await task.resolve?.();
|
|
return [name, { description: _task?.meta?.description }];
|
|
})
|
|
);
|
|
return {
|
|
tasks: Object.fromEntries(_tasks),
|
|
scheduledTasks
|
|
};
|
|
})
|
|
);
|
|
nitroApp.router.use(
|
|
"/_nitro/tasks/:name",
|
|
defineEventHandler(async (event) => {
|
|
const name = getRouterParam(event, "name");
|
|
const payload = {
|
|
...getQuery$1(event),
|
|
...await readBody(event).then((r) => r?.payload).catch(() => ({}))
|
|
};
|
|
return await runTask(name, { payload });
|
|
})
|
|
);
|
|
function listen(useRandomPort = Boolean(
|
|
NITRO_NO_UNIX_SOCKET || process.versions.webcontainer || "Bun" in globalThis && process.platform === "win32"
|
|
)) {
|
|
return new Promise((resolve, reject) => {
|
|
try {
|
|
listener = server.listen(useRandomPort ? 0 : getSocketAddress(), () => {
|
|
const address = server.address();
|
|
parentPort?.postMessage({
|
|
event: "listen",
|
|
address: typeof address === "string" ? { socketPath: address } : { host: "localhost", port: address?.port }
|
|
});
|
|
resolve();
|
|
});
|
|
} catch (error) {
|
|
reject(error);
|
|
}
|
|
});
|
|
}
|
|
function getSocketAddress() {
|
|
const socketName = `nitro-worker-${process.pid}-${threadId}-${NITRO_DEV_WORKER_ID}-${Math.round(Math.random() * 1e4)}.sock`;
|
|
if (process.platform === "win32") {
|
|
return join(String.raw`\\.\pipe`, socketName);
|
|
}
|
|
if (process.platform === "linux") {
|
|
const nodeMajor = Number.parseInt(process.versions.node.split(".")[0], 10);
|
|
if (nodeMajor >= 20) {
|
|
return `\0${socketName}`;
|
|
}
|
|
}
|
|
return join(tmpdir(), socketName);
|
|
}
|
|
async function shutdown() {
|
|
server.closeAllConnections?.();
|
|
await Promise.all([
|
|
new Promise((resolve) => listener?.close(resolve)),
|
|
nitroApp.hooks.callHook("close").catch(console.error)
|
|
]);
|
|
parentPort?.postMessage({ event: "exit" });
|
|
}
|
|
|
|
const _messages = { "appName": "Nuxt", "version": "", "statusCode": 500, "statusMessage": "Server error", "description": "An error occurred in the application and the page could not be served. If you are the application owner, check your server logs for details.", "stack": "" };
|
|
const template$1 = (messages) => {
|
|
messages = { ..._messages, ...messages };
|
|
return '<!DOCTYPE html><html lang="en"><head><title>' + escapeHtml(messages.statusCode) + " - " + escapeHtml(messages.statusMessage || "Internal Server Error") + `</title><meta charset="utf-8"><meta content="width=device-width,initial-scale=1.0,minimum-scale=1.0" name="viewport"><style>.spotlight{background:linear-gradient(45deg,#00dc82,#36e4da 50%,#0047e1);bottom:-40vh;filter:blur(30vh);height:60vh;opacity:.8}*,:after,:before{border-color:var(--un-default-border-color,#e5e7eb);border-style:solid;border-width:0;box-sizing:border-box}:after,:before{--un-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-moz-tab-size:4;tab-size:4;-webkit-tap-highlight-color:transparent}body{line-height:inherit;margin:0}h1{font-size:inherit;font-weight:inherit}h1,p{margin:0}*,:after,:before{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 transparent;--un-ring-shadow:0 0 transparent;--un-shadow-inset: ;--un-shadow:0 0 transparent;--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgba(147,197,253,.5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }.pointer-events-none{pointer-events:none}.fixed{position:fixed}.left-0{left:0}.right-0{right:0}.z-10{z-index:10}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.h-auto{height:auto}.min-h-screen{min-height:100vh}.flex{display:flex}.flex-1{flex:1 1 0%}.flex-col{flex-direction:column}.overflow-y-auto{overflow-y:auto}.rounded-t-md{border-top-left-radius:.375rem;border-top-right-radius:.375rem}.bg-black\\/5{background-color:#0000000d}.bg-white{--un-bg-opacity:1;background-color:rgb(255 255 255/var(--un-bg-opacity))}.p-8{padding:2rem}.px-10{padding-left:2.5rem;padding-right:2.5rem}.pt-14{padding-top:3.5rem}.text-6xl{font-size:3.75rem;line-height:1}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-black{--un-text-opacity:1;color:rgb(0 0 0/var(--un-text-opacity))}.font-light{font-weight:300}.font-medium{font-weight:500}.leading-tight{line-height:1.25}.font-sans{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@media (prefers-color-scheme:dark){.dark\\:bg-black{--un-bg-opacity:1;background-color:rgb(0 0 0/var(--un-bg-opacity))}.dark\\:bg-white\\/10{background-color:#ffffff1a}.dark\\:text-white{--un-text-opacity:1;color:rgb(255 255 255/var(--un-text-opacity))}}@media (min-width:640px){.sm\\:text-2xl{font-size:1.5rem;line-height:2rem}.sm\\:text-8xl{font-size:6rem;line-height:1}}</style><script>!function(){const e=document.createElement("link").relList;if(!(e&&e.supports&&e.supports("modulepreload"))){for(const e of document.querySelectorAll('link[rel="modulepreload"]'))r(e);new MutationObserver((e=>{for(const o of e)if("childList"===o.type)for(const e of o.addedNodes)"LINK"===e.tagName&&"modulepreload"===e.rel&&r(e)})).observe(document,{childList:!0,subtree:!0})}function r(e){if(e.ep)return;e.ep=!0;const r=function(e){const r={};return e.integrity&&(r.integrity=e.integrity),e.referrerPolicy&&(r.referrerPolicy=e.referrerPolicy),"use-credentials"===e.crossOrigin?r.credentials="include":"anonymous"===e.crossOrigin?r.credentials="omit":r.credentials="same-origin",r}(e);fetch(e.href,r)}}();<\/script></head><body class="antialiased bg-white dark:bg-black dark:text-white flex flex-col font-sans min-h-screen pt-14 px-10 text-black"><div class="fixed left-0 pointer-events-none right-0 spotlight"></div><h1 class="font-medium mb-6 sm:text-8xl text-6xl">` + escapeHtml(messages.statusCode) + '</h1><p class="font-light leading-tight mb-8 sm:text-2xl text-xl">' + escapeHtml(messages.description) + '</p><div class="bg-black/5 bg-white dark:bg-white/10 flex-1 h-auto overflow-y-auto rounded-t-md"><div class="font-light leading-tight p-8 text-xl z-10">' + escapeHtml(messages.stack) + "</div></div></body></html>";
|
|
};
|
|
|
|
const errorDev = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
__proto__: null,
|
|
template: template$1
|
|
}, Symbol.toStringTag, { value: 'Module' }));
|
|
|
|
const remarkPlugins = {
|
|
'remark-emoji': { instance: _RemarkEmoji },
|
|
};
|
|
|
|
const rehypePlugins = {
|
|
};
|
|
|
|
const highlight = {};
|
|
|
|
const mdcImports = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
__proto__: null,
|
|
highlight: highlight,
|
|
rehypePlugins: rehypePlugins,
|
|
remarkPlugins: remarkPlugins
|
|
}, Symbol.toStringTag, { value: 'Module' }));
|
|
|
|
let configs;
|
|
function getMdcConfigs () {
|
|
if (!configs) {
|
|
configs = Promise.all([
|
|
]);
|
|
}
|
|
return configs
|
|
}
|
|
|
|
const mdcConfigs = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
__proto__: null,
|
|
getMdcConfigs: getMdcConfigs
|
|
}, Symbol.toStringTag, { value: 'Module' }));
|
|
|
|
const sources$1 = [
|
|
{
|
|
"context": {
|
|
"name": "sitemap:urls",
|
|
"description": "Set with the `sitemap.urls` config."
|
|
},
|
|
"urls": [],
|
|
"sourceType": "user"
|
|
},
|
|
{
|
|
"context": {
|
|
"name": "@nuxt/content:urls",
|
|
"description": "Generated from your markdown files.",
|
|
"tips": [
|
|
"You can provide a `sitemap` key in your markdown frontmatter to configure specific URLs. Make sure you include a `loc`."
|
|
]
|
|
},
|
|
"fetch": "/__sitemap__/nuxt-content-urls.json",
|
|
"sourceType": "app"
|
|
},
|
|
{
|
|
"context": {
|
|
"name": "nuxt:pages",
|
|
"description": "Generated from your static page files.",
|
|
"tips": [
|
|
"Can be disabled with `{ excludeAppSources: ['nuxt:pages'] }`."
|
|
]
|
|
},
|
|
"urls": [
|
|
{
|
|
"loc": "/error",
|
|
"_sitemap": "en",
|
|
"alternatives": [
|
|
{
|
|
"hreflang": "en",
|
|
"href": "/error"
|
|
},
|
|
{
|
|
"hreflang": "zh",
|
|
"href": "/zh/error"
|
|
},
|
|
{
|
|
"hreflang": "zh-hant",
|
|
"href": "/zh-hant/error"
|
|
},
|
|
{
|
|
"hreflang": "x-default",
|
|
"href": "/error"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"loc": "/zh/error",
|
|
"_sitemap": "zh",
|
|
"alternatives": [
|
|
{
|
|
"hreflang": "en",
|
|
"href": "/error"
|
|
},
|
|
{
|
|
"hreflang": "zh",
|
|
"href": "/zh/error"
|
|
},
|
|
{
|
|
"hreflang": "zh-hant",
|
|
"href": "/zh-hant/error"
|
|
},
|
|
{
|
|
"hreflang": "x-default",
|
|
"href": "/error"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"loc": "/zh-hant/error",
|
|
"_sitemap": "zh-hant",
|
|
"alternatives": [
|
|
{
|
|
"hreflang": "en",
|
|
"href": "/error"
|
|
},
|
|
{
|
|
"hreflang": "zh",
|
|
"href": "/zh/error"
|
|
},
|
|
{
|
|
"hreflang": "zh-hant",
|
|
"href": "/zh-hant/error"
|
|
},
|
|
{
|
|
"hreflang": "x-default",
|
|
"href": "/error"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"loc": "/",
|
|
"_sitemap": "en",
|
|
"alternatives": [
|
|
{
|
|
"hreflang": "en",
|
|
"href": "/"
|
|
},
|
|
{
|
|
"hreflang": "zh",
|
|
"href": "/zh"
|
|
},
|
|
{
|
|
"hreflang": "zh-hant",
|
|
"href": "/zh-hant"
|
|
},
|
|
{
|
|
"hreflang": "x-default",
|
|
"href": "/"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"loc": "/zh",
|
|
"_sitemap": "zh",
|
|
"alternatives": [
|
|
{
|
|
"hreflang": "en",
|
|
"href": "/"
|
|
},
|
|
{
|
|
"hreflang": "zh",
|
|
"href": "/zh"
|
|
},
|
|
{
|
|
"hreflang": "zh-hant",
|
|
"href": "/zh-hant"
|
|
},
|
|
{
|
|
"hreflang": "x-default",
|
|
"href": "/"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"loc": "/zh-hant",
|
|
"_sitemap": "zh-hant",
|
|
"alternatives": [
|
|
{
|
|
"hreflang": "en",
|
|
"href": "/"
|
|
},
|
|
{
|
|
"hreflang": "zh",
|
|
"href": "/zh"
|
|
},
|
|
{
|
|
"hreflang": "zh-hant",
|
|
"href": "/zh-hant"
|
|
},
|
|
{
|
|
"hreflang": "x-default",
|
|
"href": "/"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"loc": "/contact",
|
|
"_sitemap": "en",
|
|
"alternatives": [
|
|
{
|
|
"hreflang": "en",
|
|
"href": "/contact"
|
|
},
|
|
{
|
|
"hreflang": "zh",
|
|
"href": "/zh/contact"
|
|
},
|
|
{
|
|
"hreflang": "zh-hant",
|
|
"href": "/zh-hant/contact"
|
|
},
|
|
{
|
|
"hreflang": "x-default",
|
|
"href": "/contact"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"loc": "/zh/contact",
|
|
"_sitemap": "zh",
|
|
"alternatives": [
|
|
{
|
|
"hreflang": "en",
|
|
"href": "/contact"
|
|
},
|
|
{
|
|
"hreflang": "zh",
|
|
"href": "/zh/contact"
|
|
},
|
|
{
|
|
"hreflang": "zh-hant",
|
|
"href": "/zh-hant/contact"
|
|
},
|
|
{
|
|
"hreflang": "x-default",
|
|
"href": "/contact"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"loc": "/zh-hant/contact",
|
|
"_sitemap": "zh-hant",
|
|
"alternatives": [
|
|
{
|
|
"hreflang": "en",
|
|
"href": "/contact"
|
|
},
|
|
{
|
|
"hreflang": "zh",
|
|
"href": "/zh/contact"
|
|
},
|
|
{
|
|
"hreflang": "zh-hant",
|
|
"href": "/zh-hant/contact"
|
|
},
|
|
{
|
|
"hreflang": "x-default",
|
|
"href": "/contact"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"loc": "/pricing",
|
|
"_sitemap": "en",
|
|
"alternatives": [
|
|
{
|
|
"hreflang": "en",
|
|
"href": "/pricing"
|
|
},
|
|
{
|
|
"hreflang": "zh",
|
|
"href": "/zh/pricing"
|
|
},
|
|
{
|
|
"hreflang": "zh-hant",
|
|
"href": "/zh-hant/pricing"
|
|
},
|
|
{
|
|
"hreflang": "x-default",
|
|
"href": "/pricing"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"loc": "/zh/pricing",
|
|
"_sitemap": "zh",
|
|
"alternatives": [
|
|
{
|
|
"hreflang": "en",
|
|
"href": "/pricing"
|
|
},
|
|
{
|
|
"hreflang": "zh",
|
|
"href": "/zh/pricing"
|
|
},
|
|
{
|
|
"hreflang": "zh-hant",
|
|
"href": "/zh-hant/pricing"
|
|
},
|
|
{
|
|
"hreflang": "x-default",
|
|
"href": "/pricing"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"loc": "/zh-hant/pricing",
|
|
"_sitemap": "zh-hant",
|
|
"alternatives": [
|
|
{
|
|
"hreflang": "en",
|
|
"href": "/pricing"
|
|
},
|
|
{
|
|
"hreflang": "zh",
|
|
"href": "/zh/pricing"
|
|
},
|
|
{
|
|
"hreflang": "zh-hant",
|
|
"href": "/zh-hant/pricing"
|
|
},
|
|
{
|
|
"hreflang": "x-default",
|
|
"href": "/pricing"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"loc": "/solutions",
|
|
"_sitemap": "en",
|
|
"alternatives": [
|
|
{
|
|
"hreflang": "en",
|
|
"href": "/solutions"
|
|
},
|
|
{
|
|
"hreflang": "zh",
|
|
"href": "/zh/solutions"
|
|
},
|
|
{
|
|
"hreflang": "zh-hant",
|
|
"href": "/zh-hant/solutions"
|
|
},
|
|
{
|
|
"hreflang": "x-default",
|
|
"href": "/solutions"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"loc": "/zh/solutions",
|
|
"_sitemap": "zh",
|
|
"alternatives": [
|
|
{
|
|
"hreflang": "en",
|
|
"href": "/solutions"
|
|
},
|
|
{
|
|
"hreflang": "zh",
|
|
"href": "/zh/solutions"
|
|
},
|
|
{
|
|
"hreflang": "zh-hant",
|
|
"href": "/zh-hant/solutions"
|
|
},
|
|
{
|
|
"hreflang": "x-default",
|
|
"href": "/solutions"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"loc": "/zh-hant/solutions",
|
|
"_sitemap": "zh-hant",
|
|
"alternatives": [
|
|
{
|
|
"hreflang": "en",
|
|
"href": "/solutions"
|
|
},
|
|
{
|
|
"hreflang": "zh",
|
|
"href": "/zh/solutions"
|
|
},
|
|
{
|
|
"hreflang": "zh-hant",
|
|
"href": "/zh-hant/solutions"
|
|
},
|
|
{
|
|
"hreflang": "x-default",
|
|
"href": "/solutions"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"loc": "/blog",
|
|
"_sitemap": "en",
|
|
"alternatives": [
|
|
{
|
|
"hreflang": "en",
|
|
"href": "/blog"
|
|
},
|
|
{
|
|
"hreflang": "zh",
|
|
"href": "/zh/blog"
|
|
},
|
|
{
|
|
"hreflang": "zh-hant",
|
|
"href": "/zh-hant/blog"
|
|
},
|
|
{
|
|
"hreflang": "x-default",
|
|
"href": "/blog"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"loc": "/zh/blog",
|
|
"_sitemap": "zh",
|
|
"alternatives": [
|
|
{
|
|
"hreflang": "en",
|
|
"href": "/blog"
|
|
},
|
|
{
|
|
"hreflang": "zh",
|
|
"href": "/zh/blog"
|
|
},
|
|
{
|
|
"hreflang": "zh-hant",
|
|
"href": "/zh-hant/blog"
|
|
},
|
|
{
|
|
"hreflang": "x-default",
|
|
"href": "/blog"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"loc": "/zh-hant/blog",
|
|
"_sitemap": "zh-hant",
|
|
"alternatives": [
|
|
{
|
|
"hreflang": "en",
|
|
"href": "/blog"
|
|
},
|
|
{
|
|
"hreflang": "zh",
|
|
"href": "/zh/blog"
|
|
},
|
|
{
|
|
"hreflang": "zh-hant",
|
|
"href": "/zh-hant/blog"
|
|
},
|
|
{
|
|
"hreflang": "x-default",
|
|
"href": "/blog"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"loc": "/sitemap.xml",
|
|
"_sitemap": "en"
|
|
},
|
|
{
|
|
"loc": "/index-sitemap.xml",
|
|
"_sitemap": "en"
|
|
},
|
|
{
|
|
"loc": "/en-sitemap.xml",
|
|
"_sitemap": "en"
|
|
},
|
|
{
|
|
"loc": "/zh-sitemap.xml",
|
|
"_sitemap": "en"
|
|
},
|
|
{
|
|
"loc": "/zh-hant-sitemap.xml",
|
|
"_sitemap": "en"
|
|
}
|
|
],
|
|
"sourceType": "app"
|
|
}
|
|
];
|
|
|
|
const globalSources = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
__proto__: null,
|
|
sources: sources$1
|
|
}, Symbol.toStringTag, { value: 'Module' }));
|
|
|
|
const sources = {
|
|
"en": [],
|
|
"zh": [],
|
|
"zh-hant": []
|
|
};
|
|
|
|
const childSources = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
__proto__: null,
|
|
sources: sources
|
|
}, Symbol.toStringTag, { value: 'Module' }));
|
|
|
|
const template = "";
|
|
|
|
const _virtual__spaTemplate = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
__proto__: null,
|
|
template: template
|
|
}, Symbol.toStringTag, { value: 'Module' }));
|
|
|
|
const styles = {};
|
|
|
|
const styles$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
__proto__: null,
|
|
default: styles
|
|
}, Symbol.toStringTag, { value: 'Module' }));
|
|
|
|
function jsonParse(value) {
|
|
return JSON.parse(value, regExpReviver);
|
|
}
|
|
function regExpReviver(_key, value) {
|
|
const withOperator = typeof value === "string" && value.match(/^--([A-Z]+) (.+)$/) || [];
|
|
if (withOperator[1] === "REGEX") {
|
|
const regex = withOperator[2]?.match(/\/(.*)\/([dgimsuy]*)$/);
|
|
return regex?.[1] ? new RegExp(regex[1], regex[2] || "") : value;
|
|
}
|
|
return value;
|
|
}
|
|
|
|
const parseJSONQueryParams = (body) => {
|
|
try {
|
|
return jsonParse(body);
|
|
} catch {
|
|
throw createError({ statusCode: 400, message: "Invalid _params query" });
|
|
}
|
|
};
|
|
const decodeQueryParams = (encoded) => {
|
|
encoded = encoded.replace(/\//g, "");
|
|
encoded = encoded.replace(/-/g, "+").replace(/_/g, "/");
|
|
encoded = encoded.padEnd(encoded.length + (4 - encoded.length % 4) % 4, "=");
|
|
return parseJSONQueryParams(typeof Buffer !== "undefined" ? Buffer.from(encoded, "base64").toString() : atob(encoded));
|
|
};
|
|
const memory = {};
|
|
const getContentQuery = (event) => {
|
|
const { params } = event.context.params || {};
|
|
if (params) {
|
|
return decodeQueryParams(params.replace(/.json$/, ""));
|
|
}
|
|
const qid = event.context.params?.qid?.replace(/.json$/, "");
|
|
const query = getQuery$1(event) || {};
|
|
if (qid && query._params) {
|
|
memory[qid] = parseJSONQueryParams(decodeURIComponent(query._params));
|
|
if (memory[qid]?.where && !Array.isArray(memory[qid]?.where)) {
|
|
memory[qid].where = [memory[qid].where];
|
|
}
|
|
return memory[qid];
|
|
}
|
|
if (qid && memory[qid]) {
|
|
return memory[qid];
|
|
}
|
|
if (query._params) {
|
|
return parseJSONQueryParams(decodeURIComponent(query._params));
|
|
}
|
|
if (typeof query.only === "string" && query.only.includes(",")) {
|
|
query.only = query.only.split(",").map((s) => s.trim());
|
|
}
|
|
if (typeof query.without === "string" && query.without.includes(",")) {
|
|
query.without = query.without.split(",").map((s) => s.trim());
|
|
}
|
|
const where = query.where || {};
|
|
for (const key of ["draft", "partial", "empty"]) {
|
|
if (query[key] && ["true", "false"].includes(query[key])) {
|
|
where[key] = query[key] === "true";
|
|
delete query[key];
|
|
}
|
|
}
|
|
if (query.sort) {
|
|
query.sort = String(query.sort).split(",").map((s) => {
|
|
const [key, order] = s.split(":");
|
|
return [key, Number.parseInt(order || "0", 10)];
|
|
});
|
|
}
|
|
const reservedKeys = ["partial", "draft", "only", "without", "where", "sort", "limit", "skip"];
|
|
for (const key of Object.keys(query)) {
|
|
if (reservedKeys.includes(key)) {
|
|
continue;
|
|
}
|
|
query.where = query.where || {};
|
|
query.where[key] = query[key];
|
|
}
|
|
if (Object.keys(where).length > 0) {
|
|
query.where = [where];
|
|
} else {
|
|
delete query.where;
|
|
}
|
|
return query;
|
|
};
|
|
|
|
const query = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
__proto__: null,
|
|
decodeQueryParams: decodeQueryParams,
|
|
getContentQuery: getContentQuery
|
|
}, Symbol.toStringTag, { value: 'Module' }));
|
|
|
|
function createNav(contents, configs) {
|
|
const { navigation } = useRuntimeConfig().public.content;
|
|
if (navigation === false) {
|
|
return [];
|
|
}
|
|
const pickNavigationFields = (content) => ({
|
|
...pick(["title", ...navigation.fields])(content),
|
|
...isObject(content?.navigation) ? content.navigation : {}
|
|
});
|
|
const nav = contents.sort((a, b) => a._path.localeCompare(b._path)).reduce((nav2, content) => {
|
|
const parts = content._path.substring(1).split("/");
|
|
const idParts = content._id.split(":").slice(1);
|
|
const isIndex = !!idParts[idParts.length - 1]?.match(/([1-9][0-9]*\.)?index.md/g);
|
|
const getNavItem = (content2) => ({
|
|
title: content2.title,
|
|
_path: content2._path,
|
|
_file: content2._file,
|
|
children: [],
|
|
...pickNavigationFields(content2),
|
|
...content2._draft ? { _draft: true } : {}
|
|
});
|
|
const navItem = getNavItem(content);
|
|
if (isIndex) {
|
|
const dirConfig = configs[navItem._path];
|
|
if (typeof dirConfig?.navigation !== "undefined" && !dirConfig?.navigation) {
|
|
return nav2;
|
|
}
|
|
if (content._path !== "/") {
|
|
const indexItem = getNavItem(content);
|
|
navItem.children.push(indexItem);
|
|
}
|
|
if (dirConfig) {
|
|
Object.assign(
|
|
navItem,
|
|
pickNavigationFields(dirConfig)
|
|
);
|
|
}
|
|
}
|
|
if (parts.length === 1) {
|
|
nav2.push(navItem);
|
|
return nav2;
|
|
}
|
|
const siblings = parts.slice(0, -1).reduce((nodes, part, i) => {
|
|
const currentPathPart = "/" + parts.slice(0, i + 1).join("/");
|
|
const conf = configs[currentPathPart];
|
|
if (typeof conf?.navigation !== "undefined" && !conf.navigation) {
|
|
return [];
|
|
}
|
|
let parent = nodes.find((n) => n._path === currentPathPart);
|
|
if (!parent) {
|
|
parent = {
|
|
title: generateTitle(part),
|
|
_path: currentPathPart,
|
|
_file: content._file,
|
|
children: [],
|
|
...conf && pickNavigationFields(conf)
|
|
};
|
|
nodes.push(parent);
|
|
}
|
|
return parent.children;
|
|
}, nav2);
|
|
siblings.push(navItem);
|
|
return nav2;
|
|
}, []);
|
|
return sortAndClear(nav);
|
|
}
|
|
const collator = new Intl.Collator(void 0, { numeric: true, sensitivity: "base" });
|
|
function sortAndClear(nav) {
|
|
nav.forEach((item) => {
|
|
item._file = item._file.split(".").slice(0, -1).join(".");
|
|
});
|
|
const sorted = nav.sort((a, b) => collator.compare(a._file, b._file));
|
|
for (const item of sorted) {
|
|
if (item.children?.length) {
|
|
sortAndClear(item.children);
|
|
} else {
|
|
delete item.children;
|
|
}
|
|
delete item._file;
|
|
}
|
|
return nav;
|
|
}
|
|
function pick(keys) {
|
|
return (obj) => {
|
|
obj = obj || {};
|
|
if (keys && keys.length) {
|
|
return keys.filter((key) => typeof obj[key] !== "undefined").reduce((newObj, key) => Object.assign(newObj, { [key]: obj[key] }), {});
|
|
}
|
|
return obj;
|
|
};
|
|
}
|
|
function isObject(obj) {
|
|
return Object.prototype.toString.call(obj) === "[object Object]";
|
|
}
|
|
|
|
const navigation = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
__proto__: null,
|
|
createNav: createNav
|
|
}, Symbol.toStringTag, { value: 'Module' }));
|
|
|
|
function renderPayloadResponse(ssrContext) {
|
|
return {
|
|
body: stringify(splitPayload(ssrContext).payload, ssrContext._payloadReducers) ,
|
|
statusCode: getResponseStatus(ssrContext.event),
|
|
statusMessage: getResponseStatusText(ssrContext.event),
|
|
headers: {
|
|
"content-type": "application/json;charset=utf-8" ,
|
|
"x-powered-by": "Nuxt"
|
|
}
|
|
};
|
|
}
|
|
function renderPayloadJsonScript(opts) {
|
|
const contents = opts.data ? stringify(opts.data, opts.ssrContext._payloadReducers) : "";
|
|
const payload = {
|
|
"type": "application/json",
|
|
"innerHTML": contents,
|
|
"data-nuxt-data": appId,
|
|
"data-ssr": !(opts.ssrContext.noSSR)
|
|
};
|
|
{
|
|
payload.id = "__NUXT_DATA__";
|
|
}
|
|
if (opts.src) {
|
|
payload["data-src"] = opts.src;
|
|
}
|
|
const config = uneval(opts.ssrContext.config);
|
|
return [
|
|
payload,
|
|
{
|
|
innerHTML: `window.__NUXT__={};window.__NUXT__.config=${config}`
|
|
}
|
|
];
|
|
}
|
|
function splitPayload(ssrContext) {
|
|
const { data, prerenderedAt, ...initial } = ssrContext.payload;
|
|
return {
|
|
initial: { ...initial, prerenderedAt },
|
|
payload: { data, prerenderedAt }
|
|
};
|
|
}
|
|
|
|
const renderSSRHeadOptions = {"omitLineBreaks":false};
|
|
|
|
globalThis.__buildAssetsURL = buildAssetsURL;
|
|
globalThis.__publicAssetsURL = publicAssetsURL;
|
|
const HAS_APP_TELEPORTS = !!(appTeleportAttrs.id);
|
|
const APP_TELEPORT_OPEN_TAG = HAS_APP_TELEPORTS ? `<${appTeleportTag}${propsToString(appTeleportAttrs)}>` : "";
|
|
const APP_TELEPORT_CLOSE_TAG = HAS_APP_TELEPORTS ? `</${appTeleportTag}>` : "";
|
|
const PAYLOAD_URL_RE = /^[^?]*\/_payload.json(?:\?.*)?$/ ;
|
|
const renderer = defineRenderHandler(async (event) => {
|
|
const nitroApp = useNitroApp();
|
|
const ssrError = event.path.startsWith("/__nuxt_error") ? getQuery$1(event) : null;
|
|
if (ssrError && !("__unenv__" in event.node.req)) {
|
|
throw createError({
|
|
statusCode: 404,
|
|
statusMessage: "Page Not Found: /__nuxt_error"
|
|
});
|
|
}
|
|
const ssrContext = createSSRContext(event);
|
|
const headEntryOptions = { mode: "server" };
|
|
ssrContext.head.push(appHead, headEntryOptions);
|
|
if (ssrError) {
|
|
ssrError.statusCode &&= Number.parseInt(ssrError.statusCode);
|
|
setSSRError(ssrContext, ssrError);
|
|
}
|
|
const isRenderingPayload = PAYLOAD_URL_RE.test(ssrContext.url);
|
|
if (isRenderingPayload) {
|
|
const url = ssrContext.url.substring(0, ssrContext.url.lastIndexOf("/")) || "/";
|
|
ssrContext.url = url;
|
|
event._path = event.node.req.url = url;
|
|
}
|
|
const routeOptions = getRouteRules(event);
|
|
if (routeOptions.ssr === false) {
|
|
ssrContext.noSSR = true;
|
|
}
|
|
const renderer = await getRenderer(ssrContext);
|
|
const _rendered = await renderer.renderToString(ssrContext).catch(async (error) => {
|
|
if (ssrContext._renderResponse && error.message === "skipping render") {
|
|
return {};
|
|
}
|
|
const _err = !ssrError && ssrContext.payload?.error || error;
|
|
await ssrContext.nuxt?.hooks.callHook("app:error", _err);
|
|
throw _err;
|
|
});
|
|
const inlinedStyles = [];
|
|
await ssrContext.nuxt?.hooks.callHook("app:rendered", { ssrContext, renderResult: _rendered });
|
|
if (ssrContext._renderResponse) {
|
|
return ssrContext._renderResponse;
|
|
}
|
|
if (ssrContext.payload?.error && !ssrError) {
|
|
throw ssrContext.payload.error;
|
|
}
|
|
if (isRenderingPayload) {
|
|
const response = renderPayloadResponse(ssrContext);
|
|
return response;
|
|
}
|
|
const NO_SCRIPTS = routeOptions.noScripts;
|
|
const { styles, scripts } = getRequestDependencies(ssrContext, renderer.rendererContext);
|
|
if (ssrContext._preloadManifest && !NO_SCRIPTS) {
|
|
ssrContext.head.push({
|
|
link: [
|
|
{ rel: "preload", as: "fetch", fetchpriority: "low", crossorigin: "anonymous", href: buildAssetsURL(`builds/meta/${ssrContext.runtimeConfig.app.buildId}.json`) }
|
|
]
|
|
}, { ...headEntryOptions, tagPriority: "low" });
|
|
}
|
|
if (inlinedStyles.length) {
|
|
ssrContext.head.push({ style: inlinedStyles });
|
|
}
|
|
const link = [];
|
|
for (const resource of Object.values(styles)) {
|
|
if ("inline" in getQuery(resource.file)) {
|
|
continue;
|
|
}
|
|
link.push({ rel: "stylesheet", href: renderer.rendererContext.buildAssetsURL(resource.file), crossorigin: "" });
|
|
}
|
|
if (link.length) {
|
|
ssrContext.head.push({ link }, headEntryOptions);
|
|
}
|
|
if (!NO_SCRIPTS) {
|
|
ssrContext.head.push({
|
|
link: getPreloadLinks(ssrContext, renderer.rendererContext)
|
|
}, headEntryOptions);
|
|
ssrContext.head.push({
|
|
link: getPrefetchLinks(ssrContext, renderer.rendererContext)
|
|
}, headEntryOptions);
|
|
ssrContext.head.push({
|
|
script: renderPayloadJsonScript({ ssrContext, data: ssrContext.payload })
|
|
}, {
|
|
...headEntryOptions,
|
|
// this should come before another end of body scripts
|
|
tagPosition: "bodyClose",
|
|
tagPriority: "high"
|
|
});
|
|
}
|
|
if (!routeOptions.noScripts) {
|
|
const tagPosition = "head";
|
|
ssrContext.head.push({
|
|
script: Object.values(scripts).map((resource) => ({
|
|
type: resource.module ? "module" : null,
|
|
src: renderer.rendererContext.buildAssetsURL(resource.file),
|
|
defer: resource.module ? null : true,
|
|
// if we are rendering script tag payloads that import an async payload
|
|
// we need to ensure this resolves before executing the Nuxt entry
|
|
tagPosition,
|
|
crossorigin: ""
|
|
}))
|
|
}, headEntryOptions);
|
|
}
|
|
const { headTags, bodyTags, bodyTagsOpen, htmlAttrs, bodyAttrs } = await renderSSRHead(ssrContext.head, renderSSRHeadOptions);
|
|
const htmlContext = {
|
|
htmlAttrs: htmlAttrs ? [htmlAttrs] : [],
|
|
head: normalizeChunks([headTags]),
|
|
bodyAttrs: bodyAttrs ? [bodyAttrs] : [],
|
|
bodyPrepend: normalizeChunks([bodyTagsOpen, ssrContext.teleports?.body]),
|
|
body: [
|
|
replaceIslandTeleports(ssrContext, _rendered.html) ,
|
|
APP_TELEPORT_OPEN_TAG + (HAS_APP_TELEPORTS ? joinTags([ssrContext.teleports?.[`#${appTeleportAttrs.id}`]]) : "") + APP_TELEPORT_CLOSE_TAG
|
|
],
|
|
bodyAppend: [bodyTags]
|
|
};
|
|
await nitroApp.hooks.callHook("render:html", htmlContext, { event });
|
|
return {
|
|
body: renderHTMLDocument(htmlContext),
|
|
statusCode: getResponseStatus(event),
|
|
statusMessage: getResponseStatusText(event),
|
|
headers: {
|
|
"content-type": "text/html;charset=utf-8",
|
|
"x-powered-by": "Nuxt"
|
|
}
|
|
};
|
|
});
|
|
function normalizeChunks(chunks) {
|
|
return chunks.filter(Boolean).map((i) => i.trim());
|
|
}
|
|
function joinTags(tags) {
|
|
return tags.join("");
|
|
}
|
|
function joinAttrs(chunks) {
|
|
if (chunks.length === 0) {
|
|
return "";
|
|
}
|
|
return " " + chunks.join(" ");
|
|
}
|
|
function renderHTMLDocument(html) {
|
|
return `<!DOCTYPE html><html${joinAttrs(html.htmlAttrs)}><head>${joinTags(html.head)}</head><body${joinAttrs(html.bodyAttrs)}>${joinTags(html.bodyPrepend)}${joinTags(html.body)}${joinTags(html.bodyAppend)}</body></html>`;
|
|
}
|
|
|
|
const renderer$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
__proto__: null,
|
|
default: renderer
|
|
}, Symbol.toStringTag, { value: 'Module' }));
|
|
|
|
async function buildSitemapIndex(resolvers, runtimeConfig) {
|
|
const {
|
|
sitemaps,
|
|
// enhancing
|
|
autoLastmod,
|
|
// chunking
|
|
defaultSitemapsChunkSize,
|
|
autoI18n,
|
|
isI18nMapped,
|
|
sortEntries,
|
|
sitemapsPathPrefix
|
|
} = runtimeConfig;
|
|
if (!sitemaps)
|
|
throw new Error("Attempting to build a sitemap index without required `sitemaps` configuration.");
|
|
function maybeSort(urls) {
|
|
return sortEntries ? sortSitemapUrls(urls) : urls;
|
|
}
|
|
const isChunking = typeof sitemaps.chunks !== "undefined";
|
|
const chunks = {};
|
|
if (isChunking) {
|
|
const sitemap = sitemaps.chunks;
|
|
const sources = await resolveSitemapSources(await globalSitemapSources());
|
|
const normalisedUrls = resolveSitemapEntries(sitemap, sources, { autoI18n, isI18nMapped }, resolvers);
|
|
const enhancedUrls = normalisedUrls.map((e) => defu$1(e, sitemap.defaults));
|
|
const sortedUrls = maybeSort(enhancedUrls);
|
|
sortedUrls.forEach((url, i) => {
|
|
const chunkIndex = Math.floor(i / defaultSitemapsChunkSize);
|
|
chunks[chunkIndex] = chunks[chunkIndex] || { urls: [] };
|
|
chunks[chunkIndex].urls.push(url);
|
|
});
|
|
} else {
|
|
for (const sitemap in sitemaps) {
|
|
if (sitemap !== "index") {
|
|
chunks[sitemap] = chunks[sitemap] || { urls: [] };
|
|
}
|
|
}
|
|
}
|
|
const entries = [];
|
|
for (const name in chunks) {
|
|
const sitemap = chunks[name];
|
|
const entry = {
|
|
_sitemapName: name,
|
|
sitemap: resolvers.canonicalUrlResolver(joinURL(sitemapsPathPrefix, `/${name}.xml`))
|
|
};
|
|
let lastmod = sitemap.urls.filter((a) => !!a?.lastmod).map((a) => typeof a.lastmod === "string" ? new Date(a.lastmod) : a.lastmod).sort((a, b) => (b?.getTime() || 0) - (a?.getTime() || 0))?.[0];
|
|
if (!lastmod && autoLastmod)
|
|
lastmod = /* @__PURE__ */ new Date();
|
|
if (lastmod)
|
|
entry.lastmod = normaliseDate(lastmod);
|
|
entries.push(entry);
|
|
}
|
|
if (sitemaps.index) {
|
|
entries.push(...sitemaps.index.sitemaps.map((entry) => {
|
|
return typeof entry === "string" ? { sitemap: entry } : entry;
|
|
}));
|
|
}
|
|
return entries;
|
|
}
|
|
function urlsToIndexXml(sitemaps, resolvers, { version, xsl, credits, minify }) {
|
|
const sitemapXml = sitemaps.map((e) => [
|
|
" <sitemap>",
|
|
` <loc>${escapeValueForXml(e.sitemap)}</loc>`,
|
|
// lastmod is optional
|
|
e.lastmod ? ` <lastmod>${escapeValueForXml(e.lastmod)}</lastmod>` : false,
|
|
" </sitemap>"
|
|
].filter(Boolean).join("\n")).join("\n");
|
|
return wrapSitemapXml([
|
|
'<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
|
|
sitemapXml,
|
|
"</sitemapindex>"
|
|
], resolvers, { version, xsl, credits, minify });
|
|
}
|
|
|
|
const sitemap_index_xml = defineEventHandler(async (e) => {
|
|
const runtimeConfig = useSimpleSitemapRuntimeConfig();
|
|
const nitro = useNitroApp();
|
|
const resolvers = useNitroUrlResolvers(e);
|
|
const sitemaps = await buildSitemapIndex(resolvers, runtimeConfig);
|
|
const indexResolvedCtx = { sitemaps };
|
|
await nitro.hooks.callHook("sitemap:index-resolved", indexResolvedCtx);
|
|
const output = urlsToIndexXml(indexResolvedCtx.sitemaps, resolvers, runtimeConfig);
|
|
const ctx = { sitemap: output, sitemapName: "sitemap" };
|
|
await nitro.hooks.callHook("sitemap:output", ctx);
|
|
setHeader(e, "Content-Type", "text/xml; charset=UTF-8");
|
|
if (runtimeConfig.cacheMaxAgeSeconds)
|
|
setHeader(e, "Cache-Control", `public, max-age=${runtimeConfig.cacheMaxAgeSeconds}, must-revalidate`);
|
|
else
|
|
setHeader(e, "Cache-Control", `no-cache, no-store`);
|
|
return ctx.sitemap;
|
|
});
|
|
|
|
const sitemap_index_xml$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
__proto__: null,
|
|
default: sitemap_index_xml
|
|
}, Symbol.toStringTag, { value: 'Module' }));
|
|
|
|
const _sitemap__xml = defineEventHandler(async (e) => {
|
|
const runtimeConfig = useSimpleSitemapRuntimeConfig(e);
|
|
const { sitemaps } = runtimeConfig;
|
|
const sitemapName = withoutLeadingSlash(withoutTrailingSlash((getRouterParam(e, "sitemap") || e.path)?.replace(".xml", "").replace(runtimeConfig.sitemapsPathPrefix, "")));
|
|
const isChunking = typeof sitemaps.chunks !== "undefined" && !Number.isNaN(Number(sitemapName));
|
|
if (!(sitemapName in sitemaps) && !isChunking) {
|
|
return createError({
|
|
statusCode: 404,
|
|
message: `Sitemap "${sitemapName}" not found.`
|
|
});
|
|
}
|
|
return createSitemap(e, isChunking ? {
|
|
...sitemaps.chunks,
|
|
sitemapName
|
|
} : sitemaps[sitemapName], runtimeConfig);
|
|
});
|
|
|
|
const _sitemap__xml$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
__proto__: null,
|
|
default: _sitemap__xml
|
|
}, Symbol.toStringTag, { value: 'Module' }));
|
|
//# sourceMappingURL=index.mjs.map
|