DEV: Make `CookedPostProcessor#post_process_images` method private.

This commit is contained in:
Guo Xiang Tan 2019-05-27 11:28:37 +08:00
parent baf7eac704
commit f54e4b71b1
2 changed files with 378 additions and 385 deletions

View File

@ -65,15 +65,6 @@ class CookedPostProcessor
BadgeGranter.grant(Badge.find(Badge::FirstReplyByEmail), @post.user, post_id: @post.id) if @post.is_reply_by_email?
end
def post_process_images
extract_images.each do |img|
unless add_image_placeholder!(img)
limit_size!(img)
convert_to_link!(img)
end
end
end
def post_process_quotes
@doc.css("aside.quote").each do |q|
post_number = q['data-post']
@ -688,6 +679,15 @@ class CookedPostProcessor
private
def post_process_images
extract_images.each do |img|
unless add_image_placeholder!(img)
limit_size!(img)
convert_to_link!(img)
end
end
end
def process_inline_onebox(element)
inline_onebox = InlineOneboxer.lookup(
element.attributes["href"].value,

View File

@ -6,11 +6,7 @@ require "file_store/s3_store"
describe CookedPostProcessor do
context "#post_process" do
fab!(:upload) do
Fabricate(:upload,
url: '/uploads/default/original/1X/1/1234567890123456.jpg'
)
end
fab!(:upload) { Fabricate(:upload) }
fab!(:post) do
Fabricate(:post, raw: <<~RAW)
@ -254,409 +250,408 @@ describe CookedPostProcessor do
end
end
end
end
context "#post_process_images" do
before do
SiteSetting.responsive_post_image_sizes = ""
end
context "responsive images" do
before { SiteSetting.responsive_post_image_sizes = "1|1.5|3" }
it "includes responsive images on demand" do
upload = Fabricate(:upload, width: 2000, height: 1500, filesize: 10000)
post = Fabricate(:post, raw: "hello <img src='#{upload.url}'>")
# fake some optimized images
OptimizedImage.create!(
url: '/uploads/default/666x500.jpg',
width: 666,
height: 500,
upload_id: upload.id,
sha1: SecureRandom.hex,
extension: '.jpg',
filesize: 500,
version: OptimizedImage::VERSION
)
# fake 3x optimized image, we lose 2 pixels here over original due to rounding on downsize
OptimizedImage.create!(
url: '/uploads/default/1998x1500.jpg',
width: 1998,
height: 1500,
upload_id: upload.id,
sha1: SecureRandom.hex,
extension: '.jpg',
filesize: 800
)
# Fake a loading image
optimized_image = OptimizedImage.create!(
url: '/uploads/default/10x10.png',
width: CookedPostProcessor::LOADING_SIZE,
height: CookedPostProcessor::LOADING_SIZE,
upload_id: upload.id,
sha1: SecureRandom.hex,
extension: '.png',
filesize: 123
)
cpp = CookedPostProcessor.new(post)
cpp.add_to_size_cache(upload.url, 2000, 1500)
cpp.post_process_images
cpp.optimize_urls
html = cpp.html
expect(html).to include(%Q|data-small-upload="//test.localhost/uploads/default/10x10.png"|)
# 1.5x is skipped cause we have a missing thumb
expect(html).to include('srcset="//test.localhost/uploads/default/666x500.jpg, //test.localhost/uploads/default/1998x1500.jpg 3x"')
expect(html).to include('src="//test.localhost/uploads/default/666x500.jpg"')
# works with CDN
set_cdn_url("http://cdn.localhost")
cpp = CookedPostProcessor.new(post)
cpp.add_to_size_cache(upload.url, 2000, 1500)
cpp.post_process_images
cpp.optimize_urls
html = cpp.html
expect(html).to include(%Q|data-small-upload="//cdn.localhost/uploads/default/10x10.png"|)
expect(html).to include('srcset="//cdn.localhost/uploads/default/666x500.jpg, //cdn.localhost/uploads/default/1998x1500.jpg 3x"')
expect(html).to include('src="//cdn.localhost/uploads/default/666x500.jpg"')
end
it "doesn't include response images for cropped images" do
upload = Fabricate(:upload, width: 200, height: 4000, filesize: 12345)
post = Fabricate(:post, raw: "hello <img src='#{upload.url}'>")
# fake some optimized images
OptimizedImage.create!(
url: 'http://a.b.c/200x500.jpg',
width: 200,
height: 500,
upload_id: upload.id,
sha1: SecureRandom.hex,
extension: '.jpg',
filesize: 500
)
cpp = CookedPostProcessor.new(post)
cpp.add_to_size_cache(upload.url, 200, 4000)
cpp.post_process_images
cpp.optimize_urls
expect(cpp.html).to_not include('srcset="')
end
end
shared_examples "leave dimensions alone" do
it "doesn't use them" do
expect(cpp.html).to match(/src="http:\/\/foo.bar\/image.png" width="" height=""/)
expect(cpp.html).to match(/src="http:\/\/domain.com\/picture.jpg" width="50" height="42"/)
expect(cpp).to be_dirty
end
end
context "with image_sizes" do
fab!(:post) { Fabricate(:post_with_image_urls) }
let(:cpp) { CookedPostProcessor.new(post, image_sizes: image_sizes) }
context "processing images" do
before do
cpp.post_process_images
cpp.optimize_urls
SiteSetting.responsive_post_image_sizes = ""
end
context "valid" do
let(:image_sizes) { { "http://foo.bar/image.png" => { "width" => 111, "height" => 222 } } }
context "responsive images" do
before { SiteSetting.responsive_post_image_sizes = "1|1.5|3" }
it "uses them" do
expect(cpp.html).to match(/src="http:\/\/foo.bar\/image.png" width="111" height="222"/)
it "includes responsive images on demand" do
upload = Fabricate(:upload, width: 2000, height: 1500, filesize: 10000)
post = Fabricate(:post, raw: "hello <img src='#{upload.url}'>")
# fake some optimized images
OptimizedImage.create!(
url: '/uploads/default/666x500.jpg',
width: 666,
height: 500,
upload_id: upload.id,
sha1: SecureRandom.hex,
extension: '.jpg',
filesize: 500,
version: OptimizedImage::VERSION
)
# fake 3x optimized image, we lose 2 pixels here over original due to rounding on downsize
OptimizedImage.create!(
url: '/uploads/default/1998x1500.jpg',
width: 1998,
height: 1500,
upload_id: upload.id,
sha1: SecureRandom.hex,
extension: '.jpg',
filesize: 800
)
# Fake a loading image
optimized_image = OptimizedImage.create!(
url: '/uploads/default/10x10.png',
width: CookedPostProcessor::LOADING_SIZE,
height: CookedPostProcessor::LOADING_SIZE,
upload_id: upload.id,
sha1: SecureRandom.hex,
extension: '.png',
filesize: 123
)
cpp = CookedPostProcessor.new(post)
cpp.add_to_size_cache(upload.url, 2000, 1500)
cpp.post_process
html = cpp.html
expect(html).to include(%Q|data-small-upload="//test.localhost/uploads/default/10x10.png"|)
# 1.5x is skipped cause we have a missing thumb
expect(html).to include('srcset="//test.localhost/uploads/default/666x500.jpg, //test.localhost/uploads/default/1998x1500.jpg 3x"')
expect(html).to include('src="//test.localhost/uploads/default/666x500.jpg"')
# works with CDN
set_cdn_url("http://cdn.localhost")
cpp = CookedPostProcessor.new(post)
cpp.add_to_size_cache(upload.url, 2000, 1500)
cpp.post_process
html = cpp.html
expect(html).to include(%Q|data-small-upload="//cdn.localhost/uploads/default/10x10.png"|)
expect(html).to include('srcset="//cdn.localhost/uploads/default/666x500.jpg, //cdn.localhost/uploads/default/1998x1500.jpg 3x"')
expect(html).to include('src="//cdn.localhost/uploads/default/666x500.jpg"')
end
it "doesn't include response images for cropped images" do
upload = Fabricate(:upload, width: 200, height: 4000, filesize: 12345)
post = Fabricate(:post, raw: "hello <img src='#{upload.url}'>")
# fake some optimized images
OptimizedImage.create!(
url: 'http://a.b.c/200x500.jpg',
width: 200,
height: 500,
upload_id: upload.id,
sha1: SecureRandom.hex,
extension: '.jpg',
filesize: 500
)
cpp = CookedPostProcessor.new(post)
cpp.add_to_size_cache(upload.url, 200, 4000)
cpp.post_process
expect(cpp.html).to_not include('srcset="')
end
end
shared_examples "leave dimensions alone" do
it "doesn't use them" do
expect(cpp.html).to match(/src="http:\/\/foo.bar\/image.png" width="" height=""/)
expect(cpp.html).to match(/src="http:\/\/domain.com\/picture.jpg" width="50" height="42"/)
expect(cpp).to be_dirty
end
end
context "invalid width" do
let(:image_sizes) { { "http://foo.bar/image.png" => { "width" => 0, "height" => 222 } } }
include_examples "leave dimensions alone"
end
context "invalid height" do
let(:image_sizes) { { "http://foo.bar/image.png" => { "width" => 111, "height" => 0 } } }
include_examples "leave dimensions alone"
end
context "invalid width & height" do
let(:image_sizes) { { "http://foo.bar/image.png" => { "width" => 0, "height" => 0 } } }
include_examples "leave dimensions alone"
end
end
context "with unsized images" do
fab!(:post) { Fabricate(:post_with_unsized_images) }
let(:cpp) { CookedPostProcessor.new(post) }
it "adds the width and height to images that don't have them" do
FastImage.expects(:size).returns([123, 456])
cpp.post_process_images
expect(cpp.html).to match(/width="123" height="456"/)
expect(cpp).to be_dirty
end
end
context "with large images" do
fab!(:upload) { Fabricate(:upload) }
fab!(:post) { Fabricate(:post_with_large_image) }
let(:cpp) { CookedPostProcessor.new(post, disable_loading_image: true) }
before do
SiteSetting.max_image_height = 2000
SiteSetting.create_thumbnails = true
FastImage.expects(:size).returns([1750, 2000])
end
it "generates overlay information" do
Upload.expects(:get_from_url).returns(upload)
OptimizedImage.expects(:resize).returns(true)
FileStore::BaseStore.any_instance.expects(:get_depth_for).returns(0)
cpp.post_process_images
cpp.optimize_urls
expect(cpp.html).to match_html <<~HTML
<p><div class="lightbox-wrapper"><a class="lightbox" href="//test.localhost/uploads/default/original/1X/1234567890123456.jpg" data-download-href="//test.localhost/uploads/default/#{upload.sha1}" title="logo.png"><img src="//test.localhost/uploads/default/optimized/1X/#{upload.sha1}_#{OptimizedImage::VERSION}_690x788.png" width="690" height="788"><div class="meta">
<svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use xlink:href="#far-image"></use></svg><span class="filename">logo.png</span><span class="informations">1750×2000 1.21 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use xlink:href="#discourse-expand"></use></svg>
</div></a></div></p>
HTML
expect(cpp).to be_dirty
end
describe 'when image is inside onebox' do
let(:url) { 'https://image.com/my-avatar' }
let(:post) { Fabricate(:post, raw: url) }
context "with image_sizes" do
fab!(:post) { Fabricate(:post_with_image_urls) }
let(:cpp) { CookedPostProcessor.new(post, image_sizes: image_sizes) }
before do
Oneboxer.stubs(:onebox).with(url, anything).returns("<img class='onebox' src='/uploads/default/original/1X/1234567890123456.jpg' />")
cpp.post_process
end
it 'should not add lightbox' do
cpp.post_process_oneboxes
cpp.post_process_images
cpp.optimize_urls
context "valid" do
let(:image_sizes) { { "http://foo.bar/image.png" => { "width" => 111, "height" => 222 } } }
expect(cpp.html).to match_html <<~HTML
<p><img class="onebox" src="//test.localhost/uploads/default/original/1X/1234567890123456.jpg" width="690" height="788"></p>
HTML
it "uses them" do
expect(cpp.html).to match(/src="http:\/\/foo.bar\/image.png" width="111" height="222"/)
expect(cpp.html).to match(/src="http:\/\/domain.com\/picture.jpg" width="50" height="42"/)
expect(cpp).to be_dirty
end
end
context "invalid width" do
let(:image_sizes) { { "http://foo.bar/image.png" => { "width" => 0, "height" => 222 } } }
include_examples "leave dimensions alone"
end
context "invalid height" do
let(:image_sizes) { { "http://foo.bar/image.png" => { "width" => 111, "height" => 0 } } }
include_examples "leave dimensions alone"
end
context "invalid width & height" do
let(:image_sizes) { { "http://foo.bar/image.png" => { "width" => 0, "height" => 0 } } }
include_examples "leave dimensions alone"
end
end
describe 'when image is an svg' do
fab!(:post) do
Fabricate(:post, raw: '<img src="/uploads/default/original/1X/1234567890123456.svg">')
context "with unsized images" do
fab!(:post) { Fabricate(:post_with_unsized_images) }
let(:cpp) { CookedPostProcessor.new(post) }
it "adds the width and height to images that don't have them" do
FastImage.expects(:size).returns([123, 456])
cpp.post_process
expect(cpp.html).to match(/width="123" height="456"/)
expect(cpp).to be_dirty
end
it 'should not add lightbox' do
cpp.post_process_images
cpp.optimize_urls
end
expect(cpp.html).to match_html <<~HTML
<p><img src="//test.localhost/uploads/default/original/1X/1234567890123456.svg" width="690" height="788"></p>
context "with large images" do
fab!(:upload) { Fabricate(:upload) }
fab!(:post) do
Fabricate(:post, raw: <<~HTML)
<img src="#{upload.url}">
HTML
end
describe 'when image src is an URL' do
let(:post) do
Fabricate(:post, raw: '<img src="http://test.discourse/uploads/default/original/1X/1234567890123456.svg?somepamas">')
let(:cpp) { CookedPostProcessor.new(post, disable_loading_image: true) }
before do
SiteSetting.max_image_height = 2000
SiteSetting.create_thumbnails = true
FastImage.expects(:size).returns([1750, 2000])
end
it "generates overlay information" do
OptimizedImage.expects(:resize).returns(true)
FileStore::BaseStore.any_instance.expects(:get_depth_for).returns(0)
cpp.post_process
expect(cpp.html).to match_html <<~HTML
<p><div class="lightbox-wrapper"><a class="lightbox" href="//test.localhost#{upload.url}" data-download-href="//test.localhost/uploads/default/#{upload.sha1}" title="logo.png"><img src="//test.localhost/uploads/default/optimized/1X/#{upload.sha1}_#{OptimizedImage::VERSION}_690x788.png" width="690" height="788"><div class="meta">
<svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use xlink:href="#far-image"></use></svg><span class="filename">logo.png</span><span class="informations">1750×2000 1.21 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use xlink:href="#discourse-expand"></use></svg>
</div></a></div></p>
HTML
expect(cpp).to be_dirty
end
describe 'when image is inside onebox' do
let(:url) { 'https://image.com/my-avatar' }
let(:post) { Fabricate(:post, raw: url) }
before do
Oneboxer.stubs(:onebox).with(url, anything).returns("<img class='onebox' src='/uploads/default/original/1X/1234567890123456.jpg' />")
end
it 'should not add lightbox' do
SiteSetting.crawl_images = true
cpp.post_process_images
cpp.optimize_urls
cpp.post_process
expect(cpp.html).to match_html("<p><img src=\"http://test.discourse/uploads/default/original/1X/1234567890123456.svg?somepamas\" width=\"690\"\ height=\"788\"></p>")
expect(cpp.html).to match_html <<~HTML
<p><img class="onebox" src="//test.localhost/uploads/default/original/1X/1234567890123456.jpg" width="690" height="788"></p>
HTML
end
end
describe 'when image is an svg' do
fab!(:post) do
Fabricate(:post, raw: '<img src="/uploads/default/original/1X/1234567890123456.svg">')
end
it 'should not add lightbox' do
cpp.post_process
expect(cpp.html).to match_html <<~HTML
<p><img src="//test.localhost/uploads/default/original/1X/1234567890123456.svg" width="690" height="788"></p>
HTML
end
describe 'when image src is an URL' do
let(:post) do
Fabricate(:post, raw: '<img src="http://test.discourse/uploads/default/original/1X/1234567890123456.svg?somepamas">')
end
it 'should not add lightbox' do
SiteSetting.crawl_images = true
cpp.post_process
expect(cpp.html).to match_html("<p><img src=\"http://test.discourse/uploads/default/original/1X/1234567890123456.svg?somepamas\" width=\"690\"\ height=\"788\"></p>")
end
end
end
end
context "with tall images" do
fab!(:upload) { Fabricate(:upload) }
fab!(:post) do
Fabricate(:post, raw: <<~HTML)
<img src="#{upload.url}">
HTML
end
let(:cpp) { CookedPostProcessor.new(post, disable_loading_image: true) }
before do
SiteSetting.create_thumbnails = true
FastImage.expects(:size).returns([860, 2000])
OptimizedImage.expects(:resize).never
OptimizedImage.expects(:crop).returns(true)
FileStore::BaseStore.any_instance.expects(:get_depth_for).returns(0)
end
it "crops the image" do
cpp.post_process
expect(cpp.html).to match(/width="690" height="500">/)
expect(cpp).to be_dirty
end
end
context "with iPhone X screenshots" do
fab!(:upload) { Fabricate(:upload) }
fab!(:post) do
Fabricate(:post, raw: <<~HTML)
<img src="#{upload.url}">
HTML
end
let(:cpp) { CookedPostProcessor.new(post, disable_loading_image: true) }
before do
SiteSetting.create_thumbnails = true
FastImage.expects(:size).returns([1125, 2436])
OptimizedImage.expects(:resize).returns(true)
OptimizedImage.expects(:crop).never
FileStore::BaseStore.any_instance.expects(:get_depth_for).returns(0)
end
it "crops the image" do
cpp.post_process
expect(cpp.html).to match_html <<~HTML
<p><div class="lightbox-wrapper"><a class="lightbox" href="//test.localhost#{upload.url}" data-download-href="//test.localhost/uploads/default/#{upload.sha1}" title="logo.png"><img src="//test.localhost/uploads/default/optimized/1X/#{upload.sha1}_#{OptimizedImage::VERSION}_230x500.png" width="230" height="500"><div class="meta">
<svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use xlink:href="#far-image"></use></svg><span class="filename">logo.png</span><span class="informations">1125×2436 1.21 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use xlink:href="#discourse-expand"></use></svg>
</div></a></div></p>
HTML
expect(cpp).to be_dirty
end
end
context "with large images when using subfolders" do
fab!(:upload) { Fabricate(:upload) }
fab!(:post) do
Fabricate(:post, raw: <<~HTML)
<img src="/subfolder#{upload.url}">
HTML
end
let(:cpp) { CookedPostProcessor.new(post, disable_loading_image: true) }
let(:base_url) { "http://test.localhost/subfolder" }
let(:base_uri) { "/subfolder" }
before do
SiteSetting.max_image_height = 2000
SiteSetting.create_thumbnails = true
Discourse.stubs(:base_url).returns(base_url)
Discourse.stubs(:base_uri).returns(base_uri)
FastImage.expects(:size).returns([1750, 2000])
OptimizedImage.expects(:resize).returns(true)
FileStore::BaseStore.any_instance.expects(:get_depth_for).returns(0)
end
it "generates overlay information" do
cpp.post_process
expect(cpp.html). to match_html <<~HTML
<p><div class="lightbox-wrapper"><a class="lightbox" href="//test.localhost/subfolder#{upload.url}" data-download-href="//test.localhost/subfolder/uploads/default/#{upload.sha1}" title="logo.png"><img src="//test.localhost/subfolder/uploads/default/optimized/1X/#{upload.sha1}_#{OptimizedImage::VERSION}_690x788.png" width="690" height="788"><div class="meta">
<svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use xlink:href="#far-image"></use></svg><span class="filename">logo.png</span><span class="informations">1750×2000 1.21 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use xlink:href="#discourse-expand"></use></svg>
</div></a></div></p>
HTML
expect(cpp).to be_dirty
end
it "should escape the filename" do
upload.update!(original_filename: "><img src=x onerror=alert('haha')>.png")
cpp.post_process
expect(cpp.html).to match_html <<~HTML
<p><div class="lightbox-wrapper"><a class="lightbox" href="//test.localhost/subfolder#{upload.url}" data-download-href="//test.localhost/subfolder/uploads/default/#{upload.sha1}" title="&amp;gt;&amp;lt;img src=x onerror=alert(&amp;#39;haha&amp;#39;)&amp;gt;.png"><img src="//test.localhost/subfolder/uploads/default/optimized/1X/#{upload.sha1}_#{OptimizedImage::VERSION}_690x788.png" width="690" height="788"><div class="meta">
<svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use xlink:href="#far-image"></use></svg><span class="filename">&amp;gt;&amp;lt;img src=x onerror=alert(&amp;#39;haha&amp;#39;)&amp;gt;.png</span><span class="informations">1750×2000 1.21 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use xlink:href="#discourse-expand"></use></svg>
</div></a></div></p>
HTML
end
end
context "with title" do
fab!(:upload) { Fabricate(:upload) }
fab!(:post) do
Fabricate(:post, raw: <<~HTML)
<img src="#{upload.url}" title="WAT">
HTML
end
let(:cpp) { CookedPostProcessor.new(post, disable_loading_image: true) }
before do
SiteSetting.max_image_height = 2000
SiteSetting.create_thumbnails = true
FastImage.expects(:size).returns([1750, 2000])
OptimizedImage.expects(:resize).returns(true)
FileStore::BaseStore.any_instance.expects(:get_depth_for).returns(0)
end
it "generates overlay information" do
cpp.post_process
expect(cpp.html).to match_html <<~HTML
<p><div class="lightbox-wrapper"><a class="lightbox" href="//test.localhost#{upload.url}" data-download-href="//test.localhost/uploads/default/#{upload.sha1}" title="WAT"><img src="//test.localhost/uploads/default/optimized/1X/#{upload.sha1}_#{OptimizedImage::VERSION}_690x788.png" title="WAT" width="690" height="788"><div class="meta">
<svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use xlink:href="#far-image"></use></svg><span class="filename">WAT</span><span class="informations">1750×2000 1.21 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use xlink:href="#discourse-expand"></use></svg>
</div></a></div></p>
HTML
expect(cpp).to be_dirty
end
end
context "topic image" do
let(:topic) { build(:topic, id: 1) }
let(:post) { Fabricate(:post_with_uploaded_image, topic: topic) }
let(:cpp) { CookedPostProcessor.new(post) }
it "adds a topic image if there's one in the first post" do
FastImage.stubs(:size)
expect(post.topic.image_url).to eq(nil)
cpp.post_process
post.topic.reload
expect(post.topic.image_url).to be_present
end
end
end
context "post image" do
let(:reply) { Fabricate(:post_with_uploaded_image, post_number: 2) }
let(:cpp) { CookedPostProcessor.new(reply) }
context "with tall images" do
let(:upload) { Fabricate(:upload) }
let(:post) { Fabricate(:post_with_large_image) }
let(:cpp) { CookedPostProcessor.new(post, disable_loading_image: true) }
before do
SiteSetting.create_thumbnails = true
Upload.expects(:get_from_url).returns(upload)
FastImage.expects(:size).returns([860, 2000])
OptimizedImage.expects(:resize).never
OptimizedImage.expects(:crop).returns(true)
FileStore::BaseStore.any_instance.expects(:get_depth_for).returns(0)
end
it "crops the image" do
cpp.post_process_images
expect(cpp.html).to match(/width="690" height="500">/)
expect(cpp).to be_dirty
end
end
context "with iPhone X screenshots" do
let(:upload) { Fabricate(:upload) }
let(:post) { Fabricate(:post_with_large_image) }
let(:cpp) { CookedPostProcessor.new(post, disable_loading_image: true) }
before do
SiteSetting.create_thumbnails = true
Upload.expects(:get_from_url).returns(upload)
FastImage.expects(:size).returns([1125, 2436])
OptimizedImage.expects(:resize).returns(true)
OptimizedImage.expects(:crop).never
FileStore::BaseStore.any_instance.expects(:get_depth_for).returns(0)
end
it "crops the image" do
cpp.post_process_images
cpp.optimize_urls
expect(cpp.html).to match_html <<~HTML
<p><div class="lightbox-wrapper"><a class="lightbox" href="//test.localhost/uploads/default/original/1X/1234567890123456.jpg" data-download-href="//test.localhost/uploads/default/#{upload.sha1}" title="logo.png"><img src="//test.localhost/uploads/default/optimized/1X/#{upload.sha1}_#{OptimizedImage::VERSION}_230x500.png" width="230" height="500"><div class="meta">
<svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use xlink:href="#far-image"></use></svg><span class="filename">logo.png</span><span class="informations">1125×2436 1.21 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use xlink:href="#discourse-expand"></use></svg>
</div></a></div></p>
HTML
expect(cpp).to be_dirty
end
end
context "with large images when using subfolders" do
fab!(:upload) { Fabricate(:upload) }
fab!(:post) { Fabricate(:post_with_large_image_on_subfolder) }
let(:cpp) { CookedPostProcessor.new(post, disable_loading_image: true) }
let(:base_url) { "http://test.localhost/subfolder" }
let(:base_uri) { "/subfolder" }
before do
SiteSetting.max_image_height = 2000
SiteSetting.create_thumbnails = true
Discourse.stubs(:base_url).returns(base_url)
Discourse.stubs(:base_uri).returns(base_uri)
Upload.expects(:get_from_url).returns(upload)
FastImage.expects(:size).returns([1750, 2000])
OptimizedImage.expects(:resize).returns(true)
FileStore::BaseStore.any_instance.expects(:get_depth_for).returns(0)
end
it "generates overlay information" do
cpp.post_process_images
cpp.optimize_urls
expect(cpp.html). to match_html <<~HTML
<p><div class="lightbox-wrapper"><a class="lightbox" href="//test.localhost/subfolder/uploads/default/original/1X/1234567890123456.jpg" data-download-href="//test.localhost/subfolder/uploads/default/#{upload.sha1}" title="logo.png"><img src="//test.localhost/subfolder/uploads/default/optimized/1X/#{upload.sha1}_#{OptimizedImage::VERSION}_690x788.png" width="690" height="788"><div class="meta">
<svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use xlink:href="#far-image"></use></svg><span class="filename">logo.png</span><span class="informations">1750×2000 1.21 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use xlink:href="#discourse-expand"></use></svg>
</div></a></div></p>
HTML
expect(cpp).to be_dirty
end
it "should escape the filename" do
upload.update!(original_filename: "><img src=x onerror=alert('haha')>.png")
cpp.post_process_images
cpp.optimize_urls
expect(cpp.html).to match_html <<~HTML
<p><div class="lightbox-wrapper"><a class="lightbox" href="//test.localhost/subfolder/uploads/default/original/1X/1234567890123456.jpg" data-download-href="//test.localhost/subfolder/uploads/default/#{upload.sha1}" title="&amp;gt;&amp;lt;img src=x onerror=alert(&amp;#39;haha&amp;#39;)&amp;gt;.png"><img src="//test.localhost/subfolder/uploads/default/optimized/1X/#{upload.sha1}_#{OptimizedImage::VERSION}_690x788.png" width="690" height="788"><div class="meta">
<svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use xlink:href="#far-image"></use></svg><span class="filename">&amp;gt;&amp;lt;img src=x onerror=alert(&amp;#39;haha&amp;#39;)&amp;gt;.png</span><span class="informations">1750×2000 1.21 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use xlink:href="#discourse-expand"></use></svg>
</div></a></div></p>
HTML
end
end
context "with title" do
let(:upload) { Fabricate(:upload) }
let(:post) { Fabricate(:post_with_large_image_and_title) }
let(:cpp) { CookedPostProcessor.new(post, disable_loading_image: true) }
before do
SiteSetting.max_image_height = 2000
SiteSetting.create_thumbnails = true
Upload.expects(:get_from_url).returns(upload)
FastImage.expects(:size).returns([1750, 2000])
OptimizedImage.expects(:resize).returns(true)
FileStore::BaseStore.any_instance.expects(:get_depth_for).returns(0)
end
it "generates overlay information" do
cpp.post_process_images
cpp.optimize_urls
expect(cpp.html).to match_html <<~HTML
<p><div class="lightbox-wrapper"><a class="lightbox" href="//test.localhost/uploads/default/original/1X/1234567890123456.jpg" data-download-href="//test.localhost/uploads/default/#{upload.sha1}" title="WAT"><img src="//test.localhost/uploads/default/optimized/1X/#{upload.sha1}_#{OptimizedImage::VERSION}_690x788.png" title="WAT" width="690" height="788"><div class="meta">
<svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use xlink:href="#far-image"></use></svg><span class="filename">WAT</span><span class="informations">1750×2000 1.21 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use xlink:href="#discourse-expand"></use></svg>
</div></a></div></p>
HTML
expect(cpp).to be_dirty
end
end
context "topic image" do
let(:topic) { build(:topic, id: 1) }
let(:post) { Fabricate(:post_with_uploaded_image, topic: topic) }
let(:cpp) { CookedPostProcessor.new(post) }
it "adds a topic image if there's one in the first post" do
FastImage.stubs(:size)
expect(post.topic.image_url).to eq(nil)
cpp.update_post_image
post.topic.reload
expect(post.topic.image_url).to be_present
it "adds a post image if there's one in the post" do
FastImage.stubs(:size)
expect(reply.image_url).to eq(nil)
cpp.post_process
reply.reload
expect(reply.image_url).to be_present
end
end
end
context "post image" do
let(:reply) { Fabricate(:post_with_uploaded_image, post_number: 2) }
let(:cpp) { CookedPostProcessor.new(reply) }
it "adds a post image if there's one in the post" do
FastImage.stubs(:size)
expect(reply.image_url).to eq(nil)
cpp.update_post_image
reply.reload
expect(reply.image_url).to be_present
end
end
end
context "#extract_images" do
@ -867,9 +862,7 @@ describe CookedPostProcessor do
post.save_custom_fields
cpp = CookedPostProcessor.new(post, invalidate_oneboxes: true)
cpp.post_process_oneboxes
cpp.post_process_images
cpp.optimize_urls
cpp.post_process
expect(cpp.doc.to_s).to match(/<div class="large-image-placeholder">/)
end