Module: Metanorma::Standoc::Image
- Included in:
- Cleanup
- Defined in:
- lib/metanorma/cleanup/image.rb
Constant Summary collapse
- IRI_TAG_PROPERTIES_MAP =
{ clipPath: ["clip-path"], "color-profile": nil, cursor: nil, filter: nil, linearGradient: ["fill", "stroke"], marker: ["marker", "marker-end", "marker-mid", "marker-start"], mask: nil, pattern: ["fill", "stroke"], radialGradient: ["fill", "stroke"], }.freeze
- SVG_NS =
"http://www.w3.org/2000/svg".freeze
Instance Method Summary collapse
- #altmedia_cleanup(xmldoc) ⇒ Object
- #altmedia_prep(img) ⇒ Object
- #altmedia_root_cleanup(img) ⇒ Object
- #altsource_attr_copy(src, dest, img) ⇒ Object
- #altsource_populate(img, dlist) ⇒ Object
- #datauri_image(xmldoc) ⇒ Object
- #image_attr_copy(src, dest) ⇒ Object
- #img_cleanup(xmldoc) ⇒ Object
- #read_in_if_svg?(img, localdir) ⇒ Boolean
- #svg_attrupdate(elem, iri_properties, idx, ids) ⇒ Object
- #svg_classupdate(xmldoc) ⇒ Object
- #svg_classupdate1(svg, style, idx) ⇒ Object
- #svg_cleanup(xmldoc) ⇒ Object
- #svg_idupdate(elem, idx, ids) ⇒ Object
- #svg_iri_properties(id_elems) ⇒ Object
- #svg_linkupdate(elem, idx, ids) ⇒ Object
- #svg_styleupdate(elem, idx, ids) ⇒ Object
- #svg_suffix_css_style(node, idx) ⇒ Object
- #svg_uniqueids(xmldoc) ⇒ Object
- #svg_uniqueids1(svg, idx, ids) ⇒ Object
- #svg_uniqueids2(svg, iri_properties, idx, ids) ⇒ Object
- #svg_update_url(text, idx, ids) ⇒ Object
- #svgmap_cleanup(xmldoc) ⇒ Object
- #svgmap_moveattrs(xmldoc) ⇒ Object
- #svgmap_moveattrs1(svgmap, figure) ⇒ Object
- #svgmap_populate(xmldoc) ⇒ Object
- #svgmap_target(nodeset) ⇒ Object
Instance Method Details
#altmedia_cleanup(xmldoc) ⇒ Object
73 74 75 76 77 78 79 80 |
# File 'lib/metanorma/cleanup/image.rb', line 73 def altmedia_cleanup(xmldoc) xmldoc.xpath("//image[@altmedia]").each do |i| altmedia_root_cleanup(i) d = altmedia_prep(i) d or next altsource_populate(i, d) end end |
#altmedia_prep(img) ⇒ Object
115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/metanorma/cleanup/image.rb', line 115 def altmedia_prep(img) dl = img.at("./dl") or return d = extract_symbols_list(dl.remove).map do |e| { dt: e[:dt].text, dd: e[:dd].at(".//image") } end unless d.detect { |e| e[:dt] == "default" } d << d.first.dup d[-1][:dt] = "default" end d end |
#altmedia_root_cleanup(img) ⇒ Object
109 110 111 112 113 |
# File 'lib/metanorma/cleanup/image.rb', line 109 def altmedia_root_cleanup(img) %w(altmedia src filename mimetype).each do |k| img.delete(k) end end |
#altsource_attr_copy(src, dest, img) ⇒ Object
97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/metanorma/cleanup/image.rb', line 97 def altsource_attr_copy(src, dest, img) %w(media).each do |k| src[k] and dest[k] = src[k] end %w(height width).each do |k| dest[k] = img[k] src[k] or next src[k] == "auto" and next dest[k] = src[k] end end |
#altsource_populate(img, dlist) ⇒ Object
82 83 84 85 86 87 88 89 |
# File 'lib/metanorma/cleanup/image.rb', line 82 def altsource_populate(img, dlist) dlist.each do |e| e[:dd].nil? and next img << "<altsource tag='#{e[:dt]}'/>" image_attr_copy(e[:dd], img.elements.last) altsource_attr_copy(e[:dd], img.elements.last, img) end end |
#datauri_image(xmldoc) ⇒ Object
64 65 66 67 68 69 70 71 |
# File 'lib/metanorma/cleanup/image.rb', line 64 def datauri_image(xmldoc) xmldoc.xpath("//image | //altsource").each do |i| # do not datauri encode SVG, we need to deduplicate its IDs unless read_in_if_svg?(i, @localdir) i["src"] &&= Vectory::Utils::datauri(i["src"], @localdir) end end end |
#image_attr_copy(src, dest) ⇒ Object
91 92 93 94 95 |
# File 'lib/metanorma/cleanup/image.rb', line 91 def image_attr_copy(src, dest) %w(src mimetype filename alt).each do |k| src[k] and dest[k] = src[k] end end |
#img_cleanup(xmldoc) ⇒ Object
57 58 59 60 61 62 |
# File 'lib/metanorma/cleanup/image.rb', line 57 def img_cleanup(xmldoc) altmedia_cleanup(xmldoc) @datauriimage and datauri_image(xmldoc) svg_cleanup(xmldoc) xmldoc end |
#read_in_if_svg?(img, localdir) ⇒ Boolean
132 133 134 135 136 137 138 139 140 141 |
# File 'lib/metanorma/cleanup/image.rb', line 132 def read_in_if_svg?(img, localdir) img["src"] or return false path = Vectory::Utils.svgmap_rewrite0_path(img["src"], localdir) File.file?(path) or return false types = MIME::Types.type_for(path) or return false types.first == "image/svg+xml" or return false svg = File.read(path, encoding: "utf-8") or return false img.add_first_child Nokogiri::XML(svg).root true end |
#svg_attrupdate(elem, iri_properties, idx, ids) ⇒ Object
237 238 239 240 241 242 |
# File 'lib/metanorma/cleanup/image.rb', line 237 def svg_attrupdate(elem, iri_properties, idx, ids) iri_properties.each do |p| elem[p] or next elem[p] = svg_update_url(elem[p], idx, ids) end end |
#svg_classupdate(xmldoc) ⇒ Object
143 144 145 146 147 148 |
# File 'lib/metanorma/cleanup/image.rb', line 143 def svg_classupdate(xmldoc) xmldoc.xpath("//m:svg[m:style]", "m" => SVG_NS) .each_with_index do |s, i| svg_classupdate1(s, s.at("./m:style", "m" => SVG_NS), i) end end |
#svg_classupdate1(svg, style, idx) ⇒ Object
150 151 152 153 154 155 156 157 158 |
# File 'lib/metanorma/cleanup/image.rb', line 150 def svg_classupdate1(svg, style, idx) tree = Crass.parse(style.text) tree.each { |n| svg_suffix_css_style(n, idx) } style.children = Crass::Parser.stringify(tree) svg.xpath(".//*[@class]").each do |n| n["class"] = n["class"].split(/\s+/) .map { |x| "#{x}_inject_#{idx}" }.join(" ") end end |
#svg_cleanup(xmldoc) ⇒ Object
127 128 129 130 |
# File 'lib/metanorma/cleanup/image.rb', line 127 def svg_cleanup(xmldoc) svg_uniqueids(xmldoc) svg_classupdate(xmldoc) end |
#svg_idupdate(elem, idx, ids) ⇒ Object
253 254 255 256 257 |
# File 'lib/metanorma/cleanup/image.rb', line 253 def svg_idupdate(elem, idx, ids) elem["id"] or return ids[elem["id"]] or return elem["id"] += "_inject_#{idx}" end |
#svg_iri_properties(id_elems) ⇒ Object
192 193 194 195 196 197 198 199 200 201 |
# File 'lib/metanorma/cleanup/image.rb', line 192 def svg_iri_properties(id_elems) iri_tag_names = id_elems.each_with_object([]) do |e, m| IRI_TAG_PROPERTIES_MAP.key?(e.name.to_sym) and m << e.name end.uniq iri_properties = iri_tag_names.each_with_object([]) do |t, m| (IRI_TAG_PROPERTIES_MAP[t.to_sym] || [t]).each { |t1| m = m << t1 } end.uniq iri_properties.empty? and return [] iri_properties << "style" end |
#svg_linkupdate(elem, idx, ids) ⇒ Object
244 245 246 247 248 249 250 251 |
# File 'lib/metanorma/cleanup/image.rb', line 244 def svg_linkupdate(elem, idx, ids) %w(xlink:href href).each do |ref| iri = elem[ref]&.strip /^#/.match?(iri) or next ids[iri.sub(/^#/, "")] or next elem[ref] += "_inject_#{idx}" end end |
#svg_styleupdate(elem, idx, ids) ⇒ Object
233 234 235 |
# File 'lib/metanorma/cleanup/image.rb', line 233 def svg_styleupdate(elem, idx, ids) elem.children = svg_update_url(elem.text, idx, ids) end |
#svg_suffix_css_style(node, idx) ⇒ Object
160 161 162 163 164 165 166 |
# File 'lib/metanorma/cleanup/image.rb', line 160 def svg_suffix_css_style(node, idx) (node[:node] == :style_rule && /\./.match?(node[:selector][:value])) or return v = node[:selector][:value] .gsub(/([^.\s]*\.\S+)/, "\\1_inject_#{idx}") node[:selector] = Crass.parse("#{v} {}").first[:selector] end |
#svg_uniqueids(xmldoc) ⇒ Object
182 183 184 185 186 187 188 189 190 |
# File 'lib/metanorma/cleanup/image.rb', line 182 def svg_uniqueids(xmldoc) # only keep non-unique identifiers ids = xmldoc.xpath("//m:svg//*/@id | //svg/@id", "m" => SVG_NS) .map(&:text).group_by(&:itself).transform_values(&:count) .delete_if { |_, v| v < 2 } xmldoc.xpath("//m:svg", "m" => SVG_NS).each_with_index do |s, i| ids = svg_uniqueids1(s, i, ids) end end |
#svg_uniqueids1(svg, idx, ids) ⇒ Object
203 204 205 206 207 208 209 210 |
# File 'lib/metanorma/cleanup/image.rb', line 203 def svg_uniqueids1(svg, idx, ids) id_elems = svg.xpath(".//*[@id] | ./@id/..") iri_properties = svg_iri_properties(id_elems) svg_uniqueids2(svg, iri_properties, idx, ids) new_ids = id_elems.map { |x| x["id"] } .map { |x| x + (ids[x] ? "_inject_#{idx}" : "") } ids.merge(new_ids.each.to_h { |value| [value, true] }) end |
#svg_uniqueids2(svg, iri_properties, idx, ids) ⇒ Object
212 213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/metanorma/cleanup/image.rb', line 212 def svg_uniqueids2(svg, iri_properties, idx, ids) svg.traverse do |e| e.element? or next if e.name == "style" svg_styleupdate(e, idx, ids) elsif !e.attributes.empty? svg_attrupdate(e, iri_properties, idx, ids) end svg_linkupdate(e, idx, ids) svg_idupdate(e, idx, ids) end end |
#svg_update_url(text, idx, ids) ⇒ Object
225 226 227 228 229 230 231 |
# File 'lib/metanorma/cleanup/image.rb', line 225 def svg_update_url(text, idx, ids) text.gsub(/url\("?#([a-zA-Z][\w:.-]*)"?\)/) do |x| if ids[$1] then "url(##{$1}_inject_#{idx})" else x end end end |
#svgmap_cleanup(xmldoc) ⇒ Object
7 8 9 10 11 |
# File 'lib/metanorma/cleanup/image.rb', line 7 def svgmap_cleanup(xmldoc) svgmap_moveattrs(xmldoc) svgmap_populate(xmldoc) Vectory::SvgMapping.new(xmldoc, @localdir).call end |
#svgmap_moveattrs(xmldoc) ⇒ Object
13 14 15 16 17 18 19 20 21 22 23 24 |
# File 'lib/metanorma/cleanup/image.rb', line 13 def svgmap_moveattrs(xmldoc) xmldoc.xpath("//svgmap").each do |s| f = s.at(".//figure") or next (t = s.at("./name")) && !f.at("./name") and f.add_first_child t.remove if s["anchor"] # && Metanorma::Utils::guid_anchor?(f["id"]) f["anchor"] = s["anchor"] s.delete("anchor") end svgmap_moveattrs1(s, f) end end |
#svgmap_moveattrs1(svgmap, figure) ⇒ Object
26 27 28 29 30 31 32 33 |
# File 'lib/metanorma/cleanup/image.rb', line 26 def svgmap_moveattrs1(svgmap, figure) %w(unnumbered number subsequence keep-with-next keep-lines-together tag multilingual-rendering).each do |a| figure[a] || !svgmap[a] and next figure[a] = svgmap[a] svgmap.delete(a) end end |
#svgmap_populate(xmldoc) ⇒ Object
35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/metanorma/cleanup/image.rb', line 35 def svgmap_populate(xmldoc) xmldoc.xpath("//svgmap").each do |s| s1 = s.dup s.children.remove f = s1.at(".//figure") and s << f s1.xpath(".//li").each do |li| t = li.at(".//eref | .//link | .//xref") or next href = t.xpath("./following-sibling::node()") href.empty? or s << %[<target href="#{svgmap_target(href)}">#{t.to_xml}</target>] end end end |
#svgmap_target(nodeset) ⇒ Object
49 50 51 52 53 54 55 |
# File 'lib/metanorma/cleanup/image.rb', line 49 def svgmap_target(nodeset) nodeset.each do |n| n.name == "link" or next n.children = n["target"] end nodeset.text.sub(/^[,; ]/, "").strip end |