metanorma-iso 1.4.3 → 1.5.4

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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ubuntu.yml +1 -1
  3. data/lib/asciidoctor/iso/base.rb +9 -20
  4. data/lib/asciidoctor/iso/cleanup.rb +2 -3
  5. data/lib/asciidoctor/iso/front.rb +6 -7
  6. data/lib/asciidoctor/iso/front_id.rb +6 -6
  7. data/lib/asciidoctor/iso/isodoc.rng +16 -7
  8. data/lib/asciidoctor/iso/section.rb +5 -11
  9. data/lib/asciidoctor/iso/term_lookup_cleanup.rb +0 -1
  10. data/lib/asciidoctor/iso/validate_section.rb +40 -44
  11. data/lib/isodoc/iso/base_convert.rb +3 -64
  12. data/lib/isodoc/iso/html/wordstyle.css +10 -9
  13. data/lib/isodoc/iso/html/wordstyle.scss +15 -9
  14. data/lib/isodoc/iso/html_convert.rb +2 -1
  15. data/lib/{asciidoctor → isodoc}/iso/i18n-en.yaml +0 -1
  16. data/lib/{asciidoctor → isodoc}/iso/i18n-fr.yaml +0 -0
  17. data/lib/{asciidoctor → isodoc}/iso/i18n-zh-Hans.yaml +0 -0
  18. data/lib/isodoc/iso/i18n.rb +19 -0
  19. data/lib/isodoc/iso/init.rb +33 -0
  20. data/lib/isodoc/iso/iso.amendment.xsl +1403 -1719
  21. data/lib/isodoc/iso/iso.international-standard.xsl +1403 -1719
  22. data/lib/isodoc/iso/metadata.rb +1 -1
  23. data/lib/isodoc/iso/presentation_xml_convert.rb +99 -1
  24. data/lib/isodoc/iso/sections.rb +3 -8
  25. data/lib/isodoc/iso/word_convert.rb +19 -14
  26. data/lib/isodoc/iso/xref.rb +2 -0
  27. data/lib/metanorma/iso/version.rb +1 -1
  28. data/metanorma-iso.gemspec +2 -2
  29. data/spec/asciidoctor-iso/base_spec.rb +3 -11
  30. data/spec/asciidoctor-iso/cleanup_spec.rb +31 -7
  31. data/spec/asciidoctor-iso/inline_spec.rb +8 -2
  32. data/spec/asciidoctor-iso/refs_spec.rb +3 -3
  33. data/spec/asciidoctor-iso/section_spec.rb +9 -6
  34. data/spec/asciidoctor-iso/table_spec.rb +7 -1
  35. data/spec/asciidoctor-iso/validate_spec.rb +100 -21
  36. data/spec/isodoc/amd_spec.rb +309 -153
  37. data/spec/isodoc/blocks_spec.rb +362 -28
  38. data/spec/isodoc/i18n_spec.rb +468 -108
  39. data/spec/isodoc/inline_spec.rb +99 -31
  40. data/spec/isodoc/iso_spec.rb +95 -29
  41. data/spec/isodoc/postproc_spec.rb +190 -150
  42. data/spec/isodoc/ref_spec.rb +175 -3
  43. data/spec/isodoc/section_spec.rb +148 -82
  44. data/spec/isodoc/table_spec.rb +142 -5
  45. data/spec/isodoc/terms_spec.rb +78 -53
  46. data/spec/isodoc/xref_spec.rb +831 -658
  47. data/spec/metanorma/processor_spec.rb +2 -1
  48. metadata +11 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4e88ecac9a1d970682830fc23fc1b808c7b83dedc00a3e6a3adcad7822225622
4
- data.tar.gz: 413f8bb0aac5a124b33992bdaf7977d3e89da0e701512a4d877af68255fd8ba1
3
+ metadata.gz: 9b80a62eb663a85ad1428d97e32114a9b6341303689f0d43a5bac63e071e4740
4
+ data.tar.gz: 11412874aa684c02fde2eb00899f1f4290b3cede75b6981f6df11c2b0e99be29
5
5
  SHA512:
6
- metadata.gz: 7b9b163582c5602c131691c8aa484fe20cf4fe02f2fca00b66ef6d50b5515673b8794e0cd4e4a4e404ff169697221551e7a521dac9c7ebb2998b406de7d9b649
7
- data.tar.gz: 26f82fb95d062ddc527a2ac2cefa798edee6771d332307713759ab494fa27a8f16a1e8b27b4f817c088da7ee9e6beac7ea41221618cfd12cfe01dc3f561d309d
6
+ metadata.gz: 8a513b51527259420edc479f2cb6a2438e47383c66a1aceb2386cfba0ce7b2c7f16d3c55661cf83c6b5d8db35550c1a7354d81474df66d32df3a4dce6c79f104
7
+ data.tar.gz: 7676550f3771804a384e1b1d7f7948e46e950be96844031108f5d0ef019bbc605d18c8367b428858ea36d97b398134e34a529cb8ab4b09a82ac20594140c420a
@@ -39,7 +39,7 @@ jobs:
39
39
  polling_interval_seconds: 5
40
40
  timeout_minutes: 5
41
41
  max_attempts: 3
42
- command: sudo bash -c "curl -L https://github.com/metanorma/plantuml-install/raw/master/ubuntu.sh | bash"
42
+ command: sudo apt-get update -y && sudo bash -c "curl -L https://github.com/metanorma/plantuml-install/raw/master/ubuntu.sh | bash"
43
43
  - name: Run specs
44
44
  run: |
45
45
  bundle exec rake
@@ -3,7 +3,6 @@ require "nokogiri"
3
3
  require "json"
4
4
  require "pathname"
5
5
  require "open-uri"
6
- require "pp"
7
6
  require "isodoc"
8
7
  require "fileutils"
9
8
  require 'asciidoctor/iso/macros'
@@ -47,32 +46,22 @@ module Asciidoctor
47
46
 
48
47
  def init(node)
49
48
  super
50
- @amd = %w(amendment technical-corrigendum).include? node.attr("doctype")
49
+ @amd = %w(amendment technical-corrigendum).include? doctype(node)
51
50
  end
52
51
 
53
52
  def outputs(node, ret)
54
53
  File.open(@filename + ".xml", "w:UTF-8") { |f| f.write(ret) }
55
54
  presentation_xml_converter(node).convert(@filename + ".xml")
56
- html_converter_alt(node).convert(@filename + ".presentation.xml", nil, false, "#{@filename}_alt.html")
57
- html_converter(node).convert(@filename + ".presentation.xml", nil, false, "#{@filename}.html")
58
- doc_converter(node).convert(@filename + ".presentation.xml", nil, false, "#{@filename}.doc")
59
- pdf_converter(node)&.convert(@filename + ".presentation.xml", nil, false, "#{@filename}.pdf")
55
+ html_converter_alt(node).convert(@filename + ".presentation.xml",
56
+ nil, false, "#{@filename}_alt.html")
57
+ html_converter(node).convert(@filename + ".presentation.xml",
58
+ nil, false, "#{@filename}.html")
59
+ doc_converter(node).convert(@filename + ".presentation.xml",
60
+ nil, false, "#{@filename}.doc")
61
+ pdf_converter(node)&.convert(@filename + ".presentation.xml",
62
+ nil, false, "#{@filename}.pdf")
60
63
  #sts_converter(node)&.convert(@filename + ".xml")
61
64
  end
62
-
63
- def load_yaml(lang, script)
64
- y = if @i18nyaml then YAML.load_file(@i18nyaml)
65
- elsif lang == "en"
66
- YAML.load_file(File.join(File.dirname(__FILE__), "i18n-en.yaml"))
67
- elsif lang == "fr"
68
- YAML.load_file(File.join(File.dirname(__FILE__), "i18n-fr.yaml"))
69
- elsif lang == "zh" && script == "Hans"
70
- YAML.load_file(File.join(File.dirname(__FILE__), "i18n-zh-Hans.yaml"))
71
- else
72
- YAML.load_file(File.join(File.dirname(__FILE__), "i18n-en.yaml"))
73
- end
74
- super.merge(y)
75
- end
76
65
  end
