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.
- checksums.yaml +4 -4
- data/Gemfile +14 -0
- data/lib/metanorma/collection/collection.rb +46 -104
- data/lib/metanorma/collection/config/config.rb +5 -0
- data/lib/metanorma/collection/config/converters.rb +1 -0
- data/lib/metanorma/collection/config/manifest.rb +23 -0
- data/lib/metanorma/collection/document/document.rb +35 -13
- data/lib/metanorma/collection/filelookup/base.rb +43 -0
- data/lib/metanorma/collection/filelookup/filelookup.rb +168 -69
- data/lib/metanorma/collection/filelookup/filelookup_sectionsplit.rb +49 -10
- data/lib/metanorma/collection/filelookup/utils.rb +93 -0
- data/lib/metanorma/collection/helpers.rb +82 -0
- data/lib/metanorma/collection/manifest/manifest.rb +14 -3
- data/lib/metanorma/collection/multilingual/multilingual.rb +1 -1
- data/lib/metanorma/collection/renderer/filelocation.rb +162 -0
- data/lib/metanorma/collection/renderer/fileparse.rb +9 -6
- data/lib/metanorma/collection/renderer/fileprocess.rb +56 -42
- data/lib/metanorma/collection/renderer/navigation.rb +15 -1
- data/lib/metanorma/collection/renderer/render_word.rb +8 -4
- data/lib/metanorma/collection/renderer/renderer.rb +104 -10
- data/lib/metanorma/collection/renderer/svg.rb +54 -7
- data/lib/metanorma/collection/renderer/utils.rb +58 -22
- data/lib/metanorma/collection/sectionsplit/collection.rb +14 -5
- data/lib/metanorma/collection/sectionsplit/sectionsplit.rb +20 -7
- data/lib/metanorma/collection/util/disambig_files.rb +4 -5
- data/lib/metanorma/collection/util/util.rb +106 -6
- data/lib/metanorma/collection/xrefprocess/xrefprocess.rb +2 -2
- data/lib/metanorma/compile/compile.rb +2 -2
- data/lib/metanorma/compile/compile_options.rb +23 -11
- data/lib/metanorma/compile/flavor.rb +11 -4
- data/lib/metanorma/compile/render.rb +1 -0
- data/lib/metanorma/input/asciidoc.rb +1 -1
- data/lib/metanorma/util/fontist_helper.rb +5 -6
- data/lib/metanorma/version.rb +1 -1
- data/metanorma.gemspec +4 -14
- 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,
|
|
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,
|
|
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
|
-
|
|
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
|
|
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
|
|
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)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
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
|
-
|
|
180
|
-
newbib
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
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)
|
|
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,
|
|
49
|
-
|
|
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 =
|
|
152
|
-
|
|
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
|
|
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
|