metanorma-standoc 2.4.8 → 2.5.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ce54912310b9af4d98ddc7626191a27b3dd982afbcbba47af1f2b1503d1eaac1
4
- data.tar.gz: db2b1f1bafa6875952c611db4bc4f31568d63102545fb15b9236afd69e77f84b
3
+ metadata.gz: 1d6a56b88b9f58482764ff6aede297e389577151d0d112a215b2215d5cfb41cf
4
+ data.tar.gz: cb0a1a1d73930e89169a27185bcce3d19130f1150a22fd7345da61a73dbd759f
5
5
  SHA512:
6
- metadata.gz: 43d771eebc8879517b65e977a74add3008cc6bfc636f8408a48c0761352a31e113cb2a5720406ce0748faccdbad4e6ff1f290b2a4c446fd576f2a0f91c6bb054
7
- data.tar.gz: 73da28422191e64bd324959c1fa63fc29b82074284fc1dc9a25ea70a5982bdb471d1961a3259d26455c9ea470b9f77ee3cc7c64a03f6e645acd9e8e69aa93787
6
+ metadata.gz: 158547c563e269b769f39123cbd03f749a4891f7e4c772e9462ea40a9221ee4b58839991b2580fc40d9a24007387866d2741867ee6a8f5f39770fa3d38a57138
7
+ data.tar.gz: ba7b26ed9ebfae0f92dedc50750aad4e31c53b5e5b16defe3e2a2ea6583049fab738f07449846ac62aa74af06944d725389fed9d54357bf9ff9c33b3196cac2f
@@ -98,7 +98,7 @@ h1, h2, h3, h4, h5, h6 {
98
98
 
99
99
  blockquote, q {
100
100
  quotes: none; }
101
- blockquote:before, blockquote:after, q:before, q:after {
101
+ blockquote::before, blockquote::after, q::before, q::after {
102
102
  content: '';
103
103
  content: none; }
104
104
 
@@ -121,14 +121,18 @@ b, strong {
121
121
  div.document-stage-band, div.document-type-band {
122
122
  background-color: #333333; }
123
123
 
124
- a.FootnoteRef + a.FootnoteRef:before {
124
+ a.FootnoteRef + a.FootnoteRef::before {
125
125
  content: ", ";
126
126
  vertical-align: super; }
127
127
 
128
- a.TableFootnoteRef + a.TableFootnoteRef:before {
128
+ a.TableFootnoteRef + a.TableFootnoteRef::before {
129
129
  content: ", ";
130
130
  vertical-align: super; }
131
131
 
132
+ a.TableFootnoteRef, span.TableFootnoteRef,
133
+ a.FootnoteRef, span.FootnoteRef {
134
+ vertical-align: super; }
135
+
132
136
  .addition {
133
137
  color: blue; }
134
138
 
@@ -594,7 +598,7 @@ ul, ol {
594
598
  ul li {
595
599
  list-style: none; }
596
600
 
597
- ul li:before {
601
+ ul li::before {
598
602
  content: "—";
599
603
  display: inline-block;
600
604
  width: 1em;
@@ -612,7 +616,7 @@ ul li:first-child {
612
616
  #toc-list li {
613
617
  list-style-type: none; }
614
618
 
615
- #toc li:before {
619
+ #toc li::before {
616
620
  content: " ";
617
621
  display: none; }
618
622
 
@@ -633,13 +637,13 @@ ol[class="alphabet"] > li {
633
637
  ol[class="alphabet"] ol[class="alphabet"] > li {
634
638
  list-style: inherit; }
635
639
 
636
- ol[class="alphabet"] > li:before {
640
+ ol[class="alphabet"] > li::before {
637
641
  counter-increment: alphabet;
638
642
  content: counter(alphabet, lower-alpha) ") ";
639
643
  position: absolute;
640
644
  left: -1.4em; }
641
645
 
642
- ol[class="alphabet"] ol[class="alphabet"] > li:before {
646
+ ol[class="alphabet"] ol[class="alphabet"] > li::before {
643
647
  counter-increment: none;
644
648
  content: initial; }
645
649
 
@@ -653,13 +657,13 @@ ol[class="roman"] > li {
653
657
  ol[class="roman"] ol[class="roman"] > li {
654
658
  list-style: inherit; }
655
659
 
656
- ol[class="roman"] > li:before {
660
+ ol[class="roman"] > li::before {
657
661
  counter-increment: roman;
658
662
  content: "(" counter(roman, lower-roman) ") ";
659
663
  position: absolute;
660
664
  left: -2.0em; }
661
665
 
662
- ol[class="roman"] ol[class="roman"] > li:before {
666
+ ol[class="roman"] ol[class="roman"] > li::before {
663
667
  counter-increment: none;
664
668
  content: initial; }
665
669
 
@@ -230,7 +230,7 @@ ul li {
230
230
  list-style: none;
231
231
  }
232
232
 
233
- ul li:before {
233
+ ul li::before {
234
234
  content: "—";
235
235
  display: inline-block; width: 1em;
236
236
  margin-left: -1.2em;
@@ -252,7 +252,7 @@ ul li:first-child {
252
252
  list-style-type: none;
253
253
  }
254
254
 
255
- #toc li:before {
255
+ #toc li::before {
256
256
  content: " ";
257
257
  display: none;
258
258
  }
@@ -275,13 +275,13 @@ ol[class="alphabet"] > li {
275
275
  ol[class="alphabet"] ol[class="alphabet"] > li {
276
276
  list-style: inherit;
277
277
  }
278
- ol[class="alphabet"] > li:before {
278
+ ol[class="alphabet"] > li::before {
279
279
  counter-increment: alphabet;
280
280
  content: counter(alphabet, lower-alpha)") ";
281
281
  position: absolute;
282
282
  left: -1.4em;
283
283
  }
284
- ol[class="alphabet"] ol[class="alphabet"] > li:before {
284
+ ol[class="alphabet"] ol[class="alphabet"] > li::before {
285
285
  counter-increment: none;
286
286
  content: initial;
287
287
  }
@@ -295,13 +295,13 @@ ol[class="roman"] > li {
295
295
  ol[class="roman"] ol[class="roman"] > li {
296
296
  list-style: inherit;
297
297
  }
298
- ol[class="roman"] > li:before {
298
+ ol[class="roman"] > li::before {
299
299
  counter-increment: roman;
300
300
  content: "("counter(roman, lower-roman)") ";
301
301
  position: absolute;
302
302
  left: -2.0em;
303
303
  }
304
- ol[class="roman"] ol[class="roman"] > li:before {
304
+ ol[class="roman"] ol[class="roman"] > li::before {
305
305
  counter-increment: none;
306
306
  content: initial;
307
307
  }
@@ -76,7 +76,7 @@ module Metanorma
76
76
  def stem(node)
77
77
  noko do |xml|
78
78
  xml.formula **formula_attrs(node) do |s|
79
- stem_parse(node.lines.join("\n"), s, node.style.to_sym)
79
+ stem_parse(node.lines.join("\n"), s, node.style.to_sym, node.block?)
80
80
  end
81
81
  end
82
82
  end
@@ -1,24 +1,24 @@
1
1
  require "nokogiri"
2
2
  require "pathname"
3
3
  require "html2doc"
4
- require_relative "./cleanup_block"
5
- require_relative "./cleanup_table"
6
- require_relative "./cleanup_footnotes"
7
- require_relative "./cleanup_ref"
8
- require_relative "./cleanup_asciibib"
9
- require_relative "./cleanup_boilerplate"
10
- require_relative "./cleanup_bibdata"
11
- require_relative "./cleanup_section"
12
- require_relative "./cleanup_terms"
13
- require_relative "./cleanup_symbols"
14
- require_relative "./cleanup_xref"
15
- require_relative "./cleanup_inline"
16
- require_relative "./cleanup_amend"
17
- require_relative "./cleanup_maths"
18
- require_relative "./cleanup_image"
19
- require_relative "./cleanup_reqt"
20
- require_relative "./cleanup_text"
21
- require_relative "./cleanup_toc"
4
+ require_relative "cleanup_block"
5
+ require_relative "cleanup_table"
6
+ require_relative "cleanup_footnotes"
7
+ require_relative "cleanup_ref"
8
+ require_relative "cleanup_asciibib"
9
+ require_relative "cleanup_boilerplate"
10
+ require_relative "cleanup_bibdata"
11
+ require_relative "cleanup_section"
12
+ require_relative "cleanup_terms"
13
+ require_relative "cleanup_symbols"
14
+ require_relative "cleanup_xref"
15
+ require_relative "cleanup_inline"
16
+ require_relative "cleanup_amend"
17
+ require_relative "cleanup_maths"
18
+ require_relative "cleanup_image"
19
+ require_relative "cleanup_reqt"
20
+ require_relative "cleanup_text"
21
+ require_relative "cleanup_toc"
22
22
  require "relaton_iev"
23
23
 
24
24
  module Metanorma
@@ -51,6 +51,7 @@ module Metanorma
51
51
  normref_cleanup(xmldoc)
52
52
  biblio_cleanup(xmldoc)
53
53
  reference_names(xmldoc)
54
+ asciimath_cleanup(xmldoc) # feeds: mathml_cleanup, termdef_cleanup, symbols_cleanup
54
55
  symbols_cleanup(xmldoc) # feeds: termdef_cleanup
55
56
  xref_cleanup(xmldoc) # feeds: concept_cleanup, origin_cleanup
56
57
  concept_cleanup(xmldoc) # feeds: related_cleanup, termdef_cleanup
@@ -79,6 +80,7 @@ module Metanorma
79
80
  empty_element_cleanup(xmldoc)
80
81
  img_cleanup(xmldoc)
81
82
  anchor_cleanup(xmldoc)
83
+ link_cleanup(xmldoc)
82
84
  xmldoc
83
85
  end
84
86
 
@@ -107,7 +109,7 @@ module Metanorma
107
109
  end
108
110
 
109
111
  def element_name_cleanup(xmldoc)
110
- xmldoc.traverse { |n| n.name = n.name.gsub(/_/, "-") }
112
+ xmldoc.traverse { |n| n.name = n.name.gsub("_", "-") }
111
113
  end
112
114
 
113
115
  # allows us to deal with doc relation localities,
@@ -233,6 +233,7 @@ module Metanorma
233
233
  def unnumbered_blocks_cleanup(xmldoc)
234
234
  @blockunnumbered&.each do |b|
235
235
  xmldoc.xpath("//#{b}").each do |e|
236
+ /^[^_]/.match?(e["id"]) and e["unnumbered"] = "false"
236
237
  e["unnumbered"] ||= "true"
237
238
  end
238
239
  end
@@ -78,7 +78,7 @@ module Metanorma
78
78
  def concept_cleanup1(elem)
79
79
  elem.children.remove if elem&.children&.text&.strip&.empty?
80
80
  key_extract_locality(elem)
81
- if /:/.match?(elem["key"]) then concept_termbase_cleanup(elem)
81
+ if elem["key"].include?(":") then concept_termbase_cleanup(elem)
82
82
  elsif refid? elem["key"] then concept_eref_cleanup(elem)
83
83
  else concept_xref_cleanup(elem)
84
84
  end
@@ -95,15 +95,14 @@ module Metanorma
95
95
  end
96
96
 
97
97
  def key_extract_locality(elem)
98
- return unless /,/.match?(elem["key"])
99
-
98
+ elem["key"].include?(",") or return
100
99
  elem.add_child("<locality>#{elem['key'].sub(/^[^,]+,/, '')}</locality>")
101
100
  elem["key"] = elem["key"].sub(/,.*$/, "")
102
101
  end
103
102
 
104
103
  def concept_termbase_cleanup(elem)
105
104
  t = elem&.at("./xrefrender")&.remove&.children
106
- termbase, key = elem["key"].split(/:/, 2)
105
+ termbase, key = elem["key"].split(":", 2)
107
106
  elem.add_child(%(<termref base="#{termbase}" target="#{key}">) +
108
107
  "#{t&.to_xml}</termref>")
109
108
  end
@@ -207,6 +206,21 @@ module Metanorma
207
206
  end
208
207
  end
209
208
 
209
+ def link_cleanup(xmldoc)
210
+ xmldoc.xpath("//link[@target]").each do |l|
211
+ l["target"] = URI.parse(l["target"]).to_s
212
+ rescue StandardError
213
+ err = "Malformed URI: #{l['target']}"
214
+ @log.add("Anchors", l, err)
215
+ @fatalerror << err
216
+ warn err
217
+ end
218
+ end
219
+
220
+ def uri_component_encode(comp)
221
+ CGI.escape(comp).gsub("+", "%20")
222
+ end
223
+
210
224
  private
211
225
 
212
226
  # skip ZWNJ inserted to prevent regexes operating in asciidoctor
@@ -3,17 +3,28 @@ require "asciimath2unitsml"
3
3
  module Metanorma
4
4
  module Standoc
5
5
  module Cleanup
6
- def asciimath2mathml(text)
7
- text = text.gsub(%r{<stem type="AsciiMath">(.+?)</stem>}m) do
8
- "<amathstem>#{@c.decode($1)}</amathstem>"
6
+ def asciimath_cleanup(xml)
7
+ !@keepasciimath and asciimath2mathml(xml)
8
+ end
9
+
10
+ def asciimath2mathml(xml)
11
+ xpath = xml.xpath("//stem[@type = 'AsciiMath']")
12
+ xpath.each_with_index do |x, i|
13
+ progress_conv(i, 500, xpath.size, 1000, "AsciiMath")
14
+ asciimath2mathml_indiv(x)
9
15
  end
10
- text = Html2Doc.new({})
11
- .asciimath_to_mathml(text, ["<amathstem>", "</amathstem>"],
12
- retain_asciimath: true)
13
- asciimath2mathml_wrap(text)
16
+ asciimath2mathml_wrap(xml)
17
+ end
18
+
19
+ def asciimath2mathml_indiv(elem)
20
+ elem["type"] = "MathML"
21
+ expr = @c.decode(elem.text)
22
+ ret = Plurimath::Math.parse(expr, "asciimath")
23
+ .to_mathml(display_style: elem["block"])
24
+ ret += "<asciimath>#{@c.encode(@c.decode(expr), :basic)}</asciimath>"
25
+ elem.children = ret
14
26
  rescue StandardError => e
15
- asciimath2mathml_err(text, e)
16
- text
27
+ asciimath2mathml_err(elem.to_xml, e)
17
28
  end
18
29
 
19
30
  def asciimath2mathml_err(text, expr)
@@ -23,25 +34,27 @@ module Metanorma
23
34
  warn err
24
35
  end
25
36
 
26
- def asciimath2mathml_wrap(text)
27
- x = Nokogiri::XML(text)
28
- x.xpath("//*[local-name() = 'math'][@display]").each do |y|
37
+ def asciimath2mathml_wrap(xml)
38
+ xml.xpath("//*[local-name() = 'math'][@display]").each do |y|
29
39
  y.delete("display")
30
40
  end
31
- x.xpath("//*[local-name() = 'math'][not(parent::stem)]").each do |y|
32
- y.wrap("<stem type='MathML'></stem>")
33
- end
34
- x.xpath("//stem").each do |y|
35
- y.next_element&.name == "asciimath" and y << y.next_element
36
- end
37
- to_xml(x)
41
+ # x.xpath("//stem").each do |y|
42
+ # y.next_element&.name == "asciimath" and y << y.next_element
43
+ # end
44
+ xml
45
+ end
46
+
47
+ def progress_conv(idx, step, total, threshold, msg)
48
+ return unless (idx % step).zero? && total > threshold && idx.positive?
49
+
50
+ warn "#{msg} #{idx} of #{total}"
38
51
  end
39
52
 
40
53
  def xml_unescape_mathml(xml)
41
54
  return if xml.children.any?(&:element?)
42
55
 
43
- math = xml.text.gsub(/&lt;/, "<").gsub(/&gt;/, ">")
44
- .gsub(/&quot;/, '"').gsub(/&apos;/, "'").gsub(/&amp;/, "&")
56
+ math = xml.text.gsub("&lt;", "<").gsub("&gt;", ">")
57
+ .gsub("&quot;", '"').gsub("&apos;", "'").gsub("&amp;", "&")
45
58
  .gsub(/<[^: \r\n\t\/]+:/, "<").gsub(/<\/[^ \r\n\t:]+:/, "</")
46
59
  xml.children = math
47
60
  end
@@ -1,3 +1,5 @@
1
+ require "metanorma/standoc/utils"
2
+
1
3
  module Metanorma
2
4
  module Standoc
3
5
  module Cleanup
@@ -8,31 +10,12 @@ module Metanorma
8
10
  def symbol_key(sym)
9
11
  @c.decode(asciimath_key(sym).text)
10
12
  .gsub(/[\[\]{}<>()]/, "").gsub(/\s/m, "")
11
- .gsub(/[[:punct:]]|[_^]/, ":\\0").gsub(/`/, "")
13
+ .gsub(/[[:punct:]]|[_^]/, ":\\0").gsub("`", "")
12
14
  .gsub(/[0-9]+/, "þ\\0")
13
15
  .tr("AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz",
14
16
  "ABCFEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
15
17
  end
16
18
 
17
- def asciimath_key(sym)
18
- key = sym.dup
19
- key.traverse do |n|
20
- if n.name == "stem" && a = n.at(".//asciimath")
21
- n.children = @c.encode(
22
- @c.decode(grkletters(a.text)), :basic
23
- )
24
- end
25
- end
26
- key.xpath(".//asciimath").each(&:remove)
27
- Nokogiri::XML(key.to_xml)
28
- end
29
-
30
- def grkletters(text)
31
- text.gsub(/\b(alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|
32
- lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|
33
- psi|omega)\b/xi, "&\\1;")
34
- end
35
-
36
19
  def extract_symbols_list(dlist)
37
20
  dl_out = []
38
21
  dlist.xpath("./dt | ./dd").each do |dtd|
@@ -111,6 +111,7 @@ module Metanorma
111
111
  term_dl_to_metadata(xmldoc)
112
112
  term_termsource_to_designation(xmldoc)
113
113
  term_designation_reorder(xmldoc)
114
+ term_designation_redundant(xmldoc)
114
115
  termdef_from_termbase(xmldoc)
115
116
  termdomain_cleanup(xmldoc)
116
117
  termdef_stem_cleanup(xmldoc)
@@ -101,7 +101,7 @@ module Metanorma
101
101
 
102
102
  def term_dl_to_designation_category(prev, category)
103
103
  cat = prev.at(".//expression/grammar/#{category}")
104
- /,/.match?(cat&.text) and
104
+ cat&.text&.include?(",") and
105
105
  cat.replace(cat.text.split(/,\s*/)
106
106
  .map { |x| "<#{category}>#{x}</#{category}>" }.join)
107
107
  end
@@ -148,13 +148,15 @@ module Metanorma
148
148
  end
149
149
  end
150
150
 
151
+ DESIGNATOR = %w(preferred admitted deprecates related).freeze
152
+
151
153
  def term_termsource_to_designation(xmldoc)
152
154
  xmldoc.xpath("//term/termsource").each do |t|
153
155
  p = t.previous_element
154
156
  while %w(domain subject).include? p&.name
155
157
  p = p.previous_element
156
158
  end
157
- %w(preferred admitted deprecates related).include?(p&.name) or
159
+ DESIGNATOR.include?(p&.name) or
158
160
  next
159
161
  related2pref(p) << t.remove
160
162
  end
@@ -162,8 +164,7 @@ module Metanorma
162
164
 
163
165
  def term_designation_reorder(xmldoc)
164
166
  xmldoc.xpath("//term").each do |t|
165
- des = %w(preferred admitted deprecates related)
166
- .each_with_object([]) do |tag, m|
167
+ des = DESIGNATOR.each_with_object([]) do |tag, m|
167
168
  t.xpath("./#{tag}").each { |x| m << x.remove }
168
169
  end.reverse
169
170
  t << " "
@@ -174,7 +175,21 @@ module Metanorma
174
175
  end
175
176
 
176
177
  def related2pref(elem)
177
- elem&.name == "related" ? elem = elem.at("./preferred") : elem
178
+ elem&.name == "related" ? elem.at("./preferred") : elem
179
+ end
180
+
181
+ def term_designation_redundant(xmldoc)
182
+ xmldoc.xpath("//term").each do |t|
183
+ DESIGNATOR.each do |n|
184
+ t.xpath("./#{n}/expression/name").each_with_object([]) do |d, m|
185
+ if m.include?(d.text)
186
+ @log.add("Terms", t, "Removed duplicate designation #{d.text}")
187
+ d.parent.parent.remove
188
+ end
189
+ m << d.text
190
+ end
191
+ end
192
+ end
178
193
  end
179
194
  end
180
195
  end
@@ -3,7 +3,6 @@ module Metanorma
3
3
  module Cleanup
4
4
  def textcleanup(result)
5
5
  text = result.flatten.map { |l| l.sub(/\s*\Z/, "") } * "\n"
6
- !@keepasciimath and text = asciimath2mathml(text)
7
6
  text = text.gsub(/\s+<fn /, "<fn ")
8
7
  %w(passthrough passthrough-inline).each do |v|
9
8
  text.gsub!(%r{<#{v}\s+formats="metanorma">([^<]*)
@@ -20,6 +20,8 @@ module Metanorma
20
20
  # schema encapsulation of the document for validation
21
21
  class Converter
22
22
  Asciidoctor::Extensions.register do
23
+ preprocessor Metanorma::Standoc::EmbedIncludeProcessor
24
+ preprocessor Metanorma::Standoc::NamedEscapePreprocessor
23
25
  preprocessor Metanorma::Standoc::Datamodel::AttributesTablePreprocessor
24
26
  preprocessor Metanorma::Standoc::Datamodel::DiagramPreprocessor
25
27
  preprocessor Metanorma::Plugin::Datastruct::Json2TextPreprocessor
@@ -60,8 +62,6 @@ module Metanorma
60
62
  treeprocessor Metanorma::Standoc::ToDoInlineAdmonitionBlock
61
63
  block Metanorma::Standoc::PlantUMLBlockMacro
62
64
  block Metanorma::Standoc::PseudocodeBlockMacro
63
- preprocessor Metanorma::Standoc::EmbedIncludeProcessor
64
- preprocessor Metanorma::Standoc::NamedEscapePreprocessor
65
65
  end
66
66
 
67
67
  include ::Asciidoctor::Converter
@@ -138,9 +138,10 @@ module Metanorma
138
138
  noko { |xml| xml.hr }.join
139
139
  end
140
140
 
141
- def latex_parse1(text)
141
+ def latex_parse1(text, block)
142
142
  lxm_input = Unicode2LaTeX.unicode2latex(@c.decode(text))
143
- results = Plurimath::Math.parse(lxm_input, "latex").to_mathml
143
+ results = Plurimath::Math.parse(lxm_input, "latex")
144
+ .to_mathml(display_style: block)
144
145
  if results.nil?
145
146
  @log.add("Math", nil,
146
147
  "latexmlmath failed to process equation:\n#{lxm_input}")
@@ -149,22 +150,23 @@ module Metanorma
149
150
  results.sub(%r{<math ([^>]+ )?display="block"}, "<math \\1")
150
151
  end
151
152
 
152
- def stem_parse(text, xml, style)
153
+ def stem_parse(text, xml, style, block)
153
154
  if /&lt;([^:>&]+:)?math(\s+[^>&]+)?&gt; |
154
155
  <([^:>&]+:)?math(\s+[^>&]+)?>/x.match? text
155
156
  math = xml_encode(text)
156
- xml.stem type: "MathML" do |s|
157
+ xml.stem type: "MathML", block: block do |s|
157
158
  s << math
158
159
  end
159
- elsif style == :latexmath then latex_parse(text, xml)
160
+ elsif style == :latexmath then latex_parse(text, xml, block)
160
161
  else
161
- xml.stem text&.gsub(/&amp;#/, "&#"), type: "AsciiMath"
162
+ xml.stem text&.gsub("&amp;#", "&#"), type: "AsciiMath", block: block
162
163
  end
163
164
  end
164
165
 
165
- def latex_parse(text, xml)
166
- latex = latex_parse1(text) or return xml.stem type: "MathML"
167
- xml.stem type: "MathML" do |s|
166
+ def latex_parse(text, xml, block)
167
+ latex = latex_parse1(text, block) or
168
+ return xml.stem type: "MathML", block: block
169
+ xml.stem type: "MathML", block: block do |s|
168
170
  math = Nokogiri::XML.fragment(latex.sub(/<\?[^>]+>/, ""))
169
171
  .elements[0]
170
172
  math.delete("alttext")
@@ -187,8 +189,8 @@ module Metanorma
187
189
  when :single then xml << "'#{node.text}'"
188
190
  when :superscript then xml.sup { |s| s << node.text }
189
191
  when :subscript then xml.sub { |s| s << node.text }
190
- when :asciimath then stem_parse(node.text, xml, :asciimath)
191
- when :latexmath then stem_parse(node.text, xml, :latexmath)
192
+ when :asciimath then stem_parse(node.text, xml, :asciimath, false)
193
+ when :latexmath then stem_parse(node.text, xml, :latexmath, false)
192
194
  when :mark then highlight_parse(node.text, xml)
193
195
  else
194
196
  case node.role
@@ -215,7 +217,14 @@ module Metanorma
215
217
  end
216
218
 
217
219
  def image_attributes(node)
218
- uri = node.image_uri (node.attr("target") || node.target)
220
+ nodetarget = node.attr("target") || node.target
221
+ if Gem.win_platform? && /^[a-zA-Z]:/.match?(nodetarget)
222
+ nodetarget.prepend("/")
223
+ end
224
+ uri = node.image_uri (nodetarget)
225
+ if Gem.win_platform? && /^\/[a-zA-Z]:/.match?(uri)
226
+ uri = uri[1..-1]
227
+ end
219
228
  types = if /^data:/.match?(uri) then Metanorma::Utils::datauri2mime(uri)
220
229
  else MIME::Types.type_for(uri)
221
230
  end
@@ -17,7 +17,7 @@
17
17
  these elements; we just want one namespace for any child grammars
18
18
  of this.
19
19
  -->
20
- <!-- VERSION v1.2.2 -->
20
+ <!-- VERSION v1.2.3 -->
21
21
  <grammar xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0" xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
22
22
  <include href="reqt.rng"/>
23
23
  <include href="basicdoc.rng">
@@ -192,9 +192,11 @@
192
192
  </attribute>
193
193
  </optional>
194
194
  <attribute name="citeas"/>
195
- <attribute name="type">
196
- <ref name="ReferenceFormat"/>
197
- </attribute>
195
+ <optional>
196
+ <attribute name="type">
197
+ <ref name="ReferenceFormat"/>
198
+ </attribute>
199
+ </optional>
198
200
  <optional>
199
201
  <attribute name="alt"/>
200
202
  </optional>
@@ -836,6 +838,26 @@
836
838
  <ref name="paragraph"/>
837
839
  </element>
838
840
  </define>
841
+ <define name="stem">
842
+ <element name="stem">
843
+ <attribute name="type">
844
+ <choice>
845
+ <value>MathML</value>
846
+ <value>AsciiMath</value>
847
+ <value>LatexMath</value>
848
+ </choice>
849
+ </attribute>
850
+ <attribute name="block">
851
+ <data type="boolean"/>
852
+ </attribute>
853
+ <oneOrMore>
854
+ <choice>
855
+ <text/>
856
+ <ref name="AnyElement"/>
857
+ </choice>
858
+ </oneOrMore>
859
+ </element>
860
+ </define>
839
861
  <define name="em">
840
862
  <element name="em">
841
863
  <zeroOrMore>
@@ -1,5 +1,3 @@
1
- require "asciidoctor/extensions"
2
- require "fileutils"
3
1
  require "uuidtools"
4
2
  require "yaml"
5
3
  require "csv"
@@ -85,13 +85,14 @@ module Metanorma
85
85
  end
86
86
  end
87
87
 
88
- def fetchable_ref_code?(ref)
89
- ref[:code].nil? || ref[:code].empty? || ref[:no_year] ||
88
+ def unfetchable_ref_code?(ref)
89
+ ref[:code].nil? || ref[:code].empty? || ref[:no_year] ||
90
+ /^\(.+\)$/.match?(ref[:code]) ||
90
91
  (@bibdb.nil? && !ref[:localfile])
91
92
  end
92
93
 
93
94
  def fetch_ref_async(ref, idx, res)
94
- if fetchable_ref_code?(ref)
95
+ if unfetchable_ref_code?(ref)
95
96
  res << [ref, idx, nil]
96
97
  elsif ref[:localfile]
97
98
  res << [ref, idx, @local_bibdb.get(ref[:code], ref[:localfile])]
@@ -1,11 +1,10 @@
1
- # frozen_string_literal: true.
2
1
  require "metanorma/standoc/utils"
3
2
 
4
3
  module Metanorma
5
4
  module Standoc
6
5
  # Intelligent term lookup xml modifier
7
6
  class TermLookupCleanup
8
- AUTOMATIC_GENERATED_ID_REGEXP = /\A_/.freeze
7
+ AUTO_GEN_ID_REGEXP = /\A_/.freeze
9
8
  EXISTING_TERM_REGEXP = /\Aterm-/.freeze
10
9
  EXISTING_SYMBOL_REGEXP = /\Asymbol-/.freeze
11
10
 
@@ -16,6 +15,8 @@ module Metanorma
16
15
  @log = log
17
16
  @termlookup = { term: {}, symbol: {}, secondary2primary: {} }
18
17
  @idhash = {}
18
+ @unique_designs = {}
19
+ @c = HTMLEntities.new
19
20
  @terms_tags = xmldoc.xpath("//terms").each_with_object({}) do |t, m|
20
21
  m[t["id"]] = true
21
22
  end
@@ -23,63 +24,102 @@ module Metanorma
23
24
 
24
25
  def call
25
26
  @idhash = populate_idhash
27
+ @unique_designs = unique_designators
26
28
  @termlookup = replace_automatic_generated_ids_terms
27
29
  set_termxref_tags_target
28
30
  concept_cleanup
29
31
  related_cleanup
32
+ remove_missing_refs
33
+ concept_cleanup2
30
34
  end
31
35
 
32
36
  private
33
37
 
38
+ def unique_designators
39
+ ret = xmldoc
40
+ .xpath("//preferred/expression/name | //admitted/expression/name | " \
41
+ "//deprecated/expression/name").each_with_object({}) do |n, m|
42
+ m[n.text] ||= 0
43
+ m[n.text] += 1
44
+ end
45
+ ret.each { |k, v| v == 1 or ret.delete(k) }
46
+ ret
47
+ end
48
+
34
49
  def concept_cleanup
35
50
  xmldoc.xpath("//concept").each do |n|
36
- n.delete("type")
37
51
  refterm = n.at("./refterm") or next
38
- p = @termlookup[:secondary2primary][refterm.text] and
39
- refterm.children = p
52
+ lookup = normalize_ref_id_text(refterm.text.strip)
53
+ p = @termlookup[:secondary2primary][lookup] and
54
+ refterm.children = @c.encode(p)
40
55
  end
41
56
  end
42
57
 
58
+ def concept_cleanup2
59
+ xmldoc.xpath("//concept").each { |n| n.delete("type") }
60
+ end
61
+
43
62
  def related_cleanup
44
63
  xmldoc.xpath("//related").each do |n|
45
64
  refterm = n.at("./refterm") or next
46
- p = @termlookup[:secondary2primary][refterm.text] and
47
- refterm.children = p
48
- refterm.replace("<preferred><expression>" \
49
- "<name>#{refterm.children.to_xml}" \
50
- "</name></expression></preferred>")
65
+ lookup = normalize_ref_id_text(refterm.text.strip)
66
+ p = @termlookup[:secondary2primary][lookup] and
67
+ refterm.children = @c.encode(p)
68
+ p || @termlookup[:term][lookup] and
69
+ refterm.replace("<preferred><expression>" \
70
+ "<name>#{refterm.children.to_xml}" \
71
+ "</name></expression></preferred>")
51
72
  end
52
73
  end
53
74
 
54
75
  def populate_idhash
55
76
  xmldoc.xpath("//*[@id]").each_with_object({}) do |n, mem|
56
- next unless /^(term|symbol)-/.match?(n["id"])
57
-
77
+ /^(term|symbol)-/.match?(n["id"]) or next
58
78
  mem[n["id"]] = true
59
79
  end
60
80
  end
61
81
 
62
82
  def set_termxref_tags_target
63
83
  xmldoc.xpath("//termxref").each do |node|
64
- target = normalize_ref_id(node)
65
- if termlookup[:term][target].nil? && termlookup[:symbol][target].nil?
66
- remove_missing_ref(node, target)
67
- next
68
- end
84
+ target = normalize_ref_id1(node)
69
85
  x = node.at("../xrefrender") and modify_ref_node(x, target)
70
86
  node.name = "refterm"
71
87
  end
72
88
  end
73
89
 
90
+ def remove_missing_refs
91
+ xmldoc.xpath("//refterm").each do |node|
92
+ remove_missing_ref?(node) or next
93
+ lookup_refterm(node)
94
+ end
95
+ end
96
+
97
+ def remove_missing_ref?(node)
98
+ node.at("../eref | ../termref") and return false
99
+ xref = node.at("../xref") or return true
100
+ xref["target"] && !xref["target"]&.empty? and return false
101
+ xref.remove # if xref supplied by user, we won't delete
102
+ true
103
+ end
104
+
105
+ def lookup_refterm(node)
106
+ target = normalize_ref_id1(node)
107
+ if termlookup[:term][target].nil? && termlookup[:symbol][target].nil?
108
+ remove_missing_ref(node, target)
109
+ else
110
+ x = node.at("../xrefrender") and x.name = "xref"
111
+ end
112
+ end
113
+
74
114
  def remove_missing_ref(node, target)
75
115
  if node.at("./parent::concept[@type = 'symbol']")
76
116
  log.add("AsciiDoc Input", node,
77
117
  remove_missing_ref_msg(node, target, :symbol))
78
- remove_missing_ref_symbol(node, target)
118
+ remove_missing_ref_term(node, target, "symbol")
79
119
  else
80
120
  log.add("AsciiDoc Input", node,
81
121
  remove_missing_ref_msg(node, target, :term))
82
- remove_missing_ref_term(node, target)
122
+ remove_missing_ref_term(node, target, "term")
83
123
  end
84
124
  end
85
125
 
@@ -94,7 +134,7 @@ module Metanorma
94
134
  end
95
135
 
96
136
  def remove_missing_ref_msg1(_node, target, ret)
97
- target2 = "_#{target.downcase.gsub(/-/, '_')}"
137
+ target2 = "_#{target.downcase.gsub('-', '_')}"
98
138
  if @terms_tags[target] || @terms_tags[target2]
99
139
  ret.strip!
100
140
  ret += ". Did you mean to point to a subterm?"
@@ -102,23 +142,13 @@ module Metanorma
102
142
  ret
103
143
  end
104
144
 
105
- def remove_missing_ref_term(node, target)
106
- node.name = "strong"
107
- node.at("../xrefrender")&.remove
108
- display = node.at("../renderterm")&.remove&.children
109
- display = [] if display.nil? || display.to_xml == node.text
110
- d = display.empty? ? "" : ", display <tt>#{display.to_xml}</tt>"
111
- node.children = "term <tt>#{node.text}</tt>#{d} " \
112
- "not resolved via ID <tt>#{target}</tt>"
113
- end
114
-
115
- def remove_missing_ref_symbol(node, target)
145
+ def remove_missing_ref_term(node, target, type)
116
146
  node.name = "strong"
117
- node.at("../xrefrender")&.remove
147
+ node.xpath("../xrefrender | ../xref").each(&:remove)
118
148
  display = node.at("../renderterm")&.remove&.children
119
149
  display = [] if display.nil? || display.to_xml == node.text
120
150
  d = display.empty? ? "" : ", display <tt>#{display.to_xml}</tt>"
121
- node.children = "symbol <tt>#{node.text}</tt>#{d} " \
151
+ node.children = "#{type} <tt>#{@c.encode(node.text)}</tt>#{d} " \
122
152
  "not resolved via ID <tt>#{target}</tt>"
123
153
  end
124
154
 
@@ -137,35 +167,50 @@ module Metanorma
137
167
 
138
168
  def replace_automatic_generated_ids_terms
139
169
  r = xmldoc.xpath("//term").each.with_object({}) do |n, res|
140
- normalize_id_and_memorize(n, res, "./preferred//name", "term")
141
- normalize_id_and_memorize(n, res, "./admitted//name", "term")
170
+ norm_id_memorize(n, res, "./preferred//name", "term", true)
171
+ norm_id_memorize(n, res, "./admitted//name", "term", true)
142
172
  end
143
173
  s = xmldoc.xpath("//definitions//dt").each.with_object({}) do |n, res|
144
- normalize_id_and_memorize(n, res, ".", "symbol")
174
+ norm_id_memorize(n, res, ".", "symbol", false)
145
175
  end
146
176
  { term: r, symbol: s, secondary2primary: pref_secondary2primary }
147
177
  end
148
178
 
149
179
  def pref_secondary2primary
150
- term = ""
151
180
  xmldoc.xpath("//term").each.with_object({}) do |n, res|
152
- n.xpath("./preferred//name").each_with_index do |p, i|
153
- i.zero? and term = p.text
154
- i.positive? and res[p.text] = term
155
- end
156
- n.xpath("./admitted//name").each { |p| res[p.text] = term }
181
+ primary = domain_prefix(n, n.at("./preferred//name")&.text)
182
+ pref_secondary2primary_preferred(n, res, primary)
183
+ pref_secondary2primary_admitted(n, res, primary)
184
+ end
185
+ end
186
+
187
+ def pref_secondary2primary_preferred(term, res, primary)
188
+ term.xpath("./preferred//name").each_with_index do |p, i|
189
+ t = p.text.strip
190
+ i.positive? and
191
+ res[normalize_ref_id_text(domain_prefix(term, t))] = primary
192
+ @unique_designs[t] && term.at(".//domain") and
193
+ res[normalize_ref_id_text(t)] = primary
194
+ end
195
+ end
196
+
197
+ def pref_secondary2primary_admitted(term, res, primary)
198
+ term.xpath("./admitted//name").each do |p|
199
+ t = p.text.strip
200
+ res[normalize_ref_id_text(domain_prefix(term, t))] = primary
201
+ @unique_designs[t] && term.at(".//domain") and
202
+ res[normalize_ref_id_text(t)] = primary
157
203
  end
158
204
  end
159
205
 
160
- def normalize_id_and_memorize(node, res_table, text_selector, prefix)
161
- normalize_id_and_memorize_init(node, res_table, text_selector, prefix)
162
- memorize_other_pref_terms(node, res_table, text_selector)
206
+ def norm_id_memorize(node, res_table, selector, prefix, use_domain)
207
+ norm_id_memorize_init(node, res_table, selector, prefix, use_domain)
208
+ memorize_other_pref_terms(node, res_table, selector, use_domain)
163
209
  end
164
210
 
165
- def normalize_id_and_memorize_init(node, res_table, text_selector, prefix)
166
- term_text = normalize_ref_id(node.at(text_selector)) or return
167
- unless AUTOMATIC_GENERATED_ID_REGEXP.match(node["id"]).nil? &&
168
- !node["id"].nil?
211
+ def norm_id_memorize_init(node, res_table, selector, prefix, use_domain)
212
+ term_text = normalize_ref_id(node, selector, use_domain) or return
213
+ unless AUTO_GEN_ID_REGEXP.match(node["id"]).nil? && !node["id"].nil?
169
214
  id = unique_text_id(term_text, prefix)
170
215
  node["id"] = id
171
216
  @idhash[id] = true
@@ -173,34 +218,46 @@ module Metanorma
173
218
  res_table[term_text] = node["id"]
174
219
  end
175
220
 
176
- def memorize_other_pref_terms(node, res_table, text_selector)
221
+ def memorize_other_pref_terms(node, res_table, text_selector, use_domain)
177
222
  node.xpath(text_selector).each_with_index do |p, i|
178
- next unless i.positive?
179
-
180
- res_table[normalize_ref_id(p)] = node["id"]
223
+ i.positive? or next
224
+ res_table[normalize_ref_id1(p, use_domain ? node : nil)] = node["id"]
181
225
  end
182
226
  end
183
227
 
184
- def normalize_ref_id(term)
185
- return nil if term.nil?
228
+ def domain_prefix(node, term)
229
+ d = node&.at(".//domain") or return term
230
+ "<#{d.text}> #{term}"
231
+ end
232
+
233
+ def normalize_ref_id(node, selector, use_domain)
234
+ term = node.at(selector) or return nil
235
+ normalize_ref_id1(term, use_domain ? node : nil)
236
+ end
186
237
 
238
+ def normalize_ref_id1(term, node = nil)
187
239
  t = term.dup
188
240
  t.xpath(".//index").map(&:remove)
189
- Metanorma::Utils::to_ncname(t.text.strip
190
- .gsub(/[[:space:]]+/, "-"))
241
+ ret = asciimath_key(t).text.strip
242
+ node and ret = domain_prefix(node, ret)
243
+ normalize_ref_id_text(ret)
244
+ end
245
+
246
+ def normalize_ref_id_text(text)
247
+ Metanorma::Utils::to_ncname(text.gsub(/[[:space:]]+/, "-"))
191
248
  end
192
249
 
193
250
  def unique_text_id(text, prefix)
194
- unless @idhash["#{prefix}-#{text}"]
251
+ @idhash["#{prefix}-#{text}"] or
195
252
  return "#{prefix}-#{text}"
196
- end
197
-
198
253
  (1..Float::INFINITY).lazy.each do |index|
199
254
  unless @idhash["#{prefix}-#{text}-#{index}"]
200
255
  break("#{prefix}-#{text}-#{index}")
201
256
  end
202
257
  end
203
258
  end
259
+
260
+ include ::Metanorma::Standoc::Utils
204
261
  end
205
262
  end
206
263
  end
@@ -70,10 +70,10 @@ module Metanorma
70
70
 
71
71
  def xml_encode(text)
72
72
  @c.encode(text, :basic, :hexadecimal)
73
- .gsub(/&amp;gt;/, ">").gsub(/&amp;lt;/, "<").gsub(/&amp;amp;/, "&")
74
- .gsub(/&gt;/, ">").gsub(/&lt;/, "<").gsub(/&amp;/, "&")
75
- .gsub(/&quot;/, '"').gsub(/&#xa;/, "\n").gsub(/&amp;#/, "&#")
76
- .gsub(/&apos;/, "'")
73
+ .gsub("&amp;gt;", ">").gsub("&amp;lt;", "<").gsub("&amp;amp;", "&")
74
+ .gsub("&gt;", ">").gsub("&lt;", "<").gsub("&amp;", "&")
75
+ .gsub("&quot;", '"').gsub("&#xa;", "\n").gsub("&amp;#", "&#")
76
+ .gsub("&apos;", "'")
77
77
  end
78
78
 
79
79
  # wrapped in <sections>
@@ -85,6 +85,25 @@ module Metanorma
85
85
  Nokogiri::XML(c).at("//xmlns:sections")
86
86
  end
87
87
 
88
+ def asciimath_key(sym)
89
+ key = sym.dup
90
+ key.traverse do |n|
91
+ if n.name == "stem" && a = n.at(".//asciimath")
92
+ n.children = @c.encode(
93
+ @c.decode(grkletters(a.text)), :basic
94
+ )
95
+ end
96
+ end
97
+ key.xpath(".//asciimath").each(&:remove)
98
+ Nokogiri::XML(key.to_xml)
99
+ end
100
+
101
+ def grkletters(text)
102
+ text.gsub(/\b(alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|
103
+ lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|
104
+ psi|omega)\b/xi, "&\\1;")
105
+ end
106
+
88
107
  module_function :adoc2xml
89
108
 
90
109
  class EmptyAttr
@@ -1,7 +1,7 @@
1
1
  require "metanorma/standoc/utils"
2
- require_relative "./validate_section"
3
- require_relative "./validate_table"
4
- require_relative "./validate_xref"
2
+ require_relative "validate_section"
3
+ require_relative "validate_table"
4
+ require_relative "validate_term"
5
5
  require "nokogiri"
6
6
  require "jing"
7
7
  require "iev"
@@ -10,38 +10,6 @@ require "pngcheck"
10
10
  module Metanorma
11
11
  module Standoc
12
12
  module Validate
13
- SOURCELOCALITY = "./origin//locality[@type = 'clause']/" \
14
- "referenceFrom".freeze
15
-
16
- def init_iev
17
- @no_isobib and return nil
18
- @iev and return @iev
19
- @iev = Iev::Db.new(@iev_globalname, @iev_localname) unless @no_isobib
20
- @iev
21
- end
22
-
23
- def iev_validate(xmldoc)
24
- @iev = init_iev or return
25
- xmldoc.xpath("//term").each do |t|
26
- t.xpath(".//termsource").each do |src|
27
- (/^IEC[  ]60050-/.match(src.at("./origin/@citeas")&.text) &&
28
- loc = src.xpath(SOURCELOCALITY)&.text) or next
29
- iev_validate1(t, loc, xmldoc)
30
- end
31
- end
32
- end
33
-
34
- def iev_validate1(term, loc, xmldoc)
35
- iev = @iev.fetch(loc,
36
- xmldoc.at("//language")&.text || "en") or return
37
- pref = term.xpath("./preferred//name").inject([]) do |m, x|
38
- m << x.text&.downcase
39
- end
40
- pref.include?(iev.downcase) or
41
- @log.add("Bibliography", term, %(Term "#{pref[0]}" does not match ) +
42
- %(IEV #{loc} "#{iev}"))
43
- end
44
-
45
13
  def content_validate(doc)
46
14
  repeat_id_validate(doc.root) # feeds xref_validate
47
15
  xref_validate(doc) # feeds nested_asset_validate
@@ -51,6 +19,7 @@ module Metanorma
51
19
  iev_validate(doc.root)
52
20
  concept_validate(doc, "concept", "refterm")
53
21
  concept_validate(doc, "related", "preferred//name")
22
+ preferred_validate(doc)
54
23
  table_validate(doc)
55
24
  @fatalerror += requirement_validate(doc)
56
25
  image_validate(doc)
@@ -73,7 +42,7 @@ module Metanorma
73
42
  def mathml_sanitise(math)
74
43
  math.to_xml(encoding: "US-ASCII").gsub(/ xmlns=["'][^"']+["']/, "")
75
44
  .gsub(%r{<[^:/>]+:}, "<").gsub(%r{</[^:/>]+:}, "</")
76
- #.gsub(/&#([^;]+);/) { |x| "&#x#{$1.to_i.to_s(16)};" }
45
+ # .gsub(/&#([^;]+);/) { |x| "&#x#{$1.to_i.to_s(16)};" }
77
46
  end
78
47
 
79
48
  def math_validate_error(math, elem, error)
@@ -125,37 +94,6 @@ module Metanorma
125
94
  # @fatalerror << err2
126
95
  end
127
96
 
128
- def concept_validate(doc, tag, refterm)
129
- found = false
130
- concept_validate_ids(doc)
131
- doc.xpath("//#{tag}/xref").each do |x|
132
- @concept_ids[x["target"]] and next
133
- @log.add("Anchors", x, concept_validate_msg(doc, tag, refterm, x))
134
- found = true
135
- end
136
- found and @fatalerror << "#{tag.capitalize} not cross-referencing " \
137
- "term or symbol"
138
- end
139
-
140
- def concept_validate_ids(doc)
141
- @concept_ids ||= doc.xpath("//term | //definitions//dt")
142
- .each_with_object({}) { |x, m| m[x["id"]] = true }
143
- @concept_terms_tags ||= doc.xpath("//terms")
144
- .each_with_object({}) { |t, m| m[t["id"]] = true }
145
- nil
146
- end
147
-
148
- def concept_validate_msg(_doc, tag, refterm, xref)
149
- ret = <<~LOG
150
- #{tag.capitalize} #{xref.at("../#{refterm}")&.text} is pointing to #{xref['target']}, which is not a term or symbol
151
- LOG
152
- if @concept_terms_tags[xref["target"]]
153
- ret = ret.strip
154
- ret += ". Did you mean to point to a subterm?"
155
- end
156
- ret
157
- end
158
-
159
97
  def schema_validate(doc, schema)
160
98
  Tempfile.open(["tmp", ".xml"], encoding: "UTF-8") do |f|
161
99
  schema_validate1(f, doc, schema)
@@ -247,6 +185,33 @@ module Metanorma
247
185
  schema_validate(formattedstr_strip(doc.dup),
248
186
  File.join(File.dirname(__FILE__), "isodoc-compile.rng"))
249
187
  end
188
+
189
+ def repeat_id_validate1(elem)
190
+ if @doc_ids[elem["id"]]
191
+ @log.add("Anchors", elem, "Anchor #{elem['id']} has already been " \
192
+ "used at line #{@doc_ids[elem['id']]}")
193
+ @fatalerror << "Multiple instances of same ID: #{elem['id']}"
194
+ end
195
+ @doc_ids[elem["id"]] = elem.line
196
+ end
197
+
198
+ def repeat_id_validate(doc)
199
+ @doc_ids = {}
200
+ doc.xpath("//*[@id]").each do |x|
201
+ repeat_id_validate1(x)
202
+ end
203
+ end
204
+
205
+ # manually check for xref/@target, xref/@to integrity
206
+ def xref_validate(doc)
207
+ @doc_xrefs = doc.xpath("//xref/@target | //xref/@to")
208
+ .each_with_object({}) do |x, m|
209
+ m[x.text] = x
210
+ @doc_ids[x.text] and next
211
+ @log.add("Anchors", x.parent,
212
+ "Crossreference target #{x} is undefined")
213
+ end
214
+ end
250
215
  end
251
216
  end
252
217
  end
@@ -0,0 +1,89 @@
1
+ module Metanorma
2
+ module Standoc
3
+ module Validate
4
+ SOURCELOCALITY = "./origin//locality[@type = 'clause']/" \
5
+ "referenceFrom".freeze
6
+
7
+ def init_iev
8
+ @no_isobib and return nil
9
+ @iev and return @iev
10
+ @iev = Iev::Db.new(@iev_globalname, @iev_localname) unless @no_isobib
11
+ @iev
12
+ end
13
+
14
+ def iev_validate(xmldoc)
15
+ @iev = init_iev or return
16
+ xmldoc.xpath("//term").each do |t|
17
+ t.xpath(".//termsource").each do |src|
18
+ (/^IEC[  ]60050-/.match(src.at("./origin/@citeas")&.text) &&
19
+ loc = src.xpath(SOURCELOCALITY)&.text) or next
20
+ iev_validate1(t, loc, xmldoc)
21
+ end
22
+ end
23
+ end
24
+
25
+ def iev_validate1(term, loc, xmldoc)
26
+ iev = @iev.fetch(loc,
27
+ xmldoc.at("//language")&.text || "en") or return
28
+ pref = term.xpath("./preferred//name").inject([]) do |m, x|
29
+ m << x.text&.downcase
30
+ end
31
+ pref.include?(iev.downcase) or
32
+ @log.add("Bibliography", term, %(Term "#{pref[0]}" does not match ) +
33
+ %(IEV #{loc} "#{iev}"))
34
+ end
35
+
36
+ def concept_validate(doc, tag, refterm)
37
+ found = false
38
+ concept_validate_ids(doc)
39
+ doc.xpath("//#{tag}/xref").each do |x|
40
+ @concept_ids[x["target"]] and next
41
+ @log.add("Anchors", x, concept_validate_msg(doc, tag, refterm, x))
42
+ found = true
43
+ end
44
+ found and @fatalerror << "#{tag.capitalize} not cross-referencing " \
45
+ "term or symbol"
46
+ end
47
+
48
+ def concept_validate_ids(doc)
49
+ @concept_ids ||= doc.xpath("//term | //definitions//dt")
50
+ .each_with_object({}) { |x, m| m[x["id"]] = true }
51
+ @concept_terms_tags ||= doc.xpath("//terms")
52
+ .each_with_object({}) { |t, m| m[t["id"]] = true }
53
+ nil
54
+ end
55
+
56
+ def concept_validate_msg(_doc, tag, refterm, xref)
57
+ ret = <<~LOG
58
+ #{tag.capitalize} #{xref.at("../#{refterm}")&.text} is pointing to #{xref['target']}, which is not a term or symbol
59
+ LOG
60
+ if @concept_terms_tags[xref["target"]]
61
+ ret = ret.strip
62
+ ret += ". Did you mean to point to a subterm?"
63
+ end
64
+ ret
65
+ end
66
+
67
+ def preferred_validate(doc)
68
+ out = []
69
+ ret = doc.xpath("//term").each_with_object({}) do |t, m|
70
+ prefix = t.at("./domain")&.text
71
+ t.xpath("./preferred//name").each do |n|
72
+ ret = n.text
73
+ prefix and ret = "<#{prefix}> #{ret}"
74
+ (m[ret] and out << ret) or m[ret] = t
75
+ end
76
+ end
77
+ preferred_validate_report(out, ret)
78
+ end
79
+
80
+ def preferred_validate_report(terms, locations)
81
+ terms.each do |e|
82
+ err = "Term #{e} occurs twice as preferred designation"
83
+ @log.add("Terms", locations[e], err)
84
+ @fatalerror << err
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -19,6 +19,6 @@ module Metanorma
19
19
  end
20
20
 
21
21
  module Standoc
22
- VERSION = "2.4.8".freeze
22
+ VERSION = "2.5.0".freeze
23
23
  end
24
24
  end
@@ -30,7 +30,7 @@ Gem::Specification.new do |spec|
30
30
 
31
31
  spec.add_dependency "asciidoctor", "~> 2.0.0"
32
32
  spec.add_dependency "iev", "~> 0.3.0"
33
- spec.add_dependency "isodoc", "~> 2.5.4"
33
+ spec.add_dependency "isodoc", "~> 2.6.0"
34
34
  spec.add_dependency "metanorma", ">= 1.5.0"
35
35
  spec.add_dependency "metanorma-plugin-datastruct", "~> 0.2.0"
36
36
  spec.add_dependency "metanorma-plugin-glossarist", "~> 0.1.1"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metanorma-standoc
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.8
4
+ version: 2.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-06 00:00:00.000000000 Z
11
+ date: 2023-08-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: asciidoctor
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 2.5.4
47
+ version: 2.6.0
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 2.5.4
54
+ version: 2.6.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: metanorma
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -529,7 +529,7 @@ files:
529
529
  - lib/metanorma/standoc/validate.rb
530
530
  - lib/metanorma/standoc/validate_section.rb
531
531
  - lib/metanorma/standoc/validate_table.rb
532
- - lib/metanorma/standoc/validate_xref.rb
532
+ - lib/metanorma/standoc/validate_term.rb
533
533
  - lib/metanorma/standoc/version.rb
534
534
  - lib/metanorma/standoc/views/datamodel/model_representation.adoc.erb
535
535
  - lib/metanorma/standoc/views/datamodel/plantuml_representation.adoc.erb
@@ -1,32 +0,0 @@
1
- module Metanorma
2
- module Standoc
3
- module Validate
4
- def repeat_id_validate1(elem)
5
- if @doc_ids[elem["id"]]
6
- @log.add("Anchors", elem, "Anchor #{elem['id']} has already been " \
7
- "used at line #{@doc_ids[elem['id']]}")
8
- @fatalerror << "Multiple instances of same ID: #{elem['id']}"
9
- end
10
- @doc_ids[elem["id"]] = elem.line
11
- end
12
-
13
- def repeat_id_validate(doc)
14
- @doc_ids = {}
15
- doc.xpath("//*[@id]").each do |x|
16
- repeat_id_validate1(x)
17
- end
18
- end
19
-
20
- # manually check for xref/@target, xref/@to integrity
21
- def xref_validate(doc)
22
- @doc_xrefs = doc.xpath("//xref/@target | //xref/@to")
23
- .each_with_object({}) do |x, m|
24
- m[x.text] = x
25
- @doc_ids[x.text] and next
26
- @log.add("Anchors", x.parent,
27
- "Crossreference target #{x} is undefined")
28
- end
29
- end
30
- end
31
- end
32
- end