text: const util = require('./util')
  
  module.exports = mathBlock
  
  const lineFeed = 10 //  '\n'
  const space = 32 // ' '
  const dollarSign = 36 // '$'
  
  const lineFeedChar = '\n'
  const dollarSignChar = '$'
  
  const minFenceCount = 2
  
  const classList = ['math', 'math-display']
  
  function mathBlock() {
    const parser = this.Parser
    const compiler = this.Compiler
  
    if (util.isRemarkParser(parser)) {
      attachParser(parser)
    }
  
    if (util.isRemarkCompiler(compiler)) {
      attachCompiler(compiler)
    }
  }
  
  function attachParser(parser) {
    const proto = parser.prototype
    const blockMethods = proto.blockMethods
    const interruptParagraph = proto.interruptParagraph
    const interruptList = proto.interruptList
    const interruptBlockquote = proto.interruptBlockquote
  
    proto.blockTokenizers.math = mathBlockTokenizer
  
    blockMethods.splice(blockMethods.indexOf('fencedCode') + 1, 0, 'math')
  
    // Inject math to interrupt rules
    interruptParagraph.splice(interruptParagraph.indexOf('fencedCode') + 1, 0, [
      'math'
    ])
    interruptList.splice(interruptList.indexOf('fencedCode') + 1, 0, ['math'])
    interruptBlockquote.splice(interruptBlockquote.indexOf('fencedCode') + 1, 0, [
      'math'
    ])
  
    function mathBlockTokenizer(eat, value, silent) {
      var length = value.length
      var index = 0
      let code
      let content
      let lineEnd
      let lineIndex
      let openingFenceIndentSize
      let openingFenceSize
      let openingFenceContentStart
      let closingFence
      let closingFenceSize
      let lineContentStart
      let lineContentEnd
  
      // Skip initial spacing.
      while (index < length && value.charCodeAt(index) === space) {
        index++
      }
  
      openingFenceIndentSize = index
  
      // Skip the fence.
      while (index < length && value.charCodeAt(index) === dollarSign) {
        index++
      }
  
      openingFenceSize = index - openingFenceIndentSize
  
      // Exit if there is not enough of a fence.
      if (openingFenceSize < minFenceCount) {
        return
      }
  
      // Skip spacing after the fence.
      while (index < length && value.charCodeAt(index) === space) {
        index++
      }
  
      openingFenceContentStart = index
  
      // Eat everything after the fence.
      while (index < length) {
        code = value.charCodeAt(index)
  
        // We don’t allow dollar signs here, as that could interfere with inline
        // math.
        if (code === dollarSign) {
          return
        }
  
        if (code === lineFeed) {
          break
        }
  
        index++
      }
  
      if (value.charCodeAt(index) !== lineFeed) {
        return
      }
  
      if (silent) {
        return true
      }
  
      content = []
  
      if (openingFenceContentStart !== index) {
        content.push(value.slice(openingFenceContentStart, index))
      }
  
      index++
      lineEnd = value.indexOf(lineFeedChar, index + 1)
      lineEnd = lineEnd === -1 ? length : lineEnd
  
      while (index < length) {
        closingFence = false
        lineContentStart = index
        lineContentEnd = lineEnd
        lineIndex = lineEnd
        closingFenceSize = 0
  
        // First, let’s see if this is a valid closing fence.
        // Skip trailing white space
        while (
          lineIndex > lineContentStart &&
          value.charCodeAt(lineIndex - 1) === space
        ) {
          lineIndex--
        }
  
        // Skip the fence.
        while (
          lineIndex > lineContentStart &&
          value.charCodeAt(lineIndex - 1) === dollarSign
        ) {
          closingFenceSize++
          lineIndex--
        }
  
        // Check if this is a valid closing fence line.
        if (
          openingFenceSize <= closingFenceSize &&
          value.indexOf(dollarSignChar, lineContentStart) === lineIndex
        ) {
          closingFence = true
          lineContentEnd = lineIndex
        }
  
        // Sweet, next, we need to trim the line.
        // Skip initial spacing.
        while (
          lineContentStart <= lineContentEnd &&
          lineContentStart - index < openingFenceIndentSize &&
          value.charCodeAt(lineContentStart) === space
        ) {
          lineContentStart++
        }
  
        // If this is a closing fence, skip final spacing.
        if (closingFence) {
          while (
            lineContentEnd > lineContentStart &&
            value.charCodeAt(lineContentEnd - 1) === space
          ) {
            lineContentEnd--
          }
        }
  
        // If this is a content line, or if there is content before the fence:
        if (!closingFence || lineContentStart !== lineContentEnd) {
          content.push(value.slice(lineContentStart, lineContentEnd))
        }
  
        if (closingFence) {
          break
        }
  
        index = lineEnd + 1
        lineEnd = value.indexOf(lineFeedChar, index + 1)
        lineEnd = lineEnd === -1 ? length : lineEnd
      }
  
      content = content.join('\n')
  
      return eat(value.slice(0, lineEnd))({
        type: 'math',
        value: content,
        data: {
          hName: 'div',
          hProperties: {className: classList.concat()},
          hChildren: [{type: 'text', value: content}]
        }
      })
    }
  }
  
  function attachCompiler(compiler) {
    const proto = compiler.prototype
  
    proto.visitors.math = compileBlockMath
  
    function compileBlockMath(node) {
      return '$$\n' + node.value + '\n$$'
    }
  }
  