metanorma 2.3.4 → 2.3.5

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: 4f915998387c2b307208f4022e9e8e5187eaec5402bc207be589e87a2db75810
4
- data.tar.gz: 7791d0a533ed5825bbdd97786d5e1fcc2bfe05c9c3440ca5cd842aa3141d3a77
3
+ metadata.gz: 36c2caa601ab189f0039f3965330a54ba8d399a906bedc8575fca354d2bce1cd
4
+ data.tar.gz: 49ff8a09d81edd8bd8f27b7db85a5a4dbb8a76ba7596d2cf7bf8b6a73aff0f67
5
5
  SHA512:
6
- metadata.gz: 1f2bcb45e92a68d8963adbf142dabe682967dec2bc4220b99a022a5e7657571b26817bc206b8e7c26dc171ceaac7e677ca7283eebc82db18f90ad7adfd26707d
7
- data.tar.gz: 149e62e37840dd568eb11b84770bea7c3e7ad389d52587084db70d035ac2e48f1fae1289cb62e01805644b62710db0d0ffa02729935f237de488c68267864655
6
+ metadata.gz: e6575113b013098bfd0e364054b455ac6e5fdb958c05a03edf0519862d62670625fadd03d02f7ad93882e4cd09894ca76859c1cef9498fd8e419beaa7566fdba
7
+ data.tar.gz: 2e48a397971851fd8e53cf97fe6c4590a7a8ef141cad4d7c28e365745649f30b098f19ba7519764f290ebe91ba172f38bc306047b3ff652a0a0b612c183c6627
@@ -191,12 +191,13 @@ module Metanorma
191
191
  # TODO: retrieve flavor based on @bibdata publisher when lookup implemented
192
192
  # Will still infer based on docid, but will validate it before proceeding
193
193
  def fetch_flavor
194
- docid = @bibdata.docidentifier.first or return
195
- f = docid.type.downcase || docid.id.sub(/\s.*$/, "").downcase or return
194
+ docid = @bibdata&.docidentifier&.first or return
195
+ f = docid.type&.downcase || docid.content&.sub(/\s.*$/,
196
+ "")&.downcase or return
196
197
  f = Util::taste2flavor(f)
197
198
  require ::Metanorma::Compile.new.stdtype2flavor_gem(f)
198
199
  f
199
- rescue LoadError
200
+ rescue LoadError, NameError
200
201
  nil
201
202
  end
202
203
  end
@@ -5,7 +5,7 @@ module Metanorma
5
5
  class Collection
6
6
  module Config
7
7
  class Bibdata < ::Lutaml::Model::Serializable
8
- model ::RelatonBib::BibliographicItem
8
+ model ::Relaton::Bib::ItemData
9
9
  end
10
10
  end
11
11
  end
@@ -1,13 +1,47 @@
1
- require "relaton-cli"
1
+ require "relaton/bib"
2
+ require "relaton/bib/hash_parser_v1"
2
3
 
3
4
  module Metanorma
4
5
  class Collection
5
6
  module Config
6
7
  module Converters
8
+ # Keys present only in 1.x YAML format — unambiguously absent in 2.x
9
+ V1_BIBDATA_KEYS = %w[docid link biblionote].freeze
10
+
7
11
  def bibdata_from_yaml(model, value)
8
- value and !value.empty? or return
12
+ (value and !value.empty?) or return
13
+ if value.is_a?(String)
14
+ value = YAML.safe_load_file(value,
15
+ permitted_classes: [Date,
16
+ Symbol])
17
+ end
9
18
  force_primary_docidentifier_yaml(value)
