You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
94 lines
2.8 KiB
Ruby
94 lines
2.8 KiB
Ruby
# Liquid tag for embedding video.js players from assets, mirroring how images
|
|
# are embedded via plain relative paths (see _includes/head.html's <base> tag).
|
|
#
|
|
# Syntax:
|
|
# {% video urls [class names] [width height] [preload:auto|metadata|none] %}
|
|
#
|
|
# `urls` is a comma-separated list of one or more relative asset paths, used
|
|
# as <source> elements (multiple formats/resolutions). Everything after that
|
|
# is free-form, order-independent tokens classified by shape:
|
|
# - preload:auto|metadata|none -> preload attribute
|
|
# - a bare integer -> width, then height
|
|
# - anything else -> appended to the CSS class list
|
|
#
|
|
# The rendered markup is a plain HTML5 <video controls> element with
|
|
# class="video-js" and data-setup='{}', which is exactly what video.js
|
|
# progressively enhances if/when its script loads (see head.html). If it
|
|
# never loads, the element is already a fully working native player.
|
|
require 'cgi'
|
|
|
|
module Jekyll
|
|
class VideoTag < Liquid::Tag
|
|
PRELOAD_TOKEN = /\Apreload:(auto|metadata|none)\z/
|
|
INTEGER_TOKEN = /\A\d+\z/
|
|
|
|
MIME_TYPES = {
|
|
'.mp4' => 'video/mp4',
|
|
'.m4v' => 'video/mp4',
|
|
'.webm' => 'video/webm',
|
|
'.ogv' => 'video/ogg',
|
|
}.freeze
|
|
|
|
def initialize(tag_name, markup, tokens)
|
|
super
|
|
args = markup.strip.split(/\s+/)
|
|
|
|
urls_arg = args.shift
|
|
if urls_arg.nil? || urls_arg.empty?
|
|
raise Liquid::SyntaxError, "Syntax error in tag 'video' - valid syntax: {% video urls [class names] [width height] [preload:auto|metadata|none] %}"
|
|
end
|
|
@urls = urls_arg.split(',').map(&:strip).reject(&:empty?)
|
|
|
|
@classes = []
|
|
@width = nil
|
|
@height = nil
|
|
@preload = nil
|
|
|
|
args.each do |token|
|
|
case token
|
|
when PRELOAD_TOKEN
|
|
@preload = Regexp.last_match(1)
|
|
when INTEGER_TOKEN
|
|
if @width.nil?
|
|
@width = token
|
|
else
|
|
@height = token
|
|
end
|
|
else
|
|
@classes << token
|
|
end
|
|
end
|
|
end
|
|
|
|
def render(_context)
|
|
classes = (['video-js'] + @classes).join(' ')
|
|
|
|
attrs = [%(class="#{escape(classes)}")]
|
|
attrs << 'controls'
|
|
attrs << %(width="#{escape(@width)}") if @width
|
|
attrs << %(height="#{escape(@height)}") if @height
|
|
attrs << %(preload="#{escape(@preload)}") if @preload
|
|
attrs << %(data-setup='{}')
|
|
|
|
sources = @urls.map do |url|
|
|
%( <source src="#{escape(url)}" type="#{mime_type_for(url)}">)
|
|
end.join("\n")
|
|
|
|
"<video #{attrs.join(' ')}>\n#{sources}\n</video>"
|
|
end
|
|
|
|
private
|
|
|
|
def mime_type_for(url)
|
|
ext = File.extname(url).downcase
|
|
MIME_TYPES.fetch(ext, 'video/mp4')
|
|
end
|
|
|
|
def escape(value)
|
|
CGI.escapeHTML(value.to_s)
|
|
end
|
|
end
|
|
end
|
|
|
|
Liquid::Template.register_tag('video', Jekyll::VideoTag)
|