Module: RedQuilt::HtmlBlock

Defined in:
lib/red_quilt/html_block.rb

Overview

CommonMark HTML-block classification (spec 4.6). Pure functions over a line’s text: given the raw line they decide whether it opens an HTML block and of which of the seven types. No arena or parser state is involved, so this lives apart from BlockParser’s node construction.

Defined Under Namespace

Classes: Parser

Class Method Summary collapse

Class Method Details

.start?(text) ⇒ Boolean

True when ‘text` opens an HTML block (any of the 7 types). Indented code (4+ leading spaces) takes precedence and is never an HTML block.

Returns:

  • (Boolean)


13
14
15
16
17
# File 'lib/red_quilt/html_block.rb', line 13

def start?(text)
  return false if text.start_with?("    ")

  !type(text).nil?
end

.type(text) ⇒ Object

The HTML block type (1..7) opened by ‘text`, or nil if it opens none.



20
21
22
23
24
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
# File 'lib/red_quilt/html_block.rb', line 20

def type(text)
  # Fast reject: every HTML block starts with `<`. lstrip strips
  # 0-3 indent spaces (more would already be indented code), so peek
  # the leading non-space byte before doing any allocations.
  i = 0
  # CommonMark: HTML block lines may have 0-3 spaces of indent.
  while i < 3 && i < text.length && text.getbyte(i) == 0x20
    i += 1
  end
  return nil unless i < text.length && text.getbyte(i) == 0x3C

  stripped = i.zero? ? text : text[i..]

  # Type 1: <script|pre|style|textarea (case-insensitive) followed by
  # space/tab/end-of-line or `>`. CommonMark restricts the separator
  # to space, tab, or a line ending (not any whitespace class).
  return 1 if stripped.match?(%r{\A<(script|pre|style|textarea)(?:[ \t]|>|$)}i)

  # Type 2: <!--
  return 2 if stripped.start_with?("<!--")

  # Type 3: <?
  return 3 if stripped.start_with?("<?")

  # Type 4: <! followed by uppercase ASCII letter
  return 4 if stripped.match?(%r{\A<![A-Z]})

  # Type 5: <![CDATA[
  return 5 if stripped.start_with?("<![CDATA[")

  # Type 6: line opens with one of the listed block-level tags.
  return 6 if stripped.match?(TYPE_6_RE)

  # Type 7: a complete open or closing tag spanning the line.
  return 7 if valid_tag?(stripped)

  nil
end

.valid_tag?(text) ⇒ Boolean

Returns:

  • (Boolean)


86
87
88
89
90
91
# File 'lib/red_quilt/html_block.rb', line 86

def valid_tag?(text)
  # Fast reject: every type-7 tag must begin with `<`.
  return false unless text.start_with?("<")

  TYPE_7_OPEN_TAG_RE.match?(text) || TYPE_7_CLOSING_TAG_RE.match?(text)
end