metanorma-iec 1.0.3 → 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/macos.yml +8 -7
  3. data/.github/workflows/ubuntu.yml +12 -9
  4. data/.github/workflows/windows.yml +8 -8
  5. data/lib/asciidoctor/iec/biblio.rng +142 -37
  6. data/lib/asciidoctor/iec/converter.rb +22 -130
  7. data/lib/asciidoctor/iec/front.rb +220 -0
  8. data/lib/asciidoctor/iec/isodoc.rng +48 -2
  9. data/lib/asciidoctor/iec/isostandard.rng +17 -1
  10. data/lib/isodoc/iec/base_convert.rb +157 -0
  11. data/lib/isodoc/iec/html/htmlstyle.scss +11 -8
  12. data/lib/isodoc/iec/html/isodoc.scss +15 -9
  13. data/lib/isodoc/iec/html/scripts.html +23 -21
  14. data/lib/isodoc/iec/html/wordstyle.scss +0 -3
  15. data/lib/isodoc/iec/html_convert.rb +8 -0
  16. data/lib/isodoc/iec/i18n-en.yaml +2 -0
  17. data/lib/isodoc/iec/i18n-fr.yaml +2 -0
  18. data/lib/isodoc/iec/iec.international-standard.xsl +4133 -0
  19. data/lib/isodoc/iec/metadata.rb +3 -52
  20. data/lib/isodoc/iec/pdf_convert.rb +31 -0
  21. data/lib/isodoc/iec/word_convert.rb +17 -6
  22. data/lib/metanorma-iec.rb +1 -0
  23. data/lib/metanorma/iec/processor.rb +12 -1
  24. data/lib/metanorma/iec/version.rb +1 -1
  25. data/spec/asciidoctor-iec/base_spec.rb +20 -29
  26. data/spec/asciidoctor-iec/blocks_spec.rb +15 -7
  27. data/spec/asciidoctor-iec/cleanup_spec.rb +13 -7
  28. data/spec/asciidoctor-iec/iev_spec.rb +161 -0
  29. data/spec/asciidoctor-iec/inline_spec.rb +2 -1
  30. data/spec/asciidoctor-iec/section_spec.rb +8 -8
  31. data/spec/assets/iso.xml +65 -2
  32. data/spec/examples/rice.html +5 -5
  33. data/spec/examples/rice_img/rice_image1.png +0 -0
  34. data/spec/examples/rice_img/rice_image2.png +0 -0
  35. data/spec/examples/rice_img/rice_image3_1.png +0 -0
  36. data/spec/examples/rice_img/rice_image3_2.png +0 -0
  37. data/spec/examples/rice_img/rice_image3_3.png +0 -0
  38. data/spec/isodoc/blocks_spec.rb +160 -0
  39. data/spec/isodoc/i18n_spec.rb +15 -22
  40. data/spec/isodoc/iev_spec.rb +360 -0
  41. data/spec/isodoc/inline_spec.rb +2 -2
  42. data/spec/isodoc/iso_spec.rb +2 -19
  43. data/spec/isodoc/metadata_spec.rb +92 -9
  44. data/spec/isodoc/postproc_spec.rb +8 -2
  45. data/spec/isodoc/ref_spec.rb +249 -0
  46. data/spec/isodoc/section_spec.rb +49 -14
  47. data/spec/isodoc/terms_spec.rb +2 -2
  48. data/spec/metanorma/processor_spec.rb +3 -3
  49. data/spec/spec_helper.rb +3 -2
  50. metadata +14 -2
@@ -0,0 +1,220 @@
1
+ module Asciidoctor
2
+ module Iec
3
+ class Converter < ISO::Converter
4
+ def metadata_author(node, xml)
5
+ publishers = node.attr("publisher") || "IEC"
6
+ publishers.split(/,[ ]?/).each do |p|
7
+ xml.contributor do |c|
8
+ c.role **{ type: "author" }
9
+ c.organization { |a| organization(a, p) }
10
+ end
11
+ end
12
+ end
13
+
14
+ def metadata_publisher(node, xml)
15
+ publishers = node.attr("publisher") || "IEC"
16
+ publishers.split(/,[ ]?/).each do |p|
17
+ xml.contributor do |c|
18
+ c.role **{ type: "publisher" }
19
+ c.organization { |a| organization(a, p) }
20
+ end
21
+ end
22
+ end
23
+
24
+ def metadata_copyright(node, xml)
25
+ publishers = node.attr("publisher") || "IEC"
26
+ publishers.split(/,[ ]?/).each do |p|
27
+ xml.copyright do |c|
28
+ c.from (node.attr("copyright-year") || Date.today.year)
29
+ c.owner do |owner|
30
+ owner.organization { |o| organization(o, p) }
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ def iso_id(node, xml)
37
+ return unless node.attr("docnumber")
38
+ part, subpart = node&.attr("partnumber")&.split(/-/)
39
+ dn = add_id_parts(node.attr("docnumber"), part, subpart)
40
+ dn = id_stage_prefix(dn, node, false)
41
+ dn = id_edition_suffix(dn, node)
42
+ xml.docidentifier dn, **attr_code(type: "iso")
43
+ end
44
+
45
+ def id_edition_suffix(dn, node)
46
+ ed = node.attr("edition") || 1
47
+ dn += " ED #{ed}"
48
+ dn
49
+ end
50
+
51
+ STAGE_CODES = {
52
+ "PNW" => "1000",
53
+ "ANW" => "2000",
54
+ "CAN" => "2098",
55
+ "ACD" => "2099",
56
+ "CD" => "3020",
57
+ "BWG" => "3092",
58
+ "A2CD" => "3099",
59
+ "2CD" => "3520",
60
+ "3CD" => "3520",
61
+ "4CD" => "3520",
62
+ "5CD" => "3520",
63
+ "6CD" => "3520",
64
+ "7CD" => "3520",
65
+ "8CD" => "3520",
66
+ "9CD" => "3520",
67
+ "CDM" => "3591",
68
+ "A3CD" => "3592",
69
+ "A4CD" => "3592",
70
+ "A5CD" => "3592",
71
+ "A6CD" => "3592",
72
+ "A7CD" => "3592",
73
+ "A8CD" => "3592",
74
+ "A9CD" => "3592",
75
+ "ACDV" => "3599",
76
+ "CCDV" => "4020",
77
+ "CDVM" => "4091",
78
+ "NCDV" => "4092",
79
+ "NADIS" => "4093",
80
+ "ADIS" => "4099",
81
+ "ADTR" => "4099",
82
+ "ADTS" => "4099",
83
+ "RDISH" => "5000",
84
+ "RFDIS" => "5000",
85
+ "CDISH" => "5020",
86
+ "CDPAS" => "5020",
87
+ "CDTR" => "5020",
88
+ "CDTS" => "5020",
89
+ "CFDIS" => "5020",
90
+ "DTRM" => "5092",
91
+ "DTSM" => "5092",
92
+ "NDTR" => "5092",
93
+ "NDTS" => "5092",
94
+ "NFDIS" => "5092",
95
+ "APUB" => "5099",
96
+ "BPUB" => "6000",
97
+ "PPUB" => "6060",
98
+ "RR" => "9092",
99
+ "AMW" => "9220",
100
+ "WPUB" => "9599",
101
+ "DELPUB" => "9960",
102
+ }.freeze
103
+
104
+ DOC_STAGE = {
105
+ "00": "PWI",
106
+ "10": "NWIP",
107
+ "20": "WD",
108
+ "30": "CD",
109
+ "40": "CDV",
110
+ "50": "FDIS",
111
+ "60": "PPUB",
112
+ "90": "RR",
113
+ "92": "AMW",
114
+ "95": "WPUB",
115
+ "99": "DELPUB",
116
+ }.freeze
117
+
118
+ STAGE_ABBRS = {
119
+ "00" => {"00" => "PWI"},
120
+ "10" => {"00" => "PNW"},
121
+ "20" => {"00" => "ANW", "98" => "CAN", "99" => "ACD"},
122
+ "30" => {"00" => "CD", "20" => "CD", "92" => "BWG", "97" => "MERGED", "98" => "DREJ", "99" => "A2CD"},
123
+ "35" => {"00" => "CD", "20" => "CD", "91" => "CDM", "92" => "ACD", "99" => "ACDV"},
124
+ "40" => {"00" => "CCDV", "20" => "CCDV", "91" => "CDVM", "92" => "NCDV", "93" => "NADIS", "95" => "ADISSB", "99" => "ADIS"},
125
+ "50" => {"00" => "RFDIS", "20" => "CFDIS", "92" => "NFDIS", "95" => "APUBSB", "99" => "APUB"},
126
+ "60" => {"00" => "BPUB", "60" => "PPUB"},
127
+ "90" => {"00" => "RR", "92" => "RR"},
128
+ "92" => {"00" => "AMW", "20" => "AMW"},
129
+ "95" => {"00" => "WPUB", "99" => "WPUB"},
130
+ "99" => {"00" => "DELPUB", "60" => "DELPUB"},
131
+ }.freeze
132
+
133
+ STAGE_NAMES = {
134
+ "00": "Preliminary work item",
135
+ "10": "New work item proposal",
136
+ "20": "Working draft",
137
+ "30": "Committee draft",
138
+ "35": "Committee draft",
139
+ "40": "Committed draft for vote",
140
+ "50": "Final draft international standard",
141
+ "60": "International standard",
142
+ "90": "Review",
143
+ "92": "Review",
144
+ "95": "Withdrawal",
145
+ "99": "Deleted",
146
+ }.freeze
147
+
148
+ def status_abbrev1(stage, substage, iter, doctype, draft)
149
+ return "" unless stage
150
+ abbr = STAGE_ABBRS.dig(stage, substage) || "??"
151
+ if stage == "35" && substage == "92"
152
+ iter = (iter.to_i + 1) % "02"
153
+ end
154
+ case doctype
155
+ when "technical-report"
156
+ stage = "ADTR" if stage == "40" && substage == "99"
157
+ stage = "CDTR" if stage == "50" && substage == "20"
158
+ stage = "DTRM" if stage == "50" && substage == "92"
159
+ when "technical-specification"
160
+ stage = "ADTS" if stage == "40" && substage == "99"
161
+ stage = "CDTS" if stage == "50" && substage == "20"
162
+ stage = "DTSM" if stage == "50" && substage == "92"
163
+ when "interpretation-sheet"
164
+ stage = "RDISH" if stage == "50" && substage == "00"
165
+ stage = "CDISH" if stage == "50" && substage == "20"
166
+ when "publicly-available-specification"
167
+ stage = "CDPAS" if stage == "50" && substage == "20"
168
+ end
169
+ abbr = abbr.sub(/CD$/, "#{iter}CD") if iter
170
+ abbr
171
+ end
172
+
173
+ def stage_abbr(stage, substage)
174
+ return "PPUB" if stage == "60"
175
+ DOC_STAGE[stage.to_sym] || "??"
176
+ end
177
+
178
+ def stage_name(stage, substage, _doctype, _iteration)
179
+ STAGE_NAMES[stage.to_sym]
180
+ end
181
+
182
+ def get_stage(node)
183
+ stage = node.attr("status") || node.attr("docstage") || "60"
184
+ m = /([0-9])CD$/.match(stage) and
185
+ node.set_attr("iteration", m[1])
186
+ STAGE_CODES[stage] and stage = STAGE_CODES[stage][0..1]
187
+ stage
188
+ end
189
+
190
+ def get_substage(node)
191
+ st = node.attr("status") || node.attr("docstage")
192
+ stage = get_stage(node)
193
+ node.attr("docsubstage") ||
194
+ ( stage == "60" ? "60" :
195
+ STAGE_CODES[st] ? STAGE_CODES[st][2..3] :
196
+ "00" )
197
+ end
198
+
199
+ def id_stage_abbr(stage, substage, node)
200
+ return "" if stage == "60"
201
+ abbr = DOC_STAGE[stage.to_sym] || ""
202
+ abbr = node.attr("iteration") + abbr if node.attr("iteration")
203
+ abbr
204
+ end
205
+
206
+ def metadata_status(node, xml)
207
+ stage = get_stage(node)
208
+ substage = get_substage(node)
209
+ xml.status do |s|
210
+ s.stage stage, **attr_code(abbreviation: stage_abbr(stage, substage))
211
+ s.substage substage,
212
+ **attr_code(abbreviation: status_abbrev1(stage, substage,
213
+ node.attr("iteration"),
214
+ doctype(node),node.attr("draft")))
215
+ node.attr("iteration") && (s.iteration node.attr("iteration"))
216
+ end
217
+ end
218
+ end
219
+ end
220
+ end
@@ -53,6 +53,14 @@
53
53
  <optional>
54
54
  <attribute name="alt"/>
55
55
  </optional>
56
+ <optional>
57
+ <attribute name="case">
58
+ <choice>
59
+ <value>capital</value>
60
+ <value>lowercase</value>
61
+ </choice>
62
+ </attribute>
63
+ </optional>
56
64
  <text/>
57
65
  </element>
58
66
  </define>
@@ -129,6 +137,9 @@
129
137
  </choice>
130
138
  </attribute>
131
139
  </optional>
140
+ <attribute name="normative">
141
+ <data type="boolean"/>
142
+ </attribute>
132
143
  <optional>
133
144
  <ref name="section-title"/>
134
145
  </optional>
@@ -305,6 +316,21 @@
305
316
  </define>
306
317
  </include>
307
318
  <!-- end overrides -->
319
+ <define name="TextElement" combine="choice">
320
+ <ref name="concept"/>
321
+ </define>
322
+ <define name="concept">
323
+ <element name="concept">
324
+ <optional>
325
+ <attribute name="term"/>
326
+ </optional>
327
+ <choice>
328
+ <ref name="eref"/>
329
+ <ref name="xref"/>
330
+ <ref name="termref"/>
331
+ </choice>
332
+ </element>
333
+ </define>
308
334
  <define name="BasicBlock" combine="choice">