10
- model.bibdata = Relaton::Cli::YAMLConvertor.convert_single_file(value)
19
+ model.bibdata = if bibdata_yaml_v1_format?(value)
20
+ # 1.x YAML format (docid:/link:/biblionote: present) —
21
+ # bridge via HashParserV1 for backward compatibility
22
+ h = Relaton::Bib::HashParserV1.hash_to_bib(value)
23
+ Relaton::Bib::ItemData.new(**h)
24
+ else
25
+ # 2.x YAML format (docidentifier:/uri:/note: keys) —
26
+ # parse directly with lutaml-model
27
+ Relaton::Bib::Item.from_yaml(value.to_yaml)
28
+ end
29
+ end
30
+
31
+ # Recursively detect 1.x-format YAML by presence of renamed keys.
32
+ # Checks the entire nested structure so relation:/contributor: entries
33
+ # are also detected.
34
+ def bibdata_yaml_v1_format?(obj)
35
+ case obj
36
+ when Hash
37
+ return true if (obj.keys.map(&:to_s) & V1_BIBDATA_KEYS).any?
38
+
39
+ obj.values.any? { |v| bibdata_yaml_v1_format?(v) }
40
+ when Array
41
+ obj.any? { |v| bibdata_yaml_v1_format?(v) }
42
+ else
43
+ false
44
+ end
11
45
  end
12
46
 
13
47
  def force_primary_docidentifier_yaml(value)
@@ -24,7 +58,10 @@ module Metanorma
24
58
  end
25
59
 
26
60
  def bibdata_to_yaml(model, doc)
27
- doc["bibdata"] = model.bibdata&.to_hash
61
+ return unless model.bibdata
62
+
63
+ doc["bibdata"] = YAML.safe_load(model.bibdata.to_yaml,
64
+ permitted_classes: [Date, Symbol])
28
65
  end
29
66
 
30
67
  def bibdata_from_xml(model, node)
@@ -48,48 +48,61 @@ module Metanorma
48
48
 
49
49
  private
50
50
 
51
- def mn2relaton_parser(tag)
51
+ # Select the appropriate Relaton parser class for the given flavor tag.
52
+ # @param tag [String, nil] flavor tag (e.g. "iso", "ietf")
53
+ # @param bibdata [Boolean] true when parsing a <bibdata> element (has <ext>);
54
+ # false when parsing a <bibitem> element (no <ext>)
55
+ # @return [Class] Relaton parser class (Bibdata or Bibitem subclass)
56
+ def mn2relaton_parser(tag, bibdata: false)
52
57
  case tag
53
58
  when "bipm"
54
- require "relaton_bipm" unless defined?(::RelatonBipm::XMLParser)
55
- ::RelatonBipm::XMLParser
59
+ require "relaton/bipm" unless defined?(::Relaton::Bipm::Bibdata)
60
+ bibdata ? ::Relaton::Bipm::Bibdata : ::Relaton::Bipm::Bibitem
56
61
  when "bsi"
57
- require "relaton_bsi" unless defined?(::RelatonBsi::XMLParser)
58
- ::RelatonBsi::XMLParser
62
+ require "relaton/bsi" unless defined?(::Relaton::Bsi::Bibdata)
63
+ bibdata ? ::Relaton::Bsi::Bibdata : ::Relaton::Bsi::Bibitem
59
64
  when "ietf"
60
- require "relaton_ietf" unless defined?(::RelatonIetf::XMLParser)
61
- ::RelatonIetf::XMLParser
65
+ require "relaton/ietf" unless defined?(::Relaton::Ietf::Bibdata)
66
+ bibdata ? ::Relaton::Ietf::Bibdata : ::Relaton::Ietf::Bibitem
62
67
  when "iho"
63
- require "relaton_iho" unless defined?(::RelatonIho::XMLParser)
64
- ::RelatonIho::XMLParser
68
+ require "relaton/iho" unless defined?(::Relaton::Iho::Bibdata)
69
+ bibdata ? ::Relaton::Iho::Bibdata : ::Relaton::Iho::Bibitem
65
70
  when "itu"
66
- require "relaton_itu" unless defined?(::RelatonItu::XMLParser)
67
- ::RelatonItu::XMLParser
71
+ require "relaton/itu" unless defined?(::Relaton::Itu::Bibdata)
72
+ bibdata ? ::Relaton::Itu::Bibdata : ::Relaton::Itu::Bibitem
68
73
  when "iec"
69
- require "relaton_iec" unless defined?(::RelatonIec::XMLParser)
70
- ::RelatonIec::XMLParser
74
+ require "relaton/iec" unless defined?(::Relaton::Iec::Bibdata)
75
+ bibdata ? ::Relaton::Iec::Bibdata : ::Relaton::Iec::Bibitem
71
76
  when "iso"
