metanorma-standoc 2.4.8 → 2.5.0

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