metanorma-iso 1.3.21 → 1.3.26

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 (64) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/macos.yml +8 -7
  3. data/.github/workflows/ubuntu.yml +8 -7
  4. data/.github/workflows/windows.yml +8 -8
  5. data/Gemfile +2 -0
  6. data/lib/asciidoctor/iso/base.rb +22 -0
  7. data/lib/asciidoctor/iso/biblio.rng +142 -37
  8. data/lib/asciidoctor/iso/cleanup.rb +19 -2
  9. data/lib/asciidoctor/iso/front.rb +19 -72
  10. data/lib/asciidoctor/iso/front_id.rb +196 -0
  11. data/lib/asciidoctor/iso/isodoc.rng +48 -2
  12. data/lib/asciidoctor/iso/isostandard-amd.rng +98 -0
  13. data/lib/asciidoctor/iso/isostandard.rng +17 -1
  14. data/lib/asciidoctor/iso/macros.rb +21 -0
  15. data/lib/asciidoctor/iso/section.rb +18 -32
  16. data/lib/asciidoctor/iso/term_lookup_cleanup.rb +87 -0
  17. data/lib/asciidoctor/iso/validate.rb +41 -21
  18. data/lib/asciidoctor/iso/validate_requirements.rb +1 -1
  19. data/lib/asciidoctor/iso/validate_section.rb +2 -2
  20. data/lib/asciidoctor/iso/validate_style.rb +7 -6
  21. data/lib/isodoc/iso/base_convert.rb +48 -64
  22. data/lib/isodoc/iso/html/header.html +10 -6
  23. data/lib/isodoc/iso/html/html_iso_titlepage.html +27 -18
  24. data/lib/isodoc/iso/html/isodoc.scss +49 -28
  25. data/lib/isodoc/iso/html/scripts.html +23 -21
  26. data/lib/isodoc/iso/html/style-human.scss +25 -2
  27. data/lib/isodoc/iso/html/style-iso.scss +20 -2
  28. data/lib/isodoc/iso/html/word_iso_titlepage.html +23 -2
  29. data/lib/isodoc/iso/html/wordstyle.scss +80 -39
  30. data/lib/isodoc/iso/html_convert.rb +7 -9
  31. data/lib/isodoc/iso/iso.amendment.xsl +4597 -0
  32. data/lib/isodoc/iso/iso.international-standard.xsl +4597 -0
  33. data/lib/isodoc/iso/metadata.rb +74 -44
  34. data/lib/isodoc/iso/pdf_convert.rb +39 -0
  35. data/lib/isodoc/iso/sections.rb +66 -0
  36. data/lib/isodoc/iso/sts_convert.rb +29 -0
  37. data/lib/metanorma-iso.rb +2 -0
  38. data/lib/metanorma/iso/processor.rb +16 -1
  39. data/lib/metanorma/iso/version.rb +1 -1
  40. data/metanorma-iso.gemspec +4 -1
  41. data/spec/asciidoctor-iso/amd_spec.rb +726 -0
  42. data/spec/asciidoctor-iso/base_spec.rb +43 -21
  43. data/spec/asciidoctor-iso/blocks_spec.rb +21 -9
  44. data/spec/asciidoctor-iso/cleanup_spec.rb +203 -175
  45. data/spec/asciidoctor-iso/inline_spec.rb +2 -1
  46. data/spec/asciidoctor-iso/macros_spec.rb +275 -0
  47. data/spec/asciidoctor-iso/refs_spec.rb +7 -4
  48. data/spec/asciidoctor-iso/section_spec.rb +8 -8
  49. data/spec/assets/iso.xml +64 -1
  50. data/spec/isodoc/amd_spec.rb +606 -0
  51. data/spec/isodoc/i18n_spec.rb +12 -20
  52. data/spec/isodoc/inline_spec.rb +2 -2
  53. data/spec/isodoc/iso_spec.rb +1 -1
  54. data/spec/isodoc/metadata_spec.rb +12 -4
  55. data/spec/isodoc/postproc_spec.rb +20 -119
  56. data/spec/isodoc/ref_spec.rb +5 -5
  57. data/spec/isodoc/section_spec.rb +36 -13
  58. data/spec/isodoc/table_spec.rb +22 -22
  59. data/spec/isodoc/terms_spec.rb +2 -2
  60. data/spec/isodoc/xref_spec.rb +19 -19
  61. data/spec/metanorma/processor_spec.rb +2 -2
  62. data/spec/spec_helper.rb +13 -1
  63. metadata +57 -5
  64. data/asciidoctor-iso.gemspec.old +0 -50
