module Metanorma::Utils
Constants
- NAMECHAR
- NAMESTARTCHAR
- SVG_NS
- VERSION
Public Class Methods
anchor_or_uuid(node = nil)
click to toggle source
# File lib/utils/main.rb, line 29 def anchor_or_uuid(node = nil) uuid = UUIDTools::UUID.random_create node.nil? || node.id.nil? || node.id.empty? ? "_#{uuid}" : node.id end
asciidoc_sub(text, flavour = :standoc)
click to toggle source
# File lib/utils/main.rb, line 34 def asciidoc_sub(text, flavour = :standoc) return nil if text.nil? return "" if text.empty? d = Asciidoctor::Document.new( text.lines.entries, { header_footer: false, backend: flavour }, ) b = d.parse.blocks.first b.apply_subs(b.source) end
datauri(uri, localdirectory = ".")
click to toggle source
sources/plantuml/plantuml20200524-90467-1iqek5i.png already includes localdir
# File lib/utils/image.rb, line 129 def datauri(uri, localdirectory = ".") return uri if /^data:/.match?(uri) path = datauri_path(uri, localdirectory) return path unless File.exist?(path) types = MIME::Types.type_for(path) type = types ? types.first.to_s : 'text/plain; charset="utf-8"' bin = File.open(path, "rb", &:read) data = Base64.strict_encode64(bin) "data:#{type};base64,#{data}" end
datauri2mime(uri)
click to toggle source
# File lib/utils/image.rb, line 154 def datauri2mime(uri) %r{^data:image/(?<imgtype>[^;]+);base64,(?<imgdata>.+)$} =~ uri type = nil imgtype = "png" unless /^[a-z0-9]+$/.match? imgtype ::Tempfile.open(["imageuri", ".#{imgtype}"]) do |file| type = datauri2mime1(file, imgdata) end [type] end
datauri2mime1(file, imgdata)
click to toggle source
# File lib/utils/image.rb, line 164 def datauri2mime1(file, imgdata) type = nil begin file.binmode file.write(Base64.strict_decode64(imgdata)) file.rewind type = Marcel::MimeType.for file ensure file.close! end type end
datauri_path(uri, localdirectory)
click to toggle source
# File lib/utils/image.rb, line 142 def datauri_path(uri, localdirectory) path = if %r{^([A-Z]:)?/}.match?(uri) then uri else File.exist?(uri) ? uri : File.join(localdirectory, uri) end unless File.exist?(path) warn "image at #{path} not found" return uri end path end
default_script(lang)
click to toggle source
# File lib/utils/main.rb, line 119 def default_script(lang) case lang when "ar", "fa" then "Arab" when "ur" then "Aran" when "ru", "bg" then "Cyrl" when "hi" then "Deva" when "el" then "Grek" when "zh" then "Hans" when "ko" then "Kore" when "he" then "Hebr" when "ja" then "Jpan" else "Latn" end end
endash_date(elem)
click to toggle source
# File lib/utils/main.rb, line 58 def endash_date(elem) elem.traverse do |n| next unless n.text? n.replace(n.text.gsub(/\s+--?\s+/, "–").gsub(/--/, "–")) end end
external_path(path)
click to toggle source
# File lib/utils/main.rb, line 108 def external_path(path) win = !!((RUBY_PLATFORM =~ /(win|w)(32|64)$/) || (RUBY_PLATFORM =~ /mswin|mingw/)) if win path.gsub!(%{/}, "\\") path[/\s/] ? "\"#{path}\"" : path else path end end
flatten_rawtext(node)
click to toggle source
not currently used if node contains blocks, flatten them into a single line; and extract only raw text
# File lib/utils/main.rb, line 156 def flatten_rawtext(node) result = [] if node.respond_to?(:blocks) && node.blocks? node.blocks.each { |b| result << flatten_rawtext(b) } elsif node.respond_to?(:lines) result = flatten_rawtext_lines(node, result) elsif node.respond_to?(:text) result << node.text.gsub(/<[^>]*>+/, "") else result << node.content.gsub(/<[^>]*>+/, "") end result.reject(&:empty?) end
flatten_rawtext_lines(node, result)
click to toggle source
not currently used
# File lib/utils/main.rb, line 140 def flatten_rawtext_lines(node, result) node.lines.each do |x| result << if node.respond_to?(:context) && (node.context == :literal || node.context == :listing) x.gsub(/</, "<").gsub(/>/, ">") else # strip not only HTML <tag>, and Asciidoc xrefs <<xref>> x.gsub(/<[^>]*>+/, "") end end result end
localdir(node)
click to toggle source
# File lib/utils/main.rb, line 46 def localdir(node) docfile = node.attr("docfile") docfile.nil? ? "./" : "#{Pathname.new(docfile).parent}/" end
rtl_script?(script)
click to toggle source
# File lib/utils/main.rb, line 135 def rtl_script?(script) %w(Arab Aran Hebr).include? script end
save_dataimage(uri)
click to toggle source
# File lib/utils/image.rb, line 25 def save_dataimage(uri) %r{^data:(image|application)/(?<imgtype>[^;]+);(charset=[^;]+;)?base64,(?<imgdata>.+)$} =~ uri imgtype.sub!(/\+[a-z0-9]+$/, "") # svg+xml imgtype = "png" unless /^[a-z0-9]+$/.match? imgtype Tempfile.open(["image", ".#{imgtype}"]) do |f| f.binmode f.write(Base64.strict_decode64(imgdata)) f.path end end
set_nested_value(hash, keys, new_val)
click to toggle source
Set hash value using keys path mod from stackoverflow.com/a/42425884
# File lib/utils/main.rb, line 68 def set_nested_value(hash, keys, new_val) key = keys[0] if keys.length == 1 hash[key] = if hash[key].is_a?(Array) then (hash[key] << new_val) else hash[key].nil? ? new_val : [hash[key], new_val] end elsif hash[key].is_a?(Array) hash[key][-1] = {} if !hash[key].empty? && hash[key][-1].nil? hash[key] << {} if hash[key].empty? || !hash[key][-1].is_a?(Hash) set_nested_value(hash[key][-1], keys[1..-1], new_val) elsif hash[key].nil? || hash[key].empty? hash[key] = {} set_nested_value(hash[key], keys[1..-1], new_val) elsif hash[key].is_a?(Hash) && !hash[key][keys[1]] set_nested_value(hash[key], keys[1..-1], new_val) elsif !hash[key][keys[1]] hash[key] = [hash[key], {}] set_nested_value(hash[key][-1], keys[1..-1], new_val) else set_nested_value(hash[key], keys[1..-1], new_val) end hash end
smartformat(text)
click to toggle source
TODO needs internationalisation
# File lib/utils/main.rb, line 52 def smartformat(text) text.gsub(/ --? /, " — ") .gsub(/--/, "—").smart_format.gsub(/</, "<") .gsub(/>/, ">") end
strict_capitalize_first(str)
click to toggle source
# File lib/utils/main.rb, line 100 def strict_capitalize_first(str) str.split(/ /).each_with_index.map do |w, i| letters = w.chars letters.first.upcase! if i.zero? letters.join end.join(" ") end
strict_capitalize_phrase(str)
click to toggle source
# File lib/utils/main.rb, line 92 def strict_capitalize_phrase(str) str.split(/ /).map do |w| letters = w.chars letters.first.upcase! letters.join end.join(" ") end
svg_update_href(svgmap, svg, namespace)
click to toggle source
# File lib/utils/image.rb, line 77 def svg_update_href(svgmap, svg, namespace) targ = svgmap_rewrite1_targets(svgmap, namespace) svg.xpath(".//m:a", "m" => SVG_NS).each do |a| ["xlink:href", "href"].each do |p| a[p] and x = targ[File.expand_path(a[p])] and a[p] = x end end end
svg_update_ids(svg, idx)
click to toggle source
# File lib/utils/image.rb, line 97 def svg_update_ids(svg, idx) ids = svg.xpath("./@id | .//@id") .each_with_object([]) { |i, m| m << i.value } return if ids.empty? svg_update_ids_attrs(svg, ids, idx) svg_update_ids_css(svg, ids, idx) end
svg_update_ids_attrs(svg, ids, idx)
click to toggle source
# File lib/utils/image.rb, line 106 def svg_update_ids_attrs(svg, ids, idx) svg.xpath(". | .//*[@*]").each do |a| a.attribute_nodes.each do |x| ids.include?(x.value) and x.value += sprintf("_%09d", idx) end end end
svg_update_ids_css(svg, ids, idx)
click to toggle source
# File lib/utils/image.rb, line 114 def svg_update_ids_css(svg, ids, idx) svg.xpath("//m:style", "m" => SVG_NS).each do |s| c = s.children.to_xml ids.each do |i| c = c.gsub(%r[##{i}\b], sprintf("#%<id>s_%<idx>09d", id: i, idx: idx)) .gsub(%r(\[id\s*=\s*['"]?#{i}['"]?\]), sprintf("[id='%<id>s_%<idx>09d']", id: i, idx: idx)) end s.children = c end end
svgmap_rewrite(xmldoc, localdirectory = "")
click to toggle source
# File lib/utils/image.rb, line 38 def svgmap_rewrite(xmldoc, localdirectory = "") n = Namespace.new(xmldoc) xmldoc.xpath(n.ns("//svgmap")).each_with_index do |s, i| next unless svgmap_rewrite0(s, n, localdirectory, i) next if s.at(n.ns("./target/eref")) s.replace(s.at(n.ns("./figure"))) end end
svgmap_rewrite0(svgmap, namespace, localdirectory, idx)
click to toggle source
# File lib/utils/image.rb, line 48 def svgmap_rewrite0(svgmap, namespace, localdirectory, idx) if (i = svgmap.at(namespace.ns(".//image"))) && (src = i["src"]) path = svgmap_rewrite0_path(src, localdirectory) File.file?(path) or return false svg = Nokogiri::XML(File.read(path, encoding: "utf-8")) i.replace(svgmap_rewrite1(svgmap, svg.root, namespace, idx)) /^data:/.match(src) and i["src"] = datauri(path) elsif i = svgmap.at(".//m:svg", "m" => SVG_NS) i.replace(svgmap_rewrite1(svgmap, i, namespace, idx)) else return false end true end
svgmap_rewrite0_path(src, localdirectory)
click to toggle source
# File lib/utils/image.rb, line 62 def svgmap_rewrite0_path(src, localdirectory) if /^data:/.match?(src) save_dataimage(src) else File.file?(src) ? src : localdirectory + src end end
svgmap_rewrite1(svgmap, svg, namespace, idx)
click to toggle source
# File lib/utils/image.rb, line 70 def svgmap_rewrite1(svgmap, svg, namespace, idx) svg_update_href(svgmap, svg, namespace) svg_update_ids(svg, idx) svg.xpath("processing-instruction()|.//processing-instruction()").remove svg.to_xml end
svgmap_rewrite1_targets(svgmap, namespace)
click to toggle source
# File lib/utils/image.rb, line 86 def svgmap_rewrite1_targets(svgmap, namespace) svgmap.xpath(namespace.ns("./target")) .each_with_object({}) do |t, m| x = t.at(namespace.ns("./xref")) and m[File.expand_path(t["href"])] = "##{x['target']}" x = t.at(namespace.ns("./link")) and m[File.expand_path(t["href"])] = x["target"] t.remove if t.at(namespace.ns("./xref | ./link")) end end
to_ncname(tag, asciionly: true)
click to toggle source
# File lib/utils/main.rb, line 17 def to_ncname(tag, asciionly: true) asciionly and tag = HTMLEntities.new.encode(tag, :basic, :hexadecimal) start = tag[0] ret1 = if %r([#{NAMECHAR}#])o.match?(start) "_" else (%r([#{NAMESTARTCHAR}#])o.match?(start) ? "_#{start}" : start) end ret2 = tag[1..-1] || "" (ret1 || "") + ret2.gsub(%r([#{NAMECHAR}#])o, "_") end