safe-mdx 1.7.0 → 1.9.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/README.md +56 -0
- package/dist/esm-parser.test.js +5 -0
- package/dist/esm-parser.test.js.map +1 -1
- package/dist/html/html-and-md.test.js +14 -41
- package/dist/html/html-and-md.test.js.map +1 -1
- package/dist/html/html-to-mdx-ast.d.ts +26 -1
- package/dist/html/html-to-mdx-ast.d.ts.map +1 -1
- package/dist/html/html-to-mdx-ast.js +40 -0
- package/dist/html/html-to-mdx-ast.js.map +1 -1
- package/dist/incremental-parse.d.ts +41 -0
- package/dist/incremental-parse.d.ts.map +1 -0
- package/dist/incremental-parse.js +139 -0
- package/dist/incremental-parse.js.map +1 -0
- package/dist/incremental-parse.test.d.ts +2 -0
- package/dist/incremental-parse.test.d.ts.map +1 -0
- package/dist/incremental-parse.test.js +299 -0
- package/dist/incremental-parse.test.js.map +1 -0
- package/dist/markdown-html.test.d.ts +2 -0
- package/dist/markdown-html.test.d.ts.map +1 -0
- package/dist/markdown-html.test.js +129 -0
- package/dist/markdown-html.test.js.map +1 -0
- package/dist/markdown.d.ts +3 -0
- package/dist/markdown.d.ts.map +1 -0
- package/dist/markdown.js +4 -0
- package/dist/markdown.js.map +1 -0
- package/dist/parse.d.ts +9 -2
- package/dist/parse.d.ts.map +1 -1
- package/dist/parse.js +34 -20
- package/dist/parse.js.map +1 -1
- package/dist/safe-mdx.d.ts.map +1 -1
- package/dist/safe-mdx.js +6 -24
- package/dist/safe-mdx.js.map +1 -1
- package/package.json +9 -1
- package/src/esm-parser.test.ts +7 -1
- package/src/html/html-and-md.test.ts +15 -47
- package/src/html/html-to-mdx-ast.ts +53 -1
- package/src/incremental-parse.test.ts +315 -0
- package/src/incremental-parse.ts +219 -0
- package/src/markdown-html.test.tsx +144 -0
- package/src/markdown.ts +4 -0
- package/src/parse.ts +46 -20
- package/src/safe-mdx.test.tsx +2 -0
- package/src/safe-mdx.tsx +6 -26
package/src/parse.ts
CHANGED
|
@@ -5,9 +5,9 @@ import { Root, RootContent } from 'mdast'
|
|
|
5
5
|
import { remark } from 'remark'
|
|
6
6
|
import remarkGfm from 'remark-gfm'
|
|
7
7
|
import remarkMdx from 'remark-mdx'
|
|
8
|
-
import {
|
|
8
|
+
import { remarkMdxJsxNormalize } from './html/remark-mdx-jsx-normalize.ts'
|
|
9
9
|
|
|
10
|
-
export {
|
|
10
|
+
export { remarkMdxJsxNormalize }
|
|
11
11
|
|
|
12
12
|
/* ── Import extraction ──────────────────────────────────────────────── */
|
|
13
13
|
|
|
@@ -34,7 +34,7 @@ export function extractImports(ast: Root): MdxImport[] {
|
|
|
34
34
|
|
|
35
35
|
for (const node of ast.children) {
|
|
36
36
|
if (node.type !== 'mdxjsEsm') continue
|
|
37
|
-
const estree =
|
|
37
|
+
const estree = node.data?.estree
|
|
38
38
|
if (!estree) continue
|
|
39
39
|
|
|
40
40
|
for (const statement of estree.body) {
|
|
@@ -70,6 +70,38 @@ export function mdxParse(code: string) {
|
|
|
70
70
|
return file.data.ast as Root
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
export type MdxProcessorOptions = {
|
|
74
|
+
/** Extra remark plugins appended after safe-mdx's default MDX, frontmatter, and GFM parsers. */
|
|
75
|
+
remarkPlugins?: any[]
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function createMdxProcessor({
|
|
79
|
+
remarkPlugins = [],
|
|
80
|
+
}: MdxProcessorOptions = {}) {
|
|
81
|
+
const processor = remark()
|
|
82
|
+
.use(remarkMdx)
|
|
83
|
+
.use(remarkFrontmatter, ['yaml', 'toml'])
|
|
84
|
+
.use(remarkGfm)
|
|
85
|
+
|
|
86
|
+
for (const plugin of remarkPlugins) {
|
|
87
|
+
if (Array.isArray(plugin)) {
|
|
88
|
+
processor.use(plugin[0], ...plugin.slice(1))
|
|
89
|
+
} else {
|
|
90
|
+
processor.use(plugin)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return processor
|
|
95
|
+
.use(remarkMarkAndUnravel)
|
|
96
|
+
.use(() => {
|
|
97
|
+
return (tree, file) => {
|
|
98
|
+
file.data.ast = tree
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export type MdxProcessor = ReturnType<typeof createMdxProcessor>
|
|
104
|
+
|
|
73
105
|
/**
|
|
74
106
|
* https://github.com/mdx-js/mdx/blob/b3351fadcb6f78833a72757b7135dcfb8ab646fe/packages/mdx/lib/plugin/remark-mark-and-unravel.js
|
|
75
107
|
* A tiny plugin that unravels `<p><h1>x</h1></p>` but also
|
|
@@ -181,7 +213,6 @@ export function resolveModulePath(
|
|
|
181
213
|
} else if (source.startsWith('./') || source.startsWith('../')) {
|
|
182
214
|
// Relative import: resolve from baseUrl
|
|
183
215
|
const joined = joinPaths(baseUrl, source)
|
|
184
|
-
if (!joined) return undefined // .. escaped above root
|
|
185
216
|
normalized = joined
|
|
186
217
|
} else {
|
|
187
218
|
// Bare specifier (npm package etc.) — not resolvable from glob
|
|
@@ -200,23 +231,27 @@ export function resolveModulePath(
|
|
|
200
231
|
}
|
|
201
232
|
|
|
202
233
|
/** Simple path join that normalizes `./a/b/../c` segments.
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
function joinPaths(base: string, relative: string): string
|
|
234
|
+
* Outputs inside-root paths with `./` prefix and outside-root paths with
|
|
235
|
+
* leading `../` segments, matching Vite glob keys from explicit imports. */
|
|
236
|
+
function joinPaths(base: string, relative: string): string {
|
|
206
237
|
// Strip ./ prefix and trailing /
|
|
207
238
|
const baseParts = base.replace(/^\.\//, '').replace(/\/$/, '').split('/').filter(Boolean)
|
|
208
239
|
const relParts = relative.replace(/^\.\//, '').split('/').filter(Boolean)
|
|
209
240
|
|
|
210
241
|
for (const part of relParts) {
|
|
211
242
|
if (part === '..') {
|
|
212
|
-
if (baseParts.length
|
|
213
|
-
|
|
243
|
+
if (baseParts.length > 0 && baseParts[baseParts.length - 1] !== '..') {
|
|
244
|
+
baseParts.pop()
|
|
245
|
+
} else {
|
|
246
|
+
baseParts.push('..')
|
|
247
|
+
}
|
|
214
248
|
} else if (part !== '.') {
|
|
215
249
|
baseParts.push(part)
|
|
216
250
|
}
|
|
217
251
|
}
|
|
218
252
|
|
|
219
|
-
|
|
253
|
+
const joined = baseParts.join('/')
|
|
254
|
+
return joined.startsWith('../') ? joined : './' + joined
|
|
220
255
|
}
|
|
221
256
|
|
|
222
257
|
export type LazyGlob = Record<string, () => Promise<Record<string, any>>>
|
|
@@ -262,13 +297,4 @@ export async function resolveModules({
|
|
|
262
297
|
return result
|
|
263
298
|
}
|
|
264
299
|
|
|
265
|
-
const mdxProcessor =
|
|
266
|
-
.use(remarkMdx)
|
|
267
|
-
.use(remarkFrontmatter, ['yaml', 'toml'])
|
|
268
|
-
.use(remarkGfm)
|
|
269
|
-
.use(remarkMarkAndUnravel)
|
|
270
|
-
.use(() => {
|
|
271
|
-
return (tree, file) => {
|
|
272
|
-
file.data.ast = tree
|
|
273
|
-
}
|
|
274
|
-
})
|
|
300
|
+
export const mdxProcessor = createMdxProcessor()
|
package/src/safe-mdx.test.tsx
CHANGED
package/src/safe-mdx.tsx
CHANGED
|
@@ -10,8 +10,7 @@ import { Fragment, ReactNode } from 'react'
|
|
|
10
10
|
import { DynamicEsmComponent } from 'safe-mdx/client'
|
|
11
11
|
import { extractComponentInfo, parseEsmImports } from './esm-parser.ts'
|
|
12
12
|
import { resolveModulePath, type EagerModules } from './parse.ts'
|
|
13
|
-
import {
|
|
14
|
-
import { validHtmlElements, nativeTags } from './html/valid-html-elements.ts'
|
|
13
|
+
import { nativeTags } from './html/valid-html-elements.ts'
|
|
15
14
|
|
|
16
15
|
export type MyRootContent = RootContent | Root
|
|
17
16
|
|
|
@@ -1081,30 +1080,11 @@ export class MdastToJsx {
|
|
|
1081
1080
|
return []
|
|
1082
1081
|
}
|
|
1083
1082
|
case 'html': {
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
}
|
|
1090
|
-
|
|
1091
|
-
// Parse HTML to MDX AST using the new approach - always returns an array
|
|
1092
|
-
const mdxAst = htmlToMdxAst({
|
|
1093
|
-
html: text,
|
|
1094
|
-
parentType: parentType || 'root',
|
|
1095
|
-
convertTagName: ({ tagName }) => {
|
|
1096
|
-
const lowerTag = tagName.toLowerCase()
|
|
1097
|
-
// Only keep valid HTML elements
|
|
1098
|
-
if (validHtmlElements.has(lowerTag)) {
|
|
1099
|
-
return lowerTag
|
|
1100
|
-
}
|
|
1101
|
-
// Return empty string for non-HTML elements
|
|
1102
|
-
return ''
|
|
1103
|
-
}
|
|
1104
|
-
})
|
|
1105
|
-
|
|
1106
|
-
// Process the MDX AST nodes
|
|
1107
|
-
return mdxAst.map(child => this.mdastTransformer(child, 'html'))
|
|
1083
|
+
// html nodes appear when rendering plain markdown (not MDX) without
|
|
1084
|
+
// the remarkHtmlToMdx pre-processing plugin. They are intentionally
|
|
1085
|
+
// ignored here — use remarkHtmlToMdx from 'safe-mdx/markdown' to convert
|
|
1086
|
+
// them to mdxJsx nodes before passing the AST to MdastToJsx.
|
|
1087
|
+
return []
|
|
1108
1088
|
}
|
|
1109
1089
|
case 'imageReference': {
|
|
1110
1090
|
return []
|