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
@@ -0,0 +1,98 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <grammar ns="https://www.metanorma.org/ns/iso" xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
3
+ <!-- default namespace isostandard = "https://www.metanorma.com/ns/iso" -->
4
+ <include href="isostandard.rng">
5
+ <start>
6
+ <ref name="iso-standard"/>
7
+ </start>
8
+ <define name="sections">
9
+ <element name="sections">
10
+ <oneOrMore>
11
+ <ref name="clause"/>
12
+ </oneOrMore>
13
+ </element>
14
+ </define>
15
+ <define name="clause">
16
+ <element name="clause">
17
+ <optional>
18
+ <attribute name="type"/>
19
+ </optional>
20
+ <optional>
21
+ <attribute name="change">
22
+ <choice>
23
+ <value>add</value>
24
+ <value>delete</value>
25
+ <value>modify</value>
26
+ </choice>
27
+ </attribute>
28
+ </optional>
29
+ <optional>
30
+ <attribute name="locality"/>
31
+ </optional>
32
+ <ref name="Clause-Section"/>
33
+ </element>
34
+ </define>
35
+ <define name="iso-standard">
36
+ <element name="iso-standard">
37
+ <ref name="bibdata"/>
38
+ <optional>
39
+ <ref name="boilerplate"/>
40
+ </optional>
41
+ <ref name="preface"/>
42
+ <oneOrMore>
43
+ <ref name="sections"/>
44
+ </oneOrMore>
45
+ </element>
46
+ </define>
47
+ <define name="documentnumber">
48
+ <element name="project-number">
49
+ <optional>
50
+ <attribute name="part">
51
+ <data type="int"/>
52
+ </attribute>
53
+ </optional>
54
+ <optional>
55
+ <attribute name="subpart">
56
+ <data type="int"/>
57
+ </attribute>
58
+ </optional>
59
+ <optional>
60
+ <attribute name="amendment">
61
+ <data type="int"/>
62
+ </attribute>
63
+ </optional>
64
+ <optional>
65
+ <attribute name="corrigendum">
66
+ <data type="int"/>
67
+ </attribute>
68
+ </optional>
69
+ <optional>
70
+ <attribute name="origyr">
71
+ <data type="int"/>
72
+ </attribute>
73
+ </optional>
74
+ <text/>
75
+ </element>
76
+ </define>
77
+ <define name="BibDataExtensionType">
78
+ <ref name="doctype"/>
79
+ <ref name="editorialgroup"/>
80
+ <zeroOrMore>
81
+ <ref name="ics"/>
82
+ </zeroOrMore>
83
+ <ref name="structuredidentifier"/>
84
+ <optional>
85
+ <ref name="stagename"/>
86
+ </optional>
87
+ <optional>
88
+ <ref name="updates_document_type"/>
89
+ </optional>
90
+ </define>
91
+ </include>
92
+ <!-- end overrides -->
93
+ <define name="updates_document_type">
94
+ <element name="updates-document-type">
95
+ <ref name="DocumentType"/>
96
+ </element>
97
+ </define>
98
+ </grammar>
@@ -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>
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'asciidoctor/extensions'
4
+
5
+ module Asciidoctor
6
+ module Iso
7
+ # Macro to transform `term[X,Y]` into em, termxref xml
8
+ class TermRefInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
9
+ use_dsl
10
+
11
+ named :term
12
+ name_positional_attributes 'name', 'termxref'
13
+ using_format :short
14
+
15
+ def process(_parent, _target, attrs)
16
+ termref = attrs['termxref'] || attrs['name']
17
+ "<em>#{attrs['name']}</em> (<termxref>#{termref}</termxref>)"
18
+ end
19
+ end
20
+ end
21
+ end
@@ -4,38 +4,12 @@ require "uri"
4
4
  module Asciidoctor
5
5
  module ISO
6
6
  class Converter < Standoc::Converter
