Skip to content

Commit 3f266d4

Browse files
authored
Make MDX nodes typed with JSX.IntrinsicElements (#515)
1 parent 5c96eac commit 3f266d4

File tree

3 files changed

+98
-35
lines changed

3 files changed

+98
-35
lines changed

.changeset/shaggy-memes-post.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
'@mdx-js/language-service': patch
3+
'@mdx-js/language-server': patch
4+
'@mdx-js/typescript-plugin': patch
5+
'vscode-mdx': patch
6+
---
7+
8+
Make Markdown syntax nodes typed with `JSX.IntrinsicElements`.

packages/language-service/lib/virtual-code.js

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,52 @@ function padOffsets(mapping, padding) {
225225
}
226226
}
227227

228+
/** @type {Partial<Record<Nodes["type"], string>>} */
229+
const mdastElementNodeNameMap = {
230+
blockquote: 'blockquote',
231+
break: 'br',
232+
delete: 'del',
233+
emphasis: 'em',
234+
html: 'html',
235+
image: 'img',
236+
imageReference: 'img',
237+
inlineCode: 'code',
238+
link: 'a',
239+
linkReference: 'a',
240+
listItem: 'li',
241+
paragraph: 'p',
242+
strong: 'strong',
243+
table: 'table',
244+
tableCell: 'td',
245+
tableRow: 'tr',
246+
thematicBreak: 'hr'
247+
}
248+
/**
249+
* Get the JSX node names for a given AST node.
250+
* @param {Nodes} node
251+
* @returns {string[]}
252+
*/
253+
function getJsxNodeNameForMdast(node) {
254+
if (node.type === 'code') {
255+
return ['pre', 'code']
256+
}
257+
258+
if (node.type === 'heading') {
259+
return ['h' + node.depth]
260+
}
261+
262+
if (node.type === 'list') {
263+
return node.ordered ? ['ol'] : ['ul']
264+
}
265+
266+
if (mdastElementNodeNameMap[node.type]) {
267+
return [/** @type string */ (mdastElementNodeNameMap[node.type])]
268+
}
269+
270+
// JSX Fragment
271+
return ['']
272+
}
273+
228274
/**
229275
* @param {string} mdx
230276
* @param {Root} ast
@@ -739,7 +785,11 @@ function getEmbeddedCodes(
739785
}
740786

741787
default: {
742-
jsx += jsxIndent + '<>'
788+
jsx +=
789+
jsxIndent +
790+
getJsxNodeNameForMdast(node)
791+
.map((name) => `<${name}>`)
792+
.join('')
743793
break
744794
}
745795
}
@@ -789,7 +839,12 @@ function getEmbeddedCodes(
789839
}
790840

791841
default: {
792-
jsx += jsxIndent + '</>'
842+
jsx +=
843+
jsxIndent +
844+
getJsxNodeNameForMdast(node)
845+
.reverse()
846+
.map((name) => `</${name}>`)
847+
.join('')
793848
break
794849
}
795850
}

packages/language-service/test/language-plugin.js

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2042,7 +2042,7 @@ test('create virtual code w/ prefixed JSX expressions in attributes', () => {
20422042
},
20432043
{
20442044
sourceOffsets: [28, 62, 103, 149, 166, 214],
2045-
generatedOffsets: [870, 916, 960, 1018, 1047, 1111],
2045+
generatedOffsets: [870, 916, 960, 1018, 1047, 1113],
20462046
lengths: [34, 39, 46, 17, 35, 6],
20472047
data: {
20482048
completion: true,
@@ -2054,7 +2054,7 @@ test('create virtual code w/ prefixed JSX expressions in attributes', () => {
20542054
}
20552055
},
20562056
{
2057-
generatedOffsets: [1551, 1574],
2057+
generatedOffsets: [1553, 1576],
20582058
lengths: [8, 8],
20592059
sourceOffsets: [62, 149],
20602060
data: {
@@ -2099,9 +2099,9 @@ test('create virtual code w/ prefixed JSX expressions in attributes', () => {
20992099
' return <>',
21002100
' <div local={<Local />} injected={<_components.Injected />} string="string" boolean />',
21012101
' <div local={<Local>{null}</Local>} injected={<_components.Injected>{null}</_components.Injected>} string="string" boolean>',
2102-
' <>',
2102+
' <p>',
21032103
" {''}",
2104-
' </>',
2104+
' </p>',
21052105
' </div>',
21062106
' </>',
21072107
'}',
@@ -2224,7 +2224,7 @@ test('create virtual code w/ mdxJsxFlowElement w/ children', () => {
22242224
},
22252225
{
22262226
sourceOffsets: [28, 87, 94, 95, 158, 160, 170, 231],
2227-
generatedOffsets: [870, 904, 915, 928, 966, 980, 994, 1030],
2227+
generatedOffsets: [870, 906, 917, 930, 970, 984, 998, 1036],
22282228
lengths: [5, 6, 1, 9, 2, 9, 7, 8],
22292229
data: {
22302230
completion: true,
@@ -2244,7 +2244,7 @@ test('create virtual code w/ mdxJsxFlowElement w/ children', () => {
22442244
structure: true,
22452245
verification: true
22462246
},
2247-
generatedOffsets: [1472],
2247+
generatedOffsets: [1478],
22482248
lengths: [8],
22492249
sourceOffsets: [95]
22502250
}
@@ -2280,19 +2280,19 @@ test('create virtual code w/ mdxJsxFlowElement w/ children', () => {
22802280
' _components',
22812281
' return <>',
22822282
' <div>',
2283-
' <>',
2283+
' <p>',
22842284
" {''}",
2285-
' </>',
2285+
' </p>',
22862286
' </div>',
22872287
' <_components.Injected>',
2288-
' <>',
2288+
' <p>',
22892289
" {''}",
2290-
' </>',
2290+
' </p>',
22912291
' </_components.Injected>',
22922292
' <Local>',
2293-
' <>',
2293+
' <p>',
22942294
" {''}",
2295-
' </>',
2295+
' </p>',
22962296
' </Local>',
22972297
' </>',
22982298
'}',
@@ -2405,7 +2405,7 @@ test('create virtual code w/ mdxJsxFlowElement w/ blockquote child', () => {
24052405
},
24062406
{
24072407
sourceOffsets: [0, 8, 15, 21],
2408-
generatedOffsets: [806, 831, 849, 868],
2408+
generatedOffsets: [806, 851, 870, 889],
24092409
lengths: [5, 6, 5, 6],
24102410
data: {
24112411
completion: true,
@@ -2444,14 +2444,14 @@ test('create virtual code w/ mdxJsxFlowElement w/ blockquote child', () => {
24442444
' _components',
24452445
' return <>',
24462446
' <div>',
2447-
' <>',
2448-
' </>',
2447+
' <blockquote>',
2448+
' </blockquote>',
24492449
' </div>',
2450-
' <>',
2450+
' <p>',
24512451
' <div>',
24522452
" {''}",
24532453
' </div>',
2454-
' </>',
2454+
' </p>',
24552455
' </>',
24562456
'}',
24572457
'',
@@ -2706,7 +2706,7 @@ test('create virtual code w/ mdxJsxTextElement', () => {
27062706
},
27072707
{
27082708
sourceOffsets: [30, 41, 42, 56],
2709-
generatedOffsets: [886, 907, 920, 945],
2709+
generatedOffsets: [887, 908, 921, 946],
27102710
lengths: [7, 1, 11, 9],
27112711
data: {
27122712
completion: true,
@@ -2718,7 +2718,7 @@ test('create virtual code w/ mdxJsxTextElement', () => {
27182718
}
27192719
},
27202720
{
2721-
generatedOffsets: [1396],
2721+
generatedOffsets: [1398],
27222722
lengths: [8],
27232723
sourceOffsets: [42],
27242724
data: {
@@ -2761,14 +2761,14 @@ test('create virtual code w/ mdxJsxTextElement', () => {
27612761
' }',
27622762
' _components',
27632763
' return <>',
2764-
' <>',
2764+
' <p>',
27652765
" {''}",
27662766
' <div />',
27672767
" {''}",
27682768
' <_components.Injected />',
27692769
" {''}",
27702770
' <Local />',
2771-
' </>',
2771+
' </p>',
27722772
' </>',
27732773
'}',
27742774
'',
@@ -2867,7 +2867,7 @@ test('create virtual code w/ mdxTextExpression', () => {
28672867
}
28682868
},
28692869
{
2870-
generatedOffsets: [822],
2870+
generatedOffsets: [823],
28712871
sourceOffsets: [4],
28722872
lengths: [9],
28732873
data: {
@@ -2906,11 +2906,11 @@ test('create virtual code w/ mdxTextExpression', () => {
29062906
' }',
29072907
' _components',
29082908
' return <>',
2909-
' <>',
2909+
' <p>',
29102910
" {''}",
29112911
' {Math.PI}',
29122912
" {''}",
2913-
' </>',
2913+
' </p>',
29142914
' </>',
29152915
'}',
29162916
'',
@@ -3003,7 +3003,7 @@ test('create virtual code w/ async mdxTextExpression', () => {
30033003
}
30043004
},
30053005
{
3006-
generatedOffsets: [828],
3006+
generatedOffsets: [829],
30073007
sourceOffsets: [4],
30083008
lengths: [32],
30093009
data: {
@@ -3042,11 +3042,11 @@ test('create virtual code w/ async mdxTextExpression', () => {
30423042
' }',
30433043
' _components',
30443044
' return <>',
3045-
' <>',
3045+
' <p>',
30463046
" {''}",
30473047
' {await Promise.resolve(Math.PI)}',
30483048
" {''}",
3049-
' </>',
3049+
' </p>',
30503050
' </>',
30513051
'}',
30523052
'',
@@ -3476,9 +3476,9 @@ test('create virtual code w/ dedented markdown content', () => {
34763476
' }',
34773477
' _components',
34783478
' return <>',
3479-
' <>',
3479+
' <p>',
34803480
" {''}",
3481-
' </>',
3481+
' </p>',
34823482
' </>',
34833483
'}',
34843484
'',
@@ -3830,9 +3830,9 @@ test('update virtual code', () => {
38303830
' }',
38313831
' _components',
38323832
' return <>',
3833-
' <>',
3833+
' <p>',
38343834
" {''}",
3835-
' </>',
3835+
' </p>',
38363836
' </>',
38373837
'}',
38383838
'',
@@ -5242,9 +5242,9 @@ test('rehype-mdx-title matching rank', () => {
52425242
' }',
52435243
' _components',
52445244
' return <>',
5245-
' <>',
5245+
' <h1>',
52465246
" {''}",
5247-
' </>',
5247+
' </h1>',
52485248
' </>',
52495249
'}',
52505250
'',

0 commit comments

Comments
 (0)