metanorma-standoc 1.10.4.1 → 1.10.8

Sign up to get free protection for your applications and to get access to all the features.
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)