All checks were successful
Publish To Prod / deploy_and_publish (push) Successful in 35s
127 lines
3.0 KiB
JavaScript
127 lines
3.0 KiB
JavaScript
'use strict'
|
||
|
||
module.exports = toMdast
|
||
|
||
var has = require('hast-util-has-property')
|
||
var minify = require('rehype-minify-whitespace')
|
||
var convert = require('unist-util-is/convert')
|
||
var visit = require('unist-util-visit')
|
||
var xtend = require('xtend')
|
||
var one = require('./lib/one')
|
||
var handlers = require('./lib/handlers')
|
||
var own = require('./lib/util/own')
|
||
|
||
var block = convert(['heading', 'paragraph', 'root'])
|
||
|
||
function toMdast(tree, options) {
|
||
var settings = options || {}
|
||
var byId = {}
|
||
var mdast
|
||
|
||
h.nodeById = byId
|
||
h.baseFound = false
|
||
h.frozenBaseUrl = null
|
||
h.wrapText = true
|
||
h.qNesting = 0
|
||
|
||
h.handlers = settings.handlers ? xtend(handlers, settings.handlers) : handlers
|
||
h.augment = augment
|
||
|
||
h.document = settings.document
|
||
h.checked = settings.checked || '[x]'
|
||
h.unchecked = settings.unchecked || '[ ]'
|
||
h.quotes = settings.quotes || ['"']
|
||
|
||
visit(tree, 'element', onelement)
|
||
|
||
minify({newlines: settings.newlines === true})(tree)
|
||
|
||
mdast = one(h, tree, null)
|
||
|
||
visit(mdast, 'text', ontext)
|
||
|
||
return mdast
|
||
|
||
function h(node, type, props, children) {
|
||
var result
|
||
|
||
if (
|
||
!children &&
|
||
(typeof props === 'string' ||
|
||
(typeof props === 'object' && 'length' in props))
|
||
) {
|
||
children = props
|
||
props = {}
|
||
}
|
||
|
||
result = xtend({type: type}, props)
|
||
|
||
if (typeof children === 'string') {
|
||
result.value = children
|
||
} else if (children) {
|
||
result.children = children
|
||
}
|
||
|
||
return augment(node, result)
|
||
}
|
||
|
||
// To do: inline in a future major.
|
||
// `right` is the finalized mdast node, created from `left`, a hast node.
|
||
function augment(left, right) {
|
||
if (left.position) {
|
||
right.position = left.position
|
||
}
|
||
|
||
return right
|
||
}
|
||
|
||
function onelement(node) {
|
||
var id = has(node, 'id') && String(node.properties.id).toUpperCase()
|
||
|
||
if (id && !own.call(byId, id)) {
|
||
byId[id] = node
|
||
}
|
||
}
|
||
|
||
// Collapse text nodes, and fix whitespace.
|
||
// Most of this is taken care of by `rehype-minify-whitespace`, but
|
||
// we’re generating some whitespace too, and some nodes are in the end
|
||
// ignored.
|
||
// So clean up:
|
||
function ontext(node, index, parent) {
|
||
var previous = parent.children[index - 1]
|
||
|
||
if (previous && node.type === previous.type) {
|
||
previous.value += node.value
|
||
|
||
parent.children.splice(index, 1)
|
||
|
||
if (previous.position && node.position) {
|
||
previous.position.end = node.position.end
|
||
}
|
||
|
||
// Iterate over the previous node again, to handle its total value.
|
||
return index - 1
|
||
}
|
||
|
||
node.value = node.value.replace(/[\t ]*(\r?\n|\r)[\t ]*/, '$1')
|
||
|
||
// We don’t care about other phrasing nodes in between (e.g., `[ asd ]()`),
|
||
// as there the whitespace matters.
|
||
if (block(parent)) {
|
||
if (!index) {
|
||
node.value = node.value.replace(/^[\t ]+/, '')
|
||
}
|
||
|
||
if (index === parent.children.length - 1) {
|
||
node.value = node.value.replace(/[\t ]+$/, '')
|
||
}
|
||
}
|
||
|
||
if (!node.value) {
|
||
parent.children.splice(index, 1)
|
||
return index
|
||
}
|
||
}
|
||
}
|