Class: Docbook::Mirror::Handlers::Inline

Inherits:
Object
  • Object
show all
Defined in:
lib/docbook/mirror/handlers/inline.rb

Constant Summary collapse

HANDLER_MAP =

Registry mapping element classes to [method_symbol, concat_flag]. Third-party code can add entries to extend inline handling (OCP).

{}.tap do |h|
  h[Docbook::Elements::Emphasis] = [:emphasis, false]
  h[Docbook::Elements::Link] = [:link, false]
  h[Docbook::Elements::Xref] = [:xref, false]
  h[Docbook::Elements::Quote] = [:quote, true]
  h[Docbook::Elements::Tag] = [:tag, false]
  h[Docbook::Elements::Biblioref] = [:biblioref, false]
  h[Docbook::Elements::FirstTerm] = [:firstterm, false]
  h[Docbook::Elements::Glossterm] = [:firstterm, false]
  h[Docbook::Elements::Citetitle] = [:citetitle, false]
  h[Docbook::Elements::Inlinemediaobject] = [:inline_image, false]
  h[Docbook::Elements::ProductName] = [:productname, false]
  h[Docbook::Elements::Trademark] = [:trademark, false]
  h[Docbook::Elements::Email] = [:email, false]
  h[Docbook::Elements::Uri] = [:uri, false]
  h[Docbook::Elements::Subscript] = [:subscript, false]
  h[Docbook::Elements::Superscript] = [:superscript, false]
  h[Docbook::Elements::KeyCap] = [:keycap, false]
  h[Docbook::Elements::CiterefEntry] = [:citerefentry, false]
  h[Docbook::Elements::Footnote] = [:footnote, false]
  h[Docbook::Elements::FootnoteRef] = [:footnoteref, false]

  # Code-style elements → all use the :code handler
  [
    Docbook::Elements::Literal, Docbook::Elements::Code,
    Docbook::Elements::UserInput, Docbook::Elements::ComputerOutput,
    Docbook::Elements::Filename, Docbook::Elements::ClassName,
    Docbook::Elements::Function, Docbook::Elements::Parameter,
    Docbook::Elements::Replaceable,
    Docbook::Elements::Command, Docbook::Elements::Option,
    Docbook::Elements::Envar, Docbook::Elements::Property,
    Docbook::Elements::Varname, Docbook::Elements::Type,
    Docbook::Elements::Errortype, Docbook::Elements::Errorcode,
    Docbook::Elements::Exceptionname, Docbook::Elements::Constant,
    Docbook::Elements::Prompt, Docbook::Elements::BuildTarget,
    Docbook::Elements::Enumvalue
  ].each { |k| h[k] = [:code, false] }

  # Plain text elements → all use the :plain_text handler
  [
    Docbook::Elements::Abbrev, Docbook::Elements::Phrase,
    Docbook::Elements::Application, Docbook::Elements::WordAsWord,
    Docbook::Elements::Date, Docbook::Elements::ReleaseInfo
  ].each { |k| h[k] = [:plain_text, false] }
end.freeze

Class Method Summary collapse

Class Method Details

.biblioref(element, context:) ⇒ Object



172
173
174
175
176
177
# File 'lib/docbook/mirror/handlers/inline.rb', line 172

def self.biblioref(element, context:)
  linkend = element.linkend.to_s
  text = element.content.join.empty? ? linkend : element.content.join
  context.text_node(text,
                    marks: [Mark::Citation.new(bibref: linkend)])
end

.citerefentry(element, context:) ⇒ Object



251
252
253
254
255
256
# File 'lib/docbook/mirror/handlers/inline.rb', line 251

def self.citerefentry(element, context:)
  title = element.refentrytitle&.content&.join
  manvol = element.manvolnum&.content&.join
  text = manvol.empty? ? title : "#{title}(#{manvol})"
  context.text_node(text)
end

.citetitle(element, context:) ⇒ Object



184
185
186
187
188
# File 'lib/docbook/mirror/handlers/inline.rb', line 184

def self.citetitle(element, context:)
  text = element.content.join
  context.text_node(text,
                    marks: [Mark::Citation.new(bibref: element.href)])
end

.code(element, context:) ⇒ Object



109
110
111
112
113
# File 'lib/docbook/mirror/handlers/inline.rb', line 109

def self.code(element, context:)
  role = code_role(element)
  text = context.extract_text(element)
  context.text_node(text, marks: [Mark::Code.new(role: role)])
end

.email(element, context:) ⇒ Object



219
220
221
222
223
# File 'lib/docbook/mirror/handlers/inline.rb', line 219

def self.email(element, context:)
  text = element.content.join
  context.text_node(text,
                    marks: [Mark::Link.new(href: "mailto:#{text}")])
end

.emphasis(element, context:) ⇒ Object

-- Individual inline element handlers --



96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/docbook/mirror/handlers/inline.rb', line 96

def self.emphasis(element, context:)
  role = element.role
  mark = if %w[bold strong].include?(role)
           Mark::Strong.new
         elsif role == "italic"
           Mark::Italic.new
         else
           Mark::Emphasis.new
         end
  text = element.content.join
  context.text_node(text, marks: [mark])
end

.firstterm(element, context:) ⇒ Object



179
180
181
182
# File 'lib/docbook/mirror/handlers/inline.rb', line 179

def self.firstterm(element, context:)
  text = context.extract_text(element)
  context.text_node(text, marks: [Mark::Emphasis.new])
