Skip to content

Commit fea30c0

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

File tree

5 files changed

+76
-40
lines changed

5 files changed

+76
-40
lines changed

Diff for: .gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
coverage/
22
node_modules/
33
.DS_Store
4-
*.d.ts
4+
index.d.ts
5+
test.d.ts
56
*.log
67
yarn.lock

Diff for: complex-types.d.ts

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import type {Literal} from 'mdast'
2+
3+
export interface Math extends Literal {
4+
type: 'math'
5+
lang?: string | null
6+
meta?: string | null
7+
}
8+
9+
export interface InlineMath extends Literal {
10+
type: 'inlineMath'
11+
}
12+
13+
declare module 'mdast' {
14+
interface StaticPhrasingContentMap {
15+
inlineMath: InlineMath
16+
}
17+
18+
interface BlockContentMap {
19+
math: Math
20+
}
21+
}

Diff for: index.js

+32-35
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
/**
2-
* @typedef {import('mdast').Literal} Literal
32
* @typedef {import('mdast-util-from-markdown').Extension} FromMarkdownExtension
43
* @typedef {import('mdast-util-from-markdown').Handle} FromMarkdownHandle
54
* @typedef {import('mdast-util-to-markdown').Options} ToMarkdownExtension
65
* @typedef {import('mdast-util-to-markdown').Handle} ToMarkdownHandle
7-
*
8-
* @typedef {Literal & {type: 'math', lang?: string|null, meta?: string|null}} Math
9-
* @typedef {Literal & {type: 'inlineMath'}} InlineMath
6+
* @typedef {import('./complex-types').Math} Math
7+
* @typedef {import('./complex-types').InlineMath} InlineMath
108
*/
119

1210
import {longestStreak} from 'longest-streak'
@@ -44,19 +42,19 @@ inlineMath.peek = inlineMathPeek
4442

4543
/** @type {FromMarkdownHandle} */
4644
function enterMathFlow(token) {
47-
/** @type {Math} */
48-
const node = {
49-
type: 'math',
50-
meta: null,
51-
value: '',
52-
data: {
53-
hName: 'div',
54-
hProperties: {className: ['math', 'math-display']},
55-
hChildren: [{type: 'text', value: ''}]
56-
}
57-
}
58-
// @ts-expect-error: custom node.
59-
this.enter(node, token)
45+
this.enter(
46+
{
47+
type: 'math',
48+
meta: null,
49+
value: '',
50+
data: {
51+
hName: 'div',
52+
hProperties: {className: ['math', 'math-display']},
53+
hChildren: [{type: 'text', value: ''}]
54+
}
55+
},
56+
token
57+
)
6058
}
6159

