Class: Markbridge::Parsers::BBCode::ClosingStrategies::TagReconciler
- Inherits:
-
Object
- Object
- Markbridge::Parsers::BBCode::ClosingStrategies::TagReconciler
- Defined in:
- lib/markbridge/parsers/bbcode/closing_strategies/tag_reconciler.rb
Overview
Encapsulates logic for reconciling mismatched closing tags
Constant Summary collapse
- MAX_AUTO_CLOSE_DEPTH =
5
Instance Method Summary collapse
-
#initialize(registry:) ⇒ TagReconciler
constructor
A new instance of TagReconciler.
-
#try_auto_close(handler:, context:) ⇒ Boolean
Attempt to auto-close tags to match a closing tag.
-
#try_reopen(handler:, context:, tokens:) ⇒ Boolean
Attempt to close the target tag and reopen any intervening auto-closeable tags so subsequent content continues in the same formatting context.
-
#try_reorder(handler:, tokens:, context:) ⇒ Boolean
Attempt to reorder closing tags.
Constructor Details
#initialize(registry:) ⇒ TagReconciler
Returns a new instance of TagReconciler.
11 12 13 |
# File 'lib/markbridge/parsers/bbcode/closing_strategies/tag_reconciler.rb', line 11 def initialize(registry:) @registry = registry end |
Instance Method Details
#try_auto_close(handler:, context:) ⇒ Boolean
Attempt to auto-close tags to match a closing tag
20 21 22 23 24 25 26 27 28 |
# File 'lib/markbridge/parsers/bbcode/closing_strategies/tag_reconciler.rb', line 20 def try_auto_close(handler:, context:) count = auto_close_count(handler, context) return false if count.nil? count.times { context.pop } context.auto_close!(count) true end |
#try_reopen(handler:, context:, tokens:) ⇒ Boolean
Attempt to close the target tag and reopen any intervening auto-closeable tags so subsequent content continues in the same formatting context. Used when closing tags are not adjacent (e.g. “[b][i]x more”).
Reopening only makes sense when there is upcoming content that would benefit from the reopened context. If the next token is a closing tag (or nothing), plain auto-close is correct.
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/markbridge/parsers/bbcode/closing_strategies/tag_reconciler.rb', line 43 def try_reopen(handler:, context:, tokens:) case tokens&.peek when TextToken, TagStartToken nil # content follows -> reopening is justified else return false end match_depth = find_matching_handler_depth(handler, context) return false if match_depth.nil? || match_depth.zero? return false unless all_auto_closeable?(context, match_depth) intervening = context.elements_from_current(match_depth - 1).map(&:class) count = match_depth + 1 count.times { context.pop } context.auto_close!(count) intervening.reverse_each { |klass| context.push(klass.new) } true end |
#try_reorder(handler:, tokens:, context:) ⇒ Boolean
Attempt to reorder closing tags
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/markbridge/parsers/bbcode/closing_strategies/tag_reconciler.rb', line 72 def try_reorder(handler:, tokens:, context:) match_depth = find_matching_handler_depth(handler, context) opening_handlers = collect_auto_closeable_handlers(context, match_depth) closing_handlers = [handler, *peek_closing_handlers(tokens, opening_handlers.size - 1)] unless opening_handlers.sort_by(&:object_id) == closing_handlers.sort_by(&:object_id) return false end # Consume the extra closing tags. We've already verified via # peek_closing_handlers that the next opening_handlers.size - 1 # tokens are TagEndTokens with handlers we accept. (opening_handlers.size - 1).times { tokens.next } opening_handlers.each { context.pop } context.auto_close!(opening_handlers.size) true end |