isodoc 1.1.4 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/lib/isodoc-yaml/i18n-en.yaml +4 -1
  3. data/lib/isodoc-yaml/i18n-fr.yaml +4 -1
  4. data/lib/isodoc-yaml/i18n-zh-Hans.yaml +4 -1
  5. data/lib/isodoc.rb +1 -0
  6. data/lib/isodoc/common.rb +0 -2
  7. data/lib/isodoc/convert.rb +33 -27
  8. data/lib/isodoc/function/blocks.rb +10 -22
  9. data/lib/isodoc/function/blocks_example_note.rb +14 -15
  10. data/lib/isodoc/function/cleanup.rb +5 -4
  11. data/lib/isodoc/function/inline.rb +6 -76
  12. data/lib/isodoc/function/references.rb +10 -9
  13. data/lib/isodoc/function/reqt.rb +12 -11
  14. data/lib/isodoc/function/section.rb +39 -54
  15. data/lib/isodoc/function/table.rb +1 -6
  16. data/lib/isodoc/function/terms.rb +13 -6
  17. data/lib/isodoc/function/to_word_html.rb +1 -0
  18. data/lib/isodoc/function/utils.rb +4 -3
  19. data/lib/isodoc/html_function/html.rb +0 -1
  20. data/lib/isodoc/{function/i18n.rb → i18n.rb} +37 -36
  21. data/lib/isodoc/metadata.rb +4 -3
  22. data/lib/isodoc/metadata_date.rb +1 -1
  23. data/lib/isodoc/presentation_function/block.rb +138 -0
  24. data/lib/isodoc/presentation_function/inline.rb +131 -0
  25. data/lib/isodoc/presentation_function/section.rb +46 -0
  26. data/lib/isodoc/presentation_xml_convert.rb +38 -5
  27. data/lib/isodoc/version.rb +1 -1
  28. data/lib/isodoc/word_function/body.rb +12 -8
  29. data/lib/isodoc/word_function/inline.rb +3 -1
  30. data/lib/isodoc/xref.rb +5 -3
  31. data/lib/isodoc/xref/xref_sect_gen.rb +3 -3
  32. data/spec/assets/i18n.yaml +12 -1
  33. data/spec/isodoc/blocks_spec.rb +1101 -147
  34. data/spec/isodoc/cleanup_spec.rb +2 -2
  35. data/spec/isodoc/footnotes_spec.rb +2 -2
  36. data/spec/isodoc/i18n_spec.rb +679 -110
  37. data/spec/isodoc/inline_spec.rb +323 -142
  38. data/spec/isodoc/lists_spec.rb +2 -2
  39. data/spec/isodoc/postproc_spec.rb +1311 -1333
  40. data/spec/isodoc/ref_spec.rb +181 -3
  41. data/spec/isodoc/section_spec.rb +508 -680
  42. data/spec/isodoc/table_spec.rb +155 -4
  43. data/spec/isodoc/terms_spec.rb +111 -79
  44. data/spec/isodoc/xref_spec.rb +1569 -1186
  45. metadata +6 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8c7c8cd474b9df23e50d6f4f606bfccf2ed246dae1f020b5df2c6dfc3d06ebaa
4
- data.tar.gz: 3a4e90f29696b21966b76422d757360f949d2d57b9435caa43a318515d353430
3
+ metadata.gz: d265dd427dc9c2951b63676d191d3dd6ff1c64cc08b78accfdd563ee88092bdf
4
+ data.tar.gz: 77eed20b4c98ce8e30c0f69d848978543cd507c1ca6cf338dbe8871ad8c7a022
5
5
  SHA512:
6
- metadata.gz: '090f97f36021765785b5b6600b6086b00654276b151485f3052484af051fd244ad8bc229a641d8dda61d8da2d347f2c94129362cc4274be4101f8815aa5546f3'
7
- data.tar.gz: ec0e7c2dca7e3313c5931454e787c8bbdebb68eb4a5f682ade46e667f45fe413481df2b850bb74fd6bc8f11496ed128c9131396fcaac265dc2dcb76047aed66b
6
+ metadata.gz: cc72270b9610c9ce3e411e969308bbd47f6c9984afd80ff3dc926dc6eb5ffd9c4d596c93f4ccd0e9c349e8a5c58235c876b6dac8c648ae0be87148b881ac9e42
7
+ data.tar.gz: a039fada53654ad08f55315b8383224f095a141fc758ce50f70c03ccd4e4963cc2824a5433265fa1c90e1909c1e69569789f5c5ee052db491639bd0532c7a75f
@@ -1,10 +1,13 @@
1
1
  term_def_boilerplate:
2
2
  scope: Scope
3
- symbols: Symbols and abbreviated terms
3
+ symbolsabbrev: Symbols and abbreviated terms
4
+ abbrev: Abbreviated terms
5
+ symbols: Symbols
4
6
  table_of_contents: Table of contents
5
7
  introduction: Introduction
6
8
  foreword: Foreword
7
9
  abstract: Abstract
10
+ acknowledgements: Acknowledgements
8
11
  termsdef: Terms and definitions
9
12
  termsdefsymbolsabbrev: Terms, definitions, symbols and abbreviated terms
10
13
  termsdefsymbols: Terms, definitions and symbols
@@ -1,10 +1,13 @@
1
1
  term_def_boilerplate:
2
2
  scope: Domaine d'application
3
- symbols: Symboles et termes abrégés
3
+ symbolabbrev: Symboles et termes abrégés
4
+ abbrev: Termes abrégés
5
+ symbols: Symboles
4
6
  table_of_contents: Sommaire
5
7
  introduction: Introduction
6
8
  foreword: Avant-propos
7
9
  abstract: Résumé
10
+ acknowledgements: Remerciements
8
11
  termsdef: Terms et définitions
9
12
  termsdefsymbolsabbrev: Terms, définitions, symboles et termes abrégés
10
13
  termsdefsymbols: Terms, définitions et symboles
@@ -1,10 +1,13 @@
1
1
  term_def_boilerplate:
2
2
  scope: 范围
3
- symbols: 符号、代号和缩略语
3
+ symbolsabbrev: 符号、代号和缩略语
4
+ abbrev: 代号和缩略语
5
+ symbols: 符号
4
6
  table_of_contents: 目次
5
7
  introduction: 引言
6
8
  foreword: 前言
7
9
  abstract: 摘要
10
+ acknowledgements: 致謝
8
11
  termsdef: 术语和定义
9
12
  termsdefsymbolsabbrev: 术语、定义、符号、代号和缩略语
10
13
  termsdefsymbols: 术语、定义、符号和代号
@@ -23,6 +23,7 @@ require "isodoc/xslfo_convert"
23
23
  require "isodoc/headlesshtml_convert"
24
24
  require "isodoc/presentation_xml_convert"
25
25
  require "isodoc/xref"
26
+ require "isodoc/i18n"
26
27
 
27
28
  module IsoDoc
28
29
 
@@ -1,6 +1,5 @@
1
1
  require_relative "./function/blocks"
2
2
  require_relative "./function/cleanup"
3
- require_relative "./function/i18n"
4
3
  require_relative "./function/inline"
5
4
  require_relative "./function/lists"
6
5
  require_relative "./function/references"
@@ -16,7 +15,6 @@ module IsoDoc
16
15
  class Common
17
16
  include Function::Blocks
18
17
  include Function::Cleanup
19
- include Function::I18n
20
18
  include Function::Inline
21
19
  include Function::Lists
22
20
  include Function::References
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
-
3
- require 'isodoc/common'
4
- require 'fileutils'
5
- require 'tempfile'
2
+ require "isodoc/common"
3
+ require "fileutils"
4
+ require "tempfile"
5
+ require_relative "i18n"
6
6
 
7
7
  module IsoDoc
8
8
  class Convert < ::IsoDoc::Common
9
9
  attr_reader :options
10
- attr_accessor :labels
10
+ attr_accessor :i18n
11
11
 
12
12
  # htmlstylesheet: Generic stylesheet for HTML
13
13
  # wordstylesheet: Generic stylesheet for Word
@@ -66,10 +66,10 @@ module IsoDoc
66
66
  @in_figure = false
67
67
  @seen_footnote = Set.new
68
68
  @c = HTMLEntities.new
