metanorma-iso 1.3.22 → 1.3.27

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) 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 +89 -32
  8. data/lib/asciidoctor/iso/cleanup.rb +20 -3
  9. data/lib/asciidoctor/iso/front.rb +16 -107
  10. data/lib/asciidoctor/iso/front_id.rb +196 -0
  11. data/lib/asciidoctor/iso/isodoc.rng +475 -2
  12. data/lib/asciidoctor/iso/isostandard-amd.rng +98 -0
  13. data/lib/asciidoctor/iso/isostandard.rng +12 -1
  14. data/lib/asciidoctor/iso/macros.rb +21 -0
  15. data/lib/asciidoctor/iso/reqt.rng +23 -0
  16. data/lib/asciidoctor/iso/section.rb +18 -32
  17. data/lib/asciidoctor/iso/term_lookup_cleanup.rb +87 -0
  18. data/lib/asciidoctor/iso/validate.rb +41 -25
  19. data/lib/asciidoctor/iso/validate_requirements.rb +1 -1
  20. data/lib/asciidoctor/iso/validate_section.rb +2 -2
  21. data/lib/asciidoctor/iso/validate_style.rb +6 -5
  22. data/lib/asciidoctor/iso/validate_title.rb +1 -1
  23. data/lib/isodoc/iso/base_convert.rb +77 -107
  24. data/lib/isodoc/iso/html/header.html +10 -6
  25. data/lib/isodoc/iso/html/html_iso_titlepage.html +27 -18
  26. data/lib/isodoc/iso/html/isodoc.scss +53 -28
  27. data/lib/isodoc/iso/html/scripts.html +23 -21
  28. data/lib/isodoc/iso/html/style-human.scss +23 -0
  29. data/lib/isodoc/iso/html/style-iso.scss +18 -0
  30. data/lib/isodoc/iso/html/word_iso_intro.html +4 -0
  31. data/lib/isodoc/iso/html/word_iso_titlepage.html +23 -2
  32. data/lib/isodoc/iso/html/wordstyle.scss +80 -39
  33. data/lib/isodoc/iso/html_convert.rb +7 -9
  34. data/lib/isodoc/iso/iso.amendment.xsl +4597 -0
  35. data/lib/isodoc/iso/iso.international-standard.xsl +4597 -0
  36. data/lib/isodoc/iso/metadata.rb +71 -23
  37. data/lib/isodoc/iso/pdf_convert.rb +39 -0
  38. data/lib/isodoc/iso/sections.rb +66 -0
  39. data/lib/isodoc/iso/sts_convert.rb +29 -0
  40. data/lib/isodoc/iso/xref.rb +105 -0
  41. data/lib/metanorma-iso.rb +2 -0
  42. data/lib/metanorma/iso/processor.rb +16 -1
  43. data/lib/metanorma/iso/version.rb +1 -1
  44. data/metanorma-iso.gemspec +4 -1
  45. data/spec/asciidoctor-iso/amd_spec.rb +726 -0
  46. data/spec/asciidoctor-iso/base_spec.rb +38 -21
  47. data/spec/asciidoctor-iso/blocks_spec.rb +6 -6
  48. data/spec/asciidoctor-iso/cleanup_spec.rb +195 -174
  49. data/spec/asciidoctor-iso/inline_spec.rb +2 -1
  50. data/spec/asciidoctor-iso/macros_spec.rb +289 -0
  51. data/spec/asciidoctor-iso/refs_spec.rb +8 -5
  52. data/spec/asciidoctor-iso/section_spec.rb +8 -8
  53. data/spec/assets/iso.xml +64 -1
  54. data/spec/isodoc/amd_spec.rb +652 -0
  55. data/spec/isodoc/blocks_spec.rb +112 -27
  56. data/spec/isodoc/i18n_spec.rb +12 -20
  57. data/spec/isodoc/inline_spec.rb +4 -4
  58. data/spec/isodoc/iso_spec.rb +1 -1
  59. data/spec/isodoc/metadata_spec.rb +92 -4
  60. data/spec/isodoc/postproc_spec.rb +21 -120
  61. data/spec/isodoc/ref_spec.rb +9 -9
  62. data/spec/isodoc/section_spec.rb +36 -13
  63. data/spec/isodoc/table_spec.rb +30 -30
  64. data/spec/isodoc/terms_spec.rb +6 -6
  65. data/spec/isodoc/xref_spec.rb +43 -37
  66. data/spec/metanorma/processor_spec.rb +2 -2
  67. data/spec/spec_helper.rb +11 -0
  68. metadata +58 -5
  69. 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>
@@ -91,6 +91,12 @@
91
91
  </define>
