metanorma-nist 1.0.4 → 1.0.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -107,7 +107,7 @@ module Asciidoctor
107
107
  File.open(filename, "w:UTF-8") { |f| f.write(ret) }
108
108
  html_converter(node).convert filename unless node.attr("nodoc")
109
109
  word_converter(node).convert filename unless node.attr("nodoc")
110
- pdf_converter(node).convert filename unless node.attr("nodoc")
110
+ pdf_converter(node)&.convert filename unless node.attr("nodoc")
111
111
  end
112
112
  @log.write(@localdir + @filename + ".err") unless @novalid
113
113
  @files_to_delete.each { |f| FileUtils.rm f }
@@ -151,36 +151,12 @@ module Asciidoctor
151
151
  end
152
152
  end
153
153
 
154
- def section(node)
155
- a = section_attributes(node)
156
- noko do |xml|
157
- case sectiontype(node)
158
- #when "normative references" then norm_ref_parse(a, xml, node)
159
- when "terms and definitions"
160
- if node.attr("style") == "appendix" && node.level == 1
161
- @term_def = true
162
- terms_annex_parse(a, xml, node)
163
- @term_def = false
164
- else
165
- clause_parse(a, xml, node)
166
- end
167
- when "acknowledgements"
168
- acknowledgements_parse(a, xml, node)
169
- else
170
- if @term_def
171
- term_def_subclause_parse(a, xml, node)
172
- elsif @biblio then bibliography_parse(a, xml, node)
173
- elsif node.attr("style") == "bibliography"
174
- bibliography_parse(a, xml, node)
175
- elsif node.attr("style") == "abstract"
176
- abstract_parse(a, xml, node)
177
- elsif node.attr("style") == "appendix" && node.level == 1
178
- annex_parse(a, xml, node)
179
- else
180
- clause_parse(a, xml, node)
181
- end
182
- end
183
- end.join("\n")
154
+ def term_def_parse(attrs, xml, node, toplevel)
155
+ if node.attr("style") == "appendix" && node.level == 1
156
+ terms_annex_parse(attrs, xml, node)
157
+ else
158
+ clause_parse(attrs, xml, node)
159
+ end
184
160
  end
185
161
 
186
162
  def bibliography_parse(a, xml, node)
@@ -236,6 +212,7 @@ module Asciidoctor
236
212
  end
237
213
 
238
214
  def pdf_converter(node)
215
+ return nil if node.attr("no-pdf")
239
216
  IsoDoc::NIST::PdfConvert.new(html_extract_attributes(node))
240
217
  end
241
218
  end
@@ -20,6 +20,7 @@ module Asciidoctor
20
20
  def metadata_version(node, xml)
21
21
  xml.edition node.attr("edition") if node.attr("edition")
22
22
  xml.edition "Revision #{node.attr("revision")}" if node.attr("revision")
23
+ xml.edition "Version #{node.attr("version")}" if node.attr("version")
23
24
  xml.version do |v|
24
25
  v.revision_date node.attr("revdate") if node.attr("revdate")
25
26
  v.draft node.attr("draft") if node.attr("draft")
@@ -46,7 +47,7 @@ module Asciidoctor
46
47
 
47
48
  def title_main(node, t, at)
48
49
  t.title(**attr_code(at.merge(type: "main"))) do |t1|
49
- t1 << Asciidoctor::Standoc::Utils::asciidoc_sub(node.attr("title-main") || node.title)
50
+ t1 << (Asciidoctor::Standoc::Utils::asciidoc_sub(node.attr("title-main")) || node.title)
50
51
  end
51
52
  node.attr("title-main-short") and
52
53
  t.title(**attr_code(at.merge(type: "short-title"))) do |t1|
@@ -144,20 +145,26 @@ module Asciidoctor
144
145
  end
145
146
 
146
147
  def relaton_relations
147
- super + %w(obsoletes obsoleted-by supersedes superseded-by)
148
+ super + %w(obsoletes obsoleted-by)
148
149
  end
