Home Reference Source Test

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