safe-mdx 1.3.7 → 1.3.9
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/dist/html/html-and-md.test.d.ts +2 -0
- package/dist/html/html-and-md.test.d.ts.map +1 -0
- package/dist/html/html-and-md.test.js +869 -0
- package/dist/html/html-and-md.test.js.map +1 -0
- package/dist/html/html-to-mdx-ast.d.ts.map +1 -1
- package/dist/html/html-to-mdx-ast.js.map +1 -1
- package/dist/html/html-to-mdx-ast.test.js +43 -0
- package/dist/html/html-to-mdx-ast.test.js.map +1 -1
- package/dist/safe-mdx.d.ts +1 -1
- package/dist/safe-mdx.d.ts.map +1 -1
- package/dist/safe-mdx.js +2 -2
- package/dist/safe-mdx.js.map +1 -1
- package/package.json +4 -4
- package/src/html/html-and-md.test.ts +953 -0
- package/src/html/html-to-mdx-ast.test.ts +48 -0
- package/src/html/html-to-mdx-ast.ts +9 -8
- package/src/safe-mdx.tsx +3 -3
|
@@ -752,4 +752,52 @@ describe('parseHtmlToMdxAst with markdown processor', () => {
|
|
|
752
752
|
])
|
|
753
753
|
})
|
|
754
754
|
})
|
|
755
|
+
|
|
756
|
+
test('block-level HTML elements as direct children of root should be flow elements', () => {
|
|
757
|
+
// Test that wrapper outer HTML elements that are direct children of root
|
|
758
|
+
// should be flow elements, not text elements
|
|
759
|
+
const htmlWithNestedBlocks = htmlToMdxAst({
|
|
760
|
+
html: `<div class="wrapper">
|
|
761
|
+
<h1>Title</h1>
|
|
762
|
+
<p>Some content</p>
|
|
763
|
+
<section>
|
|
764
|
+
<h2>Subtitle</h2>
|
|
765
|
+
</section>
|
|
766
|
+
</div>
|
|
767
|
+
<article>
|
|
768
|
+
<header>Header</header>
|
|
769
|
+
<main>Content</main>
|
|
770
|
+
</article>`,
|
|
771
|
+
parentType: 'root'
|
|
772
|
+
})
|
|
773
|
+
|
|
774
|
+
// All block-level elements at root should be flow elements
|
|
775
|
+
expect(htmlWithNestedBlocks).toHaveLength(2)
|
|
776
|
+
|
|
777
|
+
// First element: div wrapper
|
|
778
|
+
expect(htmlWithNestedBlocks[0]).toMatchObject({
|
|
779
|
+
type: 'mdxJsxFlowElement',
|
|
780
|
+
name: 'div'
|
|
781
|
+
})
|
|
782
|
+
|
|
783
|
+
// Second element: article
|
|
784
|
+
expect(htmlWithNestedBlocks[1]).toMatchObject({
|
|
785
|
+
type: 'mdxJsxFlowElement',
|
|
786
|
+
name: 'article'
|
|
787
|
+
})
|
|
788
|
+
|
|
789
|
+
// Test with various block-level tags
|
|
790
|
+
const blockTags = ['div', 'article', 'section', 'header', 'main', 'footer', 'aside', 'nav']
|
|
791
|
+
blockTags.forEach(tag => {
|
|
792
|
+
const result = htmlToMdxAst({
|
|
793
|
+
html: `<${tag}>Content</${tag}>`,
|
|
794
|
+
parentType: 'root'
|
|
795
|
+
})
|
|
796
|
+
expect(result).toHaveLength(1)
|
|
797
|
+
expect(result[0]).toMatchObject({
|
|
798
|
+
type: 'mdxJsxFlowElement',
|
|
799
|
+
name: tag
|
|
800
|
+
})
|
|
801
|
+
})
|
|
802
|
+
})
|
|
755
803
|
})
|
|
@@ -67,10 +67,11 @@ function defaultConvertAttributeValue({
|
|
|
67
67
|
return value
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
|
|
70
71
|
// Remove common indentation from multi-line text while preserving relative indentation
|
|
71
72
|
function deindent(text: string): string {
|
|
72
73
|
const lines = text.split('\n')
|
|
73
|
-
|
|
74
|
+
|
|
74
75
|
// Find minimum indentation (excluding empty lines)
|
|
75
76
|
let minIndent = Infinity
|
|
76
77
|
for (const line of lines) {
|
|
@@ -81,12 +82,12 @@ function deindent(text: string): string {
|
|
|
81
82
|
}
|
|
82
83
|
}
|
|
83
84
|
}
|
|
84
|
-
|
|
85
|
+
|
|
85
86
|
// If no indentation found, return as is
|
|
86
87
|
if (minIndent === 0 || minIndent === Infinity) {
|
|
87
88
|
return text
|
|
88
89
|
}
|
|
89
|
-
|
|
90
|
+
|
|
90
91
|
// Remove common indentation from each line, preserving relative indentation
|
|
91
92
|
return lines
|
|
92
93
|
.map(line => line.slice(minIndent))
|
|
@@ -197,24 +198,24 @@ function htmlNodeToMdxAst(
|
|
|
197
198
|
|
|
198
199
|
if (isTextNode(node)) {
|
|
199
200
|
let textValue = node.textContent || ''
|
|
200
|
-
|
|
201
|
+
|
|
201
202
|
// Skip whitespace-only nodes between elements
|
|
202
203
|
if (!textValue.trim()) {
|
|
203
204
|
const prevSibling = node.previousSibling
|
|
204
205
|
const nextSibling = node.nextSibling
|
|
205
|
-
|
|
206
|
+
|
|
206
207
|
// If between elements and contains newlines, it's likely formatting
|
|
207
|
-
if (textValue.includes('\n') &&
|
|
208
|
+
if (textValue.includes('\n') &&
|
|
208
209
|
((prevSibling && isElementNode(prevSibling)) ||
|
|
209
210
|
(nextSibling && isElementNode(nextSibling)))) {
|
|
210
211
|
return []
|
|
211
212
|
}
|
|
212
213
|
// Otherwise preserve the whitespace (could be intentional space)
|
|
213
214
|
}
|
|
214
|
-
|
|
215
|
+
|
|
215
216
|
// Always deindent text content
|
|
216
217
|
textValue = deindent(textValue).trim()
|
|
217
|
-
|
|
218
|
+
|
|
218
219
|
// Skip empty text after processing
|
|
219
220
|
if (!textValue) {
|
|
220
221
|
return []
|
package/src/safe-mdx.tsx
CHANGED
|
@@ -287,7 +287,7 @@ export class MdastToJsx {
|
|
|
287
287
|
)
|
|
288
288
|
}
|
|
289
289
|
default: {
|
|
290
|
-
return this.mdastTransformer(node, '
|
|
290
|
+
return this.mdastTransformer(node, 'mdxJsxFlowElement')
|
|
291
291
|
}
|
|
292
292
|
}
|
|
293
293
|
}
|
|
@@ -571,7 +571,7 @@ export class MdastToJsx {
|
|
|
571
571
|
return res
|
|
572
572
|
}
|
|
573
573
|
|
|
574
|
-
mdastTransformer(node: MyRootContent, parentType
|
|
574
|
+
mdastTransformer(node: MyRootContent, parentType: string): ReactNode {
|
|
575
575
|
if (!node) {
|
|
576
576
|
return []
|
|
577
577
|
}
|
|
@@ -944,7 +944,7 @@ export class MdastToJsx {
|
|
|
944
944
|
})
|
|
945
945
|
|
|
946
946
|
// Process the MDX AST nodes
|
|
947
|
-
return mdxAst.map(child => this.mdastTransformer(child,
|
|
947
|
+
return mdxAst.map(child => this.mdastTransformer(child, 'html'))
|
|
948
948
|
}
|
|
949
949
|
case 'imageReference': {
|
|
950
950
|
return []
|