6260
/** @type {FromMarkdownHandle} */
@@ -67,7 +65,8 @@ function enterMathFlowMeta() {
6765
/** @type {FromMarkdownHandle} */
6866
function exitMathFlowMeta() {
6967
const data = this.resume()
70-
this.stack[this.stack.length - 1].meta = data
68+
const node = /** @type {Math} */ (this.stack[this.stack.length - 1])
69+
node.meta = data
7170
}
7271

7372
/** @type {FromMarkdownHandle} */
@@ -81,7 +80,7 @@ function exitMathFlowFence() {
8180
/** @type {FromMarkdownHandle} */
8281
function exitMathFlow(token) {
8382
const data = this.resume().replace(/^(\r?\n|\r)|(\r?\n|\r)$/g, '')
84-
const node = this.exit(token)
83+
const node = /** @type {Math} */ (this.exit(token))
8584
node.value = data
8685
// @ts-expect-error: we defined it.
8786
node.data.hChildren[0].value = data
@@ -90,25 +89,25 @@ function exitMathFlow(token) {
9089

9190
/** @type {FromMarkdownHandle} */
9291
function enterMathText(token) {
93-
/** @type {InlineMath} */
94-
const node = {
95-
type: 'inlineMath',
96-
value: '',
97-
data: {
98-
hName: 'span',
99-
hProperties: {className: ['math', 'math-inline']},
100-
hChildren: [{type: 'text', value: ''}]
101-
}
102-
}
103-
// @ts-expect-error: custom node.
104-
this.enter(node, token)
92+
this.enter(
93+
{
94+
type: 'inlineMath',
95+
value: '',
96+
data: {
97+
hName: 'span',
98+
hProperties: {className: ['math', 'math-inline']},
99+
hChildren: [{type: 'text', value: ''}]
100+
}
101+
},
102+
token
103+
)
105104
this.buffer()
106105
}
107106

108107
/** @type {FromMarkdownHandle} */
109108
function exitMathText(token) {
110109
const data = this.resume()
111-
const node = this.exit(token)
110+
const node = /** @type {Math} */ (this.exit(token))
112111
node.value = data
113112
// @ts-expect-error: we defined it.
114113
node.data.hChildren[0].value = data
@@ -129,11 +128,9 @@ function math(node, _, context) {
129128
const fence = '$'.repeat(Math.max(longestStreak(raw, '$') + 1, 2))
130129
const exit = context.enter('mathFlow')
131130
let value = fence
132-
/** @type {ReturnType<context['enter']>} */
133-
let subexit
134131

135132
if (node.meta) {
136-
subexit = context.enter('mathFlowMeta')
133+
const subexit = context.enter('mathFlowMeta')
137134
value += safe(context, node.meta, {before: '$', after: ' ', encode: ['$']})
138135
subexit()
139136
}

Diff for: package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"main": "index.js",
3232
"types": "index.d.ts",
3333
"files": [
34+
"complex-types.d.ts",
3435
"index.d.ts",
3536
"index.js"
3637
],
@@ -54,7 +55,7 @@
5455
"xo": "^0.39.0"
5556
},
5657
"scripts": {
57-
"build": "rimraf \"*.d.ts\" && tsc && type-coverage",
58+
"build": "rimraf \"{index,test}.d.ts\" && tsc && type-coverage",
5859
"format": "remark . -qfo && prettier . -w --loglevel warn && xo --fix",
5960
"test-api": "node --conditions development test.js",
6061
"test-coverage": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 --reporter lcov node --conditions development test.js",

Diff for: test.js

+19-3
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ test('mdast -> markdown', (t) => {
148148
)
149149

150150
t.deepEqual(
151+
// @ts-expect-error: `value` missing.
151152
toMarkdown({type: 'inlineMath'}, {extensions: [mathToMarkdown]}),
152153
'$$\n',
153154
'should serialize math (text) w/o `value`'
@@ -187,12 +188,14 @@ test('mdast -> markdown', (t) => {
187188
)
188189

189190
t.deepEqual(
191+
// @ts-expect-error: `value` missing.
190192
toMarkdown({type: 'math'}, {extensions: [mathToMarkdown]}),
191193
'$$\n$$\n',
192194
'should serialize math (flow) w/o `value`'
193195
)
194196

195197
t.deepEqual(
198+
// @ts-expect-error: `value` missing.
196199
toMarkdown({type: 'math', meta: 'a'}, {extensions: [mathToMarkdown]}),
197200
'$$a\n$$\n',
198201
'should serialize math (flow) w/ `meta`'
@@ -205,6 +208,7 @@ test('mdast -> markdown', (t) => {
205208
)
206209

207210
t.deepEqual(
211+
// @ts-expect-error: `value` missing.
208212
toMarkdown({type: 'math', meta: 'a'}, {extensions: [mathToMarkdown]}),
209213
'$$a\n$$\n',
210214
'should serialize math (flow) w/ `meta`'
@@ -237,21 +241,33 @@ test('mdast -> markdown', (t) => {
237241

238242
t.deepEqual(
239243
toMarkdown(
240-
{type: 'definition', label: 'a', url: 'b', title: 'a\n$\nb'},
244+
{
245+
type: 'definition',
246+
label: 'a',
247+
identifier: 'a',
248+
url: 'b',
249+
title: 'a\n$\nb'
250+
},
241251
{extensions: [mathToMarkdown]}
242252
),
243253
'[a]: b "a\n$\nb"\n',
244254
'should not escape `$` at the start of a line'
245255
)
246256

247257
t.deepEqual(
248-
toMarkdown({type: 'math', meta: 'a\rb\nc'}, {extensions: [mathToMarkdown]}),
258+
toMarkdown(
259+
{type: 'math', meta: 'a\rb\nc', value: ''},
260+
{extensions: [mathToMarkdown]}
261+
),
249262
'$$a&#xD;b\nc\n$$\n',
250263
'should escape `\\r`, `\\n` when in `meta` of math (flow)'
251264
)
252265

253266
t.deepEqual(
254-
toMarkdown({type: 'math', meta: 'a$b'}, {extensions: [mathToMarkdown]}),
267+
toMarkdown(
268+
{type: 'math', meta: 'a$b', value: ''},
269+
{extensions: [mathToMarkdown]}
270+
),
255271
'$$a&#x24;b\n$$\n',
256272
'should escape `$` when in `meta` of math (flow)'
257273
)

0 commit comments

Comments
 (0)