Commit c266c7fa authored by Eric Hayes's avatar Eric Hayes Committed by Rémy Coutable

First support of videos in issues, MRs and notes

* Registered video MIME types
* Currently supporting browser-supported formats with extensions that match the mime type
parent 81e57e78
......@@ -53,6 +53,7 @@
#= require_directory ./u2f
#= require_directory .
#= require fuzzaldrin-plus
#= require u2f
window.slugify = (text) ->
text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase()
......
# Disables dynamic sizing of video tag, which defaults to 300px.
# Without this the video naturally fills the container.
window.VIDEOJS_NO_DYNAMIC_STYLE = true
......@@ -29,6 +29,11 @@
*/
@import "font-awesome";
/*
* Styles for VideoJS.
*/
@import "videojs/video-js";
/*
* Page specific styles (issues, projects etc):
*/
......
class Projects::UploadsController < Projects::ApplicationController
skip_before_action :reject_blocked!, :project,
:repository, if: -> { action_name == 'show' && image? }
:repository, if: -> { action_name == 'show' && image_or_video? }
before_action :authorize_upload_file!, only: [:create]
......@@ -24,7 +24,7 @@ class Projects::UploadsController < Projects::ApplicationController
def show
return render_404 if uploader.nil? || !uploader.file.exists?
disposition = uploader.image? ? 'inline' : 'attachment'
disposition = uploader.image_or_video? ? 'inline' : 'attachment'
send_file uploader.file.path, disposition: disposition
end
......@@ -49,7 +49,7 @@ class Projects::UploadsController < Projects::ApplicationController
@uploader
end
def image?
uploader && uploader.file.exists? && uploader.image?
def image_or_video?
uploader && uploader.file.exists? && uploader.image_or_video?
end
end
......@@ -33,16 +33,16 @@ class FileUploader < CarrierWave::Uploader::Base
end
def to_h
filename = image? ? self.file.basename : self.file.filename
filename = image_or_video? ? self.file.basename : self.file.filename
escaped_filename = filename.gsub("]", "\\]")
markdown = "[#{escaped_filename}](#{self.secure_url})"
markdown.prepend("!") if image?
markdown.prepend("!") if image_or_video?
{
alt: filename,
url: self.secure_url,
is_image: image?,
is_image: image_or_video?,
markdown: markdown
}
end
......
# Extra methods for uploader
module UploaderHelper
IMAGE_EXT = %w(png jpg jpeg gif bmp tiff)
VIDEO_EXT = %w(mov mp4 ogg webm flv)
def image?
img_ext = %w(png jpg jpeg gif bmp tiff)
extension_match?(IMAGE_EXT)
rescue
false
end
def video?
extension_match?(VIDEO_EXT)
rescue
false
end
def image_or_video?
image? || video?
end
def extension_match?(extensions)
if file.respond_to?(:extension)
img_ext.include?(file.extension.downcase)
extensions.include?(file.extension.downcase)
else
# Not all CarrierWave storages respond to :extension
ext = file.path.split('.').last.downcase
img_ext.include?(ext)
extensions.include?(ext)
end
rescue
false
end
def file_storage?
......
......@@ -6,5 +6,11 @@
Mime::Type.register_alias "text/plain", :diff
Mime::Type.register_alias "text/plain", :patch
Mime::Type.register_alias 'text/html', :markdown
Mime::Type.register_alias 'text/html', :md
Mime::Type.register_alias "text/html", :markdown
Mime::Type.register_alias "text/html", :md
Mime::Type.register "video/webm", :webm
Mime::Type.register "video/ogg", :ogg
Mime::Type.register "video/ogg", :ogv
Mime::Type.register "video/mp4", :mp4
Mime::Type.register "video/mp4", :m4v
module Banzai
module Filter
# HTML Filter that handles video uploads.
class VideoLinkFilter < HTML::Pipeline::Filter
include ActionView::Helpers::TagHelper
include ActionView::Context
EXTENSIONS = %w(.mov .mp4 .ogg .webm .flv)
def call
doc.search('img').each do |el|
if video?(el)
el.replace video_node(el)
end
end
doc
end
private
def video?(element)
EXTENSIONS.include? File.extname(element.attribute('src').value)
end
# Return a video tag Nokogiri node
#
def video_node(element)
vtag = content_tag(:video, "", {
src: element.attribute('src').value,
class: 'video-js', preload: 'auto',
controls: true
})
Nokogiri::HTML::DocumentFragment.parse(vtag)
end
end
end
end
......@@ -8,6 +8,7 @@ module Banzai
Filter::UploadLinkFilter,
Filter::ImageLinkFilter,
Filter::VideoLinkFilter,
Filter::EmojiFilter,
Filter::TableOfContentsFilter,
Filter::AutolinkFilter,
......
require 'spec_helper'
describe Banzai::Filter::VideoLinkFilter, lib: true do
def filter(doc, contexts = {})
contexts.reverse_merge!({
project: project
})
described_class.call(doc, contexts)
end
def image(path)
%(<img src="#{path}" />)
end
let(:project) { create(:project) }
context 'when the element src has a video extension' do
it 'replaces the image tag with a video tag' do
doc = filter(image("/path/video.mov"))
element = doc.children.first
expect(element.name).to eq( "video" )
expect(element['src']).to eq( "/path/video.mov" )
end
end
context 'when the element src is an image' do
it 'leaves the document unchanged' do
doc = filter(image("/path/my_image.jpg"))
element = doc.children.first
expect(element.name).to eq( "img" )
end
end
end
require "spec_helper"
# provides matchers like `have_dimensions`
# https://github.com/carrierwaveuploader/carrierwave#testing-with-carrierwave
# require "carrierwave/test/matchers"
describe FileUploader do
# include CarrierWave::Test::Matchers
let(:project){ create(:project) }
let(:image_file){ File.new Rails.root.join("spec", "fixtures", "rails_sample.jpg") }
let(:video_file){ File.new Rails.root.join("spec", "fixtures", "video_sample.mp4") }
let(:text_file) { File.new Rails.root.join("spec", "fixtures", "doc_sample.txt") }
before do
FileUploader.enable_processing = false
@uploader = FileUploader.new(project)
end
after do
FileUploader.enable_processing = true
@uploader.remove!
end
it "should detect an image based on file extension" do
@uploader.store!(image_file)
expect(@uploader.image_or_video?).to be true
end
it "should detect a video based on file extension" do
@uploader.store!(video_file)
expect(@uploader.image_or_video?).to be true
end
it "should not return image_or_video? for other types" do
@uploader.store!(text_file)
expect(@uploader.image_or_video?).to be false
end
end
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
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