@@ -5,6 +5,7 @@ require "json"
5
5
  require "pathname"
6
6
  require "open-uri"
7
7
  require "pp"
8
+ require "asciidoctor/iso/term_lookup_cleanup"
8
9
 
9
10
  module Asciidoctor
10
11
  module ISO
@@ -13,12 +14,12 @@ module Asciidoctor
13
14
  "//clause[title = 'Scope']//fn".freeze
14
15
 
15
16
  NORMREF_FOOTNOTES =
16
- "//references[title = 'Normative References']//fn".freeze
17
+ "//references[@normative = 'true']//fn".freeze
17
18
 
18
19
  POST_NORMREF_FOOTNOTES =
19
20
  "//sections//clause[not(title = 'Scope')]//fn | "\
20
21
  "//annex//fn | "\
21
- "//references[title = 'Bibliography']//fn".freeze
22
+ "//references[@normative = 'false']//fn".freeze
22
23
 
23
24
  def other_footnote_renumber(xmldoc)
24
25
  seen = {}
@@ -35,6 +36,7 @@ module Asciidoctor
35
36
  end
36
37
 
37
38
  def id_prefix(prefix, id)
39
+ return id.text if @amd # we're just inheriting the prefixes from parent doc
38
40
  prefix.join("/") + ( id.text.match(%{^/}) ? "" : " " ) + id.text
39
41
  end
40
42
 
@@ -57,6 +59,8 @@ module Asciidoctor
57
59
  id.content = id_prefix(prefix, id)
58
60
  id = xmldoc.at("//bibdata/docidentifier[@type = 'iso-with-lang']") and
59
61
  id.content = id_prefix(prefix, id)
62
+ id = xmldoc.at("//bibdata/docidentifier[@type = 'iso-reference']") and
63
+ id.content = id_prefix(prefix, id)
60
64
  end
61
65
 
62
66
  def format_ref(ref, type, isopub)
@@ -86,6 +90,11 @@ module Asciidoctor
86
90
  end
87
91
  end
88
92
 
93
+ def termdef_cleanup(xmldoc)
94
+ Asciidoctor::ISO::TermLookupCleanup.new(xmldoc, @log).call
95
+ super
96
+ end
97
+
89
98
  # TODO sort by authors
90
99
  # sort by: doc class (ISO, IEC, other standard (not DOI &c), other
91
100
  # then standard class (docid class other than DOI &c)
@@ -108,6 +117,14 @@ module Asciidoctor
108
117
  "#{num.nil? ? abbrid : sprintf("%09d", num.to_i)} :: "\
109
118
  "#{partid} :: #{id&.text} :: #{title}"
110
119
  end
120
+
121
+ def sections_cleanup(x)
122
+ super
123
+ return unless @amd
124
+ x.xpath("//*[@inline-header]").each do |h|
125
+ h.delete('inline-header')
126
+ end
127
+ end
111
128
  end
112
129
  end
113
130
  end
@@ -5,74 +5,18 @@ require "json"
5
5
  require "pathname"
6
6
  require "open-uri"
7
7
  require "pp"
8
+ require_relative "front_id"
8
9
 
9
10
  module Asciidoctor
10
11
  module ISO
11
12
  class Converter < Standoc::Converter
12
- def metadata_id(node, xml)
13
- iso_id(node, xml)
14
- node&.attr("tc-docnumber")&.split(/,\s*/)&.each do |n|
15
- xml.docidentifier(n, **attr_code(type: "iso-tc"))
16
- end
17
- xml.docnumber node&.attr("docnumber")
18
- end
19
-
20
- def iso_id(node, xml)
21
- return unless node.attr("docnumber")
22
- part, subpart = node&.attr("partnumber")&.split(/-/)
23
- dn = add_id_parts(node.attr("docnumber"), part, subpart)
24
- dn = id_stage_prefix(dn, node)
25
- xml.docidentifier dn, **attr_code(type: "iso")
26
- xml.docidentifier id_langsuffix(dn, node), **attr_code(type: "iso-with-lang")
27
- end
28
-
29
- def id_langsuffix(dn, node)
30
- lang = node.attr("language") || "en"
31
- suffix = case lang
32
- when "en" then "(E)"
33
- when "fr" then "(F)"
34
- else
35
- "(X)"
36
- end
37
- "#{dn} #{suffix}"
38
- end
39
-
40
13
  def metadata_ext(node, xml)
