metanorma 2.2.0 → 2.2.2

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: af06733dd8691111633e6309c85ebfa069baa2edf16cbd7e8458a17ad34d4b2a
4
- data.tar.gz: e924bb9b298cc37c2cebef6f8d9251ae3979e9cd9b537539057a5ade07e11c88
3
+ metadata.gz: 6c21a32c429827b3a3f308801ec2e8617f2e30f2baf8c8e5e6c80f2c105b0ce2
4
+ data.tar.gz: b59f55514b1413623471c7c408a7688a87513f03aca899afeb433372577f37e1
5
5
  SHA512:
6
- metadata.gz: 29499feb91dd56f4fe6f281f885263c897fb555a9905ce3a32b56d175199b520e9066041ff96489d5221302c259a08bf0d3c07bde19a232b3893d79a0bde747b
7
- data.tar.gz: 717f1409b88dfc565393c71cddb0fda604e062d38e80b45c470dc06957ac5e7cf2f5adfd7ef7083666aeb4f7f7b6356fcbc95014bb2e9091c9c927232d7c225f
6
+ metadata.gz: 06e63a51abf0ff822b2f6bed6cf51a1c0a55f08375aff1aec64d41016fd5c3f4d61ed21661911dee7bb9c4477a406b1a5bd125f95c2d00a9096415249cba24c5
7
+ data.tar.gz: 78352215966b37d04fbb5cb0203bd65d725b63eade9652ecf2142ef4d9b594fe69229232de6e5796c44c782cef3763af4e5d31c2eee2a0f67e8ab3c66bc470da
@@ -6,16 +6,37 @@ module Metanorma
6
6
  module Converters
7
7
  def bibdata_from_yaml(model, value)
8
8
  value and !value.empty? or return
9
+ force_primary_docidentifier_yaml(value)
9
10
  model.bibdata = Relaton::Cli::YAMLConvertor.convert_single_file(value)
10
11
  end
11
12
 
13
+ def force_primary_docidentifier_yaml(value)
14
+ case value["docid"]
15
+ when Array
16
+ value["docid"].empty? ||
17
+ value["docid"].none? do |x|
18
+ x["primary"] == "true"
19
+ end or
20
+ value["docid"].first["primary"] = "true"
21
+ when Hash
22
+ value["docid"]["primary"] ||= "true"
23
+ end
24
+ end
25
+
12
26
  def bibdata_to_yaml(model, doc)
13
27
  doc["bibdata"] = model.bibdata&.to_hash
14
28
  end
15
29
 
16
30
  def bibdata_from_xml(model, node)
17
- node and
18
- model.bibdata = Relaton::Cli.parse_xml(node.adapter_node)
31
+ node or return
32
+ force_primary_docidentifier_xml(node.adapter_node)
33
+ model.bibdata = Relaton::Cli.parse_xml(node.adapter_node)
34
+ end
35
+
36
+ def force_primary_docidentifier_xml(node)
37
+ node.at("//docidentifier[@primary = 'true']") and return node
38
+ d = node.at("//docidentifier") or return node
39
+ d["primary"] = "true"
19
40
  end
20
41
 
21
42
  def bibdata_to_xml(model, parent, doc)
@@ -11,14 +11,12 @@ module Metanorma
11
11
  end
12
12
 
13
13
  def svgmap_resolve(docxml, docid, presxml)
14
- #require "debug"; binding.b
15
14
  ids = @files.get(docid, :ids)
16
15
  docxml = svg_unnest(svg_datauri(docxml, docid))
17
16
  isodoc = IsoDoc::PresentationXMLConvert.new({})
18
17
  isodoc.bibitem_lookup(docxml)
19
18
  tag = presxml ? "fmt-eref" : "eref"
20
19
  docxml.xpath(ns("//svgmap//#{tag}")).each do |e|
21
- #require "debug"; binding.b
22
20
  svgmap_resolve_eref(e, isodoc, docxml, ids, presxml)
23
21
  end
