diff --git a/app/liquid_tags/vimeo_tag.rb b/app/liquid_tags/vimeo_tag.rb
new file mode 100644
index 000000000..01c2ccb09
--- /dev/null
+++ b/app/liquid_tags/vimeo_tag.rb
@@ -0,0 +1,35 @@
+class VimeoTag < LiquidTagBase
+ def initialize(tag_name, token, tokens)
+ super
+ @id = id_for token
+ @width = 710
+ @height = 399
+ end
+
+ def render(_context)
+ finalize_html <<~HTML
+
+ HTML
+ end
+
+ private
+
+ def id_for(input)
+ # This was the original plan:
+ # require "uri"
+ # File.basename URI(input).path
+ # But the markdown turns the link into html. This is simple enough,
+ # works for all the use cases and isn't exploitable.
+ input.to_s.scan(/\d+/).max_by(&:length)
+ end
+end
+
+Liquid::Template.register_tag("vimeo", VimeoTag)
diff --git a/app/views/pages/markdown_basics.html.erb b/app/views/pages/markdown_basics.html.erb
index 553709ff4..96a647a1a 100644
--- a/app/views/pages/markdown_basics.html.erb
+++ b/app/views/pages/markdown_basics.html.erb
@@ -55,9 +55,10 @@
All you need is the gist link
{% gist https://gist.github.com/QuincyLarson/4bb1682ce590dc42402b2edddbca7aaa %}
- YouTube Embed
- All you need is the YouTube id from the URL.
- {% youtube 9z-Pdfxxdyo %}
+ Video Embed
+ All you need is the id from the URL.
+ {% youtube 9z-Pdfxxdyo %}
+ {% vimeo 193110695 %}
Instagram Embed
All you need is the Instagram post id from the URL.
diff --git a/spec/liquid_tags/vimeo_tag_spec.rb b/spec/liquid_tags/vimeo_tag_spec.rb
new file mode 100644
index 000000000..cf4fc68c7
--- /dev/null
+++ b/spec/liquid_tags/vimeo_tag_spec.rb
@@ -0,0 +1,44 @@
+require "rails_helper"
+require "nokogiri"
+
+RSpec.describe VimeoTag, type: :liquid_template do
+ let(:id) { "205930710" }
+
+ def assert_parses(vimeo_id, token)
+ liquid = Liquid::Template.parse("{% vimeo #{token} %}")
+ html = Nokogiri.parse(liquid.render).root
+ expect(html.name).to eq "iframe"
+ expect(html[:src]).to eq "https://player.vimeo.com/video/#{vimeo_id}"
+ expect(html[:width]).to eq "710"
+ expect(html[:height]).to eq "399"
+ end
+
+ it "accepts vimeo video id" do
+ assert_parses id, id
+ end
+
+ it "accepts vimeo video id with wonky whitespace" do
+ assert_parses id, " #{id} \t"
+ end
+
+ it "accepts a vimeo video url" do
+ assert_parses id, "https://vimeo.com/#{id}"
+ assert_parses id, "vimeo.com/#{id}"
+ end
+
+ it "accepts a vimeo player url" do
+ assert_parses id, "https://player.vimeo.com/video/#{id}"
+ assert_parses id, "ps://player.vimeo.com/video/#{id}"
+ end
+
+ # NOTE: This is kinda dumb. It seems like the right answer is that
+ # either it should run liquid before markdown, or markdown shouldn't
+ # mess with the liquid tags (there is a fn to escape them, but it doesn't
+ # seem to escape the url here)
+ # https://github.com/thepracticaldev/dev.to/blob/master/app/labor/markdown_parser.rb#L73-L92
+ # My test suite isn't entirely passing, and I've spent longer on this than I
+ # wanted to, io Instead of looking into those, I'm going to just make this work ¯\_(ツ)_/¯
+ it "accepts urls that were over-eagerly turned into links by markdown" do
+ assert_parses id, "https://vimeo.com/192819855 "
+ end
+end