149
150
 
150
- def metadata_getrelation(node, xml, type)
151
- if type == "obsoleted-by" and node.attr("superseding-status")
151
+ def relaton_relation_descriptions
152
+ super.merge({
153
+ "supersedes" => "obsoletes",
154
+ "superseded-by" => "obsoleted-by",
155
+ })
156
+ end
157
+
158
+ def metadata_getrelation(node, xml, type, desc = nil)
159
+ if type == "obsoleted-by" and desc.nil? and node.attr("superseding-status")
152
160
  metadata_superseding_doc(node, xml)
153
- else
154
- super
155
161
  end
162
+ super
156
163
  end
157
164
 
158
165
  def metadata_superseding_doc(node, xml)
159
166
  xml.relation **{ type: "obsoletedBy" } do |r|
160
- r.bibitem do |b|
167
+ r.bibitem **{ type: "standard" } do |b|
161
168
  metadata_superseding_titles(b, node)
162
169
  doi = node.attr("superseding-doi") and
163
170
  b.uri doi, **{ type: "doi" }
@@ -197,16 +204,21 @@ module Asciidoctor
197
204
 
198
205
  def metadata_superseding_titles(b, node)
199
206
  if node.attr("superseding-title")
200
- b.title Asciidoctor::Standoc::Utils::asciidoc_sub(node.attr("superseding-title")),
201
- **{ type: "main" }
207
+ b.title **{ type: "main" } do |t|
208
+ t << Asciidoctor::Standoc::Utils::asciidoc_sub(node.attr("superseding-title"))
209
+ end
202
210
  node.attr("superseding-subtitle") and
203
- b.title Asciidoctor::Standoc::Utils::asciidoc_sub(node.attr("superseding-subtitle")),
204
- **{ type: "subtitle" }
211
+ b.title **{ type: "subtitle" } do |t|
212
+ t << Asciidoctor::Standoc::Utils::asciidoc_sub(node.attr("superseding-subtitle"))
213
+ end
205
214
  else
206
- b.title Asciidoctor::Standoc::Utils::asciidoc_sub(node.attr("title-main") || node.title),
207
- **{ type: "main" }
215
+ b.title **{ type: "main" } do |t|
216
+ t << (Asciidoctor::Standoc::Utils::asciidoc_sub(node.attr("title-main")) || node.title)
217
+ end
208
218
  node.attr("title-sub") and
209
- b.title Asciidoctor::Standoc::Utils::asciidoc_sub(node.attr("title-sub")), **{ type: "subtitle" }
219
+ b.title **{ type: "subtitle" } do |t|
220
+ t << Asciidoctor::Standoc::Utils::asciidoc_sub(node.attr("title-sub"))
221
+ end
210
222
  end
211
223
  end
212
224
 
@@ -1,17 +1,16 @@
1
+ require "iso-639"
2
+
1
3
  module Asciidoctor
2
4
  module NIST
3
5
  class Converter < Standoc::Converter
4
6
  def metadata_id(node, xml)
5
7
  did = node.attr("docidentifier")
6
8
  dn = node.attr("docnumber")
7
- dn = Iso690Render.MMMddyyyy(node.attr("issued-date")) if @series == "nist-cswp" and !dn
8
- if did
9
- xml.docidentifier did, **attr_code(type: "NIST")
10
- xml.docidentifier unabbreviate(did), **attr_code(type: "nist-long")
11
- else
12
- metadata_id_compose(node, xml, dn)
13
- end
14
- xml.docnumber node.attr("docnumber")
9
+ @series == "nist-cswp" && !node.attr("docnumber") and
10
+ dn = Iso690Render.MMMddyyyy(node.attr("issued-date"))
11
+ metadata_id_compose(node, xml, dn, did)
12
+ xml.docnumber node.attr("docnumber") ||
13
+ did&.sub(/^[^0-9]*/, "")&.sub(/[ -].*$/, "")
15
14
  end
16
15
 
