metanorma-standoc 1.8.8 → 1.9.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +3 -13
  3. data/.hound.yml +3 -1
  4. data/.rubocop.yml +3 -7
  5. data/Gemfile.devel +0 -0
  6. data/lib/asciidoctor/standoc/base.rb +42 -36
  7. data/lib/asciidoctor/standoc/biblio.rng +1 -0
  8. data/lib/asciidoctor/standoc/blocks.rb +25 -9
  9. data/lib/asciidoctor/standoc/blocks_notes.rb +41 -24
  10. data/lib/asciidoctor/standoc/cleanup.rb +59 -84
  11. data/lib/asciidoctor/standoc/cleanup_block.rb +63 -85
  12. data/lib/asciidoctor/standoc/cleanup_boilerplate.rb +51 -29
  13. data/lib/asciidoctor/standoc/cleanup_footnotes.rb +1 -0
  14. data/lib/asciidoctor/standoc/cleanup_image.rb +71 -0
  15. data/lib/asciidoctor/standoc/cleanup_maths.rb +36 -27
  16. data/lib/asciidoctor/standoc/cleanup_ref.rb +24 -15
  17. data/lib/asciidoctor/standoc/cleanup_ref_dl.rb +1 -1
  18. data/lib/asciidoctor/standoc/cleanup_reqt.rb +47 -0
  19. data/lib/asciidoctor/standoc/cleanup_section.rb +77 -134
  20. data/lib/asciidoctor/standoc/cleanup_section_names.rb +75 -0
  21. data/lib/asciidoctor/standoc/converter.rb +10 -3
  22. data/lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb +67 -66
  23. data/lib/asciidoctor/standoc/front.rb +35 -18
  24. data/lib/asciidoctor/standoc/front_contributor.rb +70 -45
  25. data/lib/asciidoctor/standoc/inline.rb +30 -22
  26. data/lib/asciidoctor/standoc/isodoc.rng +321 -4
  27. data/lib/asciidoctor/standoc/lists.rb +4 -2
  28. data/lib/asciidoctor/standoc/macros.rb +50 -23
  29. data/lib/asciidoctor/standoc/macros_form.rb +63 -0
  30. data/lib/asciidoctor/standoc/ref.rb +87 -112
  31. data/lib/asciidoctor/standoc/ref_date_id.rb +62 -0
  32. data/lib/asciidoctor/standoc/ref_sect.rb +20 -17
  33. data/lib/asciidoctor/standoc/section.rb +3 -1
  34. data/lib/asciidoctor/standoc/term_lookup_cleanup.rb +31 -16
  35. data/lib/asciidoctor/standoc/terms.rb +27 -16
  36. data/lib/asciidoctor/standoc/utils.rb +35 -9
  37. data/lib/asciidoctor/standoc/validate.rb +30 -28
  38. data/lib/metanorma-standoc.rb +0 -1
  39. data/lib/metanorma/standoc/version.rb +5 -5
  40. data/metanorma-standoc.gemspec +11 -11
  41. data/spec/asciidoctor/base_spec.rb +715 -509
  42. data/spec/asciidoctor/blocks_spec.rb +830 -727
  43. data/spec/asciidoctor/cleanup_sections_spec.rb +51 -14
  44. data/spec/asciidoctor/cleanup_spec.rb +1836 -1673
  45. data/spec/asciidoctor/inline_spec.rb +330 -283
  46. data/spec/asciidoctor/isobib_cache_spec.rb +406 -358
  47. data/spec/asciidoctor/lists_spec.rb +3 -3
  48. data/spec/asciidoctor/macros_plantuml_spec.rb +8 -8
  49. data/spec/asciidoctor/macros_spec.rb +546 -444
  50. data/spec/asciidoctor/macros_yaml2text_spec.rb +1 -1
  51. data/spec/asciidoctor/refs_dl_spec.rb +4 -4
  52. data/spec/asciidoctor/refs_spec.rb +1528 -1533
  53. data/spec/asciidoctor/section_spec.rb +778 -689
  54. data/spec/asciidoctor/table_spec.rb +6 -6
  55. data/spec/asciidoctor/validate_spec.rb +296 -304
  56. data/spec/spec_helper.rb +13 -9
  57. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +66 -66
  58. data/spec/vcr_cassettes/isobib_get_123.yml +17 -17
  59. data/spec/vcr_cassettes/isobib_get_123_1.yml +31 -31
  60. data/spec/vcr_cassettes/isobib_get_123_1_fr.yml +40 -40
  61. data/spec/vcr_cassettes/isobib_get_123_2001.yml +17 -17
  62. data/spec/vcr_cassettes/isobib_get_124.yml +16 -16
  63. data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +14 -14
  64. data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +78 -66
  65. metadata +69 -67
  66. data/lib/liquid/custom_blocks/key_iterator.rb +0 -21
  67. data/lib/liquid/custom_blocks/with_json_nested_context.rb +0 -18
  68. data/lib/liquid/custom_blocks/with_yaml_nested_context.rb +0 -19
  69. data/lib/liquid/custom_filters/values.rb +0 -7
