class MarkdownIt::RulesBlock::Fence

Public Class Methods

fence(state, startLine, endLine, silent) click to toggle source
# File lib/motion-markdown-it/rules_block/fence.rb, line 9
def self.fence(state, startLine, endLine, silent)
  haveEndMarker = false
  pos           = state.bMarks[startLine] + state.tShift[startLine]
  max           = state.eMarks[startLine]

  # if it's indented more than 3 spaces, it should be a code block
  return false if state.sCount[startLine] - state.blkIndent >= 4

  return false if pos + 3 > max

  marker = charCodeAt(state.src, pos)

  if marker != 0x7E && marker != 0x60 #  != ~ && != `
    return false
  end

  # scan marker length
  mem = pos;
  pos = state.skipChars(pos, marker)
  len = pos - mem

  return false if len < 3

  markup = state.src.slice(mem...pos)
  params = state.src.slice(pos...max)

  return false if params.include?(fromCharCode(marker))

  # Since start is found, we can report success here in validation mode
  return true if silent

  # search end of block
  nextLine = startLine

  while true
    nextLine += 1
    if nextLine >= endLine
      # unclosed block should be autoclosed by end of document.
      # also block seems to be autoclosed by end of parent
      break
    end

    pos = mem = state.bMarks[nextLine] + state.tShift[nextLine]
    max = state.eMarks[nextLine];

    if pos < max && state.sCount[nextLine] < state.blkIndent
      # non-empty line with negative indent should stop the list:
      # - ```
      #  test
      break
    end

    next if charCodeAt(state.src, pos) != marker

    if state.sCount[nextLine] - state.blkIndent >= 4
      # closing fence should be indented less than 4 spaces
      next
    end

    pos = state.skipChars(pos, marker)

    # closing code fence must be at least as long as the opening one
    next if pos - mem < len

    # make sure tail has spaces only
    pos = state.skipSpaces(pos)

    next if pos < max

    haveEndMarker = true
    # found!
    break
  end

  # If a fence has heading spaces, they should be removed from its inner block
  len           = state.sCount[startLine]

  state.line    = nextLine + (haveEndMarker ? 1 : 0)

  token         = state.push('fence', 'code', 0)
  token.info    = params
  token.content = state.getLines(startLine + 1, nextLine, len, true)
  token.markup  = markup
  token.map     = [ startLine, state.line ]

  return true
end