24
22
  docxml.xpath(ns("//svgmap/target")).each do |t| # undo Presentation XML: Vectory takes eref not fmt-eref
@@ -39,8 +39,6 @@ module Metanorma
39
39
  def add_suffix_to_attrs(doc, suffix, tag_name, attr_name, isodoc)
40
40
  (suffix.nil? || suffix.empty?) and return
41
41
  doc.xpath(isodoc.ns("//#{tag_name}[@#{attr_name}]")).each do |elem|
42
- #warn "#{tag_name} : #{elem.name}" if attr_name == "bibitemid"
43
- #require 'debug'; binding.b if attr_name == "bibitemid" && #!%w(eref fmt-eref link fmt-link).include?(elem.name)
44
42
  a = elem.attributes[attr_name].value
45
43
  /_#{suffix}$/.match?(a) or
46
44
  elem.attributes[attr_name].value = "#{a}_#{suffix}"
@@ -91,6 +89,8 @@ module Metanorma
91
89
  isodoc.i18n_init(lang, script, nil) # read in internationalisation
92
90
  # TODO locale?
93
91
  isodoc.metadata_init(lang, script, nil, isodoc.i18n)
92
+ isodoc.xref_init(lang, script, nil, isodoc.i18n, {})
93
+ isodoc.xrefs.klass.meta = isodoc.meta
94
94
  isodoc.info(xml, nil)
95
95
  isodoc
96
96
  end
@@ -184,7 +184,7 @@ module Metanorma
184
184
  end
185
185
 
186
186
  def process_input_adoc_overrides(attrs, options)
187
- @registry.tastes.available_tastes.include?(options[:supplied_type]) or
187
+ Metanorma::TasteRegister.instance.available_tastes.include?(options[:supplied_type]) or
188
188
  return
189
189
  c = Metanorma::TasteRegister.get(options[:supplied_type])
190
190
  c.process_input_adoc_overrides(attrs, options)
@@ -36,8 +36,8 @@ module Metanorma
36
36
  # @param xml [Nokogiri::XML::Document] the XML document
37
37
  # @return [String] the cleaned sourcecode
38
38
  def clean_sourcecode(xml)
39
- xml.xpath(".//callout | .//annotation | .//xmlns:callout | "\
40
- ".//xmlns:annotation").each(&:remove)
39
+ xml.xpath(".//callout | .//callout-annotation | .//xmlns:callout | "\
40
+ ".//xmlns:callout-annotation").each(&:remove)
41
41
  xml.xpath(".//br | .//xmlns:br").each { |x| x.replace("\n") }
42
42
  a = xml.at("./body | ./xmlns:body") and xml = a
43
43
  HTMLEntities.new.decode(xml.children.to_xml)
@@ -7,45 +7,160 @@ class Error < StandardError
7
7
  end
8
8
 
9
9
  module Metanorma
10
+ # Central registry for managing Metanorma processors, flavors, and their aliases
11
+ #
12
+ # This singleton class provides a centralized registry for:
13
+ # - Metanorma processors (document format processors)
14
+ # - Flavor aliases (mapping legacy/alternative names to canonical flavors)
15
+ # - Taste configurations (via TasteRegister integration)
16
+ #
17
+ # The registry maintains backward compatibility with legacy flavor names while
18
+ # integrating with the modern TasteRegister system for dynamic taste management.
19
+ #
20
+ # @example Basic usage
21
+ # registry = Metanorma::Registry.instance
22
+ #
23
+ # # Register a processor
24
+ # registry.register(MyProcessor)
25
+ #
26
+ # # Look up flavor aliases
27
+ # registry.alias(:csd) # => :cc
28
+ #
29
+ # # Register custom aliases
30
+ # registry.register_alias(:my_flavor, :iso)
31
+ #
32
+ # @example Finding processors
33
+ # processor = registry.find_processor(:iso)
34
+ # formats = registry.output_formats
35
+ # backends = registry.supported_backends
10
36
  class Registry
11
37
  include Singleton
12
38
 
13
39
  attr_reader :processors, :tastes
14
40
 