end

.footnote(element, context:) ⇒ Object



263
264
265
# File 'lib/docbook/mirror/handlers/inline.rb', line 263

def self.footnote(element, context:)
  Handlers::Footnote.call(element, context: context)
end

.footnoteref(element, context:) ⇒ Object



267
268
269
# File 'lib/docbook/mirror/handlers/inline.rb', line 267

def self.footnoteref(element, context:)
  Handlers::Footnote.ref(element, context: context)
end

.inline_image(element, context:) ⇒ Object

Cross-handler delegation wrappers (for registry uniformity)



259
260
261
# File 'lib/docbook/mirror/handlers/inline.rb', line 259

def self.inline_image(element, context:)
  Handlers::Media.inline_image(element, context: context)
end

.keycap(element, context:) ⇒ Object



240
241
242
243
244
# File 'lib/docbook/mirror/handlers/inline.rb', line 240

def self.keycap(element, context:)
  text = element.content.join
  context.text_node(text,
                    marks: [Mark::Code.new(role: "keycap")])
end


115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/docbook/mirror/handlers/inline.rb', line 115

def self.link(element, context:)
  xml_id_map = context.xml_id_map
  href = element.xlink_href&.to_s || (element.linkend ? "##{element.linkend}" : "#")

  # Handle self-closing links with no content
  if element.content.join.empty? && !has_inline_children?(element)
    # For linkend references, resolve the title from xml_id_map
    if element.linkend
      text = xml_id_map[element.linkend.to_s] || element.linkend.to_s
    else
      uri = begin
        URI(href)
      rescue StandardError
        nil
      end
      text = if uri&.path && !uri.path.empty? && uri.path != "/"
               File.basename(uri.path)
             elsif uri&.host
               uri.host
             else
               href
             end
    end
  else
    text = context.extract_text(element)
  end

  link_mark = if element.linkend
                Mark::Link.new(linkend: element.linkend)
              else
                Mark::Link.new(href: href)
              end

  context.text_node(text, marks: [link_mark])
end

.plain_text(element, context:) ⇒ Object



246
247
248
249
# File 'lib/docbook/mirror/handlers/inline.rb', line 246

def self.plain_text(element, context:)
  text = element.content.join
  context.text_node(text)
end

.process(element, context:) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/docbook/mirror/handlers/inline.rb', line 57

def self.process(element, context:)
  return [] unless element.is_a?(Lutaml::Model::Serializable)

  children = []
  element.each_mixed_content do |node|
    if node.is_a?(String)
      children << Node::Text.new(text: node) unless node.empty?
    else
      dispatch_inline(node, children, context)
    end
  end
  children
end

.productname(element, context:) ⇒ Object



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/docbook/mirror/handlers/inline.rb', line 190

def self.productname(element, context:)
  text = element.content.join
  suffix = case element.class_name
           when "trade" then "\u2122"
           when "registered" then "\u00AE"
           when "copyright" then "\u00A9"
           when "service" then "\u2120"
           else ""
           end
  full_text = text + suffix
  if element.href
    context.text_node(full_text,
                      marks: [Mark::Link.new(attrs: { href: element.href })])
  else
    context.text_node(full_text, marks: [Mark::Strong.new])
  end
end

.quote(element, context:) ⇒ Object



162
163
164
# File 'lib/docbook/mirror/handlers/inline.rb', line 162

def self.quote(element, context:)
  process(element, context: context)
end

.subscript(element, context:) ⇒ Object



230
231
232
233
# File 'lib/docbook/mirror/handlers/inline.rb', line 230

def self.subscript(element, context:)
  text = element.content.join
  context.text_node(text, marks: [Mark.new(type: "subscript")])
end

.superscript(element, context:) ⇒ Object



235
236
237
238
# File 'lib/docbook/mirror/handlers/inline.rb', line 235

def self.superscript(element, context:)
  text = element.content.join
  context.text_node(text, marks: [Mark.new(type: "superscript")])
end

.tag(element, context:) ⇒ Object



166
167
168
169
170
# File 'lib/docbook/mirror/handlers/inline.rb', line 166

def self.tag(element, context:)
  tag_name = element.content.join
  text = "<#{tag_name}>"
  context.text_node(text, marks: [Mark::Code.new(role: "tag")])
end

.trademark(element, context:) ⇒ Object



208
209
210
211
212
213
214
215
216
217
# File 'lib/docbook/mirror/handlers/inline.rb', line 208

def self.trademark(element, context:)
  text = element.content.join
  suffix = case element.class_name
           when "registered" then "\u00AE"
           when "copyright" then "\u00A9"
           when "service" then "\u2120"
           else "\u2122"
           end
  context.text_node(text + suffix)
end

.uri(element, context:) ⇒ Object



225
226
227
228
# File 'lib/docbook/mirror/handlers/inline.rb', line 225

def self.uri(element, context:)
  text = element.content.join
  context.text_node(text, marks: [Mark::Link.new(href: text)])
end

.xref(element, context:) ⇒ Object



151
152
153
154
155
156
157
158
159
160
# File 'lib/docbook/mirror/handlers/inline.rb', line 151

def self.xref(element, context:)
  xml_id_map = context.xml_id_map
  linkend = element.linkend.to_s
  resolved_title = xml_id_map[linkend] || linkend
  context.text_node(
    resolved_title,
    marks: [Mark::Xref.new(linkend: linkend,
                           resolved: resolved_title)],
  )
end