Class: Markbridge::Parsers::TextFormatter::HandlerRegistry

Inherits:
Object
  • Object
show all
Defined in:
lib/markbridge/parsers/text_formatter/handler_registry.rb

Overview

Registry of s9e/TextFormatter XML element handlers

Manages mappings between XML element names and handler objects. Handlers must respond to #process(element:, parent:) and return the created element if children should be processed, or nil otherwise.

Examples:

Using default mappings

registry = HandlerRegistry.default
element = registry.process_element(xml_element, parent)

Customizing mappings with handler objects

registry = HandlerRegistry.build_from_default do |r|
  r.register("CUSTOM", MyCustomHandler.new)
  r.register("B", SimpleHandler.new(AST::Bold))  # Override default
end

Using lambdas for simple mappings

registry = HandlerRegistry.new
registry.register("CUSTOM", ->(element:, parent:) {
  node = AST::Custom.new
  parent << node
  node  # Return node to process children
})

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeHandlerRegistry

Returns a new instance of HandlerRegistry.



43
44
45
# File 'lib/markbridge/parsers/text_formatter/handler_registry.rb', line 43

def initialize
  @mappings = {}
end

Class Method Details

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

Build from default mappings with custom additions

Yields:

Returns:



39
40
41
# File 'lib/markbridge/parsers/text_formatter/handler_registry.rb', line 39

def self.build_from_default
  default.tap { |registry| yield registry if block_given? }
end

.defaultHandlerRegistry

Create a new registry with default mappings

Returns:



32
33
34
# File 'lib/markbridge/parsers/text_formatter/handler_registry.rb', line 32

def self.default
  new.tap(&:register_defaults)
end

Instance Method Details

#has_handler?(element_name) ⇒ Boolean

Check if a handler is registered for an element

Parameters:

  • element_name (String)

    XML element name

Returns:

  • (Boolean)

    true if handler is registered



61
62
63
# File 'lib/markbridge/parsers/text_formatter/handler_registry.rb', line 61

def has_handler?(element_name)
  @mappings.key?(element_name.upcase)
end

#process_element(element, parent) ⇒ AST::Element?

Process an XML element using the registered handler

Parameters:

  • element (Nokogiri::XML::Element)
  • parent (AST::Element)

    parent node to add children to

Returns:

  • (AST::Element, nil)

    the created element if children should be processed, nil otherwise



69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/markbridge/parsers/text_formatter/handler_registry.rb', line 69

def process_element(element, parent)
  tag_name = element.name.upcase
  handler = @mappings[tag_name]
  return nil unless handler

  # Call handler and return its result (element or nil)
  if handler.respond_to?(:process)
    handler.process(element:, parent:)
  elsif handler.respond_to?(:call)
    handler.call(element:, parent:)
  else
    raise ArgumentError, "Handler must respond to :process or :call"
  end
end

#register(element_name, handler) ⇒ Object

Register a handler for an element

Examples:

With handler object

registry.register("CUSTOM", MyCustomHandler.new)

With lambda

registry.register("CUSTOM", ->(element:, parent:) { ... })

Parameters:

  • element_name (String)

    XML element name (case-insensitive)

  • handler (#process, #call)

    Handler object or lambda



54
55
56
# File 'lib/markbridge/parsers/text_formatter/handler_registry.rb', line 54

def register(element_name, handler)
  @mappings[element_name.upcase] = handler
end

#register_defaultsObject

Register all default s9e/TextFormatter element mappings



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/markbridge/parsers/text_formatter/handler_registry.rb', line 85

def register_defaults
  # Simple formatting elements
  register("B", Handlers::SimpleHandler.new(AST::Bold))
  register("I", Handlers::SimpleHandler.new(AST::Italic))
  register("U", Handlers::SimpleHandler.new(AST::Underline))
  register("S", Handlers::SimpleHandler.new(AST::Strikethrough))

  # Complex elements with attributes
  register("URL", Handlers::UrlHandler.new)
  register("EMAIL", Handlers::EmailHandler.new)
  register("CODE", Handlers::CodeHandler.new)
  register("QUOTE", Handlers::QuoteHandler.new)
  register("IMG", Handlers::ImageHandler.new)
  register("LIST", Handlers::ListHandler.new)
  register(
    "COLOR",
    Handlers::AttributeHandler.new(AST::Color, attribute: :color, param: :color),
  )
  register(
    "SIZE",
    Handlers::AttributeHandler.new(AST::Size, attribute: :size, param: :size),
  )
  register(
    "ALIGN",
    Handlers::AttributeHandler.new(AST::Align, attribute: :align, param: :alignment),
  )
  register(
    "SPOILER",
    Handlers::AttributeHandler.new(AST::Spoiler, attribute: :title, param: :title),
  )
  register("ATTACHMENT", Handlers::AttachmentHandler.new)
  register("ATTACH", Handlers::AttachmentHandler.new)

  # List item (supports both LI and * for compatibility)
  register("LI", Handlers::SimpleHandler.new(AST::ListItem))
  register("*", Handlers::SimpleHandler.new(AST::ListItem))

  # Paragraphs
  register("P", Handlers::SimpleHandler.new(AST::Paragraph))

  # Table elements
  register("TABLE", Handlers::SimpleHandler.new(AST::Table))
  register("TR", Handlers::SimpleHandler.new(AST::TableRow))
  register("TD", Handlers::TableCellHandler.new)
  register("TH", Handlers::TableCellHandler.new)

  self
end