Skip to content

Instantly share code, notes, and snippets.

@2called-chaos
Created November 1, 2013 21:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 2called-chaos/7272548 to your computer and use it in GitHub Desktop.
Save 2called-chaos/7272548 to your computer and use it in GitHub Desktop.
require "shellwords"
class ContentRenderer
def initialize str, opts
@str = str.dup
@opts = opts.reverse_merge markdown: true, youtube: true
end
def to_str
@_rendered ||= @opts.inject(@str) do |text, (opt, perform)|
perform ? try("render_#{opt}", text) || text : text
end
end
alias_method :to_s, :to_str
def render_markdown str
renderer = HTMLwithPygments.new(hard_wrap: true, with_toc_data: true)
Redcarpet::Markdown.new(renderer, {
autolink: true,
fenced_code_blocks: true,
highlight: true,
lax_spacing: true,
no_intra_emphasis: false,
strikethrough: true,
superscript: true,
tables: true,
}).render(str)
end
def render_youtube str
process_tags(str, :youtube) do |args|
defaults = {
ratio: 16/9.0, # ratio to calculate width/height
autohide: 2, # [YT] controls behaviour 2 = fade progress, 1 = fade controls, 0 = fade nothing
autoplay: false, # [YT] autoplay on load
color: "red", # [YT] progress color (red or white)
disablekb: false, # [YT] disable player keyboard controls
enablejsapi: false, # [YT] enable JS API
end: nil, # [YT] end position in seconds (from 0:00)
iv_load_policy: 1, # [YT] annotations 1 = load, 2 = ?, 3 = don't load
loop: false, # [YT] loop video
modestbranding: false, # [YT] Hide YT logo in controls
origin: nil, # [YT] origin for JS API
playlist: nil, # [YT] list of video IDs to play (after if ID given)
rel: false, # [YT] show related videos at the end
showinfo: true, # [YT] Show video info (title bar)
start: nil, # [YT] start position in seconds
theme: "dark", # [YT] theme (dark or light)
vq: "large", # [YT] video quality (small, medium, large, hd720, hd1080)
}
args.reverse_merge!(defaults)
params = youtube_params(args.slice(*defaults.keys - [:ratio]))
# calculate dimensions if only one is given
args[:width] = 420 if !args[:width] && !args[:height]
args[:height] = args[:width] / args[:ratio] if args[:width] && !args[:height]
args[:width] = args[:height] * args[:ratio] if args[:height] && !args[:width]
%{
<iframe
frameborder="0"
allowfullscreen="allowfullscreen"
width="#{args[:width]}"
height="#{args[:height]}"
src="//www.youtube.com/embed/#{args[:id]}?#{params.to_query}"
></iframe>
}.gsub("\n", "").squeeze(" ")
end
str
end
protected
# Searches for occurences of tags <tag> and
# replaces them with the result of &block.
def process_tags str, tag, &block
str.gsub!(/<#{tag}\s(.*?)>/im) do
args = {}.with_indifferent_access
Shellwords.shellsplit($1).each do |key_val|
key, val = *key_val.split("=", 2)
val = false if val.in? %w[false no]
val = true if val.in? %w[true yes]
val = parse_number(val)
args[key] = val
end
block.call(args)
end
str
end
# parse numbers from text value
def parse_number str
return str.to_i if str =~ /\A\d+\z/
return Float(str) if Float(str) rescue nil
str
end
# youtubeify params (true = 1, false = 0)
def youtube_params params
params.each_with_object({}) do |(k, v), r|
r[k] = case v
when FalseClass then "0"
when TrueClass then "1"
else v
end
end
end
end
# create a custom renderer that allows highlighting of code blocks
class HTMLwithPygments < Redcarpet::Render::HTML
def block_code(code, language)
Pygments.highlight(code, lexer: language, options: { linespans: Digest::SHA1.base64digest(code) })
end
end
class Post < ActiveRecord::Base
def content opts = {}
ContentRenderer.new(body, opts)
end
end
# <youtube id="foobar">
# <youtube id="foobar" autostart="yes" start="30" end="60">
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment