src/lib/gfm.js
import Util from './util.js'
/**
* Convert the DOM node to cell text of the table.
*
* @param {Node} node DOM node.
* @param {String} content Content text.
*
* @return {String} Cell text.
*/
function Cell (node, content) {
let index = 0
if (node.parentNode && node.parentNode.childNodes) {
index = Util.arrayIndexOf(node.parentNode.childNodes, node)
}
const prefix = (index === 0 ? '| ' : ' ')
return prefix + content + ' |'
}
/**
* RegExp for the higlighting.
* @type {RegExp}
*/
const HighlightRegEx = /highlight highlight-(\S+)/
/**
* Convert the HTML DOM Node to GFM (GitHub Flavored Markdown) text.
* @type {Array.<MdConverter>}
* @see https://github.com/domchristie/to-markdown/blob/master/lib/gfm-converters.js
*/
const GfmConverters = [
// Line break
{
filter: 'br',
replacement: () => {
return '\n'
}
},
// Delete
{
filter: ['del', 's', 'strike'],
replacement: (node, content) => {
return '~~' + content + '~~'
}
},
// Checkbox
{
filter: (node) => {
return node.type === 'checkbox' && node.parentNode.nodeName === 'LI'
},
replacement: (node) => {
return (node.checked ? '[x]' : '[ ]') + ' '
}
},
// Table cell
{
filter: [ 'th', 'td' ],
replacement: (node, content) => {
return Cell(node, content)
}
},
// Table row
{
filter: 'tr',
replacement: (node, content) => {
let borderCells = ''
const alignMap = { left: ':--', right: '--:', center: ':-:' }
if (node.parentNode.nodeName === 'THEAD') {
for (let i = 0, max = node.childNodes.length; i < max; ++i) {
const elm = node.childNodes[i]
const align = (elm.attributes ? elm.attributes.align : null)
const border = (align ? alignMap[ align.value ] : '---')
if (elm._replacement) {
borderCells += Cell(elm, border)
}
}
}
return '\n' + content + (borderCells ? '\n' + borderCells : '')
}
},
// Table
{
filter: 'table',
replacement: (node, content) => {
return '\n\n' + content + '\n\n'
}
},
// Table parts
{
filter: [ 'thead', 'tbody', 'tfoot' ],
replacement: (node, content) => {
return content
}
},
// Fenced code blocks
{
filter: (node) => {
return node.nodeName === 'PRE' &&
node.firstChild &&
node.firstChild.nodeName === 'CODE'
},
replacement: (node) => {
return '\n\n```\n' + node.firstChild.textContent + '\n```\n\n'
}
},
// Syntax-highlighted code blocks
{
filter: (node) => {
return node.nodeName === 'PRE' &&
node.parentNode.nodeName === 'DIV' &&
HighlightRegEx.test(node.parentNode.className)
},
replacement: (node) => {
const language = node.parentNode.className.match(HighlightRegEx)[ 1 ]
return '\n\n```' + language + '\n' + node.textContent + '\n```\n\n'
}
},
// Div
{
filter: (node) => {
return node.nodeName === 'DIV' &&
HighlightRegEx.test(node.className)
},
replacement: (node, content) => {
return '\n\n' + content + '\n\n'
}
}
]
export default GfmConverters