Skip to content

Commit f6ca465

Browse files
committed
Add elements to mdast node type registry
When using this utility, the element types will automatically be added to mdast in the correct places. See DefinitelyTyped/DefinitelyTyped#54421 for more information.
1 parent dd3dfae commit f6ca465

File tree

5 files changed

+136
-99
lines changed

5 files changed

+136
-99
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
coverage/
22
node_modules/
3-
*.d.ts
3+
index.d.ts
4+
test.d.ts
45
*.log
56
.DS_Store
67
yarn.lock

complex-types.d.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import {Node} from 'unist'
2+
import {Parent, Literal, BlockContent, PhrasingContent} from 'mdast'
3+
import {Program} from 'estree-jsx'
4+
5+
export interface MDXJsxAttributeValueExpression extends Literal {
6+
type: 'mdxJsxAttributeValueExpression'
7+
data?: {estree?: Program} & Literal['data']
8+
}
9+
10+
export interface MDXJsxAttribute extends Node {
11+
type: 'mdxJsxAttribute'
12+
name: string
13+
value?: MDXJsxAttributeValueExpression | string | null
14+
}
15+
16+
export interface MDXJsxExpressionAttribute extends Literal {
17+
type: 'mdxJsxExpressionAttribute'
18+
data?: {estree?: Program} & Literal['data']
19+
}
20+
21+
interface MDXJsxElementFields {
22+
name: string | null
23+
attributes: Array<MDXJsxAttribute | MDXJsxExpressionAttribute>
24+
}
25+
26+
export interface MDXJsxFlowElement extends MDXJsxElementFields, Parent {
27+
type: 'mdxJsxFlowElement'
28+
children: BlockContent[]
29+
}
30+
31+
export interface MDXJsxTextElement extends MDXJsxElementFields, Parent {
32+
type: 'mdxJsxTextElement'
33+
children: PhrasingContent[]
34+
}
35+
36+
declare module 'mdast' {
37+
interface StaticPhrasingContentMap {
38+
mdxJsxTextElement: MDXJsxTextElement
39+
}
40+
41+
interface BlockContentMap {
42+
mdxJsxFlowElement: MDXJsxFlowElement
43+
}
44+
}

index.js

Lines changed: 52 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,13 @@
66
* @typedef {import('mdast-util-from-markdown').Token} Token
77
* @typedef {import('mdast-util-to-markdown').Options} ToMarkdownExtension
88
* @typedef {import('mdast-util-to-markdown').Handle} ToMarkdownHandle
9-
* @typedef {import('estree-jsx').Program} Estree
10-
*
11-
* @typedef {Literal & {type: 'mdxJsxAttributeValueExpression', data?: {estree?: Estree}}} MDXJsxAttributeValueExpression
12-
* @typedef {Omit<Literal, 'value'> & {type: 'mdxJsxAttribute', name: string, value: MDXJsxAttributeValueExpression|string|null}} MDXJsxAttribute
13-
* @typedef {Literal & {type: 'mdxJsxExpressionAttribute'}} MDXJsxExpressionAttribute
14-
* @typedef {MDXJsxAttribute|MDXJsxExpressionAttribute} Attribute
15-
* @typedef {{name: string|null, attributes: Attribute[], close?: boolean, selfClosing?: boolean, start: Token['start'], end: Token['start']}} Tag
16-
*
17-
* @typedef {{name: string|null, attributes: Attribute[]}} MDXJsxElement
18-
* @typedef {Parent & MDXJsxElement & {type: 'mdxJsxFlowElement'}} MDXJsxFlowElement
19-
* @typedef {Parent & MDXJsxElement & {type: 'mdxJsxTextElement'}} MDXJsxTextElement
9+
* @typedef {import('estree-jsx').Program} Program
10+
* @typedef {import('./complex-types').MDXJsxAttributeValueExpression} MDXJsxAttributeValueExpression
11+
* @typedef {import('./complex-types').MDXJsxAttribute} MDXJsxAttribute
12+
* @typedef {import('./complex-types').MDXJsxExpressionAttribute} MDXJsxExpressionAttribute
13+
* @typedef {import('./complex-types').MDXJsxFlowElement} MDXJsxFlowElement
14+
* @typedef {import('./complex-types').MDXJsxTextElement} MDXJsxTextElement
15+
* @typedef {{name: string|null, attributes: (MDXJsxAttribute|MDXJsxExpressionAttribute)[], close?: boolean, selfClosing?: boolean, start: Token['start'], end: Token['start']}} Tag
2016
*/
2117

