fumadocs-core 16.15.0 → 16.15.2
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/dist/{loader-BfwY7fPX.js → dynamic-Dgf8t2t2.js} +90 -8
- package/dist/i18n/middleware.js +65 -2
- package/dist/{index-C8oBtRaX2.d.ts → index-DQWu2opy.d.ts} +30 -23
- package/dist/negotiation/index.d.ts +1 -3
- package/dist/negotiation/index.js +378 -2
- package/dist/search/flexsearch.d.ts +2 -2
- package/dist/search/mixedbread.d.ts +1 -1
- package/dist/search/server.d.ts +1 -1
- package/dist/{server-ugF9hnpc.d.ts → server-BoDPRfLi.d.ts} +1 -1
- package/dist/source/dynamic.d.ts +1 -1
- package/dist/source/dynamic.js +1 -73
- package/dist/source/index.d.ts +2 -2
- package/dist/source/index.js +2 -2
- package/dist/source/llms.d.ts +1 -1
- package/dist/source/plugins/lucide-icons.d.ts +1 -1
- package/dist/source/plugins/slugs.d.ts +1 -1
- package/dist/source/plugins/status-badges.d.ts +1 -1
- package/package.json +8 -11
- package/dist/negotiation-DAsKgSvF.js +0 -1056
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { r as normalizeUrl } from "./url-BVHvi3_K.js";
|
|
2
2
|
import { c as visit } from "./utils-Dn9VIXRN.js";
|
|
3
|
+
import { t as isEqualShallow } from "./is-equal-LdLqRs0o.js";
|
|
3
4
|
import { a as normalize, i as joinPath, n as dirname, r as extname, t as basename } from "./path-1H5VzYiT.js";
|
|
4
5
|
import { slugsPlugin } from "./source/plugins/slugs.js";
|
|
5
6
|
import { t as iconPlugin } from "./icon-BILaoXeg.js";
|
|
7
|
+
import { cache } from "react";
|
|
6
8
|
//#region src/source/storage/file-system.ts
|
|
7
9
|
/**
|
|
8
10
|
* In memory file system.
|
|
@@ -83,11 +85,8 @@ function multiple(sources) {
|
|
|
83
85
|
})) };
|
|
84
86
|
return out;
|
|
85
87
|
}
|
|
86
|
-
function source(config) {
|
|
87
|
-
return { files: [...config.pages, ...config.metas] };
|
|
88
|
-
}
|
|
89
88
|
/**
|
|
90
|
-
* update a source object in-place.
|
|
89
|
+
* update a **static** source object in-place.
|
|
91
90
|
*/
|
|
92
91
|
function update(source) {
|
|
93
92
|
return {
|
|
@@ -160,10 +159,11 @@ function createContentStorageBuilder(loaderConfig) {
|
|
|
160
159
|
function scan(type, source) {
|
|
161
160
|
for (const inputFile of source.files) {
|
|
162
161
|
let file;
|
|
162
|
+
const path = normalize(source.baseDir ? `${source.baseDir}/${inputFile.path}` : inputFile.path);
|
|
163
163
|
if (inputFile.type === "page") file = {
|
|
164
164
|
format: "page",
|
|
165
165
|
type,
|
|
166
|
-
path
|
|
166
|
+
path,
|
|
167
167
|
slugs: inputFile.slugs,
|
|
168
168
|
data: inputFile.data,
|
|
169
169
|
absolutePath: inputFile.absolutePath
|
|
@@ -171,11 +171,11 @@ function createContentStorageBuilder(loaderConfig) {
|
|
|
171
171
|
else file = {
|
|
172
172
|
format: "meta",
|
|
173
173
|
type,
|
|
174
|
-
path
|
|
174
|
+
path,
|
|
175
175
|
absolutePath: inputFile.absolutePath,
|
|
176
176
|
data: inputFile.data
|
|
177
177
|
};
|
|
178
|
-
const [storageKey, locale = i18n ? i18n.defaultLanguage : EmptyLang] = parser(
|
|
178
|
+
const [storageKey, locale = i18n ? i18n.defaultLanguage : EmptyLang] = parser(path);
|
|
179
179
|
const entry = [storageKey, file];
|
|
180
180
|
if (Array.isArray(locale)) for (const item of locale) pushMapList(fileMap, item, entry);
|
|
181
181
|
else pushMapList(fileMap, locale, entry);
|
|
@@ -820,4 +820,86 @@ function buildPlugins(plugins, sort = true) {
|
|
|
820
820
|
return flatten;
|
|
821
821
|
}
|
|
822
822
|
//#endregion
|
|
823
|
-
|
|
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 };
|
package/dist/i18n/middleware.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { t as getNegotiator } from "../negotiation-DAsKgSvF.js";
|
|
2
1
|
import { NextResponse } from "next/server.js";
|
|
3
2
|
//#region ../../node_modules/.pnpm/@formatjs+fast-memoize@3.1.7/node_modules/@formatjs/fast-memoize/index.js
|
|
4
3
|
function memoize(fn, options) {
|
|
@@ -3738,6 +3737,70 @@ function match(requestedLocales, availableLocales, defaultLocale, opts) {
|
|
|
3738
3737
|
return ResolveLocale(availableLocales, CanonicalizeLocaleList(requestedLocales), { localeMatcher: opts?.algorithm || "best fit" }, [], {}, () => defaultLocale).locale;
|
|
3739
3738
|
}
|
|
3740
3739
|
//#endregion
|
|
3740
|
+
//#region src/utils/accept-language.ts
|
|
3741
|
+
function parseAcceptLanguage(header) {
|
|
3742
|
+
const specs = [];
|
|
3743
|
+
for (const section of header.split(",")) {
|
|
3744
|
+
const [rawTag, ...params] = section.split(";");
|
|
3745
|
+
const full = rawTag.trim().toLowerCase();
|
|
3746
|
+
if (full.length === 0) continue;
|
|
3747
|
+
let quality = 1;
|
|
3748
|
+
for (const param of params) {
|
|
3749
|
+
const separator = param.indexOf("=");
|
|
3750
|
+
if (separator === -1 || param.slice(0, separator).trim().toLowerCase() !== "q") continue;
|
|
3751
|
+
const parsed = Number.parseFloat(param.slice(separator + 1));
|
|
3752
|
+
if (!Number.isNaN(parsed)) quality = parsed;
|
|
3753
|
+
}
|
|
3754
|
+
const dash = full.indexOf("-");
|
|
3755
|
+
specs.push({
|
|
3756
|
+
prefix: dash === -1 ? full : full.slice(0, dash),
|
|
3757
|
+
full,
|
|
3758
|
+
quality,
|
|
3759
|
+
order: specs.length
|
|
3760
|
+
});
|
|
3761
|
+
}
|
|
3762
|
+
return specs;
|
|
3763
|
+
}
|
|
3764
|
+
function matchLanguage(language, specs) {
|
|
3765
|
+
const full = language.trim().toLowerCase();
|
|
3766
|
+
const dash = full.indexOf("-");
|
|
3767
|
+
const prefix = dash === -1 ? full : full.slice(0, dash);
|
|
3768
|
+
const best = {
|
|
3769
|
+
language,
|
|
3770
|
+
quality: 0,
|
|
3771
|
+
specificity: 0,
|
|
3772
|
+
order: -1
|
|
3773
|
+
};
|
|
3774
|
+
for (const spec of specs) {
|
|
3775
|
+
let specificity;
|
|
3776
|
+
if (spec.full === full) specificity = 4;
|
|
3777
|
+
else if (spec.prefix === full) specificity = 2;
|
|
3778
|
+
else if (spec.full === prefix) specificity = 1;
|
|
3779
|
+
else if (spec.full === "*") specificity = 0;
|
|
3780
|
+
else continue;
|
|
3781
|
+
if ((specificity - best.specificity || spec.quality - best.quality || spec.order - best.order) > 0) {
|
|
3782
|
+
best.quality = spec.quality;
|
|
3783
|
+
best.specificity = specificity;
|
|
3784
|
+
best.order = spec.order;
|
|
3785
|
+
}
|
|
3786
|
+
}
|
|
3787
|
+
if (best.quality > 0) return best;
|
|
3788
|
+
}
|
|
3789
|
+
/**
|
|
3790
|
+
* Filter `available` down to the languages the `Accept-Language` header accepts, ordered by
|
|
3791
|
+
* client preference. A missing (`null`) header accepts everything.
|
|
3792
|
+
*/
|
|
3793
|
+
function negotiateLanguages(header, available) {
|
|
3794
|
+
const specs = parseAcceptLanguage(header ?? "*");
|
|
3795
|
+
const matches = [];
|
|
3796
|
+
for (const language of available) {
|
|
3797
|
+
const match = matchLanguage(language, specs);
|
|
3798
|
+
if (match) matches.push(match);
|
|
3799
|
+
}
|
|
3800
|
+
matches.sort((a, b) => b.quality - a.quality || b.specificity - a.specificity || a.order - b.order);
|
|
3801
|
+
return matches.map((match) => match.language);
|
|
3802
|
+
}
|
|
3803
|
+
//#endregion
|
|
3741
3804
|
//#region src/i18n/middleware.ts
|
|
3742
3805
|
const DefaultFormatter = {
|
|
3743
3806
|
get(url) {
|
|
@@ -3773,7 +3836,7 @@ function createI18nMiddleware({ languages, defaultLanguage, format = DefaultForm
|
|
|
3773
3836
|
if (pathLocale && !languages.includes(pathLocale)) pathLocale = void 0;
|
|
3774
3837
|
if (!pathLocale) {
|
|
3775
3838
|
if (hideLocale === "default-locale") return NextResponse.rewrite(formatter.add(url, defaultLanguage));
|
|
3776
|
-
const preferred = match(
|
|
3839
|
+
const preferred = match(negotiateLanguages(request.headers.get("accept-language"), languages), languages, defaultLanguage);
|
|
3777
3840
|
if (hideLocale === "always") {
|
|
3778
3841
|
const locale = request.cookies.get(cookieName)?.value ?? preferred;
|
|
3779
3842
|
return NextResponse.rewrite(formatter.add(url, locale));
|
|
@@ -333,18 +333,33 @@ type SourceUnion<Config extends SourceConfig = SourceConfig> = StaticSource<Conf
|
|
|
333
333
|
* @deprecated use `StaticSource<Config>` instead
|
|
334
334
|
*/
|
|
335
335
|
type Source<Config extends SourceConfig = SourceConfig> = StaticSource<Config>;
|
|
336
|
-
interface
|
|
337
|
-
files
|
|
336
|
+
interface GenericSourceOptions {
|
|
337
|
+
/** the base directory for generated virtual files */
|
|
338
|
+
baseDir?: string;
|
|
338
339
|
/**
|
|
339
|
-
*
|
|
340
|
+
* when the source is attached to a new static loader, before loader output is accessible.
|
|
341
|
+
*
|
|
342
|
+
* can be called multiple times when attached to a dynamic loader.
|
|
340
343
|
**/
|
|
341
344
|
configureStatic?: (opts: {
|
|
342
345
|
loader: LoaderOutput;
|
|
343
346
|
source?: string;
|
|
344
347
|
}) => void;
|
|
348
|
+
/**
|
|
349
|
+
* when the source is attached to a dynamic loader.
|
|
350
|
+
*
|
|
351
|
+
* called at most once for each source object.
|
|
352
|
+
**/
|
|
353
|
+
configureDynamic?: (opts: {
|
|
354
|
+
loader: DynamicLoader;
|
|
355
|
+
source?: string;
|
|
356
|
+
}) => void;
|
|
357
|
+
}
|
|
358
|
+
interface StaticSource<Config extends SourceConfig = SourceConfig> extends GenericSourceOptions {
|
|
359
|
+
files: VirtualFile<Config>[];
|
|
345
360
|
}
|
|
346
361
|
/** one dynamic source object can only be used by one dynamic loader */
|
|
347
|
-
|
|
362
|
+
type DynamicSource<Config extends SourceConfig = SourceConfig> = GenericSourceOptions & {
|
|
348
363
|
/**
|
|
349
364
|
* - `memory`: the dynamic loader's in-memory cache handles caching.
|
|
350
365
|
* - `custom`: the source handles caching itself. When the newer result of `files()` is (shallowly) different from the previous result, the source is considered revalidated, and all associated properties will be re-computed.
|
|
@@ -353,20 +368,19 @@ interface DynamicSource<Config extends SourceConfig = SourceConfig> {
|
|
|
353
368
|
**/
|
|
354
369
|
cache?: 'memory' | 'custom';
|
|
355
370
|
files: () => Awaitable<VirtualFile<Config>[]>;
|
|
371
|
+
/** @deprecated use `configureDynamic` instead */
|
|
356
372
|
configure?: (loader: DynamicLoader, opts: {
|
|
357
373
|
source?: string;
|
|
358
374
|
}) => void;
|
|
359
|
-
/**
|
|
360
|
-
* called when the source is attached to a new static loader, before loader output is accessible.
|
|
361
|
-
*
|
|
362
|
-
* it can be called multiple times, when the parent dynamic loader creates a different static loader.
|
|
363
|
-
**/
|
|
364
|
-
configureStatic?: (opts: {
|
|
365
|
-
loader: LoaderOutput;
|
|
366
|
-
source?: string;
|
|
367
|
-
}) => void;
|
|
375
|
+
/** when the source is invalidated */
|
|
368
376
|
invalidate?: () => void;
|
|
369
|
-
}
|
|
377
|
+
} & ({
|
|
378
|
+
cache?: 'memory';
|
|
379
|
+
/** enable time-based revalidation, the previous result will be stale after the specified duration (ms) */
|
|
380
|
+
staleTime?: number;
|
|
381
|
+
} | {
|
|
382
|
+
cache: 'custom';
|
|
383
|
+
});
|
|
370
384
|
type SourceConfig = {
|
|
371
385
|
pageData: PageData;
|
|
372
386
|
metaData: MetaData;
|
|
@@ -423,13 +437,6 @@ declare function multiple<T extends Record<string, StaticSource>>(sources: T): T
|
|
|
423
437
|
type: k;
|
|
424
438
|
};
|
|
425
439
|
}> : never; } : never;
|
|
426
|
-
declare function source<Page extends PageData, Meta extends MetaData>(config: {
|
|
427
|
-
pages: VirtualPage<Page>[];
|
|
428
|
-
metas: VirtualMeta<Meta>[];
|
|
429
|
-
}): StaticSource<{
|
|
430
|
-
pageData: Page;
|
|
431
|
-
metaData: Meta;
|
|
432
|
-
}>;
|
|
433
440
|
interface SourceUpdater<Config extends SourceConfig> {
|
|
434
441
|
files: <Page extends PageData, Meta extends MetaData>(fn: (files: VirtualFile<Config>[]) => (VirtualPage<Page> | VirtualMeta<Meta>)[]) => SourceUpdater<{
|
|
435
442
|
pageData: Page;
|
|
@@ -446,7 +453,7 @@ interface SourceUpdater<Config extends SourceConfig> {
|
|
|
446
453
|
build: () => StaticSource<Config>;
|
|
447
454
|
}
|
|
448
455
|
/**
|
|
449
|
-
* update a source object in-place.
|
|
456
|
+
* update a **static** source object in-place.
|
|
450
457
|
*/
|
|
451
458
|
declare function update<Config extends SourceConfig>(source: StaticSource<Config>): SourceUpdater<Config>;
|
|
452
459
|
declare namespace path_d_exports {
|
|
@@ -503,4 +510,4 @@ declare function llms<C extends LoaderConfig = LoaderConfig>(loader: LoaderOutpu
|
|
|
503
510
|
indexNode(node: Node, lang?: string): string;
|
|
504
511
|
};
|
|
505
512
|
//#endregion
|
|
506
|
-
export {
|
|
513
|
+
export { SlugsPluginOptions as A, ContentStoragePageFile as B, Meta as C, loader as D, createGetUrl as E, PageTreeBuilderContext as F, PageTreeOptions as I, PageTreeTransformer as L, slugsFromData as M, slugsPlugin as N, types_d_exports as O, PageTreeBuilder as P, ContentStorage as R, LoaderPluginOption as S, ResolvedLoaderConfig as T, FileSystem as V, InferPageType as _, MetaData as a, LoaderOutput as b, SourceUnion as c, multiple as d, update as f, InferMetaType as g, dynamicLoader as h, DynamicSource as i, getSlugs as j, SlugFn as k, StaticSource as l, DynamicLoaderConfig as m, llms as n, PageData as o, DynamicLoader as p, path_d_exports as r, Source as s, LLMsConfig as t, VirtualFile as u, LoaderConfig as v, Page as w, LoaderPlugin as x, LoaderOptions as y, ContentStorageMetaFile as z };
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import Negotiator from "negotiator";
|
|
2
1
|
//#region src/negotiation/index.d.ts
|
|
3
|
-
declare function getNegotiator(request: Request): Negotiator;
|
|
4
2
|
/**
|
|
5
3
|
* Rewrite incoming path matching the `source` pattern into the `destination` pattern.
|
|
6
4
|
*
|
|
@@ -16,4 +14,4 @@ declare function isMarkdownPreferred(request: Request, options?: {
|
|
|
16
14
|
markdownMediaTypes?: string[];
|
|
17
15
|
}): boolean;
|
|
18
16
|
//#endregion
|
|
19
|
-
export {
|
|
17
|
+
export { isMarkdownPreferred, rewritePath };
|