68 lines
2.0 KiB
Ruby
68 lines
2.0 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# Generated HTML is transformed back to GFM by app/assets/javascripts/behaviors/markdown/nodes/video.js
|
|
module Banzai
|
|
module Filter
|
|
# Find every image that isn't already wrapped in an `a` tag, and that has
|
|
# a `src` attribute ending with a video extension, add a new video node and
|
|
# a "Download" link in the case the video cannot be played.
|
|
class VideoLinkFilter < HTML::Pipeline::Filter
|
|
def call
|
|
doc.xpath('descendant-or-self::img[not(ancestor::a)]').each do |el|
|
|
el.replace(video_node(doc, el)) if has_video_extension?(el)
|
|
end
|
|
|
|
doc
|
|
end
|
|
|
|
private
|
|
|
|
def has_video_extension?(element)
|
|
src = element.attr('data-canonical-src').presence || element.attr('src')
|
|
|
|
return unless src.present?
|
|
|
|
src_ext = File.extname(src).sub('.', '').downcase
|
|
Gitlab::FileTypeDetection::SAFE_VIDEO_EXT.include?(src_ext)
|
|
end
|
|
|
|
def video_node(doc, element)
|
|
container = doc.document.create_element(
|
|
'div',
|
|
class: 'video-container'
|
|
)
|
|
|
|
video = doc.document.create_element(
|
|
'video',
|
|
src: element['src'],
|
|
width: '100%',
|
|
controls: true,
|
|
'data-setup' => '{}',
|
|
'data-title' => element['title'] || element['alt'])
|
|
|
|
link = doc.document.create_element(
|
|
'a',
|
|
element['title'] || element['alt'],
|
|
href: element['src'],
|
|
target: '_blank',
|
|
rel: 'noopener noreferrer',
|
|
title: "Download '#{element['title'] || element['alt']}'")
|
|
|
|
# make sure the original non-proxied src carries over
|
|
if element['data-canonical-src']
|
|
video['data-canonical-src'] = element['data-canonical-src']
|
|
link['data-canonical-src'] = element['data-canonical-src']
|
|
end
|
|
|
|
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
|