7
- def section(node)
8
- a = section_attributes(node)
9
- noko do |xml|
10
- case sectiontype(node)
11
- when "foreword" then foreword_parse(a, xml, node)
12
- when "introduction" then introduction_parse(a, xml, node)
13
- when "patent notice" then patent_notice_parse(xml, node)
14
- when "scope" then scope_parse(a, xml, node)
15
- when "normative references" then norm_ref_parse(a, xml, node)
16
- when "terms and definitions"
17
- @term_def = true
18
- term_def_parse(a, xml, node, true)
19
- @term_def = false
20
- when "symbols and abbreviated terms"
21
- symbols_parse(a, xml, node)
22
- when "acknowledgements"
23
- acknowledgements_parse(a, xml, node)
24
- when "bibliography" then bibliography_parse(a, xml, node)
25
- else
26
- if @term_def then term_def_subclause_parse(a, xml, node)
27
- elsif @biblio then bibliography_parse(a, xml, node)
28
- elsif node.attr("style") == "bibliography"
29
- bibliography_parse(a, xml, node)
30
- elsif node.attr("style") == "appendix" && node.level == 1
31
- annex_parse(a, xml, node)
32
- elsif node.option? "appendix"
33
- appendix_parse(a, xml, node)
34
- else
35
- clause_parse(a, xml, node)
36
- end
37
- end
38
- end.join("\n")
7
+ def clause_parse(attrs, xml, node)
8
+ title = node&.attr("heading")&.downcase ||
9
+ node.title.gsub(/<[^>]+>/, "").downcase
10
+ title == "scope" and return scope_parse(attrs, xml, node)
11
+ node.option? "appendix" and return appendix_parse(attrs, xml, node)
12
+ super
39
13
  end
40
14
 
41
15
  def appendix_parse(attrs, xml, node)
@@ -61,6 +35,18 @@ module Asciidoctor
61
35
  xml_section << content
62
36
  end
63
37
  end
38
+
39
+ def section_attributes(node)
40
+ super.merge(
41
+ change: @amd ? node.attr("change") : nil,
42
+ locality: @amd ? node.attr("locality") : nil,
43
+ )
44
+ end
45
+
46
+ def sectiontype(node, level = true)
47
+ return nil if @amd
48
+ super
49
+ end
64
50
  end
65
51
  end
66
52
  end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true.
2
+
3
+ module Asciidoctor
4
+ module ISO
5
+ # Intelligent term lookup xml modifier
6
+ # Lookup all `term` and `calause` tags and replace `termxref` tags with
7
+ # `xref`:target tag
8
+ class TermLookupCleanup
9
+ AUTOMATIC_GENERATED_ID_REGEXP = /\A_/
10
+ EXISTING_TERM_REGEXP = /\Aterm-/
11
+
12
+ attr_reader :xmldoc, :termlookup, :log
13
+
14
+ def initialize(xmldoc, log)
15
+ @xmldoc = xmldoc
16
+ @log = log
17
+ @termlookup = {}
18
+ end
19
+
20
+ def call
21
+ @termlookup = replace_automatic_generated_ids_terms
22
+ set_termxref_tags_target
23
+ end
24
+
25
+ private
26
+
27
+ def set_termxref_tags_target
28
+ xmldoc.xpath('//termxref').each do |node|
29
+ target = normalize_ref_id(node.text)
30
+ if termlookup[target].nil?
31
+ remove_missing_ref(node, target)
32
+ next
33
+ end
34
+ modify_ref_node(node, target)
35
+ end
36
+ end
37
+
38
+ def remove_missing_ref(node, target)
39
+ log.add('AsciiDoc Input', node,
40
+ %(Error: Term reference in `term[#{target}]` missing: \
41
+ "#{target}" is not defined in document))
42
+ term_name_node = node.previous.previous
43
+ term_name_node.remove
44
+ term_name_node.name = "strong"
45
+ term_name_node.children.first.content =
46
+ %(term "#{term_name_node.text}" not resolved)
47
+ node.add_previous_sibling(term_name_node)
48
+ node.remove
49
+ end
50
+
51
+ def modify_ref_node(node, target)
52
+ node.name = 'xref'
53
+ node['target'] = termlookup[target]
54
+ node.children.remove
55
+ node.remove_attribute('defaultref')
56
+ end
57
+
58
+ def replace_automatic_generated_ids_terms
59
+ xmldoc.xpath('//term').each.with_object({}) do |term_node, res|
60
+ next if AUTOMATIC_GENERATED_ID_REGEXP.match(term_node['id']).nil?
61
+
62
+ normalize_id_and_memorize(term_node, res, './preferred')
63
+ end
64
+ end
65
+
66
+ def normalize_id_and_memorize(term_node, res_table, text_selector)
67
+ term_text = normalize_ref_id(term_node.at(text_selector).text)
68
+ term_node['id'] = unique_text_id(term_text)
69
+ res_table[term_text] = term_node['id']
70
+ end
71
+
72
+ def normalize_ref_id(text)
73
+ text.downcase.gsub(/[[:space:]]/, '-')
74
+ end
75
+
76
+ def unique_text_id(text)
77
+ return "term-#{text}" if xmldoc.at("//*[@id = 'term-#{text}']").nil?
78
+
79
+ (1..Float::INFINITY).lazy.each do |index|
80
+ if xmldoc.at("//*[@id = 'term-#{text}-#{index}']").nil?
81
+ break("term-#{text}-#{index}")
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -24,12 +24,14 @@ module Asciidoctor
24
24
  def isosubgroup_validate(root)
