feat: move embedding config to a yaml file (#11611)
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com> Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
class CustomMarkdownRenderer < CommonMarker::HtmlRenderer
|
||||
# TODO: let move this regex from here to a config file where we can update this list much more easily
|
||||
# the config file will also have the matching embed template as well.
|
||||
YOUTUBE_REGEX = %r{https?://(?:www\.)?(?:youtube\.com/watch\?v=|youtu\.be/)([^&/]+)}
|
||||
LOOM_REGEX = %r{https?://(?:www\.)?loom\.com/share/([^&/]+)}
|
||||
VIMEO_REGEX = %r{https?://(?:www\.)?vimeo\.com/(\d+)}
|
||||
MP4_REGEX = %r{https?://(?:www\.)?.+\.(mp4)}
|
||||
ARCADE_REGEX = %r{https?://(?:www\.)?app\.arcade\.software/share/([^&/]+)}
|
||||
WISTIA_REGEX = %r{https?://(?:www\.)?([^/]+)\.wistia\.com/medias/([^&/]+)}
|
||||
BUNNY_REGEX = %r{https?://iframe\.mediadelivery\.net/play/(\d+)/([^&/?]+)}
|
||||
CONFIG_PATH = Rails.root.join('config/markdown_embeds.yml')
|
||||
|
||||
def self.config
|
||||
@config ||= YAML.load_file(CONFIG_PATH)
|
||||
end
|
||||
|
||||
def self.embed_regexes
|
||||
@embed_regexes ||= config.transform_values { |embed_config| Regexp.new(embed_config['regex']) }
|
||||
end
|
||||
|
||||
def text(node)
|
||||
content = node.string_content
|
||||
@@ -23,7 +23,7 @@ class CustomMarkdownRenderer < CommonMarker::HtmlRenderer
|
||||
def link(node)
|
||||
return if surrounded_by_empty_lines?(node) && render_embedded_content(node)
|
||||
|
||||
# If it's not YouTube or Vimeo link, render normally
|
||||
# If it's not a supported embed link, render normally
|
||||
super
|
||||
end
|
||||
|
||||
@@ -47,25 +47,35 @@ class CustomMarkdownRenderer < CommonMarker::HtmlRenderer
|
||||
|
||||
def render_embedded_content(node)
|
||||
link_url = node.url
|
||||
embedding_methods = {
|
||||
YOUTUBE_REGEX => :make_youtube_embed,
|
||||
VIMEO_REGEX => :make_vimeo_embed,
|
||||
MP4_REGEX => :make_video_embed,
|
||||
LOOM_REGEX => :make_loom_embed,
|
||||
ARCADE_REGEX => :make_arcade_embed,
|
||||
WISTIA_REGEX => :make_wistia_embed,
|
||||
BUNNY_REGEX => :make_bunny_embed
|
||||
}
|
||||
embed_html = find_matching_embed(link_url)
|
||||
|
||||
embedding_methods.each do |regex, method|
|
||||
return false unless embed_html
|
||||
|
||||
out(embed_html)
|
||||
true
|
||||
end
|
||||
|
||||
def find_matching_embed(link_url)
|
||||
self.class.embed_regexes.each do |embed_key, regex|
|
||||
match = link_url.match(regex)
|
||||
if match
|
||||
out(send(method, match))
|
||||
return true
|
||||
end
|
||||
next unless match
|
||||
|
||||
return render_embed_from_match(embed_key, match)
|
||||
end
|
||||
|
||||
false
|
||||
nil
|
||||
end
|
||||
|
||||
def render_embed_from_match(embed_key, match_data)
|
||||
embed_config = self.class.config[embed_key]
|
||||
return nil unless embed_config
|
||||
|
||||
template = embed_config['template']
|
||||
# Use Ruby's built-in named captures with gsub to handle CSS % values
|
||||
match_data.named_captures.each do |var_name, value|
|
||||
template = template.gsub("%{#{var_name}}", value)
|
||||
end
|
||||
template
|
||||
end
|
||||
|
||||
def parse_sup(content)
|
||||
@@ -77,39 +87,4 @@ class CustomMarkdownRenderer < CommonMarker::HtmlRenderer
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def make_youtube_embed(youtube_match)
|
||||
video_id = youtube_match[1]
|
||||
EmbedRenderer.youtube(video_id)
|
||||
end
|
||||
|
||||
def make_loom_embed(loom_match)
|
||||
video_id = loom_match[1]
|
||||
EmbedRenderer.loom(video_id)
|
||||
end
|
||||
|
||||
def make_vimeo_embed(vimeo_match)
|
||||
video_id = vimeo_match[1]
|
||||
EmbedRenderer.vimeo(video_id)
|
||||
end
|
||||
|
||||
def make_video_embed(link_url)
|
||||
EmbedRenderer.video(link_url)
|
||||
end
|
||||
|
||||
def make_wistia_embed(wistia_match)
|
||||
video_id = wistia_match[2]
|
||||
EmbedRenderer.wistia(video_id)
|
||||
end
|
||||
|
||||
def make_arcade_embed(arcade_match)
|
||||
video_id = arcade_match[1]
|
||||
EmbedRenderer.arcade(video_id)
|
||||
end
|
||||
|
||||
def make_bunny_embed(bunny_match)
|
||||
library_id = bunny_match[1]
|
||||
video_id = bunny_match[2]
|
||||
EmbedRenderer.bunny(library_id, video_id)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
module EmbedRenderer
|
||||
def self.youtube(video_id)
|
||||
%(
|
||||
<div style="position: relative; padding-bottom: 62.5%; height: 0;">
|
||||
<iframe
|
||||
src="https://www.youtube-nocookie.com/embed/#{video_id}"
|
||||
frameborder="0"
|
||||
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowfullscreen></iframe>
|
||||
</div>
|
||||
)
|
||||
end
|
||||
|
||||
def self.loom(video_id)
|
||||
%(
|
||||
<div style="position: relative; padding-bottom: 62.5%; height: 0;">
|
||||
<iframe
|
||||
src="https://www.loom.com/embed/#{video_id}"
|
||||
frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen
|
||||
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"></iframe>
|
||||
</div>
|
||||
)
|
||||
end
|
||||
|
||||
def self.vimeo(video_id)
|
||||
%(
|
||||
<div style="position: relative; padding-bottom: 62.5%; height: 0;">
|
||||
<iframe
|
||||
src="https://player.vimeo.com/video/#{video_id}?dnt=true"
|
||||
frameborder="0"
|
||||
allow="autoplay; fullscreen; picture-in-picture"
|
||||
allowfullscreen
|
||||
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"></iframe>
|
||||
</div>
|
||||
)
|
||||
end
|
||||
|
||||
def self.video(link_url)
|
||||
%(
|
||||
<video width="640" height="360" controls>
|
||||
<source src="#{link_url}" type="video/mp4">
|
||||
Your browser does not support the video tag.
|
||||
</video>
|
||||
)
|
||||
end
|
||||
|
||||
# Generates an HTML embed for a Wistia video.
|
||||
# @param wistia_match [MatchData] A match object from the WISTIA_REGEX regex, where wistia_match[2] contains the video ID.
|
||||
def self.wistia(video_id)
|
||||
%(
|
||||
<div style="position: relative; padding-bottom: 56.25%; height: 0;">
|
||||
<script src="https://fast.wistia.com/player.js" async></script>
|
||||
<script src="https://fast.wistia.com/embed/#{video_id}.js" async type="module"></script>
|
||||
<style>
|
||||
wistia-player[media-id='#{video_id}']:not(:defined) {
|
||||
background: center / contain no-repeat url('https://fast.wistia.com/embed/medias/#{video_id}/swatch');
|
||||
display: block;
|
||||
filter: blur(5px);
|
||||
padding-top:56.25%;
|
||||
}
|
||||
</style>
|
||||
<wistia-player
|
||||
media-id="#{video_id}"
|
||||
aspect="1.7777777777777777"
|
||||
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;">
|
||||
</wistia-player>
|
||||
</div>
|
||||
)
|
||||
end
|
||||
|
||||
def self.arcade(video_id)
|
||||
%(
|
||||
<div style="position: relative; padding-bottom: 62.5%; height: 0;">
|
||||
<iframe
|
||||
src="https://app.arcade.software/embed/#{video_id}"
|
||||
frameborder="0"
|
||||
webkitallowfullscreen
|
||||
mozallowfullscreen
|
||||
allowfullscreen
|
||||
allow="fullscreen"
|
||||
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;">
|
||||
</iframe>
|
||||
</div>
|
||||
)
|
||||
end
|
||||
|
||||
def self.bunny(library_id, video_id)
|
||||
%(
|
||||
<div style="position: relative; padding-top: 56.25%;">
|
||||
<iframe
|
||||
src="https://iframe.mediadelivery.net/embed/#{library_id}/#{video_id}?autoplay=false&loop=false&muted=false&preload=true&responsive=true"
|
||||
title="Bunny video player"
|
||||
loading="lazy"
|
||||
style="border: 0; position: absolute; top: 0; height: 100%; width: 100%;"
|
||||
allow="accelerometer; gyroscope; autoplay; encrypted-media; picture-in-picture;"
|
||||
allowfullscreen>
|
||||
</iframe>
|
||||
</div>
|
||||
)
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user