safe-mdx 0.0.4 → 0.0.6
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 +50 -4
- package/dist/plugins.d.ts +12 -0
- package/dist/plugins.d.ts.map +1 -0
- package/dist/plugins.js +68 -0
- package/dist/plugins.js.map +1 -0
- package/dist/safe-mdx.d.ts +10 -9
- package/dist/safe-mdx.d.ts.map +1 -1
- package/dist/safe-mdx.js +381 -70
- package/dist/safe-mdx.js.map +1 -1
- package/dist/safe-mdx.test.js +182 -20
- package/dist/safe-mdx.test.js.map +1 -1
- package/package.json +54 -51
- package/src/plugins.ts +87 -0
- package/src/safe-mdx.test.tsx +190 -20
- package/src/safe-mdx.tsx +367 -56
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -2
- package/dist/index.js.map +0 -1
- package/src/index.ts +0 -1
package/dist/safe-mdx.test.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import React from 'react';
|
|
3
2
|
import dedent from 'dedent';
|
|
4
|
-
import
|
|
5
|
-
import { MdastToJsx } from './safe-mdx';
|
|
3
|
+
import React from 'react';
|
|
6
4
|
import { renderToStaticMarkup } from 'react-dom/server';
|
|
5
|
+
import { expect, test } from 'vitest';
|
|
6
|
+
import { mdastBfs, MdastToJsx, mdxParse } from './safe-mdx.js';
|
|
7
7
|
void React;
|
|
8
8
|
const components = {
|
|
9
9
|
Heading({ level, children }) {
|
|
@@ -17,10 +17,100 @@ function render(code) {
|
|
|
17
17
|
// console.log(JSON.stringify(result, null, 2))
|
|
18
18
|
return { result, errors: visitor.errors || [], html };
|
|
19
19
|
}
|
|
20
|
+
test('remark and jsx does not wrap in p', () => {
|
|
21
|
+
const code = dedent `
|
|
22
|
+
# Hello
|
|
23
|
+
|
|
24
|
+
i am a paragraph
|
|
25
|
+
|
|
26
|
+
<Heading>heading</Heading>
|
|
27
|
+
|
|
28
|
+
something
|
|
29
|
+
`;
|
|
30
|
+
const mdast = mdxParse(code);
|
|
31
|
+
mdastBfs(mdast, (x) => {
|
|
32
|
+
delete x.position;
|
|
33
|
+
});
|
|
34
|
+
expect(mdast).toMatchInlineSnapshot(`
|
|
35
|
+
{
|
|
36
|
+
"children": [
|
|
37
|
+
{
|
|
38
|
+
"children": [
|
|
39
|
+
{
|
|
40
|
+
"type": "text",
|
|
41
|
+
"value": "Hello",
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
"depth": 1,
|
|
45
|
+
"type": "heading",
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"children": [
|
|
49
|
+
{
|
|
50
|
+
"type": "text",
|
|
51
|
+
"value": "i am a paragraph",
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
"type": "paragraph",
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"attributes": [],
|
|
58
|
+
"children": [
|
|
59
|
+
{
|
|
60
|
+
"type": "text",
|
|
61
|
+
"value": "heading",
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
"name": "Heading",
|
|
65
|
+
"type": "mdxJsxFlowElement",
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"children": [
|
|
69
|
+
{
|
|
70
|
+
"type": "text",
|
|
71
|
+
"value": "something",
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
"type": "paragraph",
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
"type": "root",
|
|
78
|
+
}
|
|
79
|
+
`);
|
|
80
|
+
});
|
|
20
81
|
test('basic', () => {
|
|
21
82
|
expect(render(dedent `
|
|
22
83
|
# Hello
|
|
23
84
|
|
|
85
|
+
i am a paragraph
|
|
86
|
+
|
|
87
|
+
<Heading>heading</Heading>
|
|
88
|
+
`)).toMatchInlineSnapshot(`
|
|
89
|
+
{
|
|
90
|
+
"errors": [],
|
|
91
|
+
"html": "<h1>Hello</h1><p>i am a paragraph</p><h1>heading</h1>",
|
|
92
|
+
"result": <React.Fragment>
|
|
93
|
+
<h1>
|
|
94
|
+
Hello
|
|
95
|
+
</h1>
|
|
96
|
+
<p>
|
|
97
|
+
i am a paragraph
|
|
98
|
+
</p>
|
|
99
|
+
<Heading>
|
|
100
|
+
heading
|
|
101
|
+
</Heading>
|
|
102
|
+
</React.Fragment>,
|
|
103
|
+
}
|
|
104
|
+
`);
|
|
105
|
+
});
|
|
106
|
+
test('frontmatter', () => {
|
|
107
|
+
expect(render(dedent `
|
|
108
|
+
---
|
|
109
|
+
hello: 5
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
# Hello
|
|
113
|
+
|
|
24
114
|
i am a paragraph
|
|
25
115
|
`)).toMatchInlineSnapshot(`
|
|
26
116
|
{
|
|
@@ -168,15 +258,13 @@ test('inline jsx', () => {
|
|
|
168
258
|
`)).toMatchInlineSnapshot(`
|
|
169
259
|
{
|
|
170
260
|
"errors": [],
|
|
171
|
-
"html": "<
|
|
261
|
+
"html": "<h1>hello</h1>",
|
|
172
262
|
"result": <React.Fragment>
|
|
173
|
-
<
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
</Heading>
|
|
179
|
-
</p>
|
|
263
|
+
<Heading
|
|
264
|
+
level={2}
|
|
265
|
+
>
|
|
266
|
+
hello
|
|
267
|
+
</Heading>
|
|
180
268
|
</React.Fragment>,
|
|
181
269
|
}
|
|
182
270
|
`);
|
|
@@ -740,11 +828,41 @@ test('kitchen sink', () => {
|
|
|
740
828
|
`)).toMatchInlineSnapshot(`
|
|
741
829
|
{
|
|
742
830
|
"errors": [
|
|
831
|
+
{
|
|
832
|
+
"message": "Unsupported language no-highlight",
|
|
833
|
+
},
|
|
834
|
+
{
|
|
835
|
+
"message": "Unsupported language no-highlight",
|
|
836
|
+
},
|
|
837
|
+
{
|
|
838
|
+
"message": "Unsupported language no-highlight",
|
|
839
|
+
},
|
|
840
|
+
{
|
|
841
|
+
"message": "Unsupported language no-highlight",
|
|
842
|
+
},
|
|
843
|
+
{
|
|
844
|
+
"message": "Unsupported language no-highlight",
|
|
845
|
+
},
|
|
846
|
+
{
|
|
847
|
+
"message": "Unsupported language no-highlight",
|
|
848
|
+
},
|
|
849
|
+
{
|
|
850
|
+
"message": "Unsupported language no-highlight",
|
|
851
|
+
},
|
|
852
|
+
{
|
|
853
|
+
"message": "Unsupported language no-highlight",
|
|
854
|
+
},
|
|
743
855
|
{
|
|
744
856
|
"message": "Unsupported jsx component dl",
|
|
745
857
|
},
|
|
858
|
+
{
|
|
859
|
+
"message": "Unsupported language no-highlight",
|
|
860
|
+
},
|
|
861
|
+
{
|
|
862
|
+
"message": "Unsupported language no-highlight",
|
|
863
|
+
},
|
|
746
864
|
],
|
|
747
|
-
"html": "<h1>Markdown Kitchen Sink</h1><p>This file is <a href="https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet" title="">https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet</a> plus a few fixes and additions. Used by <a href="https://github.com/obedm503/bootmark" title="">obedm503/bootmark</a> to <a href="https://obedm503.github.io/bootmark/docs/markdown-cheatsheet.html" title="">demonstrate</a> it's styling features.</p><p>This is intended as a quick reference and showcase. For more complete info, see <a href="http://daringfireball.net/projects/markdown/" title="">John Gruber's original spec</a> and the <a href="http://github.github.com/github-flavored-markdown/" title="">Github-flavored Markdown info page</a>.</p><p>Note that there is also a <a href="./Markdown-Here-Cheatsheet" title="">Cheatsheet specific to Markdown Here</a> if that's what you're looking for. You can also check out <a href="./Other-Markdown-Tools" title="">more Markdown tools</a>.</p><h5>Table of Contents</h5><p><a href="#headers" title="">Headers</a><br/><a href="#emphasis" title="">Emphasis</a><br/><a href="#lists" title="">Lists</a><br/><a href="#links" title="">Links</a><br/><a href="#images" title="">Images</a><br/><a href="#code" title="">Code and Syntax Highlighting</a><br/><a href="#tables" title="">Tables</a><br/><a href="#blockquotes" title="">Blockquotes</a><br/><a href="#html" title="">Inline HTML</a><br/><a href="#hr" title="">Horizontal Rule</a><br/><a href="#lines" title="">Line Breaks</a><br/><a href="#videos" title="">YouTube Videos</a></p><a name="headers"></a><h2>Headers</h2><h1>H1</h1><h2>H2</h2><h3>H3</h3><h4>H4</h4><h5>H5</h5><h6>H6</h6><p>Alternatively, for H1 and H2, an underline-ish style:</p><h1>Alt-H1</h1><h2>Alt-H2</h2><h1>H1</h1><h2>H2</h2><h3>H3</h3><h4>H4</h4><h5>H5</h5><h6>H6</h6><p>Alternatively, for H1 and H2, an underline-ish style:</p><h1>Alt-H1</h1><h2>Alt-H2</h2><a name="emphasis"></a><h2>Emphasis</h2><pre><code>Emphasis, aka italics, with *asterisks* or _underscores_.
|
|
865
|
+
"html": "<link rel="preload" as="image" href="https://github.com/adam-p/markdown-here/raw/master/src/common/images/icon48.png"/><h1>Markdown Kitchen Sink</h1><p>This file is <a href="https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet" title="">https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet</a> plus a few fixes and additions. Used by <a href="https://github.com/obedm503/bootmark" title="">obedm503/bootmark</a> to <a href="https://obedm503.github.io/bootmark/docs/markdown-cheatsheet.html" title="">demonstrate</a> it's styling features.</p><p>This is intended as a quick reference and showcase. For more complete info, see <a href="http://daringfireball.net/projects/markdown/" title="">John Gruber's original spec</a> and the <a href="http://github.github.com/github-flavored-markdown/" title="">Github-flavored Markdown info page</a>.</p><p>Note that there is also a <a href="./Markdown-Here-Cheatsheet" title="">Cheatsheet specific to Markdown Here</a> if that's what you're looking for. You can also check out <a href="./Other-Markdown-Tools" title="">more Markdown tools</a>.</p><h5>Table of Contents</h5><p><a href="#headers" title="">Headers</a><br/><a href="#emphasis" title="">Emphasis</a><br/><a href="#lists" title="">Lists</a><br/><a href="#links" title="">Links</a><br/><a href="#images" title="">Images</a><br/><a href="#code" title="">Code and Syntax Highlighting</a><br/><a href="#tables" title="">Tables</a><br/><a href="#blockquotes" title="">Blockquotes</a><br/><a href="#html" title="">Inline HTML</a><br/><a href="#hr" title="">Horizontal Rule</a><br/><a href="#lines" title="">Line Breaks</a><br/><a href="#videos" title="">YouTube Videos</a></p><a name="headers"></a><h2>Headers</h2><h1>H1</h1><h2>H2</h2><h3>H3</h3><h4>H4</h4><h5>H5</h5><h6>H6</h6><p>Alternatively, for H1 and H2, an underline-ish style:</p><h1>Alt-H1</h1><h2>Alt-H2</h2><h1>H1</h1><h2>H2</h2><h3>H3</h3><h4>H4</h4><h5>H5</h5><h6>H6</h6><p>Alternatively, for H1 and H2, an underline-ish style:</p><h1>Alt-H1</h1><h2>Alt-H2</h2><a name="emphasis"></a><h2>Emphasis</h2><pre><code>Emphasis, aka italics, with *asterisks* or _underscores_.
|
|
748
866
|
|
|
749
867
|
Strong emphasis, aka bold, with **asterisks** or __underscores__.
|
|
750
868
|
|
|
@@ -797,11 +915,11 @@ test('kitchen sink', () => {
|
|
|
797
915
|
|
|
798
916
|
[logo]: https://github.com/adam-p/markdown-here/raw/master/src/common/images/icon48.png "Logo Title Text 2"</code></pre><p>Here's our logo (hover to see the title text):</p><p>Inline-style:
|
|
799
917
|
<img src="https://github.com/adam-p/markdown-here/raw/master/src/common/images/icon48.png" alt="alt text" title="Logo Title Text 1"/></p><p>Reference-style:
|
|
800
|
-
</p><a name="code"></a><h2>Code and Syntax Highlighting</h2><p>Code blocks are part of the Markdown spec, but syntax highlighting isn't. However, many renderers -- like Github's and <em>Markdown Here</em> -- support syntax highlighting. Which languages are supported and how those language names should be written will vary from renderer to renderer. <em>Markdown Here</em> supports highlighting for dozens of languages (and not-really-languages, like diffs and HTTP headers); to see the complete list, and how to write the language names, see the <a href="http://softwaremaniacs.org/media/soft/highlight/test.html" title="">highlight.js demo page</a>.</p><pre><code>Inline \`code\` has \`back-ticks around\` it.</code></pre><p>Inline <code>code</code> has <code>back-ticks around</code> it.</p><p>Blocks of code are either fenced by lines with three back-ticks <code>\`\`\`</code>, or are indented with four spaces. I recommend only using the fenced code blocks -- they're easier and only they support syntax highlighting.</p><pre><code>var s = "JavaScript syntax highlighting";
|
|
801
|
-
alert(s);</code></pre><pre><code>s = "Python syntax highlighting"
|
|
918
|
+
</p><a name="code"></a><h2>Code and Syntax Highlighting</h2><p>Code blocks are part of the Markdown spec, but syntax highlighting isn't. However, many renderers -- like Github's and <em>Markdown Here</em> -- support syntax highlighting. Which languages are supported and how those language names should be written will vary from renderer to renderer. <em>Markdown Here</em> supports highlighting for dozens of languages (and not-really-languages, like diffs and HTTP headers); to see the complete list, and how to write the language names, see the <a href="http://softwaremaniacs.org/media/soft/highlight/test.html" title="">highlight.js demo page</a>.</p><pre><code>Inline \`code\` has \`back-ticks around\` it.</code></pre><p>Inline <code>code</code> has <code>back-ticks around</code> it.</p><p>Blocks of code are either fenced by lines with three back-ticks <code>\`\`\`</code>, or are indented with four spaces. I recommend only using the fenced code blocks -- they're easier and only they support syntax highlighting.</p><pre><code class="language-javascript">var s = "JavaScript syntax highlighting";
|
|
919
|
+
alert(s);</code></pre><pre><code class="language-python">s = "Python syntax highlighting"
|
|
802
920
|
print s</code></pre><pre><code>No language indicated, so no syntax highlighting.
|
|
803
|
-
But let's throw in a &lt;b&gt;tag&lt;/b&gt;.</code></pre><pre><code>var s = "JavaScript syntax highlighting";
|
|
804
|
-
alert(s);</code></pre><pre><code>s = "Python syntax highlighting"
|
|
921
|
+
But let's throw in a &lt;b&gt;tag&lt;/b&gt;.</code></pre><pre><code class="language-javascript">var s = "JavaScript syntax highlighting";
|
|
922
|
+
alert(s);</code></pre><pre><code class="language-python">s = "Python syntax highlighting"
|
|
805
923
|
print s</code></pre><pre><code>No language indicated, so no syntax highlighting in Markdown Here (varies on Github).
|
|
806
924
|
But let's throw in a <b>tag</b>.</code></pre><a name="tables"></a><h2>Tables</h2><p>Tables aren't part of the core Markdown spec, but they are part of GFM and <em>Markdown Here</em> supports them. They are an easy way of adding tables to your email -- a task that would otherwise require copy-pasting from another application.</p><pre><code>Colons can be used to align columns.
|
|
807
925
|
|
|
@@ -1394,13 +1512,17 @@ test('kitchen sink', () => {
|
|
|
1394
1512
|
, or are indented with four spaces. I recommend only using the fenced code blocks -- they're easier and only they support syntax highlighting.
|
|
1395
1513
|
</p>
|
|
1396
1514
|
<pre>
|
|
1397
|
-
<code
|
|
1515
|
+
<code
|
|
1516
|
+
className="language-javascript"
|
|
1517
|
+
>
|
|
1398
1518
|
var s = "JavaScript syntax highlighting";
|
|
1399
1519
|
alert(s);
|
|
1400
1520
|
</code>
|
|
1401
1521
|
</pre>
|
|
1402
1522
|
<pre>
|
|
1403
|
-
<code
|
|
1523
|
+
<code
|
|
1524
|
+
className="language-python"
|
|
1525
|
+
>
|
|
1404
1526
|
s = "Python syntax highlighting"
|
|
1405
1527
|
print s
|
|
1406
1528
|
</code>
|
|
@@ -1412,13 +1534,17 @@ test('kitchen sink', () => {
|
|
|
1412
1534
|
</code>
|
|
1413
1535
|
</pre>
|
|
1414
1536
|
<pre>
|
|
1415
|
-
<code
|
|
1537
|
+
<code
|
|
1538
|
+
className="language-javascript"
|
|
1539
|
+
>
|
|
1416
1540
|
var s = "JavaScript syntax highlighting";
|
|
1417
1541
|
alert(s);
|
|
1418
1542
|
</code>
|
|
1419
1543
|
</pre>
|
|
1420
1544
|
<pre>
|
|
1421
|
-
<code
|
|
1545
|
+
<code
|
|
1546
|
+
className="language-python"
|
|
1547
|
+
>
|
|
1422
1548
|
s = "Python syntax highlighting"
|
|
1423
1549
|
print s
|
|
1424
1550
|
</code>
|
|
@@ -1791,4 +1917,40 @@ test('kitchen sink', () => {
|
|
|
1791
1917
|
}
|
|
1792
1918
|
`);
|
|
1793
1919
|
});
|
|
1920
|
+
test('code block rendering', () => {
|
|
1921
|
+
const code = dedent `
|
|
1922
|
+
`;
|
|
1923
|
+
expect(render(dedent `
|
|
1924
|
+
\`\`\`typescript
|
|
1925
|
+
const x = 1;
|
|
1926
|
+
\`\`\`
|
|
1927
|
+
|
|
1928
|
+
\`\`\`invalid-language
|
|
1929
|
+
const y = 2;
|
|
1930
|
+
\`\`\`
|
|
1931
|
+
`)).toMatchInlineSnapshot(`
|
|
1932
|
+
{
|
|
1933
|
+
"errors": [
|
|
1934
|
+
{
|
|
1935
|
+
"message": "Unsupported language invalid-language",
|
|
1936
|
+
},
|
|
1937
|
+
],
|
|
1938
|
+
"html": "<pre><code class="language-typescript">const x = 1;</code></pre><pre><code>const y = 2;</code></pre>",
|
|
1939
|
+
"result": <React.Fragment>
|
|
1940
|
+
<pre>
|
|
1941
|
+
<code
|
|
1942
|
+
className="language-typescript"
|
|
1943
|
+
>
|
|
1944
|
+
const x = 1;
|
|
1945
|
+
</code>
|
|
1946
|
+
</pre>
|
|
1947
|
+
<pre>
|
|
1948
|
+
<code>
|
|
1949
|
+
const y = 2;
|
|
1950
|
+
</code>
|
|
1951
|
+
</pre>
|
|
1952
|
+
</React.Fragment>,
|
|
1953
|
+
}
|
|
1954
|
+
`);
|
|
1955
|
+
});
|
|
1794
1956
|
//# sourceMappingURL=safe-mdx.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"safe-mdx.test.js","sourceRoot":"","sources":["../src/safe-mdx.test.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,
|
|
1
|
+
{"version":3,"file":"safe-mdx.test.js","sourceRoot":"","sources":["../src/safe-mdx.test.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,53 +1,56 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
},
|
|
14
|
-
"./src/*": "./src/*.ts",
|
|
15
|
-
"./src": "./src/index.ts",
|
|
16
|
-
"./package.json": "./package.json"
|
|
2
|
+
"name": "safe-mdx",
|
|
3
|
+
"version": "0.0.6",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Render MDX in React without eval",
|
|
6
|
+
"repository": "https://github.com/holocron-hq/safe-mdx",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"types": "./dist/safe-mdx.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/safe-mdx.d.ts",
|
|
12
|
+
"default": "./dist/safe-mdx.js"
|
|
17
13
|
},
|
|
18
|
-
"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
14
|
+
"./src/*": "./src/*.tsx",
|
|
15
|
+
"./package.json": "./package.json"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"src"
|
|
20
|
+
],
|
|
21
|
+
"keywords": [
|
|
22
|
+
"mdx"
|
|
23
|
+
],
|
|
24
|
+
"author": "remorses <beats.by.morse@gmail.com>",
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"peerDependencies": {
|
|
27
|
+
"react": "*"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"collapse-white-space": "^2.1.0",
|
|
31
|
+
"html-to-jsx-transform": "^1.0.0",
|
|
32
|
+
"remark": "^15.0.1",
|
|
33
|
+
"remark-frontmatter": "^5.0.0",
|
|
34
|
+
"remark-gfm": "^4.0.0",
|
|
35
|
+
"remark-mdx": "^3.0.0",
|
|
36
|
+
"unified": "^11.0.5",
|
|
37
|
+
"unist-util-visit": "^5.0.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/mdast": "^4.0.0",
|
|
41
|
+
"@types/node": "^20.0.0",
|
|
42
|
+
"@types/react": "^18.3.11",
|
|
43
|
+
"@types/react-dom": "^18.0.0",
|
|
44
|
+
"@vitest/coverage-v8": "^1.6.0",
|
|
45
|
+
"dedent": "^1.5.1",
|
|
46
|
+
"mdast-util-mdx-jsx": "^3.2.0",
|
|
47
|
+
"react": "^19.0.0",
|
|
48
|
+
"react-dom": "^19.0.0",
|
|
49
|
+
"typescript": "5.5.2",
|
|
50
|
+
"vitest": "^3.1.1"
|
|
51
|
+
},
|
|
52
|
+
"scripts": {
|
|
53
|
+
"build": "tsc",
|
|
54
|
+
"test": "vitest"
|
|
55
|
+
}
|
|
56
|
+
}
|
package/src/plugins.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { Root, RootContent } from 'mdast'
|
|
2
|
+
import { collapseWhiteSpace } from 'collapse-white-space'
|
|
3
|
+
import { visit } from 'unist-util-visit'
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* https://github.com/mdx-js/mdx/blob/b3351fadcb6f78833a72757b7135dcfb8ab646fe/packages/mdx/lib/plugin/remark-mark-and-unravel.js
|
|
8
|
+
* A tiny plugin that unravels `<p><h1>x</h1></p>` but also
|
|
9
|
+
* `<p><Component /></p>` (so it has no knowledge of "HTML").
|
|
10
|
+
*
|
|
11
|
+
* It also marks JSX as being explicitly JSX, so when a user passes a `h1`
|
|
12
|
+
* component, it is used for `# heading` but not for `<h1>heading</h1>`.
|
|
13
|
+
*
|
|
14
|
+
*/
|
|
15
|
+
export function remarkMarkAndUnravel() {
|
|
16
|
+
return function (tree: Root) {
|
|
17
|
+
|
|
18
|
+
visit(tree, function (node, index, parent) {
|
|
19
|
+
let offset = -1
|
|
20
|
+
let all = true
|
|
21
|
+
let oneOrMore = false
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
if (
|
|
25
|
+
parent &&
|
|
26
|
+
typeof index === 'number' &&
|
|
27
|
+
node.type === 'paragraph'
|
|
28
|
+
) {
|
|
29
|
+
const children = node.children
|
|
30
|
+
|
|
31
|
+
while (++offset < children.length) {
|
|
32
|
+
const child = children[offset]
|
|
33
|
+
|
|
34
|
+
if (
|
|
35
|
+
child.type === 'mdxJsxTextElement' ||
|
|
36
|
+
child.type === 'mdxTextExpression'
|
|
37
|
+
) {
|
|
38
|
+
oneOrMore = true
|
|
39
|
+
} else if (
|
|
40
|
+
child.type === 'text' &&
|
|
41
|
+
collapseWhiteSpace(child.value, {
|
|
42
|
+
style: 'html',
|
|
43
|
+
trim: true,
|
|
44
|
+
}) === ''
|
|
45
|
+
) {
|
|
46
|
+
// Empty.
|
|
47
|
+
} else {
|
|
48
|
+
all = false
|
|
49
|
+
break
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (all && oneOrMore) {
|
|
54
|
+
offset = -1
|
|
55
|
+
|
|
56
|
+
const newChildren: RootContent[] = []
|
|
57
|
+
|
|
58
|
+
while (++offset < children.length) {
|
|
59
|
+
const child = children[offset]
|
|
60
|
+
|
|
61
|
+
if (child.type === 'mdxJsxTextElement') {
|
|
62
|
+
// @ts-expect-error: mutate because it is faster; content model is fine.
|
|
63
|
+
child.type = 'mdxJsxFlowElement'
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (child.type === 'mdxTextExpression') {
|
|
67
|
+
// @ts-expect-error: mutate because it is faster; content model is fine.
|
|
68
|
+
child.type = 'mdxFlowExpression'
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (
|
|
72
|
+
child.type === 'text' &&
|
|
73
|
+
/^[\t\r\n ]+$/.test(String(child.value))
|
|
74
|
+
) {
|
|
75
|
+
// Empty.
|
|
76
|
+
} else {
|
|
77
|
+
newChildren.push(child)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
parent.children.splice(index, 1, ...newChildren)
|
|
82
|
+
return index
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
}
|