fumadocs-core 16.8.2 → 16.8.4

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.
@@ -1,5 +1,5 @@
1
1
  import { r as findPath } from "./utils-BFW0mEx9.js";
2
- import { r as extname, t as basename } from "./path-F_GnlBmT.js";
2
+ import { r as extname, t as basename } from "./path-B4h_WlT8.js";
3
3
  //#region src/search/server/build-index.ts
4
4
  async function buildIndexDefault(page) {
5
5
  let structuredData;
@@ -56,7 +56,7 @@ const cacheDefault = { create: function create() {
56
56
  return new ObjectWithoutPrototypeCache();
57
57
  } };
58
58
  //#endregion
59
- //#region ../../node_modules/.pnpm/@formatjs+intl-localematcher@0.8.3/node_modules/@formatjs/intl-localematcher/index.js
59
+ //#region ../../node_modules/.pnpm/@formatjs+intl-localematcher@0.8.4/node_modules/@formatjs/intl-localematcher/index.js
60
60
  /**
61
61
  * http://ecma-international.org/ecma-402/7.0/index.html#sec-canonicalizelocalelist
62
62
  * @param locales
@@ -2986,7 +2986,7 @@ const regions = {
2986
2986
  "VG",
2987
2987
  "VI"
2988
2988
  ],
2989
- EU: [
2989
+ "EU": [
2990
2990
  "AT",
2991
2991
  "BE",
2992
2992
  "BG",
@@ -3016,7 +3016,7 @@ const regions = {
3016
3016
  "SI",
3017
3017
  "SK"
3018
3018
  ],
3019
- EZ: [
3019
+ "EZ": [
3020
3020
  "AT",
3021
3021
  "BE",
3022
3022
  "CY",
@@ -3038,7 +3038,7 @@ const regions = {
3038
3038
  "SI",
3039
3039
  "SK"
3040
3040
  ],
3041
- QO: [
3041
+ "QO": [
3042
3042
  "AC",
3043
3043
  "AQ",
3044
3044
  "CP",
@@ -3046,7 +3046,7 @@ const regions = {
3046
3046
  "QO",
3047
3047
  "TA"
3048
3048
  ],
3049
- UN: [
3049
+ "UN": [
3050
3050
  "AD",
3051
3051
  "AE",
3052
3052
  "AF",
@@ -3512,6 +3512,7 @@ function findBestMatch(requestedLocales, supportedLocales, threshold = DEFAULT_M
3512
3512
  } catch {}
3513
3513
  }
3514
3514
  if (result.matchedSupportedLocale && lowestDistance === 0) return result;
3515
+ lowestDistance = Infinity;
3515
3516
  requestedLocales.forEach((desired, i) => {
3516
3517
  if (!result.distances[desired]) result.distances[desired] = {};
3517
3518
  canonicalizedSupportedLocales.forEach((canonicalLocale, supportedIndex) => {
@@ -1,6 +1,6 @@
1
1
  import { t as normalizeUrl } from "./normalize-url-J3kqKlu4.js";
2
2
  import { c as visit } from "./utils-BFW0mEx9.js";
3
- import { i as joinPath, n as dirname, o as slash, r as extname, s as splitPath, t as basename } from "./path-F_GnlBmT.js";
3
+ import { i as joinPath, n as dirname, o as slash, r as extname, s as splitPath, t as basename } from "./path-B4h_WlT8.js";
4
4
  import { slugsPlugin } from "./source/plugins/slugs.js";
5
5
  import { t as iconPlugin } from "./icon-BbWo08Fw.js";
6
6
  import path from "node:path";
@@ -56,12 +56,15 @@ var FileSystem = class {
56
56
  }
57
57
  makeDir(path) {
58
58
  const cur = [];
59
- for (const seg of splitPath(path)) {
59
+ let parentPath = "";
60
+ for (const seg of path.split("/")) {
60
61
  cur.push(seg);
61
62
  const curPath = cur.join("/");
62
- if (this.folders.has(curPath)) continue;
63
- this.folders.set(curPath, []);
64
- this.folders.get(dirname(curPath)).push(curPath);
63
+ if (!this.folders.has(curPath)) {
64
+ this.folders.set(curPath, []);
65
+ this.folders.get(parentPath).push(curPath);
66
+ }
67
+ parentPath = curPath;
65
68
  }
66
69
  }
67
70
  };
@@ -120,27 +123,6 @@ function isDynamicSource(s) {
120
123
  }
121
124
  //#endregion
122
125
  //#region src/source/storage/content.ts
123
- function isLocaleValid(locale) {
124
- return locale.length > 0 && !/\d+/.test(locale);
125
- }
126
- const parsers = {
127
- dir(path) {
128
- const [locale, ...segs] = path.split("/");
129
- if (locale && segs.length > 0 && isLocaleValid(locale)) return [segs.join("/"), locale];
130
- return [path];
131
- },
132
- dot(path) {
133
- const dir = dirname(path);
134
- const parts = basename(path).split(".");
135
- if (parts.length < 3) return [path];
136
- const [locale] = parts.splice(parts.length - 2, 1);
137
- if (!isLocaleValid(locale)) return [path];
138
- return [joinPath(dir, parts.join(".")), locale];
139
- },
140
- none(path) {
141
- return [path];
142
- }
143
- };
144
126
  const EmptyLang = Symbol();
145
127
  /**
146
128
  * convert input files into virtual file system.
@@ -149,8 +131,33 @@ const EmptyLang = Symbol();
149
131
  */
150
132
  function createContentStorageBuilder(loaderConfig) {
151
133
  const { input, plugins, i18n } = loaderConfig;
152
- const parser = i18n ? parsers[i18n.parser ?? "dot"] : parsers.none;
153
- const normalized = /* @__PURE__ */ new Map();
134
+ let parser;
135
+ if (!i18n) parser = (path) => [path];
136
+ else if (i18n.parser === "dir") {
137
+ const langSet = new Set(i18n.languages);
138
+ parser = (path) => {
139
+ const [locale, ...segs] = path.split("/");
140
+ if (!locale || segs.length === 0) return [path];
141
+ if (langSet.has(locale)) return [segs.join("/"), locale];
142
+ if (locale === "$") return [segs.join("/"), i18n.languages];
143
+ return [path];
144
+ };
145
+ } else {
146
+ const langSet = new Set(i18n.languages);
147
+ parser = (path) => {
148
+ const segs = path.split("/");
149
+ const base = segs.pop();
150
+ if (!base) return [path];
151
+ const parts = base.split(".");
152
+ if (parts.length < 3) return [path];
153
+ const [locale] = parts.splice(parts.length - 2, 1);
154
+ segs.push(parts.join("."));
155
+ if (langSet.has(locale)) return [segs.join("/"), locale];
156
+ if (locale === "$") return [segs.join("/"), i18n.languages];
157
+ return [path];
158
+ };
159
+ }
160
+ const fileMap = /* @__PURE__ */ new Map();
154
161
  function scan(type, source) {
155
162
  for (const inputFile of source.files) {
156
163
  let file;
@@ -169,23 +176,17 @@ function createContentStorageBuilder(loaderConfig) {
169
176
  absolutePath: inputFile.absolutePath,
170
177
  data: inputFile.data
171
178
  };
172
- const [pathWithoutLocale, locale = i18n ? i18n.defaultLanguage : EmptyLang] = parser(file.path);
173
- let list = normalized.get(locale);
174
- if (!list) {
175
- list = [];
176
- normalized.set(locale, list);
177
- }
178
- list.push({
179
- pathWithoutLocale,
180
- file
181
- });
179
+ const [storageKey, locale = i18n ? i18n.defaultLanguage : EmptyLang] = parser(file.path);
180
+ const entry = [storageKey, file];
181
+ if (Array.isArray(locale)) for (const item of locale) pushMapList(fileMap, item, entry);
182
+ else pushMapList(fileMap, locale, entry);
182
183
  }
183
184
  }
184
185
  if (isStaticSource(input)) scan(void 0, input);
185
186
  else for (const k in input) scan(k, input[k]);
186
187
  function makeStorage(locale, inherit) {
187
188
  const storage = new FileSystem(inherit);
188
- for (const { pathWithoutLocale, file } of normalized.get(locale) ?? []) storage.write(pathWithoutLocale, file);
189
+ for (const [storageKey, file] of fileMap.get(locale) ?? []) storage.write(storageKey, file);
189
190
  const context = { storage };
190
191
  for (const plugin of plugins) plugin.transformStorage?.(context);
191
192
  return storage;
@@ -217,6 +218,14 @@ function normalizePath(path) {
217
218
  if (segments[0] === "." || segments[0] === "..") throw new Error("It must not start with './' or '../'");
218
219
  return segments.join("/");
219
220
  }
221
+ function pushMapList(map, k, v) {
222
+ let list = map.get(k);
223
+ if (!list) {
224
+ list = [];
225
+ map.set(k, list);
226
+ }
227
+ list.push(v);
228
+ }
220
229
  //#endregion
221
230
  //#region src/source/page-tree/transformer-fallback.ts
222
231
  function transformerFallback() {
@@ -585,6 +594,7 @@ function createPageIndexer({ url }) {
585
594
  page = pages.get(`${lang}.${slugs.map(decodeURI).join("/")}`);
586
595
  if (page) return page;
587
596
  },
597
+ /** do not filter by language if `lang` is not specified */
588
598
  getPages(lang) {
589
599
  const out = [];
590
600
  for (const [key, value] of pages.entries()) if (lang === void 0 || key.startsWith(`${lang}.`)) out.push(value);
@@ -1,7 +1,7 @@
1
1
  import { remarkHeading } from "./remark-heading.js";
2
2
  import { generateCodeBlockTabs, parseCodeBlockAttributes } from "./codeblock-utils.js";
3
3
  import { remarkGfm } from "./remark-gfm.js";
4
- import { i as transformerIcon, r as transformerTab } from "../rehype-code.core-Cz33III3.js";
4
+ import { i as transformerIcon, r as transformerTab } from "../rehype-code.core-D2jcAuJI.js";
5
5
  import { rehypeCode, rehypeCodeDefaultOptions } from "./rehype-code.js";
6
6
  import { remarkImage } from "./remark-image.js";
7
7
  import { defaultStringifier, remarkStructure, remarkStructureDefaultOptions, structure } from "./remark-structure.js";
@@ -1,2 +1,2 @@
1
- import { i as transformerIcon, n as rehypeCodeDefaultOptions, r as transformerTab, t as createRehypeCode } from "../rehype-code.core-Cz33III3.js";
1
+ import { i as transformerIcon, n as rehypeCodeDefaultOptions, r as transformerTab, t as createRehypeCode } from "../rehype-code.core-D2jcAuJI.js";
2
2
  export { createRehypeCode, rehypeCodeDefaultOptions, transformerIcon, transformerTab };
@@ -1,5 +1,5 @@
1
1
  import { defaultShikiFactory, wasmShikiFactory } from "../highlight/shiki/full.js";
2
- import { i as transformerIcon, n as rehypeCodeDefaultOptions$1, r as transformerTab, t as createRehypeCode } from "../rehype-code.core-Cz33III3.js";
2
+ import { i as transformerIcon, n as rehypeCodeDefaultOptions$1, r as transformerTab, t as createRehypeCode } from "../rehype-code.core-D2jcAuJI.js";
3
3
  //#region src/mdx-plugins/rehype-code.ts
4
4
  const rehypeCodeDefaultOptions = {
5
5
  engine: "js",
@@ -13,12 +13,17 @@ function basename(path, ext) {
13
13
  return path.substring(idx === -1 ? 0 : idx + 1, ext ? path.length - ext.length : path.length);
14
14
  }
15
15
  function extname(path) {
16
- const dotIdx = path.lastIndexOf(".");
17
- if (dotIdx !== -1) return path.substring(dotIdx);
16
+ for (let i = path.length - 1; i >= 0; i--) {
17
+ const c = path[i];
18
+ if (c === ".") return path.substring(i);
19
+ if (c === "/") return "";
20
+ }
18
21
  return "";
19
22
  }
20
23
  function dirname(path) {
21
- return path.split("/").slice(0, -1).join("/");
24
+ const idx = path.lastIndexOf("/");
25
+ if (idx === -1) return "";
26
+ return path.substring(0, idx);
22
27
  }
23
28
  /**
24
29
  * Split path into segments, trailing/leading slashes are removed
@@ -39,11 +44,12 @@ function splitPath(path) {
39
44
  */
40
45
  function joinPath(...paths) {
41
46
  const out = [];
42
- const parsed = paths.flatMap(splitPath);
47
+ const parsed = paths.flatMap((path) => path.split("/"));
43
48
  for (const seg of parsed) switch (seg) {
44
49
  case "..":
45
50
  out.pop();
46
51
  break;
52
+ case "":
47
53
  case ".": break;
48
54
  default: out.push(seg);
49
55
  }
@@ -622,7 +622,9 @@ function createRehypeCode(highlighterFactory) {
622
622
  if (options.icon !== false) transformers.push(transformerIcon(options.icon));
623
623
  if (options.tab !== false) transformers.push(transformerTab());
624
624
  const lazy = options.lazy ?? true;
625
- await Promise.all([highlighter.loadTheme(...getRequiredThemes(options)), !lazy && highlighter.loadLanguage(...options.langs ?? Object.keys(highlighter.getBundledLanguages()))]);
625
+ let preloadLangs = options.langs;
626
+ if (!lazy) preloadLangs ??= Object.keys(highlighter.getBundledLanguages());
627
+ await Promise.all([highlighter.loadTheme(...getRequiredThemes(options)), preloadLangs && highlighter.loadLanguage(...preloadLangs)]);
626
628
  return rehypeShikiFromHighlighter(highlighter, {
627
629
  ...options,
628
630
  transformers
@@ -1,5 +1,5 @@
1
1
  import { t as createEndpoint } from "../endpoint-CAUHRXte.js";
2
- import { n as buildBreadcrumbs, r as buildIndexDefault, t as buildDocuments } from "../build-doc-BOME1tMw.js";
2
+ import { n as buildBreadcrumbs, r as buildIndexDefault, t as buildDocuments } from "../build-doc-8RxTPr1J.js";
3
3
  import { n as search, t as createDocument } from "../utils-CkDkYuX8.js";
4
4
  import Search from "flexsearch";
5
5
  //#region src/search/flexsearch.ts
@@ -16,6 +16,9 @@ const processor = remark();
16
16
  function createContentHighlighter(query) {
17
17
  const regex = typeof query === "string" ? buildRegexFromQuery(query) : query;
18
18
  return {
19
+ /**
20
+ * @deprecated use `highlightMarkdown()` instead.
21
+ */
19
22
  highlight(content) {
20
23
  if (!regex) return [{
21
24
  type: "text",
@@ -41,6 +44,9 @@ function createContentHighlighter(query) {
41
44
  });
42
45
  return out;
43
46
  },
47
+ /**
48
+ * @param content - Markdown, it assumes the content is already sanitized & safe, no escape is performed.
49
+ */
44
50
  highlightMarkdown(content) {
45
51
  if (!regex) return content;
46
52
  const tree = processor.parse(content);
@@ -1,5 +1,5 @@
1
1
  import { n as defaultReadOptions, t as createEndpoint } from "../endpoint-CAUHRXte.js";
2
- import { n as buildBreadcrumbs, r as buildIndexDefault, t as buildDocuments } from "../build-doc-BOME1tMw.js";
2
+ import { n as buildBreadcrumbs, r as buildIndexDefault, t as buildDocuments } from "../build-doc-8RxTPr1J.js";
3
3
  import { n as searchSimple, t as searchAdvanced } from "../advanced-BCAHgGV0.js";
4
4
  import { create, insertMultiple, save } from "@orama/orama";
5
5
  //#region src/search/orama/_stemmers.ts
@@ -1,4 +1,4 @@
1
- import { i as isStaticSource, n as loader, r as isDynamicSource } from "../loader-B6mFh9dX.js";
1
+ import { i as isStaticSource, n as loader, r as isDynamicSource } from "../loader-CeIUqWDI.js";
2
2
  import { cache } from "react";
3
3
  //#region src/source/dynamic.ts
4
4
  function dynamicLoader(input, options) {
@@ -1,5 +1,5 @@
1
- import { a as path_exports } from "../path-F_GnlBmT.js";
2
- import { a as multiple, c as FileSystem, i as isStaticSource, n as loader, o as source, r as isDynamicSource, s as update, t as createGetUrl } from "../loader-B6mFh9dX.js";
1
+ import { a as path_exports } from "../path-B4h_WlT8.js";
2
+ import { a as multiple, c as FileSystem, i as isStaticSource, n as loader, o as source, r as isDynamicSource, s as update, t as createGetUrl } from "../loader-CeIUqWDI.js";
3
3
  import { getSlugs } from "./plugins/slugs.js";
4
4
  import { llms } from "./llms.js";
5
5
  export { FileSystem, path_exports as PathUtils, createGetUrl, getSlugs, isDynamicSource, isStaticSource, llms, loader, multiple, source, update };
@@ -53,7 +53,15 @@ function llms(loader, config = {}) {
53
53
  return out.join("\n");
54
54
  }
55
55
  return {
56
+ /**
57
+ * generate `llms.txt` content in Markdown format.
58
+ *
59
+ * use `indexNode(node)` instead for more control (e.g. add extra sections to output).
60
+ */
56
61
  index,
62
+ /**
63
+ * generate `llms.txt` content for a single page tree node.
64
+ */
57
65
  indexNode(node, lang) {
58
66
  return formatNode(node, 0, { lang });
59
67
  }
@@ -1,4 +1,4 @@
1
- import { n as dirname, r as extname, t as basename } from "../../path-F_GnlBmT.js";
1
+ import { n as dirname, r as extname, t as basename } from "../../path-B4h_WlT8.js";
2
2
  //#region src/source/plugins/slugs.ts
3
3
  /**
4
4
  * Generate slugs for pages if missing
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fumadocs-core",
3
- "version": "16.8.2",
3
+ "version": "16.8.4",
4
4
  "description": "The React.js library for building a documentation website",
5
5
  "keywords": [
6
6
  "Docs",
@@ -113,13 +113,13 @@
113
113
  "vfile": "^6.0.3"
114
114
  },
115
115
  "devDependencies": {
116
- "@formatjs/intl-localematcher": "^0.8.3",
116
+ "@formatjs/intl-localematcher": "^0.8.4",
117
117
  "@mdx-js/mdx": "^3.1.1",
118
- "@mixedbread/sdk": "^0.61.0",
118
+ "@mixedbread/sdk": "^0.62.0",
119
119
  "@orama/core": "^1.2.19",
120
120
  "@oramacloud/client": "^2.1.4",
121
121
  "@shikijs/transformers": "^4.0.2",
122
- "@tanstack/react-router": "1.168.23",
122
+ "@tanstack/react-router": "1.168.24",
123
123
  "@types/estree-jsx": "^1.0.5",
124
124
  "@types/hast": "^3.0.4",
125
125
  "@types/js-yaml": "^4.0.9",
@@ -128,21 +128,21 @@
128
128
  "@types/node": "25.6.0",
129
129
  "@types/react": "^19.2.14",
130
130
  "@types/react-dom": "^19.2.3",
131
- "algoliasearch": "5.50.2",
131
+ "algoliasearch": "5.51.0",
132
132
  "flexsearch": "^0.8.212",
133
133
  "image-size": "^2.0.2",
134
- "lucide-react": "^1.8.0",
134
+ "lucide-react": "^1.11.0",
135
135
  "negotiator": "^1.0.0",
136
136
  "next": "16.2.4",
137
137
  "npm-to-yarn": "^3.0.1",
138
138
  "path-to-regexp": "^8.4.2",
139
- "react-router": "^7.14.1",
139
+ "react-router": "^7.14.2",
140
140
  "remark-directive": "^4.0.0",
141
141
  "remark-mdx": "^3.1.1",
142
142
  "remove-markdown": "^0.6.3",
143
- "tsdown": "0.21.9",
143
+ "tsdown": "0.21.10",
144
144
  "typescript": "^6.0.3",
145
- "waku": "1.0.0-alpha.7",
145
+ "waku": "1.0.0-alpha.8",
146
146
  "zod": "^4.3.6",
147
147
  "tsconfig": "0.0.0"
148
148
  },
@@ -224,7 +224,7 @@
224
224
  },
225
225
  "inlinedDependencies": {
226
226
  "@formatjs/fast-memoize": "3.1.2",
227
- "@formatjs/intl-localematcher": "0.8.3",
227
+ "@formatjs/intl-localematcher": "0.8.4",
228
228
  "@shikijs/transformers": "4.0.2",
229
229
  "image-size": "2.0.2",
230
230
  "negotiator": "1.0.0",