mirror of
https://github.com/Sevichecc/Urara-Blog.git
synced 2025-05-05 20:59:31 +08:00
100 lines
2.1 KiB
Text
100 lines
2.1 KiB
Text
/**
|
||
* @typedef {import('./types.js').Node} Node
|
||
* @typedef {import('./types.js').Options} Options
|
||
* @typedef {import('./types.js').Context} Context
|
||
* @typedef {import('./types.js').Handle} Handle
|
||
* @typedef {import('./types.js').Join} Join
|
||
* @typedef {import('./types.js').Unsafe} Unsafe
|
||
*/
|
||
|
||
import {zwitch} from 'zwitch'
|
||
import {configure} from './configure.js'
|
||
import {handle} from './handle/index.js'
|
||
import {join} from './join.js'
|
||
import {unsafe} from './unsafe.js'
|
||
|
||
/**
|
||
* @param {Node} tree
|
||
* @param {Options} [options]
|
||
* @returns {string}
|
||
*/
|
||
export function toMarkdown(tree, options = {}) {
|
||
/** @type {Context} */
|
||
// @ts-expect-error: we’ll add `handle` later.
|
||
const context = {
|
||
enter,
|
||
stack: [],
|
||
unsafe: [],
|
||
join: [],
|
||
handlers: {},
|
||
options: {},
|
||
indexStack: []
|
||
}
|
||
|
||
configure(context, {unsafe, join, handlers: handle})
|
||
configure(context, options)
|
||
|
||
if (context.options.tightDefinitions) {
|
||
configure(context, {join: [joinDefinition]})
|
||
}
|
||
|
||
/** @type {Handle} */
|
||
context.handle = zwitch('type', {
|
||
invalid,
|
||
// @ts-expect-error: hush.
|
||
unknown,
|
||
// @ts-expect-error: hush.
|
||
handlers: context.handlers
|
||
})
|
||
|
||
let result = context.handle(tree, null, context, {
|
||
before: '\n',
|
||
after: '\n',
|
||
now: {line: 1, column: 1},
|
||
lineShift: 0
|
||
})
|
||
|
||
if (
|
||
result &&
|
||
result.charCodeAt(result.length - 1) !== 10 &&
|
||
result.charCodeAt(result.length - 1) !== 13
|
||
) {
|
||
result += '\n'
|
||
}
|
||
|
||
return result
|
||
|
||
/** @type {Context['enter']} */
|
||
function enter(name) {
|
||
context.stack.push(name)
|
||
return exit
|
||
|
||
function exit() {
|
||
context.stack.pop()
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @type {Handle}
|
||
* @param {unknown} value
|
||
*/
|
||
function invalid(value) {
|
||
throw new Error('Cannot handle value `' + value + '`, expected node')
|
||
}
|
||
|
||
/**
|
||
* @type {Handle}
|
||
* @param {Node} node
|
||
*/
|
||
function unknown(node) {
|
||
throw new Error('Cannot handle unknown node `' + node.type + '`')
|
||
}
|
||
|
||
/** @type {Join} */
|
||
function joinDefinition(left, right) {
|
||
// No blank line between adjacent definitions.
|
||
if (left.type === 'definition' && left.type === right.type) {
|
||
return 0
|
||
}
|
||
}
|