@@ -37,14 +37,15 @@ module Asciidoctor
37
37
  end
38
38
  end
39
39
 
40
- def insert_thead(s)
41
- thead = s.at("./thead")
40
+ def insert_thead(table)
41
+ thead = table.at("./thead")
42
42
  return thead unless thead.nil?
43
- if tname = s.at("./name")
43
+
44
+ if tname = table.at("./name")
44
45
  thead = tname.add_next_sibling("<thead/>").first
45
46
  return thead
46
47
  end
47
- s.children.first.add_previous_sibling("<thead/>").first
48
+ table.children.first.add_previous_sibling("<thead/>").first
48
49
  end
49
50
 
50
51
  def header_rows_cleanup(xmldoc)
@@ -80,21 +81,21 @@ module Asciidoctor
80
81
  end
81
82
 
82
83
  # include where definition list inside stem block
83
- def formula_cleanup(x)
84
- formula_cleanup_where1(x)
85
- formula_cleanup_where2(x)
84
+ def formula_cleanup(formula)
85
+ formula_cleanup_where1(formula)
86
+ formula_cleanup_where2(formula)
86
87
  end
87
88
 
88
- def formula_cleanup_where1(x)
89
+ def formula_cleanup_where1(formula)
89
90
  q = "//formula/following-sibling::*[1][self::dl]"
90
- x.xpath(q).each do |s|
91
+ formula.xpath(q).each do |s|
91
92
  s["key"] == "true" and s.previous_element << s.remove
92
93
  end
93
94
  end
94
95
 
95
- def formula_cleanup_where2(x)
96
+ def formula_cleanup_where2(formula)
96
97
  q = "//formula/following-sibling::*[1][self::p]"
97
- x.xpath(q).each do |s|
98
+ formula.xpath(q).each do |s|
98
99
  if s.text =~ /^\s*where[^a-z]*$/i && s&.next_element&.name == "dl"
99
100
  s.next_element["key"] = "true"
100
101
  s.previous_element << s.next_element.remove
@@ -125,9 +126,10 @@ module Asciidoctor
125
126
  # examples containing only figures become subfigures of figures
126
127
  def subfigure_cleanup(xmldoc)
127
128
  xmldoc.xpath("//example[figure]").each do |e|
128
- next unless e.elements.map { |m| m.name }.reject do |m|
129
+ next unless e.elements.map(&:name).reject do |m|
129
130
  %w(name figure).include? m
130
131
  end.empty?
132
+
131
133
  e.name = "figure"
132
134
  end
133
135
  end
@@ -142,7 +144,7 @@ module Asciidoctor
142
144
  ELEMS_ALLOW_NOTES = %w[p formula ul ol dl figure].freeze
143
145
 
144
146
  # if a note is at the end of a section, it is left alone
145
- # if a note is followed by a non-note block,
147
+ # if a note is followed by a non-note block,
146
148
  # it is moved inside its preceding block if it is not delimited
147
149
  # (so there was no way of making that block include the note)
148
150
  def note_cleanup(xmldoc)
@@ -150,6 +152,7 @@ module Asciidoctor
150
152
  xmldoc.xpath(q).each do |n|
151
153
  next if n["keep-separate"] == "true"
152
154
  next unless n.ancestors("table").empty?
155
+
153
156
  prev = n.previous_element || next
154
157
  n.parent = prev if ELEMS_ALLOW_NOTES.include? prev.name