309
335
  <choice>
310
336
  <ref name="requirement"/>
@@ -884,7 +910,15 @@
884
910
  <attribute name="id">
885
911
  <data type="ID"/>
886
912
  </attribute>
887
- <ref name="paragraph"/>
913
+ <oneOrMore>
914
+ <choice>
915
+ <ref name="paragraph"/>
916
+ <ref name="ul"/>
917
+ <ref name="ol"/>
918
+ <ref name="dl"/>
919
+ <ref name="formula"/>
920
+ </choice>
921
+ </oneOrMore>
888
922
  </element>
889
923
  </define>
890
924
  <define name="termexample">
@@ -911,7 +945,10 @@
911
945
  </define>
912
946
  <define name="origin">
913
947
  <element name="origin">
914
- <ref name="erefType"/>
948
+ <choice>
949
+ <ref name="erefType"/>
950
+ <ref name="termref"/>
951
+ </choice>
915
952
  </element>
916
953
  </define>
917
954
  <define name="modification">
@@ -919,6 +956,15 @@
919
956
  <ref name="paragraph"/>
920
957
  </element>
921
958
  </define>
959
+ <define name="termref">
960
+ <element name="termref">
961
+ <attribute name="base"/>
962
+ <attribute name="target"/>
963
+ <optional>
964
+ <text/>
965
+ </optional>
966
+ </element>
967
+ </define>
922
968
  <define name="structuredidentifier">
923
969
  <element name="structuredidentifier">
924
970
  <optional>
@@ -43,6 +43,9 @@
43
43
  <ref name="ics"/>
44
44
  </zeroOrMore>
45
45
  <ref name="structuredidentifier"/>
46
+ <optional>
47
+ <ref name="stagename"/>
48
+ </optional>
46
49
  </define>
