metanorma 2.5.4 → 2.5.6.pre.alpha.1

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: 4f36a841296240362316b293a3353c54b85b83485b81d21e762d639fe26ce100
4
- data.tar.gz: 7302ecaa3bbf5893fa6a0c52199ce7080475efb00a9973fe8e21ace651a996b8
3
+ metadata.gz: f225922f924a7498faff8af31ef32af2b2bdb7718ddbdd4d71e8111b1e1c2024
4
+ data.tar.gz: 25d6d62381fe280580b9914e2e08208b117e69a50f916670174f8cef483de801
5
5
  SHA512:
6
- metadata.gz: b9d143219d4f9a9130321c675e3b1bc8f5966dcb09961f13527381d493e7d6a6e7efffce28bd807bf5a07b2ae040048a321f498a8d15ecab002a756d8c493f8a
7
- data.tar.gz: fd1c20bd7b7d1062130781c1276b95b921a9408d4da2a17d622f5b21053b8a20ab168daa710bfbdefbc652901bea7d5e7c75e891e7a1fb91d2dd74075edbe39b
6
+ metadata.gz: 705eb23883f6b8c1e30137ebd300e34ab9248c62858e0a49afd0d3a7b08b08d61b0b26ee1d89599af4049bc31862f00b1fba922b6e31a7c5331c73c7c2700069
7
+ data.tar.gz: 6373b0edc74e3a9fa86faffd9e4c85c08b3ff1e57327e1f54fbea6de2da12825cc995910473b4f44e4b09a33490724130dbd669c4b2437a5729284cedcf3af13
data/Gemfile CHANGED
@@ -6,6 +6,9 @@ git_source(:github) { |repo| "https://github.com/#{repo}" }
6
6
 
7
7
  gemspec
8
8
 
9
+ # TEMPORARY cross-PR pin (metanorma-core#18): Compile resolves via Core::Flavors
10
+ gem "metanorma-core", github: "metanorma/metanorma-core", branch: "feat/flavor-table"
11
+
9
12
  begin
10
13
  eval_gemfile("Gemfile.devel")
11
14
  rescue StandardError
data/Gemfile.devel ADDED
@@ -0,0 +1,20 @@
1
+ # Local development pins (eval'd by Gemfile; not committed workflow state)
2
+ gem "metanorma-document", github: "metanorma/metanorma-document", branch: "main"
3
+ gem "metanorma-standoc", github: "metanorma/metanorma-standoc", branch: "main"
4
+ gem "metanorma-iso", github: "metanorma/metanorma-iso", branch: "main"
5
+ gem "isodoc", github: "metanorma/isodoc", branch: "main"
6
+ # released metanorma-iho 1.4.0 still carries lib/relaton/render/general.rb,
7
+ # which shadows relaton-render's iso690 autoload by load-path name; iho
8
+ # main relocated its render files
9
+ gem "metanorma-iho", github: "metanorma/metanorma-iho", branch: "main"
10
+ gem "pubid", "~> 2.0.0.pre.alpha"
11
+ # The 1.9.356/0.5.13x pin pair worked around the leptris#1733 to_xml
12
+ # regression; retired — the fleet line is leptris 1.9.376 + moxml 0.5.149
13
+ # (all suites green), and the exact pin now deadlocks against vectory's
14
+ # leptris >= 1.9.361.1 floor.
15
+ gem "leptris", "~> 1.9"
16
+ gem "relaton-cli", "~> 3.0.0.pre.alpha"
17
+ gem "glossarist", "~> 2.13"
18
+ gem "lutaml-model", "~> 0.8.107"
19
+ gem "metanorma-plugin-glossarist", "~> 0.5"
20
+ gem "moxml", "~> 0.5"
@@ -107,6 +107,10 @@ module Metanorma
107
107
  end
108
108
  # Relaton doesn't understand Pres XML tags
109
109
  b.xpath("//xmlns:fmt-identifier").each(&:remove)