155
158
  end
@@ -159,100 +162,75 @@ module Asciidoctor
159
162
  end
160
163
  end
161
164
 
162
- def requirement_cleanup(x)
163
- requirement_descriptions(x)
164
- requirement_inherit(x)
165
- end
166
-
167
- def requirement_inherit(x)
168
- x.xpath("//requirement | //recommendation | //permission").each do |r|
169
- ins = r.at("./classification") ||
170
- r.at("./description | ./measurementtarget | ./specification | "\
171
- "./verification | ./import | ./description | ./requirement | "\
172
- "./recommendation | ./permission")
173
- r.xpath("./*//inherit").each { |i| ins.previous = i }
165
+ def link_callouts_to_annotations(callouts, annotations)
166
+ callouts.each_with_index do |c, i|
167
+ c["target"] = "_#{UUIDTools::UUID.random_create}"
168
+ annotations[i]["id"] = c["target"]
174
169
  end
175
170
  end
176
171
 
177
- def requirement_descriptions(x)
178
- x.xpath("//requirement | //recommendation | //permission").each do |r|
179
- r.children.each do |e|
180
- unless e.element? && (reqt_subpart(e.name) ||
181
- %w(requirement recommendation permission).include?(e.name))
182
- t = Nokogiri::XML::Element.new("description", x)
183
- e.before(t)
184
- t.children = e.remove
185
- end
186
- end
187
- requirement_cleanup1(r)
172
+ def align_callouts_to_annotations(xmldoc)
173
+ xmldoc.xpath("//sourcecode").each do |x|
174
+ callouts = x.elements.select { |e| e.name == "callout" }
175
+ annotations = x.elements.select { |e| e.name == "annotation" }
176
+ callouts.size == annotations.size and
177
+ link_callouts_to_annotations(callouts, annotations)
188
178
  end
189
179
  end
190
180
 
191
- def requirement_cleanup1(r)
192
- while d = r.at("./description[following-sibling::*[1]"\
193
- "[self::description]]")
194
- n = d.next.remove
195
- d << n.children
196
- end
197
- r.xpath("./description[normalize-space(.)='']").each do |d|
198
- d.replace("\n")
181
+ def merge_annotations_into_sourcecode(xmldoc)
182
+ xmldoc.xpath("//sourcecode").each do |x|
183
+ while x&.next_element&.name == "annotation"
184
+ x.next_element.parent = x
185
+ end
199
186
  end
200
187
  end
201
188
 
202
- def svgmap_cleanup(xmldoc)
203
- svgmap_moveattrs(xmldoc)
204
- svgmap_populate(xmldoc)
205
- Metanorma::Utils::svgmap_rewrite(xmldoc, @localdir)
189
+ def callout_cleanup(xmldoc)
190
+ merge_annotations_into_sourcecode(xmldoc)
191
+ align_callouts_to_annotations(xmldoc)
206
192
  end
207
193
 