25
25
  root.xpath("//technical-committee/@type").each do |t|
26
26
  unless %w{TC PC JTC JPC}.include? t.text
27
- @log.add("Document Attributes", nil, "invalid technical committee type #{t}")
27
+ @log.add("Document Attributes", nil,
28
+ "invalid technical committee type #{t}")
28
29
  end
29
30
  end
30
31
  root.xpath("//subcommittee/@type").each do |t|
31
32
  unless %w{SC JSC}.include? t.text
32
- @log.add("Document Attributes", nil, "invalid subcommittee type #{t}")
33
+ @log.add("Document Attributes", nil,
34
+ "invalid subcommittee type #{t}")
33
35
  end
34
36
  end
35
37
  end
@@ -39,10 +41,12 @@ module Asciidoctor
39
41
  root.xpath("//xref").each do |t|
40
42
  # does not deal with preceding text marked up
41
43
  preceding = t.at("./preceding-sibling::text()[last()]")
42
- next unless !preceding.nil? && /\b(see| refer to)\s*$/mi.match(preceding)
44
+ next unless !preceding.nil? &&
45
+ /\b(see| refer to)\s*$/mi.match(preceding)
43
46
  (target = root.at("//*[@id = '#{t['target']}']")) || next
44
47
  if target&.at("./ancestor-or-self::*[@obligation = 'normative']")
45
- @log.add("Style", t, "'see #{t['target']}' is pointing to a normative section")
48
+ @log.add("Style", t,
49
+ "'see #{t['target']}' is pointing to a normative section")
46
50
  end
47
51
  end
48
52
  end
@@ -51,25 +55,28 @@ module Asciidoctor
51
55
  def see_erefs_validate(root)
52
56
  root.xpath("//eref").each do |t|
53
57
  preceding = t.at("./preceding-sibling::text()[last()]")
54
- next unless !preceding.nil? && /\b(see|refer to)\s*$/mi.match(preceding)
58
+ next unless !preceding.nil? &&
59
+ /\b(see|refer to)\s*$/mi.match(preceding)
55
60
  unless target = root.at("//*[@id = '#{t['bibitemid']}']")
56
- @log.add("Bibliography", t, "'#{t} is not pointing to a real reference")
61
+ @log.add("Bibliography", t,
62
+ "'#{t} is not pointing to a real reference")
57
63
  next
58
64
  end
59
- if target.at("./ancestor::references"\
60
- "[title = 'Normative References']")
61
- @log.add("Style", t, "'see #{t}' is pointing to a normative reference")
65
+ if target.at("./ancestor::references[@normative = 'true']")
66
+ @log.add("Style", t,
67
+ "'see #{t}' is pointing to a normative reference")
62
68
  end
63
69
  end
64
70
  end
65
71
 