110
+ # Relaton models a single <edition>; flavors emit a language-neutral
111
+ # edition plus localized variants (<edition language="en">first
112
+ # edition</edition>). Keep the language-neutral one for bibdata.
113
+ b.xpath("//xmlns:edition[@language != '']").each(&:remove)
110
114
  r.from_xml(b.to_xml)
111
115
  end
112
116
 
@@ -145,6 +145,12 @@ module Metanorma
145
145
  end
146
146
 
147
147
  def update_filepaths(entry, prefix)
148
+ # `manifest_expand_yaml_entry` hands us the loaded sub-manifest's
149
+ # `entry` collection directly, which is an Array of entries.
150
+ if entry.is_a?(Array)
151
+ entry.each { |e| update_filepaths(e, prefix) }
152
+ return
153
+ end
148
154
  entry.file && !(Pathname.new entry.file).absolute? and
149
155
  entry.file = File.join(prefix, entry.file)
150
156
  entry&.entry&.each do |f|
@@ -47,7 +47,8 @@ module Metanorma
47
47
  ::Metanorma::Collection::Util::hide_refs(xml)
48
48
  # post: references containers with only hidden bibitems flagged hidden.
49
49
  sso and eref2link(xml, sso)
50
- @nested || @reinflate or svgmap_resolve(xml, docid, sso)
50
+ # svgmap_resolve hands back the tree Vectory rebuilt; keep it.
51
+ xml = svgmap_resolve(xml, docid, sso) unless @nested || @reinflate
51
52
  xml.to_xml
52
53
  end
53
54
 
@@ -36,11 +36,15 @@ module Metanorma
36
36
  # Stage 3: Process with Vectory
37
37
  # Pass document suffix to Vectory as id_suffix for proper SVG ID disambiguation.
38
38
  # Vectory handles both id_suffix (document-level) and index suffix internally.
39
+ # It parses its own copy and returns the processed document, so the
40
+ # result must be adopted here or none of its work reaches the tree.
39
41
  doc_suffix = @files.get(docid, :document_suffix)
40
- Vectory::SvgMapping.new(docxml, "", id_suffix: doc_suffix).call
42
+ mapped = Vectory::SvgMapping.new(docxml, "", id_suffix: doc_suffix).call
43
+ docxml = Nokogiri::XML(mapped.to_xml, &:huge)
41
44
 
42
45
  # Stage 4: Extract processed SVG content
43
46
  extract_svgmap_content(docxml, isodoc)
47
+ docxml
44
48
  end
45
49
 
46
50
  # Prepares document and context for svgmap resolution
@@ -98,9 +98,7 @@ module Metanorma
98
98
  end
99
99
 
100
100
  def taste2flavor(taste)
101
- tastes = Metanorma::TasteRegister.instance.aliases
102
- tastes[taste.to_sym] and taste = tastes[taste.to_sym]
103
- taste
101
+ ::Metanorma::Core::FlavorLoader.taste2flavor(taste)
104
102
  end
105
103
 
106
104
  def taste2isodoc_attrs(taste, format)
@@ -125,9 +123,16 @@ module Metanorma
125
123
  # not processed already by add_suffix_to_attrs
126
124
  def url_in_css_styles(doc, ids, document_suffix)
127
125
  update_ids_css(doc.root, ids, document_suffix)
128
- doc.xpath("//i:svg", "i" => SVG_NS).each do |s|
126
+ # svgmap SVGs are owned by Vectory::SvgMapping, which applies the
127
+ # same suffix itself; suffixing them here would double it. Only
128
+ # standalone SVGs need the suffix from this pass.
129
+ doc.xpath("//i:svg[not(ancestor::*[local-name()='svgmap'])]",
130
+ "i" => SVG_NS).each do |s|
129
131
  svg = Vectory::SvgDocument.new(s.to_xml)
130
132
  svg.suffix_ids(document_suffix)
133
+ # suffix_ids mutates SvgDocument's own parse; write the
134
+ # suffixed SVG back into the tree, or the suffix is lost
135
+ s.replace(svg.content)
131
136
  end
132
137
  end
133
138
 
