metanorma-standoc 1.10.4.1 → 1.10.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +19 -23
  3. data/lib/asciidoctor/standoc/base.rb +11 -13
  4. data/lib/asciidoctor/standoc/basicdoc.rng +21 -4
  5. data/lib/asciidoctor/standoc/blocks.rb +27 -22
  6. data/lib/asciidoctor/standoc/blocks_notes.rb +17 -22
  7. data/lib/asciidoctor/standoc/cleanup.rb +38 -71
  8. data/lib/asciidoctor/standoc/cleanup_block.rb +5 -70
  9. data/lib/asciidoctor/standoc/cleanup_image.rb +6 -7
  10. data/lib/asciidoctor/standoc/cleanup_inline.rb +27 -98
  11. data/lib/asciidoctor/standoc/cleanup_maths.rb +113 -21
  12. data/lib/asciidoctor/standoc/cleanup_ref.rb +5 -0
  13. data/lib/asciidoctor/standoc/cleanup_reqt.rb +56 -18
  14. data/lib/asciidoctor/standoc/cleanup_section.rb +1 -0
  15. data/lib/asciidoctor/standoc/cleanup_section_names.rb +31 -14
  16. data/lib/asciidoctor/standoc/cleanup_table.rb +68 -0
  17. data/lib/asciidoctor/standoc/cleanup_terms.rb +1 -1
  18. data/lib/asciidoctor/standoc/cleanup_text.rb +73 -0
  19. data/lib/asciidoctor/standoc/cleanup_xref.rb +107 -0
  20. data/lib/asciidoctor/standoc/converter.rb +13 -0
  21. data/lib/asciidoctor/standoc/isodoc.rng +241 -61
  22. data/lib/asciidoctor/standoc/lists.rb +15 -15
  23. data/lib/asciidoctor/standoc/macros.rb +14 -43
  24. data/lib/asciidoctor/standoc/macros_note.rb +45 -0
  25. data/lib/asciidoctor/standoc/macros_terms.rb +33 -15
  26. data/lib/asciidoctor/standoc/reqt.rb +2 -2
  27. data/lib/asciidoctor/standoc/reqt.rng +23 -2
  28. data/lib/asciidoctor/standoc/table.rb +22 -20
  29. data/lib/asciidoctor/standoc/terms.rb +9 -1
  30. data/lib/asciidoctor/standoc/validate.rb +23 -14
  31. data/lib/asciidoctor/standoc/validate_section.rb +5 -2
  32. data/lib/metanorma/standoc/version.rb +1 -1
  33. data/metanorma-standoc.gemspec +1 -1
  34. data/spec/asciidoctor/base_spec.rb +0 -33
  35. data/spec/asciidoctor/blank_spec.rb +37 -0
  36. data/spec/asciidoctor/blocks_spec.rb +151 -30
  37. data/spec/asciidoctor/cleanup_blocks_spec.rb +1018 -0
  38. data/spec/asciidoctor/cleanup_sections_spec.rb +207 -0
  39. data/spec/asciidoctor/cleanup_spec.rb +193 -1078
  40. data/spec/asciidoctor/inline_spec.rb +36 -0
  41. data/spec/asciidoctor/isobib_cache_spec.rb +8 -8
  42. data/spec/asciidoctor/lists_spec.rb +6 -6
  43. data/spec/asciidoctor/macros_plantuml_spec.rb +1 -1
  44. data/spec/asciidoctor/macros_spec.rb +41 -26
  45. data/spec/asciidoctor/refs_dl_spec.rb +1 -1
  46. data/spec/asciidoctor/refs_spec.rb +220 -444
  47. data/spec/asciidoctor/section_spec.rb +1 -1
  48. data/spec/asciidoctor/validate_spec.rb +51 -0
  49. data/spec/assets/xref_error.adoc +1 -0
  50. data/spec/fixtures/datamodel_description_sections_tree.xml +24 -24
  51. data/spec/spec_helper.rb +5 -7
  52. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +231 -143
  53. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec1.yml +152 -0
  54. data/spec/vcr_cassettes/isobib_get_123.yml +52 -36
  55. data/spec/vcr_cassettes/isobib_get_123_1.yml +103 -71
  56. data/spec/vcr_cassettes/isobib_get_123_1_fr.yml +112 -80
  57. data/spec/vcr_cassettes/isobib_get_123_2001.yml +50 -34
  58. data/spec/vcr_cassettes/isobib_get_124.yml +51 -35
  59. data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +16 -16
  60. data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +70 -46
  61. metadata +11 -4
