metanorma-standoc 3.0.7 → 3.0.8

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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/lib/metanorma/standoc/anchor.rb +1 -1
  3. data/lib/metanorma/standoc/base.rb +1 -1
  4. data/lib/metanorma/standoc/basicdoc.rng +9 -5
  5. data/lib/metanorma/standoc/blocks.rb +7 -4
  6. data/lib/metanorma/standoc/blocks_image.rb +2 -6
  7. data/lib/metanorma/standoc/blocks_notes.rb +2 -6
  8. data/lib/metanorma/standoc/cleanup_amend.rb +6 -8
  9. data/lib/metanorma/standoc/cleanup_asciibib.rb +17 -13
  10. data/lib/metanorma/standoc/cleanup_bibdata.rb +19 -13
  11. data/lib/metanorma/standoc/cleanup_bibitem.rb +9 -6
  12. data/lib/metanorma/standoc/cleanup_block.rb +6 -6
  13. data/lib/metanorma/standoc/cleanup_boilerplate.rb +5 -4
  14. data/lib/metanorma/standoc/cleanup_footnotes.rb +2 -4
  15. data/lib/metanorma/standoc/cleanup_image.rb +3 -3
  16. data/lib/metanorma/standoc/cleanup_inline.rb +12 -38
  17. data/lib/metanorma/standoc/cleanup_review.rb +7 -5
  18. data/lib/metanorma/standoc/cleanup_section.rb +5 -2
  19. data/lib/metanorma/standoc/cleanup_table.rb +1 -2
  20. data/lib/metanorma/standoc/cleanup_terms.rb +1 -1
  21. data/lib/metanorma/standoc/cleanup_terms_designations.rb +1 -1
  22. data/lib/metanorma/standoc/cleanup_toc.rb +1 -1
  23. data/lib/metanorma/standoc/cleanup_xref.rb +1 -1
  24. data/lib/metanorma/standoc/init.rb +15 -7
  25. data/lib/metanorma/standoc/inline.rb +7 -7
  26. data/lib/metanorma/standoc/isodoc.rng +132 -5
  27. data/lib/metanorma/standoc/localbib.rb +1 -2
  28. data/lib/metanorma/standoc/macros_form.rb +21 -3
  29. data/lib/metanorma/standoc/macros_link.rb +4 -5
  30. data/lib/metanorma/standoc/ref.rb +2 -2
  31. data/lib/metanorma/standoc/ref_sect.rb +1 -1
  32. data/lib/metanorma/standoc/ref_utility.rb +4 -3
  33. data/lib/metanorma/standoc/section.rb +5 -6
  34. data/lib/metanorma/standoc/table.rb +9 -13
  35. data/lib/metanorma/standoc/term_lookup_cleanup.rb +26 -9
  36. data/lib/metanorma/standoc/terms.rb +1 -1
  37. data/lib/metanorma/standoc/utils.rb +4 -0
  38. data/lib/metanorma/standoc/validate.rb +50 -23
  39. data/lib/metanorma/standoc/validate_schema.rb +2 -0
  40. data/lib/metanorma/standoc/validate_term.rb +8 -7
  41. data/lib/metanorma/standoc/version.rb +1 -1
  42. data/metanorma-standoc.gemspec +1 -1
  43. metadata +4 -4
@@ -12,7 +12,7 @@ module Metanorma
12
12
  module Validate
13
13
  def content_validate(doc)
14
14
  @doctype = doc.at("//bibdata/ext/doctype")&.text
15
- repeat_id_validate(doc.root) # feeds xref_validate
15
+ repeat_id_validate(doc.root) # feeds xref_validate, termsect_validate
16
16
  xref_validate(doc) # feeds nested_asset_validate
17
17
  nested_asset_validate(doc)
18
18
  section_validate(doc)
@@ -92,7 +92,7 @@ module Metanorma
92
92
  end
93
93
 
94
94
  def nested_asset_xref_report(outer, inner, _doc)
95
- i = @doc_xrefs[inner["id"]] or return
95
+ i = @doc_xrefs[inner["anchor"]] or return
96
96
  err2 = "There is a crossreference to an instance of #{inner.name} " \
97
97
  "nested within #{outer.name}: #{i.to_xml}"
98
98
  @log.add("Style", i, err2)
@@ -158,37 +158,63 @@ module Metanorma
158
158
  schema_validate(formattedstr_strip(doc.dup), schema_location)
159
159
  end
160
160
 
161
+ # Check should never happen with content ids, but will check it anyway
162
+ # since consequences are so catastrophic
161
163
  def repeat_id_validate1(elem)
162
164
  if @doc_ids[elem["id"]]
163
165
  @log.add("Anchors", elem,
164
- "Anchor #{elem['id']} has already been " \
165
- "used at line #{@doc_ids[elem['id']]}", severity: 0)
166
+ "ID #{elem['id']} has already been " \
167
+ "used at line #{@doc_ids[elem['id']][:line]}", severity: 0)
166
168
  else