41
14
  super
42
15
  structured_id(node, xml)
43
- end
44
-
45
- def structured_id(node, xml)
46
- return unless node.attr("docnumber")
47
- part, subpart = node&.attr("partnumber")&.split(/-/)
48
- xml.structuredidentifier do |i|
49
- i.project_number node.attr("docnumber"),
50
- **attr_code(part: part, subpart: subpart)
51
- end
52
- end
53
-
54
- def add_id_parts(dn, part, subpart)
55
- dn += "-#{part}" if part
56
- dn += "-#{subpart}" if subpart
57
- dn
58
- end
59
-
60
- def id_stage_abbr(stage, substage, node)
61
- IsoDoc::Iso::Metadata.new("en", "Latn", {}).
62
- status_abbrev(stage, substage, node.attr("iteration"),
63
- node.attr("draft"))
64
- end
65
-
66
- def id_stage_prefix(dn, node)
67
- stage = get_stage(node)
68
- substage = get_substage(node)
69
- if stage && (stage.to_i < 60 || stage.to_i == 60 && substage.to_i < 60)
70
- abbr = id_stage_abbr(stage, substage, node)
71
- dn = "/#{abbr} #{dn}" unless abbr.nil? || abbr.empty? # prefixes added in cleanup
72
- else
73
- dn += ":#{node.attr("copyright-year")}" if node.attr("copyright-year")
74
- end
75
- dn
16
+ xml.stagename stage_name(get_stage(node), get_substage(node),
17
+ node.attr("doctype"), node.attr("iteration"))
18
+ @amd && a = node.attr("updates-document-type") and
19
+ xml.updates_document_type a
76
20
  end
77
21
 
78
22
  def organization(org, orgname)
@@ -121,19 +65,12 @@ module Asciidoctor
121
65
  end
122
66
  end
123
67
 
124
- def get_stage(node)
125
- stage = node.attr("status") || node.attr("docstage") || "60"
126
- end
127
-
128
- def get_substage(node)
129
- stage = get_stage(node)
130
- node.attr("docsubstage") || ( stage == "60" ? "60" : "00" )
131
- end
132
-
133
68
  def metadata_status(node, xml)
69
+ stage = get_stage(node)
70
+ substage = get_substage(node)
134
71
  xml.status do |s|
135
- s.stage get_stage(node)
136
- s.substage get_substage(node)
72
+ s.stage stage, **attr_code(abbreviation: stage_abbr(stage, substage, node.attr("doctype")))
73
+ s.substage substage
137
74
  node.attr("iteration") && (s.iteration node.attr("iteration"))
138
75
  end
139
76
  end
@@ -167,12 +104,21 @@ module Asciidoctor
167
104
  end
168
105
  end
169
106
 
107
+ def title_amd(node, t, lang, at)
108
+ return unless node.attr("title-amendment-#{lang}")
109
+ t.title(**attr_code(at.merge(type: "title-amd"))) do |t1|
110
+ t1 << Asciidoctor::Standoc::Utils::asciidoc_sub(node.attr("title-amendment-#{lang}"))
111
+ end
112
+ end
113
+
170
114
  def title_full(node, t, lang, at)
171
115
  title = node.attr("title-main-#{lang}")
172
116
  intro = node.attr("title-intro-#{lang}")
173
117
  part = node.attr("title-part-#{lang}")
118
+ amd = node.attr("title-amendment-#{lang}")
174
119
  title = "#{intro} -- #{title}" if intro
175
120
  title = "#{title} -- #{part}" if part
121
+ title = "#{title} -- #{amd}" if amd && @amd
176
122
  t.title **attr_code(at.merge(type: "main")) do |t1|
