metanorma-iso 1.3.25 → 1.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/macos.yml +0 -1
  3. data/.github/workflows/ubuntu.yml +6 -3
  4. data/.github/workflows/windows.yml +0 -1
  5. data/Gemfile +1 -0
  6. data/Rakefile +2 -0
  7. data/lib/asciidoctor/iso/base.rb +16 -13
  8. data/lib/asciidoctor/iso/biblio.rng +14 -4
  9. data/lib/asciidoctor/iso/cleanup.rb +1 -1
  10. data/lib/asciidoctor/iso/front.rb +3 -155
  11. data/lib/asciidoctor/iso/front_id.rb +196 -0
  12. data/lib/asciidoctor/iso/isodoc.rng +444 -1
  13. data/lib/asciidoctor/iso/isostandard.rng +10 -1
  14. data/lib/asciidoctor/iso/reqt.rng +23 -0
  15. data/lib/asciidoctor/iso/term_lookup_cleanup.rb +7 -10
  16. data/lib/asciidoctor/iso/validate.rb +1 -5
  17. data/lib/asciidoctor/iso/validate_requirements.rb +1 -1
  18. data/lib/asciidoctor/iso/validate_style.rb +6 -5
  19. data/lib/asciidoctor/iso/validate_title.rb +1 -1
  20. data/lib/isodoc/iso/base_convert.rb +67 -112
  21. data/lib/isodoc/iso/html/header.html +5 -1
  22. data/lib/isodoc/iso/html/html_iso_titlepage.html +9 -0
  23. data/lib/isodoc/iso/html/htmlstyle.scss +0 -1
  24. data/lib/isodoc/iso/html/isodoc.scss +25 -1
  25. data/lib/isodoc/iso/html/style-human.scss +8 -1
  26. data/lib/isodoc/iso/html/style-iso.scss +8 -1
  27. data/lib/isodoc/iso/html/word_iso_intro.html +4 -0
  28. data/lib/isodoc/iso/html/word_iso_titlepage.html +4 -4
  29. data/lib/isodoc/iso/html/wordstyle.scss +20 -7
  30. data/lib/isodoc/iso/iso.amendment.xsl +5114 -0
  31. data/lib/isodoc/iso/iso.international-standard.xsl +1258 -530
  32. data/lib/isodoc/iso/metadata.rb +31 -27
  33. data/lib/isodoc/iso/pdf_convert.rb +5 -11
  34. data/lib/isodoc/iso/presentation_xml_convert.rb +13 -0
  35. data/lib/isodoc/iso/sections.rb +66 -0
  36. data/lib/isodoc/iso/sts_convert.rb +31 -0
  37. data/lib/isodoc/iso/xref.rb +111 -0
  38. data/lib/metanorma-iso.rb +2 -0
  39. data/lib/metanorma/iso/processor.rb +14 -8
  40. data/lib/metanorma/iso/version.rb +1 -1
  41. data/metanorma-iso.gemspec +6 -2
  42. data/spec/asciidoctor-iso/amd_spec.rb +412 -4
  43. data/spec/asciidoctor-iso/base_spec.rb +18 -16
  44. data/spec/asciidoctor-iso/cleanup_spec.rb +2 -2
  45. data/spec/asciidoctor-iso/macros_spec.rb +33 -17
  46. data/spec/asciidoctor-iso/refs_spec.rb +1 -1
  47. data/spec/asciidoctor-iso/table_spec.rb +1 -1
  48. data/spec/isodoc/amd_spec.rb +652 -0
  49. data/spec/isodoc/blocks_spec.rb +112 -27
  50. data/spec/isodoc/inline_spec.rb +2 -2
  51. data/spec/isodoc/metadata_spec.rb +88 -4
  52. data/spec/isodoc/postproc_spec.rb +9 -9
  53. data/spec/isodoc/ref_spec.rb +6 -6
  54. data/spec/isodoc/section_spec.rb +28 -1
  55. data/spec/isodoc/table_spec.rb +8 -8
  56. data/spec/isodoc/terms_spec.rb +4 -4
  57. data/spec/isodoc/xref_spec.rb +24 -18
  58. data/spec/metanorma/processor_spec.rb +2 -2
  59. metadata +73 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 766cfd076caf6c78f48542cc22353664f2ee4667be97659e201643418b4990ad
4
- data.tar.gz: 667d8b7ed3ac77f49a88cd74cae0eaa3f097c2d65c3ed4269806351fdc87e07e
3
+ metadata.gz: d1cf4345d777fb37031e719c6121a5f27fd23dc56ebacab1a099aa2c108a82d2
4
+ data.tar.gz: d571ce7dcd5a38ebc7e19460b7ab65e2f77499ab46a836d74857d7f6eb78f88d
5
5
  SHA512:
6
- metadata.gz: 35ab4b8f52d75727d867920d7de2bd8696e37e38715dcc3895fe67f821311b6a13ac71e5d3a65096694ce800972e81fce5a881d861b534d911cdfcdf17d6f73f
7
- data.tar.gz: 3d11aecb223c66aa9b2cc1c68bd9b6c227b6ea4710b3afa11556ba0351d969efcf8b39911899670aeab7af43ea6b1aeee8ba56196c575fd802fcb250cfb0a622
6
+ metadata.gz: 8ed62ccec92b596bb8063267750c04e1df0ffc6376d2339b5771b1780400c526041793d37a1cb115117dafb35e45d1f680244d1ce1bd975a010703ec9bbaff25
7
+ data.tar.gz: 97a5255d0a7ee3992dde8b88b005aa3aab743ed03f2b0983cb7c02bea1b010c988f28ad1f1bbf9086356ff32f2a6eb8fed164b65b20887a83fa58da2e49500d9
@@ -29,7 +29,6 @@ jobs:
29
29
  uses: actions/setup-ruby@v1
30
30
  with:
31
31
  ruby-version: ${{ matrix.ruby }}
32
- architecture: 'x64'
33
32
  - name: Update gems
34
33
  run: |
35
34
  sudo gem install bundler --force
@@ -29,14 +29,17 @@ jobs:
29
29
  uses: actions/setup-ruby@v1
30
30
  with:
31
31
  ruby-version: ${{ matrix.ruby }}
32
- architecture: 'x64'
33
32
  - name: Update gems
34
33
  run: |
35
34
  gem install bundler
36
35
  bundle install --jobs 4 --retry 3
37
36
  - name: Install PlantUML
38
- run: |
39
- sudo bash -c "curl -L https://github.com/riboseinc/plantuml-install/raw/master/ubuntu.sh | bash"
37
+ uses: nick-invision/retry@v1
38
+ with:
39
+ polling_interval_seconds: 5
40
+ timeout_minutes: 5
41
+ max_attempts: 3
42
+ command: sudo bash -c "curl -L https://github.com/metanorma/plantuml-install/raw/master/ubuntu.sh | bash"
40
43
  - name: Run specs
41
44
  run: |
42
45
  bundle exec rake
@@ -29,7 +29,6 @@ jobs:
29
29
  uses: actions/setup-ruby@v1
30
30
  with:
31
31
  ruby-version: ${{ matrix.ruby }}
32
- architecture: 'x64'
33
32
  - name: Update gems
34
33
  shell: pwsh
35
34
  run: |
data/Gemfile CHANGED
@@ -5,6 +5,7 @@ source "https://rubygems.org"
5
5
  git_source(:github) { |repo| "https://github.com/#{repo}" }
6
6
 
7
7
  #gem "asciimath", git: "https://github.com/asciidoctor/asciimath"
8
+
8
9
  gemspec
9
10
 
10
11
  if File.exist? 'Gemfile.devel'
data/Rakefile CHANGED
@@ -1,6 +1,8 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rspec/core/rake_task"
3
+ require 'isodoc/gem_tasks'
3
4
 
5
+ IsoDoc::GemTasks.install
4
6
  RSpec::Core::RakeTask.new(:spec)
5
7
 
6
8
  task default: :spec
@@ -36,25 +36,28 @@ module Asciidoctor
36
36
  IsoDoc::Iso::PdfConvert.new(doc_extract_attributes(node))
37
37
  end
38
38
 
39
+ def sts_converter(node)
40
+ return nil if node.attr("no-pdf")
41
+ IsoDoc::Iso::StsConvert.new(html_extract_attributes(node))
42
+ end
43
+
44
+ def presentation_xml_converter(node)
45
+ IsoDoc::Iso::PresentationXMLConvert.new(html_extract_attributes(node))
46
+ end
47
+
39
48
  def init(node)
40
49
  super
41
50
  @amd = %w(amendment technical-corrigendum).include? node.attr("doctype")
42
51
  end
43
52
 
44
- def document(node)
45
- init(node)
46
- ret = makexml(node).to_xml(indent: 2)
47
- unless node.attr("nodoc") || !node.attr("docfile")
53
+ def outputs(node, ret)
48
54
  File.open(@filename + ".xml", "w:UTF-8") { |f| f.write(ret) }