47
50
  <define name="bdate">
48
51
  <element name="date">
@@ -88,6 +91,12 @@
88
91
  </define>
89
92
  <define name="sections">
90
93
  <element name="sections">
94
+ <zeroOrMore>
95
+ <choice>
96
+ <ref name="note"/>
97
+ <ref name="admonition"/>
98
+ </choice>
99
+ </zeroOrMore>
91
100
  <ref name="clause"/>
92
101
  <optional>
93
102
  <choice>
@@ -260,6 +269,8 @@
260
269
  <value>publicly-available-specification</value>
261
270
  <value>international-workshop-agreement</value>
262
271
  <value>guide</value>
272
+ <value>amendment</value>
273
+ <value>technical-corrigendum</value>
263
274
  </choice>
264
275
  </define>
265
276
  <define name="structuredidentifier">
@@ -507,8 +518,13 @@
507
518
  </attribute>
508
519
  </optional>
509
520
  <oneOrMore>
510
- <ref name="paragraph-with-footnote"/>
521
+ <ref name="BasicBlock"/>
511
522
  </oneOrMore>
512
523
  </element>
513
524
  </define>
525
+ <define name="stagename">
526
+ <element name="stagename">
527
+ <text/>
528
+ </element>
529
+ </define>
514
530
  </grammar>
@@ -72,6 +72,163 @@ module IsoDoc
72
72
  obl = l10n("(#{@norm_annex_lbl})") if clause["obligation"] == "normative"
73
73
  l10n("<b>#{@annex_lbl} #{num}</b><br/><br/>#{obl}")
74
74
  end
