metanorma-standoc 2.2.8 → 2.3.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 243e174494c4a7ce6b3b8ca5d861feb72d045439ce32948b44af9c14f9180981
4
- data.tar.gz: 40c2d970ccb90fdf19c77cd38d5e9e7c7626fa10c96050a0486a4697c3146624
3
+ metadata.gz: 95723e2c2f2095e87fcc969fafc1372b8297cd68b4376ce49b50e8bbd3b993b5
4
+ data.tar.gz: ad570f41788f288d281b419d72eb1026b046e7d4f35260281ccd09138c181ebd
5
5
  SHA512:
6
- metadata.gz: d957db18f3b90d596f69c048fa93c703e45736c23bbaa5787fd5111aaded043fd532a219187a4ff174067a3e456c0bfb48fea4e38d1c4705d6e97754a92ed26b
7
- data.tar.gz: 7c37929c7115382a789348ee12041496f4fe10847c2aac893cd7f60ac3e0b413d63c5573dfd6dfadf6e58af5c5455bca09ca150fe0262f9e6324b6e064cfdabe
6
+ metadata.gz: 135b01bb780350e849b3dd5dc7edac3600a1a75fcfdc336b904ca67dfac219923e5c697e5d05b4871ac827194cb582aadb0abcdcfb84280f024a3b7c75c0881f
7
+ data.tar.gz: e8a1dbe9aeaced49888d73b237c13a8531471c567c7d5ff4278e8cd38d0cdb171bc6c5f3ff824e2df57e7e8bb9e8dd0ff493df6ca16e5c1efda7364e4f692364
@@ -9,6 +9,7 @@ require "fileutils"
9
9
  require "metanorma-utils"
10
10
  require "isodoc/xslfo_convert"
11
11
  require_relative "render"
12
+ require_relative "localbib"
12
13
  require "mn-requirements"
13
14
 
14
15
  module Metanorma
@@ -18,6 +19,8 @@ module Metanorma
18
19
  XML_NAMESPACE = "https://www.metanorma.org/ns/standoc".freeze
19
20
  FONTS_MANIFEST = "fonts-manifest".freeze
20
21
 
22
+ attr_accessor :log, :fatalerror
23
+
21
24
  def xml_root_tag
22
25
  self.class::XML_ROOT_TAG
23
26
  end
@@ -32,7 +35,7 @@ module Metanorma
32
35
  init_processing(node)
33
36
  init_reqt(node)
34
37
  init_toc(node)
35
- init_output(node)
38
+ init_output(node) # feeds init_biblio
36
39
  init_i18n(node)
37
40
  init_biblio(node)
38
41
  @metadata_attrs = metadata_attrs(node)
@@ -96,6 +99,7 @@ module Metanorma
96
99
  end
97
100
  @localdir = Metanorma::Utils::localdir(node)
98
101
  @output_dir = outputdir node
102
+ @fatalerror = []
99
103
  end
100
104
 
101
105
  def init_i18n(node)
@@ -113,6 +117,8 @@ module Metanorma
113
117
  @bibdb = nil
114
118
  init_bib_caches(node)
115
119
  init_iev_caches(node)
120
+ @local_bibdb =
121
+ ::Metanorma::Standoc::LocalBiblio.new(node, @localdir, self)
116
122
  end
117
123
 
118
124
  def requirements_processor
@@ -226,8 +232,7 @@ module Metanorma
226
232
  def outputdir(node)
227
233
  if node.attr("output_dir").nil_or_empty?
228
234
  Metanorma::Utils::localdir(node)
229
- else
230
- File.join(node.attr("output_dir"), "")
235
+ else File.join(node.attr("output_dir"), "")
231
236
  end
232
237
  end
233
238
  end
@@ -683,6 +683,9 @@
683
683
  </define>
684
684
  <define name="underline">
685
685
  <element name="underline">
686
+ <optional>
687
+ <attribute name="style"/>
688
+ </optional>
686
689
  <zeroOrMore>
687
690
  <ref name="PureTextElement"/>
688
691
  </zeroOrMore>
