@vezham/docs-core 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +5 -0
- package/dist/advanced-Ct13khZr.js +79 -0
- package/dist/algolia-C0E5qQhM.d.ts +66 -0
- package/dist/breadcrumb.d.ts +46 -0
- package/dist/breadcrumb.js +59 -0
- package/dist/build-doc-4OvfjVN2.js +85 -0
- package/dist/client-kQ39Ub0-.d.ts +247 -0
- package/dist/codeblock-utils-CyP8qsYv.d.ts +29 -0
- package/dist/content/github.d.ts +41 -0
- package/dist/content/github.js +28 -0
- package/dist/content/md/frontmatter.d.ts +15 -0
- package/dist/content/md/frontmatter.js +24 -0
- package/dist/content/md.d.ts +24 -0
- package/dist/content/md.js +43 -0
- package/dist/content/mdx/preset-bundler.d.ts +29 -0
- package/dist/content/mdx/preset-bundler.js +39 -0
- package/dist/content/mdx/preset-runtime.d.ts +26 -0
- package/dist/content/mdx/preset-runtime.js +36 -0
- package/dist/content/toc.d.ts +19 -0
- package/dist/content/toc.js +14 -0
- package/dist/definitions-CFOhwE1k.d.ts +72 -0
- package/dist/dynamic-CTsodhTH.js +905 -0
- package/dist/dynamic-link.d.ts +12 -0
- package/dist/dynamic-link.js +31 -0
- package/dist/endpoint-MyoBU5IC.js +28 -0
- package/dist/framework/astro.d.ts +21 -0
- package/dist/framework/astro.js +52 -0
- package/dist/framework/index.d.ts +40 -0
- package/dist/framework/index.js +66 -0
- package/dist/framework/next.d.ts +10 -0
- package/dist/framework/next.js +19 -0
- package/dist/framework/react-router.d.ts +10 -0
- package/dist/framework/react-router.js +43 -0
- package/dist/framework/tanstack.d.ts +13 -0
- package/dist/framework/tanstack.js +54 -0
- package/dist/framework/waku.d.ts +10 -0
- package/dist/framework/waku.js +46 -0
- package/dist/highlight/client.d.ts +11 -0
- package/dist/highlight/client.js +15 -0
- package/dist/highlight/index.d.ts +31 -0
- package/dist/highlight/index.js +30 -0
- package/dist/highlight/shiki/full.d.ts +7 -0
- package/dist/highlight/shiki/full.js +23 -0
- package/dist/highlight/shiki/index.d.ts +2 -0
- package/dist/highlight/shiki/index.js +27 -0
- package/dist/highlight/shiki/react.d.ts +23 -0
- package/dist/highlight/shiki/react.js +50 -0
- package/dist/i18n/index.d.ts +2 -0
- package/dist/i18n/index.js +63 -0
- package/dist/i18n/middleware.d.ts +34 -0
- package/dist/i18n/middleware.js +3855 -0
- package/dist/icon-BILaoXeg.js +17 -0
- package/dist/index-B-0R0VbS.d.ts +18 -0
- package/dist/index-BM36H-xw.d.ts +36 -0
- package/dist/index-BMEUQz-F.d.ts +21 -0
- package/dist/index-DAYtLGbx.d.ts +16 -0
- package/dist/index-DIwKCYOz.d.ts +513 -0
- package/dist/index-DydiXvgS.d.ts +90 -0
- package/dist/index-E8Qh_yQs.d.ts +49 -0
- package/dist/is-equal-LdLqRs0o.js +8 -0
- package/dist/link.d.ts +17 -0
- package/dist/link.js +23 -0
- package/dist/mdx-plugins/codeblock-utils.d.ts +2 -0
- package/dist/mdx-plugins/codeblock-utils.js +68 -0
- package/dist/mdx-plugins/index.d.ts +20 -0
- package/dist/mdx-plugins/index.js +18 -0
- package/dist/mdx-plugins/rehype-code.core.d.ts +3 -0
- package/dist/mdx-plugins/rehype-code.core.js +3 -0
- package/dist/mdx-plugins/rehype-code.d.ts +4 -0
- package/dist/mdx-plugins/rehype-code.js +24 -0
- package/dist/mdx-plugins/rehype-toc.d.ts +2 -0
- package/dist/mdx-plugins/rehype-toc.js +139 -0
- package/dist/mdx-plugins/remark-admonition.d.ts +2 -0
- package/dist/mdx-plugins/remark-admonition.js +71 -0
- package/dist/mdx-plugins/remark-block-id.d.ts +37 -0
- package/dist/mdx-plugins/remark-block-id.js +41 -0
- package/dist/mdx-plugins/remark-code-tab.d.ts +2 -0
- package/dist/mdx-plugins/remark-code-tab.js +190 -0
- package/dist/mdx-plugins/remark-directive-admonition.d.ts +2 -0
- package/dist/mdx-plugins/remark-directive-admonition.js +57 -0
- package/dist/mdx-plugins/remark-feedback-block.d.ts +2 -0
- package/dist/mdx-plugins/remark-feedback-block.js +54 -0
- package/dist/mdx-plugins/remark-gfm.d.ts +2 -0
- package/dist/mdx-plugins/remark-gfm.js +2 -0
- package/dist/mdx-plugins/remark-heading.d.ts +2 -0
- package/dist/mdx-plugins/remark-heading.js +46 -0
- package/dist/mdx-plugins/remark-image.d.ts +2 -0
- package/dist/mdx-plugins/remark-image.js +167 -0
- package/dist/mdx-plugins/remark-llms.d.ts +2 -0
- package/dist/mdx-plugins/remark-llms.js +338 -0
- package/dist/mdx-plugins/remark-llms.runtime.d.ts +10 -0
- package/dist/mdx-plugins/remark-llms.runtime.js +24 -0
- package/dist/mdx-plugins/remark-mdx-files.d.ts +2 -0
- package/dist/mdx-plugins/remark-mdx-files.js +182 -0
- package/dist/mdx-plugins/remark-mdx-mermaid.d.ts +2 -0
- package/dist/mdx-plugins/remark-mdx-mermaid.js +28 -0
- package/dist/mdx-plugins/remark-npm.d.ts +2 -0
- package/dist/mdx-plugins/remark-npm.js +76 -0
- package/dist/mdx-plugins/remark-steps.d.ts +2 -0
- package/dist/mdx-plugins/remark-steps.js +93 -0
- package/dist/mdx-plugins/remark-structure.d.ts +2 -0
- package/dist/mdx-plugins/remark-structure.js +118 -0
- package/dist/mdx-plugins/stringifier.d.ts +2 -0
- package/dist/mdx-plugins/stringifier.js +91 -0
- package/dist/mdx-plugins/transformer-icon.d.ts +2 -0
- package/dist/mdx-plugins/transformer-icon.js +145 -0
- package/dist/negotiation/index.d.ts +17 -0
- package/dist/negotiation/index.js +378 -0
- package/dist/page-tree/index.d.ts +3 -0
- package/dist/page-tree/index.js +2 -0
- package/dist/path-1H5VzYiT.js +75 -0
- package/dist/rehype-code-D-RFJb9W.d.ts +14 -0
- package/dist/rehype-code.core-BUwNuchP.js +548 -0
- package/dist/rehype-code.core-BjH1uHWj.d.ts +115 -0
- package/dist/rehype-toc-K51AGb5U.d.ts +43 -0
- package/dist/remark-admonition-BwTcmI_S.d.ts +20 -0
- package/dist/remark-code-tab-DE_4bdnu.d.ts +34 -0
- package/dist/remark-directive-admonition-BLiJ5l43.d.ts +27 -0
- package/dist/remark-feedback-block-BxtINXN-.d.ts +45 -0
- package/dist/remark-gfm-DpVfAX1x.d.ts +2 -0
- package/dist/remark-heading-DEIzTkU5.d.ts +33 -0
- package/dist/remark-image-BI2S9LOb.d.ts +57 -0
- package/dist/remark-llms-bD3WvU2V.d.ts +73 -0
- package/dist/remark-mdx-files-Buvxc-sa.d.ts +54 -0
- package/dist/remark-mdx-mermaid-C1bCHHc6.d.ts +15 -0
- package/dist/remark-npm-BbpvkJaT.d.ts +31 -0
- package/dist/remark-steps-DqVEo0iq.d.ts +23 -0
- package/dist/remark-structure-CnHwvNZr.d.ts +87 -0
- package/dist/remove-markdown-DfKNMl9w.js +40 -0
- package/dist/remove-undefined-CzMSKybq.js +24 -0
- package/dist/rolldown-runtime-DC62tzP2.js +33 -0
- package/dist/search/algolia.d.ts +2 -0
- package/dist/search/algolia.js +75 -0
- package/dist/search/client/algolia.d.ts +2 -0
- package/dist/search/client/algolia.js +53 -0
- package/dist/search/client/fetch.d.ts +2 -0
- package/dist/search/client/fetch.js +28 -0
- package/dist/search/client/flexsearch-static.d.ts +2 -0
- package/dist/search/client/flexsearch-static.js +42 -0
- package/dist/search/client/mixedbread.d.ts +2 -0
- package/dist/search/client/mixedbread.js +65 -0
- package/dist/search/client/orama-cloud-legacy.d.ts +2 -0
- package/dist/search/client/orama-cloud-legacy.js +84 -0
- package/dist/search/client/orama-cloud.d.ts +2 -0
- package/dist/search/client/orama-cloud.js +86 -0
- package/dist/search/client/orama-static.d.ts +2 -0
- package/dist/search/client/orama-static.js +75 -0
- package/dist/search/client.d.ts +2 -0
- package/dist/search/client.js +97 -0
- package/dist/search/flexsearch.d.ts +56 -0
- package/dist/search/flexsearch.js +128 -0
- package/dist/search/index.d.ts +2 -0
- package/dist/search/index.js +74 -0
- package/dist/search/mixedbread.d.ts +49 -0
- package/dist/search/mixedbread.js +77 -0
- package/dist/search/orama-cloud-legacy.d.ts +75 -0
- package/dist/search/orama-cloud-legacy.js +48 -0
- package/dist/search/orama-cloud.d.ts +75 -0
- package/dist/search/orama-cloud.js +50 -0
- package/dist/search/server.d.ts +2 -0
- package/dist/search/server.js +237 -0
- package/dist/server-CCqACwlF.d.ts +165 -0
- package/dist/server.browser.d.ts +13 -0
- package/dist/server.browser.js +22 -0
- package/dist/server.d.ts +42 -0
- package/dist/server.js +398 -0
- package/dist/source/client/index.d.ts +2 -0
- package/dist/source/client/index.js +37 -0
- package/dist/source/dynamic.d.ts +2 -0
- package/dist/source/dynamic.js +2 -0
- package/dist/source/index.d.ts +2 -0
- package/dist/source/index.js +5 -0
- package/dist/source/llms.d.ts +2 -0
- package/dist/source/llms.js +74 -0
- package/dist/source/plugins/lucide-icons.d.ts +11 -0
- package/dist/source/plugins/lucide-icons.js +21 -0
- package/dist/source/plugins/slugs.d.ts +2 -0
- package/dist/source/plugins/slugs.js +75 -0
- package/dist/source/plugins/status-badges.d.ts +50 -0
- package/dist/source/plugins/status-badges.js +52 -0
- package/dist/source/schema.d.ts +30 -0
- package/dist/source/schema.js +28 -0
- package/dist/stringifier-B_QUcUyo.d.ts +63 -0
- package/dist/toc-CtW5lwA1.d.ts +64 -0
- package/dist/toc.d.ts +2 -0
- package/dist/toc.js +245 -0
- package/dist/transformer-icon-DlrneIS3.d.ts +17 -0
- package/dist/types-D89QoQR-.d.ts +4 -0
- package/dist/url-BVHvi3_K.js +29 -0
- package/dist/util-BDsqOxh3.d.ts +6 -0
- package/dist/util-DjBr9b3w.js +8 -0
- package/dist/utils/use-media-query.d.ts +4 -0
- package/dist/utils/use-media-query.js +20 -0
- package/dist/utils/use-on-change.d.ts +9 -0
- package/dist/utils/use-on-change.js +17 -0
- package/dist/utils-Bvy3V-fv.js +59 -0
- package/dist/utils-Cgs-6U-z.js +39 -0
- package/dist/utils-DEVq3cEC.js +151 -0
- package/dist/utils-Yx0IL9eW.js +48 -0
- package/package.json +251 -0
|
@@ -0,0 +1,905 @@
|
|
|
1
|
+
import { r as normalizeUrl } from "./url-BVHvi3_K.js";
|
|
2
|
+
import { l as visit } from "./utils-DEVq3cEC.js";
|
|
3
|
+
import { t as isEqualShallow } from "./is-equal-LdLqRs0o.js";
|
|
4
|
+
import { a as normalize, i as joinPath, n as dirname, r as extname, t as basename } from "./path-1H5VzYiT.js";
|
|
5
|
+
import { slugsPlugin } from "./source/plugins/slugs.js";
|
|
6
|
+
import { t as iconPlugin } from "./icon-BILaoXeg.js";
|
|
7
|
+
import { cache } from "react";
|
|
8
|
+
//#region src/source/storage/file-system.ts
|
|
9
|
+
/**
|
|
10
|
+
* In memory file system.
|
|
11
|
+
*/
|
|
12
|
+
var FileSystem = class {
|
|
13
|
+
constructor(inherit) {
|
|
14
|
+
this.files = /* @__PURE__ */ new Map();
|
|
15
|
+
this.folders = /* @__PURE__ */ new Map();
|
|
16
|
+
if (inherit) {
|
|
17
|
+
for (const [k, v] of inherit.folders) this.folders.set(k, [...v]);
|
|
18
|
+
for (const [k, v] of inherit.files) this.files.set(k, v);
|
|
19
|
+
} else this.folders.set("", []);
|
|
20
|
+
}
|
|
21
|
+
read(path) {
|
|
22
|
+
return this.files.get(path);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* get the direct children of folder (in virtual file path)
|
|
26
|
+
*/
|
|
27
|
+
readDir(path) {
|
|
28
|
+
return this.folders.get(path);
|
|
29
|
+
}
|
|
30
|
+
write(path, file) {
|
|
31
|
+
if (!this.files.has(path)) {
|
|
32
|
+
const dir = dirname(path);
|
|
33
|
+
this.makeDir(dir);
|
|
34
|
+
this.readDir(dir)?.push(path);
|
|
35
|
+
}
|
|
36
|
+
this.files.set(path, file);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Delete files at specified path.
|
|
40
|
+
*
|
|
41
|
+
* @param path - the target path.
|
|
42
|
+
* @param [recursive=false] - if set to `true`, it will also delete directories.
|
|
43
|
+
*/
|
|
44
|
+
delete(path, recursive = false) {
|
|
45
|
+
if (this.files.delete(path)) return true;
|
|
46
|
+
if (recursive) {
|
|
47
|
+
const folder = this.folders.get(path);
|
|
48
|
+
if (!folder) return false;
|
|
49
|
+
this.folders.delete(path);
|
|
50
|
+
for (const child of folder) this.delete(child);
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
getFiles() {
|
|
56
|
+
return Array.from(this.files.keys());
|
|
57
|
+
}
|
|
58
|
+
makeDir(path) {
|
|
59
|
+
const cur = [];
|
|
60
|
+
let parentPath = "";
|
|
61
|
+
for (const seg of path.split("/")) {
|
|
62
|
+
cur.push(seg);
|
|
63
|
+
const curPath = cur.join("/");
|
|
64
|
+
if (!this.folders.has(curPath)) {
|
|
65
|
+
this.folders.set(curPath, []);
|
|
66
|
+
this.folders.get(parentPath).push(curPath);
|
|
67
|
+
}
|
|
68
|
+
parentPath = curPath;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
//#endregion
|
|
73
|
+
//#region src/source/source.ts
|
|
74
|
+
/**
|
|
75
|
+
* @deprecated you can directly pass a record of source objects to `loader()`.
|
|
76
|
+
*/
|
|
77
|
+
function multiple(sources) {
|
|
78
|
+
const out = {};
|
|
79
|
+
for (const k in sources) out[k] = { files: sources[k].files.map((file) => ({
|
|
80
|
+
...file,
|
|
81
|
+
data: {
|
|
82
|
+
...file.data,
|
|
83
|
+
type: k
|
|
84
|
+
}
|
|
85
|
+
})) };
|
|
86
|
+
return out;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* update a **static** source object in-place.
|
|
90
|
+
*/
|
|
91
|
+
function update(source) {
|
|
92
|
+
return {
|
|
93
|
+
files(fn) {
|
|
94
|
+
source.files = fn(source.files);
|
|
95
|
+
return this;
|
|
96
|
+
},
|
|
97
|
+
page(fn) {
|
|
98
|
+
for (let i = 0; i < source.files.length; i++) {
|
|
99
|
+
const file = source.files[i];
|
|
100
|
+
if (file.type === "page") source.files[i] = fn(file);
|
|
101
|
+
}
|
|
102
|
+
return this;
|
|
103
|
+
},
|
|
104
|
+
meta(fn) {
|
|
105
|
+
for (let i = 0; i < source.files.length; i++) {
|
|
106
|
+
const file = source.files[i];
|
|
107
|
+
if (file.type === "meta") source.files[i] = fn(file);
|
|
108
|
+
}
|
|
109
|
+
return this;
|
|
110
|
+
},
|
|
111
|
+
build() {
|
|
112
|
+
return source;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
function isStaticSource(s) {
|
|
117
|
+
return "files" in s && Array.isArray(s.files);
|
|
118
|
+
}
|
|
119
|
+
function isDynamicSource(s) {
|
|
120
|
+
return "files" in s && typeof s.files === "function";
|
|
121
|
+
}
|
|
122
|
+
//#endregion
|
|
123
|
+
//#region src/source/storage/content.ts
|
|
124
|
+
const EmptyLang = Symbol();
|
|
125
|
+
/**
|
|
126
|
+
* convert input files into virtual file system.
|
|
127
|
+
*
|
|
128
|
+
* in the storage, locale codes are removed from file paths, hence the same file will have same file paths in every storage.
|
|
129
|
+
*/
|
|
130
|
+
function createContentStorageBuilder(loaderConfig) {
|
|
131
|
+
const { input, plugins, i18n } = loaderConfig;
|
|
132
|
+
let parser;
|
|
133
|
+
if (!i18n) parser = (path) => [path];
|
|
134
|
+
else if (i18n.parser === "dir") {
|
|
135
|
+
const langSet = new Set(i18n.languages);
|
|
136
|
+
parser = (path) => {
|
|
137
|
+
const [locale, ...segs] = path.split("/");
|
|
138
|
+
if (!locale || segs.length === 0) return [path];
|
|
139
|
+
if (langSet.has(locale)) return [segs.join("/"), locale];
|
|
140
|
+
if (locale === "$") return [segs.join("/"), i18n.languages];
|
|
141
|
+
return [path];
|
|
142
|
+
};
|
|
143
|
+
} else {
|
|
144
|
+
const langSet = new Set(i18n.languages);
|
|
145
|
+
parser = (path) => {
|
|
146
|
+
const segs = path.split("/");
|
|
147
|
+
const base = segs.pop();
|
|
148
|
+
if (!base) return [path];
|
|
149
|
+
const parts = base.split(".");
|
|
150
|
+
if (parts.length < 3) return [path];
|
|
151
|
+
const [locale] = parts.splice(parts.length - 2, 1);
|
|
152
|
+
segs.push(parts.join("."));
|
|
153
|
+
if (langSet.has(locale)) return [segs.join("/"), locale];
|
|
154
|
+
if (locale === "$") return [segs.join("/"), i18n.languages];
|
|
155
|
+
return [path];
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
const fileMap = /* @__PURE__ */ new Map();
|
|
159
|
+
function scan(type, source) {
|
|
160
|
+
for (const inputFile of source.files) {
|
|
161
|
+
let file;
|
|
162
|
+
const path = normalize(source.baseDir ? `${source.baseDir}/${inputFile.path}` : inputFile.path);
|
|
163
|
+
if (inputFile.type === "page") file = {
|
|
164
|
+
format: "page",
|
|
165
|
+
type,
|
|
166
|
+
path,
|
|
167
|
+
slugs: inputFile.slugs,
|
|
168
|
+
data: inputFile.data,
|
|
169
|
+
absolutePath: inputFile.absolutePath
|
|
170
|
+
};
|
|
171
|
+
else file = {
|
|
172
|
+
format: "meta",
|
|
173
|
+
type,
|
|
174
|
+
path,
|
|
175
|
+
absolutePath: inputFile.absolutePath,
|
|
176
|
+
data: inputFile.data
|
|
177
|
+
};
|
|
178
|
+
const [storageKey, locale = i18n ? i18n.defaultLanguage : EmptyLang] = parser(path);
|
|
179
|
+
const entry = [storageKey, file];
|
|
180
|
+
if (Array.isArray(locale)) for (const item of locale) pushMapList(fileMap, item, entry);
|
|
181
|
+
else pushMapList(fileMap, locale, entry);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (isStaticSource(input)) scan(void 0, input);
|
|
185
|
+
else for (const k in input) scan(k, input[k]);
|
|
186
|
+
function makeStorage(locale, inherit) {
|
|
187
|
+
const storage = new FileSystem(inherit);
|
|
188
|
+
for (const [storageKey, file] of fileMap.get(locale) ?? []) storage.write(storageKey, file);
|
|
189
|
+
const context = { storage };
|
|
190
|
+
for (const plugin of plugins) plugin.transformStorage?.(context);
|
|
191
|
+
return storage;
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
i18n() {
|
|
195
|
+
const storages = {};
|
|
196
|
+
if (!i18n) return storages;
|
|
197
|
+
const fallbackLang = i18n.fallbackLanguage !== null ? i18n.fallbackLanguage ?? i18n.defaultLanguage : null;
|
|
198
|
+
function scan(lang) {
|
|
199
|
+
if (storages[lang]) return storages[lang];
|
|
200
|
+
return storages[lang] = makeStorage(lang, fallbackLang && fallbackLang !== lang ? scan(fallbackLang) : void 0);
|
|
201
|
+
}
|
|
202
|
+
for (const lang of i18n.languages) scan(lang);
|
|
203
|
+
return storages;
|
|
204
|
+
},
|
|
205
|
+
single() {
|
|
206
|
+
return makeStorage(EmptyLang);
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
function pushMapList(map, k, v) {
|
|
211
|
+
let list = map.get(k);
|
|
212
|
+
if (!list) {
|
|
213
|
+
list = [];
|
|
214
|
+
map.set(k, list);
|
|
215
|
+
}
|
|
216
|
+
list.push(v);
|
|
217
|
+
}
|
|
218
|
+
//#endregion
|
|
219
|
+
//#region src/source/page-tree/transformer-fallback.ts
|
|
220
|
+
function transformerFallback() {
|
|
221
|
+
const addedFiles = /* @__PURE__ */ new Set();
|
|
222
|
+
function shouldIgnore(context) {
|
|
223
|
+
return context.custom?._fallback === true;
|
|
224
|
+
}
|
|
225
|
+
return {
|
|
226
|
+
root(root) {
|
|
227
|
+
if (shouldIgnore(this)) return root;
|
|
228
|
+
const isolatedStorage = new FileSystem();
|
|
229
|
+
if (addedFiles.size === this.storage.files.size) return root;
|
|
230
|
+
for (const file of this.storage.getFiles()) {
|
|
231
|
+
if (addedFiles.has(file)) continue;
|
|
232
|
+
isolatedStorage.write(file, this.storage.read(file));
|
|
233
|
+
}
|
|
234
|
+
root.fallback = createPageTreeBuilder(isolatedStorage, {
|
|
235
|
+
...this.options,
|
|
236
|
+
idPrefix: this.options.idPrefix ? `fallback:${this.options.idPrefix}` : "fallback",
|
|
237
|
+
generateFallback: false,
|
|
238
|
+
context: {
|
|
239
|
+
...this.custom,
|
|
240
|
+
_fallback: true
|
|
241
|
+
}
|
|
242
|
+
}).root();
|
|
243
|
+
addedFiles.clear();
|
|
244
|
+
return root;
|
|
245
|
+
},
|
|
246
|
+
file(node, file) {
|
|
247
|
+
if (shouldIgnore(this)) return node;
|
|
248
|
+
if (file) addedFiles.add(file);
|
|
249
|
+
return node;
|
|
250
|
+
},
|
|
251
|
+
folder(node, _dir, metaPath) {
|
|
252
|
+
if (shouldIgnore(this)) return node;
|
|
253
|
+
if (metaPath) addedFiles.add(metaPath);
|
|
254
|
+
return node;
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
//#endregion
|
|
259
|
+
//#region src/source/page-tree/builder.ts
|
|
260
|
+
const group = /^\((?<name>.+)\)$/;
|
|
261
|
+
const link = /^(?<external>external:)?(?:\[(?<icon>[^\]]+)])?\[(?<name>[^\]]+)]\((?<url>[^)]+)\)$/;
|
|
262
|
+
const separator = /^---(?:\[(?<icon>[^\]]+)])?(?<name>.+)---|^---$/;
|
|
263
|
+
const rest = "...";
|
|
264
|
+
const restReversed = "z...a";
|
|
265
|
+
const extractPrefix = "...";
|
|
266
|
+
const excludePrefix = "!";
|
|
267
|
+
const SymbolUnfinished = Symbol("unfinished");
|
|
268
|
+
const SymbolName = Symbol("name");
|
|
269
|
+
const SymbolOwner = Symbol("owner");
|
|
270
|
+
function createPageTreeBuilder(input, options) {
|
|
271
|
+
const flattenPathToFullPath = /* @__PURE__ */ new Map();
|
|
272
|
+
const transformers = [];
|
|
273
|
+
/** virtual file path -> output page tree node (if cached) */
|
|
274
|
+
const pathToNode = /* @__PURE__ */ new Map();
|
|
275
|
+
let _nextId = 0;
|
|
276
|
+
const { noRef = false, idPrefix, url: getUrl, generateFallback = true, sort: { by: sortBy = "path", locales: sortLocales, options: sortOptions } = {} } = options;
|
|
277
|
+
/** passed as additional information to transformers */
|
|
278
|
+
let ctx;
|
|
279
|
+
if (options.transformers) transformers.push(...options.transformers);
|
|
280
|
+
if (generateFallback) transformers.push(transformerFallback());
|
|
281
|
+
if (Array.isArray(input)) {
|
|
282
|
+
const [locale, storages] = input;
|
|
283
|
+
ctx = {
|
|
284
|
+
get builder() {
|
|
285
|
+
return builder;
|
|
286
|
+
},
|
|
287
|
+
storage: storages[locale],
|
|
288
|
+
storages,
|
|
289
|
+
locale,
|
|
290
|
+
transformers,
|
|
291
|
+
custom: options.context,
|
|
292
|
+
options
|
|
293
|
+
};
|
|
294
|
+
} else ctx = {
|
|
295
|
+
get builder() {
|
|
296
|
+
return builder;
|
|
297
|
+
},
|
|
298
|
+
storage: input,
|
|
299
|
+
transformers,
|
|
300
|
+
custom: options.context,
|
|
301
|
+
options
|
|
302
|
+
};
|
|
303
|
+
const { storage, locale } = ctx;
|
|
304
|
+
for (const file of storage.getFiles()) {
|
|
305
|
+
const content = storage.read(file);
|
|
306
|
+
const flattenPath = file.substring(0, file.length - extname(file).length);
|
|
307
|
+
flattenPathToFullPath.set(flattenPath + "." + content.format, file);
|
|
308
|
+
}
|
|
309
|
+
function resolveFlattenPath(name, format) {
|
|
310
|
+
return flattenPathToFullPath.get(name + "." + format) ?? name;
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* try to register as the owner of `node`.
|
|
314
|
+
*
|
|
315
|
+
* when a node is referenced by multiple folders, this determines which folder they should belong to.
|
|
316
|
+
*
|
|
317
|
+
* @returns whether the owner owns the node.
|
|
318
|
+
*/
|
|
319
|
+
function own(ownerPath, node, priority) {
|
|
320
|
+
if (node[SymbolUnfinished]) return false;
|
|
321
|
+
const existing = node[SymbolOwner];
|
|
322
|
+
if (!existing) {
|
|
323
|
+
node[SymbolOwner] = {
|
|
324
|
+
owner: ownerPath,
|
|
325
|
+
priority
|
|
326
|
+
};
|
|
327
|
+
return true;
|
|
328
|
+
}
|
|
329
|
+
if (existing.owner === ownerPath) {
|
|
330
|
+
existing.priority = Math.max(existing.priority, priority);
|
|
331
|
+
return true;
|
|
332
|
+
}
|
|
333
|
+
if (existing.priority >= priority) return false;
|
|
334
|
+
const folder = pathToNode.get(existing.owner);
|
|
335
|
+
if (folder && folder.type === "folder") {
|
|
336
|
+
if (folder.index === node) delete folder.index;
|
|
337
|
+
else {
|
|
338
|
+
const idx = folder.children.indexOf(node);
|
|
339
|
+
if (idx !== -1) folder.children.splice(idx, 1);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
existing.owner = ownerPath;
|
|
343
|
+
existing.priority = priority;
|
|
344
|
+
return true;
|
|
345
|
+
}
|
|
346
|
+
function transferOwner(ownerPath, node) {
|
|
347
|
+
const existing = node[SymbolOwner];
|
|
348
|
+
if (existing) existing.owner = ownerPath;
|
|
349
|
+
}
|
|
350
|
+
function generateId(localId = `_${_nextId++}`) {
|
|
351
|
+
let id = localId;
|
|
352
|
+
if (locale) id = `${locale}:${id}`;
|
|
353
|
+
if (idPrefix) id = `${idPrefix}:${id}`;
|
|
354
|
+
return id;
|
|
355
|
+
}
|
|
356
|
+
function buildPaths(paths, filter, reversed = false) {
|
|
357
|
+
const nodes = [];
|
|
358
|
+
let indexNode;
|
|
359
|
+
for (const path of paths) {
|
|
360
|
+
if (filter && !filter(path)) continue;
|
|
361
|
+
const fileNode = buildFile(path);
|
|
362
|
+
if (fileNode) {
|
|
363
|
+
nodes.push(fileNode);
|
|
364
|
+
if (!indexNode && basename(path, extname(path)) === "index") indexNode = fileNode;
|
|
365
|
+
continue;
|
|
366
|
+
}
|
|
367
|
+
const dirNode = buildFolder(path);
|
|
368
|
+
if (dirNode) nodes.push(dirNode);
|
|
369
|
+
}
|
|
370
|
+
const factor = reversed ? -1 : 1;
|
|
371
|
+
const useName = sortBy === "name";
|
|
372
|
+
return nodes.sort((a, b) => {
|
|
373
|
+
if (a === indexNode) return -100;
|
|
374
|
+
if (b === indexNode) return 100;
|
|
375
|
+
const aT = useName && a[SymbolName] || (a.type === "folder" ? a.$ref.folder : a.$ref);
|
|
376
|
+
const bT = useName && b[SymbolName] || (b.type === "folder" ? b.$ref.folder : b.$ref);
|
|
377
|
+
const aK = a.type === "folder" ? 10 : 0;
|
|
378
|
+
const bK = b.type === "folder" ? 10 : 0;
|
|
379
|
+
return factor * (aT.localeCompare(bT, sortLocales, sortOptions) + (aK - bK));
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
function resolveLink(item) {
|
|
383
|
+
const match = link.exec(item);
|
|
384
|
+
if (!match?.groups) return;
|
|
385
|
+
const { icon, url, name, external } = match.groups;
|
|
386
|
+
let node = {
|
|
387
|
+
$id: generateId(),
|
|
388
|
+
type: "page",
|
|
389
|
+
icon,
|
|
390
|
+
name,
|
|
391
|
+
url,
|
|
392
|
+
external: external ? true : void 0
|
|
393
|
+
};
|
|
394
|
+
for (const transformer of transformers) {
|
|
395
|
+
if (!transformer.file) continue;
|
|
396
|
+
node = transformer.file.call(ctx, node);
|
|
397
|
+
}
|
|
398
|
+
return node;
|
|
399
|
+
}
|
|
400
|
+
function resolveSeparator(item) {
|
|
401
|
+
const match = separator.exec(item);
|
|
402
|
+
if (!match?.groups) return;
|
|
403
|
+
let node = {
|
|
404
|
+
$id: generateId(),
|
|
405
|
+
type: "separator",
|
|
406
|
+
icon: match.groups.icon,
|
|
407
|
+
name: match.groups.name
|
|
408
|
+
};
|
|
409
|
+
for (const transformer of transformers) {
|
|
410
|
+
if (!transformer.separator) continue;
|
|
411
|
+
node = transformer.separator.call(ctx, node);
|
|
412
|
+
}
|
|
413
|
+
return node;
|
|
414
|
+
}
|
|
415
|
+
function resolveFolderItem(folderPath, item, outputArray, excludedPaths) {
|
|
416
|
+
if (item === rest || item === restReversed) {
|
|
417
|
+
outputArray.push(item);
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
const separator = resolveSeparator(item);
|
|
421
|
+
if (separator) {
|
|
422
|
+
outputArray.push(separator);
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
const link = resolveLink(item);
|
|
426
|
+
if (link) {
|
|
427
|
+
outputArray.push(link);
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
if (item.startsWith(excludePrefix)) {
|
|
431
|
+
const path = joinPath(folderPath, item.slice(1));
|
|
432
|
+
excludedPaths.add(path);
|
|
433
|
+
excludedPaths.add(resolveFlattenPath(path, "page"));
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
if (item.startsWith(extractPrefix)) {
|
|
437
|
+
const path = joinPath(folderPath, item.slice(3));
|
|
438
|
+
const node = buildFolder(path);
|
|
439
|
+
if (!node) return;
|
|
440
|
+
const children = node.index ? [node.index, ...node.children] : node.children;
|
|
441
|
+
if (own(folderPath, node, 2)) {
|
|
442
|
+
for (const child of children) {
|
|
443
|
+
transferOwner(folderPath, child);
|
|
444
|
+
outputArray.push(child);
|
|
445
|
+
}
|
|
446
|
+
excludedPaths.add(path);
|
|
447
|
+
} else for (const child of children) if (own(folderPath, child, 2)) outputArray.push(child);
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
let path = joinPath(folderPath, item);
|
|
451
|
+
let node = buildFolder(path);
|
|
452
|
+
if (!node) {
|
|
453
|
+
path = resolveFlattenPath(path, "page");
|
|
454
|
+
node = buildFile(path);
|
|
455
|
+
}
|
|
456
|
+
if (!node || !own(folderPath, node, 2)) return;
|
|
457
|
+
outputArray.push(node);
|
|
458
|
+
excludedPaths.add(path);
|
|
459
|
+
}
|
|
460
|
+
function buildFolder(folderPath, isGlobalRoot = false) {
|
|
461
|
+
const cached = pathToNode.get(folderPath);
|
|
462
|
+
if (cached) return cached;
|
|
463
|
+
const files = storage.readDir(folderPath);
|
|
464
|
+
if (!files) return;
|
|
465
|
+
let metaPath = resolveFlattenPath(joinPath(folderPath, "meta"), "meta");
|
|
466
|
+
let meta = storage.read(metaPath);
|
|
467
|
+
if (!meta || meta.format !== "meta") {
|
|
468
|
+
meta = void 0;
|
|
469
|
+
metaPath = void 0;
|
|
470
|
+
}
|
|
471
|
+
const metadata = meta?.data ?? {};
|
|
472
|
+
const isRoot = metadata.root ?? isGlobalRoot;
|
|
473
|
+
let node = {
|
|
474
|
+
type: "folder",
|
|
475
|
+
name: null,
|
|
476
|
+
root: metadata.root,
|
|
477
|
+
defaultOpen: metadata.defaultOpen,
|
|
478
|
+
description: metadata.description,
|
|
479
|
+
collapsible: metadata.collapsible,
|
|
480
|
+
children: [],
|
|
481
|
+
$id: generateId(folderPath),
|
|
482
|
+
$ref: {
|
|
483
|
+
folder: folderPath,
|
|
484
|
+
meta: metaPath
|
|
485
|
+
},
|
|
486
|
+
[SymbolUnfinished]: true
|
|
487
|
+
};
|
|
488
|
+
pathToNode.set(folderPath, node);
|
|
489
|
+
let indexPath;
|
|
490
|
+
if (metadata.pagesIndex) {
|
|
491
|
+
const resolvedPath = resolveFlattenPath(joinPath(folderPath, metadata.pagesIndex), "page");
|
|
492
|
+
const page = buildFile(resolvedPath);
|
|
493
|
+
if (page && own(folderPath, page, 3)) {
|
|
494
|
+
indexPath = resolvedPath;
|
|
495
|
+
node.index = page;
|
|
496
|
+
} else node.index = resolveLink(metadata.pagesIndex);
|
|
497
|
+
} else if (!isRoot) {
|
|
498
|
+
const defaultPath = resolveFlattenPath(joinPath(folderPath, "index"), "page");
|
|
499
|
+
const page = buildFile(defaultPath);
|
|
500
|
+
if (page && own(folderPath, page, 0)) {
|
|
501
|
+
indexPath = defaultPath;
|
|
502
|
+
node.index = page;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
if (metadata.pages) {
|
|
506
|
+
const outputArray = [];
|
|
507
|
+
const excludedPaths = /* @__PURE__ */ new Set();
|
|
508
|
+
for (const item of metadata.pages) resolveFolderItem(folderPath, item, outputArray, excludedPaths);
|
|
509
|
+
if (indexPath) {
|
|
510
|
+
if (excludedPaths.has(indexPath)) delete node.index;
|
|
511
|
+
else excludedPaths.add(indexPath);
|
|
512
|
+
}
|
|
513
|
+
for (const item of outputArray) {
|
|
514
|
+
if (item !== rest && item !== restReversed) {
|
|
515
|
+
node.children.push(item);
|
|
516
|
+
continue;
|
|
517
|
+
}
|
|
518
|
+
const resolvedItem = buildPaths(files, (file) => !excludedPaths.has(file), item === restReversed);
|
|
519
|
+
for (const child of resolvedItem) if (own(folderPath, child, 0)) node.children.push(child);
|
|
520
|
+
}
|
|
521
|
+
} else for (const item of buildPaths(files, indexPath ? (file) => file !== indexPath : void 0)) if (own(folderPath, item, 0)) node.children.push(item);
|
|
522
|
+
node.icon = metadata.icon ?? node.index?.icon;
|
|
523
|
+
node.name = metadata.title ?? node.index?.name;
|
|
524
|
+
node[SymbolName] = metadata.title ?? node.index?.[SymbolName];
|
|
525
|
+
if (!node.name) {
|
|
526
|
+
const folderName = basename(folderPath);
|
|
527
|
+
node.name = pathToName(group.exec(folderName)?.[1] ?? folderName);
|
|
528
|
+
}
|
|
529
|
+
for (const transformer of transformers) {
|
|
530
|
+
if (!transformer.folder) continue;
|
|
531
|
+
node = transformer.folder.call(ctx, node, folderPath, metaPath);
|
|
532
|
+
}
|
|
533
|
+
pathToNode.set(folderPath, node);
|
|
534
|
+
delete node[SymbolUnfinished];
|
|
535
|
+
return node;
|
|
536
|
+
}
|
|
537
|
+
function buildFile(path) {
|
|
538
|
+
const cached = pathToNode.get(path);
|
|
539
|
+
if (cached) return cached;
|
|
540
|
+
const page = storage.read(path);
|
|
541
|
+
if (!page || page.format !== "page") return;
|
|
542
|
+
const { title, description, icon } = page.data;
|
|
543
|
+
let item = {
|
|
544
|
+
$id: generateId(path),
|
|
545
|
+
type: "page",
|
|
546
|
+
name: title ?? pathToName(basename(path, extname(path))),
|
|
547
|
+
description,
|
|
548
|
+
icon,
|
|
549
|
+
url: getUrl(page.slugs, ctx.locale),
|
|
550
|
+
$ref: path,
|
|
551
|
+
[SymbolName]: title
|
|
552
|
+
};
|
|
553
|
+
for (const transformer of transformers) {
|
|
554
|
+
if (!transformer.file) continue;
|
|
555
|
+
item = transformer.file.call(ctx, item, path);
|
|
556
|
+
}
|
|
557
|
+
pathToNode.set(path, item);
|
|
558
|
+
return item;
|
|
559
|
+
}
|
|
560
|
+
const builder = {
|
|
561
|
+
resolveFlattenPath,
|
|
562
|
+
root(id = "root", path = "") {
|
|
563
|
+
const folder = buildFolder(path, true);
|
|
564
|
+
for (const node of pathToNode.values()) {
|
|
565
|
+
delete node[SymbolName];
|
|
566
|
+
delete node[SymbolOwner];
|
|
567
|
+
if (noRef && "$ref" in node) delete node.$ref;
|
|
568
|
+
}
|
|
569
|
+
let root = {
|
|
570
|
+
type: "root",
|
|
571
|
+
$ref: folder?.$ref,
|
|
572
|
+
$id: generateId(id),
|
|
573
|
+
name: folder?.name || "Docs",
|
|
574
|
+
description: folder?.description,
|
|
575
|
+
children: folder ? folder.children : []
|
|
576
|
+
};
|
|
577
|
+
for (const transformer of transformers) {
|
|
578
|
+
if (!transformer.root) continue;
|
|
579
|
+
root = transformer.root.call(ctx, root);
|
|
580
|
+
}
|
|
581
|
+
return root;
|
|
582
|
+
}
|
|
583
|
+
};
|
|
584
|
+
return builder;
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* Get item name from file name
|
|
588
|
+
*
|
|
589
|
+
* @param name - file name
|
|
590
|
+
*/
|
|
591
|
+
function pathToName(name) {
|
|
592
|
+
const result = [];
|
|
593
|
+
for (const c of name) if (result.length === 0) result.push(c.toLocaleUpperCase());
|
|
594
|
+
else if (c === "-") result.push(" ");
|
|
595
|
+
else result.push(c);
|
|
596
|
+
return result.join("");
|
|
597
|
+
}
|
|
598
|
+
//#endregion
|
|
599
|
+
//#region src/source/loader.ts
|
|
600
|
+
function createPageIndexer({ url }) {
|
|
601
|
+
const pages = /* @__PURE__ */ new Map();
|
|
602
|
+
const pathToMeta = /* @__PURE__ */ new Map();
|
|
603
|
+
const pathToPage = /* @__PURE__ */ new Map();
|
|
604
|
+
const urlToPage = /* @__PURE__ */ new Map();
|
|
605
|
+
return {
|
|
606
|
+
scan(storage, lang) {
|
|
607
|
+
for (const filePath of storage.getFiles()) {
|
|
608
|
+
const item = storage.read(filePath);
|
|
609
|
+
const prefix = lang ? `${lang}.` : ".";
|
|
610
|
+
const path = prefix + filePath;
|
|
611
|
+
if (item.format === "meta") {
|
|
612
|
+
pathToMeta.set(path, {
|
|
613
|
+
type: item.type,
|
|
614
|
+
path: item.path,
|
|
615
|
+
absolutePath: item.absolutePath,
|
|
616
|
+
data: item.data
|
|
617
|
+
});
|
|
618
|
+
continue;
|
|
619
|
+
}
|
|
620
|
+
const page = {
|
|
621
|
+
type: item.type,
|
|
622
|
+
path: item.path,
|
|
623
|
+
absolutePath: item.absolutePath,
|
|
624
|
+
url: url(item.slugs, lang),
|
|
625
|
+
slugs: item.slugs,
|
|
626
|
+
data: item.data,
|
|
627
|
+
locale: lang
|
|
628
|
+
};
|
|
629
|
+
pathToPage.set(path, page);
|
|
630
|
+
pages.set(prefix + page.slugs.join("/"), page);
|
|
631
|
+
urlToPage.set(prefix + page.url, page);
|
|
632
|
+
}
|
|
633
|
+
},
|
|
634
|
+
getPage(path, lang = "") {
|
|
635
|
+
return pathToPage.get(`${lang}.${path}`);
|
|
636
|
+
},
|
|
637
|
+
getPageByUrl(url, lang = "") {
|
|
638
|
+
return urlToPage.get(`${lang}.${url}`);
|
|
639
|
+
},
|
|
640
|
+
getMeta(path, lang = "") {
|
|
641
|
+
return pathToMeta.get(`${lang}.${path}`);
|
|
642
|
+
},
|
|
643
|
+
getPageBySlugs(slugs, lang = "") {
|
|
644
|
+
let page = pages.get(`${lang}.${slugs.join("/")}`);
|
|
645
|
+
if (page) return page;
|
|
646
|
+
page = pages.get(`${lang}.${slugs.map(decodeURI).join("/")}`);
|
|
647
|
+
if (page) return page;
|
|
648
|
+
},
|
|
649
|
+
/** do not filter by language if `lang` is not specified */
|
|
650
|
+
getPages(lang) {
|
|
651
|
+
const out = [];
|
|
652
|
+
for (const [key, value] of pages.entries()) if (lang === void 0 || key.startsWith(`${lang}.`)) out.push(value);
|
|
653
|
+
return out;
|
|
654
|
+
}
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
function createGetUrl(baseUrl, i18n) {
|
|
658
|
+
const baseSlugs = baseUrl.split("/");
|
|
659
|
+
return (slugs, locale) => {
|
|
660
|
+
const hideLocale = i18n?.hideLocale ?? "never";
|
|
661
|
+
let urlLocale;
|
|
662
|
+
if (hideLocale === "never") urlLocale = locale;
|
|
663
|
+
else if (hideLocale === "default-locale" && locale !== i18n?.defaultLanguage) urlLocale = locale;
|
|
664
|
+
const paths = [...baseSlugs, ...slugs];
|
|
665
|
+
if (urlLocale) paths.unshift(urlLocale);
|
|
666
|
+
return `/${paths.filter((v) => v.length > 0).join("/")}`;
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
function loader(...args) {
|
|
670
|
+
const loaderConfig = args.length === 2 ? resolveConfig(args[0], args[1]) : resolveConfig(args[0].source, args[0]);
|
|
671
|
+
const { i18n } = loaderConfig;
|
|
672
|
+
const storage = i18n ? createContentStorageBuilder(loaderConfig).i18n() : createContentStorageBuilder(loaderConfig).single();
|
|
673
|
+
const indexer = createPageIndexer(loaderConfig);
|
|
674
|
+
if (storage instanceof FileSystem) indexer.scan(storage);
|
|
675
|
+
else for (const locale in storage) indexer.scan(storage[locale], locale);
|
|
676
|
+
let pageTrees;
|
|
677
|
+
function getPageTrees() {
|
|
678
|
+
if (pageTrees) return pageTrees;
|
|
679
|
+
const { plugins, url, pageTree: pageTreeConfig } = loaderConfig;
|
|
680
|
+
const transformers = [];
|
|
681
|
+
if (pageTreeConfig?.transformers) transformers.push(...pageTreeConfig.transformers);
|
|
682
|
+
for (const plugin of plugins) if (plugin.transformPageTree) transformers.push(plugin.transformPageTree);
|
|
683
|
+
const options = {
|
|
684
|
+
url,
|
|
685
|
+
...pageTreeConfig,
|
|
686
|
+
transformers
|
|
687
|
+
};
|
|
688
|
+
if (storage instanceof FileSystem) return pageTrees = createPageTreeBuilder(storage, options).root();
|
|
689
|
+
else {
|
|
690
|
+
const out = {};
|
|
691
|
+
for (const locale in storage) out[locale] = createPageTreeBuilder([locale, storage], options).root();
|
|
692
|
+
return pageTrees = out;
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
const out = {
|
|
696
|
+
_i18n: i18n,
|
|
697
|
+
get pageTree() {
|
|
698
|
+
return getPageTrees();
|
|
699
|
+
},
|
|
700
|
+
set pageTree(v) {
|
|
701
|
+
pageTrees = v;
|
|
702
|
+
},
|
|
703
|
+
getPageByHref(href, { dir = "", language = i18n?.defaultLanguage } = {}) {
|
|
704
|
+
const [value, hash] = href.split("#", 2);
|
|
705
|
+
let target;
|
|
706
|
+
if (value.startsWith("./") || value.startsWith("../")) {
|
|
707
|
+
let decoded = value;
|
|
708
|
+
try {
|
|
709
|
+
decoded = decodeURI(value);
|
|
710
|
+
} catch {}
|
|
711
|
+
const path = joinPath(dir, decoded);
|
|
712
|
+
target = indexer.getPage(path, language);
|
|
713
|
+
} else target = indexer.getPageByUrl(value, language);
|
|
714
|
+
if (target) return {
|
|
715
|
+
page: target,
|
|
716
|
+
hash
|
|
717
|
+
};
|
|
718
|
+
},
|
|
719
|
+
resolveHref(href, parent) {
|
|
720
|
+
if (href.startsWith("./") || href.startsWith("../")) {
|
|
721
|
+
const target = this.getPageByHref(href, {
|
|
722
|
+
dir: dirname(parent.path),
|
|
723
|
+
language: parent.locale
|
|
724
|
+
});
|
|
725
|
+
if (target) return target.hash ? `${target.page.url}#${target.hash}` : target.page.url;
|
|
726
|
+
}
|
|
727
|
+
return href;
|
|
728
|
+
},
|
|
729
|
+
getPages(language) {
|
|
730
|
+
return indexer.getPages(language);
|
|
731
|
+
},
|
|
732
|
+
getLanguages() {
|
|
733
|
+
const list = [];
|
|
734
|
+
if (!i18n) return list;
|
|
735
|
+
for (const language of i18n.languages) list.push({
|
|
736
|
+
language,
|
|
737
|
+
pages: this.getPages(language)
|
|
738
|
+
});
|
|
739
|
+
return list;
|
|
740
|
+
},
|
|
741
|
+
getPage(slugs = [], language = i18n?.defaultLanguage) {
|
|
742
|
+
return indexer.getPageBySlugs(slugs, language);
|
|
743
|
+
},
|
|
744
|
+
getNodeMeta(node, language = i18n?.defaultLanguage) {
|
|
745
|
+
const ref = node.$ref;
|
|
746
|
+
if (!ref?.meta) return;
|
|
747
|
+
return indexer.getMeta(ref.meta, language);
|
|
748
|
+
},
|
|
749
|
+
getNodePage(node, language = i18n?.defaultLanguage) {
|
|
750
|
+
const ref = node.$ref;
|
|
751
|
+
if (!ref) return;
|
|
752
|
+
return indexer.getPage(ref, language);
|
|
753
|
+
},
|
|
754
|
+
getPageTree(locale) {
|
|
755
|
+
if (i18n) {
|
|
756
|
+
const trees = getPageTrees();
|
|
757
|
+
if (locale && trees[locale]) return trees[locale];
|
|
758
|
+
return trees[i18n.defaultLanguage];
|
|
759
|
+
}
|
|
760
|
+
return getPageTrees();
|
|
761
|
+
},
|
|
762
|
+
generateParams(slug, lang) {
|
|
763
|
+
if (i18n) return this.getLanguages().flatMap((entry) => entry.pages.map((page) => ({
|
|
764
|
+
[slug ?? "slug"]: page.slugs,
|
|
765
|
+
[lang ?? "lang"]: entry.language
|
|
766
|
+
})));
|
|
767
|
+
return this.getPages().map((page) => ({ [slug ?? "slug"]: page.slugs }));
|
|
768
|
+
},
|
|
769
|
+
async serializePageTree(tree) {
|
|
770
|
+
const { renderToString } = await import("react-dom/server.edge");
|
|
771
|
+
return {
|
|
772
|
+
$fumadocs_loader: "page-tree",
|
|
773
|
+
data: visit(tree, (node) => {
|
|
774
|
+
node = { ...node };
|
|
775
|
+
if ("icon" in node && node.icon) node.icon = renderToString(node.icon);
|
|
776
|
+
if (node.name) node.name = renderToString(node.name);
|
|
777
|
+
if ("children" in node) node.children = [...node.children];
|
|
778
|
+
return node;
|
|
779
|
+
})
|
|
780
|
+
};
|
|
781
|
+
}
|
|
782
|
+
};
|
|
783
|
+
if (isStaticSource(loaderConfig.input)) loaderConfig.input.configureStatic?.({ loader: out });
|
|
784
|
+
else for (const [k, v] of Object.entries(loaderConfig.input)) v.configureStatic?.({
|
|
785
|
+
loader: out,
|
|
786
|
+
source: k
|
|
787
|
+
});
|
|
788
|
+
return out;
|
|
789
|
+
}
|
|
790
|
+
function resolveConfig(input, { slugs, baseSlugs, icon, plugins = [], baseUrl, url, ...base }) {
|
|
791
|
+
let config = {
|
|
792
|
+
...base,
|
|
793
|
+
url: url ? (...args) => normalizeUrl(url(...args)) : createGetUrl(baseUrl, base.i18n),
|
|
794
|
+
input,
|
|
795
|
+
plugins: buildPlugins([
|
|
796
|
+
icon && iconPlugin(icon),
|
|
797
|
+
...typeof plugins === "function" ? plugins({ typedPlugin: (plugin) => plugin }) : plugins,
|
|
798
|
+
slugsPlugin({
|
|
799
|
+
slugs,
|
|
800
|
+
baseSlugs
|
|
801
|
+
})
|
|
802
|
+
])
|
|
803
|
+
};
|
|
804
|
+
for (const plugin of config.plugins) {
|
|
805
|
+
const result = plugin.config?.(config);
|
|
806
|
+
if (result) config = result;
|
|
807
|
+
}
|
|
808
|
+
return config;
|
|
809
|
+
}
|
|
810
|
+
const priorityMap = {
|
|
811
|
+
pre: 1,
|
|
812
|
+
default: 0,
|
|
813
|
+
post: -1
|
|
814
|
+
};
|
|
815
|
+
function buildPlugins(plugins, sort = true) {
|
|
816
|
+
const flatten = [];
|
|
817
|
+
for (const plugin of plugins) if (Array.isArray(plugin)) flatten.push(...buildPlugins(plugin, false));
|
|
818
|
+
else if (plugin) flatten.push(plugin);
|
|
819
|
+
if (sort) return flatten.sort((a, b) => priorityMap[b.enforce ?? "default"] - priorityMap[a.enforce ?? "default"]);
|
|
820
|
+
return flatten;
|
|
821
|
+
}
|
|
822
|
+
//#endregion
|
|
823
|
+
//#region src/source/dynamic.ts
|
|
824
|
+
/** content loader API for static & dynamic content sources, with in-memory cache. */
|
|
825
|
+
function dynamicLoader(input, options) {
|
|
826
|
+
let cachedLoader;
|
|
827
|
+
const memoryCache = /* @__PURE__ */ new Map();
|
|
828
|
+
async function resolveSources() {
|
|
829
|
+
if (isStaticSource(input) || isDynamicSource(input)) return resolveSource(input);
|
|
830
|
+
const entries = await Promise.all(Object.entries(input).map(async ([k, v]) => [k, await resolveSource(v)]));
|
|
831
|
+
return Object.fromEntries(entries);
|
|
832
|
+
}
|
|
833
|
+
function resolveSource(v) {
|
|
834
|
+
if (isStaticSource(v)) return v;
|
|
835
|
+
const mapFiles = (files) => ({
|
|
836
|
+
baseDir: v.baseDir,
|
|
837
|
+
files,
|
|
838
|
+
configureStatic: v.configureStatic
|
|
839
|
+
});
|
|
840
|
+
if (!v.cache || v.cache === "memory") {
|
|
841
|
+
const cached = memoryCache.get(v);
|
|
842
|
+
if (cached && (cached.expires === void 0 || Date.now() < cached.expires)) return cached.value;
|
|
843
|
+
const value = Promise.resolve(v.files()).then(mapFiles).catch((e) => {
|
|
844
|
+
if (memoryCache.get(v)?.value === value) memoryCache.delete(v);
|
|
845
|
+
throw e;
|
|
846
|
+
});
|
|
847
|
+
memoryCache.set(v, {
|
|
848
|
+
value,
|
|
849
|
+
expires: v.staleTime !== void 0 ? Date.now() + v.staleTime : void 0
|
|
850
|
+
});
|
|
851
|
+
return value;
|
|
852
|
+
}
|
|
853
|
+
return Promise.resolve(v.files()).then(mapFiles);
|
|
854
|
+
}
|
|
855
|
+
const dynamicLoader = {
|
|
856
|
+
get: cache(async () => {
|
|
857
|
+
const resolved = await resolveSources();
|
|
858
|
+
if (cachedLoader && isEqual(cachedLoader.input, resolved)) return cachedLoader.value;
|
|
859
|
+
cachedLoader = {
|
|
860
|
+
input: resolved,
|
|
861
|
+
value: loader(resolved, options)
|
|
862
|
+
};
|
|
863
|
+
return cachedLoader.value;
|
|
864
|
+
}),
|
|
865
|
+
$inferPage: void 0,
|
|
866
|
+
$inferMeta: void 0,
|
|
867
|
+
async revalidate(name) {
|
|
868
|
+
dynamicLoader.invalidate(name);
|
|
869
|
+
if (name === void 0) await resolveSources();
|
|
870
|
+
else if (!isStaticSource(input) && !isDynamicSource(input)) await resolveSource(input[name]);
|
|
871
|
+
},
|
|
872
|
+
invalidate(name) {
|
|
873
|
+
if (isStaticSource(input)) return;
|
|
874
|
+
if (name === void 0) {
|
|
875
|
+
memoryCache.clear();
|
|
876
|
+
if (isDynamicSource(input)) input.invalidate?.();
|
|
877
|
+
else for (const v of Object.values(input)) if (isDynamicSource(v)) v.invalidate?.();
|
|
878
|
+
return;
|
|
879
|
+
}
|
|
880
|
+
if (isDynamicSource(input)) return;
|
|
881
|
+
const s = input[name];
|
|
882
|
+
if (!isDynamicSource(s)) return;
|
|
883
|
+
memoryCache.delete(s);
|
|
884
|
+
s.invalidate?.();
|
|
885
|
+
}
|
|
886
|
+
};
|
|
887
|
+
if (isDynamicSource(input) || isStaticSource(input)) {
|
|
888
|
+
input.configureDynamic?.({ loader: dynamicLoader });
|
|
889
|
+
if (isDynamicSource(input)) input.configure?.(dynamicLoader, {});
|
|
890
|
+
} else for (const [k, v] of Object.entries(input)) {
|
|
891
|
+
v.configureDynamic?.({
|
|
892
|
+
loader: dynamicLoader,
|
|
893
|
+
source: k
|
|
894
|
+
});
|
|
895
|
+
if (isDynamicSource(v)) v.configure?.(dynamicLoader, { source: k });
|
|
896
|
+
}
|
|
897
|
+
return dynamicLoader;
|
|
898
|
+
}
|
|
899
|
+
function isEqual(a, b) {
|
|
900
|
+
if (isStaticSource(a) && isStaticSource(b)) return isEqualShallow(a.files, b.files);
|
|
901
|
+
if (!isStaticSource(a) && !isStaticSource(b)) return Object.keys(b).every((k) => isEqualShallow(a[k].files, b[k].files));
|
|
902
|
+
return false;
|
|
903
|
+
}
|
|
904
|
+
//#endregion
|
|
905
|
+
export { update as a, multiple as i, createGetUrl as n, FileSystem as o, loader as r, dynamicLoader as t };
|