Module: RedQuilt::Blockquote

Defined in:
lib/red_quilt/blockquote.rb

Overview

CommonMark spec 5.1 blockquotes.

Module-level functions are stateless helpers used by BlockParser’s predicate dispatch. ‘Blockquote::Parser` is a cached collaborator created once in BlockParser#initialize and reused for every blockquote (including nested ones) — per-call state lives in method locals so reentrant `#parse` calls are safe.

Defined Under Namespace

Classes: Parser

Constant Summary collapse

BLOCKQUOTE_PREFIX_RE =
/\A {0,3}>/

Class Method Summary collapse

Class Method Details

.match?(text) ⇒ Boolean

Returns:

  • (Boolean)


16
17
18
# File 'lib/red_quilt/blockquote.rb', line 16

def match?(text)
  text.match?(BLOCKQUOTE_PREFIX_RE)
end

.strip_prefix(line) ⇒ Object

Strip the leading ‘>` (and at most one column of whitespace after it) from a blockquote line. Returns a new Line whose content is the inner text. If the line has no `>` prefix, the original line is returned unchanged (wrapped in a fresh Line so the caller treats it uniformly).



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/red_quilt/blockquote.rb', line 25

def strip_prefix(line)
  content = line.content
  bytes = content.bytesize
  i = 0
  abs_col = 0
  # Up to 3 spaces of indent before `>`.
  while i < 3 && i < bytes && content.getbyte(i) == 0x20
    i += 1
    abs_col += 1
  end
  unless i < bytes && content.getbyte(i) == 0x3E
    return Line.new(content, line.start_byte, line.end_byte, !content.match?(/\S/))
  end

  i += 1
  abs_col += 1 # consume `>`

  # Count column width of leading whitespace after `>` using
  # absolute-column tracking so a tab right after `>` (at col 1) is
  # correctly billed as only 3 columns of indent, not 4.
  ws_start_col = abs_col
  j = i
  while j < bytes
    b = content.getbyte(j)
    if b == 0x20
      abs_col += 1
    elsif b == 0x09
      abs_col = ((abs_col / 4) + 1) * 4
    else
      break
    end
    j += 1
  end
  ws_cols = abs_col - ws_start_col

  if ws_cols >= 1
    tail = (" " * (ws_cols - 1)) + content.byteslice(j..)
    offset = j
  else
    tail = content.byteslice(i..)
    offset = i
  end

  Line.new(tail, line.start_byte + offset, line.end_byte, !tail.match?(/\S/))
end