Class: Markbridge::Renderers::Discourse::Renderer
- Inherits:
-
Object
- Object
- Markbridge::Renderers::Discourse::Renderer
- Defined in:
- lib/markbridge/renderers/discourse/renderer.rb
Overview
Renders AST to Discourse-flavored Markdown in-memory.
Instance Attribute Summary collapse
-
#postprocessor ⇒ Object
readonly
Returns the value of attribute postprocessor.
Instance Method Summary collapse
-
#initialize(tag_library: nil, escaper: nil, html_escaper: nil, postprocessor: nil) ⇒ Renderer
constructor
A new instance of Renderer.
-
#render(node, context: RenderContext.new) ⇒ String
Render a node to Markdown.
-
#render_children(node, context:) ⇒ String
Render all children of a node.
-
#render_default(node, context: RenderContext.new) ⇒ String
Render a node with the stock tag for its class, ignoring any override registered in this renderer's tag library.
Constructor Details
#initialize(tag_library: nil, escaper: nil, html_escaper: nil, postprocessor: nil) ⇒ Renderer
Returns a new instance of Renderer.
10 11 12 13 14 15 16 17 18 |
# File 'lib/markbridge/renderers/discourse/renderer.rb', line 10 def initialize(tag_library: nil, escaper: nil, html_escaper: nil, postprocessor: nil) @tag_library = tag_library || TagLibrary.shared_default @escaper = escaper || MarkdownEscaper.new @html_escaper = html_escaper || HtmlEscaper @postprocessor = postprocessor || Postprocessor::DEFAULT # @interface_cache, @resolved_tags, and @resolved_default_tags # are lazily initialized during a top-level #render / # #render_default call and reset to nil after the call completes. end |
Instance Attribute Details
#postprocessor ⇒ Object (readonly)
Returns the value of attribute postprocessor.
8 9 10 |
# File 'lib/markbridge/renderers/discourse/renderer.rb', line 8 def postprocessor @postprocessor end |
Instance Method Details
#render(node, context: RenderContext.new) ⇒ String
Render a node to Markdown
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 |
# File 'lib/markbridge/renderers/discourse/renderer.rb', line 28 def render(node, context: RenderContext.new) root_call = @interface_cache.nil? @interface_cache = {} if root_call # Exact-class hit first (a single Hash lookup, the common case), # then the memoized ancestry fallback so a subclass without its # own tag renders through its nearest ancestor's tag. tag = @tag_library[node.class] || resolved_tag(node.class) if tag result = tag.render(node, interface_for(context)) unless result.is_a?(String) raise TypeError, "#{tag.class} rendered #{node.class} to " \ "#{result.inspect} — tags must return a String " \ "(use interface.render_default(node) to fall back " \ "to the stock rendering)" end return result end render_without_tag(node, context) ensure if root_call @interface_cache = nil @resolved_tags = nil @resolved_default_tags = nil end end |
#render_children(node, context:) ⇒ String
Render all children of a node
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/markbridge/renderers/discourse/renderer.rb', line 93 def render_children(node, context:) result = +"" node.children.each do |child| part = render(child, context:) next if part.empty? # Integer-byte check avoids allocating substrings for the # per-child adjacency probe. EMPHASIS_DELIMITER_BYTES.include? # over a 4-element Set is O(1). if !result.empty? && (last_byte = result.getbyte(-1)) == part.getbyte(0) && EMPHASIS_DELIMITER_BYTES.include?(last_byte) result << EMPHASIS_BOUNDARY end result << part end result end |
#render_default(node, context: RenderContext.new) ⇒ String
Render a node with the stock tag for its class, ignoring any override registered in this renderer's tag library. Lets a custom tag intercept only the nodes it cares about and delegate the rest:
library.register(AST::Quote, Tag.new do |node, interface|
next interface.render_default(node) unless node.username&.start_with?("legacy_")
...custom rendering...
end)
Children still render through this renderer, so overrides for other node classes keep applying inside the delegated subtree.
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/markbridge/renderers/discourse/renderer.rb', line 73 def render_default(node, context: RenderContext.new) root_call = @interface_cache.nil? @interface_cache = {} if root_call tag = default_tag_library[node.class] || resolved_default_tag(node.class) return tag.render(node, interface_for(context)) if tag render_without_tag(node, context) ensure if root_call @interface_cache = nil @resolved_tags = nil @resolved_default_tags = nil end end |