208
- def guid?(x)
209
- /^_[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i.
210
- match(x)
211
- end
194
+ def sourcecode_cleanup(xmldoc)
195
+ xmldoc.xpath("//sourcecode").each do |x|
196
+ x.traverse do |n|
197
+ next unless n.text?
198
+ next unless /#{Regexp.escape(@sourcecode_markup_start)}/
199
+ .match?(n.text)
212
200
 
213
- def svgmap_moveattrs(xmldoc)
214
- xmldoc.xpath("//svgmap").each do |s|
215
- f = s.at(".//figure") or next
216
- if t = s.at("./name") and !f.at("./name")
217
- f.children.first.previous = t.remove
201
+ n.replace(sourcecode_markup(n))
218
202
  end
219
- if s["id"] && guid?(f["id"])
220
- f["id"] = s["id"]
221
- s.delete("id")
222
- end
223
- svgmap_moveattrs1(s, f)
224
203
  end
225
204
  end
226
205
 
227
- def svgmap_moveattrs1(s, f)
228
- %w(unnumbered number subsequence keep-with-next
229
- keep-lines-together).each do |a|
230
- next if f[a] || !s[a]
231
- f[a] = s[a]
232
- s.delete(a)
233
- end
206
+ def safe_noko(text, doc)
207
+ Nokogiri::XML::Text.new(text, doc).to_xml(
208
+ encoding: "US-ASCII",
209
+ save_with: Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
210
+ )
234
211
  end
235
212
 
236
- def svgmap_populate(xmldoc)
237
- xmldoc.xpath("//svgmap").each do |s|
238
- s1 = s.dup
239
- s.children.remove
240
- f = s1.at(".//figure") and s << f
241
- s1.xpath(".//li").each do |li|
242
- t = li&.at(".//eref | .//link | .//xref") or next
243
- href = t.xpath("./following-sibling::node()")
244
- href.empty? or
245
- s << %[<target href="#{svgmap_target(href)}">#{t.to_xml}</target>]
246
- end
213
+ def sourcecode_markup(node)
214
+ acc = []
215
+ node.text.split(/(#{Regexp.escape(@sourcecode_markup_start)}|
216
+ #{Regexp.escape(@sourcecode_markup_end)})/x)
217
+ .each_slice(4).map do |a|
218
+ acc << safe_noko(a[0], node.document)
219
+ next unless a.size == 4
220
+
221
+ acc << Asciidoctor.convert(
222
+ a[2], doctype: :inline, backend: (self&.backend&.to_sym || :standoc)
223
+ )
247
224
  end
225
+ acc.join
248
226
  end
249
227
 
250
- def svgmap_target(nodeset)
251
- nodeset.each do |n|
252
- next unless n.name == "link"
253
- n.children = n["target"]
228
+ def form_cleanup(xmldoc)
229
+ xmldoc.xpath("//select").each do |s|
230
+ while s&.next_element&.name == "option"
231
+ s << s.next_element
232
+ end
254
233
  end
255
- nodeset.text.sub(/^[,; ]/, "").strip
256
234
  end
257
235
  end
258
236
  end
@@ -3,21 +3,26 @@ module Asciidoctor
3
3
  module Cleanup
4
4
  def external_terms_boilerplate(sources)
5
5
  @i18n.l10n(
6
- @i18n.external_terms_boilerplate.gsub(/%/, sources || "???"), @lang, @script)
6
+ @i18n.external_terms_boilerplate.gsub(/%/, sources || "???"),
7
+ @lang, @script
8
+ )
7
9
  end
8
10
 
9
11
  def internal_external_terms_boilerplate(sources)
10
12
  @i18n.l10n(
11
- @i18n.internal_external_terms_boilerplate.gsub(/%/, sources || "??"), @lang, @script)
13
+ @i18n.internal_external_terms_boilerplate.gsub(/%/, sources || "??"),
14
+ @lang, @script
15
+ )
12
16
  end
13
17
 
14
18
  def term_defs_boilerplate(div, source, term, preface, isodoc)
15
19
  a = @i18n.term_def_boilerplate and div.next = a
16
20
  source.each do |s|
17
21
  @anchors[s["bibitemid"]] or
18
- @log.add("Crossreferences", nil, "term source #{s['bibitemid']} not referenced")
22
+ @log.add("Crossreferences", nil,
23
+ "term source #{s['bibitemid']} not referenced")
19
24
  end
20
- a = (source.empty? && term.nil?) ? @i18n.no_terms_boilerplate :
25
+ a = source.empty? && term.nil? ? @i18n.no_terms_boilerplate :
21
26
  term_defs_boilerplate_cont(source, term, isodoc)
22
27
  a and div.next = a
23
28
  end
@@ -33,17 +38,23 @@ module Asciidoctor
33
38
  end
34
39
  end
35
40
 
36
- def norm_ref_preface(f)
37
- refs = f.elements.select do |e|
38
- ["reference", "bibitem"].include? e.name
41
+ def norm_ref_preface(ref)
42
+ if ref.at("./note[@type = 'boilerplate']")
43
+ unwrap_boilerplate_clauses(ref, ".")
44
+ else
45
+ refs = ref.elements.select do |e|
46
+ %w(references bibitem).include? e.name
47
+ end
48
+ pref = refs.empty? ? @i18n.norm_empty_pref : @i18n.norm_with_refs_pref
49
+ ref.at("./title").next = "<p>#{pref}</p>"
39
50
  end
40
- f.at("./title").next =
41
- "<p>#{(refs.empty? ? @i18n.norm_empty_pref : @i18n.norm_with_refs_pref)}</p>"
42
51
  end
43
52
 
44
- TERM_CLAUSE = "//sections/terms | //sections/clause[descendant::terms]".freeze
53
+ TERM_CLAUSE = "//sections/terms | "\
54
+ "//sections/clause[descendant::terms]".freeze
45
55
 
46
- NORM_REF = "//bibliography/references[@normative = 'true']".freeze
56
+ NORM_REF = "//bibliography/references[@normative = 'true'] | "\
57
+ "//bibliography/clause[.//references[@normative = 'true']]".freeze
47
58
 
48
59
  def boilerplate_isodoc(xmldoc)
49
60
  x = xmldoc.dup
@@ -55,44 +66,53 @@ module Asciidoctor
55
66
  end
56
67
 
57
68
  def termdef_boilerplate_cleanup(xmldoc)
58
- #termdef_remove_initial_paras(xmldoc)
69
+ # termdef_remove_initial_paras(xmldoc)
59
70
  end
60
71
 
61
72
  def termdef_remove_initial_paras(xmldoc)
62
73
  xmldoc.xpath("//terms/p | //terms/ul").each(&:remove)
63
74
  end
64
75
 
65
- def termdef_unwrap_boilerplate_clauses(xmldoc)
66
- xmldoc.xpath(self.class::TERM_CLAUSE).each do |f|
67
- f.xpath(".//clause[@type = 'boilerplate']").each do |c|
76
+ def unwrap_boilerplate_clauses(xmldoc, xpath)
77
+ xmldoc.xpath(xpath).each do |f|
78
+ f.xpath(".//clause[@type = 'boilerplate'] | "\
79
+ ".//note[@type = 'boilerplate']").each do |c|
68
80
  c&.at("./title")&.remove
69
81
  c.replace(c.children)
70
82
  end
71
83
  end
72
84
  end
73
85
 
74
- def boilerplate_cleanup(xmldoc)
75
- isodoc = boilerplate_isodoc(xmldoc)
76
- termdef_boilerplate_cleanup(xmldoc)
86
+ def termdef_boilerplate_insert(xmldoc, isodoc, once = false)
77
87
  xmldoc.xpath(self.class::TERM_CLAUSE).each do |f|
78
88
  next if f.at("./clause[@type = 'boilerplate']")
79
- term_defs_boilerplate(f.at("./title"), xmldoc.xpath(".//termdocsource"),
89
+
90
+ term_defs_boilerplate(f.at("./title"),
91
+ xmldoc.xpath(".//termdocsource"),
80
92
  f.at(".//term"), f.at(".//p"), isodoc)
93
+ break if once
81
94
  end
82
- termdef_unwrap_boilerplate_clauses(xmldoc)
95
+ end
96
+
97
+ def boilerplate_cleanup(xmldoc)
98
+ isodoc = boilerplate_isodoc(xmldoc)
99
+ termdef_boilerplate_cleanup(xmldoc)
100
+ termdef_boilerplate_insert(xmldoc, isodoc)
101
+ unwrap_boilerplate_clauses(xmldoc, self.class::TERM_CLAUSE)
83
102
  f = xmldoc.at(self.class::NORM_REF) and norm_ref_preface(f)
84
103
  initial_boilerplate(xmldoc, isodoc)
85
104
  end
86
105
 
87
- def initial_boilerplate(x, isodoc)
88
- return if x.at("//boilerplate")
89
- preface = x.at("//preface") || x.at("//sections") || x.at("//annex") ||
90
- x.at("//references") || return
91
- b = boilerplate(x, isodoc) or return
106
+ def initial_boilerplate(xml, isodoc)
107
+ return if xml.at("//boilerplate")
108
+
109
+ preface = xml.at("//preface") || xml.at("//sections") ||
110
+ xml.at("//annex") || xml.at("//references") || return
111
+ b = boilerplate(xml, isodoc) or return
92
112
  preface.previous = b
93
113
  end
94
114
 
95
- def boilerplate_file(xmldoc)
115
+ def boilerplate_file(_xmldoc)
96
116
  File.join(@libdir, "boilerplate.xml")
97
117
  end
98
118
 
@@ -100,7 +120,7 @@ module Asciidoctor
100
120
  file = boilerplate_file(xml)
101
121
  file = File.join(@localdir, @boilerplateauthority) if @boilerplateauthority
102
122
  !file.nil? and File.exists?(file) or return
103
- conv.populate_template((File.read(file, encoding: "UTF-8")), nil)
123
+ conv.populate_template(File.read(file, encoding: "UTF-8"), nil)
104
124
  end
105
125
 
106
126
  def bibdata_cleanup(xmldoc)
@@ -118,14 +138,16 @@ module Asciidoctor
118
138
  def bibdata_docidentifier_cleanup(xmldoc)
119
139
  ins = xmldoc.at("//bibdata/docidentifier")
120
140
  xmldoc.xpath("//bibdata/docidentifier").each_with_index do |b, i|
121
- next if i == 0
141
+ next if i.zero?
142
+
122
143
  ins.next = b.remove
123
144
  ins = ins.next
124
145
  end
125
146
  end
126
147
 
127
148
  def gather_indirect_erefs(xmldoc, prefix)
128
- xmldoc.xpath("//eref[@type = '#{prefix}']").each_with_object({}) do |e, m|
149
+ xmldoc.xpath("//eref[@type = '#{prefix}']")
150
+ .each_with_object({}) do |e, m|
129
151
  e.delete("type")
130
152
  m[e["bibitemid"]] = true
131
153
  end.keys
@@ -20,6 +20,7 @@ module Asciidoctor
20
20
  nomatches = true
21
21
  xmldoc.xpath(q).each do |s|
22
22
  next if s.children.map { |c| c.text? && /[[:alpha:]]/.match(c.text) }.any?
23
+
23
24
  s.previous_element << s.first_element_child.remove
24
25
  s.remove
25
26
  nomatches = false
@@ -0,0 +1,71 @@
1
+ module Asciidoctor
2
+ module Standoc
3
+ module Cleanup
4
+ def svgmap_cleanup(xmldoc)
5
+ svgmap_moveattrs(xmldoc)
6
+ svgmap_populate(xmldoc)
7
+ Metanorma::Utils::svgmap_rewrite(xmldoc, @localdir)
8
+ end
9
+
10
+ def guid?(str)
11
+ /^_[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i
12
+ .match(str)
13
+ end
14
+
15
+ def svgmap_moveattrs(xmldoc)
16
+ xmldoc.xpath("//svgmap").each do |s|
17
+ f = s.at(".//figure") or next
18
+ if (t = s.at("./name")) && !f.at("./name")
19
+ f.children.first.previous = t.remove
20
+ end
21
+ if s["id"] && guid?(f["id"])
22
+ f["id"] = s["id"]
23
+ s.delete("id")
24
+ end
25
+ svgmap_moveattrs1(s, f)
26
+ end
27
+ end
28
+
29
+ def svgmap_moveattrs1(s, f)
30
+ %w(unnumbered number subsequence keep-with-next
31
+ keep-lines-together).each do |a|
32
+ next if f[a] || !s[a]
33
+
34
+ f[a] = s[a]
35
+ s.delete(a)
36
+ end
37
+ end
38
+
39
+ def svgmap_populate(xmldoc)
40
+ xmldoc.xpath("//svgmap").each do |s|
41
+ s1 = s.dup
42
+ s.children.remove
43
+ f = s1.at(".//figure") and s << f
44
+ s1.xpath(".//li").each do |li|
45
+ t = li&.at(".//eref | .//link | .//xref") or next
46
+ href = t.xpath("./following-sibling::node()")
47
+ href.empty? or
48
+ s << %[<target href="#{svgmap_target(href)}">#{t.to_xml}</target>]
49
+ end
50
+ end
51
+ end
52
+
53
+ def svgmap_target(nodeset)
54
+ nodeset.each do |n|
55
+ next unless n.name == "link"
56
+
57
+ n.children = n["target"]
58
+ end
59
+ nodeset.text.sub(/^[,; ]/, "").strip
60
+ end
61
+
62
+ def img_cleanup(xmldoc)
63
+ return xmldoc unless @datauriimage
64
+
65
+ xmldoc.xpath("//image").each do |i|
66
+ i["src"] = Metanorma::Utils::datauri(i["src"], @localdir)
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end