require "csv" module IsoDoc class PresentationXMLConvert < ::IsoDoc::Convert def bibdata(docxml) toc_metadata(docxml) fonts_metadata(docxml) docid_prefixes(docxml) a = bibdata_current(docxml) or return address_precompose(a) bibdata_i18n(a) a.next = "#{i8n_name(trim_hash(@i18n.get), '').join}" \ "" end def toc_metadata(docxml) return unless @tocfigures || @toctables || @tocrecommendations ins = docxml.at(ns("//metanorma-extension")) || docxml.at(ns("//bibdata")).after("").next_element @tocfigures and ins << "#{@i18n.toc_figures}" @toctables and ins << "#{@i18n.toc_tables}" @tocfigures and ins << "#{@i18n.toc_recommendations}" \ "" end def address_precompose(bib) bib.xpath(ns("//bibdata//address")).each do |b| next if b.at(ns("./formattedAddress")) x = address_precompose1(b) b.children = "#{x}" end end def fonts_metadata(xmldoc) return unless @fontist_fonts ins = xmldoc.at(ns("//presentation-metadata")) || xmldoc.at(ns("//metanorma-extension")) || xmldoc.at(ns("//bibdata")) CSV.parse_line(@fontist_fonts, col_sep: ";").map(&:strip).each do |f| ins.next = presmeta("fonts", f) end @fontlicenseagreement and ins.next = presmeta("font-license-agreement", @fontlicenseagreement) end def presmeta(name, value) "#{name}#{value}" \ "" end def address_precompose1(addr) ret = [] addr.xpath(ns("./street")).each { |s| ret << to_xml(s.children) } a = addr.at(ns("./city")) and ret << to_xml(a.children) addr.xpath(ns("./state")).each { |s| ret << to_xml(s.children) } a = addr.at(ns("./country")) and ret << to_xml(a.children) a = addr.at(ns("./postcode")) and ret[-1] += " #{to_xml a.children}" ret.join("
") end def bibdata_current(docxml) a = docxml.at(ns("//bibdata")) or return a.xpath(ns("./language")).each do |l| l.text == @lang and l["current"] = "true" end a.xpath(ns("./script")).each do |l| l.text == @script and l["current"] = "true" end a end def bibdata_i18n(bib) hash_translate(bib, @i18n.get["doctype_dict"], "./ext/doctype") hash_translate(bib, @i18n.get["stage_dict"], "./status/stage") hash_translate(bib, @i18n.get["substage_dict"], "./status/substage") edition_translate(bib) end def hash_translate(bibdata, hash, xpath, lang = @lang) x = bibdata.at(ns(xpath)) or return hash.is_a? Hash or return hash[x.text] or return tag_translate(x, lang, hash[x.text]) end # does not allow %Spellout and %Ordinal in the ordinal expression to be mixed def edition_translate(bibdata) x = bibdata.at(ns("./edition")) or return /^\d+$/.match?(x.text) or return tag_translate(x, @lang, @i18n.edition_ordinal.sub(/%(Spellout|Ordinal)?/, edition_translate1(x.text.to_i))) end def edition_translate1(num) ruleset = case @i18n.edition_ordinal when /%Spellout/ then "SpelloutRules" when /%Ordinal/ then "OrdinalRules" else "Digit" end ruleset == "Digit" and return num.to_s ed = @c.decode(@i18n.edition) @i18n.inflect_ordinal(num, @i18n.inflection&.dig(ed) || {}, ruleset) end def tag_translate(tag, lang, value) tag["language"] = "" tag.next = tag.dup tag.next["language"] = lang tag.next.children = value 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) return hash unless hash.is_a? Hash hash.each_with_object({}) do |(k, v), g| next if blank?(v) 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