17
16
  def unabbreviate(did)
@@ -21,26 +20,42 @@ module Asciidoctor
21
20
  end
22
21
 
23
22
  def id_args(node, dn0)
23
+ return nil unless dn0
24
24
  {
25
25
  id: dn0,
26
26
  series: node.attr("series"),
27
+ edition: node.attr("edition"),
28
+ version: node.attr("version"),
27
29
  revision: node.attr("revision"),
30
+ update: node.attr("update"),
31
+ year: (node.attr("copyright-year") || node.attr("updated-date") ||
32
+ node.attr("revdate") || node.attr("circulated-date") ||
33
+ Date.today.year.to_s).sub(/^(....).*$/, "\\1"),
28
34
  vol: node.attr("volume"),
35
+ part: node.attr("part") || node.attr("part-number"),
36
+ section: node.attr("section") || node.attr("section-number"),
37
+ supplement: node.attr("supplement") || node.attr("supplement-number"),
38
+ index: node.attr("index") || node.attr("index-number"),
29
39
  stage: node.attr("status") || node.attr("docstage"),
30
40
  iter: node.attr("iteration"),
41
+ language: node.attr("language") || "en",
31
42
  date: /^draft/.match(node.attr("status") || node.attr("docstage")) ?
32
43
  (node.attr("circulated-date") || node.attr("revdate")) :
33
44
  node.attr("updated-date")
34
45
  }
35
46
  end
36
47
 
37
- def metadata_id_compose(node, xml, dn0)
38
- return unless dn0
39
- args = id_args(node, dn0)
40
- xml.docidentifier add_id_parts(args, false), **attr_code(type: "NIST")
41
- xml.docidentifier add_id_parts(args, true),
42
- **attr_code(type: "nist-long")
43
- xml.docidentifier add_id_parts_mr(args), **attr_code(type: "nist-mr")
48
+ def metadata_id_compose(node, xml, dn0, did)
49
+ if did
50
+ xml.docidentifier did, **attr_code(type: "NIST")
51
+ xml.docidentifier unabbreviate(did), **attr_code(type: "nist-long")
52
+ else
53
+ args = id_args(node, dn0) || return
54
+ xml.docidentifier add_id_parts(args, false), **attr_code(type: "NIST")
55
+ xml.docidentifier add_id_parts(args, true),
56
+ **attr_code(type: "nist-long")
57
+ xml.docidentifier add_id_parts_mr(args), **attr_code(type: "nist-mr")
58
+ end
44
59
  end
45
60
 
46
61
  def MMMddyyyy(isodate)
@@ -48,26 +63,61 @@ module Asciidoctor
48
63
  Date.parse(isodate).strftime("%B %d, %Y")
49
64
  end
50
65
 
66
+ def status_abbr(stage, iter)
67
+ IsoDoc::NIST::Metadata.new(nil, nil, {}).status_abbr(stage, iter)
68
+ end
69
+
51
70
  def add_id_parts(args, long)
52
- vol_delim = " Volume "
53
- ed_delim = " Revision "
54
71
  args[:series] and series_name = long ?
55
72
  SERIES.dig(args[:series].to_sym) :
56
73
  SERIES_ABBR.dig(args[:series].to_sym)
57
74
  dn = (series_name || "NIST #{args[:series]}") + " " + args[:id]
58
- dn += "#{vol_delim}#{args[:vol]}" if args[:vol]
75
+ dn += " Volume #{args[:vol]}" if args[:vol]
59
76
  dn += "," if args[:vol] && args[:revision]
60
- dn += "#{ed_delim}#{args[:revision]}" if args[:revision]
61
- stage = IsoDoc::NIST::Metadata.new(nil, nil, {}).status_abbr(args[:stage], args[:iter])
62
- dn += " (#{stage})" if stage
77
+ dn += " Revision #{args[:revision]}" if args[:revision]
78
+ dn += "/Upd #{args[:update]}:#{args[:year]}" if args[:update]
79
+ stage = status_abbr(args[:stage], args[:iter]) and dn += " (#{stage})"
63
80
  dn += " (#{MMMddyyyy(args[:date])})" if args[:date]
