metanorma-iec 1.4.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +4 -32
  3. data/.gitignore +14 -0
  4. data/Gemfile +6 -0
  5. data/Rakefile +1 -1
  6. data/lib/isodoc/iec/base_convert.rb +25 -59
  7. data/lib/isodoc/iec/html/htmlstyle.css +38 -6
  8. data/lib/isodoc/iec/html/htmlstyle.scss +35 -6
  9. data/lib/isodoc/iec/html/isodoc.css +1 -2
  10. data/lib/isodoc/iec/html/isodoc.scss +1 -2
  11. data/lib/isodoc/iec/html/scripts.html +0 -1
  12. data/lib/isodoc/iec/html/wordstyle.css +13 -11
  13. data/lib/isodoc/iec/html/wordstyle.scss +13 -11
  14. data/lib/isodoc/iec/html_convert.rb +2 -1
  15. data/lib/isodoc/iec/iec.international-standard.xsl +724 -330
  16. data/lib/isodoc/iec/presentation_xml_convert.rb +193 -5
  17. data/lib/isodoc/iec/xref.rb +9 -8
  18. data/lib/{asciidoctor → metanorma}/iec/basicdoc.rng +0 -0
  19. data/lib/{asciidoctor → metanorma}/iec/biblio.rng +0 -0
  20. data/lib/metanorma/iec/converter.rb +143 -0
  21. data/lib/{asciidoctor → metanorma}/iec/front.rb +3 -4
  22. data/lib/{asciidoctor → metanorma}/iec/iec.rng +48 -0
  23. data/lib/{asciidoctor → metanorma}/iec/iec_intro_en.xml +0 -0
  24. data/lib/{asciidoctor → metanorma}/iec/iec_intro_fr.xml +0 -0
  25. data/lib/{asciidoctor → metanorma}/iec/isodoc.rng +90 -18
  26. data/lib/{asciidoctor → metanorma}/iec/isostandard.rng +14 -0
  27. data/lib/metanorma/iec/processor.rb +15 -8
  28. data/lib/{asciidoctor → metanorma}/iec/reqt.rng +0 -0
  29. data/lib/metanorma/iec/version.rb +1 -1
  30. data/lib/metanorma-iec.rb +1 -1
  31. data/metanorma-iec.gemspec +3 -3
  32. data/spec/isodoc/iev_spec.rb +462 -120
  33. data/spec/isodoc/postproc_spec.rb +2 -5
  34. data/spec/isodoc/ref_spec.rb +359 -353
  35. data/spec/isodoc/terms_spec.rb +183 -181
  36. data/spec/{asciidoctor → metanorma}/base_spec.rb +1 -5
  37. data/spec/{asciidoctor → metanorma}/blocks_spec.rb +1 -1
  38. data/spec/metanorma/cleanup_spec.rb +374 -0
  39. data/spec/metanorma/iev_spec.rb +248 -0
  40. data/spec/{asciidoctor → metanorma}/inline_spec.rb +1 -1
  41. data/spec/{asciidoctor → metanorma}/lists_spec.rb +1 -1
  42. data/spec/metanorma/processor_spec.rb +139 -44
  43. data/spec/{asciidoctor → metanorma}/section_spec.rb +1 -1
  44. data/spec/{asciidoctor → metanorma}/validate_spec.rb +1 -1
  45. data/spec/spec_helper.rb +12 -14
  46. metadata +26 -26
  47. data/lib/asciidoctor/iec/converter.rb +0 -105
  48. data/spec/asciidoctor/cleanup_spec.rb +0 -345
  49. data/spec/asciidoctor/iev_spec.rb +0 -243
@@ -4,6 +4,14 @@ require "isodoc"
4
4
  module IsoDoc
5
5
  module Iec
6
6
  class PresentationXMLConvert < IsoDoc::Iso::PresentationXMLConvert
7
+ def i18n_init(lang, script, i18nyaml = nil)
8
+ super
9
+ @i18n_lg = {}
10
+ @i18n_lg["en"] = I18n.new("en", "Latn", i18nyaml || @i18nyaml)
11
+ @i18n_lg["fr"] = I18n.new("fr", "Latn", i18nyaml || @i18nyaml)
12
+ @i18n_lg["default"] = @i18n
13
+ end
14
+
7
15
  def clause(docxml)
