metanorma 1.7.6 → 2.0.0
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 +5 -1
- data/lib/metanorma/array_monkeypatch.rb +9 -0
- data/lib/metanorma/asciidoctor_extensions/glob_include_processor.rb +13 -11
- data/lib/metanorma/collection/collection.rb +225 -0
- data/lib/metanorma/collection/config/bibdata.rb +12 -0
- data/lib/metanorma/collection/config/compile_options.rb +13 -0
- data/lib/metanorma/collection/config/config.rb +163 -0
- data/lib/metanorma/collection/config/converters.rb +30 -0
- data/lib/metanorma/collection/config/directive.rb +10 -0
- data/lib/metanorma/collection/config/manifest.rb +88 -0
- data/lib/metanorma/collection/document/document.rb +133 -0
- data/lib/metanorma/collection/filelookup/filelookup.rb +250 -0
- data/lib/metanorma/collection/filelookup/filelookup_sectionsplit.rb +87 -0
- data/lib/metanorma/collection/manifest/manifest.rb +237 -0
- data/lib/metanorma/collection/renderer/fileparse.rb +247 -0
- data/lib/metanorma/collection/renderer/fileprocess.rb +173 -0
- data/lib/metanorma/collection/renderer/navigation.rb +133 -0
- data/lib/metanorma/collection/renderer/render_word.rb +133 -0
- data/lib/metanorma/collection/renderer/renderer.rb +157 -0
- data/lib/metanorma/collection/renderer/utils.rb +183 -0
- data/lib/metanorma/collection/sectionsplit/sectionsplit.rb +218 -0
- data/lib/metanorma/collection/util/disambig_files.rb +37 -0
- data/lib/metanorma/collection/util/util.rb +72 -0
- data/lib/metanorma/collection/xrefprocess/xrefprocess.rb +222 -0
- data/lib/metanorma/{compile.rb → compile/compile.rb} +17 -11
- data/lib/metanorma/{compile_options.rb → compile/compile_options.rb} +9 -5
- data/lib/metanorma/{compile_validate.rb → compile/compile_validate.rb} +1 -1
- data/lib/metanorma/{extract.rb → compile/extract.rb} +2 -2
- data/lib/metanorma/{config.rb → config/config.rb} +1 -1
- data/lib/metanorma/input/asciidoc.rb +3 -3
- data/lib/metanorma/input/base.rb +1 -5
- data/lib/metanorma/processor/processor.rb +54 -0
- data/lib/metanorma/processor.rb +1 -49
- data/lib/metanorma/{registry.rb → registry/registry.rb} +0 -1
- data/lib/metanorma/shale_monkeypatch.rb +15 -0
- data/lib/metanorma/util/fontist_helper.rb +130 -0
- data/lib/metanorma/util/util.rb +45 -0
- data/lib/metanorma/util/worker_pool.rb +39 -0
- data/lib/metanorma/version.rb +1 -1
- data/lib/metanorma.rb +13 -8
- data/metanorma.gemspec +2 -1
- metadata +51 -26
- data/Gemfile.devel +0 -2
- data/lib/metanorma/collection.rb +0 -243
- data/lib/metanorma/collection_fileparse.rb +0 -254
- data/lib/metanorma/collection_fileprocess.rb +0 -157
- data/lib/metanorma/collection_manifest.rb +0 -139
- data/lib/metanorma/collection_render_utils.rb +0 -169
- data/lib/metanorma/collection_render_word.rb +0 -131
- data/lib/metanorma/collection_renderer.rb +0 -230
- data/lib/metanorma/document.rb +0 -133
- data/lib/metanorma/files_lookup.rb +0 -208
- data/lib/metanorma/files_lookup_sectionsplit.rb +0 -84
- data/lib/metanorma/fontist_utils.rb +0 -122
- data/lib/metanorma/sectionsplit.rb +0 -216
- data/lib/metanorma/sectionsplit_links.rb +0 -189
- data/lib/metanorma/util.rb +0 -127
- data/lib/metanorma/worker_pool.rb +0 -29
@@ -1,208 +0,0 @@
|
|
1
|
-
require "isodoc"
|
2
|
-
require "htmlentities"
|
3
|
-
require "metanorma-utils"
|
4
|
-
require_relative "files_lookup_sectionsplit"
|
5
|
-
|
6
|
-
module Metanorma
|
7
|
-
# XML collection renderer
|
8
|
-
class FileLookup
|
9
|
-
attr_accessor :files_to_delete, :parent
|
10
|
-
|
11
|
-
# hash for each document in collection of document identifier to:
|
12
|
-
# document reference (fileref or id), type of document reference,
|
13
|
-
# and bibdata entry for that file
|
14
|
-
# @param path [String] path to collection
|
15
|
-
def initialize(path, parent)
|
16
|
-
@c = HTMLEntities.new
|
17
|
-
@files = {}
|
18
|
-
@parent = parent
|
19
|
-
@xml = parent.xml
|
20
|
-
@isodoc = parent.isodoc
|
21
|
-
@path = path
|
22
|
-
@compile = parent.compile
|
23
|
-
@documents = parent.documents
|
24
|
-
@files_to_delete = []
|
25
|
-
read_files
|
26
|
-
end
|
27
|
-
|
28
|
-
def read_files
|
29
|
-
@disambig = Util::DisambigFiles.new
|
30
|
-
@xml.xpath(ns("//docref")).each { |d| read_file(d) }
|
31
|
-
end
|
32
|
-
|
33
|
-
def read_file(docref)
|
34
|
-
ident = docref.at(ns("./identifier"))
|
35
|
-
i = key(@isodoc.docid_prefix(ident["type"], ident.children.to_xml))
|
36
|
-
entry = file_entry(docref, ident.children.to_xml)
|
37
|
-
bibdata_process(entry, i)
|
38
|
-
bibitem_process(entry)
|
39
|
-
@files[i] = entry
|
40
|
-
end
|
41
|
-
|
42
|
-
def bibdata_process(entry, ident)
|
43
|
-
if entry[:attachment]
|
44
|
-
entry[:bibdata] = Metanorma::Document.attachment_bibitem(ident).root
|
45
|
-
else
|
46
|
-
file, _filename = targetfile(entry, read: true)
|
47
|
-
xml = Nokogiri::XML(file, &:huge)
|
48
|
-
add_document_suffix(ident, xml)
|
49
|
-
entry.merge!(anchors: read_anchors(xml), ids: read_ids(xml),
|
50
|
-
bibdata: xml.at(ns("//bibdata")),
|
51
|
-
document_suffix: xml.root["document_suffix"])
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def bibitem_process(entry)
|
56
|
-
entry[:bibitem] = entry[:bibdata].dup
|
57
|
-
entry[:bibitem].name = "bibitem"
|
58
|
-
entry[:bibitem]["hidden"] = "true"
|
59
|
-
entry[:bibitem].at("./*[local-name() = 'ext']")&.remove
|
60
|
-
end
|
61
|
-
|
62
|
-
# rel_path is the source file address, determined relative to the YAML.
|
63
|
-
# out_path is the destination file address, with any references outside
|
64
|
-
# the working directory (../../...) truncated
|
65
|
-
# identifier is the id with only spaces, no nbsp
|
66
|
-
def file_entry(ref, identifier)
|
67
|
-
out = ref["attachment"] ? ref["fileref"] : File.basename(ref["fileref"])
|
68
|
-
out1 = @disambig.source2dest_filename(out)
|
69
|
-
ret = if ref["fileref"]
|
70
|
-
{ type: "fileref", ref: @documents[Util::key identifier].file,
|
71
|
-
rel_path: ref["fileref"],
|
72
|
-
out_path: out1 } # @disambig.source2dest_filename(out) }
|
73
|
-
else { type: "id", ref: ref["id"] }
|
74
|
-
end
|
75
|
-
file_entry_copy(ref, ret)
|
76
|
-
ret.compact
|
77
|
-
end
|
78
|
-
|
79
|
-
def file_entry_copy(ref, ret)
|
80
|
-
%w(attachment sectionsplit index presentation-xml
|
81
|
-
bare-after-first).each do |s|
|
82
|
-
ret[s.gsub("-", "").to_sym] = ref[s] if ref[s]
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
def add_document_suffix(identifier, doc)
|
87
|
-
document_suffix = Metanorma::Utils::to_ncname(identifier)
|
88
|
-
Metanorma::Utils::anchor_attributes.each do |(tag_name, attribute_name)|
|
89
|
-
Util::add_suffix_to_attributes(doc, document_suffix, tag_name,
|
90
|
-
attribute_name, @isodoc)
|
91
|
-
end
|
92
|
-
url_in_css_styles(doc, document_suffix)
|
93
|
-
doc.root["document_suffix"] ||= ""
|
94
|
-
doc.root["document_suffix"] += document_suffix
|
95
|
-
end
|
96
|
-
|
97
|
-
# update relative URLs, url(#...), in CSS in @style attrs (including SVG)
|
98
|
-
def url_in_css_styles(doc, document_suffix)
|
99
|
-
doc.xpath("//*[@style]").each do |s|
|
100
|
-
s["style"] = s["style"]
|
101
|
-
.gsub(%r{url\(#([^)]+)\)}, "url(#\\1_#{document_suffix})")
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
# return file contents + output filename for each file in the collection,
|
106
|
-
# given a docref entry
|
107
|
-
# @param data [Hash] docref entry
|
108
|
-
# @param read [Boolean] read the file in and return it
|
109
|
-
# @param doc [Boolean] I am a Metanorma document,
|
110
|
-
# so my URL should end with html or pdf or whatever
|
111
|
-
# @param relative [Boolean] Return output path,
|
112
|
-
# formed relative to YAML file, not input path, relative to calling function
|
113
|
-
# @return [Array<String, nil>]
|
114
|
-
def targetfile(data, options)
|
115
|
-
options = { read: false, doc: true, relative: false }.merge(options)
|
116
|
-
path = options[:relative] ? data[:rel_path] : data[:ref]
|
117
|
-
if data[:type] == "fileref"
|
118
|
-
ref_file path, data[:out_path], options[:read], options[:doc]
|
119
|
-
else
|
120
|
-
xml_file data[:id], options[:read]
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
def targetfile_id(ident, options)
|
125
|
-
targetfile(get(ident), options)
|
126
|
-
end
|
127
|
-
|
128
|
-
def ref_file(ref, out, read, doc)
|
129
|
-
file = File.read(ref, encoding: "utf-8") if read
|
130
|
-
filename = out.dup
|
131
|
-
filename.sub!(/\.xml$/, ".html") if doc
|
132
|
-
[file, filename]
|
133
|
-
end
|
134
|
-
|
135
|
-
def xml_file(id, read)
|
136
|
-
file = @xml.at(ns("//doc-container[@id = '#{id}']")).to_xml if read
|
137
|
-
filename = "#{id}.html"
|
138
|
-
[file, filename]
|
139
|
-
end
|
140
|
-
|
141
|
-
# map locality type and label (e.g. "clause" "1") to id = anchor for
|
142
|
-
# a document
|
143
|
-
# Note: will only key clauses, which have unambiguous reference label in
|
144
|
-
# locality. Notes, examples etc with containers are just plunked against
|
145
|
-
# UUIDs, so that their IDs can at least be registered to be tracked
|
146
|
-
# as existing.
|
147
|
-
def read_anchors(xml)
|
148
|
-
xrefs = @isodoc.xref_init(@lang, @script, @isodoc, @isodoc.i18n,
|
149
|
-
{ locale: @locale })
|
150
|
-
xrefs.parse xml
|
151
|
-
xrefs.get.each_with_object({}) do |(k, v), ret|
|
152
|
-
read_anchors1(k, v, ret)
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
def read_anchors1(key, val, ret)
|
157
|
-
val[:type] ||= "clause"
|
158
|
-
ret[val[:type]] ||= {}
|
159
|
-
index = if val[:container] || val[:label].nil? || val[:label].empty?
|
160
|
-
UUIDTools::UUID.random_create.to_s
|
161
|
-
else val[:label]
|
162
|
-
end
|
163
|
-
ret[val[:type]][index] = key
|
164
|
-
ret[val[:type]][val[:value]] = key if val[:value]
|
165
|
-
end
|
166
|
-
|
167
|
-
# Also parse all ids in doc (including ones which won't be xref targets)
|
168
|
-
def read_ids(xml)
|
169
|
-
ret = {}
|
170
|
-
xml.traverse do |x|
|
171
|
-
x.text? and next
|
172
|
-
/^semantic__/.match?(x.name) and next
|
173
|
-
x["id"] and ret[x["id"]] = true
|
174
|
-
end
|
175
|
-
ret
|
176
|
-
end
|
177
|
-
|
178
|
-
def key(ident)
|
179
|
-
@c.decode(ident).gsub(/(\p{Zs})+/, " ").sub(/^metanorma-collection /, "")
|
180
|
-
end
|
181
|
-
|
182
|
-
def keys
|
183
|
-
@files.keys
|
184
|
-
end
|
185
|
-
|
186
|
-
def get(ident, attr = nil)
|
187
|
-
if attr then @files[key(ident)][attr]
|
188
|
-
else @files[key(ident)]
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
def set(ident, attr, value)
|
193
|
-
@files[key(ident)][attr] = value
|
194
|
-
end
|
195
|
-
|
196
|
-
def each
|
197
|
-
@files.each
|
198
|
-
end
|
199
|
-
|
200
|
-
def each_with_index
|
201
|
-
@files.each_with_index
|
202
|
-
end
|
203
|
-
|
204
|
-
def ns(xpath)
|
205
|
-
@isodoc.ns(xpath)
|
206
|
-
end
|
207
|
-
end
|
208
|
-
end
|
@@ -1,84 +0,0 @@
|
|
1
|
-
module Metanorma
|
2
|
-
# XML collection renderer
|
3
|
-
class FileLookup
|
4
|
-
def add_section_split
|
5
|
-
ret = @files.keys.each_with_object({}) do |k, m|
|
6
|
-
if @files[k][:sectionsplit] == "true" && !@files[k]["attachment"]
|
7
|
-
process_section_split_instance(k, m)
|
8
|
-
cleanup_section_split_instance(k, m)
|
9
|
-
end
|
10
|
-
m[k] = @files[k]
|
11
|
-
end
|
12
|
-
@files = ret
|
13
|
-
end
|
14
|
-
|
15
|
-
def process_section_split_instance(key, manifest)
|
16
|
-
s, sectionsplit_manifest = sectionsplit(@files[key][:ref],
|
17
|
-
@files[key][:out_path], key)
|
18
|
-
s.each_with_index do |f1, i|
|
19
|
-
add_section_split_instance(f1, manifest, key, i)
|
20
|
-
end
|
21
|
-
manifest["#{key}:index.html"] =
|
22
|
-
add_section_split_cover(sectionsplit_manifest, key)
|
23
|
-
end
|
24
|
-
|
25
|
-
def cleanup_section_split_instance(key, manifest)
|
26
|
-
@files_to_delete << manifest["#{key}:index.html"][:ref]
|
27
|
-
#@files[key].delete(:ids).delete(:anchors)
|
28
|
-
@files[key][:indirect_key] = @sectionsplit.key
|
29
|
-
end
|
30
|
-
|
31
|
-
def add_section_split_cover(manifest, ident)
|
32
|
-
cover = @sectionsplit
|
33
|
-
.section_split_cover(manifest, @parent.dir_name_cleanse(ident),
|
34
|
-
one_doc_collection?)
|
35
|
-
@files[ident][:out_path] = cover
|
36
|
-
{ attachment: true, index: false, out_path: cover,
|
37
|
-
ref: File.join(File.dirname(manifest.file), cover) }
|
38
|
-
end
|
39
|
-
|
40
|
-
def one_doc_collection?
|
41
|
-
return false
|
42
|
-
docs = 0
|
43
|
-
@files.each_value do |v|
|
44
|
-
v[:attachment] and next
|
45
|
-
v[:presentationxml] and next
|
46
|
-
docs += 1
|
47
|
-
end
|
48
|
-
docs > 1
|
49
|
-
end
|
50
|
-
|
51
|
-
def add_section_split_instance(file, manifest, key, idx)
|
52
|
-
presfile, newkey, xml =
|
53
|
-
add_section_split_instance_prep(file, key)
|
54
|
-
manifest[newkey] =
|
55
|
-
{ parentid: key, presentationxml: true, type: "fileref",
|
56
|
-
rel_path: file[:url], out_path: File.basename(file[:url]),
|
57
|
-
anchors: read_anchors(xml), ids: read_ids(xml),
|
58
|
-
sectionsplit_output: true,
|
59
|
-
bibdata: @files[key][:bibdata], ref: presfile }
|
60
|
-
@files_to_delete << file[:url]
|
61
|
-
manifest[newkey][:bare] = true unless idx.zero?
|
62
|
-
end
|
63
|
-
|
64
|
-
def add_section_split_instance_prep(file, key)
|
65
|
-
presfile = File.join(File.dirname(@files[key][:ref]),
|
66
|
-
File.basename(file[:url]))
|
67
|
-
newkey = key("#{key.strip} #{file[:title]}")
|
68
|
-
xml = Nokogiri::XML(File.read(presfile), &:huge)
|
69
|
-
[presfile, newkey, xml]
|
70
|
-
end
|
71
|
-
|
72
|
-
def sectionsplit(file, outfile, ident)
|
73
|
-
@sectionsplit = Sectionsplit
|
74
|
-
.new(input: file, base: outfile, dir: File.dirname(file),
|
75
|
-
output: outfile, compile_opts: @parent.compile_options,
|
76
|
-
fileslookup: self, ident: ident, isodoc: @isodoc)
|
77
|
-
coll = @sectionsplit.sectionsplit.sort_by { |f| f[:order] }
|
78
|
-
xml = Nokogiri::XML(File.read(file, encoding: "UTF-8"), &:huge)
|
79
|
-
[coll, @sectionsplit
|
80
|
-
.collection_manifest(File.basename(file), coll, xml, nil,
|
81
|
-
File.dirname(file))]
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
@@ -1,122 +0,0 @@
|
|
1
|
-
module Metanorma
|
2
|
-
class FontistUtils
|
3
|
-
class << self
|
4
|
-
private
|
5
|
-
|
6
|
-
def validate_options(options)
|
7
|
-
agree_to_terms = options[:agree_to_terms] || false
|
8
|
-
continue_without_fonts = options[:continue_without_fonts] || false
|
9
|
-
no_progress = options[:no_progress] || false
|
10
|
-
|
11
|
-
[agree_to_terms, continue_without_fonts, no_progress]
|
12
|
-
end
|
13
|
-
|
14
|
-
def validate_install_fonts(processor, options)
|
15
|
-
if options[:no_install_fonts]
|
16
|
-
Util.log("[fontist] Skip font installation because" \
|
17
|
-
" --no-install-fonts argument passed", :debug)
|
18
|
-
return false
|
19
|
-
elsif !has_custom_fonts?(processor, options, options)
|
20
|
-
Util.log("[fontist] Skip font installation because "\
|
21
|
-
"fonts_manifest is missing", :debug)
|
22
|
-
return false
|
23
|
-
end
|
24
|
-
true
|
25
|
-
end
|
26
|
-
|
27
|
-
def install_fonts_safe(manifest, agree, continue, no_progress)
|
28
|
-
fontist_install(manifest, agree, no_progress)
|
29
|
-
rescue Fontist::Errors::LicensingError
|
30
|
-
license_error_log(continue)
|
31
|
-
rescue Fontist::Errors::FontError => e
|
32
|
-
log_level = continue ? :warning : :fatal
|
33
|
-
Util.log("[fontist] '#{e.font}' font is not supported. " \
|
34
|
-
"Please report this issue at github.com/metanorma/metanorma" \
|
35
|
-
"/issues to report this issue.", log_level)
|
36
|
-
rescue Fontist::Errors::FormulaIndexNotFoundError
|
37
|
-
fintist_update_repo(manifest, agree, continue, no_progress)
|
38
|
-
end
|
39
|
-
|
40
|
-
def fontist_install(manifest, agree, no_progress)
|
41
|
-
if agree
|
42
|
-
no_license_log
|
43
|
-
else
|
44
|
-
Fontist.log_level = :info
|
45
|
-
end
|
46
|
-
|
47
|
-
Fontist::Manifest::Install.from_hash(
|
48
|
-
manifest,
|
49
|
-
confirmation: agree ? "yes" : "no",
|
50
|
-
no_progress: no_progress,
|
51
|
-
)
|
52
|
-
end
|
53
|
-
|
54
|
-
def license_error_log(continue)
|
55
|
-
if continue
|
56
|
-
Util.log(
|
57
|
-
"[fontist] Processing will continue without fonts installed",
|
58
|
-
:debug,
|
59
|
-
)
|
60
|
-
else
|
61
|
-
Util.log("[fontist] Aborting without proper fonts installed," \
|
62
|
-
" make sure that you have set option --agree-to-terms",
|
63
|
-
:fatal)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def no_license_log
|
68
|
-
Util.log(
|
69
|
-
"[fontist] Font licenses are not shown with --agree-to-terms option.",
|
70
|
-
:info,
|
71
|
-
)
|
72
|
-
end
|
73
|
-
|
74
|
-
def fintist_update_repo(manifest, agree, continue, no_progress)
|
75
|
-
if @@updated_formulas_repo
|
76
|
-
Util.log(
|
77
|
-
"[fontist] Bug: formula index not found after 'fontist update'",
|
78
|
-
:fatal,
|
79
|
-
)
|
80
|
-
end
|
81
|
-
Util.log("[fontist] Missing formula index. Fetching it...", :debug)
|
82
|
-
Fontist::Formula.update_formulas_repo
|
83
|
-
@@updated_formulas_repo = true
|
84
|
-
install_fonts_safe(manifest, agree, continue, no_progress)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def self.install_fonts(processor, options)
|
89
|
-
return unless validate_install_fonts(processor, options)
|
90
|
-
|
91
|
-
@@updated_formulas_repo = false
|
92
|
-
manifest = processor.fonts_manifest.dup
|
93
|
-
append_source_fonts(manifest, options)
|
94
|
-
agree_to_terms, can_without_fonts, no_progress = validate_options(options)
|
95
|
-
|
96
|
-
install_fonts_safe(
|
97
|
-
manifest,
|
98
|
-
agree_to_terms,
|
99
|
-
can_without_fonts,
|
100
|
-
no_progress,
|
101
|
-
)
|
102
|
-
end
|
103
|
-
|
104
|
-
def self.has_custom_fonts?(processor, options, source_attributes)
|
105
|
-
!options[:no_install_fonts] \
|
106
|
-
&& processor.respond_to?(:fonts_manifest) \
|
107
|
-
&& !processor.fonts_manifest.nil? \
|
108
|
-
|| source_attributes[:fonts]
|
109
|
-
end
|
110
|
-
|
111
|
-
def self.location_manifest(processor, source_attributes)
|
112
|
-
Fontist::Manifest::Locations.from_hash(
|
113
|
-
append_source_fonts(processor.fonts_manifest.dup, source_attributes),
|
114
|
-
)
|
115
|
-
end
|
116
|
-
|
117
|
-
def self.append_source_fonts(manifest, source_attributes)
|
118
|
-
source_attributes[:fonts]&.split(";")&.each { |f| manifest[f] = nil }
|
119
|
-
manifest
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
@@ -1,216 +0,0 @@
|
|
1
|
-
require "yaml"
|
2
|
-
require_relative "util"
|
3
|
-
require_relative "sectionsplit_links"
|
4
|
-
|
5
|
-
module Metanorma
|
6
|
-
class Sectionsplit
|
7
|
-
attr_accessor :filecache, :key
|
8
|
-
|
9
|
-
def initialize(opts)
|
10
|
-
@input_filename = opts[:input]
|
11
|
-
@base = opts[:base]
|
12
|
-
@output_filename = opts[:output]
|
13
|
-
@xml = opts[:xml]
|
14
|
-
@dir = opts[:dir]
|
15
|
-
@compile_opts = opts[:compile_opts] || {}
|
16
|
-
@fileslookup = opts[:fileslookup]
|
17
|
-
@ident = opts[:ident]
|
18
|
-
@isodoc = opts[:isodoc]
|
19
|
-
end
|
20
|
-
|
21
|
-
def ns(xpath)
|
22
|
-
@isodoc.ns(xpath)
|
23
|
-
end
|
24
|
-
|
25
|
-
def build_collection
|
26
|
-
collection_setup(@base, @dir)
|
27
|
-
files = sectionsplit # (@input_filename, @base, @dir, @compile_opts)
|
28
|
-
input_xml = Nokogiri::XML(File.read(@input_filename,
|
29
|
-
encoding: "UTF-8"), &:huge)
|
30
|
-
collection_manifest(@base, files, input_xml, @xml, @dir).render(
|
31
|
-
{ format: %i(html), output_folder: "#{@output_filename}_collection",
|
32
|
-
coverpage: File.join(@dir, "cover.html") }.merge(@compile_opts),
|
33
|
-
)
|
34
|
-
end
|
35
|
-
|
36
|
-
def collection_manifest(filename, files, origxml, _presxml, dir)
|
37
|
-
File.open(File.join(dir, "#{filename}.html.yaml"), "w:UTF-8") do |f|
|
38
|
-
f.write(collectionyaml(files, origxml))
|
39
|
-
end
|
40
|
-
Metanorma::Collection.parse File.join(dir, "#{filename}.html.yaml")
|
41
|
-
end
|
42
|
-
|
43
|
-
def collection_setup(filename, dir)
|
44
|
-
FileUtils.mkdir_p "#{filename}_collection" if filename
|
45
|
-
FileUtils.mkdir_p dir
|
46
|
-
File.open(File.join(dir, "cover.html"), "w:UTF-8") do |f|
|
47
|
-
f.write(coll_cover)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def coll_cover
|
52
|
-
<<~COVER
|
53
|
-
<html><head><meta charset="UTF-8"/></head><body>
|
54
|
-
<h1>{{ doctitle }}</h1>
|
55
|
-
<h2>{{ docnumber }}</h2>
|
56
|
-
<nav>{{ navigation }}</nav>
|
57
|
-
</body></html>
|
58
|
-
COVER
|
59
|
-
end
|
60
|
-
|
61
|
-
SPLITSECTIONS =
|
62
|
-
[["//preface/*", "preface"], ["//sections/*", "sections"],
|
63
|
-
["//annex", nil],
|
64
|
-
["//bibliography/*[not(@hidden = 'true')]", "bibliography"],
|
65
|
-
["//indexsect", nil], ["//colophon", nil]].freeze
|
66
|
-
|
67
|
-
# Input XML is Semantic
|
68
|
-
# def sectionsplit(filename, basename, dir, compile_options, fileslookup = nil, ident = nil)
|
69
|
-
def sectionsplit
|
70
|
-
xml = sectionsplit_prep(File.read(@input_filename), @base, @dir)
|
71
|
-
@key = xref_preprocess(xml, @fileslookup, @ident)
|
72
|
-
SPLITSECTIONS.each_with_object([]) do |n, ret|
|
73
|
-
conflate_floatingtitles(xml.xpath(ns(n[0]))).each do |s|
|
74
|
-
ret << sectionfile(xml, emptydoc(xml), "#{@base}.#{ret.size}", s,
|
75
|
-
n[1])
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def block?(node)
|
81
|
-
%w(p table formula admonition ol ul dl figure quote sourcecode example
|
82
|
-
pre note pagebrreak hr bookmark requirement recommendation permission
|
83
|
-
svgmap inputform toc passthrough review imagemap).include?(node.name)
|
84
|
-
end
|
85
|
-
|
86
|
-
def conflate_floatingtitles(nodes)
|
87
|
-
holdover = false
|
88
|
-
nodes.each_with_object([]) do |x, m|
|
89
|
-
if holdover then m.last << x
|
90
|
-
else m << [x]
|
91
|
-
end
|
92
|
-
holdover = block?(x)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
def sectionsplit_prep(file, filename, dir)
|
97
|
-
@splitdir = dir
|
98
|
-
xml1filename, type = sectionsplit_preprocess_semxml(file, filename)
|
99
|
-
Compile.new.compile(
|
100
|
-
xml1filename,
|
101
|
-
{ format: :asciidoc, extension_keys: [:presentation], type: type }
|
102
|
-
.merge(@compile_opts),
|
103
|
-
)
|
104
|
-
Nokogiri::XML(File.read(xml1filename.sub(/\.xml$/, ".presentation.xml"),
|
105
|
-
encoding: "utf-8"), &:huge)
|
106
|
-
end
|
107
|
-
|
108
|
-
def sectionsplit_preprocess_semxml(file, filename)
|
109
|
-
xml = Nokogiri::XML(file, &:huge)
|
110
|
-
type = xml.root.name.sub("-standard", "").to_sym
|
111
|
-
sectionsplit_update_xrefs(xml)
|
112
|
-
xml1 = sectionsplit_write_semxml(filename, xml)
|
113
|
-
@filecache ||= []
|
114
|
-
@filecache << xml1
|
115
|
-
[xml1.path, type]
|
116
|
-
end
|
117
|
-
|
118
|
-
def sectionsplit_update_xrefs(xml)
|
119
|
-
if c = @fileslookup&.parent
|
120
|
-
n = c.nested
|
121
|
-
c.nested = true # so unresolved erefs are not deleted
|
122
|
-
c.update_xrefs(xml, @ident, {})
|
123
|
-
c.nested = n
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
def sectionsplit_write_semxml(filename, xml)
|
128
|
-
Tempfile.open([filename, ".xml"], encoding: "utf-8") do |f|
|
129
|
-
# f.write(@isodoc.to_xml(svg_preprocess(xml)))
|
130
|
-
f.write(@isodoc.to_xml(xml))
|
131
|
-
f
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
def emptydoc(xml)
|
136
|
-
out = xml.dup
|
137
|
-
out.xpath(
|
138
|
-
ns("//preface | //sections | //annex | //bibliography/clause | " \
|
139
|
-
"//bibliography/references[not(@hidden = 'true')] | //indexsect | " \
|
140
|
-
"//colophon"),
|
141
|
-
).each(&:remove)
|
142
|
-
out
|
143
|
-
end
|
144
|
-
|
145
|
-
def sectionfile(fulldoc, xml, file, chunks, parentnode)
|
146
|
-
fname = create_sectionfile(fulldoc, xml.dup, file, chunks, parentnode)
|
147
|
-
{ order: chunks.last["displayorder"].to_i, url: fname,
|
148
|
-
title: titlerender(chunks.last) }
|
149
|
-
end
|
150
|
-
|
151
|
-
def create_sectionfile(xml, out, file, chunks, parentnode)
|
152
|
-
ins = out.at(ns("//metanorma-extension")) || out.at(ns("//bibdata"))
|
153
|
-
sectionfile_insert(ins, chunks, parentnode)
|
154
|
-
xref_process(out, xml, @key)
|
155
|
-
outname = "#{file}.xml"
|
156
|
-
File.open(File.join(@splitdir, outname), "w:UTF-8") do |f|
|
157
|
-
f.write(out)
|
158
|
-
end
|
159
|
-
outname
|
160
|
-
end
|
161
|
-
|
162
|
-
def sectionfile_insert(ins, chunks, parentnode)
|
163
|
-
if parentnode
|
164
|
-
ins.next = "<#{parentnode}/>"
|
165
|
-
chunks.each { |c| ins.next.add_child(c.dup) }
|
166
|
-
else chunks.each { |c| ins.next = c.dup }
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
def titlerender(section)
|
171
|
-
title = section.at(ns("./title")) or return "[Untitled]"
|
172
|
-
t = title.dup
|
173
|
-
t.xpath(ns(".//tab | .//br")).each { |x| x.replace(" ") }
|
174
|
-
t.xpath(ns(".//strong")).each { |x| x.replace(x.children) }
|
175
|
-
t.children.to_xml
|
176
|
-
end
|
177
|
-
|
178
|
-
def collectionyaml(files, xml)
|
179
|
-
ret = {
|
180
|
-
directives: ["presentation-xml", "bare-after-first"],
|
181
|
-
bibdata: {
|
182
|
-
title: {
|
183
|
-
type: "title-main", language: @lang,
|
184
|
-
content: xml.at(ns("//bibdata/title")).text
|
185
|
-
},
|
186
|
-
type: "collection",
|
187
|
-
docid: {
|
188
|
-
type: xml.at(ns("//bibdata/docidentifier/@type")).text,
|
189
|
-
id: xml.at(ns("//bibdata/docidentifier")).text,
|
190
|
-
},
|
191
|
-
},
|
192
|
-
manifest: {
|
193
|
-
level: "collection", title: "Collection",
|
194
|
-
docref: files.sort_by { |f| f[:order] }.each.map do |f|
|
195
|
-
{ fileref: f[:url], identifier: f[:title] }
|
196
|
-
end
|
197
|
-
},
|
198
|
-
}
|
199
|
-
Util::recursive_string_keys(ret).to_yaml
|
200
|
-
end
|
201
|
-
|
202
|
-
def section_split_cover(col, ident, one_doc_coll)
|
203
|
-
dir = File.dirname(col.file)
|
204
|
-
collection_setup(nil, dir)
|
205
|
-
CollectionRenderer.new(col, dir,
|
206
|
-
output_folder: "#{ident}_collection",
|
207
|
-
format: %i(html),
|
208
|
-
coverpage: File.join(dir, "cover.html")).coverpage
|
209
|
-
#filename = one_doc_coll ? "#{ident}_index.html" : "index.html"
|
210
|
-
filename = "#{ident}_index.html"
|
211
|
-
FileUtils.mv "#{ident}_collection/index.html", File.join(dir, filename)
|
212
|
-
FileUtils.rm_rf "#{ident}_collection"
|
213
|
-
filename
|
214
|
-
end
|
215
|
-
end
|
216
|
-
end
|