64
81
  dn
65
82
  end
66
83
 
84
+ def id_parts_mr(args)
85
+ part = []
86
+ part << "v-#{args[:vol]}" if args[:vol]
87
+ part << "pt-#{args[:part]}" if args[:part]
88
+ part << "sec-#{args[:section]}" if args[:section]
89
+ part << "sup-#{args[:supplement]}" if args[:supplement]
90
+ part << "indx-#{args[:index]}" if args[:index]
91
+ part
92
+ end
93
+
94
+ def id_editions_mr(args)
95
+ part = []
96
+ part << "e-#{args[:edition]}" if args[:edition]
97
+ part << "r-#{args[:revision]}" if args[:revision]
98
+ part << "ver-#{args[:version]}" if args[:version]
99
+ part
100
+ end
101
+
102
+ def id_lang_mr(args)
103
+ ret = args[:language].split(/,\s*/).map do |l|
104
+ ISO_639.find(l).alpha3
105
+ end.join(",")
106
+ end
107
+
67
108
  def add_id_parts_mr(args)
109
+ ret = ["NIST"]
68
110
  args[:series] and
69
- name = SERIES_ABBR&.dig(args[:series].to_sym)&.sub(/^NIST /, "")
70
- "NIST.#{name}.#{args[:id]}.#{args[:vol]}.#{args[:revision]}.#{args[:date]}"
111
+ ret << SERIES_ABBR&.dig(args[:series].to_sym)&.sub(/^NIST /, "")
112
+ stage = status_abbr(args[:stage], nil) || ""
113
+ stage += "[-#{args[:iter]}]" if args[:iter]
114
+ ret << stage unless stage.empty?
115
+ ret << args[:id]
116
+ ret += id_parts_mr(args)
117
+ ret += id_editions_mr(args)
118
+ ret << id_lang_mr(args)
119
+ args[:update] and ret << "upd-#{args[:update]}:#{args[:year]}"
120
+ ret.join(".")
71
121
  end
72
122
  end
73
123
  end
@@ -53,6 +53,14 @@
53
53
  <optional>
54
54
  <attribute name="alt"/>
55
55
  </optional>
56
+ <optional>
57
+ <attribute name="case">
58
+ <choice>
59
+ <value>capital</value>
60
+ <value>lowercase</value>
61
+ </choice>
62
+ </attribute>
63
+ </optional>
56
64
  <text/>
57
65
  </element>
58
66
  </define>
@@ -129,6 +137,9 @@
129
137
  </choice>
130
138
  </attribute>
131
139
  </optional>
140
+ <attribute name="normative">
141
+ <data type="boolean"/>
142
+ </attribute>
132
143
  <optional>
133
144
  <ref name="section-title"/>
134
145
  </optional>
@@ -305,6 +316,21 @@
305
316
  </define>
306
317
  </include>
307
318
  <!-- end overrides -->
319
+ <define name="TextElement" combine="choice">
320
+ <ref name="concept"/>
321
+ </define>
322
+ <define name="concept">
323
+ <element name="concept">
324
+ <optional>
325
+ <attribute name="term"/>
326
+ </optional>
327
+ <choice>
328
+ <ref name="eref"/>
329
+ <ref name="xref"/>
330
+ <ref name="termref"/>
331
+ </choice>
332
+ </element>
333
+ </define>
308
334
  <define name="BasicBlock" combine="choice">
309
335
  <choice>
310
336
  <ref name="requirement"/>
@@ -884,7 +910,15 @@
884
910
  <attribute name="id">
885
911
  <data type="ID"/>
886
912
  </attribute>
887
- <ref name="paragraph"/>
913
+ <oneOrMore>
914
+ <choice>
915
+ <ref name="paragraph"/>
916
+ <ref name="ul"/>
917
+ <ref name="ol"/>
918
+ <ref name="dl"/>
919
+ <ref name="formula"/>
920
+ </choice>
921
+ </oneOrMore>
888
922
  </element>
