Class: Markbridge::Parsers::HTML::HandlerRegistry

Inherits:
Object
  • Object
show all
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 <div> or <section> still trigger boundary collapsing and <pre>/<code> 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

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeHandlerRegistry

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_tagsSet<String> (readonly)

Returns mutable set of tag names treated as block-level.

Returns:

  • (Set<String>)

    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
  @block_level_tags
end

#whitespace_preserving_tagsSet<String> (readonly)

Returns mutable set of tag names whose contents preserve source whitespace.

Returns:

  • (Set<String>)

    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
  @whitespace_preserving_tags
end

Class Method Details

.build_from_default {|HandlerRegistry| ... } ⇒ HandlerRegistry

Build a registry from the default configuration with optional customization

Yields:

Returns:



147
148
149
150
151
# File 'lib/markbridge/parsers/html/handler_registry.rb', line 147

def self.build_from_default
  registry = default
  yield(registry) if block_given?
  registry
end

.defaultHandlerRegistry

Create the default handler registry with common HTML tags

Returns:



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/markbridge/parsers/html/handler_registry.rb', line 120

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

Instance Method Details

#[](tag_name) ⇒ BaseHandler?

Get handler for a tag name

Parameters:

  • tag_name (String)

Returns:

  • (BaseHandler, nil)


114
115
116
# File 'lib/markbridge/parsers/html/handler_registry.rb', line 114

def [](tag_name)
  @handlers[tag_name.to_s.downcase]
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.

Parameters:

  • tag_names (String, Array<String>)

Yield Parameters:

  • previous (BaseHandler, nil)

    previously bound handler

Returns:

  • (self)


103
104
105
106
107
108
109
# File 'lib/markbridge/parsers/html/handler_registry.rb', line 103

def overlay(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

Parameters:

  • tag_names (String, Array<String>)

    tag name(s) to register

  • handler (BaseHandler)

    the handler instance — must respond to #process(element:, parent:)



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