@docubook/core 1.0.0 → 1.1.1
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/README.md +132 -28
- package/dist/compile.d.ts +19 -0
- package/dist/compile.d.ts.map +1 -0
- package/{src/compile.ts → dist/compile.js} +22 -62
- package/dist/compile.js.map +1 -0
- package/dist/content.d.ts +41 -0
- package/dist/content.d.ts.map +1 -0
- package/dist/content.js +74 -0
- package/dist/content.js.map +1 -0
- package/dist/extract.d.ts +5 -0
- package/dist/extract.d.ts.map +1 -0
- package/{src/extract.ts → dist/extract.js} +9 -15
- package/dist/extract.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/{src/types.ts → dist/types.d.ts} +1 -2
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +14 -4
- package/src/content.ts +0 -129
- package/src/index.ts +0 -23
- package/tsconfig.json +0 -15
package/README.md
CHANGED
|
@@ -32,32 +32,118 @@ Bun (independent runtime/package manager):
|
|
|
32
32
|
bun add @docubook/core
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
##
|
|
35
|
+
## Usage
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
### Quick Start (Recommended)
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
```ts
|
|
40
|
+
import { cache } from "react";
|
|
41
|
+
import { createMdxContentService } from "@docubook/core";
|
|
40
42
|
|
|
41
|
-
|
|
43
|
+
type Frontmatter = {
|
|
44
|
+
title: string;
|
|
45
|
+
description: string;
|
|
46
|
+
image: string;
|
|
47
|
+
date: string;
|
|
48
|
+
};
|
|
42
49
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
- remark-gfm
|
|
49
|
-
- unist-util-visit
|
|
50
|
+
type TocItem = {
|
|
51
|
+
level: number;
|
|
52
|
+
text: string;
|
|
53
|
+
href: string;
|
|
54
|
+
};
|
|
50
55
|
|
|
51
|
-
|
|
56
|
+
const components = {
|
|
57
|
+
// your MDX components
|
|
58
|
+
};
|
|
52
59
|
|
|
53
|
-
|
|
60
|
+
const docsService = createMdxContentService<Frontmatter, TocItem>({
|
|
61
|
+
parseOptions: { components },
|
|
62
|
+
cacheFn: cache,
|
|
63
|
+
});
|
|
54
64
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
65
|
+
const doc = await docsService.getCompiledForSlug("getting-started/introduction");
|
|
66
|
+
const frontmatter = await docsService.getFrontmatterForSlug("getting-started/introduction");
|
|
67
|
+
const tocs = await docsService.getTocsForSlug("getting-started/introduction");
|
|
68
|
+
```
|
|
59
69
|
|
|
60
|
-
|
|
70
|
+
### Importable APIs and What They Do
|
|
71
|
+
|
|
72
|
+
#### Runtime APIs
|
|
73
|
+
|
|
74
|
+
- `parseMdx`: Compile raw MDX string with optional custom parse options. Returns `MdxCompileResult<Frontmatter>`.
|
|
75
|
+
- `createMdxContentService`: Create slug-based docs service (`getParsedForSlug`, `getCompiledForSlug`, `getFrontmatterForSlug`, `getTocsForSlug`). Returns a service object.
|
|
76
|
+
- `readMdxFileBySlug`: Read `slug.mdx` or `slug/index.mdx` from docs directory. Returns `ReadMdxFileResult`.
|
|
77
|
+
- `parseMdxFile`: Convert raw file result into `frontmatter`, `tocs`, `content`, `filePath`. Returns `ParsedMdxFile<Frontmatter, TocItem>`.
|
|
78
|
+
- `compileParsedMdxFile`: Compile parsed MDX while preserving metadata and TOCs. Returns `CompiledMdxFile<Frontmatter, TocItem>`.
|
|
79
|
+
- `extractFrontmatter`: Parse frontmatter only from raw markdown/MDX. Returns `Frontmatter`.
|
|
80
|
+
- `extractTocsFromRawMdx`: Extract headings for table of contents generation. Returns `TocItem[]`.
|
|
81
|
+
- `sluggify`: Convert heading text into URL-safe slug. Returns `string`.
|
|
82
|
+
- `createDefaultRehypePlugins`: Get default DocuBook rehype plugin stack. Returns `unknown[]`.
|
|
83
|
+
- `createDefaultRemarkPlugins`: Get default DocuBook remark plugin stack. Returns `unknown[]`.
|
|
84
|
+
- `preProcess`: Add pre-processing behavior for code blocks (advanced customization). Returns a transformer function.
|
|
85
|
+
- `postProcess`: Add post-processing behavior for code blocks (advanced customization). Returns a transformer function.
|
|
86
|
+
- `handleCodeTitles`: Move code title metadata to `<pre>` attributes (advanced customization). Returns a transformer function.
|
|
87
|
+
|
|
88
|
+
#### Type Exports
|
|
89
|
+
|
|
90
|
+
| Type | Purpose |
|
|
91
|
+
| -------------------------------- | --------------------------------------------- |
|
|
92
|
+
| `MdxCompileResult` | Result shape for compiled MDX content |
|
|
93
|
+
| `TocItem` | Heading item structure used by TOC extraction |
|
|
94
|
+
| `ParseMdxOptions` | Options for `parseMdx` compile behavior |
|
|
95
|
+
| `ReadMdxFileResult` | Return type for `readMdxFileBySlug` |
|
|
96
|
+
| `ParsedMdxFile` | Parsed file structure before compile |
|
|
97
|
+
| `CompiledMdxFile` | Compiled file structure with metadata and TOC |
|
|
98
|
+
| `CreateMdxContentServiceOptions` | Options for creating the content service |
|
|
99
|
+
|
|
100
|
+
### Quick Import Recipes
|
|
101
|
+
|
|
102
|
+
#### 1. Compile raw MDX only
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
import { parseMdx } from "@docubook/core";
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Use this when your source is already in memory and you only need compiled content.
|
|
109
|
+
|
|
110
|
+
#### 2. Read frontmatter only
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
import { extractFrontmatter } from "@docubook/core";
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Use this for metadata pages where full MDX compilation is unnecessary.
|
|
117
|
+
|
|
118
|
+
#### 3. Build TOC from raw content
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
import { extractTocsFromRawMdx } from "@docubook/core";
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Use this when you need heading navigation from markdown/MDX text.
|
|
125
|
+
|
|
126
|
+
#### 4. Slug-based docs service (recommended for app integration)
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
import { createMdxContentService } from "@docubook/core";
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Use this as the default app-level integration for frontmatter, TOC, and compiled docs in one service.
|
|
133
|
+
|
|
134
|
+
#### 5. Low-level file pipeline (advanced)
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
import {
|
|
138
|
+
readMdxFileBySlug,
|
|
139
|
+
parseMdxFile,
|
|
140
|
+
compileParsedMdxFile,
|
|
141
|
+
} from "@docubook/core";
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Use this when you need full control over each pipeline step.
|
|
145
|
+
|
|
146
|
+
### Basic Compile Helpers
|
|
61
147
|
|
|
62
148
|
```ts
|
|
63
149
|
import {
|
|
@@ -109,20 +195,38 @@ const docsService = createMdxContentService<Frontmatter>({
|
|
|
109
195
|
const doc = await docsService.getCompiledForSlug("getting-started/introduction");
|
|
110
196
|
```
|
|
111
197
|
|
|
112
|
-
##
|
|
198
|
+
## Dependency Management Policy
|
|
113
199
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
-
|
|
121
|
-
-
|
|
200
|
+
Dependencies required for markdown processing are managed in this package and updated by the DocuBook author.
|
|
201
|
+
|
|
202
|
+
This means app-level users should focus on content and integration. Plugin upgrades, compatibility checks, and pipeline maintenance are handled centrally by DocuBook.
|
|
203
|
+
|
|
204
|
+
### Managed Markdown Dependencies
|
|
205
|
+
|
|
206
|
+
- gray-matter
|
|
207
|
+
- rehype-autolink-headings
|
|
208
|
+
- rehype-code-titles
|
|
209
|
+
- rehype-prism-plus
|
|
210
|
+
- rehype-slug
|
|
211
|
+
- remark-gfm
|
|
212
|
+
- unist-util-visit
|
|
213
|
+
|
|
214
|
+
The `remark` and `rehype` plugin stack is intentionally owned by this package to avoid dependency drift across apps.
|
|
215
|
+
|
|
216
|
+
## Why This Matters
|
|
217
|
+
|
|
218
|
+
- Consistent behavior across all DocuBook-based projects
|
|
219
|
+
- Easier maintenance and safer upgrades
|
|
220
|
+
- Less dependency duplication in app-level package.json files
|
|
221
|
+
- Faster onboarding for users who only need to write docs
|
|
122
222
|
|
|
123
223
|
## Notes
|
|
124
224
|
|
|
125
|
-
|
|
225
|
+
`@docubook/core` already includes and manages the MDX runtime/compile dependencies (including `next-mdx-remote`) as part of the package contract.
|
|
226
|
+
|
|
227
|
+
In most integrations, users only need to install `@docubook/core` and use the core APIs.
|
|
228
|
+
|
|
229
|
+
Only add `next-mdx-remote` directly in your app if your app explicitly imports it in app-level code.
|
|
126
230
|
|
|
127
231
|
For compile pipeline plugins (especially `remark` and `rehype` plugins), rely on this package and avoid re-declaring them at app level unless you have a specific override requirement.
|
|
128
232
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { compileMDX } from "next-mdx-remote/rsc";
|
|
2
|
+
import type { Node } from "unist";
|
|
3
|
+
import type { MdxCompileResult } from "./types";
|
|
4
|
+
type CompileMdxInput = Parameters<typeof compileMDX<Record<string, unknown>>>[0];
|
|
5
|
+
type CompileMdxOptions = NonNullable<CompileMdxInput["options"]>;
|
|
6
|
+
type CompilerMdxOptions = NonNullable<CompileMdxOptions["mdxOptions"]>;
|
|
7
|
+
export type ParseMdxOptions = {
|
|
8
|
+
components?: CompileMdxInput["components"];
|
|
9
|
+
rehypePlugins?: CompilerMdxOptions["rehypePlugins"];
|
|
10
|
+
remarkPlugins?: CompilerMdxOptions["remarkPlugins"];
|
|
11
|
+
};
|
|
12
|
+
export declare const handleCodeTitles: () => (tree: Node) => void;
|
|
13
|
+
export declare const preProcess: () => (tree: Node) => void;
|
|
14
|
+
export declare const postProcess: () => (tree: Node) => void;
|
|
15
|
+
export declare function createDefaultRehypePlugins(): unknown[];
|
|
16
|
+
export declare function createDefaultRemarkPlugins(): unknown[];
|
|
17
|
+
export declare function parseMdx<Frontmatter>(rawMdx: string, options?: ParseMdxOptions): Promise<MdxCompileResult<Frontmatter>>;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=compile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../src/compile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,IAAI,EAAU,MAAM,OAAO,CAAC;AAO1C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAkBhD,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjF,KAAK,iBAAiB,GAAG,WAAW,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC;AACjE,KAAK,kBAAkB,GAAG,WAAW,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAC,CAAC;AAEvE,MAAM,MAAM,eAAe,GAAG;IAC1B,UAAU,CAAC,EAAE,eAAe,CAAC,YAAY,CAAC,CAAC;IAC3C,aAAa,CAAC,EAAE,kBAAkB,CAAC,eAAe,CAAC,CAAC;IACpD,aAAa,CAAC,EAAE,kBAAkB,CAAC,eAAe,CAAC,CAAC;CACvD,CAAC;AAEF,eAAO,MAAM,gBAAgB,SAAU,MAAM,IAAI,SAgChD,CAAC;AAEF,eAAO,MAAM,UAAU,SAAU,MAAM,IAAI,SAa1C,CAAC;AAEF,eAAO,MAAM,WAAW,SAAU,MAAM,IAAI,SAS3C,CAAC;AAEF,wBAAgB,0BAA0B,IAAI,OAAO,EAAE,CAUtD;AAED,wBAAgB,0BAA0B,IAAI,OAAO,EAAE,CAEtD;AAED,wBAAsB,QAAQ,CAAC,WAAW,EACtC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,eAAoB,GAC9B,OAAO,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC,CAexC"}
|
|
@@ -1,61 +1,29 @@
|
|
|
1
1
|
import { compileMDX } from "next-mdx-remote/rsc";
|
|
2
|
-
import type { Node, Parent } from "unist";
|
|
3
2
|
import { visit } from "unist-util-visit";
|
|
4
3
|
import remarkGfm from "remark-gfm";
|
|
5
4
|
import rehypePrism from "rehype-prism-plus";
|
|
6
5
|
import rehypeAutolinkHeadings from "rehype-autolink-headings";
|
|
7
6
|
import rehypeSlug from "rehype-slug";
|
|
8
7
|
import rehypeCodeTitles from "rehype-code-titles";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
interface Element extends Node {
|
|
12
|
-
type: string;
|
|
13
|
-
tagName?: string;
|
|
14
|
-
properties?: Record<string, unknown> & {
|
|
15
|
-
className?: string[];
|
|
16
|
-
raw?: string;
|
|
17
|
-
};
|
|
18
|
-
children?: Node[];
|
|
19
|
-
raw?: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
interface TextNode extends Node {
|
|
23
|
-
type: "text";
|
|
24
|
-
value: string;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
type CompileMdxInput = Parameters<typeof compileMDX<Record<string, unknown>>>[0];
|
|
28
|
-
type CompileMdxOptions = NonNullable<CompileMdxInput["options"]>;
|
|
29
|
-
type CompilerMdxOptions = NonNullable<CompileMdxOptions["mdxOptions"]>;
|
|
30
|
-
|
|
31
|
-
export type ParseMdxOptions = {
|
|
32
|
-
components?: CompileMdxInput["components"];
|
|
33
|
-
rehypePlugins?: CompilerMdxOptions["rehypePlugins"];
|
|
34
|
-
remarkPlugins?: CompilerMdxOptions["remarkPlugins"];
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export const handleCodeTitles = () => (tree: Node) => {
|
|
38
|
-
visit(tree, "element", (node: Element, index: number | null, parent: Parent | null) => {
|
|
8
|
+
export const handleCodeTitles = () => (tree) => {
|
|
9
|
+
visit(tree, "element", (node, index, parent) => {
|
|
39
10
|
if (!parent || index === null || node.tagName !== "div") {
|
|
40
11
|
return;
|
|
41
12
|
}
|
|
42
|
-
|
|
43
13
|
const isTitleDiv = node.properties?.className?.includes("rehype-code-title");
|
|
44
14
|
if (!isTitleDiv) {
|
|
45
15
|
return;
|
|
46
16
|
}
|
|
47
|
-
|
|
48
|
-
let nextElement: Element | null = null;
|
|
17
|
+
let nextElement = null;
|
|
49
18
|
for (let i = index + 1; i < parent.children.length; i++) {
|
|
50
19
|
const sibling = parent.children[i];
|
|
51
20
|
if (sibling.type === "element") {
|
|
52
|
-
nextElement = sibling
|
|
21
|
+
nextElement = sibling;
|
|
53
22
|
break;
|
|
54
23
|
}
|
|
55
24
|
}
|
|
56
|
-
|
|
57
25
|
if (nextElement?.tagName === "pre") {
|
|
58
|
-
const titleNode = node.children?.[0]
|
|
26
|
+
const titleNode = node.children?.[0];
|
|
59
27
|
if (titleNode?.type === "text") {
|
|
60
28
|
if (!nextElement.properties) {
|
|
61
29
|
nextElement.properties = {};
|
|
@@ -67,25 +35,23 @@ export const handleCodeTitles = () => (tree: Node) => {
|
|
|
67
35
|
}
|
|
68
36
|
});
|
|
69
37
|
};
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const element = node as Element;
|
|
38
|
+
export const preProcess = () => (tree) => {
|
|
39
|
+
visit(tree, (node) => {
|
|
40
|
+
const element = node;
|
|
74
41
|
if (element?.type === "element" && element?.tagName === "pre" && element.children) {
|
|
75
|
-
const [codeEl] = element.children
|
|
76
|
-
if (codeEl.tagName !== "code" || !codeEl.children?.[0])
|
|
77
|
-
|
|
78
|
-
const textNode = codeEl.children[0]
|
|
42
|
+
const [codeEl] = element.children;
|
|
43
|
+
if (codeEl.tagName !== "code" || !codeEl.children?.[0])
|
|
44
|
+
return;
|
|
45
|
+
const textNode = codeEl.children[0];
|
|
79
46
|
if (textNode.type === "text" && textNode.value) {
|
|
80
47
|
element.raw = textNode.value;
|
|
81
48
|
}
|
|
82
49
|
}
|
|
83
50
|
});
|
|
84
51
|
};
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const element = node as Element;
|
|
52
|
+
export const postProcess = () => (tree) => {
|
|
53
|
+
visit(tree, "element", (node) => {
|
|
54
|
+
const element = node;
|
|
89
55
|
if (element?.type === "element" && element?.tagName === "pre") {
|
|
90
56
|
if (element.properties && element.raw) {
|
|
91
57
|
element.properties.raw = element.raw;
|
|
@@ -93,8 +59,7 @@ export const postProcess = () => (tree: Node) => {
|
|
|
93
59
|
}
|
|
94
60
|
});
|
|
95
61
|
};
|
|
96
|
-
|
|
97
|
-
export function createDefaultRehypePlugins(): unknown[] {
|
|
62
|
+
export function createDefaultRehypePlugins() {
|
|
98
63
|
return [
|
|
99
64
|
preProcess,
|
|
100
65
|
rehypeCodeTitles,
|
|
@@ -105,19 +70,13 @@ export function createDefaultRehypePlugins(): unknown[] {
|
|
|
105
70
|
postProcess,
|
|
106
71
|
];
|
|
107
72
|
}
|
|
108
|
-
|
|
109
|
-
export function createDefaultRemarkPlugins(): unknown[] {
|
|
73
|
+
export function createDefaultRemarkPlugins() {
|
|
110
74
|
return [remarkGfm];
|
|
111
75
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
): Promise<MdxCompileResult<Frontmatter>> {
|
|
117
|
-
const rehypePlugins = options.rehypePlugins ?? (createDefaultRehypePlugins() as CompilerMdxOptions["rehypePlugins"]);
|
|
118
|
-
const remarkPlugins = options.remarkPlugins ?? (createDefaultRemarkPlugins() as CompilerMdxOptions["remarkPlugins"]);
|
|
119
|
-
|
|
120
|
-
return await compileMDX<Frontmatter>({
|
|
76
|
+
export async function parseMdx(rawMdx, options = {}) {
|
|
77
|
+
const rehypePlugins = options.rehypePlugins ?? createDefaultRehypePlugins();
|
|
78
|
+
const remarkPlugins = options.remarkPlugins ?? createDefaultRemarkPlugins();
|
|
79
|
+
return await compileMDX({
|
|
121
80
|
source: rawMdx,
|
|
122
81
|
options: {
|
|
123
82
|
parseFrontmatter: true,
|
|
@@ -129,3 +88,4 @@ export async function parseMdx<Frontmatter>(
|
|
|
129
88
|
components: options.components,
|
|
130
89
|
});
|
|
131
90
|
}
|
|
91
|
+
//# sourceMappingURL=compile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile.js","sourceRoot":"","sources":["../src/compile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type ParseMdxOptions } from "./compile";
|
|
2
|
+
import type { MdxCompileResult, TocItem } from "./types";
|
|
3
|
+
type CacheFn = <T extends (...args: any[]) => any>(fn: T) => T;
|
|
4
|
+
export type ReadMdxFileResult = {
|
|
5
|
+
content: string;
|
|
6
|
+
filePath: string;
|
|
7
|
+
};
|
|
8
|
+
export type ParsedMdxFile<Frontmatter, T extends TocItem = TocItem> = {
|
|
9
|
+
content: string;
|
|
10
|
+
filePath: string;
|
|
11
|
+
frontmatter: Frontmatter;
|
|
12
|
+
tocs: T[];
|
|
13
|
+
};
|
|
14
|
+
export type CompiledMdxFile<Frontmatter, T extends TocItem = TocItem> = MdxCompileResult<Frontmatter> & {
|
|
15
|
+
filePath: string;
|
|
16
|
+
tocs: T[];
|
|
17
|
+
};
|
|
18
|
+
type ReadMdxBySlugOptions = {
|
|
19
|
+
rootDir?: string;
|
|
20
|
+
docsDir?: string;
|
|
21
|
+
};
|
|
22
|
+
export declare function readMdxFileBySlug(slug: string, options?: ReadMdxBySlugOptions): Promise<ReadMdxFileResult>;
|
|
23
|
+
type ParseMdxFileOptions<T extends TocItem> = {
|
|
24
|
+
tocsExtractor?: (rawMdx: string) => T[];
|
|
25
|
+
};
|
|
26
|
+
export declare function parseMdxFile<Frontmatter, T extends TocItem = TocItem>(raw: ReadMdxFileResult, options?: ParseMdxFileOptions<T>): ParsedMdxFile<Frontmatter, T>;
|
|
27
|
+
export declare function compileParsedMdxFile<Frontmatter, T extends TocItem = TocItem>(parsed: ParsedMdxFile<Frontmatter, T>, options?: ParseMdxOptions): Promise<CompiledMdxFile<Frontmatter, T>>;
|
|
28
|
+
export type CreateMdxContentServiceOptions<Frontmatter, T extends TocItem = TocItem> = {
|
|
29
|
+
parseOptions?: ParseMdxOptions;
|
|
30
|
+
readOptions?: ReadMdxBySlugOptions;
|
|
31
|
+
tocsExtractor?: (rawMdx: string) => T[];
|
|
32
|
+
cacheFn?: CacheFn;
|
|
33
|
+
};
|
|
34
|
+
export declare function createMdxContentService<Frontmatter, T extends TocItem = TocItem>(options?: CreateMdxContentServiceOptions<Frontmatter, T>): {
|
|
35
|
+
getParsedForSlug: (slug: string) => Promise<ParsedMdxFile<Frontmatter, T>>;
|
|
36
|
+
getCompiledForSlug: (slug: string) => Promise<CompiledMdxFile<Frontmatter, T>>;
|
|
37
|
+
getFrontmatterForSlug: (slug: string) => Promise<Frontmatter>;
|
|
38
|
+
getTocsForSlug: (slug: string) => Promise<T[]>;
|
|
39
|
+
};
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=content.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../src/content.ts"],"names":[],"mappings":"AAGA,OAAO,EAAY,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzD,KAAK,OAAO,GAAG,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;AAE/D,MAAM,MAAM,iBAAiB,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,aAAa,CAAC,WAAW,EAAE,CAAC,SAAS,OAAO,GAAG,OAAO,IAAI;IAClE,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,WAAW,CAAC;IACzB,IAAI,EAAE,CAAC,EAAE,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,eAAe,CAAC,WAAW,EAAE,CAAC,SAAS,OAAO,GAAG,OAAO,IAAI,gBAAgB,CAAC,WAAW,CAAC,GAAG;IACpG,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,CAAC,EAAE,CAAC;CACb,CAAC;AAEF,KAAK,oBAAoB,GAAG;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAyBpH;AAED,KAAK,mBAAmB,CAAC,CAAC,SAAS,OAAO,IAAI;IAC1C,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,CAAC,EAAE,CAAC;CAC3C,CAAC;AAEF,wBAAgB,YAAY,CAAC,WAAW,EAAE,CAAC,SAAS,OAAO,GAAG,OAAO,EACjE,GAAG,EAAE,iBAAiB,EACtB,OAAO,GAAE,mBAAmB,CAAC,CAAC,CAAM,GACrC,aAAa,CAAC,WAAW,EAAE,CAAC,CAAC,CAS/B;AAED,wBAAsB,oBAAoB,CAAC,WAAW,EAAE,CAAC,SAAS,OAAO,GAAG,OAAO,EAC/E,MAAM,EAAE,aAAa,CAAC,WAAW,EAAE,CAAC,CAAC,EACrC,OAAO,GAAE,eAAoB,GAC9B,OAAO,CAAC,eAAe,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAS1C;AAED,MAAM,MAAM,8BAA8B,CAAC,WAAW,EAAE,CAAC,SAAS,OAAO,GAAG,OAAO,IAAI;IACnF,YAAY,CAAC,EAAE,eAAe,CAAC;IAC/B,WAAW,CAAC,EAAE,oBAAoB,CAAC;IACnC,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,CAAC,EAAE,CAAC;IACxC,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,CAAC,SAAS,OAAO,GAAG,OAAO,EAC5E,OAAO,GAAE,8BAA8B,CAAC,WAAW,EAAE,CAAC,CAAM;6BAKd,MAAM,KAAG,OAAO,CAAC,aAAa,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;+BAK7C,MAAM,KAAG,OAAO,CAAC,eAAe,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;kCAKtD,MAAM,KAAG,OAAO,CAAC,WAAW,CAAC;2BAKpC,MAAM,KAAG,OAAO,CAAC,CAAC,EAAE,CAAC;EAW5D"}
|
package/dist/content.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { promises as fs } from "fs";
|
|
3
|
+
import { extractFrontmatter, extractTocsFromRawMdx } from "./extract";
|
|
4
|
+
import { parseMdx } from "./compile";
|
|
5
|
+
export async function readMdxFileBySlug(slug, options = {}) {
|
|
6
|
+
const docsDir = options.docsDir ?? "docs";
|
|
7
|
+
// Keep file-system path operations ignored by Turbopack tracing.
|
|
8
|
+
// The runtime path is constrained to docsDir and slug candidates below.
|
|
9
|
+
const docsRoot = options.rootDir
|
|
10
|
+
? path.join(/*turbopackIgnore: true*/ options.rootDir, docsDir)
|
|
11
|
+
: path.join(/*turbopackIgnore: true*/ process.cwd(), docsDir);
|
|
12
|
+
const paths = [
|
|
13
|
+
path.join(/*turbopackIgnore: true*/ docsRoot, `${slug}.mdx`),
|
|
14
|
+
path.join(/*turbopackIgnore: true*/ docsRoot, slug, "index.mdx"),
|
|
15
|
+
];
|
|
16
|
+
for (const p of paths) {
|
|
17
|
+
try {
|
|
18
|
+
const content = await fs.readFile(/*turbopackIgnore: true*/ p, "utf-8");
|
|
19
|
+
return {
|
|
20
|
+
content,
|
|
21
|
+
filePath: `${docsDir}/${path.relative(/*turbopackIgnore: true*/ docsRoot, p)}`,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
// ignore and try next candidate
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
throw new Error(`Could not find mdx file for slug: ${slug}`);
|
|
29
|
+
}
|
|
30
|
+
export function parseMdxFile(raw, options = {}) {
|
|
31
|
+
const tocsExtractor = options.tocsExtractor ?? ((mdx) => extractTocsFromRawMdx(mdx));
|
|
32
|
+
return {
|
|
33
|
+
content: raw.content,
|
|
34
|
+
filePath: raw.filePath,
|
|
35
|
+
frontmatter: extractFrontmatter(raw.content),
|
|
36
|
+
tocs: tocsExtractor(raw.content),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export async function compileParsedMdxFile(parsed, options = {}) {
|
|
40
|
+
const compiled = await parseMdx(parsed.content, options);
|
|
41
|
+
return {
|
|
42
|
+
...compiled,
|
|
43
|
+
frontmatter: parsed.frontmatter,
|
|
44
|
+
filePath: parsed.filePath,
|
|
45
|
+
tocs: parsed.tocs,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export function createMdxContentService(options = {}) {
|
|
49
|
+
const identityCache = (fn) => fn;
|
|
50
|
+
const cacheFn = options.cacheFn ?? identityCache;
|
|
51
|
+
const getParsedForSlug = cacheFn(async (slug) => {
|
|
52
|
+
const raw = await readMdxFileBySlug(slug, options.readOptions);
|
|
53
|
+
return parseMdxFile(raw, { tocsExtractor: options.tocsExtractor });
|
|
54
|
+
});
|
|
55
|
+
const getCompiledForSlug = cacheFn(async (slug) => {
|
|
56
|
+
const parsed = await getParsedForSlug(slug);
|
|
57
|
+
return compileParsedMdxFile(parsed, options.parseOptions);
|
|
58
|
+
});
|
|
59
|
+
async function getFrontmatterForSlug(slug) {
|
|
60
|
+
const parsed = await getParsedForSlug(slug);
|
|
61
|
+
return parsed.frontmatter;
|
|
62
|
+
}
|
|
63
|
+
async function getTocsForSlug(slug) {
|
|
64
|
+
const parsed = await getParsedForSlug(slug);
|
|
65
|
+
return parsed.tocs;
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
getParsedForSlug,
|
|
69
|
+
getCompiledForSlug,
|
|
70
|
+
getFrontmatterForSlug,
|
|
71
|
+
getTocsForSlug,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=content.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content.js","sourceRoot":"","sources":["../src/content.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { TocItem } from "./types";
|
|
2
|
+
export declare function sluggify(text: string): string;
|
|
3
|
+
export declare function extractTocsFromRawMdx(rawMdx: string): TocItem[];
|
|
4
|
+
export declare function extractFrontmatter<Frontmatter>(content: string): Frontmatter;
|
|
5
|
+
//# sourceMappingURL=extract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../src/extract.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG7C;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,EAAE,CA+B/D;AAED,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,WAAW,CAE5E"}
|
|
@@ -1,20 +1,16 @@
|
|
|
1
1
|
import matter from "gray-matter";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export function sluggify(text: string): string {
|
|
2
|
+
export function sluggify(text) {
|
|
5
3
|
const slug = text.toLowerCase().replace(/\s+/g, "-");
|
|
6
4
|
return slug.replace(/[^a-z0-9-]/g, "");
|
|
7
5
|
}
|
|
8
|
-
|
|
9
|
-
export function extractTocsFromRawMdx(rawMdx: string): TocItem[] {
|
|
6
|
+
export function extractTocsFromRawMdx(rawMdx) {
|
|
10
7
|
// Match code blocks, markdown headings, and <Release version="x.y.z" />.
|
|
11
8
|
const combinedRegex = /(```[\s\S]*?```)|^(#{2,4})\s(.+)$|<Release[^>]*version="([^"]+)"/gm;
|
|
12
|
-
const extractedHeadings
|
|
13
|
-
|
|
14
|
-
let match: RegExpExecArray | null;
|
|
9
|
+
const extractedHeadings = [];
|
|
10
|
+
let match;
|
|
15
11
|
while ((match = combinedRegex.exec(rawMdx)) !== null) {
|
|
16
|
-
if (match[1])
|
|
17
|
-
|
|
12
|
+
if (match[1])
|
|
13
|
+
continue;
|
|
18
14
|
if (match[2]) {
|
|
19
15
|
const headingLevel = match[2].length;
|
|
20
16
|
const headingText = match[3].trim();
|
|
@@ -25,7 +21,6 @@ export function extractTocsFromRawMdx(rawMdx: string): TocItem[] {
|
|
|
25
21
|
});
|
|
26
22
|
continue;
|
|
27
23
|
}
|
|
28
|
-
|
|
29
24
|
if (match[4]) {
|
|
30
25
|
const version = match[4];
|
|
31
26
|
extractedHeadings.push({
|
|
@@ -35,10 +30,9 @@ export function extractTocsFromRawMdx(rawMdx: string): TocItem[] {
|
|
|
35
30
|
});
|
|
36
31
|
}
|
|
37
32
|
}
|
|
38
|
-
|
|
39
33
|
return extractedHeadings;
|
|
40
34
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
return matter(content).data as Frontmatter;
|
|
35
|
+
export function extractFrontmatter(content) {
|
|
36
|
+
return matter(content).data;
|
|
44
37
|
}
|
|
38
|
+
//# sourceMappingURL=extract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.js","sourceRoot":"","sources":["../src/extract.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AAGjC,MAAM,UAAU,QAAQ,CAAC,IAAY;IACjC,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACrD,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,MAAc;IAChD,yEAAyE;IACzE,MAAM,aAAa,GAAG,oEAAoE,CAAC;IAC3F,MAAM,iBAAiB,GAAc,EAAE,CAAC;IAExC,IAAI,KAA6B,CAAC;IAClC,OAAO,CAAC,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACnD,IAAI,KAAK,CAAC,CAAC,CAAC;YAAE,SAAS;QAEvB,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;YACX,MAAM,YAAY,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;YACrC,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YACpC,iBAAiB,CAAC,IAAI,CAAC;gBACnB,KAAK,EAAE,YAAY;gBACnB,IAAI,EAAE,WAAW;gBACjB,IAAI,EAAE,IAAI,QAAQ,CAAC,WAAW,CAAC,EAAE;aACpC,CAAC,CAAC;YACH,SAAS;QACb,CAAC;QAED,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;YACX,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACzB,iBAAiB,CAAC,IAAI,CAAC;gBACnB,KAAK,EAAE,CAAC;gBACR,IAAI,EAAE,IAAI,OAAO,EAAE;gBACnB,IAAI,EAAE,IAAI,OAAO,EAAE;aACtB,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IAED,OAAO,iBAAiB,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAc,OAAe;IAC3D,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,IAAmB,CAAC;AAC/C,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type { TocItem, MdxCompileResult } from "./types";
|
|
2
|
+
export { parseMdx, preProcess, postProcess, handleCodeTitles, createDefaultRehypePlugins, createDefaultRemarkPlugins, } from "./compile";
|
|
3
|
+
export { extractFrontmatter, extractTocsFromRawMdx, sluggify } from "./extract";
|
|
4
|
+
export type { ParseMdxOptions } from "./compile";
|
|
5
|
+
export { readMdxFileBySlug, parseMdxFile, compileParsedMdxFile, createMdxContentService, } from "./content";
|
|
6
|
+
export type { ReadMdxFileResult, ParsedMdxFile, CompiledMdxFile, CreateMdxContentServiceOptions, } from "./content";
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AACzD,OAAO,EACH,QAAQ,EACR,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,0BAA0B,EAC1B,0BAA0B,GAC7B,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAChF,YAAY,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EACH,iBAAiB,EACjB,YAAY,EACZ,oBAAoB,EACpB,uBAAuB,GAC1B,MAAM,WAAW,CAAC;AACnB,YAAY,EACR,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,8BAA8B,GACjC,MAAM,WAAW,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { parseMdx, preProcess, postProcess, handleCodeTitles, createDefaultRehypePlugins, createDefaultRemarkPlugins, } from "./compile";
|
|
2
|
+
export { extractFrontmatter, extractTocsFromRawMdx, sluggify } from "./extract";
|
|
3
|
+
export { readMdxFileBySlug, parseMdxFile, compileParsedMdxFile, createMdxContentService, } from "./content";
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACH,QAAQ,EACR,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,0BAA0B,EAC1B,0BAA0B,GAC7B,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAEhF,OAAO,EACH,iBAAiB,EACjB,YAAY,EACZ,oBAAoB,EACpB,uBAAuB,GAC1B,MAAM,WAAW,CAAC"}
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
|
-
|
|
3
2
|
export type TocItem = {
|
|
4
3
|
level: number;
|
|
5
4
|
text: string;
|
|
6
5
|
href: string;
|
|
7
6
|
};
|
|
8
|
-
|
|
9
7
|
export type MdxCompileResult<Frontmatter> = {
|
|
10
8
|
content: ReactNode;
|
|
11
9
|
frontmatter: Frontmatter;
|
|
12
10
|
scope?: Record<string, unknown>;
|
|
13
11
|
};
|
|
12
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,MAAM,OAAO,GAAG;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,gBAAgB,CAAC,WAAW,IAAI;IACxC,OAAO,EAAE,SAAS,CAAC;IACnB,WAAW,EAAE,WAAW,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC,CAAC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docubook/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Shared MDX compile pipeline and markdown utilities for DocuBook",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "./
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
7
8
|
"exports": {
|
|
8
|
-
".":
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
}
|
|
9
14
|
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
10
18
|
"scripts": {
|
|
11
|
-
"build": "
|
|
19
|
+
"build": "tsc -p tsconfig.json",
|
|
20
|
+
"clean": "rm -rf dist",
|
|
21
|
+
"prepublishOnly": "pnpm run clean && pnpm run build"
|
|
12
22
|
},
|
|
13
23
|
"keywords": [
|
|
14
24
|
"docubook",
|
package/src/content.ts
DELETED
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import path from "path";
|
|
2
|
-
import { promises as fs } from "fs";
|
|
3
|
-
import { extractFrontmatter, extractTocsFromRawMdx } from "./extract";
|
|
4
|
-
import { parseMdx, type ParseMdxOptions } from "./compile";
|
|
5
|
-
import type { MdxCompileResult, TocItem } from "./types";
|
|
6
|
-
|
|
7
|
-
type CacheFn = <T extends (...args: any[]) => any>(fn: T) => T;
|
|
8
|
-
|
|
9
|
-
export type ReadMdxFileResult = {
|
|
10
|
-
content: string;
|
|
11
|
-
filePath: string;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export type ParsedMdxFile<Frontmatter, T extends TocItem = TocItem> = {
|
|
15
|
-
content: string;
|
|
16
|
-
filePath: string;
|
|
17
|
-
frontmatter: Frontmatter;
|
|
18
|
-
tocs: T[];
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export type CompiledMdxFile<Frontmatter, T extends TocItem = TocItem> = MdxCompileResult<Frontmatter> & {
|
|
22
|
-
filePath: string;
|
|
23
|
-
tocs: T[];
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
type ReadMdxBySlugOptions = {
|
|
27
|
-
rootDir?: string;
|
|
28
|
-
docsDir?: string;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export async function readMdxFileBySlug(slug: string, options: ReadMdxBySlugOptions = {}): Promise<ReadMdxFileResult> {
|
|
32
|
-
const docsDir = options.docsDir ?? "docs";
|
|
33
|
-
// Keep file-system path operations ignored by Turbopack tracing.
|
|
34
|
-
// The runtime path is constrained to docsDir and slug candidates below.
|
|
35
|
-
const docsRoot = options.rootDir
|
|
36
|
-
? path.join(/*turbopackIgnore: true*/ options.rootDir, docsDir)
|
|
37
|
-
: path.join(/*turbopackIgnore: true*/ process.cwd(), docsDir);
|
|
38
|
-
const paths = [
|
|
39
|
-
path.join(/*turbopackIgnore: true*/ docsRoot, `${slug}.mdx`),
|
|
40
|
-
path.join(/*turbopackIgnore: true*/ docsRoot, slug, "index.mdx"),
|
|
41
|
-
];
|
|
42
|
-
|
|
43
|
-
for (const p of paths) {
|
|
44
|
-
try {
|
|
45
|
-
const content = await fs.readFile(/*turbopackIgnore: true*/ p, "utf-8");
|
|
46
|
-
return {
|
|
47
|
-
content,
|
|
48
|
-
filePath: `${docsDir}/${path.relative(/*turbopackIgnore: true*/ docsRoot, p)}`,
|
|
49
|
-
};
|
|
50
|
-
} catch {
|
|
51
|
-
// ignore and try next candidate
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
throw new Error(`Could not find mdx file for slug: ${slug}`);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
type ParseMdxFileOptions<T extends TocItem> = {
|
|
59
|
-
tocsExtractor?: (rawMdx: string) => T[];
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
export function parseMdxFile<Frontmatter, T extends TocItem = TocItem>(
|
|
63
|
-
raw: ReadMdxFileResult,
|
|
64
|
-
options: ParseMdxFileOptions<T> = {}
|
|
65
|
-
): ParsedMdxFile<Frontmatter, T> {
|
|
66
|
-
const tocsExtractor = options.tocsExtractor ?? ((mdx) => extractTocsFromRawMdx(mdx) as T[]);
|
|
67
|
-
|
|
68
|
-
return {
|
|
69
|
-
content: raw.content,
|
|
70
|
-
filePath: raw.filePath,
|
|
71
|
-
frontmatter: extractFrontmatter<Frontmatter>(raw.content),
|
|
72
|
-
tocs: tocsExtractor(raw.content),
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export async function compileParsedMdxFile<Frontmatter, T extends TocItem = TocItem>(
|
|
77
|
-
parsed: ParsedMdxFile<Frontmatter, T>,
|
|
78
|
-
options: ParseMdxOptions = {}
|
|
79
|
-
): Promise<CompiledMdxFile<Frontmatter, T>> {
|
|
80
|
-
const compiled = await parseMdx<Frontmatter>(parsed.content, options);
|
|
81
|
-
|
|
82
|
-
return {
|
|
83
|
-
...compiled,
|
|
84
|
-
frontmatter: parsed.frontmatter,
|
|
85
|
-
filePath: parsed.filePath,
|
|
86
|
-
tocs: parsed.tocs,
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export type CreateMdxContentServiceOptions<Frontmatter, T extends TocItem = TocItem> = {
|
|
91
|
-
parseOptions?: ParseMdxOptions;
|
|
92
|
-
readOptions?: ReadMdxBySlugOptions;
|
|
93
|
-
tocsExtractor?: (rawMdx: string) => T[];
|
|
94
|
-
cacheFn?: CacheFn;
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
export function createMdxContentService<Frontmatter, T extends TocItem = TocItem>(
|
|
98
|
-
options: CreateMdxContentServiceOptions<Frontmatter, T> = {}
|
|
99
|
-
) {
|
|
100
|
-
const identityCache: CacheFn = (fn) => fn;
|
|
101
|
-
const cacheFn = options.cacheFn ?? identityCache;
|
|
102
|
-
|
|
103
|
-
const getParsedForSlug = cacheFn(async (slug: string): Promise<ParsedMdxFile<Frontmatter, T>> => {
|
|
104
|
-
const raw = await readMdxFileBySlug(slug, options.readOptions);
|
|
105
|
-
return parseMdxFile<Frontmatter, T>(raw, { tocsExtractor: options.tocsExtractor });
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
const getCompiledForSlug = cacheFn(async (slug: string): Promise<CompiledMdxFile<Frontmatter, T>> => {
|
|
109
|
-
const parsed = await getParsedForSlug(slug);
|
|
110
|
-
return compileParsedMdxFile<Frontmatter, T>(parsed, options.parseOptions);
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
async function getFrontmatterForSlug(slug: string): Promise<Frontmatter> {
|
|
114
|
-
const parsed = await getParsedForSlug(slug);
|
|
115
|
-
return parsed.frontmatter;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
async function getTocsForSlug(slug: string): Promise<T[]> {
|
|
119
|
-
const parsed = await getParsedForSlug(slug);
|
|
120
|
-
return parsed.tocs;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
return {
|
|
124
|
-
getParsedForSlug,
|
|
125
|
-
getCompiledForSlug,
|
|
126
|
-
getFrontmatterForSlug,
|
|
127
|
-
getTocsForSlug,
|
|
128
|
-
};
|
|
129
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
export type { TocItem, MdxCompileResult } from "./types";
|
|
2
|
-
export {
|
|
3
|
-
parseMdx,
|
|
4
|
-
preProcess,
|
|
5
|
-
postProcess,
|
|
6
|
-
handleCodeTitles,
|
|
7
|
-
createDefaultRehypePlugins,
|
|
8
|
-
createDefaultRemarkPlugins,
|
|
9
|
-
} from "./compile";
|
|
10
|
-
export { extractFrontmatter, extractTocsFromRawMdx, sluggify } from "./extract";
|
|
11
|
-
export type { ParseMdxOptions } from "./compile";
|
|
12
|
-
export {
|
|
13
|
-
readMdxFileBySlug,
|
|
14
|
-
parseMdxFile,
|
|
15
|
-
compileParsedMdxFile,
|
|
16
|
-
createMdxContentService,
|
|
17
|
-
} from "./content";
|
|
18
|
-
export type {
|
|
19
|
-
ReadMdxFileResult,
|
|
20
|
-
ParsedMdxFile,
|
|
21
|
-
CompiledMdxFile,
|
|
22
|
-
CreateMdxContentServiceOptions,
|
|
23
|
-
} from "./content";
|
package/tsconfig.json
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2020",
|
|
4
|
-
"module": "ESNext",
|
|
5
|
-
"moduleResolution": "Bundler",
|
|
6
|
-
"strict": true,
|
|
7
|
-
"skipLibCheck": true,
|
|
8
|
-
"declaration": true,
|
|
9
|
-
"declarationMap": true,
|
|
10
|
-
"jsx": "preserve"
|
|
11
|
-
},
|
|
12
|
-
"include": [
|
|
13
|
-
"src/**/*"
|
|
14
|
-
]
|
|
15
|
-
}
|