15
- # TODO: make aliases configurable
41
+ # Default legacy aliases for backward compatibility
42
+ # Maps old flavor names to their canonical equivalents
43
+ DEFAULT_ALIASES = { csd: :cc, m3d: :m3aawg, mpfd: :mpfa, csand: :csa }.freeze
44
+
45
+ # Initialize the registry with processors, tastes, and aliases
46
+ #
47
+ # Sets up the registry by:
48
+ # 1. Initializing empty processors hash
49
+ # 2. Connecting to the TasteRegister instance
50
+ # 3. Initializing custom aliases with defaults
16
51
  def initialize
17
52
  @processors = {}
18
53
  @tastes = Metanorma::TasteRegister.instance
19
- tastealiases = @tastes.available_tastes.each_with_object({}) do |x, m|
20
- m[x] = @tastes.taste_info(x)[:base_flavor]
21
- end
22
- @aliases = { csd: :cc, m3d: :m3aawg, mpfd: :mpfa, csand: :csa }
23
- .merge tastealiases
54
+ @custom_aliases = DEFAULT_ALIASES.dup
24
55
  end
25
56
 
57
+ # Look up the canonical flavor name for a given alias
58
+ #
59
+ # Checks aliases in priority order:
60
+ # 1. Custom registered aliases (highest priority)
61
+ # 2. Taste-based aliases from TasteRegister
62
+ # 3. Returns nil if no alias found
63
+ #
64
+ # @param flavour [Symbol, String, nil] The flavor alias to look up
65
+ # @return [Symbol, nil] The canonical flavor name, or nil if no alias exists
66
+ #
67
+ # @example
68
+ # registry.alias(:csd) # => :cc (from DEFAULT_ALIASES)
69
+ # registry.alias(:icc) # => :iso (from taste configuration)
70
+ # registry.alias(:unknown) # => nil
71
+ # registry.alias(nil) # => nil
26
72
  def alias(flavour)
27
- @aliases[flavour]
73
+ return nil if flavour.nil?
74
+
75
+ flavour_sym = flavour.to_sym
76
+
77
+ # Check custom aliases first (includes defaults)
78
+ return @custom_aliases[flavour_sym] if @custom_aliases.key?(flavour_sym)
79
+
80
+ # Then check taste aliases
81
+ taste_aliases = @tastes.aliases
82
+ taste_aliases[flavour_sym]
83
+ end
84
+
85
+ # Register a custom alias mapping
86
+ #
87
+ # Allows runtime registration of flavor aliases. Custom aliases take precedence
88
+ # over taste-based aliases, allowing overrides of taste configurations.
89
+ #
90
+ # @param alias_name [Symbol, String] The alias name to register
91
+ # @param target_flavor [Symbol, String] The canonical flavor it should map to
92
+ #
93
+ # @example
94
+ # registry.register_alias(:my_custom, :iso)
95
+ # registry.alias(:my_custom) # => :iso
96
+ #
97
+ # # Override a taste alias
98
+ # registry.register_alias(:icc, :custom_iso)
99
+ def register_alias(alias_name, target_flavor)
100
+ @custom_aliases[alias_name.to_sym] = target_flavor.to_sym
28
101
  end
29
102
 
103
+ # Register a Metanorma processor
104
+ #
105
+ # Registers a processor class and automatically creates aliases for all its
106
+ # short names. The last short name is considered the canonical name.
107
+ #
108
+ # @param processor [Class] A processor class that inherits from Metanorma::Processor
109
+ # @raise [Error] If the processor doesn't inherit from Metanorma::Processor
110
+ # @return [Array<Symbol>] Array of short names for the processor
111
+ #
112
+ # @example
113
+ # registry.register(Metanorma::ISO::Processor)
114
+ # # Registers processor and creates aliases for all its short names
30
115
  def register(processor)
