metanorma-standoc 1.5.1 → 1.5.2

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 (30) hide show
  1. checksums.yaml +4 -4
  2. data/lib/asciidoctor/standoc/base.rb +1 -1
  3. data/lib/asciidoctor/standoc/cleanup.rb +1 -0
  4. data/lib/asciidoctor/standoc/cleanup_inline.rb +57 -1
  5. data/lib/asciidoctor/standoc/cleanup_ref.rb +3 -1
  6. data/lib/asciidoctor/standoc/cleanup_section.rb +18 -1
  7. data/lib/asciidoctor/standoc/cleanup_terms.rb +2 -2
  8. data/lib/asciidoctor/standoc/isodoc.rng +4 -1
  9. data/lib/asciidoctor/standoc/log.rb +10 -1
  10. data/lib/asciidoctor/standoc/utils.rb +2 -1
  11. data/lib/asciidoctor/standoc/validate.rb +30 -18
  12. data/lib/asciidoctor/standoc/validate_section.rb +1 -1
  13. data/lib/metanorma/standoc/version.rb +1 -1
  14. data/metanorma-standoc.gemspec +1 -1
  15. data/spec/asciidoctor-standoc/base_spec.rb +2 -1
  16. data/spec/asciidoctor-standoc/blocks_spec.rb +8 -1
  17. data/spec/asciidoctor-standoc/cleanup_spec.rb +121 -11
  18. data/spec/asciidoctor-standoc/inline_spec.rb +4 -1
  19. data/spec/asciidoctor-standoc/macros_spec.rb +41 -23
  20. data/spec/asciidoctor-standoc/refs_dl_spec.rb +3 -1
  21. data/spec/asciidoctor-standoc/table_spec.rb +7 -1
  22. data/spec/asciidoctor-standoc/validate_spec.rb +22 -0
  23. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +66 -66
  24. data/spec/vcr_cassettes/isobib_get_123.yml +16 -16
  25. data/spec/vcr_cassettes/isobib_get_123_1.yml +33 -33
  26. data/spec/vcr_cassettes/isobib_get_123_2001.yml +19 -19
  27. data/spec/vcr_cassettes/isobib_get_124.yml +19 -19
  28. data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +8 -8
  29. data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +28 -28
  30. metadata +4 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2b4ec9dd5050345506b6b416eaad6b57865cb3c0b9e57e00e3b52f625fe87a48
4
- data.tar.gz: 4e53f6a44684a9694104f74c7560040893a47c70c5c8292810e9349a32c1e151
3
+ metadata.gz: 910ada4e6d4f62c6106391e3ec0de46a7ba4a9d5362bb103cd80ee0b2acef9dc
4
+ data.tar.gz: de8546c035da0236faa4a6ca5df9b0f54f16806d09386793f359e55b69884212
5
5
  SHA512:
6
- metadata.gz: 8d437d0619e0da4931009f2f92db0778bdd0eccb9bd15f81a7e38edc66a89474cecaa4099bd55bf8178a13a9551d533378068730231e2ed13d2ead794da7cb3a
7
- data.tar.gz: c5a606e3c94a341a6ce19bf5e77df8bf49eeae5d68cf6143d7050190a29f7213a34d74ab7743b87f54d7766fd17606cfb05f05b51a63f7a85ae113b9a23e98fd
6
+ metadata.gz: 422e64b66f95fa4c49727687c446bd3f79bc09aa0609b352bd68cc659ff06bf57243ed410e4baa8f0cb501f101212d305a756b41548fcee7e877135aea22e1f3
7
+ data.tar.gz: 97d6e164975997ecc396376abdaf2edad43c1f4fbfa601dbbc5f2f4d465747164350f500aaadc05f9fd6ed1e499925df7d74626fcde21a0578feeb50d607b84e
@@ -170,7 +170,7 @@ module Asciidoctor
170
170
  end
171
171
 
172
172
  def doctype(node)
173
- node.attr("doctype")
173
+ node.attr("doctype")&.gsub(/\s+/, "-")&.downcase
174
174
  end
175
175
 
176
176
  def front(node, xml)
@@ -71,6 +71,7 @@ module Asciidoctor
71
71
  para_cleanup(xmldoc)
72
72
  empty_element_cleanup(xmldoc)
73
73
  img_cleanup(xmldoc)
