Commit 98e54053 authored by Rémy Coutable's avatar Rémy Coutable

Use a more powerful query to match videos in img tags

Also, always add a link to download videos since video playback is
tricky. Also, it solves the issue with email client not supporting
videos.
Signed-off-by: default avatarRémy Coutable <remy@rymai.me>
parent 29ea8d09
...@@ -8,8 +8,8 @@ module Banzai ...@@ -8,8 +8,8 @@ module Banzai
include ActionView::Context include ActionView::Context
def call def call
doc.search('img').each do |el| doc.xpath(query).each do |el|
el.replace(video_tag(doc, el)) if video?(el) el.replace(video_node(doc, el))
end end
doc doc
...@@ -17,19 +17,44 @@ module Banzai ...@@ -17,19 +17,44 @@ module Banzai
private private
def video?(element) def query
extension = File.extname(element.attribute('src').value).delete('.') @query ||= begin
UploaderHelper::VIDEO_EXT.include?(extension) src_query = UploaderHelper::VIDEO_EXT.map do |ext|
"'.#{ext}' = substring(@src, string-length(@src) - #{ext.size})"
end
"descendant-or-self::img[not(ancestor::a) and (#{src_query.join(' or ')})]"
end
end end
# Return a video tag Nokogiri node # Return a video tag Nokogiri node
# #
def video_node(doc, element) def video_node(doc, element)
doc.document.create_element( container = doc.document.create_element(
'div',
class: 'video-container'
)
video = doc.document.create_element(
'video', 'video',
src: element.attribute('src').value, src: element['src'],
class: 'video-js', class: 'video-js vjs-sublime-skin',
controls: true) controls: true,
"data-setup": '{}')
link = doc.document.create_element(
'a',
element['title'] || element['alt'],
href: element['src'],
target: '_blank',
title: "Downlad '#{element['title'] || element['alt']}'")
download_paragraph = doc.document.create_element('p')
download_paragraph.children = link
container.add_child(video)
container.add_child(download_paragraph)
container
end end
end end
......
...@@ -7,8 +7,8 @@ module Banzai ...@@ -7,8 +7,8 @@ module Banzai
Filter::SanitizationFilter, Filter::SanitizationFilter,
Filter::UploadLinkFilter, Filter::UploadLinkFilter,
Filter::ImageLinkFilter,
Filter::VideoLinkFilter, Filter::VideoLinkFilter,
Filter::ImageLinkFilter,
Filter::EmojiFilter, Filter::EmojiFilter,
Filter::TableOfContentsFilter, Filter::TableOfContentsFilter,
Filter::AutolinkFilter, Filter::AutolinkFilter,
......
...@@ -9,28 +9,34 @@ describe Banzai::Filter::VideoLinkFilter, lib: true do ...@@ -9,28 +9,34 @@ describe Banzai::Filter::VideoLinkFilter, lib: true do
described_class.call(doc, contexts) described_class.call(doc, contexts)
end end
def image(path) def link_to_image(path)
%(<img src="#{path}" />) %(<img src="#{path}" />)
end end
let(:project) { create(:project) } let(:project) { create(:project) }
context 'when the element src has a video extension' do context 'when the element src has a video extension' do
it 'replaces the image tag with a video tag' do UploaderHelper::VIDEO_EXT.each do |ext|
doc = filter(image("/path/video.mov")) it "replaces the image tag 'path/video.#{ext}' with a video tag" do
element = doc.children.first element = filter(link_to_image("/path/video.#{ext}")).children.first
expect(element.name).to eq( "video" )
expect(element['src']).to eq( "/path/video.mov" ) expect(element.name).to eq 'video'
expect(element['src']).to eq "/path/video.#{ext}"
fallback_link = element.children.first
expect(fallback_link.name).to eq 'a'
expect(fallback_link['href']).to eq "/path/video.#{ext}"
expect(fallback_link['target']).to eq '_blank'
end
end end
end end
context 'when the element src is an image' do context 'when the element src is an image' do
it 'leaves the document unchanged' do it 'leaves the document unchanged' do
doc = filter(image("/path/my_image.jpg")) element = filter(link_to_image("/path/my_image.jpg")).children.first
element = doc.children.first
expect(element.name).to eq( "img" ) expect(element.name).to eq 'img'
end end
end end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment