metanorma 2.2.9 → 2.3.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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +14 -0
  3. data/lib/metanorma/collection/collection.rb +46 -104
  4. data/lib/metanorma/collection/config/config.rb +5 -0
  5. data/lib/metanorma/collection/config/converters.rb +1 -0
  6. data/lib/metanorma/collection/config/manifest.rb +23 -0
  7. data/lib/metanorma/collection/document/document.rb +35 -13
  8. data/lib/metanorma/collection/filelookup/base.rb +43 -0
  9. data/lib/metanorma/collection/filelookup/filelookup.rb +168 -69
  10. data/lib/metanorma/collection/filelookup/filelookup_sectionsplit.rb +49 -10
  11. data/lib/metanorma/collection/filelookup/utils.rb +93 -0
  12. data/lib/metanorma/collection/helpers.rb +82 -0
  13. data/lib/metanorma/collection/manifest/manifest.rb +14 -3
  14. data/lib/metanorma/collection/multilingual/multilingual.rb +1 -1
  15. data/lib/metanorma/collection/renderer/filelocation.rb +162 -0
  16. data/lib/metanorma/collection/renderer/fileparse.rb +9 -6
  17. data/lib/metanorma/collection/renderer/fileprocess.rb +56 -42
  18. data/lib/metanorma/collection/renderer/navigation.rb +15 -1
  19. data/lib/metanorma/collection/renderer/render_word.rb +8 -4
  20. data/lib/metanorma/collection/renderer/renderer.rb +104 -10
  21. data/lib/metanorma/collection/renderer/svg.rb +54 -7
  22. data/lib/metanorma/collection/renderer/utils.rb +58 -22
  23. data/lib/metanorma/collection/sectionsplit/collection.rb +14 -5
  24. data/lib/metanorma/collection/sectionsplit/sectionsplit.rb +20 -7
  25. data/lib/metanorma/collection/util/disambig_files.rb +4 -5
  26. data/lib/metanorma/collection/util/util.rb +106 -6
  27. data/lib/metanorma/collection/xrefprocess/xrefprocess.rb +2 -2
  28. data/lib/metanorma/compile/compile.rb +2 -2
  29. data/lib/metanorma/compile/compile_options.rb +23 -11
  30. data/lib/metanorma/compile/flavor.rb +11 -4
  31. data/lib/metanorma/compile/render.rb +1 -0
  32. data/lib/metanorma/input/asciidoc.rb +1 -1
  33. data/lib/metanorma/util/fontist_helper.rb +5 -6
  34. data/lib/metanorma/version.rb +1 -1
  35. data/metanorma.gemspec +4 -14
  36. metadata +28 -150
@@ -0,0 +1,162 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Metanorma
4
+ class Collection
5
+ class Renderer
6
+ def file_compile_formats(filename, identifier, opts)
7
+ f = @files.get(identifier, :outputs)
8
+ format = opts[:extension_keys]
9
+ concatenate_presentation?({ format: }) and format << :presentation
10
+ format.each do |e|
11
+ e == :pdf and output_filename = opts[:pdffile]
12
+ file_compile_format(filename, identifier, e, f, output_filename)
13
+ end
14
+ @files.set(identifier, :outputs, f)
15
+ end
16
+
17
+ # Generate output filename with correct extension
18
+ def output_filename_with_extension(fname, format)
19
+ ext = @compile.processor.output_formats[format]
20
+ fname_base = File.basename(fname)
21
+ # ONLY replace .xml or .html extensions, NEVER remove section numbers
22
+ if /\.(xml|html)$/.match?(fname_base)
23
+ fname_base.sub(/\.(xml|html)$/, ".#{ext}")
24
+ else
25
+ "#{fname_base}.#{ext}"
26
+ end
27
+ end
28
+
29
+ # Move file to new output filename if specified
30
+ def handle_new_output_filename(output_fname, new_output_fname)
31
+ return output_fname unless new_output_fname
32
+
33
+ FileUtils.mv(File.join(@outdir, output_fname),
34
+ File.join(@outdir, new_output_fname))
35
+ new_output_fname
36
+ end
37
+
38
+ # Apply custom filename pattern with substitutions
39
+ def apply_custom_filename_pattern(ident, custom_fname, output_fname,
40
+ format)
41
+ idx = @files.get(ident, :idx)
42
+ original_file = @files.get(ident, :ref)
43
+ basename = File.basename(original_file, ".*")
44
+ basename_legacy = File.basename(original_file)
45
+ custom_fname = @files.substitute_filename_pattern(
46
+ custom_fname, document_num: idx,
47
+ basename: basename, basename_legacy: basename_legacy
48
+ )
49
+ if File.dirname(custom_fname) == "."
50
+ output_fname
51
+ else
52
+ preserve_output_dir_structure(custom_fname, output_fname,
53
+ format, explicit_custom: true)
54
+ end
55
+ end
56
+
57
+ # Apply directory preservation for files with directory structure
58
+ def apply_directory_preservation(fname, output_fname, format)
59
+ fname_dir = File.dirname(fname)
60
+ output_fname = File.join(fname_dir, output_fname)
61
+ preserve_output_dir_structure(fname, output_fname, format)
62
+ end
63
+
64
+ # Compile single format for a file and update outputs hash
65
+ def file_compile_format(fname, ident, format, outputs, new_output_fname)
66
+ ext = @compile.processor.output_formats[format]
67
+ output_fname = output_filename_with_extension(fname, format)
68
+ output_fname = handle_new_output_filename(output_fname,
69
+ new_output_fname)
70
+ if !new_output_fname && (custom = @files.preserve_directory_structure?(ident))
71
+ output_fname = apply_custom_filename_pattern(ident, custom,
72
+ output_fname, format)
73
+ elsif !new_output_fname && File.dirname(fname) != "."
74
+ output_fname = apply_directory_preservation(fname, output_fname,
75
+ format)
76
+ end
77
+ should_skip = /html$/.match?(ext) && @files.get(ident, :sectionsplit)
78
+ should_skip or outputs[format] = File.join(@outdir, output_fname)
79
+ end
80
+
81
+ # Determine if file should be moved to subdirectory
82
+ def should_move_to_subdirectory?(ext, output_basename, explicit_custom)
83
+ if explicit_custom
84
+ # For explicit output-filename: move html, doc, pdf, presentation.xml
85
+ ext.end_with?("html") || ext == "doc" || ext == "pdf" ||
86
+ output_basename.end_with?(".presentation.xml")
87
+ else
88
+ # Default: only HTML and presentation files
89
+ ext.end_with?("html") ||
90
+ output_basename.end_with?(".html", ".presentation.xml")
91
+ end
92
+ end
93
+
94
+ # Move file from root to subdirectory
95
+ def move_file_to_subdirectory(fname_dir, output_basename)
96
+ output_with_dir = File.join(fname_dir, output_basename)
97
+ output_dest = File.join(@outdir, output_with_dir)
98
+ output_src = File.join(@outdir, output_basename)
99
+ return nil unless File.exist?(output_src) && output_src != output_dest
100
+
101
+ FileUtils.mkdir_p(File.dirname(output_dest))
102
+ FileUtils.mv(output_src, output_dest)
103
+ output_with_dir
104
+ end
105
+
106
+ # Handle case where destination already exists
107
+ def handle_existing_destination(output_with_dir, output_src)
108
+ output_dest = File.join(@outdir, output_with_dir)
109
+ return nil unless File.exist?(output_dest)
110
+ return output_with_dir unless File.exist?(output_src)
111
+
112
+ FileUtils.rm_f(output_src)
113
+ err_src = output_src.sub(/\.html$/, ".err.html")
114
+ FileUtils.rm_f(err_src) if File.exist?(err_src)
115
+ output_with_dir
116
+ end
117
+
118
+ # Generate custom basename with extension
119
+ def custom_basename_with_extension(fname, output_basename)
120
+ custom_basename = File.basename(fname, ".*")
121
+ ext = File.extname(output_basename)
122
+ "#{custom_basename}#{ext}"
123
+ end
124
+
125
+ # Preserve directory structure from input filename in output
126
+ def preserve_output_dir_structure(fname, output_fname, format = nil,
127
+ explicit_custom: false)
128
+ fname_dir = File.dirname(fname)
129
+ return output_fname if fname_dir == "."
130
+
131
+ output_basename = File.basename(output_fname)
132
+ ext = format ? @compile.processor.output_formats[format].to_s : ""
133
+ should_move = should_move_to_subdirectory?(ext, output_basename,
134
+ explicit_custom)
135
+ if should_move
136
+ result = move_file_to_subdirectory(fname_dir, output_basename)
137
+ return result if result
138
+
139
+ handle_existing_destination(File.join(fname_dir, output_basename),
140
+ File.join(@outdir,
141
+ output_basename)) || output_fname
142
+ elsif explicit_custom
143
+ custom_basename_with_extension(fname, output_basename)
144
+ else
145
+ output_basename
146
+ end
147
+ end
148
+
149
+ def copy_file_to_dest(identifier)
150
+ out = Pathname.new(@files.get(identifier, :out_path)).cleanpath
151
+ out.absolute? and
152
+ out = out.relative_path_from(File.expand_path(FileUtils.pwd))
153
+ dest = File.join(@outdir,
154
+ @disambig.source2dest_filename(out.to_s,
155
+ preserve_dirs: true))
156
+ FileUtils.mkdir_p(File.dirname(dest))
157
+ source = @files.get(identifier, :ref)
158
+ source != dest and FileUtils.cp_r source, dest, remove_destination: true
159
+ end
160
+ end
161
+ end
162
+ end
@@ -22,7 +22,8 @@ module Metanorma
22
22
  @ncnames = {}
23
23
  @nested or update_indirect_refs_to_docs(xml, docid, internal_refs, sso)
24
24
  @files.add_document_suffix(docid, xml)
25
- @nested or update_sectionsplit_refs_to_docs(xml, internal_refs, sso)
25
+ @nested or update_sectionsplit_refs_to_docs(xml, docid, internal_refs,
26
+ sso)
26
27
  update_direct_refs_to_docs(xml, docid, sso)
27
28
  ::Metanorma::Collection::Util::hide_refs(xml)
28
29
  sso and eref2link(xml, sso)
@@ -38,7 +39,8 @@ module Metanorma
38
39
  [docxml, sso]
39
40
  end
40
41
 
41
- def update_sectionsplit_refs_to_docs(docxml, internal_refs, presxml)
42
+ def update_sectionsplit_refs_to_docs(docxml, docid, internal_refs,
43
+ presxml)
42
44
  Util::gather_citeases(docxml, presxml).each do |k, v|
43
45
  (@files.get(k) && @files.get(k, :sectionsplit)) or next
44
46
  opts = { key: @files.get(k, :indirect_key),
@@ -47,7 +49,7 @@ module Metanorma
47
49
  refs = v.each_with_object({}) do |eref, m|
48
50
  update_sectionsplit_eref_to_doc(eref, internal_refs, m, opts)
49
51
  end
50
- add_hidden_bibliography(docxml, refs)
52
+ add_hidden_bibliography(docxml, refs, docid)
51
53
  end
52
54
  end
53
55
 
@@ -65,7 +67,7 @@ module Metanorma
65
67
 
66
68
  BIBITEM_NOT_REPO_XPATH = <<~XPATH.strip
67
69
  //bibitem[not(ancestor::bibitem)][not(ancestor::bibdata)][not(./docidentifier[@type = 'repository'])]
68
- XPATH
70
+ XPATH
69
71
 
70
72
  def supply_repo_ids(doc)
71
73
  doc.xpath(ns(BIBITEM_NOT_REPO_XPATH)).each do |b|
@@ -106,7 +108,8 @@ module Metanorma
106
108
  erefs.each do |k, v|
107
109
  v.each do |e|
108
110
  if loc = e.at(".//#{ANCHOR_XPATH}") then anchors[k] << loc
109
- else no_anchor[k] << e end
111
+ else no_anchor[k] << e
112
+ end
110
113
  end
111
114
  end
112
115
  [erefs, no_anchor, anchors, Util::gather_bibitemids(docxml, presxml)]
@@ -229,7 +232,7 @@ module Metanorma
229
232
  type = "clause" if type == "annex"
230
233
  ref = ins.at(ns("./locality/referenceFrom"))&.text
231
234
  a = @files.get(docid, :anchors).dig(type, ref) or return
232
- ins << "<locality type='anchor'><referenceFrom>#{a.sub(/^_/, '')}" \
235
+ ins << "<locality type='anchor'><referenceFrom>#{a}" \
233
236
  "</referenceFrom></locality>"
234
237
  end
235
238
  end
@@ -3,6 +3,7 @@
3
3
  require "isodoc"
4
4
  require "metanorma-utils"
5
5
  require_relative "fileparse"
6
+ require_relative "filelocation"
6
7
 
7
8
  module Metanorma
8
9
  class Collection
@@ -10,18 +11,28 @@ module Metanorma
10
11
  # compile and output individual file in collection
11
12
  # warn "metanorma compile -x html #{f.path}"
12
13
  def file_compile(file, filename, identifier)
13
- @files.get(identifier, :sectionsplit) and return
14
- opts = {
15
- format: :asciidoc,
16
- extension_keys: @files.get(identifier, :format),
17
- output_dir: @outdir,
18
- type: @flavor,
19
- }.merge(compile_options_update(identifier))
14
+ sectionsplit_val = @files.get(identifier, :sectionsplit)
15
+ sectionsplit_val and return
16
+ opts = compile_options_base(identifier)
17
+ .merge(compile_options_update(identifier))
18
+
20
19
  @compile.compile file, opts
21
20
  @files.set(identifier, :outputs, {})
22
21
  file_compile_formats(filename, identifier, opts)
23
22
  end
24
23
 
24
+ def compile_options_base(identifier)
25
+ e = @files.get(identifier, :extract_opts)
26
+ {
27
+ format: :asciidoc,
28
+ extension_keys: @files.get(identifier, :format),
29
+ fonts: e&.dig(:fonts),
30
+ output_dir: @outdir,
31
+ pdffile: @files.get(identifier, :pdffile),
32
+ type: Util::taste2flavor(@flavor),
33
+ }
34
+ end
35
+
25
36
  def compile_options_update(identifier)
26
37
  ret = @compile_options.dup
27
38
  @directives.detect { |d| d.key == "presentation-xml" } ||
@@ -43,33 +54,6 @@ module Metanorma
43
54
  # ret
44
55
  # end
45
56
 
46
- def file_compile_formats(filename, identifier, opts)
47
- f = @files.get(identifier, :outputs)
48
- format = opts[:extension_keys]
49
- concatenate_presentation?({ format: format }) and format << :presentation
50
- format.each do |e|
51
- file_compile_format(filename, identifier, e, f)
52
- end
53
- @files.set(identifier, :outputs, f)
54
- end
55
-
56
- def file_compile_format(filename, identifier, format, output_formats)
57
- ext = @compile.processor.output_formats[format]
58
- fn = File.basename(filename).sub(/(?<=\.)[^.]+$/, ext.to_s)
59
- (/html$/.match?(ext) && @files.get(identifier, :sectionsplit)) or
60
- output_formats[format] = File.join(@outdir, fn)
61
- end
62
-
63
- def copy_file_to_dest(identifier)
64
- out = Pathname.new(@files.get(identifier, :out_path)).cleanpath
65
- out.absolute? and
66
- out = out.relative_path_from(File.expand_path(FileUtils.pwd))
67
- dest = File.join(@outdir, @disambig.source2dest_filename(out.to_s))
68
- FileUtils.mkdir_p(File.dirname(dest))
69
- source = @files.get(identifier, :ref)
70
- source != dest and FileUtils.cp_r source, dest, remove_destination: true
71
- end
72
-
73
57
  # process each file in the collection
74
58
  # files are held in memory, and altered as postprocessing
75
59
  def files # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
@@ -85,7 +69,11 @@ module Metanorma
85
69
  file, fname = @files.targetfile_id(ident, read: true)
86
70
  warn "\n\n\n\n\nProcess #{fname}: #{DateTime.now.strftime('%H:%M:%S')}"
87
71
  collection_xml = update_xrefs(file, ident, internal_refs)
88
- collection_filename = File.basename(fname, File.extname(fname))
72
+ # Strip .xml or .html extension, but NOT section numbers like .0
73
+ fname_base = File.basename(fname)
74
+ collection_filename = fname_base
75
+ /\.(xml|html)$/.match?(fname_base) and
76
+ collection_filename = fname_base.sub(/\.(xml|html)$/, "")
89
77
  collection_xml_path = File.join(Dir.tmpdir,
90
78
  "#{collection_filename}.xml")
91
79
  File.write collection_xml_path, collection_xml, encoding: "UTF-8"
@@ -168,23 +156,49 @@ module Metanorma
168
156
  def locate_internal_refs1_prep(file)
169
157
  xml = Nokogiri::XML(file, &:huge)
170
158
  r = xml.root["document_suffix"]
171
- xml.xpath("//*[@id]").each_with_object({}) do |i, x|
172
- /^semantic_/.match?(i.name) and next
159
+ ret = xml.xpath("//*[@id]").each_with_object({}) do |i, x|
173
160
  x[i["id"]] = i
174
161
  r and x[i["id"].sub(/_#{r}$/, "")] = i
175
162
  end
163
+ xml.xpath("//*[@anchor]").each do |i|
164
+ ret[i["anchor"]] = i
165
+ r and ret[i["anchor"].sub(/_#{r}$/, "")] = i
166
+ end
167
+ ret
176
168
  end
177
169
 
178
170
  def update_bibitem(bib, identifier)
179
- docid = get_bibitem_docid(bib, identifier) or return
180
- newbib = dup_bibitem(docid, bib)
181
- url = @files.url(docid, relative: true,
182
- doc: !@files.get(docid, :attachment))
183
- dest = newbib.at("./docidentifier") || newbib.at(ns("./docidentifier"))
171
+ newbib, url = update_bibitem_prep(bib, identifier)
172
+ newbib or return
173
+ dest = begin
174
+ newbib.at("./docidentifier") || newbib.at(ns("./docidentifier"))
175
+ rescue StandardError
176
+ nil
177
+ end
184
178
  dest or dest = newbib.elements[-1]
185
179
  dest.previous = "<uri type='citation'>#{url}</uri>"
186
180
  bib.replace(newbib)
187
181
  end
182
+
183
+ def update_bibitem_prep(bib, identifier)
184
+ docid = get_bibitem_docid(bib, identifier) or return [nil, nil]
185
+ newbib = dup_bibitem(docid, bib)
186
+ url = @files.url(docid, relative: true,
187
+ doc: !@files.get(docid, :attachment))
188
+ # Use :outputs[:html] if available (after compilation),
189
+ # otherwise convert :out_path to HTML (before compilation)
190
+ current_html = @files.get(identifier, :outputs)&.dig(:html)
191
+ if !current_html && (out_path = @files.get(identifier, :out_path))
192
+ # Convert .xml to .html, following same logic as ref_file_xml2html
193
+ current_html = if out_path.end_with?(".xml")
194
+ out_path.sub(/\.xml$/, ".html")
195
+ else
196
+ "#{out_path}.html"
197
+ end
198
+ end
199
+ url = make_relative_path(current_html, url) if current_html
200
+ [newbib, url]
201
+ end
188
202
  end
189
203
  end
190
204
  end
@@ -39,9 +39,23 @@ module Metanorma
39
39
  @c.decode(@isodoc.docid_prefix(nil, ident))
40
40
  end
41
41
 
42
+ # Check if file has a recognized MIME type (other than XML)
43
+ # If so, don't append .html (e.g., .svg, .png, .jpg, etc.)
42
44
  def index_link(docref, ident)
43
45
  if docref.file
44
- @files.get(ident, :out_path).sub(/\.xml$/, ".html")
46
+ out_path = @files.get(ident, :out_path)
47
+ # Ensure the path ends with .html for documents, but not for recognized file types
48
+ if Util::mime_file_recognised?(out_path) && !out_path.end_with?(".xml")
49
+ # File has a recognized extension (like .svg, .png), keep it as is
50
+ out_path
51
+ elsif out_path.end_with?(".xml")
52
+ out_path.sub(/\.xml$/, ".html")
53
+ elsif out_path.end_with?(".html")
54
+ out_path
55
+ else
56
+ "#{out_path}.html"
57
+ end
58
+
45
59
  else "#{docref.id}.html"
46
60
  end
47
61
  end
@@ -1,11 +1,13 @@
1
1
  module Metanorma
2
2
  class Collection
3
3
  class Renderer
4
- def docconv
4
+ def docconv(added_options = {})
5
5
  @tempfile_cache ||= []
6
- flavor = @flavor.to_sym
6
+ flavor = Util::taste2flavor(@flavor).to_sym
7
+ opts = Util::taste2isodoc_attrs(@flavor, :doc)
7
8
  x = Asciidoctor.load nil, backend: flavor
8
- x.converter.doc_converter(DocOptionsNode.new(@directives, @dirname))
9
+ x.converter.doc_converter(DocOptionsNode.new(@directives, @dirname,
10
+ added_options.merge(opts)))
9
11
  end
10
12
 
11
13
  def concat_extract_files(filename)
@@ -112,7 +114,7 @@ module Metanorma
112
114
  end
113
115
 
114
116
  class DocOptionsNode
115
- def initialize(directives, dir)
117
+ def initialize(directives, dir, options)
116
118
  @dir = dir
117
119
  @wordcoverpage =
118
120
  Util::hash_key_detect(directives, "document-word-coverpage",
@@ -120,12 +122,14 @@ module Metanorma
120
122
  @wordintropage =
121
123
  Util::hash_key_detect(directives, "document-word-intropage",
122
124
  @wordintropage)
125
+ @options = options
123
126
  end
124
127
 
125
128
  def attr(key)
126
129
  case key
127
130
  when "wordcoverpage" then Util::rel_path_resolve(@dir, @wordcoverpage)
128
131
  when "wordintropage" then Util::rel_path_resolve(@dir, @wordintropage)
132
+ else @options[key.to_sym]
129
133
  end
130
134
  end
131
135
  end
@@ -1,5 +1,6 @@
1
1
  require "isodoc"
2
2
  require "htmlentities"
3
+ require "mime/types"
3
4
  require_relative "fileprocess"
4
5
  require_relative "../../util/fontist_helper"
5
6
  require_relative "../../util/util"
@@ -14,7 +15,7 @@ require_relative "../log"
14
15
  module Metanorma
15
16
  class Collection
16
17
  class Renderer
17
- FORMATS = %i[html xml doc pdf].freeze
18
+ FORMATS = %i[html xml doc pdf pdf-portfolio].freeze
18
19
 
19
20
  attr_accessor :isodoc, :isodoc_presxml, :nested
20
21
  attr_reader :xml, :compile, :compile_options, :documents, :outdir,
@@ -45,11 +46,12 @@ module Metanorma
45
46
  @compile.load_flavor(@flavor)
46
47
 
47
48
  # output processor for flavour
48
- @isodoc = Util::isodoc_create(@flavor, @lang, @script, @xml)
49
- @isodoc_presxml = Util::isodoc_create(@flavor, @lang, @script, @xml,
49
+ @isodoc = Util::isodoc_create(Util::taste2flavor(@flavor), @lang,
50
+ @script, @xml)
51
+ @isodoc_presxml = Util::isodoc_create(Util::taste2flavor(@flavor),
52
+ @lang, @script, @xml,
50
53
  presxml: true)
51
54
  @outdir = dir_name_cleanse(options[:output_folder])
52
- @coverpage = options[:coverpage] || collection.coverpage
53
55
  @format = ::Metanorma::Util.sort_extensions_execution(options[:format])
54
56
  @compile_options = options[:compile] || {}
55
57
  @compile_options[:install_fonts] = true if options[:install_fonts]
@@ -71,6 +73,11 @@ module Metanorma
71
73
  # if true, then this is not the last time Renderer will be run
72
74
  # (e.g. this is sectionsplit)
73
75
 
76
+ @coverpage = options[:coverpage] || collection.coverpage
77
+ @coverpage_pdf_portflio = options[:coverpage_pdf_portfolio] ||
78
+ collection.coverpage_pdf_portfolio || Util::taste2coverpage_pdf_portfolio(@flavor)
79
+ collection.directives = directives_normalise(collection.directives)
80
+ @directives = collection.directives
74
81
  # list of files in the collection
75
82
  @files = Metanorma::Collection::FileLookup.new(folder, self)
76
83
  @files.add_section_split
@@ -78,6 +85,50 @@ module Metanorma
78
85
  create_non_existing_directory(@outdir)
79
86
  end
80
87
 
88
+ def directives_normalise(directives)
89
+ @coverpage_pdf_portflio and
90
+ directives = directives_normalise_coverpage_pdf_portfolio(directives)
91
+ directives_normalise_keystore_pdf_portfolio(directives)
92
+ end
93
+
94
+ # KILL
95
+ def directives_normalise_coverpage_pdf_portfolio(directives)
96
+ directives.reject! { |d| d.key == "coverpage-pdf-portfolio" }
97
+ absolute_coverpage_pdf_portflio = @coverpage_pdf_portflio &&
98
+ Pathname.new(@coverpage_pdf_portflio).absolute?
99
+ @coverpage_pdf_portflio =
100
+ Util::rel_path_resolve(@dirname, @coverpage_pdf_portflio)
101
+ absolute_coverpage_pdf_portflio or
102
+ @coverpage_pdf_portflio = Pathname.new(@coverpage_pdf_portflio)
103
+ .relative_path_from(Pathname.new(@outdir)).to_s
104
+ directives << ::Metanorma::Collection::Config::Directive
105
+ .new(key: "coverpage-pdf-portfolio", value: @coverpage_pdf_portflio)
106
+ directives
107
+ end
108
+
109
+ def directives_normalise_coverpage_pdf_portfolio(directives)
110
+ directives_resolve_filepath(directives, "coverpage-pdf-portfolio",
111
+ @coverpage_pdf_portflio)
112
+ end
113
+
114
+ def directives_normalise_keystore_pdf_portfolio(directives)
115
+ f = directives.find { |d| d.key == "keystore-pdf-portfolio" }
116
+ f.nil? || f.value.nil? and return directives
117
+ directives_resolve_filepath(directives, "keystore-pdf-portfolio",
118
+ f.value)
119
+ end
120
+
121
+ def directives_resolve_filepath(directives, name, val)
122
+ abs = Pathname.new(val).absolute?
123
+ directives.reject! { |d| d.key == name }
124
+ val = Util::rel_path_resolve(@dirname, val)
125
+ abs or
126
+ val = Pathname.new(val).relative_path_from(Pathname.new(@outdir)).to_s
127
+ directives << ::Metanorma::Collection::Config::Directive
128
+ .new(key: name, value: val)
129
+ directives
130
+ end
131
+
81
132
  def flush_files
82
133
  warn "\n\n\n\n\nDone: #{DateTime.now.strftime('%H:%M:%S')}"
83
134
  warn "\nFiles to delete:\n"
@@ -148,14 +199,59 @@ module Metanorma
148
199
  end
149
200
 
150
201
  def concatenate_outputs(options)
151
- pres = File.join(@outdir, "collection.presentation.xml")
152
- options[:format].include?(:pdf) and pdfconv.convert(pres)
202
+ pres, compile_opts = concatenate_outputs_prep(options)
203
+ warn pp compile_opts
204
+ options[:format].include?(:pdf) and pdfconv(compile_opts).convert(pres)
205
+ options[:format].include?(:"pdf-portfolio") and
206
+ pdfconv(pdf_portfolio_mn2pdf_options)
207
+ .convert(pres, nil, nil,
208
+ File.join(@outdir, "collection.portfolio.pdf"))
153
209
  options[:format].include?(:doc) and docconv_convert(pres)
210
+ bilingual_output(options, pres)
211
+ end
212
+
213
+ def concatenate_outputs_prep(_options)
214
+ pres = File.join(@outdir, "collection.presentation.xml")
215
+ fonts = extract_added_fonts(pres)
216
+ if fonts
217
+ # Install fonts before trying to locate them
218
+ font_options = @compile_options.merge({ fonts: fonts })
219
+ ::Metanorma::Util::FontistHelper.install_fonts(@compile.processor,
220
+ font_options)
221
+
222
+ mn2pdf = {
223
+ font_manifest: ::Metanorma::Util::FontistHelper
224
+ .location_manifest(@compile.processor, { fonts: fonts }),
225
+ }
226
+ end
227
+ [pres, { fonts: fonts, mn2pdf: mn2pdf }.compact]
228
+ end
229
+
230
+ def extract_added_fonts(pres)
231
+ File.exist?(pres) or return
232
+ xml = Nokogiri::XML(File.read(pres, encoding: "UTF-8"), &:huge)
233
+ x = xml.xpath("//*[local-name() = 'presentation-metadata']/" \
234
+ "*[local-name() = 'fonts']")
235
+ x.empty? and return
236
+ x.map(&:text).join(";")
237
+ end
238
+
239
+ def pdf_portfolio_mn2pdf_options
240
+ f1 = @directives.find { |d| d.key == "keystore-pdf-portfolio" }&.value
241
+ f2 = @directives.find do |d|
242
+ d.key == "keystore-password-pdf-portfolio"
243
+ end&.value
244
+ { "pdf-portfolio": "true", pdfkeystore: f1,
245
+ pdfkeystorepassword: f2 }.compact
246
+ end
247
+
248
+ def bilingual_output(options, pres)
154
249
  @directives.detect { |d| d.key == "bilingual" } &&
155
250
  options[:format].include?(:html) and
156
251
  Metanorma::Collection::Multilingual.new(
157
- { flavor: flavor.to_sym,
158
- converter_options: PdfOptionsNode.new(flavor, @compile_options),
252
+ { flavor: Util::taste2flavor(flavor).to_sym,
253
+ converter_options: PdfOptionsNode.new(Util::taste2flavor(flavor),
254
+ @compile_options),
159
255
  outdir: @outdir },
160
256
  ).to_html(pres)
161
257
  end
@@ -183,10 +279,8 @@ module Metanorma
183
279
  # collection manifest
184
280
  def coverpage
185
281
  @coverpage or return
186
-
187
282
  @coverpage_path = Util::rel_path_resolve(@dirname, @coverpage)
188
283
  warn "\n\n\n\n\nCoverpage: #{DateTime.now.strftime('%H:%M:%S')}"
189
-
190
284
  File.open(File.join(@outdir, "index.html"), "w:UTF-8") do |f|
191
285
  f.write @isodoc.populate_template(File.read(@coverpage_path))
192
286
  end