FEATURE: improve support for (whitelisted) SVGs as images

This commit is contained in:
Régis Hanol 2016-06-20 10:22:13 +02:00
parent 41718be67f
commit 5e2545a578
4 changed files with 43 additions and 14 deletions

View File

@ -61,7 +61,7 @@ gem 'fast_xs'
gem 'fast_xor'
# while we sort out https://github.com/sdsykes/fastimage/pull/46
gem 'discourse_fastimage', '2.0.2', require: 'fastimage'
gem 'discourse_fastimage', '2.0.3', require: 'fastimage'
gem 'aws-sdk', require: false
gem 'excon', require: false
gem 'unf', require: false

View File

@ -73,7 +73,7 @@ GEM
diff-lcs (1.2.5)
discourse-qunit-rails (0.0.9)
railties
discourse_fastimage (2.0.2)
discourse_fastimage (2.0.3)
docile (1.1.5)
domain_name (0.5.25)
unf (>= 0.0.5, < 1.0.0)
@ -410,7 +410,7 @@ DEPENDENCIES
byebug
certified
discourse-qunit-rails
discourse_fastimage (= 2.0.2)
discourse_fastimage (= 2.0.3)
email_reply_trimmer (= 0.1.3)
ember-rails (= 0.18.5)
ember-source (= 1.12.2)

View File

@ -59,6 +59,32 @@ class Upload < ActiveRecord::Base
# list of image types that will be cropped
CROPPED_IMAGE_TYPES ||= %w{avatar profile_background card_background}
WHITELISTED_SVG_ELEMENTS ||= %w{
circle
clippath
defs
ellipse
g
line
linearGradient
path
polygon
polyline
radialGradient
rect
stop
svg
text
textpath
tref
tspan
use
}
def self.svg_whitelist_xpath
@@svg_whitelist_xpath ||= "//*[#{WHITELISTED_SVG_ELEMENTS.map { |e| "name()!='#{e}'" }.join(" and ") }]"
end
# options
# - content_type
# - origin (url)
@ -68,18 +94,21 @@ class Upload < ActiveRecord::Base
DistributedMutex.synchronize("upload_#{user_id}_#{filename}") do
# do some work on images
if FileHelper.is_image?(filename) && is_actual_image?(file)
if filename =~ /\.svg$/i
svg = Nokogiri::XML(file).at_css("svg")
w = svg["width"].to_i
h = svg["height"].to_i
if filename[/\.svg$/i]
# whitelist svg elements
doc = Nokogiri::XML(file)
doc.xpath(svg_whitelist_xpath).remove
File.write(file.path, doc.to_s)
file.rewind
else
# fix orientation first
fix_image_orientation(file.path) if should_optimize?(file.path)
# retrieve image info
image_info = FastImage.new(file) rescue nil
w, h = *(image_info.try(:size) || [0, 0])
end
# retrieve image info
image_info = FastImage.new(file)
w, h = *(image_info.try(:size) || [0, 0])
# default size
width, height = ImageSizer.resize(w, h)
@ -107,7 +136,7 @@ class Upload < ActiveRecord::Base
end
end
# optimize image (except GIFs and large PNGs)
# optimize image (except GIFs, SVGs and large PNGs)
if should_optimize?(file.path)
ImageOptim.new.optimize_image!(file.path) rescue nil
# update the file size
@ -178,8 +207,8 @@ class Upload < ActiveRecord::Base
LARGE_PNG_SIZE ||= 3.megabytes
def self.should_optimize?(path)
# don't optimize GIFs
return false if path =~ /\.gif$/i
# don't optimize GIFs or SVGs
return false if path =~ /\.(gif|svg)$/i
return true if path !~ /\.png$/i
image_info = FastImage.new(path) rescue nil
w, h = *(image_info.try(:size) || [0, 0])

View File

@ -157,7 +157,7 @@ server {
try_files $uri =404;
}
# this allows us to bypass rails
location ~* \.(gif|png|jpg|jpeg|bmp|tif|tiff)$ {
location ~* \.(gif|png|jpg|jpeg|bmp|tif|tiff|svg)$ {
try_files $uri =404;
}
# thumbnails & optimized images