889
923
  </define>
890
924
  <define name="termexample">
@@ -911,7 +945,10 @@
911
945
  </define>
912
946
  <define name="origin">
913
947
  <element name="origin">
914
- <ref name="erefType"/>
948
+ <choice>
949
+ <ref name="erefType"/>
950
+ <ref name="termref"/>
951
+ </choice>
915
952
  </element>
916
953
  </define>
917
954
  <define name="modification">
@@ -919,6 +956,15 @@
919
956
  <ref name="paragraph"/>
920
957
  </element>
921
958
  </define>
959
+ <define name="termref">
960
+ <element name="termref">
961
+ <attribute name="base"/>
962
+ <attribute name="target"/>
963
+ <optional>
964
+ <text/>
965
+ </optional>
966
+ </element>
967
+ </define>
922
968
  <define name="structuredidentifier">
923
969
  <element name="structuredidentifier">
924
970
  <optional>
@@ -2,20 +2,12 @@ require "isodoc"
2
2
  require_relative "metadata"
3
3
  require_relative "xrefs"
4
4
  require_relative "refs"
5
+ require_relative "section"
5
6
  require "fileutils"
6
7
 
7
8
  module IsoDoc
8
9
  module NIST
9
10
  module BaseConvert
10
- def abstract(isoxml, out)
11
- f = isoxml.at(ns("//preface/abstract")) || return
12
- #page_break(out)
13
- out.div **attr_code(id: f["id"]) do |s|
14
- clause_name(nil, @abstract_lbl, s, class: "AbstractTitle")
15
- f.elements.each { |e| parse(e, s) unless e.name == "title" }
16
- end
17
- end
18
-
19
11
  def keywords(_docxml, out)
20
12
  kw = @meta.get[:keywords]
21
13
  kw.empty? and return
@@ -25,27 +17,8 @@ module IsoDoc
25
17
  end
26
18
  end
27
19
 
28
- FRONT_CLAUSE = "//*[parent::preface][not(local-name() = 'abstract' or local-name() = 'foreword')]".freeze
29
-
30
- # All "[preface]" sections should have class "IntroTitle" to prevent
31
- # page breaks
32
- # But for the Exec Summary
33
- def preface(isoxml, out)
34
- isoxml.xpath(ns(FRONT_CLAUSE)).each do |c|
35
- next if skip_render(c, isoxml)
36
- title = c&.at(ns("./title"))
37
- patent = ["Call for Patent Claims", "Patent Disclosure Notice"].include? title&.text
38
- out.div **attr_code(id: c["id"]) do |s|
39
- page_break(s) if patent
40
- clause_name(anchor(c['id'], :label), title, s,
41
- class: (c.name == "executivesummary") ? "NormalTitle" :
42
- "IntroTitle")
43
- c.elements.reject { |c1| c1.name == "title" }.each do |c1|
44
- parse(c1, s)
45
- end
46
- end
47
- end
48
- end
20
+ FRONT_CLAUSE = "//*[parent::preface][not(local-name() = 'abstract' or "\
21
+ "local-name() = 'foreword')]".freeze
49
22
 
50
23
  def skip_render(c, isoxml)
51
24
  return false unless c.name == "reviewernote"
@@ -157,13 +130,13 @@ module IsoDoc
157
130
  "//terms[parent::sections]".freeze
158
131
 
159
132
  def middle(isoxml, out)
133
+ middle_admonitions(isoxml, out)
160
134
  clause isoxml, out
161
135
  bibliography isoxml, out
162
136
  annex isoxml, out
163
137
  end
164
138
 
165
139
  def info(isoxml, out)
166
- @meta.keywords isoxml, out
167
140
  @meta.series isoxml, out
168
141
  @meta.commentperiod isoxml, out
169
142
  @meta.note isoxml, out
@@ -176,13 +149,15 @@ module IsoDoc
176
149
  end