72
- require "relaton_iso" unless defined?(::RelatonIsoBib::XMLParser)
73
- ::RelatonIsoBib::XMLParser
77
+ require "relaton/iso" unless defined?(::Relaton::Iso::Bibdata)
78
+ bibdata ? ::Relaton::Iso::Bibdata : ::Relaton::Iso::Bibitem
74
79
  when "nist"
75
- require "relaton_nist" unless defined?(::RelatonNist::XMLParser)
76
- ::RelatonNist::XMLParser
80
+ require "relaton/nist" unless defined?(::Relaton::Nist::Bibdata)
81
+ bibdata ? ::Relaton::Nist::Bibdata : ::Relaton::Nist::Bibitem
77
82
  when "ogc"
78
- require "relaton_ogc" unless defined?(::RelatonOgc::XMLParser)
79
- ::RelatonOgc::XMLParser
83
+ require "relaton/ogc" unless defined?(::Relaton::Ogc::Bibdata)
84
+ bibdata ? ::Relaton::Ogc::Bibdata : ::Relaton::Ogc::Bibitem
80
85
  else
81
- ::RelatonBib::XMLParser
86
+ bibdata ? ::Relaton::Bib::Bibdata : ::Relaton::Bib::Bibitem
82
87
  end
83
88
  rescue LoadError => e
84
- warn "Warning: Failed to load relaton gem for '#{tag}': #{e.message}. Falling back to RelatonBib::XMLParser"
85
- ::RelatonBib::XMLParser
89
+ warn "Warning: Failed to load relaton gem for '#{tag}': #{e.message}. Falling back to Relaton::Bib::Bibdata/Bibitem"
90
+ bibdata ? ::Relaton::Bib::Bibdata : ::Relaton::Bib::Bibitem
86
91
  end
87
92
 
88
93
  # #param xml [Nokogiri::XML::Document, Nokogiri::XML::Element]
89
94
  # @return [RelatonBib::BibliographicItem,RelatonIso::IsoBibliographicItem]
90
95
  def from_xml(xml)
91
96
  b = xml.at("//xmlns:bibitem|//xmlns:bibdata")
92
- r = mn2relaton_parser(xml.root["flavor"])
97
+ # <bibitem> elements are always flavor-independent: use the base
98
+ # Relaton::Bib::Bibitem regardless of collection flavor.
99
+ # <bibdata> elements carry flavor-specific metadata (<ext> etc.) and
100
+ # must be parsed with the appropriate flavor Bibdata class.
101
+ r = if b.name == "bibitem"
102
+ ::Relaton::Bib::Bibitem
103
+ else
104
+ mn2relaton_parser(xml.root["flavor"], bibdata: true)
105
+ end
93
106
  # Relaton doesn't understand Pres XML tags
94
107
  b.xpath("//xmlns:fmt-identifier").each(&:remove)
95
108
  r.from_xml(b.to_xml)
@@ -137,9 +150,9 @@ module Metanorma
137
150
 
138
151
  # @return [String]
139
152
  def type
140
- first = @bibitem.docidentifier.first
153
+ first = @bibitem.docidentifier&.first
141
154
  @type ||= (first&.type&.downcase ||
142
- first&.id&.match(/^[^\s]+/)&.to_s)&.downcase ||
155
+ first&.content&.match(/^[^\s]+/)&.to_s)&.downcase ||
143
156
  "standoc"
144
157
  end
145
158
 
@@ -149,7 +162,7 @@ module Metanorma
149
162
  if @raw
150
163
  builder.parent.add_child(@bibitem.root)
151
164
  else
152
- builder.send("metanorma") do |b|
165
+ builder.send(:metanorma) do |b|
153
166
  b << @bibitem.to_xml(bibdata: true)
154
167
  end
155
168
  end
@@ -4,10 +4,10 @@ module Metanorma
4
4
  # @param elm [Nokogiri::XML::Element]
5
5
  # @return [String]
6
6
  def indexfile_title(entry)