49
- html_converter_alt(node).convert(@filename + ".xml")
50
- FileUtils.mv "#{@filename}.html", "#{@filename}_alt.html"
51
- html_converter(node).convert(@filename + ".xml")
52
- doc_converter(node).convert(@filename + ".xml")
53
- pdf_converter(node)&.convert(@filename + ".xml")
54
- end
55
- @log.write(@localdir + @filename + ".err") unless @novalid
56
- @files_to_delete.each { |f| FileUtils.rm f }
57
- ret
55
+ 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")
60
+ #sts_converter(node)&.convert(@filename + ".xml")
58
61
  end
59
62
 
60
63
  def load_yaml(lang, script)
@@ -532,7 +532,7 @@
532
532
  </define>
533
533
  <define name="LocalityType">
534
534
  <data type="string">
535
- <param name="pattern">section|clause|part|paragraph|chapter|page|whole|table|annex|figure|note|list|example|volume|issue|time|locality:[a-zA-Z0-9_]+</param>
535
+ <param name="pattern">section|clause|part|paragraph|chapter|page|whole|table|annex|figure|note|list|example|volume|issue|time|anchor|locality:[a-zA-Z0-9_]+</param>
536
536
  </data>
537
537
  </define>
538
538
  <define name="referenceFrom">
@@ -661,9 +661,9 @@
661
661
  <optional>
662
662
  <ref name="status"/>
663
663
  </optional>
664
- <optional>
664
+ <zeroOrMore>
665
665
  <ref name="copyright"/>
666
- </optional>
666
+ </zeroOrMore>
667
667
  <zeroOrMore>
668
668
  <ref name="docrelation"/>
669
669
  </zeroOrMore>
@@ -1021,7 +1021,17 @@
1021
1021
  <optional>
1022
1022
  <ref name="to"/>
1023
1023
  </optional>
1024
- <ref name="owner"/>
1024
+ <oneOrMore>
1025
+ <ref name="owner"/>
1026
+ </oneOrMore>
1027
+ <optional>
1028
+ <ref name="copyright_scope"/>
1029
+ </optional>
1030
+ </element>
1031
+ </define>
1032
+ <define name="copyright_scope">
1033
+ <element name="scope">
1034
+ <text/>
1025
1035
  </element>
1026
1036
  </define>
1027
1037
  <define name="from">
@@ -53,7 +53,7 @@ module Asciidoctor
53
53
  # ISO as a prefix goes first
54
54
  def docidentifier_cleanup(xmldoc)
55
55
  prefix = get_id_prefix(xmldoc)
56
- id = xmldoc.at("//bibdata/docidentifier[@type = 'iso']") or return
56
+ id = xmldoc.at("//bibdata/docidentifier[@type = 'ISO']") or return
57
57
  id.content = id_prefix(prefix, id)
58
58
  id = xmldoc.at("//bibdata/ext/structuredidentifier/project-number") and
59
59
  id.content = id_prefix(prefix, id)
@@ -5,154 +5,20 @@ 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
- 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 international standard",
30
- "50": "Final draft international standard",
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
- return "PRF" if stage == "60" && substage == "00"
39
- ret = STAGE_ABBRS[stage.to_sym]
40
- ret = "DTS" if ret == "DIS" && %w(technical-report technical-specification).include?(doctype)
41
- ret = "FDTS" if ret == "FDIS" && %w(technical-report technical-specification).include?(doctype)
42
- ret
43
- end
44
-
45
- def stage_name(stage, substage, doctype)
46
- return "Proof" if stage == "60" && substage == "00"
47
- ret = STAGE_NAMES[stage.to_sym]
48
- if %w(technical-report technical-specification).include? doctype
49
- ret = "Draft technical standard" if ret == "Draft international standard"
50
- ret = "Final draft technical standard" if ret == "Final draft international standard"
51
- end
52
- ret
53
- end
54
-
55
- def metadata_id(node, xml)
56
- iso_id(node, xml)
57
- node&.attr("tc-docnumber")&.split(/,\s*/)&.each do |n|
58
- xml.docidentifier(n, **attr_code(type: "iso-tc"))
59
- end
60
- xml.docnumber node&.attr("docnumber")
61
- end
62
-
63
- def iso_id(node, xml)
64
- return unless !@amd && node.attr("docnumber") || @amd && node.attr("updates")
65
- dn = iso_id1(node)
66
- dn1 = id_stage_prefix(dn, node, false)
67
- dn2 = id_stage_prefix(dn, node, true)
68
- xml.docidentifier dn1, **attr_code(type: "iso")
69
- xml.docidentifier id_langsuffix(dn1, node), **attr_code(type: "iso-with-lang")
70
- xml.docidentifier id_langsuffix(dn2, node), **attr_code(type: "iso-reference")
71
- end
72
-
73
- def iso_id1(node)
74
- if @amd
75
- dn = node.attr("updates")
76
- return add_amd_parts(dn, node)
77
- else
78
- part, subpart = node&.attr("partnumber")&.split(/-/)
79
- dn = add_id_parts(node.attr("docnumber"), part, subpart)
80
- end
81
- end
82
-
83
- def add_amd_parts(dn, node)
84
- a = node.attr("amendment-number")
85
- c = node.attr("corrigendum-number")
86
- case node.attr("doctype")
87
- when "amendment"
88
- "#{dn}/Amd.#{node.attr('amendment-number')}"
89
- when "technical corrigendum"
90
- "#{dn}/Cor.#{node.attr('corrigendum-number')}"
91
- end
92
- end
93
-
94
- def id_langsuffix(dn, node)
95
- lang = node.attr("language") || "en"
96
- suffix = case lang
97
- when "en" then "(E)"
98
- when "fr" then "(F)"
99
- else
100
- "(X)"
101
- end
102
- "#{dn}#{suffix}"
103
- end
104
-
105
13
  def metadata_ext(node, xml)