2218
import {parseEntities} from 'parse-entities'
@@ -122,9 +118,7 @@ function enterMdxJsxTag(token) {
122118

123119
/** @type {FromMarkdownHandle} */
124120
function enterMdxJsxTagClosingMarker(token) {
125-
/** @type {Tag[]} */
126-
// @ts-expect-error: hush
127-
const stack = this.getData('mdxJsxTagStack')
121+
const stack = /** @type {Tag[]} */ (this.getData('mdxJsxTagStack'))
128122

129123
if (stack.length === 0) {
130124
throw new VFileMessage(
@@ -137,9 +131,7 @@ function enterMdxJsxTagClosingMarker(token) {
137131

138132
/** @type {FromMarkdownHandle} */
139133
function enterMdxJsxTagAnyAttribute(token) {
140-
/** @type {Tag} */
141-
// @ts-expect-error: hush
142-
const tag = this.getData('mdxJsxTag')
134+
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
143135

144136
if (tag.close) {
145137
throw new VFileMessage(
@@ -152,9 +144,7 @@ function enterMdxJsxTagAnyAttribute(token) {
152144

153145
/** @type {FromMarkdownHandle} */
154146
function enterMdxJsxTagSelfClosingMarker(token) {
155-
/** @type {Tag} */
156-
// @ts-expect-error: hush
157-
const tag = this.getData('mdxJsxTag')
147+
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
158148

159149
if (tag.close) {
160150
throw new VFileMessage(
@@ -167,64 +157,50 @@ function enterMdxJsxTagSelfClosingMarker(token) {
167157

168158
/** @type {FromMarkdownHandle} */
169159
function exitMdxJsxTagClosingMarker() {
170-
/** @type {Tag} */
171-
// @ts-expect-error: hush
172-
const tag = this.getData('mdxJsxTag')
160+
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
173161
tag.close = true
174162
}
175163

176164
/** @type {FromMarkdownHandle} */
177165
function exitMdxJsxTagNamePrimary(token) {
178-
/** @type {Tag} */
179-
// @ts-expect-error: hush
180-
const tag = this.getData('mdxJsxTag')
166+
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
181167
tag.name = this.sliceSerialize(token)
182168
}
183169

184170
/** @type {FromMarkdownHandle} */
185171
function exitMdxJsxTagNameMember(token) {
186-
/** @type {Tag} */
187-
// @ts-expect-error: hush
188-
const tag = this.getData('mdxJsxTag')
172+
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
189173
tag.name += '.' + this.sliceSerialize(token)
190174
}
191175

192176
/** @type {FromMarkdownHandle} */
193177
function exitMdxJsxTagNameLocal(token) {
194-
/** @type {Tag} */
195-
// @ts-expect-error: hush
196-
const tag = this.getData('mdxJsxTag')
178+
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
197179
tag.name += ':' + this.sliceSerialize(token)
198180
}
199181

200182
/** @type {FromMarkdownHandle} */
201183
function enterMdxJsxTagAttribute(token) {
202-
/** @type {Tag} */
203-
// @ts-expect-error: hush
204-
const tag = this.getData('mdxJsxTag')
184+
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
205185
enterMdxJsxTagAnyAttribute.call(this, token)
206186
tag.attributes.push({type: 'mdxJsxAttribute', name: '', value: null})
207187
}
208188

209189
/** @type {FromMarkdownHandle} */
210190
function enterMdxJsxTagExpressionAttribute(token) {
211-
/** @type {Tag} */
212-
// @ts-expect-error: hush
213-
const tag = this.getData('mdxJsxTag')
191+
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
214192
enterMdxJsxTagAnyAttribute.call(this, token)
215193
tag.attributes.push({type: 'mdxJsxExpressionAttribute', value: ''})
216194
this.buffer()
217195
}
218196

219197
/** @type {FromMarkdownHandle} */
220198
function exitMdxJsxTagExpressionAttribute(token) {
221-
/** @type {Tag} */
222-
// @ts-expect-error: hush
223-
const tag = this.getData('mdxJsxTag')
224-
/** @type {MDXJsxExpressionAttribute} */
225-
// @ts-expect-error: hush
226-
const tail = tag.attributes[tag.attributes.length - 1]
227-
/** @type {Estree?} */
199+
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
200+
const tail = /** @type {MDXJsxExpressionAttribute} */ (
201+
tag.attributes[tag.attributes.length - 1]
202+
)
203+
/** @type {Program|undefined} */
228204
// @ts-expect-error: custom.
229205
const estree = token.estree
230206

@@ -237,26 +213,25 @@ function exitMdxJsxTagExpressionAttribute(token) {
237213

238214
/** @type {FromMarkdownHandle} */
239215
function exitMdxJsxTagAttributeNamePrimary(token) {
240-
/** @type {Tag} */
241-
// @ts-expect-error: hush
242-
const tag = this.getData('mdxJsxTag')
243-
tag.attributes[tag.attributes.length - 1].name = this.sliceSerialize(token)
216+
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
217+
const node = /** @type {MDXJsxAttribute} */ (
218+
tag.attributes[tag.attributes.length - 1]
219+
)
220+
node.name = this.sliceSerialize(token)
244221
}
245222

246223
/** @type {FromMarkdownHandle} */
247224
function exitMdxJsxTagAttributeNameLocal(token) {
248-
/** @type {Tag} */
249-
// @ts-expect-error: hush
250-
const tag = this.getData('mdxJsxTag')
251-
tag.attributes[tag.attributes.length - 1].name +=
252-
':' + this.sliceSerialize(token)
225+
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
226+
const node = /** @type {MDXJsxAttribute} */ (
227+
tag.attributes[tag.attributes.length - 1]
228+
)
229+
node.name += ':' + this.sliceSerialize(token)
253230
}
254231

255232
/** @type {FromMarkdownHandle} */
256233
function exitMdxJsxTagAttributeValueLiteral() {
257-
/** @type {Tag} */
258-
// @ts-expect-error: hush
259-
const tag = this.getData('mdxJsxTag')
234+
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
260235
tag.attributes[tag.attributes.length - 1].value = parseEntities(
261236
this.resume(),
262237
{nonTerminated: false}
@@ -265,15 +240,13 @@ function exitMdxJsxTagAttributeValueLiteral() {
265240

266241
/** @type {FromMarkdownHandle} */
267242
function exitMdxJsxTagAttributeValueExpression(token) {
268-
/** @type {Tag} */
269-
// @ts-expect-error: hush
270-
const tag = this.getData('mdxJsxTag')
271-
/** @type {MDXJsxAttribute} */
272-
// @ts-expect-error: hush
273-
const tail = tag.attributes[tag.attributes.length - 1]
243+
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
244+
const tail = /** @type {MDXJsxAttribute} */ (
245+
tag.attributes[tag.attributes.length - 1]
246+
)
274247
/** @type {MDXJsxAttributeValueExpression} */
275248
const node = {type: 'mdxJsxAttributeValueExpression', value: this.resume()}
276-
/** @type {Estree?} */
249+
/** @type {Program|undefined} */
277250
// @ts-expect-error: custom.
278251
const estree = token.estree
279252

@@ -286,21 +259,15 @@ function exitMdxJsxTagAttributeValueExpression(token) {
286259

287260
/** @type {FromMarkdownHandle} */
288261
function exitMdxJsxTagSelfClosingMarker() {
289-
/** @type {Tag} */
290-
// @ts-expect-error: hush
291-
const tag = this.getData('mdxJsxTag')
262+
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
292263

293264
tag.selfClosing = true
294265
}
295266

296267
/** @type {FromMarkdownHandle} */
297268
function exitMdxJsxTag(token) {
298-
/** @type {Tag} */
299-
// @ts-expect-error: hush
300-
const tag = this.getData('mdxJsxTag')
301-
/** @type {Tag[]} */
302-
// @ts-expect-error: hush
303-
const stack = this.getData('mdxJsxTagStack')
269+
const tag = /** @type {Tag} */ (this.getData('mdxJsxTag'))
270+
const stack = /** @type {Tag[]} */ (this.getData('mdxJsxTagStack'))
304271
const tail = stack[stack.length - 1]
305272

306273
if (tag.close && tail.name !== tag.name) {
@@ -323,19 +290,18 @@ function exitMdxJsxTag(token) {
323290
if (tag.close) {
324291
stack.pop()
325292
} else {
326-
/** @type {MDXJsxFlowElement|MDXJsxTextElement} */
327-
const node = {
328-
type:
329-
token.type === 'mdxJsxTextTag'
330-
? 'mdxJsxTextElement'
331-
: 'mdxJsxFlowElement',
332-
name: tag.name,
333-
attributes: tag.attributes,
334-
children: []
335-
}
336-
337-
// @ts-expect-error: custom
338-
this.enter(node, token)
293+
this.enter(
294+
{
295+
type:
296+
token.type === 'mdxJsxTextTag'
297+
? 'mdxJsxTextElement'
298+
: 'mdxJsxFlowElement',
299+
name: tag.name,
300+
attributes: tag.attributes,
301+
children: []
302+
},
303+
token
304+
)
339305
}
340306

341307
if (tag.selfClosing || tag.close) {

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,13 @@
3131
"main": "index.js",
3232
"types": "index.d.ts",
3333
"files": [
34+
"complex-types.d.ts",
3435
"index.d.ts",
3536
"index.js"
3637
],
3738
"dependencies": {
3839
"@types/estree-jsx": "^0.0.1",
39-
"@types/mdast": "^3.0.3",
40+
"@types/mdast": "^3.0.0",
4041
"mdast-util-to-markdown": "^1.0.0",
4142
"parse-entities": "^3.0.0",
4243
"stringify-entities": "^4.0.0",
@@ -60,7 +61,7 @@
6061
"xo": "^0.39.0"
6162
},
6263
"scripts": {
63-
"build": "rimraf \"*.d.ts\" && tsc && type-coverage",
64+
"build": "rimraf \"{index,test}.d.ts\" && tsc && type-coverage",
6465
"format": "remark . -qfo && prettier . -w --loglevel warn && xo --fix",
6566
"test-api": "node --conditions development test.js",
6667
"test-coverage": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 --reporter lcov node --conditions development test.js",

0 commit comments

Comments
 (0)