@@ -210,7 +210,13 @@ module Metanorma
210
210
  # external_bibitems[x.sub(/^#{key}_/, "")]
211
211
  end.each do |x|
212
212
  ins << if b = internal_bibitems[x.sub(/^#{key}_/, "")]
213
- b.dup.tap { |m| m["id"] = x }
213
+ b.dup.tap do |m|
214
+ m["id"] = x
215
+ # The anchor belongs to the original bibitem: the
216
+ # hidden copy is referenced by its new id, and a
217
+ # duplicated anchor fails id-uniqueness validation.
218
+ m.delete("anchor")
219
+ end
214
220
  else new_indirect_bibitem(x, key)
215
221
  end
216
222
  end
@@ -39,7 +39,13 @@ module Metanorma
39
39
  end
40
40
 
41
41
  def options_in_file(filename)
42
+ # the adoc preprocessing path re-extracts options from a Tempfile
43
+ filename = filename.path if filename.is_a?(Tempfile)
42
44
  content = read_file(filename)
45
+ # XML inputs carry no AsciiDoc header options; booting the adoc
46
+ # pipeline for them only drags every plugin into the compile.
47
+ return extract_xml_options(content) if filename.end_with?(".xml")
48
+
43
49
  Metanorma::Input::Asciidoc.new.extract_metanorma_options(content)
44
50
  .merge(extract_xml_options(content))
45
51
  end
@@ -74,20 +80,34 @@ module Metanorma
74
80
  Metanorma::TasteRegister.document_transformers_for(taste) || {}
75
81
  end
76
82
 
77
- # The processor's output formats merged with the suffixes of any
78
- # taste-contributed document-model formats, so those formats pass
79
- # extension validation and get an output suffix.
83
+ # Harness formats available to every flavor, regardless of the
84
+ # processor's own list. MKO (metanorma-document) is resolved via
85
+ # Core::Flavors, so it needs nothing from the flavor gems.
86
+ HARNESS_OUTPUT_FORMATS = { mko: "mko" }.freeze
87
+
88
+ # Formats a flavor offers by default: its own list plus
89
+ # taste-contributed document-model formats. The harness formats
90
+ # (mko) are deliberately absent — they are opt-in via
91
+ # --extensions, never a surprise default output.
92
+ def default_output_formats(options)
93
+ @processor.output_formats
94
+ .merge(
95
+ taste_transformers(options)
96
+ .transform_values { |spec| spec[:suffix] }.compact,
97
+ )
98
+ end
99
+
100
+ # The default formats merged with the harness formats, so those
101
+ # pass extension validation and get an output suffix.
80
102
  def effective_output_formats(options)
81
- @processor.output_formats.merge(
82
- taste_transformers(options)
83
- .transform_values { |spec| spec[:suffix] }.compact,
84
- )
103
+ default_output_formats(options).merge(HARNESS_OUTPUT_FORMATS)
85
104
  end
86
105
 
87
106
  # Whether +ext+ is generated from presentation XML, honouring both the
88
107
  # processor's own answer and a taste transformer's +:presentation+ flag.
89
108
  def uses_presentation_xml?(ext, options)
90
- @processor.use_presentation_xml(ext) ||
109
+ ext == :mko || # unit numbering comes from the presentation model
110
+ @processor.use_presentation_xml(ext) ||
91
111
  (taste_transformers(options)[ext] || {})[:presentation] == true
92
112
  end
93
113
 
@@ -98,13 +118,19 @@ module Metanorma
98
118
  end and ext << :presentation
99
119
  !ext.include?(:rxl) && options[:site_generate] and
100
120
  ext << :rxl
121
+ # Keep options[:extension_keys] in sync: get_isodoc_options filters
122
+ # output_formats by extension_keys, and presentation is an implicit
123
+ # dependency of html/doc/pdf — if it is only on the local +ext+ array,
124
+ # the filter strips it from the formats table (and, when the processor
125
+ # hands out a live hash, permanently from the flavor config).
126
+ options[:extension_keys] = ext
101
127
  ext
102
128
  end
103
129
 
104
130
  def extract_extensions(options)
105
131
  formats = effective_output_formats(options)
106
132
  options[:extension_keys] ||=
107
- formats.reduce([]) { |memo, (k, _)| memo << k }
133
+ default_output_formats(options).reduce([]) { |memo, (k, _)| memo << k }
108
134
  options[:extension_keys].reduce([]) do |memo, e|
109
135
  if formats[e] then memo << e
110
136
  else
@@ -134,8 +160,14 @@ module Metanorma
134
160
  get_isodoc_fileparams(options, ret)
135
161
  copy_isodoc_options_attrs(options, ret)
136
162
  font_manifest_mn2pdf(options, ret, ext)
137
- ret[:output_formats]&.select! do |k, _|
138
- options[:extension_keys].include?(k)
163
+ # Filter a COPY — never select! the processor's live formats table.
164
+ # Generic (and any flavor that returns configuration.formats directly)
165
+ # would otherwise permanently lose :presentation after the first
166
+ # html/doc request that did not list presentation in extension_keys.
167
+ if ret[:output_formats]
168
+ keys = options[:extension_keys] || []
169
+ ret[:output_formats] = ret[:output_formats]
170
+ .select { |k, _| keys.include?(k) }
139
171
  end
140
172
  ret[:log] = @log
141
173
  ret
@@ -2,16 +2,25 @@
2
2
 
3
3
  module Metanorma
4
4
  class Compile
5
+ # Thin adapter: taste resolution reads the core table; gem loading
6
+ # stays on FlavorLoader so the existing SystemExit / processor-
7
+ # registration contract is byte-identical to main.
5
8
  module Flavor
6
9
  def load_flavor(stdtype)
7
- Metanorma::Core::FlavorLoader.load_flavor(stdtype)
10
+ Metanorma::Core::FlavorLoader.load_flavor(taste2flavor(stdtype))
8
11
  end
9
12
 
10
13
  def taste2flavor(stdtype)
14
+ entry = Metanorma::Core::Flavors.find(stdtype)
15
+ return entry.base_flavor if entry&.taste?
16
+
11
17
  Metanorma::Core::FlavorLoader.taste2flavor(stdtype)
12
18
  end
13
19
 
14
20
  def stdtype2flavor_gem(stdtype)
21
+ entry = Metanorma::Core::Flavors.find(stdtype)
22
+ return entry.gem if entry && !entry.taste?
23
+
15
24
  Metanorma::Core::FlavorLoader.stdtype2flavor_gem(stdtype)
16
25
  end
17
26
  end
@@ -1,6 +1,6 @@
1
1
  module Metanorma
2
2
  class Compile
3
- NO_FONTIST_FORMATS = %i[xml presentation rxl].freeze
3
+ NO_FONTIST_FORMATS = %i[xml presentation rxl mko].freeze
4
4
 
5
5
  # Generate presentation XML from semantic XML
6
6
  def generate_presentation_xml(source_file, xml, bibdata, output_paths, opt)
@@ -109,6 +109,10 @@ module Metanorma
109
109
  end
110
110
  FileUtils.cp f, output_paths[:presentationxml]
111
111
  true
112
+ elsif ext == :mko
113
+ # Harness format: export the MKO bundle from the typed model
114
+ export_mko_bundle(output_paths)
115
+ true
112
116
  elsif ext == :html && options[:sectionsplit]
113
117
  # Special case: Split HTML into sections
114
118
  sectionsplit_convert(
@@ -120,6 +124,32 @@ module Metanorma
120
124
  end
121
125
  end
122
126
 
127
+ # Export the MKO machine serialization (metanorma-document). The
128
+ # semantic and presentation XML are already on disk by the time this
129
+ # runs; Mko resolves the flavor model via the Core::Flavors registry.
130
+ def export_mko_bundle(output_paths)
131
+ require "metanorma/document"
132
+ require "metanorma/mko"
133
+ # :xml is the freshly written semantic XML; orig_filename is the
134
+ # adoc SOURCE and is only right when an output_dir kept the
135
+ # semantic XML at the input location.
136
+ semantic_path = [output_paths[:xml], output_paths[:orig_filename]]
137
+ .find { |p1| p1 && File.exist?(p1) && File.extname(p1) != ".adoc" }
138
+ presentation = if File.exist?(output_paths[:presentationxml])
139
+ File.read(output_paths[:presentationxml])
140
+ end
141
+ Metanorma::Mko.export(File.read(semantic_path),
142
+ to: File.dirname(output_paths[:out]),
143
+ presentation_xml: presentation)
144
+ rescue LoadError => e
145
+ @log.add_msg("MKO_OUTPUT" => { category: "MKO Output",
146
+ error: "the mko output format requires " \
147
+ "the metanorma-document gem: %s",
148
+ severity: 0 })
149
+ @log.add("MKO_OUTPUT", nil, params: [e.message])
150
+ nil
151
+ end
152
+
123
153
  # Process format that requires presentation XML
124
154
  def process_via_presentation_xml(ext, output_paths, options, isodoc_options)
125
155
  @queue.schedule(ext, output_paths.dup, options.dup,
@@ -1,3 +1,3 @@
1
1
  module Metanorma
2
- VERSION = "2.5.4".freeze
2
+ VERSION = "2.5.6.pre.alpha.1".freeze
3
3
  end
data/metanorma.gemspec CHANGED
@@ -31,7 +31,7 @@ Gem::Specification.new do |spec|
31
31
  spec.add_runtime_dependency "isodoc", ">= 3.5.0"
32
32
  spec.add_runtime_dependency "marcel"
33
33
  spec.add_runtime_dependency "metanorma-core"
34
- spec.add_runtime_dependency "metanorma-standoc"
34
+ spec.add_runtime_dependency "metanorma-standoc", ">= 3.5.0"
35
35
  spec.add_runtime_dependency "mn2pdf", "~> 2"
36
36
  spec.add_runtime_dependency "nokogiri"
37
37
  spec.add_development_dependency "canon" #, "= 0.2.3"
@@ -39,5 +39,4 @@ Gem::Specification.new do |spec|
39
39
  spec.add_development_dependency "metanorma-iso"
40
40
 
41
41
  # relaton-cli is required by Metanorma::Collection
42
- spec.add_dependency "relaton-cli"
43
- end
42
+ spec.add_dependency "relaton-cli", ">= 3.0.0.pre.alpha"end
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.5.4
4
+ version: 2.5.6.pre.alpha.1
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-08-30 00:00:00.000000000 Z
11
+ date: 2026-10-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: asciidoctor
@@ -114,14 +114,14 @@ dependencies:
114
114
  requirements:
115
115
  - - ">="
116
116
  - !ruby/object:Gem::Version
117
- version: '0'
117
+ version: 3.5.0
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - ">="
123
123
  - !ruby/object:Gem::Version
124
- version: '0'
124
+ version: 3.5.0
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: mn2pdf
127
127
  requirement: !ruby/object:Gem::Requirement
@@ -198,14 +198,14 @@ dependencies:
198
198
  requirements:
199
199
  - - ">="
200
200
  - !ruby/object:Gem::Version
201
- version: '0'
201
+ version: 3.0.0.pre.alpha
202
202
  type: :runtime
203
203
  prerelease: false
204
204
  version_requirements: !ruby/object:Gem::Requirement
205
205
  requirements:
206
206
  - - ">="
207
207
  - !ruby/object:Gem::Version
208
- version: '0'
208
+ version: 3.0.0.pre.alpha
209
209
  description: Library to process any Metanorma standard.
210
210
  email:
211
211
  - open.source@ribose.com
@@ -223,6 +223,7 @@ files:
223
223
  - CHANGELOG.adoc
224
224
  - CODE_OF_CONDUCT.md
225
225
  - Gemfile
226
+ - Gemfile.devel
226
227
  - LICENSE.txt
227
228
  - README.adoc
228
229
  - lib/metanorma.rb