7
- if entry.bibdata &&
8
- x = entry.bibdata.title.detect { |t| t.type == "main" } ||
9
- entry.bibdata.title.first
10
- x.title.content
7
+ titles = entry.bibdata && Array(entry.bibdata.title)
8
+ if titles && !titles.empty? &&
9
+ (x = titles.detect { |t| t.type == "main" } || titles.first)
10
+ x.content
11
11
  else
12
12
  entry.title
13
13
  end
@@ -158,7 +158,7 @@ module Metanorma
158
158
  options[:site_generate] and options[:format] << :xml
159
159
  options[:format].include?(:rxl) or return
160
160
  File.open(File.join(@outdir, "collection.rxl"), "w:UTF-8") do |f|
161
- f.write(@bibdata.to_xml)
161
+ f.write(@bibdata.to_xml(bibdata: true))
162
162
  end
163
163
  end
164
164
 
@@ -231,7 +231,7 @@ module Metanorma
231
231
  File.exist?(pres) or return
232
232
  xml = Nokogiri::XML(File.read(pres, encoding: "UTF-8"), &:huge)
233
233
  x = xml.xpath("//*[local-name() = 'presentation-metadata']/" \
234
- "*[local-name() = 'fonts']")
234
+ "*[local-name() = 'fonts']")
235
235
  x.empty? and return
236
236
  x.map(&:text).join(";")
237
237
  end
@@ -61,8 +61,8 @@ module Metanorma
61
61
  tag = presxml ? "fmt-eref" : "eref"
62
62
  docxml.xpath(ns("//#{tag}"))
63
63
  .each_with_object({ citeas: {}, bibitemid: {} }) do |i, m|
64
- m[:citeas][i["citeas"]] = true
65
- m[:bibitemid][i["bibitemid"]] = true
64
+ m[:citeas][i["citeas"]] = true
65
+ m[:bibitemid][i["bibitemid"]] = true
66
66
  end
67
67
  end
68
68
 
@@ -158,7 +158,7 @@ module Metanorma
158
158
  read_in_if_svg(i, directory.sub(%r{(?<!=/)$}, "/"))
159
159
  end
160
160
  docxml.xpath(ns("//image")).each do |i| # rubocop:disable Style/CombinableLoops
161
- i["src"] && !i["src"].empty? or next
161
+ (i["src"] && !i["src"].empty?) or next
162
162
  i["src"] = Vectory::Utils::datauri(i["src"], directory)
163
163
  end
164
164
  docxml
@@ -209,11 +209,13 @@ module Metanorma
209
209
  def isodoc_populate
210
210
  @isodoc.info(@xml, nil)
211
211
  { navigation: indexfile(@manifest), nav_object: index_object(@manifest),
212
- bibdata: @bibdata.to_hash, docrefs: liquid_docrefs(@manifest),
212
+ bibdata: YAML.safe_load(@bibdata.to_yaml,
213
+ permitted_classes: [Date, Symbol]),
214
+ docrefs: liquid_docrefs(@manifest),
213
215
  "prefatory-content": isodoc_builder(@xml.at("//prefatory-content")),
214
216
  "final-content": isodoc_builder(@xml.at("//final-content")),
215
- doctitle: @bibdata.title.first.title.content,
216
- docnumber: @bibdata.docidentifier.first.id }.each do |k, v|
217
+ doctitle: Array(@bibdata.title).first&.content,
218
+ docnumber: Array(@bibdata.docidentifier).first&.content }.each do |k, v|
217
219
  v and @isodoc.meta.set(k, v)
218
220
  end
219
221
  end
@@ -239,7 +241,7 @@ module Metanorma
239
241
  def error_anchor(erefs, docid)
240
242
  erefs.each do |e|
241
243
  msg = "<strong>** Unresolved reference to document #{docid} " \
242
- "from eref</strong>"
244
+ "from eref</strong>"
243
245
  e << msg
244
246
  strip_eref(e)
245
247
  @log&.add("METANORMA_3", e, params: [docid])
@@ -15,12 +15,12 @@ module Metanorma
15
15
 
16
16
  def validate_install_fonts(processor, options)
17
17
  unless install_fonts?(options)
18
- Util.log("[fontist] Skip font installation because" \
19
- " --no-install-fonts argument passed", :debug)
18
+ Util.log("[fontist] Skip font installation because " \
19
+ "--no-install-fonts argument passed", :debug)
20
20
  return false
