@vx-oss/docs-satteri 1.0.3
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/dist/compile-SBpZsgmI.d.ts +42 -0
- package/dist/compile.d.ts +2 -0
- package/dist/compile.js +63 -0
- package/dist/index-AvS9vC2S.d.ts +29 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/local-md/client.d.ts +2 -0
- package/dist/local-md/client.js +2 -0
- package/dist/local-md/dev/react-client.d.ts +2 -0
- package/dist/local-md/dev/react-client.js +2 -0
- package/dist/local-md/dev/vite.d.ts +2 -0
- package/dist/local-md/dev/vite.js +2 -0
- package/dist/local-md/dev/ws.d.ts +2 -0
- package/dist/local-md/dev/ws.js +2 -0
- package/dist/local-md/index.d.ts +70 -0
- package/dist/local-md/index.js +104 -0
- package/dist/preset-DdTDKnqd.js +104 -0
- package/dist/preset-DzMkd76i.d.ts +35 -0
- package/dist/preset.d.ts +2 -0
- package/dist/preset.js +2 -0
- package/dist/rehype-code-CLGqDUSe.d.ts +13 -0
- package/dist/rehype-code.d.ts +2 -0
- package/dist/rehype-code.js +79 -0
- package/dist/rehype-katex-h_E-WUwT.d.ts +15 -0
- package/dist/rehype-katex.d.ts +2 -0
- package/dist/rehype-katex.js +52 -0
- package/dist/rehype-toc-wT8IcPFi.d.ts +33 -0
- package/dist/rehype-toc.d.ts +2 -0
- package/dist/rehype-toc.js +84 -0
- package/dist/remark-admonition.d.ts +13 -0
- package/dist/remark-admonition.js +79 -0
- package/dist/remark-auto-type-table.d.ts +9 -0
- package/dist/remark-auto-type-table.js +189 -0
- package/dist/remark-block-id.d.ts +18 -0
- package/dist/remark-block-id.js +46 -0
- package/dist/remark-code-tab-BYruQJUs.d.ts +15 -0
- package/dist/remark-code-tab.d.ts +2 -0
- package/dist/remark-code-tab.js +170 -0
- package/dist/remark-directive-admonition.d.ts +13 -0
- package/dist/remark-directive-admonition.js +54 -0
- package/dist/remark-feedback-block.d.ts +18 -0
- package/dist/remark-feedback-block.js +51 -0
- package/dist/remark-heading-CYhI2Dkg.d.ts +15 -0
- package/dist/remark-heading.d.ts +2 -0
- package/dist/remark-heading.js +43 -0
- package/dist/remark-image-C28nbosW.d.ts +29 -0
- package/dist/remark-image.d.ts +2 -0
- package/dist/remark-image.js +141 -0
- package/dist/remark-include.d.ts +22 -0
- package/dist/remark-include.js +336 -0
- package/dist/remark-llms.d.ts +36 -0
- package/dist/remark-llms.js +191 -0
- package/dist/remark-mdx-mermaid.d.ts +10 -0
- package/dist/remark-mdx-mermaid.js +22 -0
- package/dist/remark-npm-DdmTKhyi.d.ts +18 -0
- package/dist/remark-npm.d.ts +2 -0
- package/dist/remark-npm.js +72 -0
- package/dist/remark-steps.d.ts +14 -0
- package/dist/remark-steps.js +127 -0
- package/dist/remark-structure.d.ts +29 -0
- package/dist/remark-structure.js +94 -0
- package/dist/remark-ts2js.d.ts +25 -0
- package/dist/remark-ts2js.js +56 -0
- package/dist/renderer-BtFWPZB8.js +54 -0
- package/dist/renderer-E5KzV19n.d.ts +30 -0
- package/dist/stringifier-COIWcXys.js +130 -0
- package/dist/utils-I3DkmAkd.js +27 -0
- package/package.json +124 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Fuma
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Data, MdxCompileOptions, MdxToJsResult } from "satteri";
|
|
2
|
+
//#region src/compile.d.ts
|
|
3
|
+
type DocumentFormat = 'md' | 'mdx';
|
|
4
|
+
interface CompileMdxOptions {
|
|
5
|
+
source: string;
|
|
6
|
+
filePath: string;
|
|
7
|
+
/**
|
|
8
|
+
* Which parser to use.
|
|
9
|
+
*
|
|
10
|
+
* Defaults to the `filePath` extension, so a `.md` file is not silently given
|
|
11
|
+
* MDX semantics.
|
|
12
|
+
*/
|
|
13
|
+
format?: DocumentFormat;
|
|
14
|
+
frontmatter?: Record<string, unknown>;
|
|
15
|
+
isDevelopment?: boolean;
|
|
16
|
+
environment?: 'bundler' | 'runtime';
|
|
17
|
+
options: MdxCompileOptions;
|
|
18
|
+
}
|
|
19
|
+
type CompileMdxResult = MdxToJsResult;
|
|
20
|
+
type OutputFormat = 'program' | 'function-body';
|
|
21
|
+
interface AfterToJsContext {
|
|
22
|
+
result: MdxToJsResult;
|
|
23
|
+
outputFormat: OutputFormat;
|
|
24
|
+
}
|
|
25
|
+
interface CollectExportsContext {
|
|
26
|
+
data: Data;
|
|
27
|
+
/** declare `export const <name> = <valueCode>`, a repeated name replaces the earlier one */
|
|
28
|
+
addExport: (name: string, valueCode: string) => void;
|
|
29
|
+
}
|
|
30
|
+
interface ExtraPluginHooks {
|
|
31
|
+
/**
|
|
32
|
+
* Declare module exports. Runs after every plugin has seen the document, so
|
|
33
|
+
* `data` is final. Exports go into the tree as an ESM node, so the compiler
|
|
34
|
+
* emits them correctly for either output format.
|
|
35
|
+
*/
|
|
36
|
+
collectExports?: (opts: CollectExportsContext) => void;
|
|
37
|
+
/** post-process the generated code, use {@link collectExports} for exports */
|
|
38
|
+
afterToJs?: (opts: AfterToJsContext) => void;
|
|
39
|
+
}
|
|
40
|
+
declare function compileMdx({ source, filePath, format, frontmatter, isDevelopment, environment, options: { mdastPlugins, hastPlugins, ...satteriOptions } }: CompileMdxOptions): Promise<CompileMdxResult>;
|
|
41
|
+
//#endregion
|
|
42
|
+
export { DocumentFormat as a, compileMdx as c, CompileMdxResult as i, CollectExportsContext as n, ExtraPluginHooks as o, CompileMdxOptions as r, OutputFormat as s, AfterToJsContext as t };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as DocumentFormat, c as compileMdx, i as CompileMdxResult, n as CollectExportsContext, o as ExtraPluginHooks, r as CompileMdxOptions, s as OutputFormat, t as AfterToJsContext } from "./compile-SBpZsgmI.js";
|
|
2
|
+
export { AfterToJsContext, CollectExportsContext, CompileMdxOptions, CompileMdxResult, DocumentFormat, ExtraPluginHooks, OutputFormat, compileMdx };
|
package/dist/compile.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { markdownToJs, mdxToJs } from "satteri";
|
|
2
|
+
import { pathToFileURL } from "node:url";
|
|
3
|
+
//#region src/compile.ts
|
|
4
|
+
async function compileMdx({ source, filePath, format = filePath.endsWith(".mdx") ? "mdx" : "md", frontmatter, isDevelopment = false, environment = "bundler", options: { mdastPlugins = [], hastPlugins = [], ...satteriOptions } }) {
|
|
5
|
+
const data = { ...satteriOptions.data };
|
|
6
|
+
if (frontmatter) data.frontmatter = frontmatter;
|
|
7
|
+
const plugins = [...mdastPlugins, ...hastPlugins];
|
|
8
|
+
const outputFormat = environment === "runtime" ? "function-body" : satteriOptions.outputFormat ?? "program";
|
|
9
|
+
const compileOptions = {
|
|
10
|
+
...satteriOptions,
|
|
11
|
+
mdastPlugins,
|
|
12
|
+
hastPlugins: [...hastPlugins, exportsPlugin(plugins)],
|
|
13
|
+
development: isDevelopment,
|
|
14
|
+
outputFormat,
|
|
15
|
+
fileURL: satteriOptions.fileURL ?? pathToFileURL(filePath),
|
|
16
|
+
data,
|
|
17
|
+
features: {
|
|
18
|
+
gfm: true,
|
|
19
|
+
frontmatter: false,
|
|
20
|
+
directive: true,
|
|
21
|
+
...satteriOptions.features
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const result = await (format === "md" ? markdownToJs(source, compileOptions) : mdxToJs(source, compileOptions));
|
|
25
|
+
for (const plugin of plugins) plugin.afterToJs?.({
|
|
26
|
+
result,
|
|
27
|
+
outputFormat
|
|
28
|
+
});
|
|
29
|
+
return {
|
|
30
|
+
code: result.code,
|
|
31
|
+
data: result.data,
|
|
32
|
+
frontmatter: result.frontmatter
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** Emits the exports declared via {@link ExtraPluginHooks.collectExports} once
|
|
36
|
+
* per document, as an ESM node prepended to the tree. */
|
|
37
|
+
function exportsPlugin(hooks) {
|
|
38
|
+
return {
|
|
39
|
+
name: "fd-exports",
|
|
40
|
+
after(root, ctx) {
|
|
41
|
+
const statements = /* @__PURE__ */ new Map();
|
|
42
|
+
const addExport = (name, valueCode) => {
|
|
43
|
+
statements.set(name, `export const ${name} = ${valueCode};`);
|
|
44
|
+
};
|
|
45
|
+
for (const hook of hooks) hook.collectExports?.({
|
|
46
|
+
data: ctx.data,
|
|
47
|
+
addExport
|
|
48
|
+
});
|
|
49
|
+
const { frontmatter, _valueToExport } = ctx.data;
|
|
50
|
+
if (frontmatter) addExport("frontmatter", JSON.stringify(frontmatter));
|
|
51
|
+
if (Array.isArray(_valueToExport)) for (const name of _valueToExport) {
|
|
52
|
+
if (!(name in ctx.data)) continue;
|
|
53
|
+
addExport(name, JSON.stringify(ctx.data[name]));
|
|
54
|
+
}
|
|
55
|
+
if (statements.size > 0) ctx.prependChild(root, {
|
|
56
|
+
type: "mdxjsEsm",
|
|
57
|
+
value: Array.from(statements.values()).join("\n")
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
export { compileMdx };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { n as RehypeTocItemType } from "./rehype-toc-wT8IcPFi.js";
|
|
2
|
+
import { StructuredData } from "@vx-oss/docs-core/mdx-plugins/remark-structure";
|
|
3
|
+
import { TOCItemType } from "@vx-oss/docs-core/toc";
|
|
4
|
+
//#region src/index.d.ts
|
|
5
|
+
/** host compiler hooks (e.g. a bundler loader), used for watch-mode dependency tracking */
|
|
6
|
+
interface CompilerHooks {
|
|
7
|
+
addDependency: (file: string) => void;
|
|
8
|
+
}
|
|
9
|
+
declare module 'satteri' {
|
|
10
|
+
interface DataMap {
|
|
11
|
+
/** `remark-structure` */
|
|
12
|
+
structuredData?: StructuredData;
|
|
13
|
+
/** `remark-heading` */
|
|
14
|
+
toc?: TOCItemType[];
|
|
15
|
+
/** `rehype-toc` */
|
|
16
|
+
rehypeToc?: RehypeTocItemType[];
|
|
17
|
+
/** `remark-llms` */
|
|
18
|
+
markdown?: string;
|
|
19
|
+
/** `remark-image` */
|
|
20
|
+
_imageImports?: string[];
|
|
21
|
+
_cwd?: string;
|
|
22
|
+
_compiler?: CompilerHooks;
|
|
23
|
+
_valueToExport?: string[];
|
|
24
|
+
frontmatter?: Record<string, unknown>;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
type BuildEnvironment = 'bundler' | 'runtime';
|
|
28
|
+
//#endregion
|
|
29
|
+
export { CompilerHooks as n, BuildEnvironment as t };
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { i as fromSerialized, n as MarkdownRendererResult, r as MarkdownRendererSerializedOptions, t as MarkdownRenderer } from "../renderer-E5KzV19n.js";
|
|
2
|
+
export { type MarkdownRenderer, type MarkdownRendererResult, type MarkdownRendererSerializedOptions, fromSerialized as rendererFromSerialized };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { t as MarkdownRenderer } from "../renderer-E5KzV19n.js";
|
|
2
|
+
import { StructuredData } from "../remark-structure.js";
|
|
3
|
+
import { n as SatteriPresetOptions } from "../preset-DzMkd76i.js";
|
|
4
|
+
import { SourceOptions, WatchableSource } from "@vx-oss/docs-local-content";
|
|
5
|
+
import * as defaultSchemas from "@vx-oss/docs-core/source/schema";
|
|
6
|
+
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
7
|
+
import { DynamicSource, MetaData, PageData, StaticSource } from "@vx-oss/docs-core/source";
|
|
8
|
+
//#region src/local-md/compiler.d.ts
|
|
9
|
+
type SatteriOptionsInput = SatteriPresetOptions | (() => SatteriPresetOptions | Promise<SatteriPresetOptions>);
|
|
10
|
+
interface MarkdownCompilerOptions {
|
|
11
|
+
/** same shape as `@vx-oss/docs-satteri/preset`, or a function returning it */
|
|
12
|
+
satteriOptions?: SatteriOptionsInput;
|
|
13
|
+
}
|
|
14
|
+
interface CompileInput {
|
|
15
|
+
path: string;
|
|
16
|
+
value: string;
|
|
17
|
+
data?: {
|
|
18
|
+
frontmatter?: Record<string, unknown>;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
interface CompileResult {
|
|
22
|
+
/** compiled function-body JavaScript. */
|
|
23
|
+
code: string;
|
|
24
|
+
filePath: string;
|
|
25
|
+
structuredData?: StructuredData;
|
|
26
|
+
}
|
|
27
|
+
interface MarkdownCompiler {
|
|
28
|
+
compile: (input: CompileInput) => Promise<CompileResult>;
|
|
29
|
+
}
|
|
30
|
+
declare function createMarkdownCompiler(config?: MarkdownCompilerOptions): MarkdownCompiler;
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region src/local-md/index.d.ts
|
|
33
|
+
declare const defaultInclude: string[];
|
|
34
|
+
interface SatteriLocalMarkdownConfig<FrontmatterSchema extends StandardSchemaV1, MetaSchema extends StandardSchemaV1> extends MarkdownCompilerOptions {
|
|
35
|
+
/** root directory for content files */
|
|
36
|
+
dir: string;
|
|
37
|
+
/** a list of glob patterns, customize the content files to be scanned */
|
|
38
|
+
include?: string[];
|
|
39
|
+
frontmatterSchema?: FrontmatterSchema;
|
|
40
|
+
metaSchema?: MetaSchema;
|
|
41
|
+
}
|
|
42
|
+
interface SatteriLocalMarkdown<FrontmatterSchema extends StandardSchemaV1, MetaSchema extends StandardSchemaV1> extends WatchableSource {
|
|
43
|
+
/**
|
|
44
|
+
* Connect to the standalone dev server for hot reload. On Vite, prefer
|
|
45
|
+
* `watchWithVite()` from `@vx-oss/docs-local-content/dev/vite`.
|
|
46
|
+
*/
|
|
47
|
+
devServer: (url?: string) => Promise<void>;
|
|
48
|
+
staticSource: <ModuleExports = Record<string, unknown>>(options?: SourceOptions) => Promise<StaticSource<{
|
|
49
|
+
pageData: LocalMarkdownPage<StandardSchemaV1.InferOutput<FrontmatterSchema>, ModuleExports>;
|
|
50
|
+
metaData: StandardSchemaV1.InferOutput<MetaSchema> & MetaData;
|
|
51
|
+
}>>;
|
|
52
|
+
dynamicSource: <ModuleExports = Record<string, unknown>>(options?: SourceOptions) => DynamicSource<{
|
|
53
|
+
pageData: LocalMarkdownPage<StandardSchemaV1.InferOutput<FrontmatterSchema>, ModuleExports>;
|
|
54
|
+
metaData: StandardSchemaV1.InferOutput<MetaSchema> & MetaData;
|
|
55
|
+
}>;
|
|
56
|
+
invalidateFile: (file: string) => void;
|
|
57
|
+
}
|
|
58
|
+
interface LocalMarkdownPage<Frontmatter = Record<string, unknown>, ModuleExports = Record<string, unknown>> extends PageData {
|
|
59
|
+
title: string;
|
|
60
|
+
description?: string;
|
|
61
|
+
icon?: string;
|
|
62
|
+
content: string;
|
|
63
|
+
frontmatter: Frontmatter;
|
|
64
|
+
/** compile the page, at most once until the file is invalidated */
|
|
65
|
+
load: () => Promise<MarkdownRenderer<ModuleExports>>;
|
|
66
|
+
structuredData: () => Promise<StructuredData>;
|
|
67
|
+
}
|
|
68
|
+
declare function localMd<FrontmatterSchema extends StandardSchemaV1 = typeof defaultSchemas.pageSchema, MetaSchema extends StandardSchemaV1 = typeof defaultSchemas.metaSchema>(config: SatteriLocalMarkdownConfig<FrontmatterSchema, MetaSchema>): SatteriLocalMarkdown<FrontmatterSchema, MetaSchema>;
|
|
69
|
+
//#endregion
|
|
70
|
+
export { type CompileResult, LocalMarkdownPage, type MarkdownCompiler, type MarkdownCompilerOptions, type MarkdownRenderer, SatteriLocalMarkdown, SatteriLocalMarkdownConfig, createMarkdownCompiler, defaultInclude, localMd };
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { t as applySatteriPreset } from "../preset-DdTDKnqd.js";
|
|
2
|
+
import { compileMdx } from "../compile.js";
|
|
3
|
+
import { t as fromJS } from "../renderer-BtFWPZB8.js";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { pathToFileURL } from "node:url";
|
|
6
|
+
import { createLocalSource } from "@vx-oss/docs-local-content";
|
|
7
|
+
import { frontmatter } from "@vx-oss/docs-core/content/md/frontmatter";
|
|
8
|
+
import * as defaultSchemas from "@vx-oss/docs-core/source/schema";
|
|
9
|
+
//#region src/local-md/compiler.ts
|
|
10
|
+
async function resolveOptions(input) {
|
|
11
|
+
const options = typeof input === "function" ? await input() : input;
|
|
12
|
+
return applySatteriPreset(options)("runtime");
|
|
13
|
+
}
|
|
14
|
+
function createMarkdownCompiler(config = {}) {
|
|
15
|
+
let resolved;
|
|
16
|
+
return { async compile(input) {
|
|
17
|
+
resolved ??= resolveOptions(config.satteriOptions);
|
|
18
|
+
const options = await resolved;
|
|
19
|
+
const result = await compileMdx({
|
|
20
|
+
source: input.value,
|
|
21
|
+
filePath: input.path,
|
|
22
|
+
format: input.path.endsWith(".mdx") ? "mdx" : "md",
|
|
23
|
+
frontmatter: input.data?.frontmatter,
|
|
24
|
+
environment: "runtime",
|
|
25
|
+
options: {
|
|
26
|
+
...options,
|
|
27
|
+
data: { ...options.data }
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
return {
|
|
31
|
+
code: result.code,
|
|
32
|
+
filePath: input.path,
|
|
33
|
+
structuredData: result.data.structuredData
|
|
34
|
+
};
|
|
35
|
+
} };
|
|
36
|
+
}
|
|
37
|
+
//#endregion
|
|
38
|
+
//#region src/local-md/index.ts
|
|
39
|
+
const defaultInclude = ["**/*.{md,mdx,json}"];
|
|
40
|
+
function localMd(config) {
|
|
41
|
+
const { include = defaultInclude, frontmatterSchema = defaultSchemas.pageSchema, metaSchema = defaultSchemas.metaSchema } = config;
|
|
42
|
+
const compiler = createMarkdownCompiler(config);
|
|
43
|
+
async function compile(file, content, frontmatter) {
|
|
44
|
+
const res = await compiler.compile({
|
|
45
|
+
path: file.absolutePath,
|
|
46
|
+
value: content,
|
|
47
|
+
data: { frontmatter }
|
|
48
|
+
});
|
|
49
|
+
return fromJS({
|
|
50
|
+
code: res.code,
|
|
51
|
+
filePath: res.filePath,
|
|
52
|
+
baseUrl: pathToFileURL(res.filePath).href,
|
|
53
|
+
structuredData: res.structuredData
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
async function page(file) {
|
|
57
|
+
const parsed = frontmatter(await file.read());
|
|
58
|
+
const result = await frontmatterSchema["~standard"].validate(parsed.data);
|
|
59
|
+
if (result.issues) throw new Error(`invalid frontmatter in "${file.absolutePath}": ${formatIssues(result.issues)}`);
|
|
60
|
+
const frontmatter$1 = result.value;
|
|
61
|
+
const pageData = frontmatter$1;
|
|
62
|
+
let loaded;
|
|
63
|
+
const load = () => loaded ??= compile(file, parsed.content, frontmatter$1);
|
|
64
|
+
return {
|
|
65
|
+
title: pageData.title ?? path.basename(file.path, path.extname(file.path)),
|
|
66
|
+
description: pageData.description,
|
|
67
|
+
icon: pageData.icon,
|
|
68
|
+
["_openapi"]: pageData._openapi,
|
|
69
|
+
content: parsed.content,
|
|
70
|
+
frontmatter: frontmatter$1,
|
|
71
|
+
load,
|
|
72
|
+
structuredData: async () => (await load()).structuredData
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
async function meta(file) {
|
|
76
|
+
const result = await metaSchema["~standard"].validate(JSON.parse(await file.read()));
|
|
77
|
+
if (result.issues) throw new Error(`invalid data in "${file.absolutePath}": ${formatIssues(result.issues)}`);
|
|
78
|
+
return result.value;
|
|
79
|
+
}
|
|
80
|
+
return createLocalSource({
|
|
81
|
+
dir: config.dir,
|
|
82
|
+
integration: {
|
|
83
|
+
include,
|
|
84
|
+
async parse(file) {
|
|
85
|
+
switch (path.extname(file.path)) {
|
|
86
|
+
case ".json": return {
|
|
87
|
+
type: "meta",
|
|
88
|
+
data: await meta(file)
|
|
89
|
+
};
|
|
90
|
+
case ".md":
|
|
91
|
+
case ".mdx": return {
|
|
92
|
+
type: "page",
|
|
93
|
+
data: await page(file)
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
function formatIssues(issues) {
|
|
101
|
+
return issues.map((issue) => issue.path ? `${issue.path}: ${issue.message}` : issue.message).join("\n");
|
|
102
|
+
}
|
|
103
|
+
//#endregion
|
|
104
|
+
export { createMarkdownCompiler, defaultInclude, localMd };
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { remarkHeading } from "./remark-heading.js";
|
|
2
|
+
import { remarkImage } from "./remark-image.js";
|
|
3
|
+
import { remarkCodeTab } from "./remark-code-tab.js";
|
|
4
|
+
import { remarkNpm } from "./remark-npm.js";
|
|
5
|
+
import { remarkStructure } from "./remark-structure.js";
|
|
6
|
+
import { rehypeCode } from "./rehype-code.js";
|
|
7
|
+
import { rehypeToc } from "./rehype-toc.js";
|
|
8
|
+
import { rehypeKatex } from "./rehype-katex.js";
|
|
9
|
+
import { defineHastPlugin } from "satteri";
|
|
10
|
+
//#region src/rehype-table.ts
|
|
11
|
+
const TABLE_STRUCTURE = [
|
|
12
|
+
"table",
|
|
13
|
+
"thead",
|
|
14
|
+
"tbody",
|
|
15
|
+
"tfoot",
|
|
16
|
+
"tr"
|
|
17
|
+
];
|
|
18
|
+
function isWhitespaceText(node) {
|
|
19
|
+
return node.type === "text" && (node.value ?? "").trim().length === 0;
|
|
20
|
+
}
|
|
21
|
+
function rehypeTable() {
|
|
22
|
+
return defineHastPlugin({
|
|
23
|
+
name: "rehype-table",
|
|
24
|
+
element: {
|
|
25
|
+
filter: TABLE_STRUCTURE,
|
|
26
|
+
visit(node, ctx) {
|
|
27
|
+
const element = node;
|
|
28
|
+
for (let i = element.children.length - 1; i >= 0; i--) if (isWhitespaceText(element.children[i])) ctx.removeChildAt(element, i);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region src/preset.ts
|
|
35
|
+
function pluginOption(def, options = []) {
|
|
36
|
+
const list = def(Array.isArray(options) ? options : []).filter(Boolean);
|
|
37
|
+
if (typeof options === "function") return options(list);
|
|
38
|
+
return list;
|
|
39
|
+
}
|
|
40
|
+
const RESOLVED_PRESET = Symbol.for("fumadocs.satteri.resolved-preset");
|
|
41
|
+
function applySatteriPreset(options = {}) {
|
|
42
|
+
return async (environment = "bundler") => {
|
|
43
|
+
if (RESOLVED_PRESET in options) {
|
|
44
|
+
const resolved = options;
|
|
45
|
+
return {
|
|
46
|
+
...resolved,
|
|
47
|
+
outputFormat: environment === "runtime" ? "function-body" : resolved.outputFormat
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
if (options.preset === "minimal") {
|
|
51
|
+
const { preset: _preset, ...rest } = options;
|
|
52
|
+
return markResolved({
|
|
53
|
+
...rest,
|
|
54
|
+
outputFormat: environment === "runtime" ? "function-body" : rest.outputFormat
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
const { valueToExport = [], rehypeCodeOptions, remarkImageOptions, remarkHeadingOptions, remarkStructureOptions, remarkCodeTabOptions, remarkNpmOptions, rehypeKatexOptions, mdastPlugins, hastPlugins, features, data, ...rest } = options;
|
|
58
|
+
const resolvedMdast = pluginOption((plugins) => [
|
|
59
|
+
remarkHeading({
|
|
60
|
+
generateToc: false,
|
|
61
|
+
...remarkHeadingOptions
|
|
62
|
+
}),
|
|
63
|
+
remarkImageOptions !== false && remarkImage(remarkImageOptions),
|
|
64
|
+
remarkCodeTabOptions !== false && remarkCodeTab(remarkCodeTabOptions),
|
|
65
|
+
remarkNpmOptions !== false && remarkNpm(remarkNpmOptions),
|
|
66
|
+
...plugins,
|
|
67
|
+
remarkStructureOptions !== false && remarkStructure({
|
|
68
|
+
exportAs: "structuredData",
|
|
69
|
+
...remarkStructureOptions
|
|
70
|
+
})
|
|
71
|
+
], mdastPlugins);
|
|
72
|
+
const resolvedHast = pluginOption((plugins) => [
|
|
73
|
+
Boolean(features?.math) && rehypeKatexOptions !== false && rehypeKatex(rehypeKatexOptions),
|
|
74
|
+
rehypeCodeOptions !== false && rehypeCode({
|
|
75
|
+
tab: false,
|
|
76
|
+
...rehypeCodeOptions
|
|
77
|
+
}),
|
|
78
|
+
...plugins,
|
|
79
|
+
rehypeTable(),
|
|
80
|
+
rehypeToc()
|
|
81
|
+
], hastPlugins);
|
|
82
|
+
return markResolved({
|
|
83
|
+
...rest,
|
|
84
|
+
data: {
|
|
85
|
+
...data,
|
|
86
|
+
...valueToExport.length > 0 ? { _valueToExport: valueToExport } : {}
|
|
87
|
+
},
|
|
88
|
+
outputFormat: environment === "runtime" ? "function-body" : rest.outputFormat,
|
|
89
|
+
features: {
|
|
90
|
+
gfm: true,
|
|
91
|
+
directive: true,
|
|
92
|
+
...features
|
|
93
|
+
},
|
|
94
|
+
mdastPlugins: resolvedMdast,
|
|
95
|
+
hastPlugins: resolvedHast
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function markResolved(options) {
|
|
100
|
+
Object.defineProperty(options, RESOLVED_PRESET, { value: true });
|
|
101
|
+
return options;
|
|
102
|
+
}
|
|
103
|
+
//#endregion
|
|
104
|
+
export { applySatteriPreset as t };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { t as BuildEnvironment } from "./index-AvS9vC2S.js";
|
|
2
|
+
import { StructureOptions } from "./remark-structure.js";
|
|
3
|
+
import { t as RemarkHeadingOptions } from "./remark-heading-CYhI2Dkg.js";
|
|
4
|
+
import { t as RemarkImageOptions } from "./remark-image-C28nbosW.js";
|
|
5
|
+
import { t as RemarkCodeTabOptions } from "./remark-code-tab-BYruQJUs.js";
|
|
6
|
+
import { t as RemarkNpmOptions } from "./remark-npm-DdmTKhyi.js";
|
|
7
|
+
import { t as RehypeCodeOptions } from "./rehype-code-CLGqDUSe.js";
|
|
8
|
+
import { t as RehypeKatexOptions } from "./rehype-katex-h_E-WUwT.js";
|
|
9
|
+
import { HastPluginInput, MdastPluginInput, MdxCompileOptions, MdxOnlyOptions } from "satteri";
|
|
10
|
+
//#region src/preset.d.ts
|
|
11
|
+
type ResolvePlugins<T> = readonly T[] | ((plugins: T[]) => T[]);
|
|
12
|
+
type DefaultSatteriOptions = Omit<MdxCompileOptions, 'mdastPlugins' | 'hastPlugins'> & {
|
|
13
|
+
mdastPlugins?: ResolvePlugins<MdastPluginInput>;
|
|
14
|
+
hastPlugins?: ResolvePlugins<HastPluginInput>;
|
|
15
|
+
valueToExport?: string[];
|
|
16
|
+
remarkStructureOptions?: StructureOptions | false;
|
|
17
|
+
remarkHeadingOptions?: RemarkHeadingOptions;
|
|
18
|
+
remarkImageOptions?: RemarkImageOptions | false;
|
|
19
|
+
remarkCodeTabOptions?: RemarkCodeTabOptions | false;
|
|
20
|
+
remarkNpmOptions?: RemarkNpmOptions | false;
|
|
21
|
+
rehypeCodeOptions?: RehypeCodeOptions | false;
|
|
22
|
+
/**
|
|
23
|
+
* KaTeX rendering, applied only when the `math` feature is enabled. Pass
|
|
24
|
+
* options to customize it, or `false` to keep math unrendered.
|
|
25
|
+
*/
|
|
26
|
+
rehypeKatexOptions?: RehypeKatexOptions | false;
|
|
27
|
+
};
|
|
28
|
+
type SatteriPresetOptions = ({
|
|
29
|
+
preset?: 'fumadocs';
|
|
30
|
+
} & DefaultSatteriOptions) | ({
|
|
31
|
+
preset: 'minimal';
|
|
32
|
+
} & MdxOnlyOptions & Pick<MdxCompileOptions, 'mdastPlugins' | 'hastPlugins' | 'features' | 'data'>);
|
|
33
|
+
declare function applySatteriPreset(options?: SatteriPresetOptions): (environment: BuildEnvironment) => Promise<MdxCompileOptions>;
|
|
34
|
+
//#endregion
|
|
35
|
+
export { SatteriPresetOptions as n, applySatteriPreset as r, DefaultSatteriOptions as t };
|
package/dist/preset.d.ts
ADDED
package/dist/preset.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { HastVisitorContext } from "satteri";
|
|
2
|
+
import { RehypeCodeOptions, RehypeCodeOptions as RehypeCodeOptions$1 } from "@vx-oss/docs-core/mdx-plugins/rehype-code";
|
|
3
|
+
import { Element } from "hast";
|
|
4
|
+
//#region src/rehype-code.d.ts
|
|
5
|
+
declare function rehypeCode$1(options?: Partial<RehypeCodeOptions>): {
|
|
6
|
+
name: string;
|
|
7
|
+
element: {
|
|
8
|
+
filter: string[];
|
|
9
|
+
visit(element: Readonly<Element>, ctx: HastVisitorContext): Promise<void>;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
//#endregion
|
|
13
|
+
export { rehypeCode$1 as n, RehypeCodeOptions$1 as t };
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { defineHastPlugin } from "satteri";
|
|
2
|
+
import { rehypeCode as rehypeCode$1 } from "@vx-oss/docs-core/mdx-plugins/rehype-code";
|
|
3
|
+
//#region src/rehype-code.ts
|
|
4
|
+
function unwrapReplacement(node) {
|
|
5
|
+
if (node.type === "root") return node.children;
|
|
6
|
+
return node;
|
|
7
|
+
}
|
|
8
|
+
const ATTRIBUTE_TO_PROP = {
|
|
9
|
+
class: "className",
|
|
10
|
+
tabindex: "tabIndex",
|
|
11
|
+
readonly: "readOnly",
|
|
12
|
+
contenteditable: "contentEditable"
|
|
13
|
+
};
|
|
14
|
+
function normalizeProperties(node) {
|
|
15
|
+
if (node.type === "element" && node.properties) {
|
|
16
|
+
for (const [attribute, prop] of Object.entries(ATTRIBUTE_TO_PROP)) if (attribute in node.properties) {
|
|
17
|
+
node.properties[prop] ??= node.properties[attribute];
|
|
18
|
+
delete node.properties[attribute];
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if ("children" in node) for (const child of node.children) normalizeProperties(child);
|
|
22
|
+
}
|
|
23
|
+
function replaceHighlightedNode(element, next, ctx) {
|
|
24
|
+
if (!next) return;
|
|
25
|
+
const replacement = unwrapReplacement(next);
|
|
26
|
+
if (Array.isArray(replacement)) {
|
|
27
|
+
if (replacement.length === 0) return;
|
|
28
|
+
ctx.replaceNode(element, replacement[0]);
|
|
29
|
+
if (replacement.length > 1) ctx.insertAfter(element, replacement.slice(1));
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
ctx.replaceNode(element, replacement);
|
|
33
|
+
}
|
|
34
|
+
function elementClasses(element) {
|
|
35
|
+
const className = element.properties.className;
|
|
36
|
+
if (Array.isArray(className)) return className.map(String);
|
|
37
|
+
if (typeof className === "string") return className.split(/\s+/);
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
40
|
+
const skipClasses = /* @__PURE__ */ new Set([
|
|
41
|
+
"shiki",
|
|
42
|
+
"language-math",
|
|
43
|
+
"math-inline",
|
|
44
|
+
"math-display"
|
|
45
|
+
]);
|
|
46
|
+
function shouldSkipHighlight(element) {
|
|
47
|
+
if (elementClasses(element).some((c) => skipClasses.has(c))) return true;
|
|
48
|
+
if (element.tagName === "pre") {
|
|
49
|
+
for (const child of element.children) if (child.type === "element" && shouldSkipHighlight(child)) return true;
|
|
50
|
+
}
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
function rehypeCode(options) {
|
|
54
|
+
const runBlock = rehypeCode$1.call({}, options);
|
|
55
|
+
const inline = options?.inline;
|
|
56
|
+
return defineHastPlugin({
|
|
57
|
+
name: "rehype-code",
|
|
58
|
+
element: {
|
|
59
|
+
filter: ["pre", "code"],
|
|
60
|
+
async visit(element, ctx) {
|
|
61
|
+
if (shouldSkipHighlight(element)) return;
|
|
62
|
+
if (element.tagName !== "pre" && !(element.tagName === "code" && inline)) return;
|
|
63
|
+
if (element.tagName === "code") {
|
|
64
|
+
const parent = ctx.parent(element);
|
|
65
|
+
if (parent?.type === "element" && parent.tagName === "pre") return;
|
|
66
|
+
}
|
|
67
|
+
const tree = {
|
|
68
|
+
type: "root",
|
|
69
|
+
children: [element]
|
|
70
|
+
};
|
|
71
|
+
await runBlock(tree, null, () => void 0);
|
|
72
|
+
normalizeProperties(tree);
|
|
73
|
+
replaceHighlightedNode(element, tree.children[0], ctx);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
//#endregion
|
|
79
|
+
export { rehypeCode };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { HastPluginDefinition } from "satteri";
|
|
2
|
+
import { KatexOptions } from "katex";
|
|
3
|
+
//#region src/rehype-katex.d.ts
|
|
4
|
+
type RehypeKatexOptions = Omit<KatexOptions, 'displayMode' | 'throwOnError'>;
|
|
5
|
+
/**
|
|
6
|
+
* Render `$…$`, `$$…$$`, and ```` ```math ```` blocks to KaTeX markup — the
|
|
7
|
+
* Satteri counterpart of `rehype-katex`. Satteri's `math` feature parses the
|
|
8
|
+
* syntax into `<code class="language-math …">` elements (raw TeX); this renders
|
|
9
|
+
* them.
|
|
10
|
+
*
|
|
11
|
+
* The preset adds this to the hast pipeline when `math` is enabled.
|
|
12
|
+
*/
|
|
13
|
+
declare function rehypeKatex(options?: RehypeKatexOptions): () => HastPluginDefinition;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { rehypeKatex as n, RehypeKatexOptions as t };
|