metanorma-iso 1.4.3 → 1.5.4

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