Class: Markbridge::Renderers::Discourse::RenderContext
- Inherits:
-
Object
- Object
- Markbridge::Renderers::Discourse::RenderContext
- Defined in:
- lib/markbridge/renderers/discourse/render_context.rb
Overview
Immutable context for rendering, implemented as a linked parent chain: each context holds the nearest parent element plus a link to the enclosing context. #with_parent runs once per rendered element — the chain form makes it a single fixed-size allocation instead of copying (and freezing) a parents array per element. Provides query methods to ask about parent elements without the renderer knowing about specific element types.
Instance Attribute Summary collapse
-
#depth ⇒ Integer
readonly
Number of parent elements in the chain.
-
#element ⇒ AST::Element?
readonly
The nearest parent element (nil at root).
-
#parent_context ⇒ RenderContext?
readonly
The enclosing context (nil at root).
Instance Method Summary collapse
-
#count_parents(klass) ⇒ Integer
Count parents that are is_a? klass (handles subclasses).
-
#find_parent(klass) ⇒ AST::Element?
Find closest parent that is_a? klass (handles subclasses).
-
#has_parent?(klass) ⇒ Boolean
Check if any parent is_a? klass (handles subclasses).
- #html_mode? ⇒ Boolean
-
#initialize(parents = [], html_mode: false, parent: nil, element: nil) ⇒ RenderContext
constructor
A new instance of RenderContext.
-
#parents ⇒ Array<AST::Element>
Parent elements in document order (outermost first), materialized from the chain into a frozen Array.
-
#root? ⇒ Boolean
Check if we're at the root (no parents).
-
#with_html_mode(value) ⇒ RenderContext
Create new context with html_mode toggled.
-
#with_parent(element) ⇒ RenderContext
Create new context with element added to parent chain.
Constructor Details
#initialize(parents = [], html_mode: false, parent: nil, element: nil) ⇒ RenderContext
Returns a new instance of RenderContext.
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/markbridge/renderers/discourse/render_context.rb', line 29 def initialize(parents = [], html_mode: false, parent: nil, element: nil) @html_mode = html_mode if element @parent_context = parent @element = element @depth = (parent ? parent.depth : 0) + 1 elsif parents.empty? # Root context: @element and @parent_context stay unset and # read as nil. @depth = 0 else @parent_context = self.class.new(parents[0, parents.size - 1], html_mode:) @element = parents.last @depth = parents.size end end |
Instance Attribute Details
#depth ⇒ Integer (readonly)
Returns number of parent elements in the chain.
15 16 17 |
# File 'lib/markbridge/renderers/discourse/render_context.rb', line 15 def depth @depth end |
#element ⇒ AST::Element? (readonly)
Returns the nearest parent element (nil at root).
18 19 20 |
# File 'lib/markbridge/renderers/discourse/render_context.rb', line 18 def element @element end |
#parent_context ⇒ RenderContext? (readonly)
Returns the enclosing context (nil at root).
21 22 23 |
# File 'lib/markbridge/renderers/discourse/render_context.rb', line 21 def parent_context @parent_context end |
Instance Method Details
#count_parents(klass) ⇒ Integer
Count parents that are is_a? klass (handles subclasses).
99 100 101 102 103 104 105 106 107 |
# File 'lib/markbridge/renderers/discourse/render_context.rb', line 99 def count_parents(klass) count = 0 context = self while context && (parent = context.element) count += 1 if parent.is_a?(klass) context = context.parent_context end count end |
#find_parent(klass) ⇒ AST::Element?
Find closest parent that is_a? klass (handles subclasses). The chain walks are inlined in each query (instead of a shared yielding helper) — these run several times per rendered text node, and a plain while loop avoids the block invocation.
88 89 90 91 92 93 94 |
# File 'lib/markbridge/renderers/discourse/render_context.rb', line 88 def find_parent(klass) context = self while context && (parent = context.element) return parent if parent.is_a?(klass) context = context.parent_context end end |
#has_parent?(klass) ⇒ Boolean
Check if any parent is_a? klass (handles subclasses).
112 113 114 115 116 117 118 119 |
# File 'lib/markbridge/renderers/discourse/render_context.rb', line 112 def has_parent?(klass) context = self while context && (parent = context.element) return true if parent.is_a?(klass) context = context.parent_context end false end |
#html_mode? ⇒ Boolean
77 78 79 |
# File 'lib/markbridge/renderers/discourse/render_context.rb', line 77 def html_mode? @html_mode end |
#parents ⇒ Array<AST::Element>
Parent elements in document order (outermost first), materialized from the chain into a frozen Array. Allocates on every call — prefer #find_parent / #has_parent? / #count_parents on hot paths.
51 52 53 54 55 56 57 58 59 60 |
# File 'lib/markbridge/renderers/discourse/render_context.rb', line 51 def parents result = [] context = self while context && (parent = context.element) result << parent context = context.parent_context end result.reverse! result.freeze end |
#root? ⇒ Boolean
Check if we're at the root (no parents).
123 124 125 |
# File 'lib/markbridge/renderers/discourse/render_context.rb', line 123 def root? @depth.zero? end |
#with_html_mode(value) ⇒ RenderContext
Create new context with html_mode toggled.
72 73 74 |
# File 'lib/markbridge/renderers/discourse/render_context.rb', line 72 def with_html_mode(value) self.class.new(html_mode: value, parent: @parent_context, element: @element) end |
#with_parent(element) ⇒ RenderContext
Create new context with element added to parent chain.
65 66 67 |
# File 'lib/markbridge/renderers/discourse/render_context.rb', line 65 def with_parent(element) self.class.new(html_mode: @html_mode, parent: self, element:) end |