@gentleduck/md 0.2.0
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/README.md +95 -0
- package/dmc.darwin-arm64.node +0 -0
- package/dmc.darwin-x64.node +0 -0
- package/dmc.linux-arm64-gnu.node +0 -0
- package/dmc.linux-x64-gnu.node +0 -0
- package/dmc.linux-x64-musl.node +0 -0
- package/dmc.win32-x64-msvc.node +0 -0
- package/index.d.ts +60 -0
- package/index.js +318 -0
- package/logo-dark.svg +9 -0
- package/mod.d.ts +206 -0
- package/mod.js +483 -0
- package/package.json +69 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 gentleduck
|
|
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.
|
package/README.md
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="./logo-dark.svg" alt="@gentleduck/md" width="120"/>
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">@gentleduck/md</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
Native Rust MDX compiler with a velite-shaped TypeScript API.
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://github.com/gentleeduck/duck-mc/blob/master/LICENSE">MIT</a> -
|
|
13
|
+
<a href="https://github.com/gentleeduck/duck-mc/blob/master/CHANGELOG.md">Changelog</a> -
|
|
14
|
+
<a href="https://github.com/gentleeduck/duck-mc/blob/master/CONTRIBUTING.md">Contributing</a> -
|
|
15
|
+
<a href="https://github.com/gentleeduck/duck-mc/tree/master/dmc-docs">Docs</a> -
|
|
16
|
+
<a href="https://github.com/gentleeduck/duck-mc/tree/master/duck-benchmarks">Benchmarks</a>
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
<p align="center">
|
|
20
|
+
<a href="https://www.npmjs.com/package/@gentleduck/md"><img src="https://img.shields.io/npm/v/@gentleduck/md.svg" alt="npm"/></a>
|
|
21
|
+
<a href="https://github.com/gentleeduck/duck-mc/blob/master/LICENSE"><img src="https://img.shields.io/npm/l/@gentleduck/md.svg" alt="MIT"/></a>
|
|
22
|
+
</p>
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Install
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
pnpm add @gentleduck/md
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Optional: `@gentleduck/md-sidecar` for foreign remark / rehype plugins.
|
|
33
|
+
|
|
34
|
+
## Quick start
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
// dmc.config.ts
|
|
38
|
+
import { defineConfig, s } from "@gentleduck/md";
|
|
39
|
+
|
|
40
|
+
export default defineConfig({
|
|
41
|
+
output: { data: ".gentleduck", html: true },
|
|
42
|
+
collections: {
|
|
43
|
+
posts: {
|
|
44
|
+
name: "Post",
|
|
45
|
+
pattern: "content/posts/**/*.mdx",
|
|
46
|
+
schema: (s) => s.object({
|
|
47
|
+
title: s.string(),
|
|
48
|
+
date: s.isodate(),
|
|
49
|
+
slug: s.path(),
|
|
50
|
+
}),
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
dmc build
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Outputs `.gentleduck/Post.json` + typed `index.d.ts`. Import from any framework.
|
|
61
|
+
|
|
62
|
+
## Native features
|
|
63
|
+
|
|
64
|
+
Pretty code (syntect), KaTeX/MathML math, emoji, code imports,
|
|
65
|
+
npm-command tabs, mermaid, bare URL autolinks, heading autolinks,
|
|
66
|
+
asset copy.
|
|
67
|
+
|
|
68
|
+
JS plugins listed in config that have native equivalents
|
|
69
|
+
(`remark-gfm`, `rehype-pretty-code`, `rehype-katex`, `rehype-slug`,
|
|
70
|
+
etc) are stripped from the sidecar payload automatically.
|
|
71
|
+
|
|
72
|
+
## Docs
|
|
73
|
+
|
|
74
|
+
Repo: [github.com/gentleeduck/duck-mc](https://github.com/gentleeduck/duck-mc)
|
|
75
|
+
|
|
76
|
+
- Per-crate references, architecture, integration guides:
|
|
77
|
+
[`dmc-docs/`](https://github.com/gentleeduck/duck-mc/tree/master/dmc-docs)
|
|
78
|
+
- duck-ui website cross-link:
|
|
79
|
+
[github.com/gentleeduck/duck-ui](https://github.com/gentleeduck/duck-ui)
|
|
80
|
+
- Migration from velite:
|
|
81
|
+
[`docs/migrating-from-velite.md`](https://github.com/gentleeduck/duck-mc/blob/master/docs/migrating-from-velite.md)
|
|
82
|
+
|
|
83
|
+
## Benchmarks
|
|
84
|
+
|
|
85
|
+
Five recorded phases; **9.5x velite** at the kitchen-sink workload.
|
|
86
|
+
Full numbers: [`duck-benchmarks/`](https://github.com/gentleeduck/duck-mc/tree/master/duck-benchmarks).
|
|
87
|
+
|
|
88
|
+
## Contributing
|
|
89
|
+
|
|
90
|
+
PR checklist + style notes:
|
|
91
|
+
[`CONTRIBUTING.md`](https://github.com/gentleeduck/duck-mc/blob/master/CONTRIBUTING.md).
|
|
92
|
+
|
|
93
|
+
## License
|
|
94
|
+
|
|
95
|
+
MIT
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
/* auto-generated by NAPI-RS */
|
|
5
|
+
|
|
6
|
+
export declare function compile(source: string): any
|
|
7
|
+
/**
|
|
8
|
+
* Render a LaTeX fragment to KaTeX HTML via the embedded KaTeX engine.
|
|
9
|
+
* Output matches the JS chain `rehype-katex` byte-for-byte. Pair with
|
|
10
|
+
* the standard `katex.min.css` for glyph rendering.
|
|
11
|
+
*/
|
|
12
|
+
export declare function latexToHtml(latex: string, display: boolean): string
|
|
13
|
+
export declare function compileMany(sources: Array<string>): Array<any>
|
|
14
|
+
export interface CollectionInput {
|
|
15
|
+
name: string
|
|
16
|
+
pattern: string
|
|
17
|
+
baseDir: string
|
|
18
|
+
schema?: any
|
|
19
|
+
single?: boolean
|
|
20
|
+
}
|
|
21
|
+
export interface BuildInput {
|
|
22
|
+
outputDir: string
|
|
23
|
+
collections: Array<CollectionInput>
|
|
24
|
+
root?: string
|
|
25
|
+
strict?: boolean
|
|
26
|
+
clean?: boolean
|
|
27
|
+
outputAssets?: string
|
|
28
|
+
outputBase?: string
|
|
29
|
+
outputName?: string
|
|
30
|
+
outputFormat?: string
|
|
31
|
+
markdownRemarkPlugins?: any
|
|
32
|
+
markdownRehypePlugins?: any
|
|
33
|
+
mdxRemarkPlugins?: any
|
|
34
|
+
mdxRehypePlugins?: any
|
|
35
|
+
copyLinkedFiles?: boolean
|
|
36
|
+
mdxOutputFormat?: string
|
|
37
|
+
mdxMinify?: boolean
|
|
38
|
+
markdownGfm?: boolean
|
|
39
|
+
includeHtml?: boolean
|
|
40
|
+
cacheEnabled?: boolean
|
|
41
|
+
/**
|
|
42
|
+
* Bypass the plugin gate for every plugin: every JS plugin runs
|
|
43
|
+
* in the sidecar, every native transformer is dropped.
|
|
44
|
+
*/
|
|
45
|
+
forceSidecar?: boolean
|
|
46
|
+
/**
|
|
47
|
+
* Per-plugin sidecar preference. Names listed here run in the
|
|
48
|
+
* sidecar; the matching native transformer is dropped from the
|
|
49
|
+
* pipeline. Names dmc recognises:
|
|
50
|
+
* "remark-gfm", "remark-math", "remark-emoji",
|
|
51
|
+
* "rehype-pretty-code", "shiki",
|
|
52
|
+
* "rehype-katex", "rehype-mathjax",
|
|
53
|
+
* "rehype-slug", "rehype-autolink-headings"
|
|
54
|
+
*/
|
|
55
|
+
preferSidecar?: Array<string>
|
|
56
|
+
}
|
|
57
|
+
export interface BuildReport {
|
|
58
|
+
diagnostics: Array<string>
|
|
59
|
+
}
|
|
60
|
+
export declare function build(input: BuildInput): BuildReport
|
package/index.js
ADDED
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
/* prettier-ignore */
|
|
4
|
+
|
|
5
|
+
/* auto-generated by NAPI-RS */
|
|
6
|
+
|
|
7
|
+
const { existsSync, readFileSync } = require('fs')
|
|
8
|
+
const { join } = require('path')
|
|
9
|
+
|
|
10
|
+
const { platform, arch } = process
|
|
11
|
+
|
|
12
|
+
let nativeBinding = null
|
|
13
|
+
let localFileExisted = false
|
|
14
|
+
let loadError = null
|
|
15
|
+
|
|
16
|
+
function isMusl() {
|
|
17
|
+
// For Node 10
|
|
18
|
+
if (!process.report || typeof process.report.getReport !== 'function') {
|
|
19
|
+
try {
|
|
20
|
+
const lddPath = require('child_process').execSync('which ldd').toString().trim()
|
|
21
|
+
return readFileSync(lddPath, 'utf8').includes('musl')
|
|
22
|
+
} catch (e) {
|
|
23
|
+
return true
|
|
24
|
+
}
|
|
25
|
+
} else {
|
|
26
|
+
const { glibcVersionRuntime } = process.report.getReport().header
|
|
27
|
+
return !glibcVersionRuntime
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
switch (platform) {
|
|
32
|
+
case 'android':
|
|
33
|
+
switch (arch) {
|
|
34
|
+
case 'arm64':
|
|
35
|
+
localFileExisted = existsSync(join(__dirname, 'dmc.android-arm64.node'))
|
|
36
|
+
try {
|
|
37
|
+
if (localFileExisted) {
|
|
38
|
+
nativeBinding = require('./dmc.android-arm64.node')
|
|
39
|
+
} else {
|
|
40
|
+
nativeBinding = require('@gentleduck/md-android-arm64')
|
|
41
|
+
}
|
|
42
|
+
} catch (e) {
|
|
43
|
+
loadError = e
|
|
44
|
+
}
|
|
45
|
+
break
|
|
46
|
+
case 'arm':
|
|
47
|
+
localFileExisted = existsSync(join(__dirname, 'dmc.android-arm-eabi.node'))
|
|
48
|
+
try {
|
|
49
|
+
if (localFileExisted) {
|
|
50
|
+
nativeBinding = require('./dmc.android-arm-eabi.node')
|
|
51
|
+
} else {
|
|
52
|
+
nativeBinding = require('@gentleduck/md-android-arm-eabi')
|
|
53
|
+
}
|
|
54
|
+
} catch (e) {
|
|
55
|
+
loadError = e
|
|
56
|
+
}
|
|
57
|
+
break
|
|
58
|
+
default:
|
|
59
|
+
throw new Error(`Unsupported architecture on Android ${arch}`)
|
|
60
|
+
}
|
|
61
|
+
break
|
|
62
|
+
case 'win32':
|
|
63
|
+
switch (arch) {
|
|
64
|
+
case 'x64':
|
|
65
|
+
localFileExisted = existsSync(
|
|
66
|
+
join(__dirname, 'dmc.win32-x64-msvc.node')
|
|
67
|
+
)
|
|
68
|
+
try {
|
|
69
|
+
if (localFileExisted) {
|
|
70
|
+
nativeBinding = require('./dmc.win32-x64-msvc.node')
|
|
71
|
+
} else {
|
|
72
|
+
nativeBinding = require('@gentleduck/md-win32-x64-msvc')
|
|
73
|
+
}
|
|
74
|
+
} catch (e) {
|
|
75
|
+
loadError = e
|
|
76
|
+
}
|
|
77
|
+
break
|
|
78
|
+
case 'ia32':
|
|
79
|
+
localFileExisted = existsSync(
|
|
80
|
+
join(__dirname, 'dmc.win32-ia32-msvc.node')
|
|
81
|
+
)
|
|
82
|
+
try {
|
|
83
|
+
if (localFileExisted) {
|
|
84
|
+
nativeBinding = require('./dmc.win32-ia32-msvc.node')
|
|
85
|
+
} else {
|
|
86
|
+
nativeBinding = require('@gentleduck/md-win32-ia32-msvc')
|
|
87
|
+
}
|
|
88
|
+
} catch (e) {
|
|
89
|
+
loadError = e
|
|
90
|
+
}
|
|
91
|
+
break
|
|
92
|
+
case 'arm64':
|
|
93
|
+
localFileExisted = existsSync(
|
|
94
|
+
join(__dirname, 'dmc.win32-arm64-msvc.node')
|
|
95
|
+
)
|
|
96
|
+
try {
|
|
97
|
+
if (localFileExisted) {
|
|
98
|
+
nativeBinding = require('./dmc.win32-arm64-msvc.node')
|
|
99
|
+
} else {
|
|
100
|
+
nativeBinding = require('@gentleduck/md-win32-arm64-msvc')
|
|
101
|
+
}
|
|
102
|
+
} catch (e) {
|
|
103
|
+
loadError = e
|
|
104
|
+
}
|
|
105
|
+
break
|
|
106
|
+
default:
|
|
107
|
+
throw new Error(`Unsupported architecture on Windows: ${arch}`)
|
|
108
|
+
}
|
|
109
|
+
break
|
|
110
|
+
case 'darwin':
|
|
111
|
+
localFileExisted = existsSync(join(__dirname, 'dmc.darwin-universal.node'))
|
|
112
|
+
try {
|
|
113
|
+
if (localFileExisted) {
|
|
114
|
+
nativeBinding = require('./dmc.darwin-universal.node')
|
|
115
|
+
} else {
|
|
116
|
+
nativeBinding = require('@gentleduck/md-darwin-universal')
|
|
117
|
+
}
|
|
118
|
+
break
|
|
119
|
+
} catch {}
|
|
120
|
+
switch (arch) {
|
|
121
|
+
case 'x64':
|
|
122
|
+
localFileExisted = existsSync(join(__dirname, 'dmc.darwin-x64.node'))
|
|
123
|
+
try {
|
|
124
|
+
if (localFileExisted) {
|
|
125
|
+
nativeBinding = require('./dmc.darwin-x64.node')
|
|
126
|
+
} else {
|
|
127
|
+
nativeBinding = require('@gentleduck/md-darwin-x64')
|
|
128
|
+
}
|
|
129
|
+
} catch (e) {
|
|
130
|
+
loadError = e
|
|
131
|
+
}
|
|
132
|
+
break
|
|
133
|
+
case 'arm64':
|
|
134
|
+
localFileExisted = existsSync(
|
|
135
|
+
join(__dirname, 'dmc.darwin-arm64.node')
|
|
136
|
+
)
|
|
137
|
+
try {
|
|
138
|
+
if (localFileExisted) {
|
|
139
|
+
nativeBinding = require('./dmc.darwin-arm64.node')
|
|
140
|
+
} else {
|
|
141
|
+
nativeBinding = require('@gentleduck/md-darwin-arm64')
|
|
142
|
+
}
|
|
143
|
+
} catch (e) {
|
|
144
|
+
loadError = e
|
|
145
|
+
}
|
|
146
|
+
break
|
|
147
|
+
default:
|
|
148
|
+
throw new Error(`Unsupported architecture on macOS: ${arch}`)
|
|
149
|
+
}
|
|
150
|
+
break
|
|
151
|
+
case 'freebsd':
|
|
152
|
+
if (arch !== 'x64') {
|
|
153
|
+
throw new Error(`Unsupported architecture on FreeBSD: ${arch}`)
|
|
154
|
+
}
|
|
155
|
+
localFileExisted = existsSync(join(__dirname, 'dmc.freebsd-x64.node'))
|
|
156
|
+
try {
|
|
157
|
+
if (localFileExisted) {
|
|
158
|
+
nativeBinding = require('./dmc.freebsd-x64.node')
|
|
159
|
+
} else {
|
|
160
|
+
nativeBinding = require('@gentleduck/md-freebsd-x64')
|
|
161
|
+
}
|
|
162
|
+
} catch (e) {
|
|
163
|
+
loadError = e
|
|
164
|
+
}
|
|
165
|
+
break
|
|
166
|
+
case 'linux':
|
|
167
|
+
switch (arch) {
|
|
168
|
+
case 'x64':
|
|
169
|
+
if (isMusl()) {
|
|
170
|
+
localFileExisted = existsSync(
|
|
171
|
+
join(__dirname, 'dmc.linux-x64-musl.node')
|
|
172
|
+
)
|
|
173
|
+
try {
|
|
174
|
+
if (localFileExisted) {
|
|
175
|
+
nativeBinding = require('./dmc.linux-x64-musl.node')
|
|
176
|
+
} else {
|
|
177
|
+
nativeBinding = require('@gentleduck/md-linux-x64-musl')
|
|
178
|
+
}
|
|
179
|
+
} catch (e) {
|
|
180
|
+
loadError = e
|
|
181
|
+
}
|
|
182
|
+
} else {
|
|
183
|
+
localFileExisted = existsSync(
|
|
184
|
+
join(__dirname, 'dmc.linux-x64-gnu.node')
|
|
185
|
+
)
|
|
186
|
+
try {
|
|
187
|
+
if (localFileExisted) {
|
|
188
|
+
nativeBinding = require('./dmc.linux-x64-gnu.node')
|
|
189
|
+
} else {
|
|
190
|
+
nativeBinding = require('@gentleduck/md-linux-x64-gnu')
|
|
191
|
+
}
|
|
192
|
+
} catch (e) {
|
|
193
|
+
loadError = e
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
break
|
|
197
|
+
case 'arm64':
|
|
198
|
+
if (isMusl()) {
|
|
199
|
+
localFileExisted = existsSync(
|
|
200
|
+
join(__dirname, 'dmc.linux-arm64-musl.node')
|
|
201
|
+
)
|
|
202
|
+
try {
|
|
203
|
+
if (localFileExisted) {
|
|
204
|
+
nativeBinding = require('./dmc.linux-arm64-musl.node')
|
|
205
|
+
} else {
|
|
206
|
+
nativeBinding = require('@gentleduck/md-linux-arm64-musl')
|
|
207
|
+
}
|
|
208
|
+
} catch (e) {
|
|
209
|
+
loadError = e
|
|
210
|
+
}
|
|
211
|
+
} else {
|
|
212
|
+
localFileExisted = existsSync(
|
|
213
|
+
join(__dirname, 'dmc.linux-arm64-gnu.node')
|
|
214
|
+
)
|
|
215
|
+
try {
|
|
216
|
+
if (localFileExisted) {
|
|
217
|
+
nativeBinding = require('./dmc.linux-arm64-gnu.node')
|
|
218
|
+
} else {
|
|
219
|
+
nativeBinding = require('@gentleduck/md-linux-arm64-gnu')
|
|
220
|
+
}
|
|
221
|
+
} catch (e) {
|
|
222
|
+
loadError = e
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
break
|
|
226
|
+
case 'arm':
|
|
227
|
+
if (isMusl()) {
|
|
228
|
+
localFileExisted = existsSync(
|
|
229
|
+
join(__dirname, 'dmc.linux-arm-musleabihf.node')
|
|
230
|
+
)
|
|
231
|
+
try {
|
|
232
|
+
if (localFileExisted) {
|
|
233
|
+
nativeBinding = require('./dmc.linux-arm-musleabihf.node')
|
|
234
|
+
} else {
|
|
235
|
+
nativeBinding = require('@gentleduck/md-linux-arm-musleabihf')
|
|
236
|
+
}
|
|
237
|
+
} catch (e) {
|
|
238
|
+
loadError = e
|
|
239
|
+
}
|
|
240
|
+
} else {
|
|
241
|
+
localFileExisted = existsSync(
|
|
242
|
+
join(__dirname, 'dmc.linux-arm-gnueabihf.node')
|
|
243
|
+
)
|
|
244
|
+
try {
|
|
245
|
+
if (localFileExisted) {
|
|
246
|
+
nativeBinding = require('./dmc.linux-arm-gnueabihf.node')
|
|
247
|
+
} else {
|
|
248
|
+
nativeBinding = require('@gentleduck/md-linux-arm-gnueabihf')
|
|
249
|
+
}
|
|
250
|
+
} catch (e) {
|
|
251
|
+
loadError = e
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
break
|
|
255
|
+
case 'riscv64':
|
|
256
|
+
if (isMusl()) {
|
|
257
|
+
localFileExisted = existsSync(
|
|
258
|
+
join(__dirname, 'dmc.linux-riscv64-musl.node')
|
|
259
|
+
)
|
|
260
|
+
try {
|
|
261
|
+
if (localFileExisted) {
|
|
262
|
+
nativeBinding = require('./dmc.linux-riscv64-musl.node')
|
|
263
|
+
} else {
|
|
264
|
+
nativeBinding = require('@gentleduck/md-linux-riscv64-musl')
|
|
265
|
+
}
|
|
266
|
+
} catch (e) {
|
|
267
|
+
loadError = e
|
|
268
|
+
}
|
|
269
|
+
} else {
|
|
270
|
+
localFileExisted = existsSync(
|
|
271
|
+
join(__dirname, 'dmc.linux-riscv64-gnu.node')
|
|
272
|
+
)
|
|
273
|
+
try {
|
|
274
|
+
if (localFileExisted) {
|
|
275
|
+
nativeBinding = require('./dmc.linux-riscv64-gnu.node')
|
|
276
|
+
} else {
|
|
277
|
+
nativeBinding = require('@gentleduck/md-linux-riscv64-gnu')
|
|
278
|
+
}
|
|
279
|
+
} catch (e) {
|
|
280
|
+
loadError = e
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
break
|
|
284
|
+
case 's390x':
|
|
285
|
+
localFileExisted = existsSync(
|
|
286
|
+
join(__dirname, 'dmc.linux-s390x-gnu.node')
|
|
287
|
+
)
|
|
288
|
+
try {
|
|
289
|
+
if (localFileExisted) {
|
|
290
|
+
nativeBinding = require('./dmc.linux-s390x-gnu.node')
|
|
291
|
+
} else {
|
|
292
|
+
nativeBinding = require('@gentleduck/md-linux-s390x-gnu')
|
|
293
|
+
}
|
|
294
|
+
} catch (e) {
|
|
295
|
+
loadError = e
|
|
296
|
+
}
|
|
297
|
+
break
|
|
298
|
+
default:
|
|
299
|
+
throw new Error(`Unsupported architecture on Linux: ${arch}`)
|
|
300
|
+
}
|
|
301
|
+
break
|
|
302
|
+
default:
|
|
303
|
+
throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (!nativeBinding) {
|
|
307
|
+
if (loadError) {
|
|
308
|
+
throw loadError
|
|
309
|
+
}
|
|
310
|
+
throw new Error(`Failed to load native binding`)
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const { compile, latexToHtml, compileMany, build } = nativeBinding
|
|
314
|
+
|
|
315
|
+
module.exports.compile = compile
|
|
316
|
+
module.exports.latexToHtml = latexToHtml
|
|
317
|
+
module.exports.compileMany = compileMany
|
|
318
|
+
module.exports.build = build
|
package/logo-dark.svg
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<svg width="1080" height="1080" viewBox="0 0 1080 1080" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
2
|
+
<rect width="1080" height="1080" fill="url(#pattern0_3323_8212)"/>
|
|
3
|
+
<defs>
|
|
4
|
+
<pattern id="pattern0_3323_8212" patternContentUnits="objectBoundingBox" width="1" height="1">
|
|
5
|
+
<use xlink:href="#image0_3323_8212" transform="scale(0.000925926)"/>
|
|
6
|
+
</pattern>
|
|
7
|
+
<image id="image0_3323_8212" width="1080" height="1080" preserveAspectRatio="none" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABDgAAAQ4CAYAAADsEGyPAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAADUJSURBVHgB7d2/b1/V+cDxw7dIMCB7axbMP2BvlAGzBYZEnZqhpp3IEIsJd4jUASWqoF0gHZJOdYZELOAOkTrFA4ip6UCVyd46ESY62VMz8dXzoQ6B/PKPc+/nPue8XpLlUFoqwc1H3Lef85znTp069V0BAAAASOz/CgAAAEByAgcAAACQnsABAAAApCdwAAAAAOkJHAAAAEB6AgcAAACQnsABAAAApCdwAAAAAOkJHAAAAEB6AgcAAACQnsABAAAApCdwAAAAAOkJHAAAAEB6AgcAAACQnsABAAAApCdwAAAAAOkJHAAAAEB6AgcAAACQnsABAAAApCdwAAAAAOkJHAAAAEB6AgcAAACQnsABAAAApCdwAAAAAOkJHAAAAEB6AgcAAACQnsABAAAApCdwAAAAAOkJHAAAAEB6AgcAAACQnsABAAAApCdwAAAAAOkJHAAAAEB6AgcAAACQnsABAAAApCdwAAAAAOkJHAAAAEB6AgcAAACQnsABAAAApCdwAAAAAOkJHAAAAEB6AgcAAACQnsABAAAApCdwAAAAAOkJHAAAAEB6AgcAAACQnsABAAAApCdwAAAAAOkJHAAAAEB6AgcAAACQnsABAAAApCdwAAAAAOkJHAAAAEB6AgcAAACQnsABAAAApCdwAAAAAOkJHAAAAEB6AgcAAACQnsABAAAApCdwAAAAAOkJHAAAAEB6AgcAAACQnsABAAAApCdwAAAAAOkJHAAAAEB6AgcAAACQnsABAAAApCdwAAAAAOkJHAAAAEB6AgcAAACQnsABAAAApCdwAAAAAOkJHAAAAEB6AgcAAACQnsABAAAApCdwAAAAAOkJHAAAAEB6AgcAAACQnsABAAAApCdwAAAAAOkJHAAAAEB6AgcAAACQnsABAAUAgOwEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9gQMAAABIT+AAAAAA0hM4AAAAgPQEDgAAACA9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AACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEhP4AAAAADSEzgAAACA9AQOAAAAID2BAwAAAEjv/wHL2txvR6WxjQAAAABJRU5ErkJggg=="/>
|
|
8
|
+
</defs>
|
|
9
|
+
</svg>
|
package/mod.d.ts
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import type { Plugin, Pluggable } from "unified";
|
|
2
|
+
export type { Plugin, Pluggable } from "unified";
|
|
3
|
+
/**
|
|
4
|
+
* Type-safe `[plugin, options]` tuple. The `options` argument is inferred
|
|
5
|
+
* from the plugin function's first parameter type, so misspelled or wrong-shape
|
|
6
|
+
* options surface as TS errors at config time.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* rehypePlugins: [
|
|
10
|
+
* rehypeSlug,
|
|
11
|
+
* definePlugin(rehypePrettyCode, { theme: { light, dark } }),
|
|
12
|
+
* definePlugin(rehypeAutolinkHeadings, { properties: {...} }),
|
|
13
|
+
* ]
|
|
14
|
+
*/
|
|
15
|
+
export declare function definePlugin<P extends Plugin>(plugin: P): P;
|
|
16
|
+
export declare function definePlugin<P extends Plugin<Params, any, any>, Params extends [any?, ...any[]] = P extends Plugin<infer X, any, any> ? X : never>(plugin: P, options: Params[0]): [P, Params[0]];
|
|
17
|
+
export interface TocItem {
|
|
18
|
+
title: string;
|
|
19
|
+
url: string;
|
|
20
|
+
items: TocItem[];
|
|
21
|
+
}
|
|
22
|
+
export interface Metadata {
|
|
23
|
+
readingTime: number;
|
|
24
|
+
wordCount: number;
|
|
25
|
+
}
|
|
26
|
+
export interface CompileOutput {
|
|
27
|
+
body: string;
|
|
28
|
+
content: string;
|
|
29
|
+
html: string;
|
|
30
|
+
excerpt: string;
|
|
31
|
+
metadata: Metadata;
|
|
32
|
+
toc: TocItem[];
|
|
33
|
+
frontmatter: unknown;
|
|
34
|
+
frontmatterRaw: string;
|
|
35
|
+
imports: string[];
|
|
36
|
+
exports: string[];
|
|
37
|
+
}
|
|
38
|
+
export type SchemaKind = "string" | "number" | "boolean" | "array" | "object" | "record" | "tuple" | "intersection" | "enum" | "literal" | "union" | "discriminatedUnion" | "optional" | "nullable" | "default" | "transform" | "refine" | "superRefine" | "coerce.string" | "coerce.number" | "coerce.boolean" | "coerce.date" | "raw" | "markdown" | "mdx" | "toc" | "metadata" | "excerpt" | "path" | "slug" | "unique" | "isodate" | "file" | "image";
|
|
39
|
+
export interface SchemaDescriptor {
|
|
40
|
+
kind: SchemaKind;
|
|
41
|
+
[field: string]: unknown;
|
|
42
|
+
}
|
|
43
|
+
export interface CollectionConfig<S = unknown> {
|
|
44
|
+
name?: string;
|
|
45
|
+
pattern: string | string[];
|
|
46
|
+
baseDir?: string;
|
|
47
|
+
single?: boolean;
|
|
48
|
+
schema?: SchemaBuilder<S> | SchemaDescriptor;
|
|
49
|
+
}
|
|
50
|
+
export interface OutputOptions {
|
|
51
|
+
data?: string;
|
|
52
|
+
assets?: string;
|
|
53
|
+
base?: string;
|
|
54
|
+
name?: string;
|
|
55
|
+
clean?: boolean;
|
|
56
|
+
format?: "esm" | "cjs";
|
|
57
|
+
/** Emit a per-record `html` field rendered by the native pipeline (no
|
|
58
|
+
* sidecar/JS plugins). Set to `false` (default) when you only want the
|
|
59
|
+
* MDX body / JSX tree and will render via React. */
|
|
60
|
+
html?: boolean;
|
|
61
|
+
}
|
|
62
|
+
export interface MarkdownOptions {
|
|
63
|
+
gfm?: boolean;
|
|
64
|
+
removeComments?: boolean;
|
|
65
|
+
copyLinkedFiles?: boolean;
|
|
66
|
+
remarkPlugins?: Pluggable[];
|
|
67
|
+
rehypePlugins?: Pluggable[];
|
|
68
|
+
/**
|
|
69
|
+
* Bypass the plugin gate for every plugin: every JS plugin runs in
|
|
70
|
+
* the sidecar, every native transformer is dropped.
|
|
71
|
+
*/
|
|
72
|
+
forceSidecar?: boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Per-plugin sidecar preference. Names listed here run in the
|
|
75
|
+
* sidecar; the matching native transformer is dropped from the
|
|
76
|
+
* pipeline. Recognised names:
|
|
77
|
+
* "remark-gfm", "remark-math", "remark-emoji",
|
|
78
|
+
* "rehype-pretty-code", "shiki",
|
|
79
|
+
* "rehype-katex", "rehype-mathjax",
|
|
80
|
+
* "rehype-slug", "rehype-autolink-headings"
|
|
81
|
+
*/
|
|
82
|
+
preferSidecar?: string[];
|
|
83
|
+
}
|
|
84
|
+
export interface MdxOptions extends MarkdownOptions {
|
|
85
|
+
outputFormat?: "function-body" | "module";
|
|
86
|
+
minify?: boolean;
|
|
87
|
+
}
|
|
88
|
+
export interface UserConfig {
|
|
89
|
+
root?: string;
|
|
90
|
+
strict?: boolean;
|
|
91
|
+
output?: OutputOptions;
|
|
92
|
+
collections: Record<string, CollectionConfig>;
|
|
93
|
+
loaders?: unknown[];
|
|
94
|
+
markdown?: MarkdownOptions;
|
|
95
|
+
mdx?: MdxOptions;
|
|
96
|
+
prepare?: (data: Record<string, unknown[]>, ctx: {
|
|
97
|
+
config: UserConfig;
|
|
98
|
+
}) => unknown;
|
|
99
|
+
complete?: (data: Record<string, unknown[]>, ctx: {
|
|
100
|
+
config: UserConfig;
|
|
101
|
+
}) => unknown;
|
|
102
|
+
}
|
|
103
|
+
export interface BuildCollectionReport {
|
|
104
|
+
name: string;
|
|
105
|
+
records: number;
|
|
106
|
+
outputPath: string;
|
|
107
|
+
}
|
|
108
|
+
export interface BuildErrorReport {
|
|
109
|
+
file: string;
|
|
110
|
+
message: string;
|
|
111
|
+
}
|
|
112
|
+
export interface BuildReport {
|
|
113
|
+
collections: BuildCollectionReport[];
|
|
114
|
+
errors: BuildErrorReport[];
|
|
115
|
+
}
|
|
116
|
+
export declare class SchemaBuilder<_T = unknown> {
|
|
117
|
+
[k: string]: unknown;
|
|
118
|
+
constructor(descriptor: SchemaDescriptor);
|
|
119
|
+
toJSON(): SchemaDescriptor;
|
|
120
|
+
optional(): SchemaBuilder;
|
|
121
|
+
nullable(): SchemaBuilder;
|
|
122
|
+
default(value: unknown): SchemaBuilder;
|
|
123
|
+
min(n: number): SchemaBuilder;
|
|
124
|
+
max(n: number): SchemaBuilder;
|
|
125
|
+
length(n: number): SchemaBuilder;
|
|
126
|
+
regex(p: string): SchemaBuilder;
|
|
127
|
+
int(): SchemaBuilder;
|
|
128
|
+
by(bucket: string): SchemaBuilder;
|
|
129
|
+
reserved(list: string[]): SchemaBuilder;
|
|
130
|
+
passthrough(): SchemaBuilder;
|
|
131
|
+
transform(fn: (v: unknown) => unknown): SchemaBuilder;
|
|
132
|
+
refine(fn: (v: unknown) => boolean, message?: string): SchemaBuilder;
|
|
133
|
+
}
|
|
134
|
+
export interface SBuilders {
|
|
135
|
+
string(): SchemaBuilder<string>;
|
|
136
|
+
number(): SchemaBuilder<number>;
|
|
137
|
+
boolean(): SchemaBuilder<boolean>;
|
|
138
|
+
array<I>(item: SchemaBuilder<I>): SchemaBuilder<I[]>;
|
|
139
|
+
object<S extends Record<string, SchemaBuilder>>(fields: S): SchemaBuilder;
|
|
140
|
+
record<V>(value: SchemaBuilder<V>): SchemaBuilder<Record<string, V>>;
|
|
141
|
+
tuple(items: SchemaBuilder[]): SchemaBuilder<unknown[]>;
|
|
142
|
+
intersection<A, B>(a: SchemaBuilder<A>, b: SchemaBuilder<B>): SchemaBuilder<A & B>;
|
|
143
|
+
enum<T>(variants: T[]): SchemaBuilder<T>;
|
|
144
|
+
literal<T>(value: T): SchemaBuilder<T>;
|
|
145
|
+
union<T>(variants: SchemaBuilder<T>[]): SchemaBuilder<T>;
|
|
146
|
+
discriminatedUnion<T>(discriminator: string, variants: SchemaBuilder<T>[]): SchemaBuilder<T>;
|
|
147
|
+
coerce: {
|
|
148
|
+
string(): SchemaBuilder<string>;
|
|
149
|
+
number(): SchemaBuilder<number>;
|
|
150
|
+
boolean(): SchemaBuilder<boolean>;
|
|
151
|
+
date(): SchemaBuilder<string>;
|
|
152
|
+
};
|
|
153
|
+
raw(): SchemaBuilder<string>;
|
|
154
|
+
markdown(): SchemaBuilder<string>;
|
|
155
|
+
mdx(): SchemaBuilder<string>;
|
|
156
|
+
toc(): SchemaBuilder<TocItem[]>;
|
|
157
|
+
metadata(): SchemaBuilder<Metadata>;
|
|
158
|
+
excerpt(opts?: {
|
|
159
|
+
length?: number;
|
|
160
|
+
}): SchemaBuilder<string>;
|
|
161
|
+
path(opts?: {
|
|
162
|
+
removeIndex?: boolean;
|
|
163
|
+
}): SchemaBuilder<string>;
|
|
164
|
+
slug(bucket?: string, reserved?: string[]): SchemaBuilder<string>;
|
|
165
|
+
unique(bucket?: string): SchemaBuilder<string>;
|
|
166
|
+
isodate(): SchemaBuilder<string>;
|
|
167
|
+
file(opts?: {
|
|
168
|
+
allowNonRelativePath?: boolean;
|
|
169
|
+
}): SchemaBuilder<string>;
|
|
170
|
+
image(opts?: {
|
|
171
|
+
absoluteRoot?: string;
|
|
172
|
+
}): SchemaBuilder<{
|
|
173
|
+
src: string;
|
|
174
|
+
width: number;
|
|
175
|
+
height: number;
|
|
176
|
+
}>;
|
|
177
|
+
}
|
|
178
|
+
export declare const s: SBuilders;
|
|
179
|
+
export declare const defineConfig: (config: UserConfig) => UserConfig;
|
|
180
|
+
export declare const defineCollection: <S>(c: CollectionConfig<S>) => CollectionConfig<S>;
|
|
181
|
+
export declare const defineLoader: <L>(l: L) => L;
|
|
182
|
+
export declare const defineSchema: <S>(sch: S) => S;
|
|
183
|
+
export interface CustomLoader<T = unknown> {
|
|
184
|
+
test: RegExp | string;
|
|
185
|
+
load: (file: {
|
|
186
|
+
path: string;
|
|
187
|
+
value: string;
|
|
188
|
+
}) => T | Promise<T>;
|
|
189
|
+
}
|
|
190
|
+
export declare function applyLoaders<T>(loaders: CustomLoader<T>[] | undefined, filePath: string, content: string): Promise<T | null>;
|
|
191
|
+
export declare function compile(source: string): CompileOutput;
|
|
192
|
+
export declare function compileMany(sources: string[]): CompileOutput[];
|
|
193
|
+
export declare function build(input: UserConfig): Promise<BuildReport>;
|
|
194
|
+
declare const _default: {
|
|
195
|
+
compile: typeof compile;
|
|
196
|
+
compileMany: typeof compileMany;
|
|
197
|
+
build: typeof build;
|
|
198
|
+
defineConfig: (config: UserConfig) => UserConfig;
|
|
199
|
+
defineCollection: <S>(c: CollectionConfig<S>) => CollectionConfig<S>;
|
|
200
|
+
defineLoader: <L>(l: L) => L;
|
|
201
|
+
defineSchema: <S>(sch: S) => S;
|
|
202
|
+
applyLoaders: typeof applyLoaders;
|
|
203
|
+
s: SBuilders;
|
|
204
|
+
SchemaBuilder: typeof SchemaBuilder;
|
|
205
|
+
};
|
|
206
|
+
export default _default;
|
package/mod.js
ADDED
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { readFileSync, writeFileSync, unlinkSync, readdirSync, statSync, existsSync, } from "node:fs";
|
|
3
|
+
import { join, relative, dirname } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
export function definePlugin(plugin, options) {
|
|
6
|
+
return options === undefined ? plugin : [plugin, options];
|
|
7
|
+
}
|
|
8
|
+
const require = createRequire(import.meta.url);
|
|
9
|
+
const native = require("./index.js");
|
|
10
|
+
// Resolve sidecar entry relative to @gentleduck/md package + propagate via env
|
|
11
|
+
function resolveSidecar() {
|
|
12
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
13
|
+
const candidates = [
|
|
14
|
+
join(here, "..", "dmc-sidecar", "index.mjs"),
|
|
15
|
+
join(here, "..", "..", "dmc-sidecar", "index.mjs"),
|
|
16
|
+
join(here, "..", "node_modules", "@duck", "md-sidecar", "index.mjs"),
|
|
17
|
+
];
|
|
18
|
+
for (const p of candidates)
|
|
19
|
+
if (existsSync(p))
|
|
20
|
+
return p;
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
const SIDECAR_PATH = resolveSidecar();
|
|
24
|
+
if (SIDECAR_PATH && !process.env.dmc_SIDECAR) {
|
|
25
|
+
process.env.dmc_SIDECAR = SIDECAR_PATH;
|
|
26
|
+
}
|
|
27
|
+
const cbRegistry = new Map();
|
|
28
|
+
let cbId = 0;
|
|
29
|
+
const registerCallback = (fn) => {
|
|
30
|
+
const id = ++cbId;
|
|
31
|
+
cbRegistry.set(id, fn);
|
|
32
|
+
return id;
|
|
33
|
+
};
|
|
34
|
+
export class SchemaBuilder {
|
|
35
|
+
constructor(descriptor) {
|
|
36
|
+
Object.assign(this, descriptor);
|
|
37
|
+
}
|
|
38
|
+
toJSON() {
|
|
39
|
+
const out = { kind: this.kind };
|
|
40
|
+
for (const k of Object.keys(this))
|
|
41
|
+
out[k] = this[k];
|
|
42
|
+
return out;
|
|
43
|
+
}
|
|
44
|
+
optional() {
|
|
45
|
+
return new SchemaBuilder({ kind: "optional", inner: this.toJSON() });
|
|
46
|
+
}
|
|
47
|
+
nullable() {
|
|
48
|
+
return new SchemaBuilder({ kind: "nullable", inner: this.toJSON() });
|
|
49
|
+
}
|
|
50
|
+
default(value) {
|
|
51
|
+
return new SchemaBuilder({
|
|
52
|
+
kind: "default",
|
|
53
|
+
inner: this.toJSON(),
|
|
54
|
+
fallback: value,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
min(n) {
|
|
58
|
+
return new SchemaBuilder({ ...this.toJSON(), min: n });
|
|
59
|
+
}
|
|
60
|
+
max(n) {
|
|
61
|
+
return new SchemaBuilder({ ...this.toJSON(), max: n });
|
|
62
|
+
}
|
|
63
|
+
length(n) {
|
|
64
|
+
return new SchemaBuilder({ ...this.toJSON(), length: n });
|
|
65
|
+
}
|
|
66
|
+
regex(p) {
|
|
67
|
+
return new SchemaBuilder({ ...this.toJSON(), regex: p });
|
|
68
|
+
}
|
|
69
|
+
int() {
|
|
70
|
+
return new SchemaBuilder({ ...this.toJSON(), int: true });
|
|
71
|
+
}
|
|
72
|
+
by(bucket) {
|
|
73
|
+
return new SchemaBuilder({ ...this.toJSON(), bucket });
|
|
74
|
+
}
|
|
75
|
+
reserved(list) {
|
|
76
|
+
return new SchemaBuilder({ ...this.toJSON(), reserved: list });
|
|
77
|
+
}
|
|
78
|
+
passthrough() {
|
|
79
|
+
return new SchemaBuilder({ ...this.toJSON(), passthrough: true });
|
|
80
|
+
}
|
|
81
|
+
transform(fn) {
|
|
82
|
+
return new SchemaBuilder({
|
|
83
|
+
kind: "transform",
|
|
84
|
+
inner: this.toJSON(),
|
|
85
|
+
__callbackId: registerCallback(fn),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
refine(fn, message) {
|
|
89
|
+
return new SchemaBuilder({
|
|
90
|
+
kind: "refine",
|
|
91
|
+
inner: this.toJSON(),
|
|
92
|
+
__callbackId: registerCallback(fn),
|
|
93
|
+
__message: message,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
const sb = (d) => new SchemaBuilder(d);
|
|
98
|
+
export const s = {
|
|
99
|
+
string: () => sb({ kind: "string" }),
|
|
100
|
+
number: () => sb({ kind: "number" }),
|
|
101
|
+
boolean: () => sb({ kind: "boolean" }),
|
|
102
|
+
array: (item) => sb({ kind: "array", item: item.toJSON() }),
|
|
103
|
+
object: (fields) => sb({
|
|
104
|
+
kind: "object",
|
|
105
|
+
fields: Object.fromEntries(Object.entries(fields).map(([k, v]) => [
|
|
106
|
+
k,
|
|
107
|
+
v.toJSON(),
|
|
108
|
+
])),
|
|
109
|
+
}),
|
|
110
|
+
record: (value) => sb({ kind: "record", value: value.toJSON() }),
|
|
111
|
+
tuple: (items) => sb({
|
|
112
|
+
kind: "tuple",
|
|
113
|
+
items: items.map((v) => v.toJSON()),
|
|
114
|
+
}),
|
|
115
|
+
intersection: (a, b) => sb({
|
|
116
|
+
kind: "intersection",
|
|
117
|
+
left: a.toJSON(),
|
|
118
|
+
right: b.toJSON(),
|
|
119
|
+
}),
|
|
120
|
+
enum: (variants) => sb({ kind: "enum", variants }),
|
|
121
|
+
literal: (expected) => sb({ kind: "literal", expected }),
|
|
122
|
+
union: (variants) => sb({
|
|
123
|
+
kind: "union",
|
|
124
|
+
variants: variants.map((v) => v.toJSON()),
|
|
125
|
+
}),
|
|
126
|
+
discriminatedUnion: (discriminator, variants) => sb({
|
|
127
|
+
kind: "discriminatedUnion",
|
|
128
|
+
discriminator,
|
|
129
|
+
variants: variants.map((v) => v.toJSON()),
|
|
130
|
+
}),
|
|
131
|
+
coerce: {
|
|
132
|
+
string: () => sb({ kind: "coerce.string" }),
|
|
133
|
+
number: () => sb({ kind: "coerce.number" }),
|
|
134
|
+
boolean: () => sb({ kind: "coerce.boolean" }),
|
|
135
|
+
date: () => sb({ kind: "coerce.date" }),
|
|
136
|
+
},
|
|
137
|
+
raw: () => sb({ kind: "raw" }),
|
|
138
|
+
markdown: () => sb({ kind: "markdown" }),
|
|
139
|
+
mdx: () => sb({ kind: "mdx" }),
|
|
140
|
+
toc: () => sb({ kind: "toc" }),
|
|
141
|
+
metadata: () => sb({ kind: "metadata" }),
|
|
142
|
+
excerpt: (opts = {}) => sb({ kind: "excerpt", ...opts }),
|
|
143
|
+
path: (opts = {}) => sb({ kind: "path", ...opts }),
|
|
144
|
+
slug: (bucket, reserved) => sb({ kind: "slug", bucket, reserved }),
|
|
145
|
+
unique: (bucket) => sb({ kind: "unique", bucket }),
|
|
146
|
+
isodate: () => sb({ kind: "isodate" }),
|
|
147
|
+
file: (opts = {}) => sb({ kind: "file", ...opts }),
|
|
148
|
+
image: (opts = {}) => sb({ kind: "image", ...opts }),
|
|
149
|
+
};
|
|
150
|
+
export const defineConfig = (config) => config;
|
|
151
|
+
export const defineCollection = (c) => c;
|
|
152
|
+
export const defineLoader = (l) => l;
|
|
153
|
+
export const defineSchema = (sch) => sch;
|
|
154
|
+
export async function applyLoaders(loaders, filePath, content) {
|
|
155
|
+
if (!loaders || loaders.length === 0)
|
|
156
|
+
return null;
|
|
157
|
+
for (const loader of loaders) {
|
|
158
|
+
const re = loader.test instanceof RegExp ? loader.test : new RegExp(loader.test);
|
|
159
|
+
if (re.test(filePath)) {
|
|
160
|
+
return await loader.load({ path: filePath, value: content });
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
function collectCallbacks(descriptor, base = []) {
|
|
166
|
+
if (!descriptor || typeof descriptor !== "object")
|
|
167
|
+
return [];
|
|
168
|
+
const found = [];
|
|
169
|
+
if (descriptor.kind === "transform" &&
|
|
170
|
+
typeof descriptor.__callbackId === "number") {
|
|
171
|
+
const fn = cbRegistry.get(descriptor.__callbackId);
|
|
172
|
+
if (fn)
|
|
173
|
+
found.push({ path: [...base], kind: "transform", fn });
|
|
174
|
+
}
|
|
175
|
+
if (descriptor.kind === "refine" &&
|
|
176
|
+
typeof descriptor.__callbackId === "number") {
|
|
177
|
+
const fn = cbRegistry.get(descriptor.__callbackId);
|
|
178
|
+
if (fn)
|
|
179
|
+
found.push({
|
|
180
|
+
path: [...base],
|
|
181
|
+
kind: "refine",
|
|
182
|
+
fn,
|
|
183
|
+
message: descriptor.__message,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
if (descriptor.inner)
|
|
187
|
+
found.push(...collectCallbacks(descriptor.inner, base));
|
|
188
|
+
if (descriptor.kind === "object" && descriptor.fields) {
|
|
189
|
+
for (const [k, v] of Object.entries(descriptor.fields)) {
|
|
190
|
+
found.push(...collectCallbacks(v, [...base, k]));
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (descriptor.kind === "array" && descriptor.item) {
|
|
194
|
+
found.push(...collectCallbacks(descriptor.item, [...base, "*"]));
|
|
195
|
+
}
|
|
196
|
+
return found;
|
|
197
|
+
}
|
|
198
|
+
function walkPath(obj, path) {
|
|
199
|
+
if (path.length === 0)
|
|
200
|
+
return [];
|
|
201
|
+
if (path[0] === "*") {
|
|
202
|
+
if (!Array.isArray(obj))
|
|
203
|
+
return [];
|
|
204
|
+
return obj.flatMap((_, i) => walkPath(obj[i], path.slice(1)));
|
|
205
|
+
}
|
|
206
|
+
const [key, ...rest] = path;
|
|
207
|
+
if (obj == null ||
|
|
208
|
+
typeof obj !== "object" ||
|
|
209
|
+
!(key in obj))
|
|
210
|
+
return [];
|
|
211
|
+
if (rest.length === 0)
|
|
212
|
+
return [{ parent: obj, key }];
|
|
213
|
+
return walkPath(obj[key], rest);
|
|
214
|
+
}
|
|
215
|
+
function applyCallbacks(record, cbs, errors, file) {
|
|
216
|
+
for (const cb of cbs) {
|
|
217
|
+
for (const { parent, key } of walkPath(record, cb.path)) {
|
|
218
|
+
const v = parent[key];
|
|
219
|
+
if (cb.kind === "transform") {
|
|
220
|
+
try {
|
|
221
|
+
parent[key] = cb.fn(v);
|
|
222
|
+
}
|
|
223
|
+
catch (e) {
|
|
224
|
+
errors.push({
|
|
225
|
+
file,
|
|
226
|
+
message: `${cb.path.join(".")}: transform threw: ${e.message ?? e}`,
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
let ok = false;
|
|
232
|
+
try {
|
|
233
|
+
ok = !!cb.fn(v);
|
|
234
|
+
}
|
|
235
|
+
catch (e) {
|
|
236
|
+
errors.push({
|
|
237
|
+
file,
|
|
238
|
+
message: `${cb.path.join(".")}: refine threw: ${e.message ?? e}`,
|
|
239
|
+
});
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
if (!ok)
|
|
243
|
+
errors.push({
|
|
244
|
+
file,
|
|
245
|
+
message: `${cb.path.join(".")}: ${cb.message ?? "failed refinement"}`,
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
function adaptToBuildInput(input) {
|
|
252
|
+
if ("outputDir" in input && Array.isArray(input.collections))
|
|
253
|
+
return input;
|
|
254
|
+
const cfg = input;
|
|
255
|
+
const root = cfg.root ?? ".";
|
|
256
|
+
const outputDir = cfg.output?.data ?? ".gentleduck";
|
|
257
|
+
const collections = Object.entries(cfg.collections ?? {}).map(([key, c]) => ({
|
|
258
|
+
name: c.name ?? key,
|
|
259
|
+
pattern: Array.isArray(c.pattern) ? c.pattern[0] : c.pattern,
|
|
260
|
+
baseDir: c.baseDir ?? root,
|
|
261
|
+
schema: c.schema instanceof SchemaBuilder
|
|
262
|
+
? c.schema.toJSON()
|
|
263
|
+
: c.schema,
|
|
264
|
+
single: c.single,
|
|
265
|
+
}));
|
|
266
|
+
return {
|
|
267
|
+
outputDir,
|
|
268
|
+
collections,
|
|
269
|
+
root,
|
|
270
|
+
strict: cfg.strict,
|
|
271
|
+
clean: cfg.output?.clean,
|
|
272
|
+
outputAssets: cfg.output?.assets,
|
|
273
|
+
outputBase: cfg.output?.base,
|
|
274
|
+
outputName: cfg.output?.name,
|
|
275
|
+
outputFormat: cfg.output?.format,
|
|
276
|
+
markdownRemarkPlugins: cfg.markdown?.remarkPlugins,
|
|
277
|
+
markdownRehypePlugins: cfg.markdown?.rehypePlugins,
|
|
278
|
+
mdxRemarkPlugins: cfg.mdx?.remarkPlugins,
|
|
279
|
+
mdxRehypePlugins: cfg.mdx?.rehypePlugins,
|
|
280
|
+
copyLinkedFiles: cfg.markdown?.copyLinkedFiles ?? cfg.mdx?.copyLinkedFiles,
|
|
281
|
+
mdxOutputFormat: cfg.mdx?.outputFormat,
|
|
282
|
+
mdxMinify: cfg.mdx?.minify,
|
|
283
|
+
markdownGfm: cfg.markdown?.gfm,
|
|
284
|
+
includeHtml: cfg.output?.html,
|
|
285
|
+
forceSidecar: cfg.markdown?.forceSidecar ?? cfg.mdx?.forceSidecar,
|
|
286
|
+
preferSidecar: cfg.markdown?.preferSidecar ?? cfg.mdx?.preferSidecar,
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
export function compile(source) {
|
|
290
|
+
return native.compile(source);
|
|
291
|
+
}
|
|
292
|
+
export function compileMany(sources) {
|
|
293
|
+
return native.compileMany(sources);
|
|
294
|
+
}
|
|
295
|
+
async function processWithUnified(markdown, remarkPlugins, rehypePlugins) {
|
|
296
|
+
const { unified } = await import("unified");
|
|
297
|
+
const { default: remarkParse } = await import("remark-parse");
|
|
298
|
+
const { default: remarkRehype } = await import("remark-rehype");
|
|
299
|
+
const { default: rehypeRaw } = await import("rehype-raw");
|
|
300
|
+
const { default: rehypeStringify } = await import("rehype-stringify");
|
|
301
|
+
// unified's `.use([fn, opts])` interprets the array as a list of plugins
|
|
302
|
+
// (not a [plugin, opts] tuple). To pass options correctly we must call
|
|
303
|
+
// `.use(fn, opts)` w/ two args. Unwrap each Pluggable shape here.
|
|
304
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
305
|
+
const apply = (proc, p) => {
|
|
306
|
+
if (typeof p === "function")
|
|
307
|
+
return proc.use(p);
|
|
308
|
+
if (Array.isArray(p))
|
|
309
|
+
return proc.use(p[0], p[1]);
|
|
310
|
+
return proc.use(p);
|
|
311
|
+
};
|
|
312
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
313
|
+
let proc = unified().use(remarkParse);
|
|
314
|
+
for (const p of remarkPlugins)
|
|
315
|
+
proc = apply(proc, p);
|
|
316
|
+
proc = proc.use(remarkRehype, { allowDangerousHtml: true }).use(rehypeRaw);
|
|
317
|
+
for (const p of rehypePlugins)
|
|
318
|
+
proc = apply(proc, p);
|
|
319
|
+
proc = proc.use(rehypeStringify, { allowDangerousHtml: true });
|
|
320
|
+
const file = await proc.process(markdown);
|
|
321
|
+
return String(file);
|
|
322
|
+
}
|
|
323
|
+
function walkDir(dir) {
|
|
324
|
+
const out = [];
|
|
325
|
+
try {
|
|
326
|
+
for (const name of readdirSync(dir)) {
|
|
327
|
+
const full = join(dir, name);
|
|
328
|
+
const st = statSync(full);
|
|
329
|
+
if (st.isDirectory())
|
|
330
|
+
out.push(...walkDir(full));
|
|
331
|
+
else
|
|
332
|
+
out.push(full);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
catch { }
|
|
336
|
+
return out;
|
|
337
|
+
}
|
|
338
|
+
async function applyCustomLoaders(input, report) {
|
|
339
|
+
const extras = new Map();
|
|
340
|
+
const loaders = input.loaders ?? [];
|
|
341
|
+
if (loaders.length === 0)
|
|
342
|
+
return { extras };
|
|
343
|
+
const root = input.root ?? ".";
|
|
344
|
+
for (const [key, c] of Object.entries(input.collections)) {
|
|
345
|
+
const baseDir = c.baseDir ?? root;
|
|
346
|
+
const files = walkDir(baseDir);
|
|
347
|
+
const matched = [];
|
|
348
|
+
const matchedPaths = new Set();
|
|
349
|
+
for (const file of files) {
|
|
350
|
+
const rel = relative(baseDir, file);
|
|
351
|
+
for (const loader of loaders) {
|
|
352
|
+
const re = loader.test instanceof RegExp ? loader.test : new RegExp(loader.test);
|
|
353
|
+
if (re.test(rel) || re.test(file)) {
|
|
354
|
+
const content = readFileSync(file, "utf8");
|
|
355
|
+
const data = await loader.load({ path: file, value: content });
|
|
356
|
+
if (data && typeof data === "object") {
|
|
357
|
+
const record = { ...data, sourceFilePath: file };
|
|
358
|
+
matched.push(record);
|
|
359
|
+
matchedPaths.add(file);
|
|
360
|
+
}
|
|
361
|
+
break;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
if (matched.length > 0) {
|
|
366
|
+
const name = c.name ?? key;
|
|
367
|
+
extras.set(name, matched);
|
|
368
|
+
const target = report.collections.find((rc) => rc.name === name);
|
|
369
|
+
if (target) {
|
|
370
|
+
const existing = JSON.parse(readFileSync(target.outputPath, "utf8"));
|
|
371
|
+
const filtered = existing.filter((r) => !matchedPaths.has(r?.sourceFilePath ?? ""));
|
|
372
|
+
const merged = [...filtered, ...matched];
|
|
373
|
+
writeFileSync(target.outputPath, JSON.stringify(merged, null, 2));
|
|
374
|
+
target.records = merged.length;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
return { extras };
|
|
379
|
+
}
|
|
380
|
+
export async function build(input) {
|
|
381
|
+
const collectionCallbacks = new Map();
|
|
382
|
+
if (input?.collections && !Array.isArray(input.collections)) {
|
|
383
|
+
for (const [key, c] of Object.entries(input.collections)) {
|
|
384
|
+
if (c.schema) {
|
|
385
|
+
const desc = c.schema instanceof SchemaBuilder
|
|
386
|
+
? c.schema.toJSON()
|
|
387
|
+
: c.schema;
|
|
388
|
+
const cbs = collectCallbacks(desc);
|
|
389
|
+
if (cbs.length)
|
|
390
|
+
collectionCallbacks.set(c.name ?? key, cbs);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
// Strip JS plugin function refs from the napi input - they can't cross
|
|
395
|
+
// the FFI boundary. The in-process post-pass below applies them.
|
|
396
|
+
const stripped = {
|
|
397
|
+
...input,
|
|
398
|
+
markdown: input.markdown
|
|
399
|
+
? {
|
|
400
|
+
...input.markdown,
|
|
401
|
+
remarkPlugins: undefined,
|
|
402
|
+
rehypePlugins: undefined,
|
|
403
|
+
}
|
|
404
|
+
: undefined,
|
|
405
|
+
mdx: input.mdx
|
|
406
|
+
? { ...input.mdx, remarkPlugins: undefined, rehypePlugins: undefined }
|
|
407
|
+
: undefined,
|
|
408
|
+
};
|
|
409
|
+
const report = native.build(adaptToBuildInput(stripped));
|
|
410
|
+
await applyCustomLoaders(input, report);
|
|
411
|
+
// In-process unified pipeline - type-safe plugin refs run here.
|
|
412
|
+
const remark = [
|
|
413
|
+
...(input.markdown?.remarkPlugins ?? []),
|
|
414
|
+
...(input.mdx?.remarkPlugins ?? []),
|
|
415
|
+
];
|
|
416
|
+
const rehype = [
|
|
417
|
+
...(input.markdown?.rehypePlugins ?? []),
|
|
418
|
+
...(input.mdx?.rehypePlugins ?? []),
|
|
419
|
+
];
|
|
420
|
+
if (remark.length || rehype.length) {
|
|
421
|
+
for (const c of report.collections) {
|
|
422
|
+
const records = JSON.parse(readFileSync(c.outputPath, "utf8"));
|
|
423
|
+
for (const r of records) {
|
|
424
|
+
const md = r.content ?? "";
|
|
425
|
+
try {
|
|
426
|
+
r.html = await processWithUnified(md, remark, rehype);
|
|
427
|
+
}
|
|
428
|
+
catch (e) {
|
|
429
|
+
report.errors.push({
|
|
430
|
+
file: r.sourceFilePath ?? c.outputPath,
|
|
431
|
+
message: `unified pipeline: ${e.message ?? e}`,
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
writeFileSync(c.outputPath, JSON.stringify(records, null, 2));
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
const needPostprocess = collectionCallbacks.size > 0 || input.prepare || input.complete;
|
|
439
|
+
if (!needPostprocess)
|
|
440
|
+
return report;
|
|
441
|
+
const data = {};
|
|
442
|
+
for (const c of report.collections) {
|
|
443
|
+
data[c.name] = JSON.parse(readFileSync(c.outputPath, "utf8"));
|
|
444
|
+
}
|
|
445
|
+
for (const c of report.collections) {
|
|
446
|
+
const cbs = collectionCallbacks.get(c.name);
|
|
447
|
+
if (!cbs)
|
|
448
|
+
continue;
|
|
449
|
+
const records = Array.isArray(data[c.name]) ? data[c.name] : [data[c.name]];
|
|
450
|
+
for (const record of records) {
|
|
451
|
+
applyCallbacks(record, cbs, report.errors, c.outputPath);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
if (input.prepare) {
|
|
455
|
+
const ret = await input.prepare(data, { config: input });
|
|
456
|
+
if (ret === false) {
|
|
457
|
+
for (const c of report.collections)
|
|
458
|
+
try {
|
|
459
|
+
unlinkSync(c.outputPath);
|
|
460
|
+
}
|
|
461
|
+
catch { }
|
|
462
|
+
return report;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
for (const c of report.collections) {
|
|
466
|
+
writeFileSync(c.outputPath, JSON.stringify(data[c.name], null, 2));
|
|
467
|
+
}
|
|
468
|
+
if (input.complete)
|
|
469
|
+
await input.complete(data, { config: input });
|
|
470
|
+
return report;
|
|
471
|
+
}
|
|
472
|
+
export default {
|
|
473
|
+
compile,
|
|
474
|
+
compileMany,
|
|
475
|
+
build,
|
|
476
|
+
defineConfig,
|
|
477
|
+
defineCollection,
|
|
478
|
+
defineLoader,
|
|
479
|
+
defineSchema,
|
|
480
|
+
applyLoaders,
|
|
481
|
+
s,
|
|
482
|
+
SchemaBuilder,
|
|
483
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@gentleduck/md",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Native Rust MDX compiler with a velite-shaped TypeScript API",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "gentleduck",
|
|
7
|
+
"homepage": "https://github.com/gentleeduck/duck-mc#readme",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/gentleeduck/duck-mc.git",
|
|
11
|
+
"directory": "dmc-napi"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/gentleeduck/duck-mc/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"mdx",
|
|
18
|
+
"markdown",
|
|
19
|
+
"compiler",
|
|
20
|
+
"velite",
|
|
21
|
+
"rust",
|
|
22
|
+
"napi",
|
|
23
|
+
"shiki",
|
|
24
|
+
"syntect",
|
|
25
|
+
"katex"
|
|
26
|
+
],
|
|
27
|
+
"type": "module",
|
|
28
|
+
"main": "mod.js",
|
|
29
|
+
"types": "mod.d.ts",
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./mod.d.ts",
|
|
33
|
+
"default": "./mod.js"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"mod.js",
|
|
38
|
+
"mod.d.ts",
|
|
39
|
+
"index.js",
|
|
40
|
+
"index.d.ts",
|
|
41
|
+
"*.node",
|
|
42
|
+
"README.md",
|
|
43
|
+
"logo-dark.svg"
|
|
44
|
+
],
|
|
45
|
+
"napi": {
|
|
46
|
+
"name": "dmc",
|
|
47
|
+
"triples": {
|
|
48
|
+
"defaults": true,
|
|
49
|
+
"additional": []
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"unified": "^11",
|
|
54
|
+
"remark-parse": "^11",
|
|
55
|
+
"remark-rehype": "^11",
|
|
56
|
+
"rehype-raw": "^7",
|
|
57
|
+
"rehype-stringify": "^10"
|
|
58
|
+
},
|
|
59
|
+
"devDependencies": {
|
|
60
|
+
"@napi-rs/cli": "^2.18.4",
|
|
61
|
+
"@types/node": "^25",
|
|
62
|
+
"@types/unist": "^3",
|
|
63
|
+
"typescript": "^6"
|
|
64
|
+
},
|
|
65
|
+
"scripts": {
|
|
66
|
+
"build": "napi build --platform --release",
|
|
67
|
+
"build:debug": "napi build --platform"
|
|
68
|
+
}
|
|
69
|
+
}
|