66
72
  # ISO/IEC DIR 2, 10.4
67
73
  def locality_erefs_validate(root)
68
- root.xpath("//eref[locality]").each do |t|
74
+ root.xpath("//eref[descendant::locality]").each do |t|
69
75
  if /^(ISO|IEC)/.match t["citeas"]
70
76
  unless /:[ ]?(\d+{4}|–)$/.match t["citeas"]
71
- @log.add("Style", t, "undated reference #{t['citeas']} should not contain "\
72
- "specific elements")
77
+ @log.add("Style", t,
78
+ "undated reference #{t['citeas']} should not contain "\
79
+ "specific elements")
73
80
  end
74
81
  end
75
82
  end
@@ -106,32 +113,37 @@ module Asciidoctor
106
113
  doctype = xmldoc&.at("//bibdata/ext/doctype")&.text
107
114
  %w(international-standard technical-specification technical-report
108
115
  publicly-available-specification international-workshop-agreement
109
- guide).include? doctype or
110
- @log.add("Document Attributes", nil, "#{doctype} is not a recognised document type")
116
+ guide amendment technical-corrigendum).include? doctype or
117
+ @log.add("Document Attributes", nil,
118
+ "#{doctype} is not a recognised document type")
111
119
  end
112
120
 
113
121
  def script_validate(xmldoc)
114
122
  script = xmldoc&.at("//bibdata/script")&.text
115
123
  script == "Latn" or
116
- @log.add("Document Attributes", nil, "#{script} is not a recognised script")
124
+ @log.add("Document Attributes", nil,
125
+ "#{script} is not a recognised script")
117
126
  end
118
127
 
119
128
  def stage_validate(xmldoc)
120
129
  stage = xmldoc&.at("//bibdata/status/stage")&.text
121
130
  %w(00 10 20 30 40 50 60 90 95).include? stage or
122
- @log.add("Document Attributes", nil, "#{stage} is not a recognised stage")
131
+ @log.add("Document Attributes", nil,
132
+ "#{stage} is not a recognised stage")
123
133
  end
124
134
 
125
135
  def substage_validate(xmldoc)
126
136
  substage = xmldoc&.at("//bibdata/status/substage")&.text or return
127
137
  %w(00 20 60 90 92 93 98 99).include? substage or
128
- @log.add("Document Attributes", nil, "#{substage} is not a recognised substage")
138
+ @log.add("Document Attributes", nil,
139
+ "#{substage} is not a recognised substage")
129
140
  end
130
141
 
131
142
  def iteration_validate(xmldoc)
132
143
  iteration = xmldoc&.at("//bibdata/status/iteration")&.text or return
133
144
  /^\d+/.match(iteration) or
134
- @log.add("Document Attributes", nil, "#{iteration} is not a recognised iteration")
145
+ @log.add("Document Attributes", nil,
146
+ "#{iteration} is not a recognised iteration")
135
147
  end
136
148
 
137
149
  def bibdata_validate(doc)
@@ -163,15 +175,23 @@ module Asciidoctor
163
175
  found = true if /^ISO DATE:/.match n.text
164
176
  end
165
177
  found or
166
- @log.add("Style", b, "Reference #{b&.at("./@id")&.text} does not have an "\
167
- "associated footnote indicating unpublished status")
178
+ @log.add("Style", b,
179
+ "Reference #{b&.at("./@id")&.text} does not have an "\
180
+ "associated footnote indicating unpublished status")
168
181
  end
169
182
  end
170
183
 
171
184
  def validate(doc)
172
185
  content_validate(doc)
186
+ doctype = doc&.at("//bibdata/ext/doctype")&.text
187
+ schema = case doctype
188
+ when "amendment", "technical-corrigendum" # @amd
189
+ "isostandard-amd.rng"
190
+ else
191
+ "isostandard.rng"
192
+ end
173
193
  schema_validate(formattedstr_strip(doc.dup),
174
- File.join(File.dirname(__FILE__), "isostandard.rng"))
194
+ File.join(File.dirname(__FILE__), schema))
175
195
  end
176
196
  end
177
197
  end