69
- @openmathdelim = '`'
70
- @closemathdelim = '`'
71
- @lang = 'en'
72
- @script = 'Latn'
69
+ @openmathdelim = "`"
70
+ @closemathdelim = "`"
71
+ @lang = options[:language] || "en"
72
+ @script = options[:script] || "Latn"
73
73
  @maxwidth = 1200
74
74
  @maxheight = 800
75
75
  @wordToClevels = options[:doctoclevels].to_i
@@ -115,8 +115,8 @@ module IsoDoc
115
115
  }
116
116
  end
117
117
 
118
- # none for this parent gem, but will be populated in child
119
- # gems which have access to stylesheets &c; e.g.
118
+ # none for this parent gem, but will be populated in child gems
119
+ # which have access to stylesheets &c; e.g.
120
120
  # {
121
121
  # htmlstylesheet: html_doc_path("htmlstyle.scss"),
122
122
  # htmlcoverpage: html_doc_path("html_rsd_titlepage.html"),
@@ -201,32 +201,38 @@ module IsoDoc
201
201
  end.join("\n")
202
202
  end
203
203
 
204
- def metadata_init(lang, script, labels)
205
- @meta = Metadata.new(lang, script, labels)
204
+ def metadata_init(lang, script, i18n)
205
+ @meta = Metadata.new(lang, script, i18n)
206
+ end
207
+
208
+ def xref_init(lang, script, _klass, i18n, options)
209
+ html = HtmlConvert.new(language: @lang, script: @script)
210
+ @xrefs = Xref.new(lang, script, html, i18n, options)
211
+ end
212
+
213
+ def i18n_init(lang, script, i18nyaml = nil)
214
+ @i18n = I18n.new(lang, script, i18nyaml || @i18nyaml)
206
215
  end
207
216
 
208
- def xref_init(lang, script, klass, labels, options)
209
- @xrefs = Xref.new(lang, script, klass, labels, options)
217
+ def l10n(x, lang = @lang, script = @script)
218
+ @i18n.l10n(x, lang, script)
210
219
  end
211
220
 
212
221
  def convert_init(file, input_filename, debug)
213
222
  docxml = Nokogiri::XML(file)
214
223
  filename, dir = init_file(input_filename, debug)
215
- docxml.root.default_namespace = ''
216
- lang = docxml&.at(ns('//bibdata/language'))&.text || @lang
217
- script = docxml&.at(ns('//bibdata/script'))&.text || @script
218
- i18n_init(lang, script)
219
- metadata_init(lang, script, @labels)
220
- @meta.fonts_options = fonts_options
221
- xref_init(lang, script, self, @labels, {})
224
+ docxml.root.default_namespace = ""
225
+ lang = docxml&.at(ns("//bibdata/language"))&.text and @lang = lang
226
+ script = docxml&.at(ns("//bibdata/script"))&.text and @script = script
227
+ i18n_init(@lang, @script)
228
+ metadata_init(@lang, @script, @i18n)
229
+ xref_init(@lang, @script, self, @i18n, {})
222
230
  [docxml, filename, dir]
223
231
  end
224
232
 