@@ -15,9 +15,8 @@ module Asciidoctor
15
15
  def svgmap_moveattrs(xmldoc)
16
16
  xmldoc.xpath("//svgmap").each do |s|
17
17
  f = s.at(".//figure") or next
18
- if (t = s.at("./name")) && !f.at("./name")
18
+ (t = s.at("./name")) && !f.at("./name") and
19
19
  f.children.first.previous = t.remove
20
- end
21
20
  if s["id"] && guid?(f["id"])
22
21
  f["id"] = s["id"]
23
22
  s.delete("id")
@@ -26,13 +25,13 @@ module Asciidoctor
26
25
  end
27
26
  end
28
27
 
29
- def svgmap_moveattrs1(s, f)
28
+ def svgmap_moveattrs1(svgmap, figure)
30
29
  %w(unnumbered number subsequence keep-with-next
31
- keep-lines-together).each do |a|
32
- next if f[a] || !s[a]
30
+ keep-lines-together tag multilingual-rendering).each do |a|
31
+ next if figure[a] || !svgmap[a]
33
32
 
34
- f[a] = s[a]
35
- s.delete(a)
33
+ figure[a] = svgmap[a]
34
+ svgmap.delete(a)
36
35
  end
37
36
  end
38
37
 
@@ -1,4 +1,5 @@
1
1
  require "metanorma-utils"
2
+ require "digest"
2
3
 
3
4
  module Asciidoctor
4
5
  module Standoc
@@ -55,103 +56,6 @@ module Asciidoctor
55
56
  end
56
57
  end
57
58
 
