Module: Metanorma::Standoc::Validate::Image
- Included in:
- Metanorma::Standoc::Validate
- Defined in:
- lib/metanorma/validate/image.rb
Constant Summary collapse
- SVG_NS =
"http://www.w3.org/2000/svg".freeze
Instance Method Summary collapse
- #expand_path(loc) ⇒ Object
- #image_exists(doc) ⇒ Object
- #image_toobig(doc) ⇒ Object
- #image_validate(doc) ⇒ Object
- #png_validate(doc) ⇒ Object
- #png_validate1(img, _path, validator) ⇒ Object
- #save_dataimage(uri, _relative_dir = true) ⇒ Object
- #save_dataimage_prep(uri) ⇒ Object
- #svg_error(id, svg, errors, options = {}) ⇒ Object
- #svg_error_locations(err) ⇒ Object
-
#svg_reference_violations(svg, result) ⇒ Object
Check for unresolved internal references.
- #svg_remed_log(remeds, svg) ⇒ Object
-
#svg_remediate(validator, profile, engine, svg, result) ⇒ Object
Apply remediation if needed.
-
#svg_validate(doc) ⇒ Object
Use SAX for fast validation.
- #svg_validate1(validator, profile, svg) ⇒ Object
- #svg_validate_fix(validator, profile, engine, svg, result) ⇒ Object
Instance Method Details
#expand_path(loc) ⇒ Object
26 27 28 29 30 31 |
# File 'lib/metanorma/validate/image.rb', line 26 def (loc) relative_path = File.join(@localdir, loc) [loc, relative_path].detect do |p| File.exist?(p) ? p : nil end end |
#image_exists(doc) ⇒ Object
17 18 19 20 21 22 23 24 |
# File 'lib/metanorma/validate/image.rb', line 17 def image_exists(doc) doc.xpath("//image[@src] | //altmedia[@src]").each do |i| Vectory::Utils::url?(i["src"]) and next Vectory::Utils::datauri?(i["src"]) and next (i["src"]) and next @log.add("STANDOC_44", i.parent, params: [i["src"]]) end end |
#image_toobig(doc) ⇒ Object
56 57 58 59 60 61 62 |
# File 'lib/metanorma/validate/image.rb', line 56 def image_toobig(doc) @dataurimaxsize.zero? and return doc.xpath("//image[@src]").each do |i| i["src"].size > @dataurimaxsize and @log.add("STANDOC_46", i.parent) end end |
#image_validate(doc) ⇒ Object
10 11 12 13 14 15 |
# File 'lib/metanorma/validate/image.rb', line 10 def image_validate(doc) image_exists(doc) image_toobig(doc) png_validate(doc) svg_validate(doc) end |
#png_validate(doc) ⇒ Object
33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/metanorma/validate/image.rb', line 33 def png_validate(doc) doc.xpath("//image[@mimetype = 'image/png'][@src]").each do |i| Vectory::Utils::url?(i["src"]) and next uri = Vectory::Utils::datauri?(i["src"]) path = uri ? save_dataimage(i["src"]) : (i["src"]) path or next PngConform::Readers::StreamingReader.open(path) do |reader| v = PngConform::Services::ValidationService.new(reader) png_validate1(i, path, v) end end end |
#png_validate1(img, _path, validator) ⇒ Object
46 47 48 49 50 51 52 53 54 |
# File 'lib/metanorma/validate/image.rb', line 46 def png_validate1(img, _path, validator) ret = validator.validate ret..each do |e| @log.add("STANDOC_45", img.parent, params: [e]) end ret.validation_result..each do |e| @log.add("STANDOC_63", img.parent, params: [e]) end end |
#save_dataimage(uri, _relative_dir = true) ⇒ Object
168 169 170 171 172 173 174 175 176 177 |
# File 'lib/metanorma/validate/image.rb', line 168 def save_dataimage(uri, _relative_dir = true) imgtype, imgdata = save_dataimage_prep(uri) Tempfile.open(["image", ".#{imgtype}"], mode: File::BINARY | File::SHARE_DELETE) do |f| f.binmode f.write(Base64.strict_decode64(imgdata)) @files_to_delete << f # persist to the end f.path end end |
#save_dataimage_prep(uri) ⇒ Object
179 180 181 182 183 184 185 186 |
# File 'lib/metanorma/validate/image.rb', line 179 def save_dataimage_prep(uri) %r{^data:(?:image|application)/(?<imgtype>[^;]+);(?:charset=[^;]+;)?base64,(?<imgdata>.+)$} =~ uri # imgtype = "emf" if emf?("#{imgclass}/#{imgtype}") imgtype = imgtype.sub(/\+[a-z0-9]+$/, "") # svg+xml imgtype = "png" unless /^[a-z0-9]+$/.match? imgtype imgtype == "postscript" and imgtype = "eps" [imgtype, imgdata] end |
#svg_error(id, svg, errors, options = {}) ⇒ Object
148 149 150 151 152 153 154 155 156 |
# File 'lib/metanorma/validate/image.rb', line 148 def svg_error(id, svg, errors, = {}) errors.each do |err| # reference violations are handled separately err.violation_type == :reference_violation and next elem, loc = svg_error_locations(err) @log.add(id, svg, params: [err.rule&.id, err., elem, loc], **) end end |
#svg_error_locations(err) ⇒ Object
158 159 160 161 162 163 164 165 166 |
# File 'lib/metanorma/validate/image.rb', line 158 def svg_error_locations(err) err.respond_to?(:element) && err.element and elem = " Element: #{err.element}" err.respond_to?(:location) && err.location and loc = " Location: #{err.location}" err.respond_to?(:node) && err.node.respond_to?(:path_id) and loc2 = " Location: #{err.node.path_id}" [elem, loc || loc2] end |
#svg_reference_violations(svg, result) ⇒ Object
Check for unresolved internal references
101 102 103 104 105 106 107 108 109 |
# File 'lib/metanorma/validate/image.rb', line 101 def svg_reference_violations(svg, result) result.unresolved_internal_references&.each do |ref| val = ref.value.sub(/^#/, "") @doc_ids.include?(val) and next @doc_anchors.include?(val) and next @log.add("STANDOC_59", svg, params: [ref.value, ref.line_number]) end end |
#svg_remed_log(remeds, svg) ⇒ Object
138 139 140 141 142 143 144 145 146 |
# File 'lib/metanorma/validate/image.rb', line 138 def svg_remed_log(remeds, svg) remeds.each do |e| e.changes_made.each do |c| @log.add("STANDOC_58", svg, params: [e.remediation_id, e., c[:type], c[:message], c[:node]]) end end end |
#svg_remediate(validator, profile, engine, svg, result) ⇒ Object
Apply remediation if needed
112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/metanorma/validate/image.rb', line 112 def svg_remediate(validator, profile, engine, svg, result) id = svg["id"] svg.delete("id") # cache will be tripped up by unique @id key = Digest::MD5.hexdigest(svg.to_xml) unless ret = @svg_remediation_cache[key] ret = svg_validate_fix(validator, profile, engine, svg, result) @svg_remediation_cache[key] = ret end svg.replace(ret.to_xml) svg["id"] = id end |
#svg_validate(doc) ⇒ Object
Use SAX for fast validation
65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/metanorma/validate/image.rb', line 65 def svg_validate(doc) profile = SvgConform::Profiles.get(@svg_conform_profile) validator = SvgConform::Validator.new(mode: :sax) engine = SvgConform::RemediationEngine.new(profile) @svg_remediation_cache = {} doc.xpath("//m:svg", "m" => SVG_NS).each do |svg_element| result = svg_validate1(validator, profile, svg_element) if profile.remediation_count.positive? && !result.valid? svg_remediate(validator, profile, engine, svg_element, result) end end end |
#svg_validate1(validator, profile, svg) ⇒ Object
79 80 81 82 83 84 85 |
# File 'lib/metanorma/validate/image.rb', line 79 def svg_validate1(validator, profile, svg) result = validator.validate(svg, profile: profile) svg_error("STANDOC_55", svg, result.errors, display: false) svg_error("STANDOC_57", svg, result.warnings, display: false) svg_reference_violations(svg, result) result end |
#svg_validate_fix(validator, profile, engine, svg, result) ⇒ Object
125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/metanorma/validate/image.rb', line 125 def svg_validate_fix(validator, profile, engine, svg, result) # Load DOM only for remediation doc = SvgConform::Document.from_content(svg.to_xml) remeds = engine.apply_remediations(doc, result) svg_remed_log(remeds, svg) # Use root to avoid processing instructions that may break SAX parser remediated_xml = doc.root result = validator.validate(remediated_xml.to_xml, profile: profile) svg_error("STANDOC_56", svg, result.errors) # we still have errors remediated_xml end |