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 |
# 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 is lazily initialized in #render's top-level # 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
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/markbridge/renderers/discourse/renderer.rb', line 27 def render(node, context: RenderContext.new) root_call = @interface_cache.nil? @interface_cache = {} if root_call tag = @tag_library[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 @interface_cache = nil if root_call end |
#render_children(node, context:) ⇒ String
Render all children of a node
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/markbridge/renderers/discourse/renderer.rb', line 81 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.
65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/markbridge/renderers/discourse/renderer.rb', line 65 def render_default(node, context: RenderContext.new) root_call = @interface_cache.nil? @interface_cache = {} if root_call tag = default_tag_library[node.class] return tag.render(node, interface_for(context)) if tag render_without_tag(node, context) ensure @interface_cache = nil if root_call end |