167
- @doc_ids[elem["id"]] = elem.line
169
+ @doc_ids[elem["id"]] =
170
+ { line: elem.line, anchor: elem["anchor"] }.compact
168
171
  end
169
172
  end
170
173
 
174
+ def repeat_anchor_validate1(elem)
175
+ if @doc_anchors[elem["anchor"]]
176
+ @log.add("Anchors", elem,
177
+ "Anchor #{elem['anchor']} has already been used at line " \
178
+ "#{@doc_anchors[elem['anchor']][:line]}", severity: 0)
179
+ else
180
+ @doc_anchors[elem["anchor"]] = { line: elem.line, id: elem["id"] }
181
+ @doc_anchor_seq << elem["anchor"]
182
+ end
183
+ end
184
+
185
+ # Check should never happen with content ids, but will check it anyway
171
186
  def repeat_id_validate(doc)
172
- @doc_ids = {} # hash of all ids in document to line number
173
- @doc_id_seq = [] # ordered list of all ids in document
187
+ repeat_id_validate_prep
174
188
  doc.xpath("//*[@id]").each do |x|
175
189
  @doc_id_seq << x["id"]
176
190
  repeat_id_validate1(x)
191
+ x["anchor"] and repeat_anchor_validate1(x)
177
192
  end
178
- @doc_id_seq.sort!
193
+ @doc_id_seq_hash = @doc_id_seq.each_with_index
194
+ .with_object({}) do |(x, i), m|
195
+ m[x] = i
196
+ end
197
+ @doc_anchor_seq_hash = @doc_anchor_seq.each_with_index
198
+ .with_object({}) do |(x, i), m|
199
+ m[x] = i
200
+ end
201
+ end
202
+
203
+ def repeat_id_validate_prep
204
+ @doc_ids = {} # hash of all ids in document to line number, anchor
205
+ @doc_anchors = {} # hash of all anchors in document to line number, id
206
+ @doc_id_seq = [] # ordered list of all ids in document
207
+ @doc_anchor_seq = [] # ordered list of all anchors in document
179
208
  end
180
209
 
181
- # Retrieve IDs between two nominated values
210
+ # Retrieve anchors between two nominated values
182
211
  # (exclusive of start_id AND exclusive of end_id)
183
- def get_ids_between(start_id, end_id)
184
- start_index = @doc_id_seq.bsearch_index { |id| id > start_id }
185
- end_index = @doc_id_seq.bsearch_index { |id| id >= end_id }
186
- # start_id is greater than or equal to all elements
187
- start_index.nil? and return []
188
- # end_id is greater than all elements
189
- end_index.nil? and end_index = @doc_id_seq.length
212
+ def get_anchors_between(start_id, end_id)
213
+ start_index = @doc_anchor_seq_hash[start_id]
214
+ end_index = @doc_anchor_seq_hash[end_id]
215
+ start_index.nil? || end_index.nil? and return []
190
216
  start_index >= end_index and return []
191
- @doc_id_seq[start_index...end_index]
217
+ @doc_anchor_seq[start_index...end_index]
192
218
  end
193
219
 
194
220
  # manually check for xref/@target et sim. integrity
@@ -198,14 +224,15 @@ module Metanorma
198
224
  end
199
225
 
200
226
  def xref_validate_exists(doc)
201
- @doc_xrefs =
202
- doc.xpath("//xref/@target | //xref//location/@target | //index/@to")
203
- .each_with_object({}) do |x, m|
204
- m[x.text] = x.parent
205
- @doc_ids[x.text] and next
227
+ @doc_xrefs = {}
228
+ Metanorma::Utils::anchor_attributes.each do |a|
229
+ doc.xpath("//#{a[0]}/@#{a[1]}").each do |x|
230
+ @doc_xrefs[x.text] = x.parent
231
+ @doc_anchors[x.text] and next
206
232
  @log.add("Anchors", x.parent,
207
233
  "Crossreference target #{x} is undefined", severity: 1)
208
234
  end
235
+ end
209
236
  end
210
237
 
211
238
  # If there is an xref range, record the IDs between the two targets
@@ -220,7 +247,7 @@ module Metanorma
220
247
  from = to_location.previous_element
221
248
  from && from.name == "location" or return
222
249
  from["target"] && to_location["target"] or return
223
- get_ids_between(from["target"], to_location["target"])
250
+ get_anchors_between(from["target"], to_location["target"])
224
251
  .each { |id| @doc_xrefs[id] = from }
225
252
  end
226
253
  end
@@ -99,6 +99,8 @@ module Metanorma
99
99
  doc.xpath("//m:svg", "m" => SVG_NS).each { |n| n.replace("<svg/>") }
100
100
  doc
101
101
  end
102
+
103
+ include ::Metanorma::Standoc::Utils
102
104
  end
103
105
  end
104
106
  end