75
+
76
+ def convert1(docxml, filename, dir)
77
+ id = docxml&.at(ns("//bibdata/docnumber"))&.text
78
+ @is_iev = id == "60050"
79
+ id = docxml&.at(ns("//bibdata/docidentifier[@type = 'iso']"))&.text
80
+ m = /60050-(\d+)/.match(id) and @iev_part = m[1]
81
+ super
82
+ end
83
+
84
+ def introduction(isoxml, out)
85
+ return super unless @is_iev
86
+ f = isoxml.at(ns("//introduction")) || return
87
+ title_attr = { class: "IntroTitle" }
88
+ page_break(out)
89
+ out.div **{ class: "Section3", id: f["id"] } do |div|
90
+ clause_name(nil, @labels["introduction_iev"], div, title_attr)
91
+ f.elements.each do |e|
92
+ parse(e, div) unless e.name == "title"
93
+ end
94
+ end
95
+ end
96
+
97
+ def introduction_names(clause)
98
+ return super unless @is_iev
99
+ end
100
+
101
+ def bibliography(isoxml, out)
102
+ return super unless @is_iev
103
+ end
104
+
105
+ def biblio_list(f, div, biblio)
106
+ return super unless @is_iev
107
+ i = 0
108
+ f.children.each do |b|
109
+ parse(b, div) unless %w(title bibitem).include? b.name
110
+ end
111
+ end
112
+
113
+ def terms_parse(node, out)
114
+ return super unless @is_iev
115
+ page_break(out)
116
+ out.div **attr_code(id: node["id"]) do |div|
117
+ out.p(**{ class: "zzSTDTitle2" }) do |p|
118
+ p.b do |b|
119
+ b << "#{anchor(node['id'], :label)} "
120
+ node&.at(ns("./title"))&.children&.each { |c2| parse(c2, b) }
121
+ end
122
+ end
123
+ node.children.reject { |c1| c1.name == "title" }.each do |c1|
124
+ parse(c1, div)
125
+ end
126
+ end
127
+ end
128
+
129
+ def initial_anchor_names(d)
130
+ super
131
+ return unless @is_iev
132
+ terms_iev_names(d)
133
+ middle_section_asset_names(d)
134
+ termnote_anchor_names(d)
135
+ termexample_anchor_names(d)
136
+ end
137
+
138
+ def terms_iev_names(d)
139
+ d.xpath(ns("//sections/clause/terms")).each_with_index do |t, i|
140
+ num = "#{@iev_part}-%02d" % [i+1]
141
+ @anchors[t["id"]] =
142
+ { label: num, xref: l10n("#{@labels["section_iev"]}-#{num}"), level: 2,
143
+ type: "clause" }
144
+ t.xpath(ns("./term")).each_with_index do |c, i|
145
+ num2 = "%02d" % [i+1]
146
+ section_names1(c, "#{num}-#{num2}", 3)
147
+ end
148
+ end
149
+ end
150
+
151
+ def termref_cleanup(docxml)
152
+ return super unless @is_iev
153
+ docxml.
154
+ gsub(%r{\s*\[/TERMREF\]\s*</p>\s*<p>\s*\[TERMREF\]}, "; ").
155
+ gsub(/\[TERMREF\]\s*/, l10n("#{@source_lbl}: ")).
156
+ gsub(/\s*\[MODIFICATION\]\s*\[\/TERMREF\]/, l10n(", #{@modified_lbl} [/TERMREF]")).
157
+ gsub(/\s*\[\/TERMREF\]\s*/, l10n("")).
158
+ gsub(/\s*\[MODIFICATION\]/, l10n(", #{@modified_lbl} &mdash; "))
159
+ end
160
+
161
+ def set_termdomain(termdomain)
162
+ return super unless @is_iev
163
+ end
164
+
165
+ def term_suffix(node, out)
166
+ return unless @is_iev
167
+ domain = node&.at(ns("../domain"))&.text
168
+ return unless domain
169
+ out << ", &lt;#{domain}&gt;"
170
+ end
171
+
172
+ def deprecated_term_parse(node, out)
173
+ out.p **{ class: "DeprecatedTerms", style:"text-align:left;" } do |p|
174
+ p << l10n("#{@deprecated_lbl}: ")
175
+ node.children.each { |c| parse(c, p) }
176
+ term_suffix(node, p)
177
+ end
178
+ end
179
+
180
+ def admitted_term_parse(node, out)
181
+ out.p **{ class: "AltTerms", style:"text-align:left;" } do |p|
182
+ node.children.each { |c| parse(c, p) }
183
+ term_suffix(node, p)
184
+ end
185
+ end
186
+
187
+ def term_parse(node, out)
188
+ return super unless @is_iev
189
+ out.p **{ class: "Terms", style:"text-align:left;" } do |p|
190
+ node.children.each { |c| parse(c, p) }
191
+ term_suffix(node, p)
192
+ end
193
+ end
194
+
195
+ def admonition_parse(node, out)
196
+ type = node["type"]
197
+ name = admonition_name(node, type)
198
+ out.div **{ id: node["id"], class: admonition_class(node) } do |div|
199
+ node.first_element_child.name == "p" ?
200
+ admonition_p_parse(node, div, name) : admonition_parse1(node, div, name)
201
+ end
202
+ end
203
+
204
+ def admonition_parse1(node, div, name)
205
+ div.p do |p|
206
+ admonition_name_parse(node, p, name) if name
207
+ end
208
+ node.children.each { |n| parse(n, div) unless n.name == "name" }
209
+ end
210
+
211
+ def admonition_p_parse(node, div, name)
212
+ div.p do |p|
213
+ admonition_name_parse(node, p, name) if name
214
+ node.first_element_child.children.each { |n| parse(n, p) }
215
+ end
216
+ node.element_children[1..-1].each { |n| parse(n, div) }
217
+ end
218
+
219
+ def admonition_name_parse(_node, div, name)
220
+ name.children.each { |n| parse(n, div) }
221
+ div << " &mdash; "
222
+ end
223
+
224
+ def clause_parse_title(node, div, c1, out)
225
+ IsoDoc::Common.instance_method(:clause_parse_title).bind(self).call(node, div, c1, out)
226
+ end
227
+
228
+ def biblio_list(f, div, biblio)
229
+ biblio = false
230
+ super
231
+ end
75
232
  end
76
233
  end
77
234
  end