metanorma-iso 1.3.21 → 1.3.26

Sign up to get free protection for your applications and to get access to all the features.
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>