177
150
 
178
151
  def get_linkend(node)
179
- link = anchor_linkend(node, docid_l10n(node["target"] || wrap_brackets(node['citeas'])))
180
- link += eref_localities(node.xpath(ns("./locality")), link)
181
- contents = node.children.select { |c| c.name != "locality" }
152
+ link = anchor_linkend(node, docid_l10n(node["target"] ||
153
+ wrap_brackets(node['citeas'])))
154
+ link += eref_localities(node.xpath(ns("./locality | ./localityStack")),
155
+ link)
156
+ contents = node.children.select do |c|
157
+ !%w{locality localityStack}.include? c.name
158
+ end
182
159
  return link if contents.nil? || contents.empty?
183
160
  Nokogiri::XML::NodeSet.new(node.document, contents).to_xml
184
- # so not <origin bibitemid="ISO7301" citeas="ISO 7301">
185
- # <locality type="section"><reference>3.1</reference></locality></origin>
186
161
  end
187
162
 
188
163
  def load_yaml(lang, script)
@@ -205,38 +180,45 @@ module IsoDoc
205
180
  end
206
181
  end
207
182
 
208
- def bibliography_parse(node, out)
209
- title = node&.at(ns("./title"))&.text || ""
210
- out.div do |div|
211
- unless suppress_biblio_title(node)
212
- anchor(node['id'], :label, false) and
213
- clause_parse_title(node, div, node.at(ns("./title")), out) or
214
- div.h2 title, **{ class: "Section3" }
215
- end
216
- biblio_list(node, div, true)
183
+ def termref_parse(node, out)
184
+ end
185
+
186
+ def term_cleanup(docxml)
187
+ docxml.xpath("//table[@class = 'terms_dl']").each do |d|
188
+ prev = d.previous_element
189
+ next unless prev && prev.name == "table" &&
190
+ prev["class"] == "terms_dl"
191
+ d.children.each { |n| prev.add_child(n.remove) }
192
+ d.remove
217
193
  end
194
+ docxml
218
195
  end
219
196
 
220
- def suppress_biblio_title(node)
221
- return false unless node.parent.name == "annex"
222
- return false if node.parent.xpath("./references | ./clause | "\
223
- "./terms | ./definitions").size > 1
224
- title1 = node&.at(ns("./title"))&.text
225
- return true unless title1
226
- title2 = node&.parent&.at(ns("./title"))&.text
227
- title1&.casecmp(title2) == 0
197
+ def term_and_termref_parse(node, dt)
198
+ pref = node.at(ns("./preferred"))
199
+ source = node.xpath(ns("./termsource"))
200
+ pref.children.each { |n| parse(n, dt) }
201
+ return if source.empty?
202
+ dt << "<br/>"
203
+ source.each_with_index do |s, i|
204
+ i > 0 and dt << "; "
205
+ s.elements.each { |n| parse(n, dt) }
206
+ end
228
207
  end
229
208
 
230
- def foreword(isoxml, out)
231
- f = isoxml.at(ns("//foreword")) || return
232
- out.div **attr_code(id: f["id"]) do |s|
233
- title = f.at(ns("./title"))
234
- s.h1(**{ class: "ForewordTitle" }) do |h1|
235
- title and title.children.each { |e| parse(e, h1) }
236
- end
237
- f.elements.each { |e| parse(e, s) unless e.name == "title" }
209
+ def term_rest_parse(node, dd)
210
+ set_termdomain("")
211
+ node.children.each do |n|
212
+ parse(n, dd) unless %w(preferred termsource).include?(n.name)
238
213
  end
239
214
  end
215
+
216
+ def modification_parse(node, out)
217
+ out << @modified_lbl
218
+ node.at(ns("./p[text()[normalize-space() != '']]")) and
219
+ out << " &mdash; "
220
+ node.at(ns("./p")).children.each { |n| parse(n, out) }
221
+ end
240
222
  end
241
223
  end
242
224
  end