mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-26 23:49:51 +00:00
MDX: Improve types
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'fumadocs-mdx': patch
|
||||
---
|
||||
|
||||
Improve types
|
||||
@@ -1,3 +1,5 @@
|
||||
import { defineDocs } from 'fumadocs-mdx/config';
|
||||
|
||||
export const { docs, meta } = defineDocs();
|
||||
export const { docs, meta } = defineDocs({
|
||||
dir: 'content/docs',
|
||||
});
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { defineDocs } from 'fumadocs-mdx/config';
|
||||
|
||||
export const { docs, meta } = defineDocs();
|
||||
export const { docs, meta } = defineDocs({
|
||||
dir: 'content/docs',
|
||||
});
|
||||
|
||||
@@ -50,10 +50,16 @@ export interface DocCollection<
|
||||
async?: Async;
|
||||
}
|
||||
|
||||
export interface DocsCollection {
|
||||
export interface DocsCollection<
|
||||
DocSchema extends StandardSchemaV1 = StandardSchemaV1,
|
||||
MetaSchema extends StandardSchemaV1 = StandardSchemaV1,
|
||||
Async extends boolean = boolean,
|
||||
> {
|
||||
type: 'docs';
|
||||
docs: DocCollection;
|
||||
meta: MetaCollection;
|
||||
dir: string | string[];
|
||||
|
||||
docs: DocCollection<DocSchema, Async>;
|
||||
meta: MetaCollection<MetaSchema>;
|
||||
}
|
||||
|
||||
export function defineCollections<
|
||||
@@ -80,9 +86,9 @@ export function defineCollections<
|
||||
}
|
||||
|
||||
export function defineDocs<
|
||||
DocData extends StandardSchemaV1 = typeof frontmatterSchema,
|
||||
MetaData extends StandardSchemaV1 = typeof metaSchema,
|
||||
DocAsync extends boolean = false,
|
||||
DocSchema extends StandardSchemaV1 = typeof frontmatterSchema,
|
||||
MetaSchema extends StandardSchemaV1 = typeof metaSchema,
|
||||
Async extends boolean = false,
|
||||
>(options?: {
|
||||
/**
|
||||
* The directory to scan files
|
||||
@@ -91,27 +97,46 @@ export function defineDocs<
|
||||
*/
|
||||
dir?: string | string[];
|
||||
|
||||
docs?: Omit<DocCollection<DocData, DocAsync>, 'dir' | 'type'>;
|
||||
meta?: Omit<MetaCollection<MetaData>, 'dir' | 'type'>;
|
||||
docs?: Omit<DocCollection<DocSchema, Async>, 'dir' | 'type'>;
|
||||
meta?: Omit<MetaCollection<MetaSchema>, 'dir' | 'type'>;
|
||||
}): {
|
||||
type: 'docs';
|
||||
docs: ReturnType<typeof defineCollections<'doc', DocData, DocAsync>>;
|
||||
meta: ReturnType<typeof defineCollections<'meta', MetaData, false>>;
|
||||
|
||||
docs: {
|
||||
type: 'doc';
|
||||
_type: {
|
||||
schema: DocSchema;
|
||||
async: Async;
|
||||
};
|
||||
};
|
||||
|
||||
meta: {
|
||||
type: 'meta';
|
||||
_type: {
|
||||
schema: MetaSchema;
|
||||
};
|
||||
};
|
||||
} {
|
||||
if (!options)
|
||||
console.warn(
|
||||
'[`source.config.ts`] Deprecated: please pass options to `defineDocs()` and specify a `dir`.',
|
||||
);
|
||||
const dir = options?.dir ?? 'content/docs';
|
||||
|
||||
return {
|
||||
type: 'docs',
|
||||
// @ts-expect-error -- internal type inferring
|
||||
docs: defineCollections({
|
||||
type: 'doc',
|
||||
dir,
|
||||
schema: frontmatterSchema as unknown as DocData,
|
||||
schema: frontmatterSchema,
|
||||
...options?.docs,
|
||||
}),
|
||||
// @ts-expect-error -- internal type inferring
|
||||
meta: defineCollections({
|
||||
type: 'meta',
|
||||
dir,
|
||||
schema: metaSchema as unknown as MetaData,
|
||||
schema: metaSchema,
|
||||
...options?.meta,
|
||||
}),
|
||||
};
|
||||
|
||||
@@ -1,68 +1,23 @@
|
||||
import { type BaseCollectionEntry, type MarkdownProps } from '@/config/types';
|
||||
import { createCompiler, type MDXOptions } from '@fumadocs/mdx-remote';
|
||||
import * as fs from 'node:fs/promises';
|
||||
import type { LoadedConfig } from '@/utils/config';
|
||||
import { remarkInclude } from '@/mdx-plugins/remark-include';
|
||||
import type { defineCollections } from '@/config/define';
|
||||
import {
|
||||
remarkStructure,
|
||||
type StructuredData,
|
||||
} from 'fumadocs-core/mdx-plugins';
|
||||
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
||||
import { _runtime, createMDXSource, type RuntimeFile } from '@/runtime/index';
|
||||
import type { MetaData, PageData, Source } from 'fumadocs-core/source';
|
||||
|
||||
export interface RuntimeAsync {
|
||||
doc: <C>(
|
||||
files: RuntimeFile[],
|
||||
collection: string,
|
||||
config: LoadedConfig,
|
||||
) => C extends ReturnType<
|
||||
typeof defineCollections<'doc', infer Schema extends StandardSchemaV1, true>
|
||||
>
|
||||
? (StandardSchemaV1.InferOutput<Schema> &
|
||||
BaseCollectionEntry & {
|
||||
load: () => Promise<MarkdownProps>;
|
||||
})[]
|
||||
: never;
|
||||
docs: <Docs>(
|
||||
docs: RuntimeFile[],
|
||||
metas: RuntimeFile[],
|
||||
collection: string,
|
||||
config: LoadedConfig,
|
||||
) => Docs extends {
|
||||
type: 'docs';
|
||||
docs: unknown;
|
||||
meta: unknown;
|
||||
}
|
||||
? {
|
||||
docs: ReturnType<typeof _runtimeAsync.doc<Docs['docs']>>;
|
||||
meta: ReturnType<typeof _runtime.meta<Docs['meta']>>;
|
||||
toFumadocsSource: () => Source<{
|
||||
pageData: ReturnType<
|
||||
typeof _runtimeAsync.doc<Docs['docs']>
|
||||
>[number] extends PageData & BaseCollectionEntry
|
||||
? ReturnType<typeof _runtimeAsync.doc<Docs['docs']>>[number]
|
||||
: never;
|
||||
metaData: ReturnType<
|
||||
typeof _runtime.meta<Docs['meta']>
|
||||
>[number] extends MetaData & BaseCollectionEntry
|
||||
? ReturnType<typeof _runtime.meta<Docs['meta']>>[number]
|
||||
: never;
|
||||
}>;
|
||||
}
|
||||
: never;
|
||||
}
|
||||
import { createMDXSource, _runtime } from '@/runtime/index';
|
||||
import type { RuntimeAsync } from '@/runtime/types';
|
||||
|
||||
async function initCompiler(config: LoadedConfig, collection: string) {
|
||||
let col = config.collections.get(collection);
|
||||
if (col?.type === 'docs') col = col.docs;
|
||||
let mdxOptions: MDXOptions | undefined;
|
||||
|
||||
let mdxOptions: MDXOptions;
|
||||
const col = config.collections.get(collection);
|
||||
if (col?.type === 'doc') mdxOptions = col.mdxOptions as MDXOptions;
|
||||
else if (col?.type === 'docs')
|
||||
mdxOptions = col.docs?.mdxOptions as MDXOptions;
|
||||
|
||||
if (col?.type === 'doc' && col.mdxOptions) {
|
||||
mdxOptions = col.mdxOptions as MDXOptions;
|
||||
} else {
|
||||
if (!mdxOptions) {
|
||||
const options =
|
||||
typeof config.global?.mdxOptions === 'function'
|
||||
? await config.global.mdxOptions()
|
||||
|
||||
@@ -3,71 +3,11 @@ import {
|
||||
type PageData,
|
||||
type Source,
|
||||
} from 'fumadocs-core/source';
|
||||
import {
|
||||
type BaseCollectionEntry,
|
||||
type defineCollections,
|
||||
type FileInfo,
|
||||
type MarkdownProps,
|
||||
} from '@/config';
|
||||
import { type BaseCollectionEntry } from '@/config';
|
||||
import type { VirtualFile } from 'fumadocs-core/source';
|
||||
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
||||
import type { Runtime } from '@/runtime/types';
|
||||
|
||||
export interface RuntimeFile {
|
||||
info: FileInfo;
|
||||
data: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export interface Runtime {
|
||||
doc: <C>(
|
||||
files: RuntimeFile[],
|
||||
) => C extends ReturnType<
|
||||
typeof defineCollections<
|
||||
'doc',
|
||||
infer Schema extends StandardSchemaV1,
|
||||
false
|
||||
>
|
||||
>
|
||||
? (Omit<MarkdownProps, keyof StandardSchemaV1.InferOutput<Schema>> &
|
||||
StandardSchemaV1.InferOutput<Schema> &
|
||||
BaseCollectionEntry)[]
|
||||
: never;
|
||||
meta: <C>(
|
||||
files: RuntimeFile[],
|
||||
) => C extends ReturnType<
|
||||
typeof defineCollections<
|
||||
'meta',
|
||||
infer Schema extends StandardSchemaV1,
|
||||
false
|
||||
>
|
||||
>
|
||||
? (StandardSchemaV1.InferOutput<Schema> & BaseCollectionEntry)[]
|
||||
: never;
|
||||
docs: <Docs>(
|
||||
docs: RuntimeFile[],
|
||||
metas: RuntimeFile[],
|
||||
) => Docs extends {
|
||||
type: 'docs';
|
||||
docs: unknown;
|
||||
meta: unknown;
|
||||
}
|
||||
? {
|
||||
docs: ReturnType<typeof _runtime.doc<Docs['docs']>>;
|
||||
meta: ReturnType<typeof _runtime.meta<Docs['meta']>>;
|
||||
toFumadocsSource: () => Source<{
|
||||
pageData: ReturnType<
|
||||
typeof _runtime.doc<Docs['docs']>
|
||||
>[number] extends PageData & BaseCollectionEntry
|
||||
? ReturnType<typeof _runtime.doc<Docs['docs']>>[number]
|
||||
: never;
|
||||
metaData: ReturnType<
|
||||
typeof _runtime.meta<Docs['meta']>
|
||||
>[number] extends MetaData & BaseCollectionEntry
|
||||
? ReturnType<typeof _runtime.meta<Docs['meta']>>[number]
|
||||
: never;
|
||||
}>;
|
||||
}
|
||||
: never;
|
||||
}
|
||||
export type { RuntimeFile } from '@/runtime/types';
|
||||
|
||||
export const _runtime: Runtime = {
|
||||
doc(files) {
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
import type { BaseCollectionEntry, FileInfo, MarkdownProps } from '@/config';
|
||||
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
||||
import type { MetaData, PageData, Source } from 'fumadocs-core/source';
|
||||
import type { LoadedConfig } from '@/utils/config';
|
||||
|
||||
export interface RuntimeFile {
|
||||
info: FileInfo;
|
||||
data: Record<string, unknown>;
|
||||
}
|
||||
|
||||
type DocOut<Schema extends StandardSchemaV1> = Omit<
|
||||
MarkdownProps,
|
||||
keyof StandardSchemaV1.InferOutput<Schema>
|
||||
> &
|
||||
StandardSchemaV1.InferOutput<Schema> &
|
||||
BaseCollectionEntry;
|
||||
|
||||
type MetaOut<Schema extends StandardSchemaV1> =
|
||||
StandardSchemaV1.InferOutput<Schema> & BaseCollectionEntry;
|
||||
|
||||
export interface Runtime {
|
||||
doc: <C>(files: RuntimeFile[]) => C extends {
|
||||
type: 'doc';
|
||||
_type: {
|
||||
schema: infer Schema extends StandardSchemaV1;
|
||||
};
|
||||
}
|
||||
? DocOut<Schema>[]
|
||||
: never;
|
||||
meta: <C>(files: RuntimeFile[]) => C extends {
|
||||
type: 'meta';
|
||||
|
||||
_type: {
|
||||
schema: infer Schema extends StandardSchemaV1;
|
||||
};
|
||||
}
|
||||
? MetaOut<Schema>[]
|
||||
: never;
|
||||
docs: <Docs>(
|
||||
docs: RuntimeFile[],
|
||||
metas: RuntimeFile[],
|
||||
) => Docs extends {
|
||||
type: 'docs';
|
||||
|
||||
docs: {
|
||||
type: 'doc';
|
||||
_type: {
|
||||
schema: infer DocSchema extends StandardSchemaV1;
|
||||
};
|
||||
};
|
||||
|
||||
meta: {
|
||||
type: 'meta';
|
||||
_type: {
|
||||
schema: infer MetaSchema extends StandardSchemaV1;
|
||||
};
|
||||
};
|
||||
}
|
||||
? {
|
||||
docs: DocOut<DocSchema>[];
|
||||
meta: MetaOut<MetaSchema>[];
|
||||
|
||||
toFumadocsSource: () => Source<{
|
||||
pageData: DocOut<DocSchema> extends PageData
|
||||
? DocOut<DocSchema>
|
||||
: never;
|
||||
metaData: MetaOut<MetaSchema> extends MetaData
|
||||
? MetaOut<MetaSchema>
|
||||
: never;
|
||||
}>;
|
||||
}
|
||||
: never;
|
||||
}
|
||||
|
||||
type AsyncDocOut<Schema extends StandardSchemaV1> =
|
||||
StandardSchemaV1.InferOutput<Schema> &
|
||||
BaseCollectionEntry & {
|
||||
load: () => Promise<MarkdownProps>;
|
||||
};
|
||||
|
||||
export interface RuntimeAsync {
|
||||
doc: <C>(
|
||||
files: RuntimeFile[],
|
||||
collection: string,
|
||||
config: LoadedConfig,
|
||||
) => C extends {
|
||||
type: 'doc';
|
||||
_type: {
|
||||
schema: infer Schema extends StandardSchemaV1;
|
||||
};
|
||||
}
|
||||
? AsyncDocOut<Schema>[]
|
||||
: never;
|
||||
docs: <Docs>(
|
||||
docs: RuntimeFile[],
|
||||
metas: RuntimeFile[],
|
||||
collection: string,
|
||||
config: LoadedConfig,
|
||||
) => Docs extends {
|
||||
type: 'docs';
|
||||
|
||||
docs: {
|
||||
type: 'doc';
|
||||
_type: {
|
||||
schema: infer DocSchema extends StandardSchemaV1;
|
||||
};
|
||||
};
|
||||
|
||||
meta: {
|
||||
type: 'meta';
|
||||
_type: {
|
||||
schema: infer MetaSchema extends StandardSchemaV1;
|
||||
};
|
||||
};
|
||||
}
|
||||
? {
|
||||
docs: AsyncDocOut<DocSchema>[];
|
||||
meta: MetaOut<MetaSchema>[];
|
||||
toFumadocsSource: () => Source<{
|
||||
pageData: AsyncDocOut<DocSchema> extends PageData
|
||||
? AsyncDocOut<DocSchema>
|
||||
: never;
|
||||
metaData: MetaOut<MetaSchema> extends MetaData
|
||||
? MetaOut<MetaSchema>
|
||||
: never;
|
||||
}>;
|
||||
}
|
||||
: never;
|
||||
}
|
||||
Reference in New Issue
Block a user