class MarkdownIt::RulesBlock::StateBlock

Attributes

bMarks[RW]
blkIndent[RW]
bsCount[RW]
ddIndent[RW]
eMarks[RW]
env[RW]
level[RW]
line[RW]
lineMax[RW]
md[RW]
parentType[RW]
result[RW]
sCount[RW]
src[RW]
tShift[RW]
tight[RW]
tokens[RW]

Public Class Methods

new(src, md, env, tokens) click to toggle source
# File lib/motion-markdown-it/rules_block/state_block.rb, line 13
def initialize(src, md, env, tokens)
  @src = src

  # link to parser instance
  @md  = md
  @env = env

  #--- Internal state variables

  @tokens = tokens

  @bMarks = []  # line begin offsets for fast jumps
  @eMarks = []  # line end offsets for fast jumps
  @tShift = []  # offsets of the first non-space characters (tabs not expanded)
  @sCount = []  # indents for each line (tabs expanded)

  # An amount of virtual spaces (tabs expanded) between beginning
  # of each line (bMarks) and real beginning of that line.
  #
  # It exists only as a hack because blockquotes override bMarks
  # losing information in the process.
  #
  # It's used only when expanding tabs, you can think about it as
  # an initial tab length, e.g. bsCount=21 applied to string `\t123`
  # means first tab should be expanded to 4-21%4 === 3 spaces.
  #
  @bsCount    = []

  # block parser variables
  @blkIndent  = 0       # required block content indent (for example, if we are in list)
  @line       = 0       # line index in src
  @lineMax    = 0       # lines count
  @tight      = false   # loose/tight mode for lists
  @parentType = 'root'  # if `list`, block parser stops on two newlines
  @ddIndent   = -1      # indent of the current dd block (-1 if there isn't any)

  # can be 'blockquote', 'list', 'root', 'paragraph' or 'reference'
  # used in lists to determine if they interrupt a paragraph
  @parentType = 'root'

  @level = 0

  # renderer
  @result = ''

  # Create caches
  # Generate markers.
  s            = @src
  indent_found = false

  start = pos = indent = offset = 0
  len = s.length
  while pos < len
    ch = charCodeAt(s, pos)

    if !indent_found
      if isSpace(ch)
        indent += 1

        if ch == 0x09
          offset += 4 - offset % 4
        else
          offset += 1
        end
        (pos += 1) and next
      else
        indent_found = true
      end
    end

    if ch == 0x0A || pos == (len - 1)
      pos += 1 if ch != 0x0A
      @bMarks.push(start)
      @eMarks.push(pos)
      @tShift.push(indent)
      @sCount.push(offset)
      @bsCount.push(0)

      indent_found = false
      indent       = 0
      offset       = 0
      start        = pos + 1
    end

    pos += 1
  end

  # Push fake entry to simplify cache bounds checks
  @bMarks.push(s.length)
  @eMarks.push(s.length)
  @tShift.push(0)
  @sCount.push(0)
  @bsCount.push(0)

  @lineMax = @bMarks.length - 1 # don't count last fake line
end

Public Instance Methods

getLines(line_begin, line_end, indent, keepLastLF) click to toggle source

cut lines range from source.

# File lib/motion-markdown-it/rules_block/state_block.rb, line 185
def getLines(line_begin, line_end, indent, keepLastLF)
  line = line_begin

  return '' if line_begin >= line_end

  queue = Array.new(line_end - line_begin)

  i = 0
  while line < line_end
    lineIndent = 0
    lineStart = first = @bMarks[line]

    if line + 1 < line_end || keepLastLF
      # No need for bounds check because we have fake entry on tail.
      last = @eMarks[line] + 1
    else
      last = @eMarks[line]
    end

    while first < last && lineIndent < indent
      ch = charCodeAt(@src, first)

      if isSpace(ch)
        if ch === 0x09
          lineIndent += 4 - (lineIndent + @bsCount[line]) % 4
        else
          lineIndent += 1
        end
      elsif first - lineStart < @tShift[line]
        # patched tShift masked characters to look like spaces (blockquotes, list markers)
        lineIndent += 1
      else
        break
      end

      first += 1
    end

    if lineIndent > indent
      # partially expanding tabs in code blocks, e.g '\t\tfoobar'
      # with indent=2 becomes '  \tfoobar'
      queue[i] = (' ' * (lineIndent - indent)) + @src.slice(first...last)
    else
      queue[i] = @src.slice(first...last)
    end
    line += 1
    i    += 1
  end

  return queue.join('')
end
isEmpty(line) click to toggle source
# File lib/motion-markdown-it/rules_block/state_block.rb, line 125
def isEmpty(line)
  return @bMarks[line] + @tShift[line] >= @eMarks[line]
end
push(type, tag, nesting) click to toggle source

Push new token to “stream”.

# File lib/motion-markdown-it/rules_block/state_block.rb, line 112
def push(type, tag, nesting)
  token       = Token.new(type, tag, nesting)
  token.block = true

  @level -= 1 if nesting < 0
  token.level = @level
  @level += 1 if nesting > 0

  @tokens.push(token)
  return token
end
skipChars(pos, code) click to toggle source

Skip char codes from given position

# File lib/motion-markdown-it/rules_block/state_block.rb, line 163
def skipChars(pos, code)
  max = @src.length
  while pos < max
    break if (charCodeAt(@src, pos) != code)
    pos += 1
  end
  return pos
end
skipCharsBack(pos, code, min) click to toggle source

Skip char codes reverse from given position - 1

# File lib/motion-markdown-it/rules_block/state_block.rb, line 174
def skipCharsBack(pos, code, min)
  return pos if pos <= min

  while (pos > min)
    return (pos + 1) if code != charCodeAt(@src, pos -= 1)
  end
  return pos
end
skipEmptyLines(from) click to toggle source
# File lib/motion-markdown-it/rules_block/state_block.rb, line 130
def skipEmptyLines(from)
  while from < @lineMax
    break if (@bMarks[from] + @tShift[from] < @eMarks[from])
    from += 1
  end
  return from
end
skipSpaces(pos) click to toggle source

Skip spaces from given position.

# File lib/motion-markdown-it/rules_block/state_block.rb, line 140
def skipSpaces(pos)
  max = @src.length
  while pos < max
    ch = charCodeAt(@src, pos)
    break if !isSpace(ch)
    pos += 1
  end
  return pos
end
skipSpacesBack(pos, min) click to toggle source

Skip spaces from given position in reverse.

# File lib/motion-markdown-it/rules_block/state_block.rb, line 152
def skipSpacesBack(pos, min)
  return pos if pos <= min

  while (pos > min)
    return pos + 1 if !isSpace(charCodeAt(@src, pos -= 1))
  end
  return pos
end