225
- def convert(input_filename,
226
- file = nil,
227
- debug = false,
233
+ def convert(input_filename, file = nil, debug = false,
228
234
  output_filename = nil)
229
- file = File.read(input_filename, encoding: 'utf-8') if file.nil?
235
+ file = File.read(input_filename, encoding: "utf-8") if file.nil?
230
236
  @openmathdelim, @closemathdelim = extract_delims(file)
231
237
  docxml, filename, dir = convert_init(file, input_filename, debug)
232
238
  result = convert1(docxml, filename, dir)
@@ -237,7 +243,7 @@ module IsoDoc
237
243
  end
238
244
 
239
245
  def middle_clause
240
- "//clause[parent::sections][not(xmlns:title = 'Scope')]"\
246
+ "//clause[parent::sections][not(@type = 'scope')]"\
241
247
  '[not(descendant::terms)]'
242
248
  end
243
249
  end
@@ -5,20 +5,15 @@ module IsoDoc::Function
5
5
  @annotation = false
6
6
 
7
7
  def figure_name_parse(node, div, name)
8
- return if name.nil? && node.at(ns("./figure"))
9
- lbl = @xrefs.anchor(node['id'], :label, false)
10
- lbl = nil if labelled_ancestor(node) && node.ancestors("figure").empty?
11
- return if lbl.nil? && name.nil?
8
+ return if name.nil?
12
9
  div.p **{ class: "FigureTitle", style: "text-align:center;" } do |p|
13
- lbl.nil? or p << l10n("#{@figure_lbl} #{lbl}")
14
- name and !lbl.nil? and p << "&nbsp;&mdash; "
15
- name and name.children.each { |n| parse(n, div) }
10
+ name.children.each { |n| parse(n, div) }
16
11
  end
17
12
  end
18
13
 
19
14
  def figure_key(out)
20
15
  out.p **{ style: "page-break-after:avoid;"} do |p|
21
- p.b { |b| b << @key_lbl }
16
+ p.b { |b| b << @i18n.key }
22
17
  end
23
18
  end
24
19
 
@@ -55,15 +50,9 @@ module IsoDoc::Function
55
50
  end
56
51
 
57
52
  def sourcecode_name_parse(node, div, name)
58
- lbl = @xrefs.anchor(node['id'], :label, false)
59
- lbl = nil if labelled_ancestor(node)
60
- return if lbl.nil? && name.nil?
53
+ return if name.nil?
61
54
  div.p **{ class: "SourceTitle", style: "text-align:center;" } do |p|
62
- if node.ancestors("example").empty?
63
- lbl.nil? or p << l10n("#{@figure_lbl} #{lbl}")
64
- name and !lbl.nil? and p << "&nbsp;&mdash; "
65
- end
66
- name&.children&.each { |n| parse(n, p) }
55
+ name.children.each { |n| parse(n, p) }
67
56
  end
68
57
  end
69
58
 
@@ -109,8 +98,8 @@ module IsoDoc::Function
109
98
  def admonition_name(node, type)
110
99
  name = node&.at(ns("./name")) and return name
111
100
  name = Nokogiri::XML::Node.new('name', node.document)
112
- return unless type && @admonition[type]
113
- name << @admonition[type]&.upcase
101
+ return unless type && @i18n.admonition[type]
102
+ name << @i18n.admonition[type]&.upcase
114
103
  name
115
104
  end
116
105
 
@@ -131,7 +120,7 @@ module IsoDoc::Function
131
120
  def formula_where(dl, out)
132
121
  return unless dl
133
122
  out.p **{ style: "page-break-after:avoid;"} do |p|
134
- p << @where_lbl
123
+ p << @i18n.where
135
124
  end
136
125
  parse(dl, out)
137
126
  out.parent.at("./dl")["class"] = "formula_dl"
@@ -141,8 +130,7 @@ module IsoDoc::Function
141
130
  out.div **attr_code(class: "formula") do |div|
142
131
  div.p do |p|
143
132
  parse(node.at(ns("./stem")), div)
144
- lbl = @xrefs.anchor(node['id'], :label, false)
145
- unless lbl.nil?
133
+ if lbl = node&.at(ns("./name"))&.text
146
134
  insert_tab(div, 1)
147
135
  div << "(#{lbl})"
148
136
  end
@@ -159,7 +147,7 @@ module IsoDoc::Function
159
147
  formula_parse1(node, div)
160
148
  formula_where(node.at(ns("./dl")), div)
161
149
  node.children.each do |n|
162
- next if %w(stem dl).include? n.name
150
+ next if %w(stem dl name).include? n.name
163
151
  parse(n, div)
164
152
  end
165
153
  end
@@ -1,13 +1,9 @@
1
1
  module IsoDoc::Function
2
2
  module Blocks
3
3
  def example_label(node, div, name)
4
- n = @xrefs.get[node["id"]]
4
+ return if name.nil?
5
5
  div.p **{ class: "example-title" } do |p|
6
- lbl = (n.nil? || n[:label].nil? || n[:label].empty?) ? @example_lbl :
7
- l10n("#{@example_lbl} #{n[:label]}")
8
- p << lbl
9
- name and !lbl.nil? and p << "&nbsp;&mdash; "
10
- name and name.children.each { |n| parse(n, div) }
6
+ name.children.each { |n| parse(n, div) }
11
7
  end
12
8
  end
13
9
 
@@ -55,16 +51,16 @@ module IsoDoc::Function
55
51
  example_div_parse(node, out)
56
52
  end
57
53
 
58
- def note_label(node)
59
- n = @xrefs.get[node["id"]]
60
- return @note_lbl if n.nil? || n[:label].nil? || n[:label].empty?
61
- l10n("#{@note_lbl} #{n[:label]}")
54
+ def note_delim
55
+ ""
62
56
  end
63
57
 
64
58
  def note_p_parse(node, div)
59
+ name = node&.at(ns("./name"))&.remove
65
60
  div.p do |p|
66
- p.span **{ class: "note_label" } do |s|
67
- s << note_label(node)
61
+ name and p.span **{ class: "note_label" } do |s|
62
+ name and name.children.each { |n| parse(n, s) }
63
+ s << note_delim
68
64
  end
69
65
  insert_tab(p, 1)
70
66
  node.first_element_child.children.each { |n| parse(n, p) }
@@ -73,9 +69,11 @@ module IsoDoc::Function
73
69
  end
74
70
 
75
71
  def note_parse1(node, div)
76
- div.p do |p|
72
+ name = node&.at(ns("./name"))&.remove
73
+ name and div.p do |p|
77
74
  p.span **{ class: "note_label" } do |s|
78
- s << note_label(node)
75
+ name.children.each { |n| parse(n, s) }
76
+ s << note_delim
79
77
  end
80
78
  insert_tab(p, 1)
81
79
  end
@@ -99,7 +97,8 @@ module IsoDoc::Function
99
97
  def note_parse(node, out)
100
98
  @note = true
101
99
  out.div **note_attrs(node) do |div|
102
- node.first_element_child.name == "p" ?
100
+ node&.at(ns("./*[local-name() != 'name'][1]"))&.name == "p" ?
101
+ #node.first_element_child.name == "p" ?
103
102
  note_p_parse(node, div) : note_parse1(node, div)
104
103
  end
105
104
  @note = false
@@ -7,10 +7,10 @@ module IsoDoc::Function
7
7
  def termref_cleanup(docxml)
8
8
  docxml.
9
9
  gsub(%r{\s*\[/TERMREF\]\s*</p>\s*<p>\s*\[TERMREF\]}, "; ").
10
- gsub(/\[TERMREF\]\s*/, l10n("[#{@source_lbl}: ")).
11
- gsub(/\s*\[MODIFICATION\]\s*\[\/TERMREF\]/, l10n(", #{@modified_lbl} [/TERMREF]")).
10
+ gsub(/\[TERMREF\]\s*/, l10n("[#{@i18n.source}: ")).
11
+ gsub(/\s*\[MODIFICATION\]\s*\[\/TERMREF\]/, l10n(", #{@i18n.modified} [/TERMREF]")).
12
12
  gsub(%r{\s*\[\/TERMREF\]\s*}, l10n("]")).
13
- gsub(/\s*\[MODIFICATION\]/, l10n(", #{@modified_lbl} &mdash; "))
13
+ gsub(/\s*\[MODIFICATION\]/, l10n(", #{@i18n.modified} &mdash; "))
14
14
  end
15
15
 
16
16
  def passthrough_cleanup(docxml)
@@ -21,6 +21,7 @@ module IsoDoc::Function
21
21
  end
22
22
 
23
23
  def cleanup(docxml)
24
+ @i18n ||= i18n_init(@lang, @script)
24
25
  comment_cleanup(docxml)
25
26
  footnote_cleanup(docxml)
26
27
  inline_header_cleanup(docxml)
@@ -80,7 +81,7 @@ module IsoDoc::Function
80
81
  def figure_get_or_make_dl(t)
81
82
  dl = t.at(".//dl")
82
83
  if dl.nil?
83
- t.add_child("<p><b>#{@key_lbl}</b></p><dl></dl>")
84
+ t.add_child("<p><b>#{@i18n.key}</b></p><dl></dl>")
84
85
  dl = t.at(".//dl")
85
86
  end
86
87
  dl
@@ -16,85 +16,16 @@ module IsoDoc::Function
16
16
  out << " &lt;#{node.text}&gt;"
17
17
  end
18
18
 
19
- def prefix_container(container, linkend, _target)
20
- l10n(@xrefs.anchor(container, :xref) + ", " + linkend)
21
- end
22
-
23
- def anchor_linkend(node, linkend)
24
- if node["citeas"].nil? && node["bibitemid"]
25
- return @xrefs.anchor(node["bibitemid"] ,:xref) || "???"
26
- elsif node["target"] && !/.#./.match(node["target"])
27
- linkend = @xrefs.anchor(node["target"], :xref)
28
- container = @xrefs.anchor(node["target"], :container, false)
29
- (container && get_note_container_id(node) != container &&
30
- @xrefs.get[node["target"]]) &&
31
- linkend = prefix_container(container, linkend, node["target"])
32
- linkend = capitalise_xref(node, linkend)
19
+ def no_locality_parse(node, out)
20
+ node.children.each do |n|
21
+ parse(n, out) unless %w{locality localityStack}.include? n.name
33
22
  end
34
- linkend || "???"
35
- end
36
-
37
- def capitalise_xref(node, linkend)
38
- return linkend unless %w(Latn Cyrl Grek).include? @script
39
- return linkend&.capitalize if node["case"] == "capital"
40
- return linkend&.downcase if node["case"] == "lowercase"
41
- return linkend if linkend[0,1].match(/\p{Upper}/)
42
- prec = nearest_block_parent(node).xpath("./descendant-or-self::text()") &
43
- node.xpath("./preceding::text()")
44
- (prec.empty? || /(?!<[^.].)\.\s+$/.match(prec.map { |p| p.text }.join)) ?
45
- linkend&.capitalize : linkend
46
- end
47
-
48
- def nearest_block_parent(node)
49
- until %w(p title td th name formula
50
- li dt dd sourcecode pre).include?(node.name)
51
- node = node.parent
52
- end
53
- node
54
- end
55
-
56
- def get_linkend(node)
57
- contents = node.children.select do |c|
58
- !%w{locality localityStack}.include? c.name
59
- end.select { |c| !c.text? || /\S/.match(c) }
60
- !contents.empty? and
61
- return Nokogiri::XML::NodeSet.new(node.document, contents).to_xml
62
- link = anchor_linkend(node, docid_l10n(node["target"] || node["citeas"]))
63
- link + eref_localities(node.xpath(ns("./locality | ./localityStack")),
64
- link)
65
- # so not <origin bibitemid="ISO7301" citeas="ISO 7301">
66
- # <locality type="section"><reference>3.1</reference></locality></origin>
67
23
  end
68
24
 
69
25
  def xref_parse(node, out)
70
26
  target = /#/.match(node["target"]) ? node["target"].sub(/#/, ".html#") :
71
27
  "##{node["target"]}"
72
- out.a(**{ "href": target }) { |l| l << get_linkend(node) }
73
- end
74
-
75
- def eref_localities(refs, target)
76
- ret = ""
77
- refs.each_with_index do |r, i|
78
- delim = ","
79
- delim = ";" if r.name == "localityStack" && i>0
80
- if r.name == "localityStack"
81
- r.elements.each_with_index do |rr, j|
82
- ret += eref_localities0(rr, j, target, delim)
83
- delim = ","
84
- end
85
- else
86
- ret += eref_localities0(r, i, target, delim)
87
- end
88
- end
89
- ret
90
- end
91
-
92
- def eref_localities0(r, i, target, delim)
93
- if r["type"] == "whole" then l10n("#{delim} #{@wholeoftext_lbl}")
94
- else
95
- eref_localities1(target, r["type"], r.at(ns("./referenceFrom")),
96
- r.at(ns("./referenceTo")), delim, @lang)
97
- end
28
+ out.a(**{ "href": target }) { |l| no_locality_parse(node, l) }
98
29
  end
99
30
 
100
31
  def suffix_url(url)
@@ -114,14 +45,13 @@ module IsoDoc::Function
114
45
  end
115
46
 
116
47
  def eref_parse(node, out)
117
- linkend = get_linkend(node)
118
48
  href = eref_target(node)
119
49
  if node["type"] == "footnote"
120
50
  out.sup do |s|
121
- s.a(**{ "href": href }) { |l| l << linkend }
51
+ s.a(**{ "href": href }) { |l| no_locality_parse(node, l) }
122
52
  end
123
53
  else
124
- out.a(**{ "href": href }) { |l| l << linkend }
54
+ out.a(**{ "href": href }) { |l| no_locality_parse(node, l) }
125
55
  end
126
56
  end
127
57