92
92
  <define name="sections">
93
93
  <element name="sections">
94
+ <zeroOrMore>
95
+ <choice>
96
+ <ref name="note"/>
97
+ <ref name="admonition"/>
98
+ </choice>
99
+ </zeroOrMore>
94
100
  <ref name="clause"/>
95
101
  <optional>
96
102
  <choice>
@@ -263,6 +269,8 @@
263
269
  <value>publicly-available-specification</value>
264
270
  <value>international-workshop-agreement</value>
265
271
  <value>guide</value>
272
+ <value>amendment</value>
273
+ <value>technical-corrigendum</value>
266
274
  </choice>
267
275
  </define>
268
276
  <define name="structuredidentifier">
@@ -354,6 +362,9 @@
354
362
  <data type="boolean"/>
355
363
  </attribute>
356
364
  </optional>
365
+ <optional>
366
+ <attribute name="number"/>
367
+ </optional>
357
368
  <optional>
358
369
  <attribute name="subsequence"/>
359
370
  </optional>
@@ -510,7 +521,7 @@
510
521
  </attribute>
511
522
  </optional>
512
523
  <oneOrMore>
513
- <ref name="paragraph-with-footnote"/>
524
+ <ref name="BasicBlock"/>
514
525
  </oneOrMore>
515
526
  </element>
516
527
  </define>
@@ -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
@@ -30,9 +30,22 @@
30
30
  <data type="boolean"/>
31
31
  </attribute>
32
32
  </optional>
33
+ <optional>
34
+ <attribute name="number"/>
35
+ </optional>
33
36
  <optional>
34
37
  <attribute name="subsequence"/>
35
38
  </optional>
39
+ <optional>
40
+ <attribute name="keep-with-next">
41
+ <data type="boolean"/>
42
+ </attribute>
43
+ </optional>
44
+ <optional>
45
+ <attribute name="keep-lines-together">
46
+ <data type="boolean"/>
47
+ </attribute>
48
+ </optional>
36
49
  <attribute name="id">
37
50
  <data type="ID"/>
38
51
  </attribute>
@@ -141,6 +154,16 @@
141
154
  <data type="boolean"/>
142
155
  </attribute>
143
156
  </optional>
157
+ <optional>
158
+ <attribute name="keep-with-next">
159
+ <data type="boolean"/>
160
+ </attribute>
161
+ </optional>
162
+ <optional>
163
+ <attribute name="keep-lines-together">
164
+ <data type="boolean"/>
165
+ </attribute>
166
+ </optional>
144
167
  <oneOrMore>
145
168
  <ref name="BasicBlock"/>
146
169
  </oneOrMore>
@@ -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
+ normalize_id_and_memorize(term_node, res, './preferred')
61
+ end
62
+ end
63
+
64
+ def normalize_id_and_memorize(term_node, res_table, text_selector)
65
+ term_text = normalize_ref_id(term_node.at(text_selector).text)
66
+ unless AUTOMATIC_GENERATED_ID_REGEXP.match(term_node['id']).nil?
67
+ term_node['id'] = unique_text_id(term_text)
68
+ end
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,14 +55,16 @@ 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
@@ -68,8 +74,9 @@ module Asciidoctor
68
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)
@@ -158,20 +170,24 @@ module Asciidoctor
158
170
 
159
171
  def bibitem_validate(xmldoc)
160
172
  xmldoc.xpath("//bibitem[date/on = '–']").each do |b|
161
- found = false
162
- b.xpath("./note").each do |n|
163
- found = true if /^ISO DATE:/.match n.text
164
- end
165
- found or
166
- @log.add("Style", b, "Reference #{b&.at("./@id")&.text} does not have an "\
167
- "associated footnote indicating unpublished status")
173
+ b.at("./note[@type = 'ISO DATE']") or
174
+ @log.add("Style", b,
175
+ "Reference #{b&.at("./@id")&.text} does not have an "\
176
+ "associated footnote indicating unpublished status")
168
177
  end
169
178
  end
170
179
 
171
180
  def validate(doc)
172
181
  content_validate(doc)
182
+ doctype = doc&.at("//bibdata/ext/doctype")&.text
183
+ schema = case doctype
184
+ when "amendment", "technical-corrigendum" # @amd
185
+ "isostandard-amd.rng"
186
+ else
187
+ "isostandard.rng"
188
+ end
173
189
  schema_validate(formattedstr_strip(doc.dup),
174
- File.join(File.dirname(__FILE__), "isostandard.rng"))
190
+ File.join(File.dirname(__FILE__), schema))
175
191
  end
176
192
  end
177
193
  end