177
123
  t1 << Asciidoctor::Standoc::Utils::asciidoc_sub(title)
178
124
  end
@@ -185,6 +131,7 @@ module Asciidoctor
185
131
  title_intro(node, xml, lang, at)
186
132
  title_main(node, xml, lang, at)
187
133
  title_part(node, xml, lang, at)
134
+ title_amd(node, xml, lang, at) if @amd
188
135
  end
189
136
  end
190
137
  end
@@ -0,0 +1,196 @@
1
+ require "date"
2
+ require "nokogiri"
3
+ require "htmlentities"
4
+ require "json"
5
+ require "pathname"
6
+ require "open-uri"
7
+ require "twitter_cldr"
8
+
9
+ module Asciidoctor
10
+ module ISO
11
+ class Converter < Standoc::Converter
12
+ STAGE_ABBRS = {
13
+ "00": "PWI",
14
+ "10": "NWIP",
15
+ "20": "WD",
16
+ "30": "CD",
17
+ "40": "DIS",
18
+ "50": "FDIS",
19
+ "60": "IS",
20
+ "90": "(Review)",
21
+ "95": "(Withdrawal)",
22
+ }.freeze
23
+
24
+ STAGE_NAMES = {
25
+ "00": "Preliminary work item",
26
+ "10": "New work item proposal",
27
+ "20": "Working draft",
28
+ "30": "Committee draft",
29
+ "40": "Draft",
30
+ "50": "Final draft",
31
+ "60": "International standard",
32
+ "90": "Review",
33
+ "95": "Withdrawal",
34
+ }.freeze
35
+
36
+ def stage_abbr(stage, substage, doctype)
37
+ return nil if stage.to_i > 60
38
+ ret = STAGE_ABBRS[stage.to_sym]
39
+ ret = "PRF" if stage == "60" && substage == "00"
40
+ if %w(amendment technical-corrigendum technical-report
41
+ technical-specification).include?(doctype)
42
+ ret = "NP" if stage == "10"
43
+ ret = "AWI" if stage == "10" && substage == "99"
44
+ ret = "D" if stage == "40" and doctype == "amendment"
45
+ ret = "FD" if stage == "50" and
46
+ %w(amendment technical-corrigendum).include?(doctype)
47
+ ret = "D" if stage == "50" and
48
+ %w(technical-report technical-specification).include?(doctype)
49
+ end
50
+ ret
51
+ end
52
+
53
+ def stage_name(stage, substage, doctype, iteration = nil)
54
+ return "Proof" if stage == "60" && substage == "00"
55
+ ret = STAGE_NAMES[stage.to_sym]
56
+ if iteration && %w(20 30).include?(stage)
57
+ prefix = iteration.to_i.localize(@lang.to_sym).
58
+ to_rbnf_s("SpelloutRules", "spellout-ordinal")
59
+ ret = "#{prefix.capitalize} #{ret.downcase}"
60
+ end
61
+ ret
62
+ end
63
+
64
+ def metadata_id(node, xml)
65
+ iso_id(node, xml)
66
+ node&.attr("tc-docnumber")&.split(/,\s*/)&.each do |n|
67
+ xml.docidentifier(n, **attr_code(type: "iso-tc"))
68
+ end
69
+ xml.docnumber node&.attr("docnumber")
70
+ end
71
+
72
+ def iso_id(node, xml)
73
+ return unless !@amd && node.attr("docnumber") ||
74
+ @amd && node.attr("updates")
75
+ dn = iso_id1(node)
76
+ dn1 = id_stage_prefix(dn, node, false)
77
+ dn2 = id_stage_prefix(dn, node, true)
78
+ xml.docidentifier dn1, **attr_code(type: "iso")
79
+ xml.docidentifier id_langsuffix(dn1, node),
80
+ **attr_code(type: "iso-with-lang")
81
+ xml.docidentifier id_langsuffix(dn2, node),
82
+ **attr_code(type: "iso-reference")
83
+ end
84
+
85
+ def iso_id1(node)
86
+ if @amd
87
+ dn = node.attr("updates")
88
+ return add_amd_parts(dn, node)
89
+ else
90
+ part, subpart = node&.attr("partnumber")&.split(/-/)
91
+ return add_id_parts(node.attr("docnumber"), part, subpart)
92
+ end
93
+ end
94
+
95
+ def add_amd_parts(dn, node)
96
+ a = node.attr("amendment-number")
97
+ c = node.attr("corrigendum-number")
98
+ case node.attr("doctype")
99
+ when "amendment"
100
+ "#{dn}/Amd #{node.attr('amendment-number')}"
101
+ when "technical-corrigendum"
102
+ "#{dn}/Cor.#{node.attr('corrigendum-number')}"
103
+ end
104
+ end
105
+
106
+ def id_langsuffix(dn, node)
107
+ lang = node.attr("language") || "en"
108
+ suffix = case lang
109
+ when "en" then "(E)"
110
+ when "fr" then "(F)"
111
+ else
112
+ "(X)"
113
+ end
114
+ "#{dn}#{suffix}"
115
+ end
116
+
117
+ def structured_id(node, xml)
118
+ return unless node.attr("docnumber")
119
+ part, subpart = node&.attr("partnumber")&.split(/-/)
120
+ xml.structuredidentifier do |i|
121
+ i.project_number node.attr("docnumber"),
122
+ **attr_code(part: part, subpart: subpart,
123
+ amendment: node.attr("amendment-number"),
124
+ corrigendum: node.attr("corrigendum-number"),
125
+ origyr: node.attr("created-date"))
126
+ end
127
+ end
128
+
129
+ def add_id_parts(dn, part, subpart)
130
+ dn += "-#{part}" if part
131
+ dn += "-#{subpart}" if subpart
132
+ dn
133
+ end
134
+
135
+ def id_stage_abbr(stage, substage, node)
136
+ ret = IsoDoc::Iso::Metadata.new("en", "Latn", {}).
137
+ status_abbrev(stage_abbr(stage, substage, node.attr("doctype")),
138
+ substage, node.attr("iteration"),
139
+ node.attr("draft"), node.attr("doctype"))
140
+ if %w(amendment technical-corrigendum amendment
141
+ technical-corrigendum).include?(node.attr("doctype"))
142
+ ret = ret + " " unless %w(40 50).include?(stage)
143
+ end
144
+ ret
145
+ end
146
+
147
+ def id_stage_prefix(dn, node, force_year)
148
+ stage = get_stage(node)
149
+ typeabbr = get_typeabbr(node)
150
+ if stage && (stage.to_i < 60)
151
+ dn = unpub_stage_prefix(dn, stage, typeabbr, node)
152
+ elsif typeabbr && !@amd then dn = "/#{typeabbr}#{dn}"
153
+ end
154
+ (force_year || !(stage && (stage.to_i < 60))) and
155
+ dn = id_add_year(dn, node)
156
+ dn
157
+ end
158
+
159
+ def unpub_stage_prefix(dn, stage, typeabbr, node)
160
+ abbr = id_stage_abbr(stage, get_substage(node), node)
161
+ %w(40 50).include?(stage) && i = node.attr("iteration") and
162
+ itersuffix = ".#{i}"
163
+ return dn if abbr.nil? || abbr.empty? # prefixes added in cleanup
164
+ return "/#{abbr}#{typeabbr} #{dn}#{itersuffix}" unless @amd
165
+ a = dn.split(%r{/})
166
+ a[-1] = "#{abbr}#{a[-1]}#{itersuffix}"
167
+ a.join("/")
168
+ end
169
+
170
+ def id_add_year(dn, node)
171
+ year = node.attr("copyright-year")
172
+ @amd and year ||= node.attr("updated-date")&.sub(/-.*$/, "")
173
+ dn += ":#{year}" if year
174
+ dn
175
+ end
176
+
177
+ def get_stage(node)
178
+ stage = node.attr("status") || node.attr("docstage") || "60"
179
+ end
180
+
181
+ def get_substage(node)
182
+ stage = get_stage(node)
183
+ node.attr("docsubstage") || ( stage == "60" ? "60" : "00" )
184
+ end
185
+
186
+ def get_typeabbr(node)
187
+ case node.attr("doctype")
188
+ when "technical-report" then "TR "
189
+ when "technical-specification" then "TS "
190
+ else
191
+ nil
192
+ end
193
+ end
194
+ end
195
+ end
196
+ 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>