metanorma-iso 3.1.3 → 3.1.5
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 +4 -4
- data/lib/isodoc/iso/html/style-human.css +39 -45
- data/lib/isodoc/iso/html/style-iso.css +40 -46
- data/lib/isodoc/iso/iso.amendment.xsl +632 -170
- data/lib/isodoc/iso/iso.international-standard.xsl +632 -170
- data/lib/isodoc/iso/presentation_section.rb +39 -4
- data/lib/isodoc/iso/word_cleanup.rb +17 -2
- data/lib/metanorma/iso/front.rb +10 -49
- data/lib/metanorma/iso/front_contributor.rb +3 -5
- data/lib/metanorma/iso/isodoc.rng +44 -19
- data/lib/metanorma/iso/validate.rb +18 -126
- data/lib/metanorma/iso/validate_numeric.rb +128 -0
- data/lib/metanorma/iso/validate_style.rb +0 -77
- data/lib/metanorma/iso/validate_xref.rb +130 -0
- data/lib/metanorma/iso/version.rb +1 -1
- metadata +4 -3
- data/lib/metanorma/iso/validate_image.rb +0 -97
@@ -84,7 +84,8 @@ module IsoDoc
|
|
84
84
|
super
|
85
85
|
end
|
86
86
|
|
87
|
-
|
87
|
+
# KILL
|
88
|
+
def middle_titlex(docxml)
|
88
89
|
@meta.get[:doctitlemain].nil? || @meta.get[:doctitlemain].empty? and
|
89
90
|
return
|
90
91
|
s = docxml.at(ns("//sections")) or return
|
@@ -92,7 +93,8 @@ module IsoDoc
|
|
92
93
|
s.add_first_child ret
|
93
94
|
end
|
94
95
|
|
95
|
-
|
96
|
+
# KILL
|
97
|
+
def middle_title_mainx
|
96
98
|
ret = "<span class='boldtitle'>#{@meta.get[:doctitleintro]}"
|
97
99
|
@meta.get[:doctitleintro] && @meta.get[:doctitlemain] and
|
98
100
|
ret += " — "
|
@@ -104,7 +106,17 @@ module IsoDoc
|
|
104
106
|
"<p class='zzSTDTitle1'>#{ret}</p>"
|
105
107
|
end
|
106
108
|
|
107
|
-
def
|
109
|
+
def middle_title_main
|
110
|
+
<<~OUTPUT
|
111
|
+
<p class='zzSTDTitle1'><span class='boldtitle'>{{ doctitleintro -}}
|
112
|
+
{% if doctitleintro and doctitlemain %} — {% endif %}{{ doctitlemain -}}
|
113
|
+
{% if doctitlemain %}{% if doctitlepart or doctitlecomplementary %} — {% endif %}{% endif -%}
|
114
|
+
</span>#{middle_title_part}</p>
|
115
|
+
OUTPUT
|
116
|
+
end
|
117
|
+
|
118
|
+
# KILL
|
119
|
+
def middle_title_partx
|
108
120
|
ret = ""
|
109
121
|
if a = @meta.get[:doctitlecomplementary]
|
110
122
|
ret += "<span class='boldtitle'>#{a}</span>"
|
@@ -116,7 +128,17 @@ module IsoDoc
|
|
116
128
|
ret
|
117
129
|
end
|
118
130
|
|
119
|
-
def
|
131
|
+
def middle_title_part
|
132
|
+
<<~OUTPUT.strip
|
133
|
+
{% if doctitlecomplementary %}<span class='boldtitle'>{{ doctitlecomplementary }}</span>
|
134
|
+
{% elsif doctitlepart -%}
|
135
|
+
{% if doctitlepartlabel %}<span class='nonboldtitle'>{{ doctitlepartlabel }}:</span>{% endif -%}
|
136
|
+
<span class='boldtitle'>{{ doctitlepart }}</span>{% endif %}
|
137
|
+
OUTPUT
|
138
|
+
end
|
139
|
+
|
140
|
+
# KILL
|
141
|
+
def middle_title_amdx
|
120
142
|
ret = ""
|
121
143
|
if a = @meta.get[:doctitleamdlabel]
|
122
144
|
ret += "<p class='zzSTDTitle2'>#{a}"
|
@@ -128,6 +150,19 @@ module IsoDoc
|
|
128
150
|
ret
|
129
151
|
end
|
130
152
|
|
153
|
+
def middle_title_amd
|
154
|
+
<<~OUTPUT
|
155
|
+
{% if doctitleamdlabel %}<p class='zzSTDTitle2'>{{ doctitleamdlabel -}}
|
156
|
+
{% if doctitleamd %}: {{doctitleamd}}{% endif -%}
|
157
|
+
</p>{% endif %}
|
158
|
+
{% if doctitlecorrlabel %}<p class='zzSTDTitle2'>{{ doctitlecorrlabel }}</p>{% endif %}
|
159
|
+
OUTPUT
|
160
|
+
end
|
161
|
+
|
162
|
+
def middle_title_template
|
163
|
+
middle_title_main + middle_title_amd
|
164
|
+
end
|
165
|
+
|
131
166
|
def move_norm_ref_to_sections(docxml)
|
132
167
|
amd?(docxml) or super
|
133
168
|
end
|
@@ -123,7 +123,9 @@ module IsoDoc
|
|
123
123
|
|
124
124
|
def authority_copyright_style(auth)
|
125
125
|
auth.xpath(".//p[not(@class)]").each { |p| p["class"] = "zzCopyright" }
|
126
|
-
auth.xpath(".//p[@class = 'Tablebody']").each
|
126
|
+
auth.xpath(".//p[@class = 'Tablebody']").each do |p|
|
127
|
+
p["class"] = "zzCopyright"
|
128
|
+
end
|
127
129
|
auth.xpath(".//p[@id = 'boilerplate-message']").each do |p|
|
128
130
|
p["class"] = "zzCopyright1"
|
129
131
|
end
|
@@ -163,14 +165,27 @@ module IsoDoc
|
|
163
165
|
toc = ""
|
164
166
|
s = docxml.at("//div[@class = 'TOC']") and toc = to_xml(s.children)
|
165
167
|
xpath = (1..level).each.map { |i| "//h#{i}" }.join (" | ")
|
168
|
+
annexid = 0
|
166
169
|
docxml.xpath(xpath).each do |h|
|
167
170
|
x = ""
|
168
|
-
|
171
|
+
if %w(ANNEX Annex).include?(h["class"])
|
172
|
+
x, annexid = annex_toc(annexid)
|
173
|
+
end
|
169
174
|
toc += word_toc_entry(h.name[1].to_i, x + header_strip(h))
|
170
175
|
end
|
171
176
|
toc.sub(/(<p class="MsoToc1">)/,
|
172
177
|
%{\\1#{word_toc_preface(level)}}) + WORD_TOC_SUFFIX1
|
173
178
|
end
|
179
|
+
|
180
|
+
# do not use in IEC, BSI, where Word does not use list to generate
|
181
|
+
# "Annex A"
|
182
|
+
def annex_toc(annexid)
|
183
|
+
instance_of?(IsoDoc::Iso::WordConvert) ||
|
184
|
+
instance_of?(WordDISConvert) or return ""
|
185
|
+
annexid += 1
|
186
|
+
x = "#{@i18n.annex} #{('@'.ord + annexid).chr} "
|
187
|
+
[x, annexid]
|
188
|
+
end
|
174
189
|
end
|
175
190
|
end
|
176
191
|
end
|
data/lib/metanorma/iso/front.rb
CHANGED
@@ -71,56 +71,18 @@ module Metanorma
|
|
71
71
|
@log.add("Document Attributes", nil, err)
|
72
72
|
end
|
73
73
|
|
74
|
-
def title_component(node, xml, lang,
|
74
|
+
def title_component(node, xml, lang, comp)
|
75
75
|
t = node.attr("title-#{comp[:name]}-#{lang}") or return
|
76
|
-
xml
|
77
|
-
t1 << Metanorma::Utils::asciidoc_sub(t)
|
78
|
-
end
|
76
|
+
add_title_xml(xml, t, lang, "title-#{comp[:abbr]}")
|
79
77
|
end
|
80
78
|
|
81
|
-
def
|
82
|
-
t = node.attr("title-intro-#{lang}") or return
|
83
|
-
xml.title(**attr_code(at.merge(type: "title-intro"))) do |t1|
|
84
|
-
t1 << Metanorma::Utils::asciidoc_sub(t)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def title_main(node, xml, lang, at)
|
89
|
-
xml.title **attr_code(at.merge(type: "title-main")) do |t1|
|
90
|
-
t1 << Metanorma::Utils::asciidoc_sub(node.attr("title-main-#{lang}"))
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
def title_part(node, xml, lang, at)
|
95
|
-
t = node.attr("title-part-#{lang}") or return
|
96
|
-
xml.title(**attr_code(at.merge(type: "title-part"))) do |t1|
|
97
|
-
t1 << Metanorma::Utils::asciidoc_sub(t)
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def title_amd(node, xml, lang, at)
|
102
|
-
t = node.attr("title-amendment-#{lang}") or return
|
103
|
-
xml.title(**attr_code(at.merge(type: "title-amd"))) do |t1|
|
104
|
-
t1 << Metanorma::Utils::asciidoc_sub(t)
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
def title_add(node, xml, lang, at)
|
109
|
-
t = node.attr("title-addendum-#{lang}") or return
|
110
|
-
xml.title(**attr_code(at.merge(type: "title-add"))) do |t1|
|
111
|
-
t1 << Metanorma::Utils::asciidoc_sub(t)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
def title_full(node, xml, lang, at)
|
79
|
+
def title_full(node, xml, lang)
|
116
80
|
title, intro, part, amd, add = title_full_prep(node, lang)
|
117
81
|
title = "#{intro} -- #{title}" if intro
|
118
82
|
title = "#{title} -- #{part}" if part
|
119
83
|
title = "#{title} -- #{amd}" if amd
|
120
84
|
title = "#{title} -- #{add}" if add
|
121
|
-
xml
|
122
|
-
t1 << Metanorma::Utils::asciidoc_sub(title)
|
123
|
-
end
|
85
|
+
add_title_xml(xml, title, lang, "main")
|
124
86
|
end
|
125
87
|
|
126
88
|
def title_full_prep(node, lang)
|
@@ -136,20 +98,19 @@ module Metanorma
|
|
136
98
|
|
137
99
|
def title(node, xml)
|
138
100
|
%w(en ru fr).each do |lang|
|
139
|
-
|
140
|
-
title1(node, xml, lang, at)
|
101
|
+
title1(node, xml, lang)
|
141
102
|
end
|
142
103
|
end
|
143
104
|
|
144
|
-
def title1(node, xml, lang
|
145
|
-
title_full(node, xml, lang
|
105
|
+
def title1(node, xml, lang)
|
106
|
+
title_full(node, xml, lang)
|
146
107
|
%w(intro main part complementary).each do |w|
|
147
|
-
title_component(node, xml, lang,
|
108
|
+
title_component(node, xml, lang, { name: w, abbr: w })
|
148
109
|
end
|
149
|
-
@amd and title_component(node, xml, lang,
|
110
|
+
@amd and title_component(node, xml, lang,
|
150
111
|
{ name: "amendment", abbr: "amd" })
|
151
112
|
node.attr("addendum-number") and
|
152
|
-
title_component(node, xml, lang,
|
113
|
+
title_component(node, xml, lang,
|
153
114
|
{ name: "addendum", abbr: "add" })
|
154
115
|
end
|
155
116
|
|
@@ -12,14 +12,12 @@ module Metanorma
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def metadata_author(node, xml)
|
15
|
-
|
16
|
-
{ source: ["publisher", "pub"], role: "author",
|
17
|
-
default: default_publisher })
|
18
|
-
committee_contributors(node, xml, default_publisher,
|
19
|
-
{ approval: false })
|
15
|
+
super
|
20
16
|
secretariat_contributor(node, xml, default_publisher)
|
21
17
|
end
|
22
18
|
|
19
|
+
def personal_author(node, xml); end
|
20
|
+
|
23
21
|
def org_organization(node, xml, org)
|
24
22
|
if org[:committee]
|
25
23
|
contrib_committee_build(xml, org[:agency], org)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
2
2
|
<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">
|
3
|
-
<!-- VERSION v2.1.
|
3
|
+
<!-- VERSION v2.1.3 -->
|
4
4
|
|
5
5
|
<!--
|
6
6
|
ALERT: cannot have root comments, because of https://github.com/metanorma/metanorma/issues/437
|
@@ -123,6 +123,10 @@ the type attribute defaults to `review` for reviews</a:documentation>
|
|
123
123
|
<a:documentation>Notes whose scope is the current block</a:documentation>
|
124
124
|
</ref>
|
125
125
|
</zeroOrMore>
|
126
|
+
<ref name="BlockSource">
|
127
|
+
<a:documentation>Bibliographic source for the information in the list.
|
128
|
+
Sources are currently only rendered in metanorma-plateau</a:documentation>
|
129
|
+
</ref>
|
126
130
|
</define>
|
127
131
|
<define name="OlBody">
|
128
132
|
<optional>
|
@@ -140,6 +144,10 @@ the type attribute defaults to `review` for reviews</a:documentation>
|
|
140
144
|
<a:documentation>Notes whose scope is the current block</a:documentation>
|
141
145
|
</ref>
|
142
146
|
</zeroOrMore>
|
147
|
+
<ref name="BlockSource">
|
148
|
+
<a:documentation>Bibliographic source for the information in the list.
|
149
|
+
Sources are currently only rendered in metanorma-plateau</a:documentation>
|
150
|
+
</ref>
|
143
151
|
</define>
|
144
152
|
<define name="OlAttributes">
|
145
153
|
<a:documentation>NOTE: `start` attribute is not included by default, because of problems it raises with DOC output</a:documentation>
|
@@ -188,6 +196,10 @@ the type attribute defaults to `review` for reviews</a:documentation>
|
|
188
196
|
<a:documentation>Notes whose scope is the current block</a:documentation>
|
189
197
|
</ref>
|
190
198
|
</zeroOrMore>
|
199
|
+
<ref name="BlockSource">
|
200
|
+
<a:documentation>Bibliographic source for the information in the list.
|
201
|
+
Sources are currently only rendered in metanorma-plateau</a:documentation>
|
202
|
+
</ref>
|
191
203
|
</define>
|
192
204
|
<define name="dt">
|
193
205
|
<element name="dt">
|
@@ -443,14 +455,7 @@ normative or informative references, some split references into sections organiz
|
|
443
455
|
</ref>
|
444
456
|
</zeroOrMore>
|
445
457
|
<zeroOrMore>
|
446
|
-
<ref name="
|
447
|
-
<a:documentation>Bibliographic item cited in the document</a:documentation>
|
448
|
-
</ref>
|
449
|
-
<zeroOrMore>
|
450
|
-
<ref name="note">
|
451
|
-
<a:documentation>Annotation of the bibliographic item</a:documentation>
|
452
|
-
</ref>
|
453
|
-
</zeroOrMore>
|
458
|
+
<ref name="ReferenceEntry"/>
|
454
459
|
</zeroOrMore>
|
455
460
|
<zeroOrMore>
|
456
461
|
<ref name="references">
|
@@ -592,18 +597,21 @@ gives an explicit page orientation</a:documentation>
|
|
592
597
|
</element>
|
593
598
|
</optional>
|
594
599
|
</define>
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
<attribute name="hiddenref">
|
601
|
-
<a:documentation>If true, number the footnote as normal, but suppress display of the footnote reference in the document body.
|
600
|
+
<define name="FnAttributes">
|
601
|
+
<ref name="RequiredId"/>
|
602
|
+
<optional>
|
603
|
+
<attribute name="hiddenref">
|
604
|
+
<a:documentation>If true, number the footnote as normal, but suppress display of the footnote reference in the document body.
|
602
605
|
This is done if the footnote reference is already presented in some other form, e.g. within a figure image.</a:documentation>
|
603
|
-
|
606
|
+
<data type="boolean"/>
|
607
|
+
</attribute>
|
608
|
+
</optional>
|
609
|
+
<attribute name="reference">
|
610
|
+
<a:documentation>The number of the footnote, used to identify it visually</a:documentation>
|
604
611
|
</attribute>
|
605
|
-
</
|
606
|
-
</
|
612
|
+
</define>
|
613
|
+
</include>
|
614
|
+
<!-- end overrides -->
|
607
615
|
<define name="TdAttributes" combine="interleave">
|
608
616
|
<ref name="RequiredId"/>
|
609
617
|
<optional>
|
@@ -841,6 +849,17 @@ titlecase, or lowercase</a:documentation>
|
|
841
849
|
<value>informative</value>
|
842
850
|
</choice>
|
843
851
|
</define>
|
852
|
+
<define name="ReferenceEntry">
|
853
|
+
<a:documentation>Entry in bibliography</a:documentation>
|
854
|
+
<ref name="doc_bibitem">
|
855
|
+
<a:documentation>Bibliographic item cited in the document</a:documentation>
|
856
|
+
</ref>
|
857
|
+
<zeroOrMore>
|
858
|
+
<ref name="note">
|
859
|
+
<a:documentation>Annotation of the bibliographic item</a:documentation>
|
860
|
+
</ref>
|
861
|
+
</zeroOrMore>
|
862
|
+
</define>
|
844
863
|
<define name="doc_bibitem">
|
845
864
|
<a:documentation>Standardisation document representation of bibliographic entry</a:documentation>
|
846
865
|
<element name="bibitem">
|
@@ -871,6 +890,12 @@ titlecase, or lowercase</a:documentation>
|
|
871
890
|
</oneOrMore>
|
872
891
|
</element>
|
873
892
|
</define>
|
893
|
+
<define name="ParagraphFnBody" combine="interleave">
|
894
|
+
<ref name="BlockSource">
|
895
|
+
<a:documentation>Bibliographic source for the information in the paragraph
|
896
|
+
parargaph sources are currently only rendered in metanorma-plateau</a:documentation>
|
897
|
+
</ref>
|
898
|
+
</define>
|
874
899
|
<define name="BasicBlock" combine="choice">
|
875
900
|
<ref name="columnbreak"/>
|
876
901
|
</define>
|
@@ -1,10 +1,11 @@
|
|
1
1
|
require "metanorma-standoc"
|
2
2
|
require_relative "validate_style"
|
3
|
+
require_relative "validate_numeric"
|
3
4
|
require_relative "validate_requirements"
|
4
5
|
require_relative "validate_section"
|
5
6
|
require_relative "validate_title"
|
6
|
-
require_relative "validate_image"
|
7
7
|
require_relative "validate_list"
|
8
|
+
require_relative "validate_xref"
|
8
9
|
require "nokogiri"
|
9
10
|
require "jing"
|
10
11
|
require "iev"
|
@@ -29,127 +30,10 @@ module Metanorma
|
|
29
30
|
end
|
30
31
|
end
|
31
32
|
|
32
|
-
# ISO/IEC DIR 2, 15.5.3, 20.2
|
33
|
-
# does not deal with preceding text marked up
|
34
|
-
def see_xrefs_validate(root)
|
35
|
-
@lang == "en" or return
|
36
|
-
anchors = extract_anchor_norm(root)
|
37
|
-
root.xpath("//xref").each do |t|
|
38
|
-
preceding = t.at("./preceding-sibling::text()[last()]")
|
39
|
-
!preceding.nil? &&
|
40
|
-
/\b(see| refer to)\p{Zs}*\Z/mi.match(preceding) or next
|
41
|
-
anchors[t["target"]] and
|
42
|
-
@log.add("Style", t,
|
43
|
-
"'see #{t['target']}' is pointing to a normative section")
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def extract_anchor_norm(root)
|
48
|
-
nodes = root.xpath("//annex[@obligation = 'normative'] | " \
|
49
|
-
"//references[@obligation = 'normative']")
|
50
|
-
ret = nodes.each_with_object({}) do |n, m|
|
51
|
-
n["anchor"] and m[n["anchor"]] = true
|
52
|
-
end
|
53
|
-
nodes.each do |n|
|
54
|
-
n.xpath(".//*[@anchor]").each { |n1| ret[n1["anchor"]] = true }
|
55
|
-
end
|
56
|
-
ret
|
57
|
-
end
|
58
|
-
|
59
|
-
# ISO/IEC DIR 2, 15.5.3
|
60
|
-
def see_erefs_validate(root)
|
61
|
-
@lang == "en" or return
|
62
|
-
bibitemids = extract_bibitem_anchors(root)
|
63
|
-
root.xpath("//eref").each do |t|
|
64
|
-
prec = t.at("./preceding-sibling::text()[last()]")
|
65
|
-
!prec.nil? && /\b(see|refer to)\p{Zs}*\Z/mi.match(prec) or next
|
66
|
-
unless target = bibitemids[t["bibitemid"]]
|
67
|
-
# unless target = root.at("//bibitem[@anchor = '#{t['bibitemid']}']")
|
68
|
-
@log.add("Bibliography", t,
|
69
|
-
"'#{t} is not pointing to a real reference")
|
70
|
-
next
|
71
|
-
end
|
72
|
-
target[:norm] and
|
73
|
-
@log.add("Style", t,
|
74
|
-
"'see #{t}' is pointing to a normative reference")
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def extract_bibitem_anchors(root)
|
79
|
-
ret = root.xpath("//references[@normative = 'true']//bibitem")
|
80
|
-
.each_with_object({}) do |b, m|
|
81
|
-
m[b["anchor"]] = { bib: b, norm: true }
|
82
|
-
end
|
83
|
-
root.xpath("//references[not(@normative = 'true')]//bibitem")
|
84
|
-
.each do |b|
|
85
|
-
ret[b["anchor"]] = { bib: b, norm: false }
|
86
|
-
end
|
87
|
-
ret
|
88
|
-
end
|
89
|
-
|
90
|
-
# ISO/IEC DIR 2, 10.4
|
91
|
-
def locality_erefs_validate(root)
|
92
|
-
root.xpath("//eref[descendant::locality]").each do |t|
|
93
|
-
if /^(ISO|IEC)/.match?(t["citeas"]) &&
|
94
|
-
!/: ?(\d+{4}|–)$/.match?(t["citeas"])
|
95
|
-
@log.add("Style", t,
|
96
|
-
"undated reference #{t['citeas']} should not contain " \
|
97
|
-
"specific elements")
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
33
|
def termdef_warn(text, regex, elem, term, msg)
|
103
34
|
regex.match(text) && @log.add("Style", elem, "#{term}: #{msg}")
|
104
35
|
end
|
105
36
|
|
106
|
-
# https://www.iso.org/ISO-house-style.html#iso-hs-s-text-r-r-ref_clause3
|
107
|
-
def term_xrefs_validate(xmldoc)
|
108
|
-
termids = xmldoc
|
109
|
-
.xpath("//sections/terms | //sections/clause[.//terms] | " \
|
110
|
-
"//annex[.//terms]").each_with_object({}) do |t, m|
|
111
|
-
t.xpath(".//*/@anchor").each { |a| m[a.text] = true }
|
112
|
-
t.xpath(".//*/@id").each { |a| m[a.text] = true }
|
113
|
-
t.name == "terms" and m[t["anchor"] || t["id"]] = true
|
114
|
-
end
|
115
|
-
xmldoc.xpath(".//xref").each do |x|
|
116
|
-
term_xrefs_validate1(x, termids)
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
def term_xrefs_validate1(xref, termids)
|
121
|
-
closest_id = xref.xpath("./ancestor::*[@id]")&.last or return
|
122
|
-
termids[xref["target"]] && !termids[closest_id["id"]] and
|
123
|
-
@log.add("Style", xref,
|
124
|
-
"only terms clauses can cross-reference terms clause " \
|
125
|
-
"(#{xref['target']})")
|
126
|
-
!termids[xref["target"]] && termids[closest_id["id"]] and
|
127
|
-
@log.add("Style", xref,
|
128
|
-
"non-terms clauses cannot cross-reference terms clause " \
|
129
|
-
"(#{xref['target']})")
|
130
|
-
end
|
131
|
-
|
132
|
-
# require that all assets of a particular type be cross-referenced
|
133
|
-
# within the document
|
134
|
-
def xrefs_mandate_validate(xmldoc)
|
135
|
-
xrefs_mandate_validate1(xmldoc, "//annex", "Annex")
|
136
|
-
xrefs_mandate_validate1(xmldoc, "//table", "Table")
|
137
|
-
xrefs_mandate_validate1(xmldoc, "//figure", "Figure")
|
138
|
-
xrefs_mandate_validate1(xmldoc, "//formula", "Formula")
|
139
|
-
end
|
140
|
-
|
141
|
-
def xrefs_mandate_validate1(xmldoc, xpath, name)
|
142
|
-
exc = %w(table note example figure).map { |x| "//#{x}#{xpath}" }
|
143
|
-
.join(" | ")
|
144
|
-
(xmldoc.xpath(xpath) - xmldoc.xpath(exc)).each do |x|
|
145
|
-
x["unnumbered"] == "true" and next
|
146
|
-
@doc_xrefs[x["anchor"]] or
|
147
|
-
@log.add("Style", x, "#{name} #{x['anchor']} has not been " \
|
148
|
-
"cross-referenced within document",
|
149
|
-
severity: xpath == "//formula" ? 2 : 1)
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
37
|
# ISO/IEC DIR 2, 16.5.6
|
154
38
|
def termdef_style(xmldoc)
|
155
39
|
xmldoc.xpath("//term").each do |t|
|
@@ -185,6 +69,22 @@ module Metanorma
|
|
185
69
|
iteration_validate(doc)
|
186
70
|
end
|
187
71
|
|
72
|
+
# DRG directives 3.7; but anticipated by standoc
|
73
|
+
def subfigure_validate(xmldoc)
|
74
|
+
elems = { footnote: "fn", note: "note", key: "dl" }
|
75
|
+
xmldoc.xpath("//figure//figure").each do |f|
|
76
|
+
elems.each do |k, v|
|
77
|
+
f.xpath(".//#{v}").each do |n|
|
78
|
+
@log.add("Style", n, "#{k} is not permitted in a subfigure")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def figure_validate(xmldoc)
|
85
|
+
subfigure_validate(xmldoc)
|
86
|
+
end
|
87
|
+
|
188
88
|
def content_validate(doc)
|
189
89
|
super
|
190
90
|
root = doc.root
|
@@ -203,14 +103,6 @@ module Metanorma
|
|
203
103
|
list_punctuation(doc)
|
204
104
|
end
|
205
105
|
|
206
|
-
def iso_xref_validate(doc)
|
207
|
-
see_xrefs_validate(doc)
|
208
|
-
term_xrefs_validate(doc)
|
209
|
-
xrefs_mandate_validate(doc)
|
210
|
-
see_erefs_validate(doc)
|
211
|
-
locality_erefs_validate(doc)
|
212
|
-
end
|
213
|
-
|
214
106
|
def bibitem_validate(xmldoc)
|
215
107
|
xmldoc.xpath("//bibitem[date/on = '–']").each do |b|
|
216
108
|
b.at("./note[@type = 'Unpublished-Status']") or
|
@@ -0,0 +1,128 @@
|
|
1
|
+
module Metanorma
|
2
|
+
module Iso
|
3
|
+
class Converter < Standoc::Converter
|
4
|
+
# https://www.iso.org/ISO-house-style.html#iso-hs-s-text-r-s-quantity
|
5
|
+
def style_subscript(node)
|
6
|
+
style_subscript_proper(node)
|
7
|
+
style_subscript_mathml(node)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Check HTML subscripts - only topmost level subs (no sub ancestors)
|
11
|
+
def style_subscript_proper(node)
|
12
|
+
node.xpath(".//sub[not(ancestor::sub)]").each do |x|
|
13
|
+
depth = calculate_subscript_depth(x)
|
14
|
+
depth < 2 and next # No warning for single level subscripts
|
15
|
+
if [2, 3].include?(depth)
|
16
|
+
style_warning(node, "may contain nested subscripts", x.to_xml)
|
17
|
+
else # depth >= 3
|
18
|
+
style_warning(node, "no more than 3 levels of subscript nesting allowed",
|
19
|
+
x.to_xml)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Check MathML subscripts - only topmost level msubs (no msub ancestors)
|
25
|
+
def style_subscript_mathml(node)
|
26
|
+
node.xpath(".//m:msub[not(ancestor::m:msub)]",
|
27
|
+
"m" => MATHML_NS).each do |x|
|
28
|
+
depth = calculate_mathml_subscript_depth(x)
|
29
|
+
depth < 2 and next # No warning for single level subscripts
|
30
|
+
if [2, 3].include?(depth)
|
31
|
+
style_warning(node, "may contain nested subscripts", x.to_xml)
|
32
|
+
else # depth > 3
|
33
|
+
style_warning(node, "no more than 3 levels of subscript nesting allowed",
|
34
|
+
x.to_xml)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# ISO/IEC DIR 2, 9.1
|
40
|
+
# ISO/IEC DIR 2, Table B.1
|
41
|
+
# https://www.iso.org/ISO-house-style.html#iso-hs-s-text-r-n-numbers
|
42
|
+
def style_number(node, text)
|
43
|
+
style_number_grouping(node, text)
|
44
|
+
style_regex(/(?:^|\p{Zs})(?<num>[0-9]+\.[0-9]+)(?!\.[0-9])/i,
|
45
|
+
"possible decimal point: mark up numbers with stem:[]", node, text)
|
46
|
+
@lang == "en" and style_regex(/\b(?<num>billions?)\b/i,
|
47
|
+
"ambiguous number", node, text)
|
48
|
+
style_regex(/(?:^|\p{Zs})(?<num>-[0-9][0-9,.]*)/i,
|
49
|
+
"hyphen instead of minus sign U+2212", node, text)
|
50
|
+
@novalid_number = true
|
51
|
+
end
|
52
|
+
|
53
|
+
def style_number_grouping(node, text)
|
54
|
+
if @validate_years
|
55
|
+
style_two_regex_not_prev(
|
56
|
+
node, text, /^(?<num>-?[0-9]{4,}[,0-9]*)\Z/,
|
57
|
+
%r{\b(ISO|IEC|IEEE|(in|January|February|March|April|May|June|August|September|October|November|December)\b)\Z},
|
58
|
+
"number not broken up in threes: mark up numbers with stem:[]"
|
59
|
+
)
|
60
|
+
else
|
61
|
+
style_two_regex_not_prev(
|
62
|
+
node, text, /^(?<num>-?(?:[0-9]{5,}[,0-9]*|[03-9]\d\d\d|1[0-8]\d\d|2[1-9]\d\d|20[5-9]\d))\Z/,
|
63
|
+
%r{\b(ISO|IEC|IEEE|\b)\Z},
|
64
|
+
"number not broken up in threes: mark up numbers with stem:[]"
|
65
|
+
)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# ISO/IEC DIR 2, 9.2.1
|
70
|
+
def style_percent(node, text)
|
71
|
+
style_regex(/\b(?<num>[0-9.,]+%)/,
|
72
|
+
"no space before percent sign", node, text)
|
73
|
+
style_regex(/\b(?<num>[0-9.,]+ \u00b1 [0-9,.]+ %)/,
|
74
|
+
"unbracketed tolerance before percent sign", node, text)
|
75
|
+
end
|
76
|
+
|
77
|
+
# leaving out as problematic: N J K C S T H h d B o E
|
78
|
+
SI_UNIT = "(m|cm|mm|km|μm|nm|g|kg|mgmol|cd|rad|sr|Hz|Hz|MHz|Pa|hPa|kJ|" \
|
79
|
+
"V|kV|W|MW|kW|F|μF|Ω|Wb|°C|lm|lx|Bq|Gy|Sv|kat|l|t|eV|u|Np|Bd|" \
|
80
|
+
"bit|kB|MB|Hart|nat|Sh|var)".freeze
|
81
|
+
|
82
|
+
# ISO/IEC DIR 2, 9.3
|
83
|
+
def style_units(node, text)
|
84
|
+
style_regex(/\b(?<num>[0-9][0-9,]*\p{Zs}+[\u00b0\u2032\u2033])/,
|
85
|
+
"space between number and degrees/minutes/seconds",
|
86
|
+
node, text)
|
87
|
+
style_regex(/\b(?<num>[0-9][0-9,]*#{SI_UNIT})\b/o,
|
88
|
+
"no space between number and SI unit", node, text)
|
89
|
+
style_non_std_units(node, text)
|
90
|
+
end
|
91
|
+
|
92
|
+
NONSTD_UNITS = {
|
93
|
+
sec: "s", mins: "min", hrs: "h", hr: "h", cc: "cm^3",
|
94
|
+
lit: "l", amp: "A", amps: "A", rpm: "r/min"
|
95
|
+
}.freeze
|
96
|
+
|
97
|
+
# ISO/IEC DIR 2, 9.3
|
98
|
+
def style_non_std_units(node, text)
|
99
|
+
NONSTD_UNITS.each do |k, v|
|
100
|
+
style_regex(/\b(?<num>[0-9][0-9,]*\p{Zs}+#{k})\b/,
|
101
|
+
"non-standard unit (should be #{v})", node, text)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def calculate_subscript_depth(sub_element)
|
108
|
+
sub_element.xpath(".//sub").empty? and return 1
|
109
|
+
max_depth = 1
|
110
|
+
sub_element.xpath(".//sub").each do |nested_sub|
|
111
|
+
depth = 1 + calculate_subscript_depth(nested_sub)
|
112
|
+
max_depth = [max_depth, depth].max
|
113
|
+
end
|
114
|
+
max_depth
|
115
|
+
end
|
116
|
+
|
117
|
+
def calculate_mathml_subscript_depth(msub_element)
|
118
|
+
msub_element.xpath(".//m:msub", "m" => MATHML_NS).empty? and return 1
|
119
|
+
max_depth = 1
|
120
|
+
msub_element.xpath(".//m:msub", "m" => MATHML_NS).each do |nested_msub|
|
121
|
+
depth = 1 + calculate_mathml_subscript_depth(nested_msub)
|
122
|
+
max_depth = [max_depth, depth].max
|
123
|
+
end
|
124
|
+
max_depth
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|