site/node_modules/mdast-util-to-markdown/lib/handle/list.js

103 lines
3 KiB
JavaScript
Raw Normal View History

2024-10-14 06:09:33 +00:00
/**
* @typedef {import('mdast').List} List
* @typedef {import('mdast').Parents} Parents
* @typedef {import('../types.js').Info} Info
* @typedef {import('../types.js').State} State
*/
import {checkBullet} from '../util/check-bullet.js'
import {checkBulletOther} from '../util/check-bullet-other.js'
import {checkBulletOrdered} from '../util/check-bullet-ordered.js'
import {checkRule} from '../util/check-rule.js'
/**
* @param {List} node
* @param {Parents | undefined} parent
* @param {State} state
* @param {Info} info
* @returns {string}
*/
export function list(node, parent, state, info) {
const exit = state.enter('list')
const bulletCurrent = state.bulletCurrent
/** @type {string} */
let bullet = node.ordered ? checkBulletOrdered(state) : checkBullet(state)
/** @type {string} */
const bulletOther = node.ordered
? bullet === '.'
? ')'
: '.'
: checkBulletOther(state)
let useDifferentMarker =
parent && state.bulletLastUsed ? bullet === state.bulletLastUsed : false
if (!node.ordered) {
const firstListItem = node.children ? node.children[0] : undefined
// If theres an empty first list item directly in two list items,
// we have to use a different bullet:
//
// ```markdown
// * - *
// ```
//
// …because otherwise it would become one big thematic break.
if (
// Bullet could be used as a thematic break marker:
(bullet === '*' || bullet === '-') &&
// Empty first list item:
firstListItem &&
(!firstListItem.children || !firstListItem.children[0]) &&
// Directly in two other list items:
state.stack[state.stack.length - 1] === 'list' &&
state.stack[state.stack.length - 2] === 'listItem' &&
state.stack[state.stack.length - 3] === 'list' &&
state.stack[state.stack.length - 4] === 'listItem' &&
// That are each the first child.
state.indexStack[state.indexStack.length - 1] === 0 &&
state.indexStack[state.indexStack.length - 2] === 0 &&
state.indexStack[state.indexStack.length - 3] === 0
) {
useDifferentMarker = true
}
// If theres a thematic break at the start of the first list item,
// we have to use a different bullet:
//
// ```markdown
// * ---
// ```
//
// …because otherwise it would become one big thematic break.
if (checkRule(state) === bullet && firstListItem) {
let index = -1
while (++index < node.children.length) {
const item = node.children[index]
if (
item &&
item.type === 'listItem' &&
item.children &&
item.children[0] &&
item.children[0].type === 'thematicBreak'
) {
useDifferentMarker = true
break
}
}
}
}
if (useDifferentMarker) {
bullet = bulletOther
}
state.bulletCurrent = bullet
const value = state.containerFlow(node, info)
state.bulletLastUsed = bullet
state.bulletCurrent = bulletCurrent
exit()
return value
}