require "twitter_cldr" module IsoDoc class PresentationXMLConvert < ::IsoDoc::Convert def prefix_container(container, linkend, _target) l10n(@xrefs.anchor(container, :xref) + ", " + linkend) end def anchor_linkend(node, linkend) if node["citeas"].nil? && node["bibitemid"] return @xrefs.anchor(node["bibitemid"] ,:xref) || "???" elsif node["target"] && node["droploc"] return @xrefs.anchor(node["target"], :value) || @xrefs.anchor(node["target"], :label) || @xrefs.anchor(node["target"], :xref) || "???" elsif node["target"] && !/.#./.match(node["target"]) linkend = anchor_linkend1(node) end linkend || "???" end def anchor_linkend1(node) linkend = @xrefs.anchor(node["target"], :xref) container = @xrefs.anchor(node["target"], :container, false) (container && get_note_container_id(node) != container && @xrefs.get[node["target"]]) && linkend = prefix_container(container, linkend, node["target"]) capitalise_xref(node, linkend) end def capitalise_xref(node, linkend) return linkend unless %w(Latn Cyrl Grek).include? @script return linkend&.capitalize if node["case"] == "capital" return linkend&.downcase if node["case"] == "lowercase" return linkend if linkend[0,1].match(/\p{Upper}/) prec = nearest_block_parent(node).xpath("./descendant-or-self::text()") & node.xpath("./preceding::text()") (prec.empty? || /(?!<[^.].)\.\s+$/.match(prec.map { |p| p.text }.join)) ? linkend&.capitalize : linkend end def nearest_block_parent(node) until %w(p title td th name formula li dt dd sourcecode pre).include?(node.name) node = node.parent end node end def non_locality_elems(node) node.children.select do |c| !%w{locality localityStack}.include? c.name end end def get_linkend(n) contents = non_locality_elems(n).select { |c| !c.text? || /\S/.match(c) } return unless contents.empty? link = anchor_linkend(n, docid_l10n(n["target"] || n["citeas"])) link += eref_localities(n.xpath(ns("./locality | ./localityStack")), link) non_locality_elems(n).each { |n| n.remove } n.add_child(link) end # so not # 3.1 def eref_localities(refs, target) ret = "" refs.each_with_index do |r, i| delim = "," delim = ";" if r.name == "localityStack" && i>0 ret = eref_locality_stack(r, i, target, delim, ret) end ret end def eref_locality_stack(r, i, target, delim, ret) if r.name == "localityStack" r.elements.each_with_index do |rr, j| ret += eref_localities0(rr, j, target, delim) delim = "," end else ret += eref_localities0(r, i, target, delim) end ret end def eref_localities0(r, i, target, delim) if r["type"] == "whole" then l10n("#{delim} #{@i18n.wholeoftext}") else eref_localities1(target, r["type"], r.at(ns("./referenceFrom")), r.at(ns("./referenceTo")), delim, @lang) end end # TODO: move to localization file def eref_localities1_zh(target, type, from, to, delim) ret = "#{delim} 第#{from.text}" if from ret += "–#{to.text}" if to loc = (@i18n.locality[type] || type.sub(/^locality:/, "").capitalize ) ret += " #{loc}" ret end # TODO: move to localization file def eref_localities1(target, type, from, to, delim, lang = "en") return "" if type == "anchor" lang == "zh" and return l10n(eref_localities1_zh(target, type, from, to, delim)) ret = delim loc = @i18n.locality[type] || type.sub(/^locality:/, "").capitalize ret += " #{loc}" ret += " #{from.text}" if from ret += "–#{to.text}" if to l10n(ret) end def xref(docxml) docxml.xpath(ns("//xref")).each { |f| xref1(f) } end def eref(docxml) docxml.xpath(ns("//eref")).each { |f| xref1(f) } end def origin(docxml) docxml.xpath(ns("//origin[not(termref)]")).each { |f| xref1(f) } end def quotesource(docxml) docxml.xpath(ns("//quote/source")).each { |f| xref1(f) } end def xref1(f) get_linkend(f) end def concept(docxml) docxml.xpath(ns("//concept")).each { |f| concept1(f) } end def concept1(node) content = node.first_element_child.children.select do |c| !%w{locality localityStack}.include? c.name end.select { |c| !c.text? || /\S/.match(c) } node.replace content.empty? ? @i18n.term_defined_in.sub(/%/, node.first_element_child.to_xml) : "#{node.children.to_xml}" end MATHML = { "m" => "http://www.w3.org/1998/Math/MathML" }.freeze def mathml(docxml) locale = twitter_cldr_localiser() docxml.xpath("//m:math", MATHML).each do |f| mathml1(f, locale) end end # symbols is merged into # TwitterCldr::DataReaders::NumberDataReader.new(locale).symbols def localize_maths(f, locale) f.xpath(".//m:mn", MATHML).each do |x| num = /\./.match(x.text) ? x.text.to_f : x.text.to_i precision = /\./.match(x.text) ? x.text.sub(/^.*\./, "").size : 0 x.children = localized_number(num, locale, precision) end end # By itself twiiter cldr does not support fraction part digits grouping # and custom delimeter, will decorate fraction part manually def localized_number(num, locale, precision) localized = precision == 0 ? num.localize(locale).to_s : num.localize(locale).to_decimal.to_s(:precision => precision) twitter_cldr_reader_symbols = twitter_cldr_reader(locale) return localized unless twitter_cldr_reader_symbols[:decimal] integer, fraction = localized.split(twitter_cldr_reader_symbols[:decimal]) return localized if fraction.nil? || fraction.length.zero? [integer, decorate_fraction_part(fraction, locale)]. join(twitter_cldr_reader_symbols[:decimal]) end def decorate_fraction_part(fract, locale) result = [] twitter_cldr_reader_symbols = twitter_cldr_reader(locale) fract = fract.slice(0..(twitter_cldr_reader_symbols[:precision] || -1)) fr_group_digits = twitter_cldr_reader_symbols[:fraction_group_digits] || 1 until fract.empty? result.push(fract.slice!(0, fr_group_digits)) end result.join(twitter_cldr_reader_symbols[:fraction_group].to_s) end def twitter_cldr_localiser_symbols {} end def twitter_cldr_reader(locale) num = TwitterCldr::DataReaders::NumberDataReader.new(locale) num.symbols.merge!(twitter_cldr_localiser_symbols) end def twitter_cldr_localiser() locale = TwitterCldr.supported_locale?(@lang.to_sym) ? @lang.to_sym : :en twitter_cldr_reader(locale) locale end def mathml1(f, locale) localize_maths(f, locale) return unless f.elements.size == 1 && f.elements.first.name == "mn" if f.parent.name == "stem" f.parent.replace(f.at("./m:mn", MATHML).children) else f.replace(f.at("./m:mn", MATHML).children) end end def variant(docxml) docxml.xpath(ns("//variant")).each { |f| variant1(f) } docxml.xpath(ns("//variant[@remove = 'true']")).each { |f| f.remove } docxml.xpath(ns("//variant")).each do |v| next unless v&.next&.name == "variant" v.next = "/" end docxml.xpath(ns("//variant")).each { |f| f.replace(f.children) } end def variant1(node) if (!node["lang"] || node["lang"] == @lang) && (!node["script"] || node["script"] == @script) elsif found_matching_variant_sibling(node) node["remove"] = "true" else #return unless !node.at("./preceding-sibling::xmlns:variant") end end def found_matching_variant_sibling(node) prev = node.xpath("./preceding-sibling::xmlns:variant") foll = node.xpath("./following-sibling::xmlns:variant") found = false (prev + foll).each do |n| found = true if n["lang"] == @lang && (!n["script"] || n["script"] == @script) end found end end end