58
- # extending localities to cover ISO referencing
59
- LOCALITY_REGEX_STR = <<~REGEXP.freeze
60
- ^((?<locality>section|clause|part|paragraph|chapter|page|
61
- table|annex|figure|example|note|formula|list|time|anchor|
62
- locality:[^ \\t\\n\\r:,;=]+)(\\s+|=)
63
- (?<ref>[^"][^ \\t\\n,:-]*|"[^"]+")
64
- (-(?<to>[^"][^ \\t\\n,:-]*|"[^"]"))?|
65
- (?<locality2>whole|locality:[^ \\t\\n\\r:,;=]+))(?<punct>[,:;]?)\\s*
66
- (?<text>.*)$
67
- REGEXP
68
- LOCALITY_RE = Regexp.new(LOCALITY_REGEX_STR.gsub(/\s/, ""),
69
- Regexp::IGNORECASE | Regexp::MULTILINE)
70
-
71
- def tq(text)
72
- text.sub(/^"/, "").sub(/"$/, "")
73
- end
74
-
75
- def extract_localities(elem)
76
- f = elem&.children&.first or return
77
- f.text? or return
78
- head = f.remove.text
79
- tail = elem&.children&.remove
80
- extract_localities1(elem, head)
81
- tail and elem << tail
82
- end
83
-
84
- def extract_localities1(elem, text)
85
- b = elem.add_child("<localityStack/>").first if LOCALITY_RE.match text
86
- while (m = LOCALITY_RE.match text)
87
- ref = m[:ref] ? "<referenceFrom>#{tq m[:ref]}</referenceFrom>" : ""
88
- refto = m[:to] ? "<referenceTo>#{tq m[:to]}</referenceTo>" : ""
89
- loc = m[:locality]&.downcase || m[:locality2]&.downcase
90
- b.add_child("<locality type='#{loc}'>#{ref}#{refto}</locality>")
91
- text = m[:text]
92
- b = elem.add_child("<localityStack/>").first if m[:punct] == ";"
93
- end
94
- elem.add_child(text) if text
95
- end
96
-
97
- def xref_to_eref(elem)
98
- elem["bibitemid"] = elem["target"]
99
- unless elem["citeas"] = @anchors&.dig(elem["target"], :xref)
100
- @internal_eref_namespaces.include?(elem["type"]) or
101
- @log.add("Crossreferences", elem,
102
- "#{elem['target']} does not have a corresponding "\
103
- "anchor ID in the bibliography!")
104
- end
105
- elem.delete("target")
106
- extract_localities(elem) unless elem.children.empty?
107
- end
108
-
109
- def xref_cleanup(xmldoc)
110
- xmldoc.xpath("//xref").each do |x|
111
- /:/.match(x["target"]) and xref_to_internal_eref(x)
112
- next unless x.name == "xref"
113
-
114
- if refid? x["target"]
115
- x.name = "eref"
116
- xref_to_eref(x)
117
- else x.delete("type")
118
- end
119
- end
120
- end
121
-
122
- def xref_to_internal_eref(elem)
123
- a = elem["target"].split(":", 3)
124
- unless a.size < 2 || a[0].empty? || a[1].empty?
125
- elem["target"] = "#{a[0]}_#{a[1]}"
126
- a.size > 2 and
127
- elem.children = %{anchor="#{a[2..-1].join}",#{elem&.children&.text}}
128
- elem["type"] = a[0]
129
- @internal_eref_namespaces << a[0]
130
- elem.name = "eref"
131
- xref_to_eref(elem)
132
- end
133
- end
134
-
135
- def quotesource_cleanup(xmldoc)
136
- xmldoc.xpath("//quote/source | //terms/source").each do |x|
137
- xref_to_eref(x)
138
- end
139
- end
140
-
141
- def origin_cleanup(xmldoc)
142
- xmldoc.xpath("//origin/concept[termref]").each do |x|
143
- t = x.at("./termref")
144
- x.replace(t)
145
- end
146
- xmldoc.xpath("//origin").each do |x|
147
- x["citeas"] = @anchors&.dig(x["bibitemid"], :xref) or
148
- @log.add("Crossreferences", x,
149
- "#{x['bibitemid']} does not have a corresponding anchor "\
150
- "ID in the bibliography!")
151
- extract_localities(x) unless x.children.empty?
152
- end
153
- end
154
-
155
59
  def concept_cleanup(xmldoc)
156
60
  xmldoc.xpath("//concept[not(termxref)]").each do |x|
157
61
  term = x.at("./refterm")
@@ -203,11 +107,13 @@ module Asciidoctor
203
107
  end
204
108
 
205
109
  IDREF = "//*/@id | //review/@from | //review/@to | "\
206
- "//callout/@target | //citation/@bibitemid | //eref/@bibitemid".freeze
110
+ "//callout/@target | //citation/@bibitemid | "\
111
+ "//eref/@bibitemid".freeze
207
112
 
208
113
  def anchor_cleanup(elem)
209
114
  anchor_cleanup1(elem)
210
115
  xreftarget_cleanup(elem)
116
+ contenthash_id_cleanup(elem)
211
117
  end
212
118
 
213
119
  def anchor_cleanup1(elem)
@@ -233,6 +139,29 @@ module Asciidoctor
233
139
  end
234
140
  end
235
141
  end
142
+
143
+ def guid?(str)
144
+ /^_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/
145
+ .match?(str)
146
+ end
147
+
148
+ def contenthash_id_cleanup(doc)
149
+ ids = doc.xpath("//*[@id]").each_with_object({}) do |x, m|
150
+ next unless guid?(x["id"])
151
+
152
+ m[x["id"]] = contenthash(x)
153
+ x["id"] = m[x["id"]]
154
+ end
155
+ [%w(review from), %(review to), %(callout target), %(eref bibitemid),
156
+ %(citation bibitemid), %(xref target), %(xref to)].each do |a|
157
+ doc.xpath("//#{a[0]}").each { |x| ids[a[1]] and x[a[1]] = ids[a[1]] }
158
+ end
159
+ end
160
+
161
+ def contenthash(elem)
162
+ Digest::MD5.hexdigest("#{elem.path}////#{elem.text}")
163
+ .sub(/^(.{8})(.{4})(.{4})(.{4})(.{12})$/, "_\\1-\\2-\\3-\\4-\\5")
164
+ end
236
165
  end
237
166
  end
238
167
  end
@@ -29,19 +29,19 @@ module Asciidoctor
29
29
  x.to_xml
30
30
  end
31
31
 
32
- def xml_unescape_mathml(x)
33
- return if x.children.any? { |y| y.element? }
32
+ def xml_unescape_mathml(xml)
33
+ return if xml.children.any? { |y| y.element? }
34
34
 
35
- math = x.text.gsub(/&lt;/, "<").gsub(/&gt;/, ">")
35
+ math = xml.text.gsub(/&lt;/, "<").gsub(/&gt;/, ">")
36
36
  .gsub(/&quot;/, '"').gsub(/&apos;/, "'").gsub(/&amp;/, "&")
37
37
  .gsub(/<[^: \r\n\t\/]+:/, "<").gsub(/<\/[^ \r\n\t:]+:/, "</")
38
- x.children = math
38
+ xml.children = math
39
39
  end
40
40
 
41
41
  MATHML_NS = "http://www.w3.org/1998/Math/MathML".freeze
42
42
 
43
- def mathml_preserve_space(m)
44
- m.xpath(".//m:mtext", "m" => MATHML_NS).each do |x|
43
+ def mathml_preserve_space(math)
44
+ math.xpath(".//m:mtext", "m" => MATHML_NS).each do |x|
45
45
  x.children = x.children.to_xml
46
46
  .gsub(/^\s/, "&#xA0;").gsub(/\s$/, "&#xA0;")
47
47
  end
@@ -57,23 +57,23 @@ module Asciidoctor
57
57
  end
58
58
 
59
59
  # presuppose multichar mi upright, singlechar mi MathML default italic
60
- def mathml_italicise(x)
61
- x.xpath(".//m:mi[not(ancestor::*[@mathvariant])]",
62
- "m" => MATHML_NS).each do |i|
60
+ def mathml_italicise(xml)
61
+ xml.xpath(".//m:mi[not(ancestor::*[@mathvariant])]",
62
+ "m" => MATHML_NS).each do |i|
63
63
  char = HTMLEntities.new.decode(i.text)
64
64
  i["mathvariant"] = "normal" if mi_italicise?(char)
65
65
  end
66
66
  end
67
67
 
68
- def mi_italicise?(c)
69
- return false if c.length > 1
68
+ def mi_italicise?(char)
69
+ return false if char.length > 1
70
70
 
71
- if /\p{Greek}/.match?(c)
72
- /\p{Lower}/.match(c) && !mathml_mi_italics[:lowergreek] ||
73
- /\p{Upper}/.match(c) && !mathml_mi_italics[:uppergreek]
74
- elsif /\p{Latin}/.match?(c)
75
- /\p{Lower}/.match(c) && !mathml_mi_italics[:lowerroman] ||
76
- /\p{Upper}/.match(c) && !mathml_mi_italics[:upperroman]
71
+ if /\p{Greek}/.match?(char)
72
+ /\p{Lower}/.match(char) && !mathml_mi_italics[:lowergreek] ||
73
+ /\p{Upper}/.match(char) && !mathml_mi_italics[:uppergreek]
74
+ elsif /\p{Latin}/.match?(char)
75
+ /\p{Lower}/.match(char) && !mathml_mi_italics[:lowerroman] ||
76
+ /\p{Upper}/.match(char) && !mathml_mi_italics[:upperroman]
77
77
  else
78
78
  false
79
79
  end
@@ -100,14 +100,14 @@ module Asciidoctor
100
100
  end
101
101
  end
102
102
 
103
- def gather_unitsml(unitsml, xmldoc, t)
104
- tags = xmldoc.xpath(".//m:#{t}", "m" => UNITSML_NS)
103
+ def gather_unitsml(unitsml, xmldoc, tag)
104
+ tags = xmldoc.xpath(".//m:#{tag}", "m" => UNITSML_NS)
105
105
  .each_with_object({}) do |x, m|
106
106
  m[x["id"]] = x.remove
107
107
  end
108
108
  return if tags.empty?
109
109
 
110
- set = unitsml.add_child("<#{t}Set/>").first
110
+ set = unitsml.add_child("<#{tag}Set/>").first
111
111
  tags.each_value { |v| set << v }
112
112
  end
113
113
 
@@ -115,14 +115,106 @@ module Asciidoctor
115
115
  { multiplier: :space }
116
116
  end
117
117
 
118
+ def mathvariant_override(inner, outer)
119
+ case outer
120
+ when "bold"
121
+ case inner
122
+ when "normal" then "bold"
123
+ when "italic" then "bold-italic"
124
+ when "fraktur" then "bold-fraktur"
125
+ when "script" then "bold-script"
126
+ when "sans-serif" then "bold-sans-serif"
127
+ when "sans-serif-italic" then "sans-serif-bold-italic"
128
+ else inner
129
+ end
130
+ when "italic"
131
+ case inner
132
+ when "normal" then "italic"
133
+ when "bold" then "bold-italic"
134
+ when "sans-serif" then "sans-serif-italic"
135
+ when "bold-sans-serif" then "sans-serif-bold-italic"
136
+ else inner
137
+ end
138
+ when "bold-italic"
139
+ case inner
140
+ when "normal", "bold", "italic" then "bold-italic"
141
+ when "sans-serif", "bold-sans-serif", "sans-serif-italic"
142
+ "sans-serif-bold-italic"
143
+ else inner
144
+ end
145
+ when "fraktur"
146
+ case inner
147
+ when "normal" then "fraktur"
148
+ when "bold" then "bold-fraktur"
149
+ else inner
150
+ end
151
+ when "bold-fraktur"
152
+ case inner
153
+ when "normal", "fraktur" then "bold-fraktur"
154
+ else inner
155
+ end
156
+ when "script"
157
+ case inner
158
+ when "normal" then "script"
159
+ when "bold" then "bold-script"
160
+ else inner
161
+ end
162
+ when "bold-script"
163
+ case inner
164
+ when "normal", "script" then "bold-script"
165
+ else inner
166
+ end
167
+ when "sans-serif"
168
+ case inner
169
+ when "normal" then "sans-serif"
170
+ when "bold" then "bold-sans-serif"
171
+ when "italic" then "sans-serif-italic"
172
+ when "bold-italic" then "sans-serif-bold-italic"
173
+ else inner
174
+ end
175
+ when "bold-sans-serif"
176
+ case inner
177
+ when "normal", "bold", "sans-serif" then "bold-sans-serif"
178
+ when "italic", "bold-italic", "sans-serif-italic"
179
+ "sans-serif-bold-italic"
180
+ else inner
181
+ end
182
+ when "sans-serif-italic"
183
+ case inner
184
+ when "normal", "italic", "sans-serif" then "sans-serif-italic"
185
+ when "bold", "bold-italic", "sans-serif-bold"
186
+ "sans-serif-bold-italic"
187
+ else inner
188
+ end
189
+ when "sans-serif-bold-italic"
190
+ case inner
191
+ when "normal", "italic", "sans-serif", "sans-serif-italic",
192
+ "bold", "bold-italic", "sans-serif-bold"
193
+ "sans-serif-bold-italic"
194
+ else inner
195
+ end
196
+ else inner
197
+ end
198
+ end
199
+
200
+ def mathml_mathvariant(math)
201
+ math.xpath(".//*[@mathvariant]").each do |outer|
202
+ outer.xpath(".//*[@mathvariant]").each do |inner|
203
+ inner["mathvariant"] =
204
+ mathvariant_override(outer["mathvariant"], inner["mathvariant"])
205
+ end
206
+ end
207
+ end
208
+
118
209
  def mathml_cleanup(xmldoc)
119
210
  unitsml = Asciimath2UnitsML::Conv.new(asciimath2unitsml_options)
120
211
  xmldoc.xpath("//stem[@type = 'MathML']").each do |x|
121
212
  xml_unescape_mathml(x)
122
213
  mathml_namespace(x)
123
214
  mathml_preserve_space(x)
124
- mathml_italicise(x)
125
215
  unitsml.MathML2UnitsML(x)
216
+ mathml_mathvariant(x)
217
+ mathml_italicise(x)
126
218
  end
127
219
  mathml_unitsML(xmldoc)
128
220
  end
@@ -84,6 +84,11 @@ module Asciidoctor
84
84
  biblio_reorder(xmldoc)
85
85
  biblio_nested(xmldoc)
86
86
  biblio_renumber(xmldoc)
87
+ biblio_no_ext(xmldoc)
88
+ end
89
+
90
+ def biblio_no_ext(xmldoc)
91
+ xmldoc.xpath("//bibitem/ext").each(&:remove)
87
92
  end
88
93
 
89
94
  def biblio_nested(xmldoc)
@@ -3,36 +3,61 @@ module Asciidoctor
3
3
  module Cleanup
4
4
  def requirement_cleanup(xmldoc)
5
5
  requirement_metadata(xmldoc)
6
- requirement_descriptions(xmldoc)
7
6
  requirement_inherit(xmldoc)
7
+ requirement_descriptions(xmldoc)
8
8
  end
9
9
 
10
10
  REQRECPER = "//requirement | //recommendation | //permission".freeze
11
11
 
12
12
  def requirement_inherit(xmldoc)
13
13
  xmldoc.xpath(REQRECPER).each do |r|
14
- ins = r.at("./classification") ||
15
- r.at("./description | ./measurementtarget | ./specification | "\
16
- "./verification | ./import | ./description | ./requirement | "\
17
- "./recommendation | ./permission | ./component")
14
+ ins = requirement_inherit_insert(r)
18
15
  r.xpath("./*//inherit").each { |i| ins.previous = i }
19
16
  end
20
17
  end
21
18
 
19
+ def requirement_inherit_insert(reqt)
20
+ ins = reqt.at("./classification") || reqt.at(
21
+ "./description | ./measurementtarget | ./specification | "\
22
+ "./verification | ./import | ./description | ./component | "\
23
+ "./requirement | ./recommendation | ./permission",
24
+ ) and return ins
25
+ requirement_inherit_insert1(reqt)
26
+ end
27
+
28
+ def requirement_inherit_insert1(reqt)
29
+ if t = reqt.at("./title")
30
+ t.next = " "
31
+ t.next
32
+ else
33
+ if reqt.children.empty? then reqt.add_child(" ")
34
+ else reqt.children.first.previous = " "
35
+ end
36
+ reqt.children.first
37
+ end
38
+ end
39
+
22
40
  def requirement_descriptions(xmldoc)
23
41
  xmldoc.xpath(REQRECPER).each do |r|
42
+ r.xpath(".//p[not(./*)][normalize-space(.)='']").each(&:remove)
24
43
  r.children.each do |e|
25
- unless e.element? && (reqt_subpart(e.name) ||
26
- %w(requirement recommendation permission).include?(e.name))
27
- t = Nokogiri::XML::Element.new("description", r)
28
- e.before(t)
29
- t.children = e.remove
30
- end
44
+ requirement_description_wrap(r, e)
31
45
  end
32
46
  requirement_description_cleanup1(r)
33
47
  end
34
48
  end
35
49
 
50
+ def requirement_description_wrap(reqt, text)
51
+ return if text.element? && (reqt_subpart(text.name) ||
52
+ %w(requirement recommendation
53
+ permission).include?(text.name)) ||
54
+ text.text.strip.empty?
55
+
56
+ t = Nokogiri::XML::Element.new("description", reqt)
57
+ text.before(t)
58
+ t.children = text.remove
59
+ end
60
+
36
61
  def requirement_description_cleanup1(reqt)
37
62
  while d = reqt.at("./description[following-sibling::*[1]"\
38
63
  "[self::description]]")
@@ -47,21 +72,34 @@ module Asciidoctor
47
72
  def requirement_metadata(xmldoc)
48
73
  xmldoc.xpath(REQRECPER).each do |r|
49
74
  dl = r&.at("./dl[@metadata = 'true']")&.remove or next
50
- requirement_metadata1(r, dl)
75
+ requirement_metadata1(r, dl, r.at("./title"))
51
76
  end
52
77
  end
53
78
 
54
- def requirement_metadata1(reqt, dlist)
55
- unless ins = reqt.at("./title")
79
+ def requirement_metadata1_tags
80
+ %w(label subject inherit)
81
+ end
82
+
83
+ def requirement_metadata1(reqt, dlist, ins)
84
+ unless ins
56
85
  reqt.children.first.previous = " "
57
86
  ins = reqt.children.first
58
87
  end
59
- %w(label subject inherit).each do |a|
88
+ %w(obligation model type).each do |a|
89
+ reqt_dl_to_attrs(reqt, dlist, a)
90
+ end
91
+ requirement_metadata1_tags.each do |a|
60
92
  ins = reqt_dl_to_elems(ins, reqt, dlist, a)
61
93
  end
62
94
  reqt_dl_to_classif(ins, reqt, dlist)
63
95
  end
64
96
 
97
+ def reqt_dl_to_attrs(reqt, dlist, name)
98
+ e = dlist.at("./dt[text()='#{name}']") or return
99
+ val = e.at("./following::dd/p") || e.at("./following::dd") or return
100
+ reqt[name] = val.text
101
+ end
102
+
65
103
  def reqt_dl_to_elems(ins, reqt, dlist, name)
66
104
  if a = reqt.at("./#{name}[last()]")
67
105
  ins = a
@@ -76,16 +114,16 @@ module Asciidoctor
76
114
  end
77
115
 
78
116
  def reqt_dl_to_classif(ins, reqt, dlist)
79
- if a = reqt.at("./classification[last()]")
80
- ins = a
81
- end
117
+ if a = reqt.at("./classification[last()]") then ins = a end
82
118
  dlist.xpath("./dt[text()='classification']").each do |e|
83
119
  val = e.at("./following::dd/p") || e.at("./following::dd")
84
120
  req_classif_parse(val.text).each do |r|
85
121
  ins.next = "<classification><tag>#{r[0]}</tag>"\
86
122
  "<value>#{r[1]}</value></classification>"
123
+ ins = ins.next
87
124
  end
88
125
  end
126
+ ins
89
127
  end
90
128
  end
91
129
  end
@@ -114,6 +114,7 @@ module Asciidoctor
114
114
  sections_order_cleanup(xml)
115
115
  sections_level_cleanup(xml)
116
116
  sections_names_cleanup(xml)
117
+ sections_variant_title_cleanup(xml)
117
118
  change_clauses(xml)
118
119
  end
119
120
 
@@ -37,39 +37,56 @@ module Asciidoctor
37
37
  end
38
38
 
39
39
  def section_names_refs_cleanup(xml)
40
- replace_title(xml, "//references[@normative = 'true']",
40
+ replace_title(xml, "//bibliography/references[@normative = 'true']",
41
41
  @i18n&.normref, true)
42
- replace_title(xml, "//references[@normative = 'false']",
42
+ replace_title(xml, "//bibliography/references[@normative = 'false']",
43
43
  @i18n&.bibliography, true)
44
44
  end
45
45
 
46
46
  NO_SYMABBR = "[.//definitions[not(@type)]]".freeze
47
47
  SYMABBR = "[.//definitions[@type = 'symbols']]"\
48
- "[.//definitions[@type = 'abbreviated_terms']]".freeze
48
+ "[.//definitions[@type = 'abbreviated_terms']]".freeze
49
49
  SYMnoABBR = "[.//definitions[@type = 'symbols']]"\
50
- "[not(.//definitions[@type = 'abbreviated_terms'])]".freeze
50
+ "[not(.//definitions[@type = 'abbreviated_terms'])]".freeze
51
51
  ABBRnoSYM = "[.//definitions[@type = 'abbreviated_terms']]"\
52
- "[not(.//definitions[@type = 'symbols'])]".freeze
52
+ "[not(.//definitions[@type = 'symbols'])]".freeze
53
53
 
54
- def section_names_terms_cleanup(x)
55
- replace_title(x, "//definitions[@type = 'symbols']", @i18n&.symbols)
56
- replace_title(x, "//definitions[@type = 'abbreviated_terms']",
54
+ def section_names_terms_cleanup(xml)
55
+ replace_title(xml, "//definitions[@type = 'symbols']", @i18n&.symbols)
56
+ replace_title(xml, "//definitions[@type = 'abbreviated_terms']",
57
57
  @i18n&.abbrev)
58
- replace_title(x, "//definitions[not(@type)]", @i18n&.symbolsabbrev)
59
- replace_title(x, "//terms#{SYMnoABBR} | //clause[.//terms]#{SYMnoABBR}",
58
+ replace_title(xml, "//definitions[not(@type)]", @i18n&.symbolsabbrev)
59
+ replace_title(xml, "//terms#{SYMnoABBR} | //clause[.//terms]#{SYMnoABBR}",
60
60
  @i18n&.termsdefsymbols, true)
61
- replace_title(x, "//terms#{ABBRnoSYM} | //clause[.//terms]#{ABBRnoSYM}",
61
+ replace_title(xml, "//terms#{ABBRnoSYM} | //clause[.//terms]#{ABBRnoSYM}",
62
62
  @i18n&.termsdefabbrev, true)
63
- replace_title(x, "//terms#{SYMABBR} | //clause[.//terms]#{SYMABBR}",
63
+ replace_title(xml, "//terms#{SYMABBR} | //clause[.//terms]#{SYMABBR}",
64
64
  @i18n&.termsdefsymbolsabbrev, true)
65
- replace_title(x, "//terms#{NO_SYMABBR} | //clause[.//terms]#{NO_SYMABBR}",
65
+ replace_title(xml, "//terms#{NO_SYMABBR} | //clause[.//terms]#{NO_SYMABBR}",
66
66
  @i18n&.termsdefsymbolsabbrev, true)
67
67
  replace_title(
68
- x,
68
+ xml,
69
69
  "//terms[not(.//definitions)] | //clause[.//terms][not(.//definitions)]",
70
70
  @i18n&.termsdef, true
71
71
  )
72
72
  end
73
+
74
+ SECTION_CONTAINERS = %w(foreword introduction acknowledgements abstract
75
+ clause clause references terms definitions annex
76
+ appendix).freeze
77
+
78
+ def sections_variant_title_cleanup(xml)
79
+ path = SECTION_CONTAINERS.map { |x| "./ancestor::#{x}" }.join(" | ")
80
+ xml.xpath("//p[@variant_title]").each do |p|
81
+ p.name = "variant-title"
82
+ p.delete("id")
83
+ p.delete("variant_title")
84
+ p.xpath("(#{path})[last()]").each do |sect|
85
+ ins = sect.at("./title") and ins.next = p or
86
+ sect.children.first.previous = p
87
+ end
88
+ end
89
+ end
73
90
  end
74
91
  end
75
92
  end
@@ -0,0 +1,68 @@
1
+ module Asciidoctor
2
+ module Standoc
3
+ module Cleanup
4
+ def dl1_table_cleanup(xmldoc)
5
+ q = "//table/following-sibling::*[1][self::dl]"
6
+ xmldoc.xpath(q).each do |s|
7
+ s["key"] == "true" and s.previous_element << s.remove
8
+ end
9
+ end
10
+
11
+ # move Key dl after table footer
12
+ def dl2_table_cleanup(xmldoc)
13
+ q = "//table/following-sibling::*[1][self::p]"
14
+ xmldoc.xpath(q).each do |s|
15
+ if s.text =~ /^\s*key[^a-z]*$/i && s&.next_element&.name == "dl"
16
+ s.next_element["key"] = "true"
17
+ s.previous_element << s.next_element.remove
18
+ s.remove
19
+ end
20
+ end
21
+ end
22
+
23
+ def insert_thead(table)
24
+ thead = table.at("./thead")
25
+ return thead unless thead.nil?
26
+
27
+ if tname = table.at("./name")
28
+ thead = tname.add_next_sibling("<thead/>").first
29
+ return thead
30
+ end
31
+ table.children.first.add_previous_sibling("<thead/>").first
32
+ end
33
+
34
+ def header_rows_cleanup(xmldoc)
35
+ xmldoc.xpath("//table[@headerrows]").each do |s|
36
+ thead = insert_thead(s)
37
+ (thead.xpath("./tr").size...s["headerrows"].to_i).each do
38
+ row = s.at("./tbody/tr")
39
+ row.parent = thead
40
+ end
41
+ thead.xpath(".//td").each { |n| n.name = "th" }
42
+ s.delete("headerrows")
43
+ end
44
+ end
45
+
46
+ def table_cleanup(xmldoc)
47
+ dl1_table_cleanup(xmldoc)
48
+ dl2_table_cleanup(xmldoc)
49
+ notes_table_cleanup(xmldoc)
50
+ header_rows_cleanup(xmldoc)
51
+ end
52
+
53
+ # move notes into table
54
+ def notes_table_cleanup(xmldoc)
55
+ nomatches = false
56
+ until nomatches
57
+ nomatches = true
58
+ xmldoc.xpath("//table/following-sibling::*[1]"\
59
+ "[self::note[not(@keep-separate = 'true')]]").each do |n|
60
+ n.delete("keep-separate")
61
+ n.previous_element << n.remove
62
+ nomatches = false
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -29,7 +29,7 @@ module Asciidoctor
29
29
  end
30
30
 
31
31
  def termdefinition_cleanup(xmldoc)
32
- xmldoc.xpath("//term").each do |d|
32
+ xmldoc.xpath("//term[not(definition)]").each do |d|
33
33
  first_child = d.at("./p | ./figure | ./formula") || next
34
34
  t = Nokogiri::XML::Element.new("definition", xmldoc)
35
35
  first_child.replace(t)