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 +4 -4
- data/lib/isodoc/html/htmlstyle.css +13 -9
- data/lib/isodoc/html/htmlstyle.scss +6 -6
- data/lib/metanorma/standoc/blocks.rb +1 -1
- data/lib/metanorma/standoc/cleanup.rb +21 -19
- data/lib/metanorma/standoc/cleanup_block.rb +1 -0
- data/lib/metanorma/standoc/cleanup_inline.rb +18 -4
- data/lib/metanorma/standoc/cleanup_maths.rb +34 -21
- data/lib/metanorma/standoc/cleanup_symbols.rb +3 -20
- data/lib/metanorma/standoc/cleanup_terms.rb +1 -0
- data/lib/metanorma/standoc/cleanup_terms_designations.rb +20 -5
- data/lib/metanorma/standoc/cleanup_text.rb +0 -1
- data/lib/metanorma/standoc/converter.rb +2 -2
- data/lib/metanorma/standoc/inline.rb +21 -12
- data/lib/metanorma/standoc/isodoc.rng +26 -4
- data/lib/metanorma/standoc/macros.rb +0 -2
- data/lib/metanorma/standoc/ref_sect.rb +4 -3
- data/lib/metanorma/standoc/term_lookup_cleanup.rb +117 -60
- data/lib/metanorma/standoc/utils.rb +23 -4
- data/lib/metanorma/standoc/validate.rb +32 -67
- data/lib/metanorma/standoc/validate_term.rb +89 -0
- data/lib/metanorma/standoc/version.rb +1 -1
- data/metanorma-standoc.gemspec +1 -1
- metadata +5 -5
- data/lib/metanorma/standoc/validate_xref.rb +0 -32
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1d6a56b88b9f58482764ff6aede297e389577151d0d112a215b2215d5cfb41cf
|
4
|
+
data.tar.gz: cb0a1a1d73930e89169a27185bcce3d19130f1150a22fd7345da61a73dbd759f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
124
|
+
a.FootnoteRef + a.FootnoteRef::before {
|
125
125
|
content: ", ";
|
126
126
|
vertical-align: super; }
|
127
127
|
|
128
|
-
a.TableFootnoteRef + a.TableFootnoteRef
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
304
|
+
ol[class="roman"] ol[class="roman"] > li::before {
|
305
305
|
counter-increment: none;
|
306
306
|
content: initial;
|
307
307
|
}
|
@@ -1,24 +1,24 @@
|
|
1
1
|
require "nokogiri"
|
2
2
|
require "pathname"
|
3
3
|
require "html2doc"
|
4
|
-
require_relative "
|
5
|
-
require_relative "
|
6
|
-
require_relative "
|
7
|
-
require_relative "
|
8
|
-
require_relative "
|
9
|
-
require_relative "
|
10
|
-
require_relative "
|
11
|
-
require_relative "
|
12
|
-
require_relative "
|
13
|
-
require_relative "
|
14
|
-
require_relative "
|
15
|
-
require_relative "
|
16
|
-
require_relative "
|
17
|
-
require_relative "
|
18
|
-
require_relative "
|
19
|
-
require_relative "
|
20
|
-
require_relative "
|
21
|
-
require_relative "
|
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,
|
@@ -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
|
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
|
-
|
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(
|
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
|
7
|
-
|
8
|
-
|
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
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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(
|
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(
|
27
|
-
|
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("
|
32
|
-
|
33
|
-
end
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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(
|
44
|
-
.gsub(
|
56
|
+
math = xml.text.gsub("<", "<").gsub(">", ">")
|
57
|
+
.gsub(""", '"').gsub("'", "'").gsub("&", "&")
|
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
|
-
|
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
|
-
|
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 =
|
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
|
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")
|
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 /<([^:>&]+:)?math(\s+[^>&]+)?> |
|
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(
|
162
|
+
xml.stem text&.gsub("&#", "&#"), type: "AsciiMath", block: block
|
162
163
|
end
|
163
164
|
end
|
164
165
|
|
165
|
-
def latex_parse(text, xml)
|
166
|
-
latex = latex_parse1(text) or
|
167
|
-
|
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
|
-
|
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.
|
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
|
-
<
|
196
|
-
<
|
197
|
-
|
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>
|
@@ -85,13 +85,14 @@ module Metanorma
|
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
|
-
def
|
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
|
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
|
-
|
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
|
-
|
39
|
-
|
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
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
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
|
-
|
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 =
|
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
|
-
|
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.
|
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 = "
|
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
|
-
|
141
|
-
|
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
|
-
|
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.
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
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
|
161
|
-
|
162
|
-
memorize_other_pref_terms(node, res_table,
|
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
|
166
|
-
term_text = normalize_ref_id(node
|
167
|
-
unless
|
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
|
-
|
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
|
185
|
-
|
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
|
-
|
190
|
-
|
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
|
-
|
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(
|
74
|
-
.gsub(
|
75
|
-
.gsub(
|
76
|
-
.gsub(
|
73
|
+
.gsub("&gt;", ">").gsub("&lt;", "<").gsub("&amp;", "&")
|
74
|
+
.gsub(">", ">").gsub("<", "<").gsub("&", "&")
|
75
|
+
.gsub(""", '"').gsub("
", "\n").gsub("&#", "&#")
|
76
|
+
.gsub("'", "'")
|
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 "
|
3
|
-
require_relative "
|
4
|
-
require_relative "
|
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
|
-
|
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
|
data/metanorma-standoc.gemspec
CHANGED
@@ -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.
|
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
|
+
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
|
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.
|
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.
|
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/
|
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
|