74
+ anchor_cleanup(xmldoc)
74
75
  xmldoc
75
76
  end
76
77
 
@@ -117,7 +117,8 @@ module Asciidoctor
117
117
  def concept_termbase_cleanup(x)
118
118
  text = x&.children&.first&.remove&.text
119
119
  termbase, key = x["key"].split(/:/, 2)
120
- x.add_child(%(<termref base="#{termbase}" target="#{key}">#{text}</termref>))
120
+ x.add_child(%(<termref base="#{termbase}" target="#{key}">) +
121
+ "#{text}</termref>")
121
122
  end
122
123
 
123
124
  def concept_xref_cleanup(x)
@@ -129,6 +130,61 @@ module Asciidoctor
129
130
  x.children = "<eref>#{x.children.to_xml}</eref>"
130
131
  extract_localities(x.first_element_child)
131
132
  end
133
+
134
+ NAMECHAR = "\u0000-\u0022\u0024\u002c\u002f\u003a-\u0040\\u005b-\u005e"\
135
+ "\u0060\u007b-\u00b6\u00b8-\u00bf\u00d7\u00f7\u037e\u2000-\u200b"\
136
+ "\u200e-\u203e\u2041-\u206f\u2190-\u2bff\u2ff0-\u3000".freeze
137
+ #"\ud800-\uf8ff\ufdd0-\ufdef\ufffe-\uffff".freeze
138
+ NAMESTARTCHAR = "\\u002d\u002e\u0030-\u0039\u00b7\u0300-\u036f"\
139
+ "\u203f-\u2040".freeze
140
+
141
+ def to_ncname(s)
142
+ start = s[0]
143
+ ret1 = %r([#{NAMECHAR}#]).match(start) ? "_" :
144
+ (%r([#{NAMESTARTCHAR}#]).match(start) ? "_#{start}" : start)
145
+ ret = ret1 + s[1..-1].gsub(%r([#{NAMECHAR}#]), "_")
146
+ ret
147
+ end
148
+
149
+ def to_xreftarget(s)
150
+ return to_ncname(s) unless /^[^#]+#.+$/.match(s)
151
+ /^(?<pref>[^#]+)#(?<suff>.+)$/ =~ s
152
+ pref = pref.gsub(%r([#{NAMECHAR}]), "_")
153
+ suff = suff.gsub(%r([#{NAMECHAR}]), "_")
154
+ "#{pref}##{suff}"
155
+ end
156
+
157
+ IDREF = "//*/@id | //review/@from | //review/@to | "\
158
+ "//callout/@target | //citation/@bibitemid | //eref/@bibitemid".freeze
159
+
160
+ def anchor_cleanup(x)
161
+ anchor_cleanup1(x)
162
+ xreftarget_cleanup(x)
163
+ end
164
+
165
+ def anchor_cleanup1(x)
166
+ x.xpath(IDREF).each do |s|
167
+ if (ret = to_ncname(s.value)) != (orig = s.value)
168
+ s.value = ret
169
+ output = s.parent.dup
170
+ output.children.remove
171
+ @log.add("Anchors", s.parent, "normalised identifier in #{output} "\
172
+ "from #{orig}")
173
+ end
174
+ end
175
+ end
176
+
177
+ def xreftarget_cleanup(x)
178
+ x.xpath("//xref/@target").each do |s|
179
+ if (ret = to_xreftarget(s.value)) != (orig = s.value)
180
+ s.value = ret
181
+ output = s.parent.dup
182
+ output.children.remove
183
+ @log.add("Anchors", s.parent, "normalised identifier in #{output} "\
184
+ "from #{orig}")
185
+ end
186
+ end
187
+ end
132
188
  end
133
189
  end
134
190
  end
@@ -203,7 +203,9 @@ module Asciidoctor
203
203
  end
204
204
  if !nested and c.at("./title")
205
205
  title = c.at("./title").remove.children.to_xml
206
- bib["title"] = bib["title"] ? Array(bib["title"]) : []
206
+ bib["title"] = [bib["title"]] if bib["title"].is_a? Hash
207
+ bib["title"] = [bib["title"]] if bib["title"].is_a? String
208
+ bib["title"] = [] unless bib["title"]
207
209
  bib["title"] << title if !title.empty?
208
210
  end
209
211
  bib
@@ -141,12 +141,29 @@ module Asciidoctor
141
141
  end
142
142
 
143
143
  def clausebefore_cleanup(xmldoc)
144
+ preface_clausebefore_cleanup(xmldoc)
145
+ sections_clausebefore_cleanup(xmldoc)
146
+ end
147
+
148
+ def preface_clausebefore_cleanup(xmldoc)
149
+ return unless xmldoc.at("//preface")
150
+ unless ins = xmldoc.at("//preface").children.first
151
+ xmldoc.at("//preface") << " "
152
+ ins = xmldoc.at("//preface").children.first
153
+ end
154
+ xmldoc.xpath("//preface//*[@beforeclauses = 'true']").each do |x|
155
+ x.delete("beforeclauses")
156
+ ins.previous = x.remove
157
+ end
158
+ end
159
+
160
+ def sections_clausebefore_cleanup(xmldoc)
144
161
  return unless xmldoc.at("//sections")
145
162
  unless ins = xmldoc.at("//sections").children.first
146
163
  xmldoc.at("//sections") << " "
147
164
  ins = xmldoc.at("//sections").children.first
148
165
  end
149
- xmldoc.xpath("//*[@beforeclauses = 'true']").each do |x|
166
+ xmldoc.xpath("//sections//*[@beforeclauses = 'true']").each do |x|
150
167
  x.delete("beforeclauses")
151
168
  ins.previous = x.remove
152
169
  end
@@ -110,8 +110,8 @@ module Asciidoctor
110
110
  end
111
111
  ret = Nokogiri::XML(key.to_xml)
112
112
  HTMLEntities.new.decode(ret.text).
113
- gsub(/[\[\]\{\}<>\(\)]/, "").strip.
114
- gsub(/[[:punct]]|[_^]/, ":\\0").gsub(/`/, "").
113
+ gsub(/[\[\]\{\}<>\(\)]/, "").gsub(/\s/m, "").
114
+ gsub(/[[:punct:]]|[_^]/, ":\\0").gsub(/`/, "").
115
115
  gsub(/[0-9]+/, "þ\\0")
116
116
  end
117
117
 
@@ -42,8 +42,11 @@
42
42
  </define>
43
43
  <define name="xref">
44
44
  <element name="xref">
45
+ <!-- attribute target { xsd:IDREF }, -->
45
46
  <attribute name="target">
46
- <data type="IDREF"/>
47
+ <data type="string">
48
+ <param name="pattern">\i\c*|\c+#\c+</param>
49
+ </data>
47
50
  </attribute>
48
51
  <optional>
49
52
  <attribute name="type">
@@ -8,7 +8,8 @@ module Asciidoctor
8
8
  def add(category, loc, msg)
9
9
  return if @novalid
10
10
  @log[category] = [] unless @log[category]
11
- @log[category] << { location: current_location(loc), message: msg }
11
+ @log[category] << { location: current_location(loc), message: msg,
12
+ context: context(loc) }
12
13
  loc = loc.nil? ? "" : "(#{current_location(loc)}): "
13
14
  warn "#{category}: #{loc}#{msg}"
14
15
  end
@@ -31,6 +32,13 @@ module Asciidoctor
31
32
  "??"
32
33
  end
33
34
 
35
+ def context(n)
36
+ return nil if n.is_a? String
37
+ n.respond_to?(:to_xml) and return n.to_xml
38
+ n.respond_to?(:to_s) and return n.to_s
39
+ nil
40
+ end
41
+
34
42
  def write(file)
35
43
  File.open(file, "w:UTF-8") do |f|
36
44
  f.puts "#{file} errors"
@@ -41,6 +49,7 @@ module Asciidoctor
41
49
  end.each do |n|
42
50
  loc = n[:location] ? "(#{n[:location]}): " : ""
43
51
  f.puts "#{loc}#{n[:message]}"
52
+ n[:context]&.split(/\n/)&.first(5)&.each { |l| f.puts "\t#{l}" }
44
53
  end
45
54
  end
46
55
  end
@@ -128,7 +128,8 @@ module Asciidoctor
128
128
  ::Nokogiri::XML::Builder.with fragment, &block
129
129
  fragment.to_xml(encoding: "US-ASCII", indent: 0).lines.map do |l|
130
130
  l.gsub(/>\n$/, ">").gsub(/\s*\n$/m, " ").gsub("&#150;", "\u0096").
131
- gsub("&#151;", "\u0097")
131
+ gsub("&#151;", "\u0097").gsub("&#x96;", "\u0096").
132
+ gsub("&#x97;", "\u0097")
132
133
  end
133
134
  end
134
135
 
@@ -8,7 +8,8 @@ module Asciidoctor
8
8
  module Standoc
9
9
  module Validate
10
10
 
11
- SOURCELOCALITY = "./termsource/origin//locality[@type = 'clause']/referenceFrom".freeze
11
+ SOURCELOCALITY = "./termsource/origin//locality[@type = 'clause']/"\
12
+ "referenceFrom".freeze
12
13
 
13
14
  def init_iev
14
15
  return nil if @no_isobib
@@ -19,13 +20,16 @@ module Asciidoctor
19
20
 
20
21
  def iev_validate(xmldoc)
21
22
  xmldoc.xpath("//term").each do |t|
22
- /^IEC 60050-/.match(t&.at("./termsource/origin/@citeas")&.text) or next
23
- pref = t.xpath("./preferred").inject([]) { |m, x| m << x&.text&.downcase }
24
- locality = t.xpath(SOURCELOCALITY)&.text or next
23
+ /^IEC 60050-/.match(t&.at("./termsource/origin/@citeas")&.text) &&
24
+ loc = t.xpath(SOURCELOCALITY)&.text or next
25
25
  @iev = init_iev or return
26
- iev = @iev.fetch(locality, xmldoc&.at("//language")&.text || "en") or next
26
+ iev = @iev.fetch(loc, xmldoc&.at("//language")&.text || "en") or next
27
+ pref = t.xpath("./preferred").inject([]) do |m, x|
28
+ m << x&.text&.downcase
29
+ end
27
30
  pref.include?(iev.downcase) or
28
- @log.add("Bibliography", t, %(Term "#{pref[0]}" does not match IEV #{locality} "#{iev}"))
31
+ @log.add("Bibliography", t, %(Term "#{pref[0]}" does not match ) +
32
+ %(IEV #{loc} "#{iev}"))
29
33
  end
30
34
  end
31
35
 
@@ -35,20 +39,26 @@ module Asciidoctor
35
39
  iev_validate(doc.root)
36
40
  end
37
41
 
42
+ def repeat_id_validate1(ids, x)
43
+ if ids[x["id"]]
44
+ @log.add("Anchors", x, "Anchor #{x['id']} has already been used "\
45
+ "at line #{ids[x['id']]}")
46
+ raise StandardError.new "Error: multiple instances of same ID"
47
+ else
48
+ ids[x["id"]] = x.line
49
+ end
50
+ ids
51
+ end
52
+
38
53
  def repeat_id_validate(doc)
39
54
  ids = {}
40
- crash = false
41
- doc.xpath("//*[@id]").each do |x|
42
- if ids[x["id"]]
43
- @log.add("Anchors", x, "Anchor #{x['id']} has already been used at line #{ids[x['id']]}")
44
- crash = true
45
- else
46
- ids[x["id"]] = x.line
55
+ begin
56
+ doc.xpath("//*[@id]").each do |x|
57
+ ids = repeat_id_validate1(ids, x)
47
58
  end
48
- end
49
- if crash
59
+ rescue StandardError => e
50
60
  clean_exit
51
- abort("Cannot deal with multiple instances of same ID")
61
+ abort(e.message)
52
62
  end
53
63
  end
54
64
 
@@ -59,8 +69,10 @@ module Asciidoctor
59
69
  f.close
60
70
  errors = Jing.new(schema).validate(f.path)
61
71
  warn "Syntax Valid!" if errors.none?
62
- errors.each do |error|
63
- @log.add("Syntax", "XML Line #{"%06d" % error[:line]}:#{error[:column]}", error[:message])
72
+ errors.each do |e|
73
+ @log.add("Metanorma XML Syntax",
74
+ "XML Line #{"%06d" % e[:line]}:#{e[:column]}",
75
+ e[:message])
64
76
  end
65
77
  rescue Jing::Error => e
66
78
  clean_exit
@@ -22,7 +22,7 @@ module Asciidoctor
22
22
  def style_warning(node, msg, text = nil)
23
23
  w = msg
24
24
  w += ": #{text}" if text
25
- @log.add("Style Warning", node, w)
25
+ @log.add("Metanorma XML Style Warning", node, w)
26
26
  end
27
27
 
28
28
  def asset_title_style(root)
@@ -1,5 +1,5 @@
1
1
  module Metanorma
2
2
  module Standoc
3
- VERSION = "1.5.1".freeze
3
+ VERSION = "1.5.2".freeze
4
4
  end
5
5
  end
@@ -30,7 +30,7 @@ Gem::Specification.new do |spec|
30
30
  spec.add_dependency "ruby-jing"
31
31
  spec.add_dependency "isodoc", "~> 1.2.0"
32
32
  spec.add_dependency "iev", "~> 0.2.1"
33
- spec.add_dependency "relaton", "~> 1.2.0"
33
+ spec.add_dependency "relaton", "~> 1.3.0"
34
34
  spec.add_dependency "relaton-iev", "~> 1.0.0"
35
35
  spec.add_dependency "sterile", "~> 1.0.14"
36
36
  spec.add_dependency "concurrent-ruby"
@@ -327,6 +327,7 @@ RSpec.describe Asciidoctor::Standoc do
327
327
  :doc-uri: E
328
328
  :relaton-uri: F
329
329
  :title-eo: Dokumenttitolo
330
+ :doctype: This is a DocType
330
331
 
331
332
  [abstract]
332
333
  == Abstract
@@ -422,7 +423,7 @@ RSpec.describe Asciidoctor::Standoc do
422
423
  </owner>
423
424
  </copyright>
424
425
  <ext>
425
- <doctype>article</doctype>
426
+ <doctype>this-is-a-doctype</doctype>
426
427
  </ext>
427
428
  </bibdata>
428
429
  <preface>
@@ -1255,7 +1255,14 @@ RSpec.describe Asciidoctor::Standoc do
1255
1255
  <description><p id="_">I recommend <em>this</em>.</p>
1256
1256
  </description><specification exclude="false" type="tabular" keep-with-next="true" keep-lines-together="true"><p id="_">This is the object of the recommendation:</p><table id="_"> <tbody> <tr> <td align="left">Object</td> <td align="left">Value</td> </tr> <tr> <td align="left">Mission</td> <td align="left">Accomplished</td> </tr> </tbody></table></specification><description>
1257
1257
  <p id="_">As for the measurement targets,</p>
1258
- </description><measurement-target exclude="false"><p id="_">The measurement target shall be measured as:</p><formula id="_"> <stem type="MathML"><math xmlns="http://www.w3.org/1998/Math/MathML"><mfrac><mi>r</mi><mn>1</mn></mfrac><mo>=</mo><mn>0</mn></math></stem></formula></measurement-target>
1258
+ </description><measurement-target exclude="false"><p id="_">The measurement target shall be measured as:</p><formula id="_"> <stem type="MathML"><math xmlns="http://www.w3.org/1998/Math/MathML"><mfrac>
1259
+ <mrow>
1260
+ <mi>r</mi>
1261
+ </mrow>
1262
+ <mrow>
1263
+ <mn>1</mn>
1264
+ </mrow>
1265
+ </mfrac><mo>=</mo><mn>0</mn></math></stem></formula></measurement-target>
1259
1266
  <verification exclude="false"><p id="_">The following code will be run for verification:</p><sourcecode lang="CoreRoot" id="_">CoreRoot(success): HttpResponse
1260
1267
  if (success)
1261
1268
  recommendation(label: success-response)
@@ -158,7 +158,21 @@ RSpec.describe Asciidoctor::Standoc do
158
158
  <terms id="_" obligation="normative">
159
159
  <title>Terms and definitions</title>
160
160
  <p id="_">For the purposes of this document, the following terms and definitions apply.</p>
161
- <term id="_"><preferred><stem type="MathML"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mi>t</mi><mn>90</mn></msub></math></stem></preferred><admitted><stem type="MathML"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mi>t</mi><mn>91</mn></msub></math></stem></admitted>
161
+ <term id="_"><preferred><stem type="MathML"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub>
162
+ <mrow>
163
+ <mi>t</mi>
164
+ </mrow>
165
+ <mrow>
166
+ <mn>90</mn>
167
+ </mrow>
168
+ </msub></math></stem></preferred><admitted><stem type="MathML"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub>
169
+ <mrow>
170
+ <mi>t</mi>
171
+ </mrow>
172
+ <mrow>
173
+ <mn>91</mn>
174
+ </mrow>
175
+ </msub></math></stem></admitted>
162
176
  <definition><p id="_">Time</p></definition></term>
163
177
  </terms>
164
178
  </sections>
@@ -229,8 +243,22 @@ RSpec.describe Asciidoctor::Standoc do
229
243
  <terms id="_" obligation="normative">
230
244
  <title>Terms and definitions</title>
231
245
  <p id="_">For the purposes of this document, the following terms and definitions apply.</p>
232
- <term id="_"><preferred><stem type="MathML"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mi>t</mi><mn>90</mn></msub></math></stem></preferred><definition><formula id="_">
233
- <stem type="MathML"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mi>t</mi><mi>A</mi></msub></math></stem>
246
+ <term id="_"><preferred><stem type="MathML"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub>
247
+ <mrow>
248
+ <mi>t</mi>
249
+ </mrow>
250
+ <mrow>
251
+ <mn>90</mn>
252
+ </mrow>
253
+ </msub></math></stem></preferred><definition><formula id="_">
254
+ <stem type="MathML"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub>
255
+ <mrow>
256
+ <mi>t</mi>
257
+ </mrow>
258
+ <mrow>
259
+ <mi>A</mi>
260
+ </mrow>
261
+ </msub></math></stem>
234
262
  </formula>
235
263
  <p id="_">This paragraph is extraneous</p></definition>
236
264
  </term>
@@ -1359,7 +1387,14 @@ end
1359
1387
  #{BLANK_HDR}
1360
1388
  <sections>
1361
1389
  <p id="_">
1362
- <stem type="MathML"><math xmlns="http://www.w3.org/1998/Math/MathML"><mfrac><mn>1</mn><mi>r</mi></mfrac></math></stem>
1390
+ <stem type="MathML"><math xmlns="http://www.w3.org/1998/Math/MathML"><mfrac>
1391
+ <mrow>
1392
+ <mn>1</mn>
1393
+ </mrow>
1394
+ <mrow>
1395
+ <mi>r</mi>
1396
+ </mrow>
1397
+ </mfrac></math></stem>
1363
1398
  </p>
1364
1399
  </sections>
1365
1400
  </standard-document>
@@ -1669,12 +1704,28 @@ it "sorts symbols lists" do
1669
1704
  x_1_:: Definition 3
1670
1705
  x_m_:: Definition 4
1671
1706
  x:: Definition 5
1707
+ stem:[n]:: Definition 6
1708
+ m:: Definition 7
1672
1709
  INPUT
1673
1710
  #{BLANK_HDR}
1674
1711
  <sections>
1675
1712
  <definitions id='L' obligation="normative">
1676
1713
  <title>Symbols and abbreviated terms</title>
1677
1714
  <dl id='_'>
1715
+ <dt>m</dt>
1716
+ <dd>
1717
+ <p id='_'>Definition 7</p>
1718
+ </dd>
1719
+ <dt>
1720
+ <stem type='MathML'>
1721
+ <math xmlns='http://www.w3.org/1998/Math/MathML'>
1722
+ <mi>n</mi>
1723
+ </math>
1724
+ </stem>
1725
+ </dt>
1726
+ <dd>
1727
+ <p id='_'>Definition 6</p>
1728
+ </dd>
1678
1729
  <dt>x</dt>
1679
1730
  <dd>
1680
1731
  <p id='_'>Definition 5</p>
@@ -1727,8 +1778,12 @@ it "sorts symbols lists" do
1727
1778
  <dt><stem type='MathML'>
1728
1779
  <math xmlns='http://www.w3.org/1998/Math/MathML'>
1729
1780
  <msub>
1730
- <mi>x</mi>
1731
- <mi>m</mi>
1781
+ <mrow>
1782
+ <mi>x</mi>
1783
+ </mrow>
1784
+ <mrow>
1785
+ <mi>m</mi>
1786
+ </mrow>
1732
1787
  </msub>
1733
1788
  </math>
1734
1789
  </stem></dt>
@@ -1738,8 +1793,12 @@ it "sorts symbols lists" do
1738
1793
  <dt><stem type='MathML'>
1739
1794
  <math xmlns='http://www.w3.org/1998/Math/MathML'>
1740
1795
  <msub>
1741
- <mi>x</mi>
1742
- <mn>1</mn>
1796
+ <mrow>
1797
+ <mi>x</mi>
1798
+ </mrow>
1799
+ <mrow>
1800
+ <mn>1</mn>
1801
+ </mrow>
1743
1802
  </msub>
1744
1803
  </math>
1745
1804
  </stem></dt>
@@ -1872,6 +1931,9 @@ it "moves %beforeclause admonitions to right position" do
1872
1931
  INPUT
1873
1932
  #{BLANK_HDR}
1874
1933
  <preface>
1934
+ <note id='_'>
1935
+ <p id='_'>Note which is very important</p>
1936
+ </note>
1875
1937
  <foreword id='_' obligation='informative'>
1876
1938
  <title>Foreword</title>
1877
1939
  <p id='_'>Foreword</p>
@@ -1882,9 +1944,6 @@ INPUT
1882
1944
  </introduction>
1883
1945
  </preface>
1884
1946
  <sections>
1885
- <note id='_'>
1886
- <p id='_'>Note which is very important</p>
1887
- </note>
1888
1947
  <admonition id='_' type='important'>
1889
1948
  <p id='_'>Notice which is very important</p>
1890
1949
  </admonition>
@@ -3102,6 +3161,57 @@ INPUT
3102
3161
  OUTPUT
3103
3162
  end
3104
3163
 
3164
+ it "fixes illegal anchors" do
3165
+ input = <<~INPUT
3166
+ #{ASCIIDOC_BLANK_HDR}
3167
+
3168
+ [[a:b]]
3169
+ == A
3170
+ <</:ab>>
3171
+ <<:>>
3172
+ <<1>>
3173
+ <<1:>>
3174
+ <<1#b>>
3175
+ <<:a#b:>>
3176
+
3177
+ INPUT
3178
+ expect(xmlpp(Asciidoctor.convert(input, backend: :standoc, header_footer: true).gsub(/<p id="_[^"]+">/, "").gsub('</p>', ""))).to be_equivalent_to (<<~"OUTPUT")
3179
+ <standard-document xmlns='https://www.metanorma.org/ns/standoc'>
3180
+ <bibdata type='standard'>
3181
+ <title language='en' format='text/plain'>Document title</title>
3182
+ <language>en</language>
3183
+ <script>Latn</script>
3184
+ <status>
3185
+ <stage>published</stage>
3186
+ </status>
3187
+ <copyright>
3188
+ <from>2020</from>
3189
+ </copyright>
3190
+ <ext>
3191
+ <doctype>article</doctype>
3192
+ </ext>
3193
+ </bibdata>
3194
+ <sections>
3195
+ <clause id='a_b' inline-header='false' obligation='normative'>
3196
+ <title>A</title>
3197
+ <xref target='__ab'/>
3198
+ <xref target='_'/>
3199
+ <xref target='_1'/>
3200
+ <xref target='_1_'/>
3201
+ <xref target='1#b'/>
3202
+ <xref target='_a#b_'/>
3203
+ </clause>
3204
+ </sections>
3205
+ </standard-document>
3206
+ OUTPUT
3207
+ expect{Asciidoctor.convert(input, backend: :standoc, header_footer: true)}.to output(%r{normalised identifier in <clause id="a_b" inline-header="false" obligation="normative"/> from a:b}).to_stderr
3208
+ expect{Asciidoctor.convert(input, backend: :standoc, header_footer: true)}.to output(%r{normalised identifier in <xref target="__ab"/> from /:ab}).to_stderr
3209
+ expect{Asciidoctor.convert(input, backend: :standoc, header_footer: true)}.to output(%r{normalised identifier in <xref target="_"/> from :}).to_stderr
3210
+ expect{Asciidoctor.convert(input, backend: :standoc, header_footer: true)}.to output(%r{normalised identifier in <xref target="_1"/> from 1}).to_stderr
3211
+ expect{Asciidoctor.convert(input, backend: :standoc, header_footer: true)}.to output(%r{normalised identifier in <xref target="_1_"/> from 1:}).to_stderr
3212
+ expect{Asciidoctor.convert(input, backend: :standoc, header_footer: true)}.to output(%r{normalised identifier in <xref target="_a#b_"/> from :a#b:}).to_stderr
3213
+ end
3214
+
3105
3215
 
3106
3216
  private
3107
3217