77
66
  end
78
67
  end
@@ -4,20 +4,19 @@ require "htmlentities"
4
4
  require "json"
5
5
  require "pathname"
6
6
  require "open-uri"
7
- require "pp"
8
7
  require "asciidoctor/iso/term_lookup_cleanup"
9
8
 
10
9
  module Asciidoctor
11
10
  module ISO
12
11
  class Converter < Standoc::Converter
13
12
  PRE_NORMREF_FOOTNOTES = "//preface//fn | "\
14
- "//clause[title = 'Scope']//fn".freeze
13
+ "//clause[@type = 'scope']//fn".freeze
15
14
 
16
15
  NORMREF_FOOTNOTES =
17
16
  "//references[@normative = 'true']//fn".freeze
18
17
 
19
18
  POST_NORMREF_FOOTNOTES =
20
- "//sections//clause[not(title = 'Scope')]//fn | "\
19
+ "//sections//clause[not(@type = 'scope')]//fn | "\
21
20
  "//annex//fn | "\
22
21
  "//references[@normative = 'false']//fn".freeze
23
22
 
@@ -4,7 +4,6 @@ require "htmlentities"
4
4
  require "json"
5
5
  require "pathname"
6
6
  require "open-uri"
7
- require "pp"
8
7
  require_relative "front_id"
9
8
 
10
9
  module Asciidoctor
@@ -14,7 +13,7 @@ module Asciidoctor
14
13
  super
15
14
  structured_id(node, xml)
16
15
  xml.stagename stage_name(get_stage(node), get_substage(node),
17
- node.attr("doctype"), node.attr("iteration"))
16
+ doctype(node), node.attr("iteration"))
18
17
  @amd && a = node.attr("updates-document-type") and
19
18
  xml.updates_document_type a
20
19
  end
@@ -35,7 +34,7 @@ module Asciidoctor
35
34
 
36
35
  def metadata_author(node, xml)
37
36
  publishers = node.attr("publisher") || "ISO"
38
- publishers.split(/,[ ]?/).each do |p|
37
+ csv_split(publishers).each do |p|
39
38
  xml.contributor do |c|
40
39
  c.role **{ type: "author" }
41
40
  c.organization { |a| organization(a, p) }
@@ -45,7 +44,7 @@ module Asciidoctor
45
44
 
46
45
  def metadata_publisher(node, xml)
47
46
  publishers = node.attr("publisher") || "ISO"
48
- publishers.split(/,[ ]?/).each do |p|
47
+ csv_split(publishers).each do |p|
49
48
  xml.contributor do |c|
50
49
  c.role **{ type: "publisher" }
51
50
  c.organization { |a| organization(a, p) }
@@ -54,8 +53,8 @@ module Asciidoctor
54
53
  end
55
54
 
56
55
  def metadata_copyright(node, xml)
57
- publishers = node.attr("publisher") || "ISO"
58
- publishers.split(/,[ ]?/).each do |p|
56
+ publishers = node.attr("copyright-holder") || node.attr("publisher") || "ISO"
57
+ csv_split(publishers).each do |p|
59
58
  xml.copyright do |c|
60
59
  c.from (node.attr("copyright-year") || Date.today.year)
61
60
  c.owner do |owner|
@@ -69,7 +68,7 @@ module Asciidoctor
69
68
  stage = get_stage(node)
70
69
  substage = get_substage(node)
71
70
  xml.status do |s|
72
- s.stage stage, **attr_code(abbreviation: stage_abbr(stage, substage, node.attr("doctype")))
71
+ s.stage stage, **attr_code(abbreviation: stage_abbr(stage, substage, doctype(node)))
73
72
  s.substage substage
74
73
  node.attr("iteration") && (s.iteration node.attr("iteration"))
75
74
  end
@@ -95,7 +95,7 @@ module Asciidoctor
95
95
  def add_amd_parts(dn, node)
96
96
  a = node.attr("amendment-number")
97
97
  c = node.attr("corrigendum-number")
98
- case node.attr("doctype")
98
+ case doctype(node)
99
99
  when "amendment"
