module IsoDoc
class PresentationXMLConvert < ::IsoDoc::Convert
def metadata(docxml)
toc_metadata(docxml)
fonts_metadata(docxml)
attachments_extract(docxml)
preprocess_xslt_insert(docxml)
a = docxml.at(ns("//bibdata")) or return
a.next =
"#{i8n_name(trim_hash(@i18n.get), '').join}" \
""
end
def attachments_extract(docxml)
docxml.at(ns("//metanorma-extension/attachment")) or return
dir = File.join(@localdir, "_#{@outputfile}_attachments")
FileUtils.rm_rf(dir)
FileUtils.mkdir_p(dir)
docxml.xpath(ns("//metanorma-extension/attachment")).each do |a|
save_attachment(a, dir)
end
end
def save_attachment(attachment, dir)
n = File.join(dir, attachment["name"])
c = attachment.text.sub(%r{^data:[^;]+;(?:charset=[^;]+;)?base64,}, "")
File.open(n, "wb") { |f| f.write(Base64.strict_decode64(c)) }
end
def extension_insert(xml, path = [])
ins = extension_insert_pt(xml)
path.each do |n|
ins = ins.at(ns("./#{n}")) || ins.add_child("<#{n}/>").first
end
ins
end
def extension_insert_pt(xml)
xml.at(ns("//metanorma-extension")) ||
xml.at(ns("//bibdata"))&.after("")
&.next_element ||
xml.root.elements.first.before("")
.previous_element
end
def toc_metadata(docxml)
@tocfigures || @toctables || @tocrecommendations or return
ins = extension_insert(docxml)
@tocfigures and
ins << "#{@i18n.toc_figures}"
@toctables and
ins << "#{@i18n.toc_tables}"
@tocfigures and
ins << "#{@i18n.toc_recommendations}" \
""
end
def fonts_metadata(xmldoc)
ins = presmeta_insert_pt(xmldoc)
@fontist_fonts and CSV.parse_line(@fontist_fonts, col_sep: ";")
.map(&:strip).reverse.each do |f|
ins.next = presmeta("fonts", f)
end
@fontlicenseagreement and
ins.next = presmeta("font-license-agreement", @fontlicenseagreement)
end
def presmeta_insert_pt(xmldoc)
xmldoc.at(ns("//presentation-metadata")) ||
xmldoc.at(ns("//metanorma-extension")) || xmldoc.at(ns("//bibdata"))
end
def presmeta(name, value)
"#{name}#{value}" \
""
end
def preprocess_xslt_insert(docxml)
content = ""
p = passthrough_xslt and content += p
p = preprocess_xslt_read and content += File.read(p)
content.empty? and return
ins = extension_insert(docxml, %w(render))
ins << content
end
COPY_XSLT =
''.freeze
COPY_CHILDREN_XSLT =
''.freeze
def xslt_template(content)
<<~XSLT
#{COPY_XSLT}
#{content}
XSLT
end
def passthrough_xslt
@output_formats.nil? and return nil
@output_formats.empty? and return nil
@output_formats.each_key.with_object([]) do |k, m|
m << <<~XSLT
#{xslt_template(<<~XSLT1)
#{COPY_XSLT}
XSLT1
}
XSLT
m << <<~XSLT
#{xslt_template(<<~XSLT1)
#{k == 'pdf' ? COPY_CHILDREN_XSLT : ''}
#{k == 'pdf' ? '' : COPY_CHILDREN_XSLT}
XSLT1
}
XSLT
end.join("\n")
end
# read in from file, but with `` wrapper
def preprocess_xslt_read
html_doc_path("preprocess.xslt")
end
def i18n_tag(key, value)
"#{value}" \
""
end
def i18n_safe(key)
key.to_s.gsub(/\s|\./, "_")
end
def i8n_name(hash, pref)
case hash
when Hash then i8n_name1(hash, pref)
when Array
hash.reject { |a| blank?(a) }.each_with_object([])
.with_index do |(v1, g), i|
i8n_name(v1, "#{i18n_safe(k)}.#{i}").each { |x| g << x }
end
else [i18n_tag(pref, hash)]
end
end
def i8n_name1(hash, pref)
hash.reject { |_k, v| blank?(v) }.each_with_object([]) do |(k, v), g|
case v
when Hash then i8n_name(v, i18n_safe(k)).each { |x| g << x }
when Array
v.reject { |a| blank?(a) }.each_with_index do |v1, i|
i8n_name(v1, "#{i18n_safe(k)}.#{i}").each { |x| g << x }
end
else
g << i18n_tag("#{pref}#{pref.empty? ? '' : '.'}#{i18n_safe(k)}", v)
end
end
end
# https://stackoverflow.com/a/31822406
def blank?(elem)
elem.nil? || (elem.respond_to?(:empty?) && elem.empty?)
end
def trim_hash(hash)
loop do
h_new = trim_hash1(hash)
break hash if hash == h_new
hash = h_new
end
end
def trim_hash1(hash)
hash.is_a?(Hash) or return hash
hash.each_with_object({}) do |(k, v), g|
blank?(v) and next
g[k] = case v
when Hash then trim_hash1(hash[k])
when Array
hash[k].map { |a| trim_hash1(a) }.reject { |a| blank?(a) }
else v
end
end
end
end
end