Skip to content

Commit

Permalink
Add containerPhrasing, containerFlow helpers on state
Browse files Browse the repository at this point in the history
  • Loading branch information
wooorm committed Jan 4, 2023
1 parent a638e2a commit 19301e7
Show file tree
Hide file tree
Showing 15 changed files with 132 additions and 52 deletions.
3 changes: 1 addition & 2 deletions lib/handle/blockquote.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
* @typedef {import('../types.js').Map} Map
*/

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

/**
Expand All @@ -22,7 +21,7 @@ export function blockquote(node, _, state, info) {
tracker.move('> ')
tracker.shift(2)
const value = state.indentLines(
containerFlow(node, state, tracker.current()),
state.containerFlow(node, tracker.current()),
map
)
exit()
Expand Down
3 changes: 1 addition & 2 deletions lib/handle/emphasis.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
*/

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

emphasis.peek = emphasisPeek
Expand All @@ -28,7 +27,7 @@ export function emphasis(node, _, state, info) {
const tracker = track(info)
let value = tracker.move(marker)
value += tracker.move(
containerPhrasing(node, state, {
state.containerPhrasing(node, {
before: value,
after: marker,
...tracker.current()
Expand Down
5 changes: 2 additions & 3 deletions lib/handle/heading.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
*/

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

/**
Expand All @@ -23,7 +22,7 @@ export function heading(node, _, state, info) {
if (formatHeadingAsSetext(node, state)) {
const exit = state.enter('headingSetext')
const subexit = state.enter('phrasing')
const value = containerPhrasing(node, state, {
const value = state.containerPhrasing(node, {
...tracker.current(),
before: '\n',
after: '\n'
Expand Down Expand Up @@ -54,7 +53,7 @@ export function heading(node, _, state, info) {
// we’ve tracked one too many characters.
tracker.move(sequence + ' ')

let value = containerPhrasing(node, state, {
let value = state.containerPhrasing(node, {
before: '# ',
after: '\n',
...tracker.current()
Expand Down
3 changes: 1 addition & 2 deletions lib/handle/link-reference.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
*/

import {association} from '../util/association.js'
import {containerPhrasing} from '../util/container-phrasing.js'
import {safe} from '../util/safe.js'
import {track} from '../util/track.js'

Expand All @@ -25,7 +24,7 @@ export function linkReference(node, _, state, info) {
let subexit = state.enter('label')
const tracker = track(info)
let value = tracker.move('[')
const text = containerPhrasing(node, state, {
const text = state.containerPhrasing(node, {
before: value,
after: ']',
...tracker.current()
Expand Down
5 changes: 2 additions & 3 deletions lib/handle/link.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

import {checkQuote} from '../util/check-quote.js'
import {formatLinkAsAutolink} from '../util/format-link-as-autolink.js'
import {containerPhrasing} from '../util/container-phrasing.js'
import {safe} from '../util/safe.js'
import {track} from '../util/track.js'

Expand Down Expand Up @@ -37,7 +36,7 @@ export function link(node, _, state, info) {
exit = state.enter('autolink')
let value = tracker.move('<')
value += tracker.move(
containerPhrasing(node, state, {
state.containerPhrasing(node, {
before: value,
after: '>',
...tracker.current()
Expand All @@ -53,7 +52,7 @@ export function link(node, _, state, info) {
subexit = state.enter('label')
let value = tracker.move('[')
value += tracker.move(
containerPhrasing(node, state, {
state.containerPhrasing(node, {
before: value,
after: '](',
...tracker.current()
Expand Down
3 changes: 1 addition & 2 deletions lib/handle/list-item.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

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

/**
Expand Down Expand Up @@ -49,7 +48,7 @@ export function listItem(node, parent, state, info) {
tracker.shift(size)
const exit = state.enter('listItem')
const value = state.indentLines(
containerFlow(node, state, tracker.current()),
state.containerFlow(node, tracker.current()),
map
)
exit()
Expand Down
3 changes: 1 addition & 2 deletions lib/handle/list.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
* @typedef {import('../types.js').Info} Info
*/

import {containerFlow} from '../util/container-flow.js'
import {checkBullet} from '../util/check-bullet.js'
import {checkBulletOther} from '../util/check-bullet-other.js'
import {checkBulletOrdered} from '../util/check-bullet-ordered.js'
Expand Down Expand Up @@ -106,7 +105,7 @@ export function list(node, parent, state, info) {
}

state.bulletCurrent = bullet
const value = containerFlow(node, state, info)
const value = state.containerFlow(node, info)
state.bulletLastUsed = bullet
state.bulletCurrent = bulletCurrent
exit()
Expand Down
4 changes: 1 addition & 3 deletions lib/handle/paragraph.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
* @typedef {import('../types.js').Info} Info
*/

import {containerPhrasing} from '../util/container-phrasing.js'

/**
* @param {Paragraph} node
* @param {Parent | undefined} _
Expand All @@ -17,7 +15,7 @@ import {containerPhrasing} from '../util/container-phrasing.js'
export function paragraph(node, _, state, info) {
const exit = state.enter('paragraph')
const subexit = state.enter('phrasing')
const value = containerPhrasing(node, state, info)
const value = state.containerPhrasing(node, info)
subexit()
exit()
return value
Expand Down
6 changes: 2 additions & 4 deletions lib/handle/root.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
*/

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

/**
* @param {Root} node
Expand All @@ -19,7 +17,7 @@ import {containerPhrasing} from '../util/container-phrasing.js'
export function root(node, _, state, info) {
// Note: `html` nodes are ambiguous.
const hasPhrasing = node.children.some((d) => phrasing(d))
const fn = hasPhrasing ? containerPhrasing : containerFlow
const fn = hasPhrasing ? state.containerPhrasing : state.containerFlow
// @ts-expect-error: `root`s are supposed to have one type of content
return fn(node, state, info)
return fn.call(state, node, info)
}
3 changes: 1 addition & 2 deletions lib/handle/strong.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
*/

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

strong.peek = strongPeek
Expand All @@ -28,7 +27,7 @@ export function strong(node, _, state, info) {
const tracker = track(info)
let value = tracker.move(marker + marker)
value += tracker.move(
containerPhrasing(node, state, {
state.containerPhrasing(node, {
before: value,
after: marker,
...tracker.current()
Expand Down
50 changes: 48 additions & 2 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
/**
* @typedef {import('./types.js').Enter} Enter
* @typedef {import('./types.js').Info} Info
* @typedef {import('./types.js').Join} Join
* @typedef {import('./types.js').FlowContent} FlowContent
* @typedef {import('./types.js').Node} Node
* @typedef {import('./types.js').Options} Options
* @typedef {import('./types.js').Parent} Parent
* @typedef {import('./types.js').PhrasingContent} PhrasingContent
* @typedef {import('./types.js').State} State
* @typedef {import('./types.js').Join} Join
* @typedef {import('./types.js').Enter} Enter
* @typedef {import('./types.js').TrackFields} TrackFields
*/

import {zwitch} from 'zwitch'
import {configure} from './configure.js'
import {handle as handlers} from './handle/index.js'
import {join} from './join.js'
import {unsafe} from './unsafe.js'
import {containerPhrasing} from './util/container-phrasing.js'
import {containerFlow} from './util/container-flow.js'
import {indentLines} from './util/indent-lines.js'

/**
Expand All @@ -28,6 +35,8 @@ export function toMarkdown(tree, options = {}) {
const state = {
enter,
indentLines,
containerPhrasing: containerPhrasingBound,
containerFlow: containerFlowBound,
stack: [],
unsafe: [],
join: [],
Expand Down Expand Up @@ -104,3 +113,40 @@ function joinDefinition(left, right) {
return 0
}
}

/**
* Serialize the children of a parent that contains phrasing children.
*
* These children will be joined flush together.
*
* @this {State}
* Info passed around about the current state.
* @param {Parent & {children: Array<PhrasingContent>}} parent
* Parent of flow nodes.
* @param {Info} info
* Info on where we are in the document we are generating.
* @returns {string}
* Serialized children, joined together.
*/
function containerPhrasingBound(parent, info) {
return containerPhrasing(parent, this, info)
}

/**
* Serialize the children of a parent that contains flow children.
*
* These children will typically be joined by blank lines.
* What they are joined by exactly is defined by `Join` functions.
*
* @this {State}
* Info passed around about the current state.
* @param {Parent & {children: Array<FlowContent>}} parent
* Parent of flow nodes.
* @param {TrackFields} info
* Info on where we are in the document we are generating.
* @returns {string}
* Serialized children, joined by (blank) lines.
*/
function containerFlowBound(parent, info) {
return containerFlow(parent, this, info)
}
28 changes: 27 additions & 1 deletion lib/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
* @returns {string}
* Padded line.
*
* @callback IndentLines
* Pad serialized markdown.
* @param {string} value
Expand All @@ -53,6 +52,29 @@
* @returns {string}
* Padded value.
*
* @callback ContainerPhrasing
* Serialize the children of a parent that contains phrasing children.
*
* These children will be joined flush together.
* @param {Parent & {children: Array<PhrasingContent>}} parent
* Parent of flow nodes.
* @param {Info} info
* Info on where we are in the document we are generating.
* @returns {string}
* Serialized children, joined together.
*
* @callback ContainerFlow
* Serialize the children of a parent that contains flow children.
*
* These children will typically be joined by blank lines.
* What they are joined by exactly is defined by `Join` functions.
* @param {Parent & {children: Array<FlowContent>}} parent
* Parent of flow nodes.
* @param {TrackFields} info
* Info on where we are in the document we are generating.
* @returns {string}
* Serialized children, joined by (blank) lines.
*
* @callback Enter
* Enter something.
* @param {ConstructName} name
Expand All @@ -73,6 +95,10 @@
* Positions of child nodes in their parents.
* @property {IndentLines} indentLines
* Pad serialized markdown.
* @property {ContainerPhrasing} containerPhrasing
* Serialize the children of a parent that contains phrasing children.
* @property {ContainerFlow} containerFlow
* Serialize the children of a parent that contains flow children.
* @property {Enter} enter
* Enter a construct (returns a corresponding exit function).
* @property {Options} options
Expand Down
50 changes: 29 additions & 21 deletions lib/util/container-flow.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@ import {track} from './track.js'

/**
* @param {Parent & {children: Array<FlowContent>}} parent
* Parent of flow nodes.
* @param {State} state
* Info passed around about the current state.
* @param {TrackFields} info
* Info on where we are in the document we are generating.
* @returns {string}
* Serialized children, joined by (blank) lines.
*/
export function containerFlow(parent, state, info) {
const indexStack = state.indexStack
Expand Down Expand Up @@ -44,38 +48,42 @@ export function containerFlow(parent, state, info) {
}

if (index < children.length - 1) {
results.push(tracker.move(between(child, children[index + 1])))
results.push(
tracker.move(between(child, children[index + 1], parent, state))
)
}
}

indexStack.pop()

return results.join('')
}

/**
* @param {Node} left
* @param {Node} right
* @returns {string}
*/
function between(left, right) {
let index = state.join.length

while (index--) {
const result = state.join[index](left, right, parent, state)
/**
* @param {Node} left
* @param {Node} right
* @param {Parent} parent
* @param {State} state
* @returns {string}
*/
function between(left, right, parent, state) {
let index = state.join.length

if (result === true || result === 1) {
break
}
while (index--) {
const result = state.join[index](left, right, parent, state)

if (typeof result === 'number') {
return '\n'.repeat(1 + result)
}
if (result === true || result === 1) {
break
}

if (result === false) {
return '\n\n<!---->\n\n'
}
if (typeof result === 'number') {
return '\n'.repeat(1 + result)
}

return '\n\n'
if (result === false) {
return '\n\n<!---->\n\n'
}
}

return '\n\n'
}

0 comments on commit 19301e7

Please sign in to comment.