8
16
  docxml.xpath(ns("//clause[not(ancestor::annex)] | "\
9
17
  "//definitions | //references | "\
@@ -29,16 +37,196 @@ module IsoDoc
29
37
  .call(elem)
30
38
  end
31
39
 
40
+ DICT_PATHS = { doctype_dict: "./ext/doctype", stage_dict: "./status/stage",
41
+ substage_dict: "./status/substage",
42
+ function_dict: "./ext/function",
43
+ horizontal_dict: "./ext/horizontal" }.freeze
44
+
32
45
  def bibdata_i18n(bib)
33
46
  fr = IsoDoc::Iec::I18n.new("fr", "Latn")
34
47
  en = IsoDoc::Iec::I18n.new("en", "Latn")
35
48
  [{ lang: "en", i18n: en }, { lang: "fr", i18n: fr }].each do |v|
36
- { doctype_dict: "./ext/doctype", stage_dict: "./status/stage",
37
- substage_dict: "./status/substage", function_dict: "./ext/function",
38
- horizontal_dict: "./ext/horizontal" }.each do |lbl, xpath|
39
- hash_translate(bib, v[:i18n].get[lbl.to_s], xpath, v[:lang])
40
- end
49
+ DICT_PATHS.each do |lbl, xpath|
50
+ hash_translate(bib, v[:i18n].get[lbl.to_s], xpath, v[:lang])
51
+ end
52
+ end
53
+ end
54
+
55
+ def concept(docxml)
56
+ @is_iev and concept_iev(docxml)
57
+ super
58
+ end
59
+
60
+ def concept_iev(docxml)
61
+ labels = @xrefs.get_anchors.each_with_object({}) do |(k, v), m|
62
+ m[v[:label]] = k
63
+ end
64
+ docpart = docxml&.at(ns("//bibdata/ext/structuredidentifier/"\
65
+ "project-number/@part"))&.text or return
66
+ docxml.xpath(ns("//termref[@base = 'IEV']")).each do |t|
67
+ concept_iev1(t, docpart, labels)
68
+ end
69
+ end
70
+
71
+ def concept_iev1(termref, docpart, labels)
72
+ /^#{docpart}-/.match?(termref["target"]) or return
73
+ newtarget = labels[termref["target"]] or return
74
+ termref.name = "xref"
75
+ termref.delete("base")
76
+ termref["target"] = newtarget
77
+ end
78
+
79
+ def terms(docxml)
80
+ otherlang_designations(docxml)
81
+ super
82
+ merge_fr_into_en_term(docxml)
83
+ end
84
+
85
+ def merge_fr_into_en_term(docxml)
86
+ return unless @is_iev
87
+
88
+ docxml.xpath(ns("//term[@language = 'en'][@tag]")).each do |en|
89
+ fr = docxml.at(ns("//term[@language = 'fr'][@tag = '#{en['tag']}']"))
90
+ merge_fr_into_en_term1(en, fr) if fr
91
+ end
92
+ @xrefs.parse docxml
93
+ docxml.xpath(ns("//term/name")).each(&:remove)
94
+ term(docxml)
95
+ end
96
+
97
+ def merge_fr_into_en_term1(en_term, fr_term)
98
+ dl = en_term&.at(ns("./dl[@type = 'other-lang']"))&.remove
99
+ en_term << fr_term.remove.children
100
+ en_term << dl if dl
101
+ en_term["language"] = "en,fr"
102
+ en_term.delete("tag")
103
+ end
104
+
105
+ def otherlang_designations(docxml)
106
+ return unless @is_iev
107
+
108
+ docxml.xpath(ns("//term")).each do |t|
109
+ otherlang_designations1(t, t["language"]&.split(/,/) || %w(en fr))
110
+ end
111
+ end
112
+
113
+ def extract_otherlang_designations(term, lgs)
114
+ term.xpath(ns(".//preferred/expression[@language]"))
115
+ .each_with_object([]) do |d, m|
116
+ lg = d["language"]
117
+ d.delete("language")
118
+ next if lgs.include?(lg)
119
+
120
+ p = d.parent
121
+ designation_annotate(p, d.at(ns("./name")))
122
+ m << { lang: lg, script: Metanorma::Utils.default_script(lg),
123
+ designation: l10n_recursive(p.remove, lg).to_xml.strip }
124
+ end
125
+ end
126
+
127
+ def l10n_recursive(xml, lang)
128
+ script = Metanorma::Utils.default_script(lang)
129
+ c = HTMLEntities.new
130
+ xml.traverse do |x|
131
+ next unless x.text?
132
+
133
+ text = c.encode(c.decode(x.text), :hexadecimal)
134
+ x.replace(cleanup_entities(l10n(text, lang, script), is_xml: false))
41
135
  end
136
+ xml
137
+ end
138
+
139
+ def merge_otherlang_designations(desgn)
140
+ h = desgn.each_with_object({}) do |e, m|
141
+ if m[e[:lang]]
142
+ m[e[:lang]][:designation] += e[:designation]
143
+ else m[e[:lang]] = e
144
+ end
145
+ end
146
+ h.keys.sort.each_with_object([]) { |k, m| m << h[k] }
147
+ end
148
+
149
+ def otherlang_designations1(term, lgs)
150
+ pr = merge_otherlang_designations(
151
+ extract_otherlang_designations(term, lgs),
152
+ )
153
+ return if pr.empty?
154
+
155
+ prefs = pr.map do |p|
156
+ "<dt>#{p[:lang]}</dt>"\
157
+ "<dd language='#{p[:lang]}' script='#{p[:script]}'>"\
158
+ "#{cleanup_entities(p[:designation])}</dd>"
159
+ end
160
+ term << "<dl type='other-lang'>#{prefs.join}</dl>"
161
+ end
162
+
163
+ def related(docxml)
164
+ docxml.xpath(ns("//term[related]")).each { |f| move_related(f) }
165
+ super
166
+ end
167
+
168
+ def move_related(term)
169
+ defn = term.at(ns("./definition")) or return
170
+ term.xpath(ns("./related")).reverse.each do |r|
171
+ defn.next = r.remove
172
+ end
173
+ end
174
+
175
+ def related1(node)
176
+ lg = node&.at("./ancestor::xmlns:term/@language")&.text
177
+ @i18n = @i18n_lg[lg] if lg && @i18n_lg[lg]
178
+ p = node.at(ns("./preferred"))
179
+ ref = node.at(ns("./xref | ./eref | ./termref"))
180
+ label = @i18n.relatedterms[node["type"]].upcase
181
+ node.replace(l10n("<p>#{label}: "\
182
+ "#{p.children.to_xml} (#{ref.to_xml})</p>"))
183
+ @i18n = @i18n_lg["default"]
184
+ end
185
+
186
+ def termsource_modification(node)
187
+ lg = node&.at("./ancestor::xmlns:term/@language")&.text
188
+ @i18n = @i18n_lg[lg] if lg && @i18n_lg[lg]
189
+ super
190
+ @i18n = @i18n_lg["default"]
191
+ end
192
+
193
+ def termsource1(node)
194
+ lg = node&.at("./ancestor::xmlns:term/@language")&.text
195
+ @i18n = @i18n_lg[lg] if lg && @i18n_lg[lg]
196
+ if @is_iev then termsource1_iev(node)
197
+ else super
198
+ end
199
+ @i18n = @i18n_lg["default"]
200
+ end
201
+
202
+ def termsource1_iev(elem)
203
+ while elem&.next_element&.name == "termsource"
204
+ elem << l10n("; #{elem.next_element.remove.children.to_xml}")
205
+ end
206
+ elem.children = l10n("#{@i18n.source}: #{elem.children.to_xml.strip}")
207
+ end
208
+
209
+ def termexample(docxml)
210
+ docxml.xpath(ns("//termexample")).each do |f|
211
+ termexample1(f)
212
+ end
213
+ end
214
+
215
+ def termexample1(elem)
216
+ lg = elem&.at("./ancestor::xmlns:term/@language")&.text
217
+ @i18n = @i18n_lg[lg] if lg && @i18n_lg[lg]
218
+ example1(elem)
219
+ @i18n = @i18n_lg["default"]
220
+ end
221
+
222
+ def termnote1(elem)
223
+ lg = elem&.at("./ancestor::xmlns:term/@language")&.text
224
+ @i18n = @i18n_lg[lg] if lg && @i18n_lg[lg]
225
+
226
+ val = @xrefs.anchor(elem["id"], :value) || "???"
227
+ lbl = @i18n.termnote.gsub(/%/, val)
228
+ prefix_name(elem, "", lower2cap(lbl), "name")
229
+ @i18n = @i18n_lg["default"]
42
230
  end
43
231
 
44
232
  include Init
@@ -16,6 +16,7 @@ module IsoDoc
16
16
  def initial_anchor_names(d)
17
17
  super
18
18
  return unless @is_iev
19
+
19
20
  terms_iev_names(d)
20
21
  middle_section_asset_names(d)
21
22
  termnote_anchor_names(d)
@@ -24,21 +25,21 @@ module IsoDoc
24
25
 
25
26
  def terms_iev_names(d)
26
27
  d.xpath(ns("//sections/clause/terms")).each_with_index do |t, i|
27
- num = "#{@iev_part}-%02d" % [i+1]
28
+ num = "#{@iev_part}-%02d" % [i + 1]
28
29
  @anchors[t["id"]] =
29
- { label: num, xref: l10n("#{@labels["section_iev"]}-#{num}"), level: 2,
30
- type: "clause" }
31
- t.xpath(ns("./term")).each_with_index do |c, i|
32
- num2 = "%02d" % [i+1]
30
+ { label: num, xref: l10n("#{@labels['section_iev']} #{num}"),
31
+ level: 2, type: "clause" }
32
+ t.xpath(ns("./term")).each_with_index do |c, j|
33
+ num2 = "%02d" % [j + 1]
33
34
  section_names1(c, "#{num}-#{num2}", 3)
34
35
  end
35
36
  end
36
37
  end
37
38
 
38
39
  def annex_name_lbl(clause, num)
39
- obl = l10n("(#{@labels["inform_annex"]})")
40
- obl = l10n("(#{@labels["norm_annex"]})") if clause["obligation"] == "normative"
41
- l10n("<strong>#{@labels["annex"]} #{num}</strong><br/>#{obl}")
40
+ obl = l10n("(#{@labels['inform_annex']})")
41
+ obl = l10n("(#{@labels['norm_annex']})") if clause["obligation"] == "normative"
42
+ l10n("<strong>#{@labels['annex']} #{num}</strong><br/>#{obl}")
42
43
  end
43
44
  end
44
45
  end
File without changes
File without changes
@@ -0,0 +1,143 @@
1
+ require "asciidoctor"
2
+ require "metanorma-iso"
3
+ require "metanorma/iso/converter"
4
+ require_relative "./front"
5
+
6
+ module Metanorma
7
+ module Iec
8
+ class Converter < ISO::Converter
9
+ XML_ROOT_TAG = "iec-standard".freeze
10
+ XML_NAMESPACE = "https://www.metanorma.org/ns/iec".freeze
11
+
12
+ register_for "iec"
13
+
14
+ def init(node)
15
+ super
16
+ if @is_iev = node.attr("docnumber") == "60050"
17
+ @vocab = true
18
+ node.set_attr("docsubtype", "vocabulary")
19
+ end
20
+ end
21
+
22
+ def boilerplate_file(x_orig)
23
+ lang = case x_orig&.at("//bibdata/language")&.text
24
+ when "fr" then "fr"
25
+ else
26
+ "en"
27
+ end
28
+ File.join(@libdir, "iec_intro_#{lang}.xml")
29
+ end
30
+
31
+ def doctype_validate(xmldoc)
32
+ doctype = xmldoc&.at("//bibdata/ext/doctype")&.text
33
+ %w(international-standard technical-specification technical-report
34
+ publicly-available-specification international-workshop-agreement
35
+ guide interpretation-sheet).include? doctype or
36
+ @log.add("Document Attributes", nil,
37
+ "#{doctype} is not a recognised document type")
38
+ if function = xmldoc&.at("//bibdata/ext/function")&.text
39
+ %w(emc quality-assurance safety environment).include? function or
40
+ @log.add("Document Attributes", nil,
41
+ "#{function} is not a recognised document function")
42
+ end
43
+ end
44
+
45
+ def validate(doc)
46
+ content_validate(doc)
47
+ schema_validate(formattedstr_strip(doc.dup),
48
+ File.join(File.dirname(__FILE__), "iec.rng"))
49
+ end
50
+
51
+ def html_converter(node)
52
+ if node.nil?
53
+ IsoDoc::Iec::HtmlConvert.new({})
54
+ else
55
+ IsoDoc::Iec::HtmlConvert.new(html_extract_attributes(node))
56
+ end
57
+ end
58
+
59
+ def doc_converter(node)
60
+ if node.nil?
61
+ IsoDoc::Iec::WordConvert.new({})
62
+ else
63
+ IsoDoc::Iec::WordConvert.new(doc_extract_attributes(node))
64
+ end
65
+ end
66
+
67
+ def pdf_converter(node)
68
+ return if node.attr("no-pdf")
69
+
70
+ if node.nil?
71
+ IsoDoc::Iec::PdfConvert.new({})
72
+ else
73
+ IsoDoc::Iec::PdfConvert.new(pdf_extract_attributes(node))
74
+ end
75
+ end
76
+
77
+ def presentation_xml_converter(node)
78
+ if node.nil?
79
+ IsoDoc::Iec::PresentationXMLConvert.new({})
80
+ else
81
+ IsoDoc::Iec::PresentationXMLConvert.new(doc_extract_attributes(node))
82
+ end
83
+ end
84
+
85
+ def norm_ref_preface(node)
86
+ return super unless @is_iev
87
+
88
+ node.at("./title").next =
89
+ "<p>#{@i18n.norm_empty_pref}</p>"
90
+ end
91
+
92
+ def term_defs_boilerplate(div, source, term, preface, isodoc)
93
+ return super unless @is_iev
94
+ end
95
+
96
+ def sections_names_cleanup(xml)
97
+ super
98
+ @is_iev and replace_title(xml, "//introduction",
99
+ @i18n&.introduction_iev)
100
+ end
101
+
102
+ def note(note)
103
+ if note.title == "Note from TC/SC Officers"
104
+ noko do |xml|
105
+ xml.tc_sc_officers_note do |c|
106
+ wrap_in_para(note, c)
107
+ end
108
+ end.join("\n")
109
+ else
110
+ super
111
+ end
112
+ end
113
+
114
+ def note_cleanup(xmldoc)
115
+ super
116
+ n = xmldoc.at("//tc-sc-officers-note") and
117
+ xmldoc.at("//bibdata/ext").add_child(n.remove)
118
+ end
119
+
120
+ def image_name_validate(xmldoc); end
121
+
122
+ def toc_cleanup(xmldoc)
123
+ toc_iev_cleanup(xmldoc) if @is_iev
124
+ super
125
+ end
126
+
127
+ def toc_iev_cleanup(xmldoc)
128
+ iev_variant_titles(xmldoc)
129
+ end
130
+
131
+ def iev_variant_titles(xmldoc)
132
+ id = xmldoc&.at("//bibdata/docidentifier[@type = 'ISO']")&.text
133
+ m = /60050-(\d+)/.match(id) or return
134
+ xmldoc.xpath("//sections/clause/terms/title").each_with_index do |t, i|
135
+ num = "%02d" % [i + 1]
136
+ t.next = "<variant-title type='toc'>"\
137
+ "#{@i18n.section_iev} #{m[1]}-#{num} &#x2013; "\
138
+ "#{t.children.to_xml}</variant-title>"
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
@@ -1,4 +1,4 @@
1
- module Asciidoctor
1
+ module Metanorma
2
2
  module Iec
3
3
  class Converter < ISO::Converter
4
4
  def metadata_author(node, xml)
@@ -199,9 +199,8 @@ module Asciidoctor
199
199
  end
200
200
  end
201
201
 
202
- def metadata_doctype(node, xml)
203
- xml.doctype doctype(node)
204
- xml.horizontal (node.attr("horizontal") || "false")
202
+ def metadata_subdoctype(node, xml)
203
+ super
205
204
  a = node.attr("function") and xml.function a
206
205
  end
207
206
 
@@ -57,6 +57,54 @@
57
57
  <ref name="tc-sc-officers-note"/>
58
58
  </optional>
59
59
  </define>
60
+ <define name="term">
61
+ <element name="term">
62
+ <optional>
63
+ <attribute name="id">
64
+ <data type="ID"/>
65
+ </attribute>
66
+ </optional>
67
+ <optional>
68
+ <attribute name="language"/>
69
+ </optional>
70
+ <optional>
71
+ <attribute name="script"/>
72
+ </optional>
73
+ <optional>
74
+ <attribute name="tag"/>
75
+ </optional>
76
+ <optional>
77
+ <attribute name="multilingual-rendering">
78
+ <ref name="MultilingualRenderingType"/>
79
+ </attribute>
80
+ </optional>
81
+ <oneOrMore>
82
+ <ref name="preferred"/>
83
+ </oneOrMore>
84
+ <zeroOrMore>
85
+ <ref name="admitted"/>
86
+ </zeroOrMore>
87
+ <zeroOrMore>
88
+ <ref name="deprecates"/>
89
+ </zeroOrMore>
90
+ <optional>
91
+ <ref name="termdomain"/>
92
+ </optional>
93
+ <ref name="termdefinition"/>
94
+ <zeroOrMore>
95
+ <ref name="termnote"/>
96
+ </zeroOrMore>
97
+ <zeroOrMore>
98
+ <ref name="termexample"/>
99
+ </zeroOrMore>
100
+ <zeroOrMore>
101
+ <ref name="termsource"/>
102
+ </zeroOrMore>
103
+ <zeroOrMore>
104
+ <ref name="term"/>
105
+ </zeroOrMore>
106
+ </element>
107
+ </define>
60
108
  </include>
61
109
  <!-- end overrides -->
62
110
  <define name="function">
File without changes
File without changes