106
14
  super
107
15
  structured_id(node, xml)
108
- xml.stagename stage_name(get_stage(node), get_substage(node), node.attr("doctype"))
16
+ xml.stagename stage_name(get_stage(node), get_substage(node),
17
+ node.attr("doctype"), node.attr("iteration"))
109
18
  @amd && a = node.attr("updates-document-type") and
110
19
  xml.updates_document_type a
111
20
  end
112
21
 
113
- def structured_id(node, xml)
114
- return unless node.attr("docnumber")
115
- part, subpart = node&.attr("partnumber")&.split(/-/)
116
- xml.structuredidentifier do |i|
117
- i.project_number node.attr("docnumber"),
118
- **attr_code(part: part, subpart: subpart, amendment: node.attr("amendment-number"),
119
- corrigendum: node.attr("corrigendum-number"), origyr: node.attr("created-date"))
120
- end
121
- end
122
-
123
- def add_id_parts(dn, part, subpart)
124
- dn += "-#{part}" if part
125
- dn += "-#{subpart}" if subpart
126
- dn
127
- end
128
-
129
- def id_stage_abbr(stage, substage, node)
130
- IsoDoc::Iso::Metadata.new("en", "Latn", {}).
131
- status_abbrev(stage_abbr(stage, substage, node.attr("doctype")),
132
- substage, node.attr("iteration"),
133
- node.attr("draft"), node.attr("doctype"))
134
- end
135
-
136
- def id_stage_prefix(dn, node, force_year)
137
- stage = get_stage(node)
138
- substage = get_substage(node)
139
- typeabbr = get_typeabbr(node)
140
- if stage && (stage.to_i < 60)
141
- abbr = id_stage_abbr(stage, substage, node)
142
- unless abbr.nil? || abbr.empty? # prefixes added in cleanup
143
- dn = @amd ? dn.sub(/ /, "/#{abbr} ") : "/#{abbr} #{typeabbr}#{dn}"
144
- end
145
- elsif typeabbr && !@amd
146
- dn = "/#{typeabbr}#{dn}"
147
- end
148
- if force_year || !(stage && (stage.to_i < 60))
149
- year = @amd ? (node.attr("copyright-year") || node.attr("updated-date").sub(/-.*$/, "")) :
150
- node.attr("copyright-year")
151
- dn += ":#{year}" if year
152
- end
153
- dn
154
- end
155
-
156
22
  def organization(org, orgname)
157
23
  if ["ISO",
158
24
  "International Organization for Standardization"].include? orgname
@@ -199,24 +65,6 @@ module Asciidoctor
199
65
  end
200
66
  end
201
67
 
202
- def get_stage(node)
203
- stage = node.attr("status") || node.attr("docstage") || "60"
204
- end
205
-
206
- def get_substage(node)
207
- stage = get_stage(node)
208
- node.attr("docsubstage") || ( stage == "60" ? "60" : "00" )
209
- end
210
-
211
- def get_typeabbr(node)
212
- case node.attr("doctype")
213
- when "technical-report" then "TR "
214
- when "technical-specification" then "TS "
215
- else
216
- nil
217
- end
218
- end
219
-
220
68
  def metadata_status(node, xml)
221
69
  stage = get_stage(node)
222
70
  substage = get_substage(node)
@@ -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