mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-26 06:31:49 +00:00
Core: default the type of plugins to LoaderPluginOption[]
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
---
|
||||
'fumadocs-core': minor
|
||||
---
|
||||
|
||||
**[Loader API] Default the type of `plugins` to `LoaderPluginOption[]`**
|
||||
|
||||
It should no longer enforce type checks on custom properties from your content source.
|
||||
|
||||
For creating fully typed plugins (with custom properties), use the following pattern:
|
||||
|
||||
```ts
|
||||
import { loader } from 'fumadocs-core/source';
|
||||
import { docs } from 'fumadocs-mdx:collections/server';
|
||||
import { lucideIconsPlugin } from 'fumadocs-core/source/lucide-icons';
|
||||
|
||||
export const source = loader(docs.toFumadocsSource(), {
|
||||
baseUrl: '/docs',
|
||||
plugins: ({ typedPlugin }) => [
|
||||
lucideIconsPlugin(),
|
||||
typedPlugin({
|
||||
// the plugin config
|
||||
}),
|
||||
],
|
||||
});
|
||||
```
|
||||
@@ -20,7 +20,11 @@ import {
|
||||
} from '@/source/page-tree/builder';
|
||||
import { joinPath } from './path';
|
||||
import { normalizeUrl } from '@/utils/normalize-url';
|
||||
import { buildPlugins, type LoaderPlugin } from '@/source/plugins';
|
||||
import {
|
||||
buildPlugins,
|
||||
type LoaderPluginOption,
|
||||
type LoaderPlugin,
|
||||
} from '@/source/plugins';
|
||||
import { slugsPlugin } from '@/source/plugins/slugs';
|
||||
import { iconPlugin, type IconResolver } from '@/source/plugins/icon';
|
||||
|
||||
@@ -29,26 +33,21 @@ export interface LoaderConfig {
|
||||
i18n: I18nConfig | undefined;
|
||||
}
|
||||
|
||||
export interface SourceConfig {
|
||||
pageData: PageData;
|
||||
metaData: MetaData;
|
||||
}
|
||||
|
||||
export interface LoaderOptions<
|
||||
S extends SourceConfig = SourceConfig,
|
||||
I18n extends I18nConfig | undefined = I18nConfig | undefined,
|
||||
> {
|
||||
export interface LoaderOptions<C extends LoaderConfig = LoaderConfig> {
|
||||
baseUrl: string;
|
||||
i18n?: I18n;
|
||||
i18n?: C['i18n'];
|
||||
url?: UrlFn;
|
||||
|
||||
/**
|
||||
* Additional options for page tree builder
|
||||
*/
|
||||
pageTree?: PageTreeOptions<S>;
|
||||
|
||||
plugins?: (LoaderPlugin<S> | LoaderPlugin<S>[] | undefined)[];
|
||||
pageTree?: PageTreeOptions<C>;
|
||||
|
||||
plugins?:
|
||||
| LoaderPluginOption[]
|
||||
| ((context: {
|
||||
typedPlugin: (plugin: LoaderPlugin<C>) => LoaderPlugin;
|
||||
}) => LoaderPluginOption[]);
|
||||
icon?: IconResolver;
|
||||
slugs?: (info: { path: string }) => string[];
|
||||
}
|
||||
@@ -66,6 +65,11 @@ export interface Source<Config extends SourceConfig = SourceConfig> {
|
||||
files: VirtualFile<Config>[];
|
||||
}
|
||||
|
||||
export interface SourceConfig {
|
||||
pageData: PageData;
|
||||
metaData: MetaData;
|
||||
}
|
||||
|
||||
interface SharedFileInfo {
|
||||
/**
|
||||
* Virtualized file path (relative to content directory)
|
||||
@@ -227,7 +231,10 @@ export function loader<
|
||||
I18n extends I18nConfig | undefined = undefined,
|
||||
>(
|
||||
source: Source<Config>,
|
||||
options: LoaderOptions<NoInfer<Config>, I18n>,
|
||||
options: LoaderOptions<{
|
||||
source: NoInfer<Config>;
|
||||
i18n: I18n;
|
||||
}>,
|
||||
): LoaderOutput<{
|
||||
source: Config;
|
||||
i18n: I18n;
|
||||
@@ -237,7 +244,10 @@ export function loader<
|
||||
Config extends SourceConfig,
|
||||
I18n extends I18nConfig | undefined = undefined,
|
||||
>(
|
||||
options: LoaderOptions<NoInfer<Config>, I18n> & {
|
||||
options: LoaderOptions<{
|
||||
source: NoInfer<Config>;
|
||||
i18n: I18n;
|
||||
}> & {
|
||||
source: Source<Config>;
|
||||
},
|
||||
): LoaderOutput<{
|
||||
@@ -277,7 +287,11 @@ function resolveConfig(
|
||||
plugins: buildPlugins([
|
||||
slugsPlugin(slugs),
|
||||
icon && iconPlugin(icon),
|
||||
...plugins,
|
||||
...(typeof plugins === 'function'
|
||||
? plugins({
|
||||
typedPlugin: (plugin) => plugin as unknown as LoaderPlugin,
|
||||
})
|
||||
: plugins),
|
||||
]),
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type * as PageTree from '@/page-tree/definitions';
|
||||
import type { MetaData, PageData, SourceConfig, UrlFn } from '@/source';
|
||||
import type { LoaderConfig, MetaData, PageData, UrlFn } from '@/source';
|
||||
import type { ContentStorage } from '@/source/storage/content';
|
||||
import { basename, extname, joinPath } from '@/source/path';
|
||||
import { transformerFallback } from '@/source/page-tree/transformer-fallback';
|
||||
@@ -47,7 +47,7 @@ export interface PageTreeTransformer<
|
||||
) => PageTree.Root;
|
||||
}
|
||||
|
||||
export interface PageTreeOptions<Config extends SourceConfig = SourceConfig> {
|
||||
export interface PageTreeOptions<Config extends LoaderConfig = LoaderConfig> {
|
||||
id?: string;
|
||||
/**
|
||||
* Remove references to the file path of original nodes (`$ref`)
|
||||
@@ -65,7 +65,10 @@ export interface PageTreeOptions<Config extends SourceConfig = SourceConfig> {
|
||||
/**
|
||||
* Additional page tree transformers to apply
|
||||
*/
|
||||
transformers?: PageTreeTransformer<Config['pageData'], Config['metaData']>[];
|
||||
transformers?: PageTreeTransformer<
|
||||
Config['source']['pageData'],
|
||||
Config['source']['metaData']
|
||||
>[];
|
||||
}
|
||||
|
||||
export interface PageTreeBuilder {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { ContentStorage } from '@/source/storage/content';
|
||||
import type { PageTreeTransformer } from '@/source/page-tree/builder';
|
||||
import type { ResolvedLoaderConfig, SourceConfig } from '@/source/loader';
|
||||
import type { LoaderConfig, ResolvedLoaderConfig } from '@/source/loader';
|
||||
|
||||
export interface LoaderPlugin<Config extends SourceConfig = SourceConfig> {
|
||||
export interface LoaderPlugin<Config extends LoaderConfig = LoaderConfig> {
|
||||
name?: string;
|
||||
|
||||
/**
|
||||
@@ -23,18 +23,26 @@ export interface LoaderPlugin<Config extends SourceConfig = SourceConfig> {
|
||||
* transform the storage after loading
|
||||
*/
|
||||
transformStorage?: (context: {
|
||||
storage: ContentStorage<Config['pageData'], Config['metaData']>;
|
||||
storage: ContentStorage<
|
||||
Config['source']['pageData'],
|
||||
Config['source']['metaData']
|
||||
>;
|
||||
}) => void;
|
||||
|
||||
/**
|
||||
* transform the generated page tree
|
||||
*/
|
||||
transformPageTree?: PageTreeTransformer<
|
||||
Config['pageData'],
|
||||
Config['metaData']
|
||||
Config['source']['pageData'],
|
||||
Config['source']['metaData']
|
||||
>;
|
||||
}
|
||||
|
||||
export type LoaderPluginOption<Config extends LoaderConfig = LoaderConfig> =
|
||||
| LoaderPlugin<Config>
|
||||
| LoaderPluginOption<Config>[]
|
||||
| undefined;
|
||||
|
||||
const priorityMap = {
|
||||
pre: 1,
|
||||
default: 0,
|
||||
@@ -42,17 +50,21 @@ const priorityMap = {
|
||||
};
|
||||
|
||||
export function buildPlugins(
|
||||
plugins: (LoaderPlugin | LoaderPlugin[] | undefined)[],
|
||||
plugins: LoaderPluginOption[],
|
||||
sort = true,
|
||||
): LoaderPlugin[] {
|
||||
const flatten: LoaderPlugin[] = [];
|
||||
|
||||
for (const plugin of plugins) {
|
||||
if (Array.isArray(plugin)) flatten.push(...plugin);
|
||||
if (Array.isArray(plugin)) flatten.push(...buildPlugins(plugin, false));
|
||||
else if (plugin) flatten.push(plugin);
|
||||
}
|
||||
|
||||
return flatten.sort(
|
||||
(a, b) =>
|
||||
priorityMap[b.enforce ?? 'default'] - priorityMap[a.enforce ?? 'default'],
|
||||
);
|
||||
if (sort)
|
||||
return flatten.sort(
|
||||
(a, b) =>
|
||||
priorityMap[b.enforce ?? 'default'] -
|
||||
priorityMap[a.enforce ?? 'default'],
|
||||
);
|
||||
return flatten;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user