21
21
  end
22
22
  unless has_custom_fonts?(processor, options, options)
23
- Util.log("[fontist] Skip font installation because "\
23
+ Util.log("[fontist] Skip font installation because " \
24
24
  "fonts_manifest is missing", :debug)
25
25
  return false
26
26
  end
@@ -60,8 +60,8 @@ module Metanorma
60
60
  :debug,
61
61
  )
62
62
  else
63
- Util.log("[fontist] Aborting without proper fonts installed," \
64
- " make sure that you have set option --agree-to-terms",
63
+ Util.log("[fontist] Aborting without proper fonts installed, " \
64
+ "make sure that you have set option --agree-to-terms",
65
65
  :fatal)
66
66
  end
67
67
  end
@@ -91,7 +91,12 @@ module Metanorma
91
91
  return unless validate_install_fonts(processor, options)
92
92
 
93
93
  @@updated_formulas_repo = false
94
- manifest = processor.fonts_manifest.dup
94
+ manifest = if processor.respond_to?(:fonts_manifest) &&
95
+ !processor.fonts_manifest.nil?
96
+ processor.fonts_manifest.dup
97
+ else
98
+ {}
99
+ end
95
100
  append_source_fonts(manifest, options)
96
101
  agree_to_terms, can_without_fonts, no_progress = validate_options(options)
97
102
 
@@ -104,16 +109,25 @@ module Metanorma
104
109
  end
105
110
 
106
111
  def self.has_custom_fonts?(processor, options, source_attributes)
107
- install_fonts?(options) \
112
+ (install_fonts?(options) \
108
113
  && processor.respond_to?(:fonts_manifest) \
109
- && !processor.fonts_manifest.nil? \
114
+ && !processor.fonts_manifest.nil?) \
110
115
  || source_attributes[:fonts]
111
116
  end
112
117
 
113
118
  def self.location_manifest(processor, source_attributes)
119
+ base = if processor.respond_to?(:fonts_manifest) &&
120
+ !processor.fonts_manifest.nil?
121
+ processor.fonts_manifest.dup
122
+ else
123
+ {}
124
+ end
125
+
126
+ return nil if base.empty? && !source_attributes[:fonts]
127
+
114
128
  instance = Fontist::Manifest.from_hash(
115
- append_source_fonts(processor.fonts_manifest.dup, source_attributes),
116
- locations: true
129
+ append_source_fonts(base, source_attributes),
130
+ locations: true,
117
131
  )
118
132
 
119
133
  instance.to_hash unless instance.nil?
@@ -1,3 +1,3 @@
1
1
  module Metanorma
2
- VERSION = "2.3.4".freeze
2
+ VERSION = "2.3.5".freeze
3
3
  end
data/metanorma.gemspec CHANGED
@@ -28,7 +28,8 @@ Gem::Specification.new do |spec|
28
28
  spec.add_runtime_dependency "concurrent-ruby"
29
29
  spec.add_runtime_dependency "fontist", ">= 2.1.2"
30
30
  spec.add_runtime_dependency "htmlentities"
31
- spec.add_runtime_dependency "isodoc", ">= 3.0.0"
31
+ spec.add_runtime_dependency "isodoc", ">= 3.5.0"
32
+ #spec.add_runtime_dependency "metanorma-standoc", ">= 3.4.0"
32
33
  spec.add_runtime_dependency "marcel"
33
34
  spec.add_runtime_dependency "metanorma-taste", "~> 1.0.0"
34
35
  spec.add_runtime_dependency "mn2pdf", "~> 2"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metanorma
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.4
4
+ version: 2.3.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-03-30 00:00:00.000000000 Z
11
+ date: 2026-04-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: asciidoctor
@@ -72,14 +72,14 @@ dependencies:
72
72
  requirements:
73
73
  - - ">="
74
74
  - !ruby/object:Gem::Version
75
- version: 3.0.0
75
+ version: 3.5.0
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
- version: 3.0.0
82
+ version: 3.5.0
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: marcel
85
85
  requirement: !ruby/object:Gem::Requirement