Class: RedQuilt::CodeBlock::Parser
- Inherits:
-
Object
- Object
- RedQuilt::CodeBlock::Parser
- Defined in:
- lib/red_quilt/code_block.rb
Overview
Cached collaborator for BlockParser. A single instance is created in BlockParser#initialize and reused; per-call state lives in method locals so reentrant calls are safe.
Instance Method Summary collapse
-
#initialize(block_parser) ⇒ Parser
constructor
A new instance of Parser.
-
#parse_fenced(parent_id, lines, index, fence) ⇒ Object
Parses a fenced block.
-
#parse_indented(parent_id, lines, index) ⇒ Object
Parses an indented code block.
Constructor Details
#initialize(block_parser) ⇒ Parser
Returns a new instance of Parser.
40 41 42 |
# File 'lib/red_quilt/code_block.rb', line 40 def initialize(block_parser) @arena = block_parser.arena end |
Instance Method Details
#parse_fenced(parent_id, lines, index, fence) ⇒ Object
Parses a fenced block. ‘fence` is CodeBlock.fenced_start’s result for lines. Returns the index past the block.
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/red_quilt/code_block.rb', line 46 def parse_fenced(parent_id, lines, index, fence) start_line = lines[index] content_lines = [] index += 1 while index < lines.length break if fence_close?(lines[index].content, fence[:char], fence[:count]) content_lines << lines[index] index += 1 end index += 1 if index < lines.length # Each content line is stripped of up to the fence's own leading # indent (CommonMark spec: a fence indented by N spaces strips up # to N spaces from every content line, but never more). Manual # byte scan beats compiling an interpolated regex per block and # short-circuits when the fence had no indent (the common case). indent_n = fence[:indent] || 0 code = content_lines.map { |l| Indentation.strip_leading_spaces(l.content, indent_n) }.join("\n") code << "\n" unless content_lines.empty? source_start = content_lines.empty? ? start_line.start_byte : content_lines.first.start_byte source_end = content_lines.empty? ? start_line.end_byte : content_lines.last.end_byte code_id = @arena.add_node(NodeType::CODE_BLOCK, source_start: source_start, source_len: source_end - source_start, str1: code, str2: fence[:info]) @arena.append_child(parent_id, code_id) index end |
#parse_indented(parent_id, lines, index) ⇒ Object
Parses an indented code block. Returns the index past the block.
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/red_quilt/code_block.rb', line 78 def parse_indented(parent_id, lines, index) start_index = index code_lines = [] while index < lines.length line = lines[index] break unless line.blank || CodeBlock.indented_line?(line.content) # CommonMark: strip up to 4 columns of leading whitespace # (tab-aware) from every line, including blank lines whose # content beyond column 4 must be preserved verbatim. code_lines << Indentation.strip_columns(line.content, 4) index += 1 end # Trailing blank lines are not part of the code block. while !code_lines.empty? && code_lines.last.strip.empty? code_lines.pop index -= 1 end start_byte = lines[start_index].start_byte end_byte = lines[index - 1].end_byte code = code_lines.empty? ? "" : code_lines.join("\n") + "\n" code_id = @arena.add_node(NodeType::CODE_BLOCK, source_start: start_byte, source_len: end_byte - start_byte, str1: code) @arena.append_child(parent_id, code_id) index end |