@@ -16,7 +16,7 @@ module Metanorma
16
16
  def iev_validate(xmldoc)
17
17
  @iev = init_iev or return
18
18
  xmldoc.xpath("//term").each do |t|
19
- t.xpath(".//termsource").each do |src|
19
+ t.xpath("./source | ./preferred/source | ./admitted/source | ./deprecates/source | ./related/source").each do |src|
20
20
  (/^IEC[  ]60050-/.match(src.at("./origin/@citeas")&.text) &&
21
21
  loc = src.xpath(SOURCELOCALITY)&.text) or next
22
22
  iev_validate1(t, loc, xmldoc)
@@ -46,15 +46,16 @@ module Metanorma
46
46
 
47
47
  def concept_validate_ids(doc)
48
48
  @concept_ids ||= doc.xpath("//term | //definitions//dt")
49
- .each_with_object({}) { |x, m| m[x["id"]] = true }
49
+ .each_with_object({}) { |x, m| m[x["anchor"]] = true }
50
50
  @concept_terms_tags ||= doc.xpath("//terms")
51
- .each_with_object({}) { |t, m| m[t["id"]] = true }
51
+ .each_with_object({}) { |t, m| m[t["anchor"]] = true }
52
52
  nil
53
53
  end
54
54
 
55
55
  def concept_validate_msg(_doc, tag, refterm, xref)
56
+ t = @doc_ids.dig(xref["target"], :anchor) || xref["target"]
56
57
  ret = <<~LOG
57
- #{tag.capitalize} #{xref.at("../#{refterm}")&.text} is pointing to #{xref['target']}, which is not a term or symbol
58
+ #{tag.capitalize} #{xref.at("../#{refterm}")&.text} is pointing to #{t}, which is not a term or symbol
58
59
  LOG
59
60
  if @concept_terms_tags[xref["target"]]
60
61
  ret = ret.strip
@@ -79,7 +80,7 @@ module Metanorma
79
80
  def preferred_validate_report(terms)
80
81
  terms.each do |k, v|
81
82
  v.size > 1 or next
82
- loc = v.map { |x| x["id"] }.join(", ")
83
+ loc = v.map { |x| x["anchor"] }.join(", ")
83
84
  err = "Term #{k} occurs twice as preferred designation: #{loc}"
84
85
  @log.add("Terms", v.first, err, severity: 1)
85
86
  end
@@ -92,7 +93,7 @@ module Metanorma
92
93
  c = d.ancestors.detect do |x|
93
94
  section_containers.include?(x.name)
94
95
  end
95
- c["id"] ||= "_#{UUIDTools::UUID.random_create}"
96
+ c["id"] or add_id(c["id"])
96
97
  m[c["id"]] ||= { clause: c, designations: [] }
97
98
  m[c["id"]][:designations] << d
98
99
  end
@@ -106,7 +107,7 @@ module Metanorma
106
107
  end.join(", ")
107
108
  err = <<~ERROR
108
109
  Clause not recognised as a term clause, but contains designation markup
109
- (preferred:[], admitted:[], alt:[], deprecated:[]):<br/>
110
+ (<code>preferred:[], admitted:[], alt:[], deprecated:[]</code>):<br/>
110
111
  #{desgns}</br>
111
112
  Ensure the parent clause is recognised as a terms clause by inserting <code>[heading=terms and definitions]</code> above the title,
112
113
  in case the heading is not automatically recognised. See also <a href="https://www.metanorma.org/author/topics/sections/concepts/#clause-title">Metanorma documentation</a>.
@@ -19,6 +19,6 @@ module Metanorma
19
19
  end
20
20
 
21
21
  module Standoc
22
- VERSION = "3.0.7".freeze
22
+ VERSION = "3.0.8".freeze
23
23
  end
24
24
  end
@@ -37,7 +37,7 @@ Gem::Specification.new do |spec|
37
37
  spec.add_dependency "metanorma-plugin-datastruct", "~> 0.3.0"
38
38
  spec.add_dependency "metanorma-plugin-glossarist", "~> 0.2.3"
39
39
  spec.add_dependency "metanorma-plugin-lutaml", "~> 0.7.0"
40
- spec.add_dependency "metanorma-utils", "~> 1.10.0"
40
+ spec.add_dependency "metanorma-utils", "~> 1.11.0"
41
41
  spec.add_dependency "ruby-jing"
42
42
  # relaton-cli not just relaton, to avoid circular reference in metanorma
43
43
  spec.add_dependency "concurrent-ruby"
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: 3.0.7
4
+ version: 3.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-04-29 00:00:00.000000000 Z
11
+ date: 2025-05-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -142,14 +142,14 @@ dependencies:
142
142
  requirements:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: 1.10.0
145
+ version: 1.11.0
146
146
  type: :runtime
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: 1.10.0
152
+ version: 1.11.0
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: ruby-jing
155
155
  requirement: !ruby/object:Gem::Requirement