Class: Markbridge::Parsers::HTML::HandlerRegistry
- Inherits:
-
Object
- Object
- Markbridge::Parsers::HTML::HandlerRegistry
- Defined in:
- lib/markbridge/parsers/html/handler_registry.rb
Overview
Registry of HTML tag handlers and per-tag-name parser configuration.
Handlers map a tag name to a handler instance. block_level_tags and
whitespace_preserving_tags configure parser whitespace behavior by
tag name, independent of whether a handler is registered — so unknown
tags like
/ still pass through verbatim. Both sets are mutable, so
downstream consumers can add or remove tags freely:
registry = HandlerRegistry.default
registry.block_level_tags << "my-block"
registry.whitespace_preserving_tags.delete("tt")
Constant Summary collapse
- DEFAULT_BLOCK_LEVEL_TAGS =
HTML5 block-level elements (per MDN). The trim-before-block rule applies to these regardless of whether a handler is registered.
%w[ address article aside blockquote canvas dd details dialog div dl dt fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 header hgroup hr html li main nav noscript ol output p pre section table tbody td tfoot th thead tr ul video ].freeze
- DEFAULT_WHITESPACE_PRESERVING_TAGS =
Tags whose default CSS preserves source whitespace (
white-space: pre*). Text inside these is passed through verbatim; outside,\s+runs collapse to a single space. %w[pre code textarea tt].freeze
Instance Attribute Summary collapse
-
#block_level_tags ⇒ Set<String>
readonly
Mutable set of tag names treated as block-level.
-
#whitespace_preserving_tags ⇒ Set<String>
readonly
Mutable set of tag names whose contents preserve source whitespace.
Class Method Summary collapse
-
.build_from_default {|HandlerRegistry| ... } ⇒ HandlerRegistry
Build a registry from the default configuration with optional customization.
-
.default ⇒ HandlerRegistry
Create the default handler registry with common HTML tags.
-
.shared_default ⇒ HandlerRegistry
Shared, deep-frozen default registry for the no-customization fast path.
Instance Method Summary collapse
-
#[](tag_name) ⇒ BaseHandler?
Get handler for a tag name.
-
#freeze ⇒ Object
Freeze the registry together with its internal collections so that mutation of a shared instance fails loudly instead of silently changing state visible to every parser.
-
#initialize ⇒ HandlerRegistry
constructor
A new instance of HandlerRegistry.
-
#overlay(tag_names) {|previous| ... } ⇒ self
Replace the handler bound to one or more tag names by yielding the previously-bound handler (which may be
nil) and registering whatever the block returns. -
#register(tag_names, handler) ⇒ Object
Register a handler for one or more tag names.
Constructor Details
#initialize ⇒ HandlerRegistry
Returns a new instance of HandlerRegistry.
80 81 82 83 84 |
# File 'lib/markbridge/parsers/html/handler_registry.rb', line 80 def initialize @handlers = {} @block_level_tags = Set.new(DEFAULT_BLOCK_LEVEL_TAGS) @whitespace_preserving_tags = Set.new(DEFAULT_WHITESPACE_PRESERVING_TAGS) end |
Instance Attribute Details
#block_level_tags ⇒ Set<String> (readonly)
Returns mutable set of tag names treated as block-level.
74 75 76 |
# File 'lib/markbridge/parsers/html/handler_registry.rb', line 74 def @block_level_tags end |
#whitespace_preserving_tags ⇒ Set<String> (readonly)
Returns mutable set of tag names whose contents preserve source whitespace.
78 79 80 |
# File 'lib/markbridge/parsers/html/handler_registry.rb', line 78 def @whitespace_preserving_tags end |
Class Method Details
.build_from_default {|HandlerRegistry| ... } ⇒ HandlerRegistry
Build a registry from the default configuration with optional customization
150 151 152 153 154 |
# File 'lib/markbridge/parsers/html/handler_registry.rb', line 150 def self.build_from_default registry = default yield(registry) if block_given? registry end |
.default ⇒ HandlerRegistry
Create the default handler registry with common HTML tags
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/markbridge/parsers/html/handler_registry.rb', line 123 def self.default new.tap do |registry| registry.register(%w[b strong], Handlers::SimpleHandler.new(AST::Bold)) registry.register(%w[i em], Handlers::SimpleHandler.new(AST::Italic)) registry.register(%w[s strike del], Handlers::SimpleHandler.new(AST::Strikethrough)) registry.register("u", Handlers::SimpleHandler.new(AST::Underline)) registry.register("sup", Handlers::SimpleHandler.new(AST::Superscript)) registry.register("sub", Handlers::SimpleHandler.new(AST::Subscript)) registry.register(%w[code pre tt], Handlers::RawHandler.new(AST::Code)) registry.register("a", Handlers::UrlHandler.new) registry.register("img", Handlers::ImageHandler.new) registry.register("blockquote", Handlers::QuoteHandler.new) registry.register("br", Handlers::SelfClosingHandler.new(AST::LineBreak)) registry.register("hr", Handlers::SelfClosingHandler.new(AST::HorizontalRule)) registry.register(%w[ul ol], Handlers::ListHandler.new) registry.register("li", Handlers::ListItemHandler.new) registry.register("table", Handlers::TableHandler.new) registry.register("tr", Handlers::TableRowHandler.new) registry.register(%w[td th], Handlers::TableCellHandler.new) registry.register("p", Handlers::ParagraphHandler.new) registry.register("span", Handlers::SpanHandler.new) end end |
.shared_default ⇒ HandlerRegistry
Shared, deep-frozen default registry for the no-customization
fast path. Built once per process; Parser falls back to it
when no handlers: are given, skipping the full registry
construction on every parse. Handlers are stateless after
construction, so sharing is safe across parsers and threads.
Callers who want to mutate the tag sets must build their own
default.
165 166 167 |
# File 'lib/markbridge/parsers/html/handler_registry.rb', line 165 def self.shared_default @shared_default ||= default.freeze end |
Instance Method Details
#[](tag_name) ⇒ BaseHandler?
Get handler for a tag name
114 115 116 117 118 119 |
# File 'lib/markbridge/parsers/html/handler_registry.rb', line 114 def [](tag_name) # Keys are always downcased strings and Nokogiri's HTML parser # yields downcased element names, so the fetch hits directly on # the hot path; the block normalizes only unusual lookups. @handlers.fetch(tag_name) { @handlers[tag_name.to_s.downcase] } end |
#freeze ⇒ Object
Freeze the registry together with its internal collections so that mutation of a shared instance fails loudly instead of silently changing state visible to every parser.
172 173 174 175 176 177 |
# File 'lib/markbridge/parsers/html/handler_registry.rb', line 172 def freeze @handlers.freeze @block_level_tags.freeze @whitespace_preserving_tags.freeze super end |
#overlay(tag_names) {|previous| ... } ⇒ self
Replace the handler bound to one or more tag names by yielding
the previously-bound handler (which may be nil) and
registering whatever the block returns. Used to install a
delegating handler that wraps the default.
103 104 105 106 107 108 109 |
# File 'lib/markbridge/parsers/html/handler_registry.rb', line 103 def (tag_names) Array(tag_names).each do |name| previous = self[name] register(name, yield(previous)) end self end |
#register(tag_names, handler) ⇒ Object
Register a handler for one or more tag names
90 91 92 93 |
# File 'lib/markbridge/parsers/html/handler_registry.rb', line 90 def register(tag_names, handler) Array(tag_names).each { |tag_name| @handlers[tag_name.to_s.downcase] = handler } self end |