Class: Markbridge::Processors::DiscourseMarkdown::CodeBlockTracker
- Inherits:
-
Object
- Object
- Markbridge::Processors::DiscourseMarkdown::CodeBlockTracker
- Defined in:
- lib/markbridge/processors/discourse_markdown/code_block_tracker.rb
Overview
Tracks whether the current position is inside a code block. Handles fenced code blocks (“‘ or ~~~), indented code blocks (4+ spaces), and inline code (`).
Fenced code blocks:
-
Can have leading whitespace (up to 3 spaces)
-
Opening fence: 3+ backticks or tildes, optionally followed by language
-
Closing fence: same or more fence characters as opening
Indented code blocks:
-
Lines indented by 4+ spaces or 1+ tab
-
Continues until a non-blank line with less indentation
Inline code:
-
Single or multiple backticks as delimiter
-
Content between matching backticks
Instance Attribute Summary collapse
-
#in_fenced_block ⇒ Boolean
readonly
True if currently inside a fenced code block.
-
#in_indented_block ⇒ Boolean
readonly
True if currently inside an indented code block.
-
#in_inline_code ⇒ Boolean
readonly
True if currently inside an inline code span.
Instance Method Summary collapse
-
#check_fenced_boundary(input, pos, line_start:) ⇒ Integer?
Check if position is at start of a fenced code block boundary.
-
#check_indented_boundary(input, pos, line_start:) ⇒ Integer?
Check if line at position is an indented code block line.
-
#check_inline_boundary(input, pos) ⇒ Integer?
Check for inline code boundary.
-
#in_code? ⇒ Boolean
Check if currently inside any code context.
-
#initialize ⇒ CodeBlockTracker
constructor
A new instance of CodeBlockTracker.
-
#reset! ⇒ Object
Reset the tracker state.
Constructor Details
#initialize ⇒ CodeBlockTracker
Returns a new instance of CodeBlockTracker.
32 33 34 35 36 37 38 39 40 |
# File 'lib/markbridge/processors/discourse_markdown/code_block_tracker.rb', line 32 def initialize @in_fenced_block = false @in_indented_block = false @in_inline_code = false # @fence_char / @fence_length / @inline_delimiter are set by # open_fence / open_inline before any helper reads them; # they're only consulted when the corresponding in_X flag is # true, which requires a prior open_* call. end |
Instance Attribute Details
#in_fenced_block ⇒ Boolean (readonly)
Returns true if currently inside a fenced code block.
24 25 26 |
# File 'lib/markbridge/processors/discourse_markdown/code_block_tracker.rb', line 24 def in_fenced_block @in_fenced_block end |
#in_indented_block ⇒ Boolean (readonly)
Returns true if currently inside an indented code block.
27 28 29 |
# File 'lib/markbridge/processors/discourse_markdown/code_block_tracker.rb', line 27 def in_indented_block @in_indented_block end |
#in_inline_code ⇒ Boolean (readonly)
Returns true if currently inside an inline code span.
30 31 32 |
# File 'lib/markbridge/processors/discourse_markdown/code_block_tracker.rb', line 30 def in_inline_code @in_inline_code end |
Instance Method Details
#check_fenced_boundary(input, pos, line_start:) ⇒ Integer?
Check if position is at start of a fenced code block boundary
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/markbridge/processors/discourse_markdown/code_block_tracker.rb', line 53 def check_fenced_boundary(input, pos, line_start:) return nil unless line_start input_length = input.length scan_pos = skip_leading_spaces(input, pos) # No `scan_pos >= input_length` guard: `input[input_length]` is # nil, and `nil == "`"` / `nil == "~"` are both false so the # next check returns nil anyway. fence_char = input[scan_pos] return nil unless fence_char == "`" || fence_char == "~" fence_length, scan_pos = count_fence_chars(input, scan_pos, fence_char, input_length) return nil if fence_length < 3 if @in_fenced_block try_close_fence(input, scan_pos, fence_char, fence_length, input_length) else open_fence(input, scan_pos, fence_char, fence_length, input_length) end end |
#check_indented_boundary(input, pos, line_start:) ⇒ Integer?
Check if line at position is an indented code block line. A line is considered indented code if it starts with 4+ spaces or 1+ tab. Blank lines within an indented block are considered part of it.
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/markbridge/processors/discourse_markdown/code_block_tracker.rb', line 82 def check_indented_boundary(input, pos, line_start:) return nil unless line_start return nil if @in_fenced_block # Fenced blocks take precedence input_length = input.length line_end = input.index("\n", pos) || input_length line_content = input[pos...line_end] is_blank = line_content.match?(/\A\s*\z/) has_code_indent = line_content.start_with?(" ") || line_content.start_with?("\t") if @in_indented_block if is_blank || has_code_indent pos_after_line(line_end, input_length) else @in_indented_block = false nil end elsif has_code_indent @in_indented_block = true pos_after_line(line_end, input_length) end end |
#check_inline_boundary(input, pos) ⇒ Integer?
Check for inline code boundary
109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/markbridge/processors/discourse_markdown/code_block_tracker.rb', line 109 def check_inline_boundary(input, pos) return nil if @in_fenced_block || @in_indented_block # No `pos >= input_length` guard: `input[input_length]` is nil, # and `nil != "`"` is true so the next check returns nil anyway. return nil if input[pos] != "`" input_length = input.length if @in_inline_code try_close_inline(input, pos, input_length) else open_inline(input, pos, input_length) end end |
#in_code? ⇒ Boolean
Check if currently inside any code context
44 45 46 |
# File 'lib/markbridge/processors/discourse_markdown/code_block_tracker.rb', line 44 def in_code? @in_fenced_block || @in_indented_block || @in_inline_code end |
#reset! ⇒ Object
Reset the tracker state. The @fence_char / @fence_length / consulted while the corresponding in_* flag is true, and open_fence / open_inline overwrites them on the next opening (same pattern as try_close_fence / try_close_inline).
210 211 212 213 214 |
# File 'lib/markbridge/processors/discourse_markdown/code_block_tracker.rb', line 210 def reset! @in_fenced_block = false @in_indented_block = false @in_inline_code = false end |