100
100
  "#{dn}/Amd #{node.attr('amendment-number')}"
101
101
  when "technical-corrigendum"
@@ -133,12 +133,12 @@ module Asciidoctor
133
133
  end
134
134
 
135
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")),
136
+ ret = IsoDoc::Iso::Metadata.new("en", "Latn", @i18n).
137
+ status_abbrev(stage_abbr(stage, substage, doctype(node)),
138
138
  substage, node.attr("iteration"),
139
- node.attr("draft"), node.attr("doctype"))
139
+ node.attr("draft"), doctype(node))
140
140
  if %w(amendment technical-corrigendum amendment
141
- technical-corrigendum).include?(node.attr("doctype"))
141
+ technical-corrigendum).include?(doctype(node))
142
142
  ret = ret + " " unless %w(40 50).include?(stage)
143
143
  end
144
144
  ret
@@ -184,7 +184,7 @@ module Asciidoctor
184
184
  end
185
185
 
186
186
  def get_typeabbr(node)
187
- case node.attr("doctype")
187
+ case doctype(node)
188
188
  when "technical-report" then "TR "
189
189
  when "technical-specification" then "TS "
190
190
  else
@@ -42,8 +42,11 @@
42
42
  </define>
43
43
  <define name="xref">
44
44
  <element name="xref">
45
+ <!-- attribute target { xsd:IDREF }, -->
45
46
  <attribute name="target">
46
- <data type="IDREF"/>
47
+ <data type="string">
48
+ <param name="pattern">\i\c*|\c+#\c+</param>
49
+ </data>
47
50
  </attribute>
48
51
  <optional>
49
52
  <attribute name="type">
@@ -922,6 +925,9 @@
922
925
  <optional>
923
926
  <attribute name="script"/>
924
927
  </optional>
928
+ <optional>
929
+ <attribute name="type"/>
930
+ </optional>
925
931
  <optional>
926
932
  <attribute name="obligation">
927
933
  <choice>
@@ -961,9 +967,6 @@
961
967
  </define>
962
968
  <define name="content-subsection">
963
969
  <element name="clause">
964
- <optional>
965
- <attribute name="type"/>
966
- </optional>
967
970
  <ref name="Content-Section"/>
968
971
  </element>
969
972
  </define>
@@ -992,6 +995,9 @@
992
995
  </choice>
993
996
  </attribute>
994
997
  </optional>
998
+ <optional>
999
+ <attribute name="type"/>
1000
+ </optional>
995
1001
  <optional>
996
1002
  <ref name="section-title"/>
997
1003
  </optional>
@@ -1011,9 +1017,6 @@
1011
1017
  </define>
1012
1018
  <define name="clause">
1013
1019
  <element name="clause">
1014
- <optional>
1015
- <attribute name="type"/>
1016
- </optional>
1017
1020
  <ref name="Clause-Section"/>
1018
1021
  </element>
1019
1022
  </define>
@@ -1042,6 +1045,9 @@
1042
1045
  </choice>
1043
1046
  </attribute>
1044
1047
  </optional>
1048
+ <optional>
1049
+ <attribute name="type"/>
1050
+ </optional>
1045
1051
  <optional>
1046
1052
  <ref name="section-title"/>
1047
1053
  </optional>
@@ -1180,6 +1186,9 @@
1180
1186
  <optional>
1181
1187
  <attribute name="script"/>
1182
1188
  </optional>
1189
+ <optional>
1190
+ <attribute name="type"/>
1191
+ </optional>
1183
1192
  <optional>
1184
1193
  <attribute name="obligation">
1185
1194
  <choice>
@@ -5,13 +5,15 @@ module Asciidoctor
5
5
  module ISO
6
6
  class Converter < Standoc::Converter
7
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
8
  node.option? "appendix" and return appendix_parse(attrs, xml, node)
12
9
  super
13
10
  end
14
11
 
12
+ def scope_parse(attrs, xml, node)
13
+ attrs = attrs.merge(type: "scope") unless @amd
14
+ clause_parse(attrs, xml, node)
15
+ end
16
+
15
17
  def appendix_parse(attrs, xml, node)