@@ -47,7 +47,7 @@
47
47
  </element>
48
48
  </define>
49
49
  <define name="DocumentType">
50
- <value>document</value>
50
+ <text/>
51
51
  </define>
52
52
  <define name="docsubtype">
53
53
  <element name="subdoctype">
@@ -37,6 +37,7 @@ module Metanorma
37
37
  reqt_subpart?(role) and return requirement_subpart(node)
38
38
  role == "form" and return form(node)
39
39
  role == "definition" and return termdefinition(node)
40
+ role == "boilerplate" and return boilerplate_note(node)
40
41
  result = []
41
42
  node.blocks.each { |b| result << send(b.context, b) }
42
43
  result
@@ -71,6 +71,11 @@ module Metanorma
71
71
  end.join("\n")
72
72
  end
73
73
 
74
+ def boilerplate_note(node)
75
+ node.set_attr("type", "boilerplate")
76
+ note(node)
77
+ end
78
+
74
79
  def admonition_attrs(node)
75
80
  attr_code(keep_attrs(node).merge(id_attr(node)
76
81
  .merge(admonition_core_attrs(node)
@@ -66,6 +66,8 @@ module Metanorma
66
66
  name: span[:val] }
67
67
  when "surname", "initials", "givenname", "formatted-initials"
68
68
  ret[:contrib] = spans_preprocess_contrib(span, ret[:contrib])
69
+ when "fullname"
70
+ ret[:contrib] = spans_preprocess_fullname(span, ret[:contrib])
69
71
  when "organization"
70
72
  ret[:contrib] = spans_preprocess_org(span, ret[:contrib])
71
73
  when "in_surname", "in_initials", "in_givenname",
@@ -74,11 +76,18 @@ module Metanorma
74
76
  span[:key].sub!(/^in_/, "")
75
77
  ret[:in][:contrib] =
76
78
  spans_preprocess_contrib(span, ret[:in][:contrib])
79
+ when "in_fullname"
80
+ ret[:in][:contrib] ||= []
81
+ span[:key].sub!(/^in_/, "")
82
+ ret[:in][:contrib] =
83
+ spans_preprocess_fullname(span, ret[:in][:contrib])
77
84
  when "in_organization"
78
85
  ret[:in][:contrib] ||= []
79
86
  span[:key].sub!(/^in_/, "")
80
87
  ret[:in][:contrib] =
81
88
  spans_preprocess_org(span, ret[:in][:contrib])
89
+ else
90
+ warn "unrecognised `span:#{span["key"]}`"
82
91
  end
83
92
  end
84
93
 
@@ -100,7 +109,12 @@ module Metanorma
100
109
 
101
110
  spans_preprocess_new_contrib?(span, contrib) and
102
111
  contrib << { role: span[:type] || "author", entity: "person" }
103
- contrib[-1][span[:key].to_sym] = span[:val]
112
+ if span[:key] == "givenname" && contrib[-1][span[:key].to_sym]
113
+ contrib[-1][span[:key].to_sym] =
114
+ Array(contrib[-1][span[:key].to_sym]) + span[:val]
115
+ else
116
+ contrib[-1][span[:key].to_sym] = span[:val]
117
+ end
104
118
  contrib
105
119
  end
106
120
 
@@ -112,6 +126,19 @@ module Metanorma
112
126
  contrib[-1][:role] != (span[:type] || "author")
113
127
  end
114
128
 
129
+ def spans_preprocess_fullname(span, contrib)
130
+ name = span[:val].gsub(/\.(?=\p{Alpha})/, ". ").split(/ /)
131
+ out = { role: span[:type] || "author", entity: "person",
132
+ surname: name[-1] }
133
+ if name.size > 1 && name[0..-2].all? { |x| /\.$/.match?(x) }
134
+ out[:"formatted-initials"] = name[0..-2].join(" ")
135
+ else
136
+ out[:givenname] = name[0..-2]
137
+ end
138
+ contrib << out
139
+ contrib
140
+ end
141
+
115
142
  def spans_preprocess_org(span, contrib)
116
143
  contrib << { role: span[:type] || "author", entity: "organization",
117
144
  name: span[:val] }
@@ -122,7 +149,7 @@ module Metanorma
122
149
  ret = ""
123
150
  spans[:title] and ret += "<title>#{spans[:title]}</title>"
124
151
  ret += spans_to_bibitem_docid(spans)
125
- spans[:contrib].each { |s| ret += span_to_contrib(s) }
152
+ spans[:contrib].each { |s| ret += span_to_contrib(s, spans[:title]) }
126
153
  spans[:series] and
127
154
  ret += "<series><title>#{spans[:series]}</title></series>"
128
155
  spans[:pubplace] and ret += "<place>#{spans[:pubplace]}</place>"
@@ -152,6 +179,8 @@ module Metanorma
152
179
  { volume: "volume", issue: "issue", pages: "page" }.each do |k, v|
153
180
  spans[k]&.each { |s| ret += span_to_extent(s, v) }
154
181
  end
182
+ return "" if ret.empty?
183
+
155
184
  "<extent>#{ret}</extent>"
156
185
  end
157
186
 
@@ -172,19 +201,28 @@ module Metanorma
172
201
  end
173
202
  end
174
203
 
175
- def span_to_contrib(span)
204
+ def span_to_contrib(span, title)
176
205
  e = if span[:entity] == "organization"
177
206
  "<organization><name>#{span[:name]}</name></organization>"
178
- else span_to_person(span)
207
+ else span_to_person(span, title)
179
208
  end
180
209
  "<contributor><role type='#{span[:role]}'/>#{e}</contributor>"
181
210
  end
182
211
 
183
- def span_to_person(span)
212
+ def validate_span_to_person(span, title)
213
+ span[:surname] and return
214
+ msg = "Missing surname: issue with bibliographic markup " \
215
+ "in \"#{title}\": #{span}"
216
+ @log.add("Bibliography", nil, msg)
217
+ @fatalerror << msg
218
+ end
219
+
220
+ def span_to_person(span, title)
221
+ validate_span_to_person(span, title)
184
222
  pre = (span[:"formatted-initials"] and
185
223
  "<formatted-initials>" \
186
224
  "#{span[:"formatted-initials"]}</formatted-initials>") ||
187
- "<forename>#{span[:givenname]}</forename>"
225
+ Array(span[:givenname]).map { |x| "<forename>#{x}</forename>" }.join
188
226
  "<person><name>#{pre}<surname>#{span[:surname]}</surname></name>" \
189
227
  "</person>"
190
228
  end
@@ -89,7 +89,8 @@ module Metanorma
89
89
 
90
90
  def termdef_boilerplate_insert(xmldoc, isodoc, once = false)
91
91
  xmldoc.xpath(self.class::TERM_CLAUSE).each do |f|
92
- next if f.at("./clause[@type = 'boilerplate']")
92
+ next if f.at("./clause[@type = 'boilerplate'] | " \
93
+ "./note[@type = 'boilerplate']")
93
94
 
94
95
  term_defs_boilerplate(f.at("./title"),
95
96
  xmldoc.xpath(".//termdocsource"),
@@ -44,11 +44,11 @@ module Metanorma
44
44
  end
45
45
 
46
46
  NO_SYMABBR = "[.//definitions[not(@type)]]".freeze
47
- SYMABBR = "[.//definitions[@type = 'symbols']]"\
47
+ SYMABBR = "[.//definitions[@type = 'symbols']]" \
48
48
  "[.//definitions[@type = 'abbreviated_terms']]".freeze
49
- SYMnoABBR = "[.//definitions[@type = 'symbols']]"\
49
+ SYMnoABBR = "[.//definitions[@type = 'symbols']]" \
50
50
  "[not(.//definitions[@type = 'abbreviated_terms'])]".freeze
51
- ABBRnoSYM = "[.//definitions[@type = 'abbreviated_terms']]"\
51
+ ABBRnoSYM = "[.//definitions[@type = 'abbreviated_terms']]" \
52
52
  "[not(.//definitions[@type = 'symbols'])]".freeze
53
53
 
54
54
  def section_names_terms_cleanup(xml)
@@ -2653,6 +2653,7 @@
2653
2653
  <value>full</value>
2654
2654
  <value>short</value>
2655
2655
  <value>id</value>
2656
+ <value>modspec</value>
2656
2657
  </choice>
2657
2658
  </define>
2658
2659
  <define name="erefTypeWithConnective">
@@ -0,0 +1,77 @@
1
+ require "relaton_bib"
2
+
3
+ module Metanorma
4
+ module Standoc
5
+ class LocalBiblio
6
+ def initialize(node, localdir, parent)
7
+ @file_bibdb = {}
8
+ @localdir = localdir
9
+ @parent = parent
10
+ read_files(node)
11
+ end
12
+
13
+ def read_files(node)
14
+ if node.attr("relaton-data-source")
15
+ init_file_bibdb1(node.attr("relaton-data-source"), "default")
16
+ else
17
+ node.attributes.each do |k, v|
18
+ /^relaton-data-source-.+/.match?(k) or next
19
+ init_file_bibdb1(v, k.sub(/^relaton-data-source-/, ""))
20
+ end
21
+ end
22
+ end
23
+
24
+ def init_file_bibdb_config(defn, key)
25
+ /=/.match?(defn) or defn = "file=#{defn}"
26
+ values = defn.split(",").map { |item| item.split /\s*=\s*/ }.to_h
27
+ values["key"] = key
28
+ values["format"] ||= "bibtex" # all we currently suppoort
29
+ values
30
+ end
31
+
32
+ def init_file_bibdb1(defn, key)
33
+ v = init_file_bibdb_config(defn, key)
34
+ r = read_file(v)
35
+ @file_bibdb[v["key"]] =
36
+ case v["format"]
37
+ when "bibtex"
38
+ RelatonBib::BibtexParser.from_bibtex(r)
39
+ else
40
+ format_error(v)
41
+ end
42
+ end
43
+
44
+ def read_file(config)
45
+ f = File.join(@localdir, config["file"])
46
+ File.exist?(f) or return file_error(config)
47
+ File.read(f)
48
+ end
49
+
50
+ def file_error(config)
51
+ msg = "Cannot process file #{config['file']} for local relaton " \
52
+ "data source #{config['key']}"
53
+ @parent.fatalerror << msg
54
+ @parent.log.add("Bibliography", nil, msg)
55
+ ""
56
+ end
57
+
58
+ def format_error(config)
59
+ msg = "Cannot process format #{config['format']} for local relaton " \
60
+ "data source #{config['key']}"
61
+ @parent.fatalerror << msg
62
+ @parent.log.add("Bibliography", nil, msg)
63
+ {}
64
+ end
65
+
66
+ def get(id, file = default)
67
+ ret = @file_bibdb.dig(file, id) and return ret
68
+
69
+ msg = "Cannot find reference #{id} for local relaton " \
70
+ "data source #{file}"
71
+ @parent.fatalerror << msg
72
+ @parent.log.add("Bibliography", nil, msg)
73
+ Nokogiri::XML("<bibitem/>")
74
+ end
75
+ end
76
+ end
77
+ end
@@ -74,7 +74,7 @@ module Metanorma
74
74
 
75
75
  def process(_parent, _target, attrs)
76
76
  termref = attrs["termxref"] || attrs["name"]
77
- "<concept type='term'><termxref>#{attrs['name']}</termxref>"\
77
+ "<concept type='term'><termxref>#{attrs['name']}</termxref>" \
78
78
  "<renderterm>#{termref}</renderterm><xrefrender/></concept>"
79
79
  end
80
80
  end
@@ -87,7 +87,7 @@ module Metanorma
87
87
 
88
88
  def process(_parent, _target, attrs)
89
89
  termref = attrs["termxref"] || attrs["name"]
90
- "<concept type='symbol'><termxref>#{attrs['name']}</termxref>"\
90
+ "<concept type='symbol'><termxref>#{attrs['name']}</termxref>" \
91
91
  "<renderterm>#{termref}</renderterm><xrefrender/></concept>"
92
92
  end
93
93
  end
@@ -113,50 +113,40 @@ module Metanorma
113
113
  .match(m[:rest].sub(/^,/, ""))
114
114
  ret[:opt] = CSV.parse_line(m2[:opt].sub(/^,opt(ion)?s=/, "")
115
115
  .sub(/^"(.+)"$/m, "\\1").sub(/^'(.+)'$/m, "\\1"))
116
- begin
117
- attrs = CSV.parse_line(m2[:rest]) || []
118
- rescue StandardError
119
- raise "error processing #{m2[:rest]} as CSV"
120
- end
121
- else
122
- begin
123
- attrs = CSV.parse_line(m[:rest].sub(/^,/, "")) || []
124
- rescue StandardError
125
- raise "error processing #{m[:rest]} as CSV"
126
- end
116
+ attrs = preprocess_attrs_csv(m2[:rest])
117
+ else attrs = preprocess_attrs_csv(m[:rest])
127
118
  end
128
119
  attrs.map! { |x| x.gsub(/\s+/, " ") }
129
120
  ret.merge(term: attrs[0], word: attrs[1] || attrs[0],
130
121
  render: attrs[2])
131
122
  end
132
123
 
124
+ def preprocess_attrs_csv(line)
125
+ CSV.parse_line(line.sub(/^,/, "")) || []
126
+ rescue StandardError
127
+ raise "error processing #{line} as CSV"
128
+ end
129
+
133
130
  def generate_attrs(opts)
134
131
  ret = ""
135
- opts.include?("noital") and ret += " ital='false'"
136
- opts.include?("noref") and ret += " ref='false'"
137
- opts.include?("ital") and ret += " ital='true'"
138
- opts.include?("ref") and ret += " ref='true'"
139
- opts.include?("nolinkmention") and ret += " linkmention='false'"
140
- opts.include?("linkmention") and ret += " linkmention='true'"
141
- opts.include?("nolinkref") and ret += " linkref='false'"
142
- opts.include?("linkref") and ret += " linkref='true'"
132
+ %w(ital ref linkmention linkref).each do |x|
133
+ opts.include?("no#{x}") and ret += " #{x}='false'"
134
+ opts.include?(x) and ret += " #{x}='true'"
135
+ end
143
136
  ret
144
137
  end
145
138
 
146
139
  def process(parent, target, _attrs)
147
140
  attrs = preprocess_attrs(target)
148
- term = Asciidoctor::Inline.new(parent, :quoted,
149
- attrs[:term]).convert
150
- word = Asciidoctor::Inline.new(parent, :quoted,
151
- attrs[:word]).convert
152
- xref = Asciidoctor::Inline.new(parent, :quoted,
153
- attrs[:render]).convert
141
+ term, word, render = %i(term word render).each_with_object([]) do |x, m|
142
+ m << Asciidoctor::Inline.new(parent, :quoted, attrs[x]).convert
143
+ end
154
144
  opt = generate_attrs(attrs[:opt] || [])
155
- if attrs[:id] then "<concept#{opt} key='#{attrs[:id]}'><refterm>"\
156
- "#{term}</refterm><renderterm>#{word}</renderterm>"\
157
- "<xrefrender>#{xref}</xrefrender></concept>"
158
- else "<concept#{opt}><termxref>#{term}</termxref><renderterm>"\
159
- "#{word}</renderterm><xrefrender>#{xref}</xrefrender></concept>"
145
+ if attrs[:id] then "<concept#{opt} key='#{attrs[:id]}'><refterm>" \
146
+ "#{term}</refterm><renderterm>#{word}</renderterm>" \
147
+ "<xrefrender>#{render}</xrefrender></concept>"
148
+ else "<concept#{opt}><termxref>#{term}</termxref><renderterm>" \
149
+ "#{word}</renderterm><xrefrender>#{render}</xrefrender></concept>"
160
150
  end
161
151
  rescue StandardError => e
162
152
  raise("processing {{#{target}}}: #{e.message}")
@@ -182,9 +172,9 @@ module Metanorma
182
172
  out = preprocess_attrs(attrs["text"])
183
173
  term = Asciidoctor::Inline.new(parent, :quoted,
184
174
  out[:term]).convert
185
- if out[:id] then "<related type='#{target}' key='#{out[:id]}'>"\
175
+ if out[:id] then "<related type='#{target}' key='#{out[:id]}'>" \
186
176
  "<refterm>#{term}</refterm></related>"
187
- else "<related type='#{target}'><termxref>#{term}</termxref>"\
177
+ else "<related type='#{target}'><termxref>#{term}</termxref>" \
188
178
  "<xrefrender>#{term}</xrefrender></related>"
189
179
  end
190
180
  rescue StandardError => e
@@ -42,10 +42,9 @@ module Metanorma
42
42
  end
43
43
 
44
44
  def isorefmatches2code(match)
45
- { code: match[:code], no_year: true,
45
+ { code: match[:code], no_year: true, lang: (@lang || :all),
46
46
  note: match[:fn], year: nil, match: match,
47
- title: match[:text], usrlbl: match[:usrlbl],
48
- lang: (@lang || :all) }
47
+ title: match[:text], usrlbl: match[:usrlbl] }
49
48
  end
50
49
 
51
50
  def isorefmatches2out(item, xml)
@@ -145,7 +144,7 @@ module Metanorma
145
144
  return { code: nil, match: match, analyse_code: code,
146
145
  hidden: code[:hidden] }
147
146
  year = refitem1yr(code[:id])
148
- { code: code[:id], analyse_code: code,
147
+ { code: code[:id], analyse_code: code, localfile: code[:localfile],
149
148
  year: year,
150
149
  title: match[:text], match: match, hidden: code[:hidden],
151
150
  usrlbl: match[:usrlbl], lang: (@lang || :all) }
@@ -221,7 +220,13 @@ module Metanorma
221
220
  refs = node.items.each_with_object([]) do |b, m|
222
221
  m << reference1code(b.text, node)
223
222
  end
224
- reference_populate(refs)
223
+ reference_populate(reference_normalise(refs))
224
+ end
225
+
226
+ def reference_normalise(refs)
227
+ refs.each do |r|
228
+ r[:code] = @c.decode(r[:code]).gsub(/\u2009\u2014\u2009/, " -- ")
229
+ end
225
230
  end
226
231
 
227
232
  def reference_populate(refs)
@@ -239,7 +244,7 @@ module Metanorma
239
244
  ref, i, doc = results.pop
240
245
  m[i.to_i] = { ref: ref }
241
246
  if doc.is_a?(RelatonBib::RequestError)
242
- @log.add("Bibliography", nil, "Could not retrieve #{ref[:code]}: "\
247
+ @log.add("Bibliography", nil, "Could not retrieve #{ref[:code]}: " \
243
248
  "no access to online site")
244
249
  else m[i.to_i][:doc] = doc
245
250
  end
@@ -69,41 +69,63 @@ module Metanorma
69
69
  return nil if opts[:no_year]
70
70
 
71
71
  code = code.sub(/^\([^)]+\)/, "")
72
- hit = @bibdb&.fetch(code, year, opts)
73
- return nil if hit.nil?
74
-
72
+ hit = fetch_ref1(code, year, opts) or return nil
75
73
  xml.parent.add_child(smart_render_xml(hit, code, opts))
76
74
  xml
77
75
  rescue RelatonBib::RequestError
78
- @log.add("Bibliography", nil, "Could not retrieve #{code}: "\
76
+ @log.add("Bibliography", nil, "Could not retrieve #{code}: " \
79
77
  "no access to online site")
80
78
  nil
81
79
  end
82
80
 
81
+ def fetch_ref1(code, year, opts)
82
+ if opts[:localfile]
83
+ @local_bibdb.get(code, opts[:localfile])
84
+ else @bibdb&.fetch(code, year, opts)
85
+ end
86
+ end
87
+
83
88
  def fetch_ref_async(ref, idx, res)
84
- if ref[:code].nil? || ref[:no_year] || @bibdb.nil?
89
+ if ref[:code].nil? || ref[:no_year] || (@bibdb.nil? && !ref[:localfile])
85
90
  res << [ref, idx, nil]
86
- else
87
- @bibdb.fetch_async(@c.decode(ref[:code]),
88
- ref[:year], ref) do |doc|
89
- res << [ref, idx, doc]
90
- end
91
+ elsif ref[:localfile]
92
+ res << [ref, idx, @local_bibdb.get(ref[:code], ref[:localfile])]
93
+ else fetch_ref_async1(ref, idx, res)
94
+ end
95
+ end
96
+
97
+ def fetch_ref_async1(ref, idx, res)
98
+ @bibdb.fetch_async(ref[:code], ref[:year], ref) do |doc|
99
+ res << [ref, idx, doc]
91
100
  end
92
101
  end
93
102
 
94
103
  def emend_biblio(xml, code, title, usrlbl)
104
+ emend_biblio_id(xml, code)
105
+ emend_biblio_title(xml, code, title)
106
+ emend_biblio_usrlbl(xml, usrlbl)
107
+ end
108
+
109
+ def emend_biblio_id(xml, code)
95
110
  unless xml.at("/bibitem/docidentifier[not(@type = 'DOI')][text()]")
96
111
  @log.add("Bibliography", nil,
97
112
  "ERROR: No document identifier retrieved for #{code}")
98
113
  xml.root << "<docidentifier>#{code}</docidentifier>"
99
114
  end
115
+ end
116
+
117
+ def emend_biblio_title(xml, code, title)
100
118
  unless xml.at("/bibitem/title[text()]")
101
119
  @log.add("Bibliography", nil,
102
120
  "ERROR: No title retrieved for #{code}")
103
121
  xml.root << "<title>#{title || '(MISSING TITLE)'}</title>"
104
122
  end
105
- usrlbl and xml.at("/bibitem/docidentifier").next =
106
- "<docidentifier type='metanorma'>#{mn_code(usrlbl)}</docidentifier>"
123
+ end
124
+
125
+ def emend_biblio_usrlbl(xml, usrlbl)
126
+ usrlbl or return
127
+ xml.at("/bibitem/docidentifier").next =
128
+ "<docidentifier type='metanorma'>#{mn_code(usrlbl)}</docidentifier>"
107
129
  end
108
130
 
109
131
  def smart_render_xml(xml, code, opts)
@@ -62,6 +62,14 @@ module Metanorma
62
62
  .sub(/^dropid\((.+)\)$/, "\\1")
63
63
  .sub(/^hidden\((.+)\)$/, "\\1")
64
64
  .sub(/^nofetch\((.+)\)$/, "\\1")
65
+ .sub(/^local-file\((.+)\)$/, "\\1")
66
+ end
67
+
68
+ def analyse_ref_localfile(ret)
69
+ m = /^local-file\((?:(?<source>[^,]+),\s*)?(?<id>.+)\)$/.match(ret[:id])
70
+ m or return ret
71
+
72
+ ret.merge(id: m[:id], localfile: (m[:source] || "default"))
65
73
  end
66
74
 
67
75
  def analyse_ref_nofetch(ret)
@@ -98,15 +106,19 @@ module Metanorma
98
106
  end
99
107
 
100
108
  # ref id = (usrlbl)code[:-]year
101
- # code = nofetch(code) | hidden(code) | dropid(code) | (repo|path):(key,code) |
102
- # \[? number \]? | ident
109
+ # code = \[? number \]? | ident | nofetch(code) | hidden(code) |
110
+ # dropid(code) | # (repo|path):(key,code) | local-file(source,? key)
103
111
  def analyse_ref_code(code)
104
112
  ret = { id: code }
105
113
  return ret if code.blank?
106
114
 
107
115
  analyse_ref_numeric(
108
116
  analyse_ref_repo_path(
109
- analyse_ref_dropid(analyse_ref_hidden(analyse_ref_nofetch(ret))),
117
+ analyse_ref_dropid(
118
+ analyse_ref_hidden(
119
+ analyse_ref_nofetch(analyse_ref_localfile(ret)),
120
+ ),
121
+ ),
110
122
  ),
111
123
  )
112
124
  end
@@ -34,8 +34,9 @@ module Metanorma
34
34
 
35
35
  def requirement_validate(docxml)
36
36
  docxml.xpath("//requirement | //recommendation | //permission")
37
- .each do |r|
38
- @reqt_models.model(r["model"]).validate(r, @log)
37
+ .each_with_object([]) do |r, m|
38
+ ret = @reqt_models.model(r["model"]).validate(r, @log)
39
+ ret.each { |x| m << x }
39
40
  end
40
41
  end
41
42
  end
@@ -60,8 +60,9 @@ module Metanorma
60
60
  "symbols and abbreviated terms", "clause", "bibliography"].freeze
61
61
 
62
62
  def start_main_section(ret, node)
63
- @preface = false if self.class::MAIN_CLAUSE_NAMES.include?(ret) &&
64
- node.role != "preface" && node.attr("style") != "preface"
63
+ return if node.role == "preface" || node.attr("style") == "preface"
64
+
65
+ @preface = false if self.class::MAIN_CLAUSE_NAMES.include?(ret)
65
66
  @preface = false if self.class::PREFACE_CLAUSE_NAMES
66
67
  .intersection(@seen_headers_canonical + [ret]).empty?
67
68
  end
@@ -43,7 +43,6 @@ module Metanorma
43
43
  end
44
44
 
45
45
  def content_validate(doc)
46
- @fatalerror = []
47
46
  xref_validate(doc)
48
47
  section_validate(doc)
49
48
  norm_ref_validate(doc)
@@ -52,7 +51,7 @@ module Metanorma
52
51
  concept_validate(doc, "concept", "refterm")
53
52
  concept_validate(doc, "related", "preferred//name")
54
53
  table_validate(doc)
55
- requirement_validate(doc)
54
+ @fatalerror += requirement_validate(doc)
56
55
  image_validate(doc)
57
56
  @fatalerror.empty? or
58
57
  clean_abort(@fatalerror.join("\n"), doc)
@@ -19,6 +19,6 @@ module Metanorma
19
19
  end
20
20
 
21
21
  module Standoc
22
- VERSION = "2.2.8".freeze
22
+ VERSION = "2.3.0".freeze
23
23
  end
24
24
  end
@@ -30,7 +30,7 @@ Gem::Specification.new do |spec|
30
30
 
31
31
  spec.add_dependency "asciidoctor", "~> 2.0.0"
32
32
  spec.add_dependency "iev", "~> 0.3.0"
33
- spec.add_dependency "isodoc", "~> 2.3.1"
33
+ spec.add_dependency "isodoc", "~> 2.4.0"
34
34
  spec.add_dependency "metanorma"
35
35
  spec.add_dependency "metanorma-plugin-datastruct", "~> 0.2.0"
36
36
  spec.add_dependency "metanorma-plugin-lutaml"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metanorma-standoc
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.8
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-11-21 00:00:00.000000000 Z
11
+ date: 2022-12-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: asciidoctor
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 2.3.1
47
+ version: 2.4.0
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 2.3.1
54
+ version: 2.4.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: metanorma
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -503,6 +503,7 @@ files:
503
503
  - lib/metanorma/standoc/isodoc-compile.rng
504
504
  - lib/metanorma/standoc/isodoc.rng
505
505
  - lib/metanorma/standoc/lists.rb
506
+ - lib/metanorma/standoc/localbib.rb
506
507
  - lib/metanorma/standoc/macros.rb
507
508
  - lib/metanorma/standoc/macros_embed.rb
508
509
  - lib/metanorma/standoc/macros_form.rb
@@ -548,7 +549,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
548
549
  - !ruby/object:Gem::Version
549
550
  version: '0'
550
551
  requirements: []
551
- rubygems_version: 3.3.7
552
+ rubygems_version: 3.3.26
552
553
  signing_key:
553
554
  specification_version: 4
554
555
  summary: metanorma-standoc realises standards following the Metanorma standoc model