31
- processor < ::Metanorma::Processor or raise Error
32
- p = processor.new
33
- # p.short[-1] is the canonical name
34
- short = Array(p.short)
35
- @processors[short[-1]] = p
36
- short.each { |s| @aliases[s] = short[-1] }
37
- Array(p.short)
38
- Util.log("[metanorma] processor \"#{Array(p.short)[0]}\" registered", :info)
116
+ unless processor < ::Metanorma::Processor
117
+ raise Error, "Processor must inherit from Metanorma::Processor"
118
+ end
119
+
120
+ # The last short name is the canonical name
121
+ processor_instance = processor.new
122
+ short_names = Array(processor_instance.short)
123
+ canonical_name = short_names.last
124
+
125
+ # Register processor with canonical name
126
+ @processors[canonical_name] = processor_instance
127
+
128
+ # Create aliases for all short names pointing to canonical name
129
+ short_names.each { |name| @custom_aliases[name] = canonical_name }
130
+
131
+ Util.log("[metanorma] processor \"#{short_names.first}\" registered", :info)
132
+ short_names
39
133
  end
40
134
 
135
+ # Find a registered processor by its short name
136
+ #
137
+ # @param short [Symbol, String] The short name of the processor to find
138
+ # @return [Metanorma::Processor, nil] The processor instance, or nil if not found
139
+ #
140
+ # @example
141
+ # processor = registry.find_processor(:iso)
142
+ # processor = registry.find_processor("iso")
41
143
  def find_processor(short)
42
144
  @processors[short.to_sym]
43
145
  end
44
146
 
147
+ # Get list of all supported backend names
148
+ #
149
+ # @return [Array<Symbol>] Array of registered processor backend names
150
+ #
151
+ # @example
152
+ # registry.supported_backends # => [:iso, :iec, :itu, ...]
45
153
  def supported_backends
46
154
  @processors.keys
47
155
  end
48
156
 
157
+ # Get output formats supported by each registered processor
158
+ #
159
+ # @return [Hash<Symbol, Hash>] Hash mapping processor names to their output formats
160
+ #
161
+ # @example
162
+ # registry.output_formats
163
+ # # => { iso: { html: "html", pdf: "pdf", ... }, iec: { ... }, ... }
49
164
  def output_formats
50
165
  @processors.inject({}) do |acc, (k, v)|
51
166
  acc[k] = v.output_formats
@@ -53,6 +168,13 @@ module Metanorma
53
168
  end
54
169
  end
55
170
 
171
+ # Get XML root tags for processors with Asciidoctor backends
172
+ #
173
+ # @return [Hash<Symbol, String>] Hash mapping processor names to their XML root tags
174
+ #
175
+ # @example
176
+ # registry.root_tags
177
+ # # => { iso: "iso-standard", iec: "iec-standard", ... }
56
178
  def root_tags
57
179
  @processors.inject({}) do |acc, (k, v)|
58
180
  if v.asciidoctor_backend
@@ -1,3 +1,3 @@
1
1
  module Metanorma
2
- VERSION = "2.2.0".freeze
2
+ VERSION = "2.2.2".freeze
3
3
  end
data/metanorma.gemspec CHANGED
@@ -29,7 +29,7 @@ Gem::Specification.new do |spec|
29
29
  spec.add_runtime_dependency "fontist", ">= 1.14.3"
30
30
  spec.add_runtime_dependency "htmlentities"
31
31
  spec.add_runtime_dependency "isodoc", ">= 3.0.0"
32
- spec.add_runtime_dependency "metanorma-taste"
32
+ spec.add_runtime_dependency "metanorma-taste", "~> 0.1.0"
33
33
  spec.add_runtime_dependency "mn2pdf", "~> 2"
34
34
  spec.add_runtime_dependency "nokogiri"
35
35
 
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.2.0
4
+ version: 2.2.2
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-06-09 00:00:00.000000000 Z
11
+ date: 2025-07-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: asciidoctor
@@ -84,16 +84,16 @@ dependencies:
84
84
  name: metanorma-taste
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ">="
87
+ - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '0'
89
+ version: 0.1.0
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ">="
94
+ - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '0'
96
+ version: 0.1.0
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: mn2pdf
99
99
  requirement: !ruby/object:Gem::Requirement