Skip to content

Commit 19301e7

Browse files
committed
Add containerPhrasing, containerFlow helpers on state
1 parent a638e2a commit 19301e7

15 files changed

+132
-52
lines changed

lib/handle/blockquote.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
* @typedef {import('../types.js').Map} Map
77
*/
88

9-
import {containerFlow} from '../util/container-flow.js'
109
import {track} from '../util/track.js'
1110

1211
/**
@@ -22,7 +21,7 @@ export function blockquote(node, _, state, info) {
2221
tracker.move('> ')
2322
tracker.shift(2)
2423
const value = state.indentLines(
25-
containerFlow(node, state, tracker.current()),
24+
state.containerFlow(node, tracker.current()),
2625
map
2726
)
2827
exit()

lib/handle/emphasis.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
*/
77

88
import {checkEmphasis} from '../util/check-emphasis.js'
9-
import {containerPhrasing} from '../util/container-phrasing.js'
109
import {track} from '../util/track.js'
1110

1211
emphasis.peek = emphasisPeek
@@ -28,7 +27,7 @@ export function emphasis(node, _, state, info) {
2827
const tracker = track(info)
2928
let value = tracker.move(marker)
3029
value += tracker.move(
31-
containerPhrasing(node, state, {
30+
state.containerPhrasing(node, {
3231
before: value,
3332
after: marker,
3433
...tracker.current()

lib/handle/heading.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
*/
77

88
import {formatHeadingAsSetext} from '../util/format-heading-as-setext.js'
9-
import {containerPhrasing} from '../util/container-phrasing.js'
109
import {track} from '../util/track.js'
1110

1211
/**
@@ -23,7 +22,7 @@ export function heading(node, _, state, info) {
2322
if (formatHeadingAsSetext(node, state)) {
2423
const exit = state.enter('headingSetext')
2524
const subexit = state.enter('phrasing')
26-
const value = containerPhrasing(node, state, {
25+
const value = state.containerPhrasing(node, {
2726
...tracker.current(),
2827
before: '\n',
2928
after: '\n'
@@ -54,7 +53,7 @@ export function heading(node, _, state, info) {
5453
// we’ve tracked one too many characters.
5554
tracker.move(sequence + ' ')
5655

57-
let value = containerPhrasing(node, state, {
56+
let value = state.containerPhrasing(node, {
5857
before: '# ',
5958
after: '\n',
6059
...tracker.current()

lib/handle/link-reference.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
*/
77

88
import {association} from '../util/association.js'
9-
import {containerPhrasing} from '../util/container-phrasing.js'
109
import {safe} from '../util/safe.js'
1110
import {track} from '../util/track.js'
1211

@@ -25,7 +24,7 @@ export function linkReference(node, _, state, info) {
2524
let subexit = state.enter('label')
2625
const tracker = track(info)
2726
let value = tracker.move('[')
28-
const text = containerPhrasing(node, state, {
27+
const text = state.containerPhrasing(node, {
2928
before: value,
3029
after: ']',
3130
...tracker.current()

lib/handle/link.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
import {checkQuote} from '../util/check-quote.js'
1010
import {formatLinkAsAutolink} from '../util/format-link-as-autolink.js'
11-
import {containerPhrasing} from '../util/container-phrasing.js'
1211
import {safe} from '../util/safe.js'
1312
import {track} from '../util/track.js'
1413

@@ -37,7 +36,7 @@ export function link(node, _, state, info) {
3736
exit = state.enter('autolink')
3837
let value = tracker.move('<')
3938
value += tracker.move(
40-
containerPhrasing(node, state, {
39+
state.containerPhrasing(node, {
4140
before: value,
4241
after: '>',
4342
...tracker.current()
@@ -53,7 +52,7 @@ export function link(node, _, state, info) {
5352
subexit = state.enter('label')
5453
let value = tracker.move('[')
5554
value += tracker.move(
56-
containerPhrasing(node, state, {
55+
state.containerPhrasing(node, {
5756
before: value,
5857
after: '](',
5958
...tracker.current()

lib/handle/list-item.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
import {checkBullet} from '../util/check-bullet.js'
1010
import {checkListItemIndent} from '../util/check-list-item-indent.js'
11-
import {containerFlow} from '../util/container-flow.js'
1211
import {track} from '../util/track.js'
1312

1413
/**
@@ -49,7 +48,7 @@ export function listItem(node, parent, state, info) {
4948
tracker.shift(size)
5049
const exit = state.enter('listItem')
5150
const value = state.indentLines(
52-
containerFlow(node, state, tracker.current()),
51+
state.containerFlow(node, tracker.current()),
5352
map
5453
)
5554
exit()

lib/handle/list.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
* @typedef {import('../types.js').Info} Info
66
*/
77

8-
import {containerFlow} from '../util/container-flow.js'
98
import {checkBullet} from '../util/check-bullet.js'
109
import {checkBulletOther} from '../util/check-bullet-other.js'
1110
import {checkBulletOrdered} from '../util/check-bullet-ordered.js'
@@ -106,7 +105,7 @@ export function list(node, parent, state, info) {
106105
}
107106

108107
state.bulletCurrent = bullet
109-
const value = containerFlow(node, state, info)
108+
const value = state.containerFlow(node, info)
110109
state.bulletLastUsed = bullet
111110
state.bulletCurrent = bulletCurrent
112111
exit()

lib/handle/paragraph.js

+1-3
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
* @typedef {import('../types.js').Info} Info
66
*/
77

8-
import {containerPhrasing} from '../util/container-phrasing.js'
9-
108
/**
119
* @param {Paragraph} node
1210
* @param {Parent | undefined} _
@@ -17,7 +15,7 @@ import {containerPhrasing} from '../util/container-phrasing.js'
1715
export function paragraph(node, _, state, info) {
1816
const exit = state.enter('paragraph')
1917
const subexit = state.enter('phrasing')
20-
const value = containerPhrasing(node, state, info)
18+
const value = state.containerPhrasing(node, info)
2119
subexit()
2220
exit()
2321
return value

lib/handle/root.js

+2-4
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
*/
77

88
import {phrasing} from 'mdast-util-phrasing'
9-
import {containerFlow} from '../util/container-flow.js'
10-
import {containerPhrasing} from '../util/container-phrasing.js'
119

1210
/**
1311
* @param {Root} node
@@ -19,7 +17,7 @@ import {containerPhrasing} from '../util/container-phrasing.js'
1917
export function root(node, _, state, info) {
2018
// Note: `html` nodes are ambiguous.
2119
const hasPhrasing = node.children.some((d) => phrasing(d))
22-
const fn = hasPhrasing ? containerPhrasing : containerFlow
20+
const fn = hasPhrasing ? state.containerPhrasing : state.containerFlow
2321
// @ts-expect-error: `root`s are supposed to have one type of content
24-
return fn(node, state, info)
22+
return fn.call(state, node, info)
2523
}

lib/handle/strong.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
*/
77

88
import {checkStrong} from '../util/check-strong.js'
9-
import {containerPhrasing} from '../util/container-phrasing.js'
109
import {track} from '../util/track.js'
1110

1211
strong.peek = strongPeek
@@ -28,7 +27,7 @@ export function strong(node, _, state, info) {
2827
const tracker = track(info)
2928
let value = tracker.move(marker + marker)
3029
value += tracker.move(
31-
containerPhrasing(node, state, {
30+
state.containerPhrasing(node, {
3231
before: value,
3332
after: marker,
3433
...tracker.current()

lib/index.js

+48-2
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
/**
2+
* @typedef {import('./types.js').Enter} Enter
3+
* @typedef {import('./types.js').Info} Info
4+
* @typedef {import('./types.js').Join} Join
5+
* @typedef {import('./types.js').FlowContent} FlowContent
26
* @typedef {import('./types.js').Node} Node
37
* @typedef {import('./types.js').Options} Options
8+
* @typedef {import('./types.js').Parent} Parent
9+
* @typedef {import('./types.js').PhrasingContent} PhrasingContent
410
* @typedef {import('./types.js').State} State
5-
* @typedef {import('./types.js').Join} Join
6-
* @typedef {import('./types.js').Enter} Enter
11+
* @typedef {import('./types.js').TrackFields} TrackFields
712
*/
813

914
import {zwitch} from 'zwitch'
1015
import {configure} from './configure.js'
1116
import {handle as handlers} from './handle/index.js'
1217
import {join} from './join.js'
1318
import {unsafe} from './unsafe.js'
19+
import {containerPhrasing} from './util/container-phrasing.js'
20+
import {containerFlow} from './util/container-flow.js'
1421
import {indentLines} from './util/indent-lines.js'
1522

1623
/**
@@ -28,6 +35,8 @@ export function toMarkdown(tree, options = {}) {
2835
const state = {
2936
enter,
3037
indentLines,
38+
containerPhrasing: containerPhrasingBound,
39+
containerFlow: containerFlowBound,
3140
stack: [],
3241
unsafe: [],
3342
join: [],
@@ -104,3 +113,40 @@ function joinDefinition(left, right) {
104113
return 0
105114
}
106115
}
116+
117+
/**
118+
* Serialize the children of a parent that contains phrasing children.
119+
*
120+
* These children will be joined flush together.
121+
*
122+
* @this {State}
123+
* Info passed around about the current state.
124+
* @param {Parent & {children: Array<PhrasingContent>}} parent
125+
* Parent of flow nodes.
126+
* @param {Info} info
127+
* Info on where we are in the document we are generating.
128+
* @returns {string}
129+
* Serialized children, joined together.
130+
*/
131+
function containerPhrasingBound(parent, info) {
132+
return containerPhrasing(parent, this, info)
133+
}
134+
135+
/**
136+
* Serialize the children of a parent that contains flow children.
137+
*
138+
* These children will typically be joined by blank lines.
139+
* What they are joined by exactly is defined by `Join` functions.
140+
*
141+
* @this {State}
142+
* Info passed around about the current state.
143+
* @param {Parent & {children: Array<FlowContent>}} parent
144+
* Parent of flow nodes.
145+
* @param {TrackFields} info
146+
* Info on where we are in the document we are generating.
147+
* @returns {string}
148+
* Serialized children, joined by (blank) lines.
149+
*/
150+
function containerFlowBound(parent, info) {
151+
return containerFlow(parent, this, info)
152+
}

lib/types.js

+27-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343
* @returns {string}
4444
* Padded line.
4545
*
46-
4746
* @callback IndentLines
4847
* Pad serialized markdown.
4948
* @param {string} value
@@ -53,6 +52,29 @@
5352
* @returns {string}
5453
* Padded value.
5554
*
55+
* @callback ContainerPhrasing
56+
* Serialize the children of a parent that contains phrasing children.
57+
*
58+
* These children will be joined flush together.
59+
* @param {Parent & {children: Array<PhrasingContent>}} parent
60+
* Parent of flow nodes.
61+
* @param {Info} info
62+
* Info on where we are in the document we are generating.
63+
* @returns {string}
64+
* Serialized children, joined together.
65+
*
66+
* @callback ContainerFlow
67+
* Serialize the children of a parent that contains flow children.
68+
*
69+
* These children will typically be joined by blank lines.
70+
* What they are joined by exactly is defined by `Join` functions.
71+
* @param {Parent & {children: Array<FlowContent>}} parent
72+
* Parent of flow nodes.
73+
* @param {TrackFields} info
74+
* Info on where we are in the document we are generating.
75+
* @returns {string}
76+
* Serialized children, joined by (blank) lines.
77+
*
5678
* @callback Enter
5779
* Enter something.
5880
* @param {ConstructName} name
@@ -73,6 +95,10 @@
7395
* Positions of child nodes in their parents.
7496
* @property {IndentLines} indentLines
7597
* Pad serialized markdown.
98+
* @property {ContainerPhrasing} containerPhrasing
99+
* Serialize the children of a parent that contains phrasing children.
100+
* @property {ContainerFlow} containerFlow
101+
* Serialize the children of a parent that contains flow children.
76102
* @property {Enter} enter
77103
* Enter a construct (returns a corresponding exit function).
78104
* @property {Options} options

lib/util/container-flow.js

+29-21
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@ import {track} from './track.js'
1010

1111
/**
1212
* @param {Parent & {children: Array<FlowContent>}} parent
13+
* Parent of flow nodes.
1314
* @param {State} state
15+
* Info passed around about the current state.
1416
* @param {TrackFields} info
17+
* Info on where we are in the document we are generating.
1518
* @returns {string}
19+
* Serialized children, joined by (blank) lines.
1620
*/
1721
export function containerFlow(parent, state, info) {
1822
const indexStack = state.indexStack
@@ -44,38 +48,42 @@ export function containerFlow(parent, state, info) {
4448
}
4549

4650
if (index < children.length - 1) {
47-
results.push(tracker.move(between(child, children[index + 1])))
51+
results.push(
52+
tracker.move(between(child, children[index + 1], parent, state))
53+
)
4854
}
4955
}
5056

5157
indexStack.pop()
5258

5359
return results.join('')
60+
}
5461

55-
/**
56-
* @param {Node} left
57-
* @param {Node} right
58-
* @returns {string}
59-
*/
60-
function between(left, right) {
61-
let index = state.join.length
62-
63-
while (index--) {
64-
const result = state.join[index](left, right, parent, state)
62+
/**
63+
* @param {Node} left
64+
* @param {Node} right
65+
* @param {Parent} parent
66+
* @param {State} state
67+
* @returns {string}
68+
*/
69+
function between(left, right, parent, state) {
70+
let index = state.join.length
6571

66-
if (result === true || result === 1) {
67-
break
68-
}
72+
while (index--) {
73+
const result = state.join[index](left, right, parent, state)
6974

70-
if (typeof result === 'number') {
71-
return '\n'.repeat(1 + result)
72-
}
75+
if (result === true || result === 1) {
76+
break
77+
}
7378

74-
if (result === false) {
75-
return '\n\n<!---->\n\n'
76-
}
79+
if (typeof result === 'number') {
80+
return '\n'.repeat(1 + result)
7781
}
7882

79-
return '\n\n'
83+
if (result === false) {
84+
return '\n\n<!---->\n\n'
85+
}
8086
}
87+
88+
return '\n\n'
8189
}

0 commit comments

Comments
 (0)