16
18
  attrs["inline-header".to_sym] = node.option? "inline-header"
17
19
  set_obligation(attrs, node)
@@ -28,14 +30,6 @@ module Asciidoctor
28
30
  xml << node.content
29
31
  end
30
32
 
31
- def scope_parse(attrs, xml, node)
32
- xml.clause **attr_code(attrs) do |xml_section|
33
- xml_section.title { |t| t << "Scope" }
34
- content = node.content
35
- xml_section << content
36
- end
37
- end
38
-
39
33
  def section_attributes(node)
40
34
  super.merge(
41
35
  change: @amd ? node.attr("change") : nil,
@@ -75,7 +75,6 @@ module Asciidoctor
75
75
 
76
76
  def unique_text_id(text)
77
77
  return "term-#{text}" if xmldoc.at("//*[@id = 'term-#{text}']").nil?
78
-
79
78
  (1..Float::INFINITY).lazy.each do |index|
80
79
  if xmldoc.at("//*[@id = 'term-#{text}-#{index}']").nil?
81
80
  break("term-#{text}-#{index}")
@@ -7,6 +7,7 @@ module Asciidoctor
7
7
  foreword_validate(doc.root)
8
8
  normref_validate(doc.root)
9
9
  symbols_validate(doc.root)
10
+ sections_presence_validate(doc.root)
10
11
  sections_sequence_validate(doc.root)
11
12
  section_style(doc.root)
12
13
  subclause_validate(doc.root)
@@ -46,46 +47,44 @@ module Asciidoctor
46
47
  end
47
48
 
48
49
  def seqcheck(names, msg, accepted)
49
- n = names.shift
50
- unless accepted.include? n
50
+ n = names.shift
51
+ return [] if n.nil?
52
+ test = accepted.map { |a| n.at(a) }
53
+ if test.all? { |a| a.nil? }
51
54
  @log.add("Style", nil, msg)
52
- names = []
53
55
  end
54
56
  names
55
57
  end
56
58
 
59
+ def sections_presence_validate(root)
60
+ root.at("//sections/clause[@type = 'scope']") or
61
+ @log.add("Style", nil, "Scope clause missing")
62
+ root.at("//references[@normative = 'true']") or
63
+ @log.add("Style", nil, "Normative references missing")
64
+ root.at("//terms") or
65
+ @log.add("Style", nil, "Terms & definitions missing")
66
+ end
67
+
57
68
  # spec of permissible section sequence
58
69
  # we skip normative references, it goes to end of list
59
70
  SEQ =
60
71
  [
61
72
  {
62
73
  msg: "Initial section must be (content) Foreword",
63
- val: [{ tag: "foreword", title: "Foreword" }],
74
+ val: ["./self::foreword"]
64
75
  },
65
76
  {
66
77
  msg: "Prefatory material must be followed by (clause) Scope",
67
- val: [{ tag: "introduction", title: "Introduction" },
68
- { tag: "clause", title: "Scope" }],
78
+ val: ["./self::introduction", "./self::clause[@type = 'scope']" ]
69
79
  },
70
80
  {
71
81
  msg: "Prefatory material must be followed by (clause) Scope",
72
- val: [{ tag: "clause", title: "Scope" }],
82
+ val: ["./self::clause[@type = 'scope']" ]
73
83
  },
74
84
  {
75
85
  msg: "Normative References must be followed by "\
76
86
  "Terms and Definitions",
77
- val: [
78
- { tag: "terms", title: "Terms and definitions" },
79
- { tag: "clause", title: "Terms and definitions" },
80
- {
81
- tag: "terms",
82
- title: "Terms, definitions, symbols and abbreviated terms",
83
- },
84
- {
85
- tag: "clause",
86
- title: "Terms, definitions, symbols and abbreviated terms",
87
- },
88
- ],
87
+ val: ["./self::terms | .//terms"]
89
88
  },
90
89
  ].freeze
91
90
 
@@ -95,50 +94,47 @@ module Asciidoctor
95
94
  "//clause[descendant::references][not(parent::clause)]".freeze
96
95
 
97
96
  def sections_sequence_validate(root)
98
- f = root.xpath(SECTIONS_XPATH)
99
- names = f.map { |s| { tag: s.name, title: s&.at("./title")&.text } }
100
- names = seqcheck(names, SEQ[0][:msg], SEQ[0][:val]) || return
97
+ names = root.xpath(SECTIONS_XPATH)
98
+ names = seqcheck(names, SEQ[0][:msg], SEQ[0][:val])
101
99
  n = names[0]
102
- names = seqcheck(names, SEQ[1][:msg], SEQ[1][:val]) || return
103
- if n == { tag: "introduction", title: "Introduction" }
104
- names = seqcheck(names, SEQ[2][:msg], SEQ[2][:val]) || return
100
+ names = seqcheck(names, SEQ[1][:msg], SEQ[1][:val])
101
+ if n&.at("./self::introduction")
102
+ names = seqcheck(names, SEQ[2][:msg], SEQ[2][:val])
105
103
  end
106
- names = seqcheck(names, SEQ[3][:msg], SEQ[3][:val]) || return
104
+ names = seqcheck(names, SEQ[3][:msg], SEQ[3][:val])
107
105
  n = names.shift
108
- if n == { tag: "definitions", title: nil }
109
- n = names.shift || return
106
+ if n&.at("./self::definitions")
107
+ n = names.shift
110
108
  end
111
- unless n
109
+ if n.nil? || n.name != "clause"
112
110
  @log.add("Style", nil, "Document must contain at least one clause")
113
- return
114
111
  end
115
- n[:tag] == "clause" ||
112
+ n&.at("./self::clause") ||
116
113
  @log.add("Style", nil, "Document must contain clause after "\
117
114
  "Terms and Definitions")
118
- n == { tag: "clause", title: "Scope" } &&
115
+ n&.at("./self::clause[@type = 'scope']") &&
119
116
  @log.add("Style", nil, "Scope must occur before Terms and Definitions")
120
- n = names.shift || return
121
- while n[:tag] == "clause"
122
- n[:title] == "Scope" &&
117
+ n = names.shift
118
+ while n&.name == "clause"
119
+ n&.at("./self::clause[@type = 'scope']")
123
120
  @log.add("Style", nil, "Scope must occur before Terms and Definitions")
124
- n = names.shift || return
121
+ n = names.shift
125
122
  end
126
- unless n[:tag] == "annex" || n[:tag] == "references"
123
+ unless %w(annex references).include? n&.name
127
124
  @log.add("Style", nil, "Only annexes and references can follow clauses")
128
125
  end
129
- while n[:tag] == "annex"
126
+ while n&.name == "annex"
130
127
  n = names.shift
131
128
  if n.nil?
132
129
  @log.add("Style", nil, "Document must include (references) "\
133
130
  "Normative References")
134
- return
135
131
  end
136
132
  end
137
- n == { tag: "references", title: "Normative References" } ||
133
+ n&.at("./self::references[@normative = 'true']") ||
138
134
  @log.add("Style", nil, "Document must include (references) "\
139
135
  "Normative References")
140
- n = names.shift
141
- n == { tag: "references", title: "Bibliography" } ||
136
+ n = names&.shift
137
+ n&.at("./self::references[@normative = 'false']") ||
142
138
  @log.add("Style", nil, "Final section must be (references) Bibliography")
143
139
  names.empty? ||
144
140
  @log.add("Style", nil, "There are sections after the final Bibliography")
@@ -157,8 +153,8 @@ module Asciidoctor
157
153
  def section_style(root)
158
154
  foreword_style(root.at("//foreword"))
159
155
  introduction_style(root.at("//introduction"))
160
- scope_style(root.at("//clause[title = 'Scope']"))
161
- scope = root.at("//clause[title = 'Scope']/clause")
156
+ scope_style(root.at("//clause[@type = 'scope']"))
157
+ scope = root.at("//clause[@type = 'scope']/clause")
162
158
  # ISO/IEC DIR 2, 14.4
163
159
  scope.nil? || style_warning(scope, SCOPE_WARN, nil)
164
160
  end