Auto-embed URLs from YouTube, Vimeo, Gists and more

rails app:template LOCATION='https://perron.railsdesigner.com/library/embed-content/template.rb'

This processor automatically converts plain text URLs in paragraphs to embedded content. Simply paste a URL to a supported platform and it will be transformed into an interactive embed.

Example

When you write:
```markdown
Check out this video:

https://www.youtube.com/watch?v=dQw4w9WgXcQ
```

It automatically becomes an embedded YouTube player instead of plain text.

Supported platforms

  • YouTube
  • Vimeo
  • GitHub Gist
  • CodePen
  • Loom

Adding your own providers

To add support for a new platform, create a new class in app/processors/embed_processor/ and add it to the PROVIDERS array in EmbedProcessor. Each provider needs a matches? method to detect URLs and an embed method to generate the iframe or script tag.

Usage

Add the processor to your pipeline and paste any supported URL on its own line. The processor will detect and transform it automatically.

Template source

create_file "app/processors/embed_processor", <<~ERB
class EmbedProcessor < Perron::HtmlProcessor::Base
  def process
    @html.css("p").each do |paragraph|
      text = paragraph.text
      provider = PROVIDERS.find { it.constantize.matches?(text) } if text.present?

      paragraph.replace(provider.constantize.embed(text, @html)) if provider
    end
  end

  private

  PROVIDERS = %w[
    EmbedProcessor::Codepen
    EmbedProcessor::Gist
    EmbedProcessor::Loom
    EmbedProcessor::Vimeo
    EmbedProcessor::Youtube
  ]
end
end


file "app/processors/embed_processor/codepen.rb" do
<<~"_"
class EmbedProcessor
  class Codepen
    def self.matches?(text)
      text.match?(%r{https?://codepen\.io/})
    end

    def self.embed(text, html)
      # extracts username/pen_id from URLs like `https://codepen.io/railsdesigner/pen/PwZJqqb`
      username, id = text.match(%r{codepen\.io/([^/]+)/pen/([^\s?]+)}).captures

      Nokogiri::XML::Node.new("iframe", html).tap do |iframe|
        iframe["src"] = "https://codepen.io/#{username}/embed/#{id}?default-tab=result"
        iframe["width"] = "100%"
        iframe["height"] = "500"
        iframe["allowfullscreen"] = "true"
      end
    end
  end
end


_
end

file "app/processors/embed_processor/gist.rb" do
<<~"_"
class EmbedProcessor
  class Gist
    def self.matches?(text)
      text.match?(%r{https?://gist\.github\.com/})
    end

    def self.embed(text, html)
      url = text[%r{https?://gist\.github\.com/[^\s]+}, 0]

      Nokogiri::XML::Node.new("script", html).tap do |script|
        script["src"] = "#{url}.js"
      end
    end
  end
end

_
end

file "app/processors/embed_processor/loom.rb" do
<<~"_"
class EmbedProcessor
  class Loom
    def self.matches?(text)
      text.match?(%r{https?://(?:www\.)?loom\.com/share/})
    end

    def self.embed(text, html)
      id = text[%r{loom\.com/share/([^\s?]+)}, 1]

      Nokogiri::XML::Node.new("iframe", html).tap do |iframe|
        iframe["src"] = "https://www.loom.com/embed/#{id}"
        iframe["width"] = "100%"
        iframe["height"] = "400"
        iframe["allowfullscreen"] = "true"
        iframe["frameborder"] = "0"
      end
    end
  end
end

_
end

file "app/processors/embed_processor/vimeo.rb" do
<<~"_"
class EmbedProcessor
  class Vimeo
    def self.matches?(text)
      text.match?(%r{https?://(?:www\.)?vimeo\.com/})
    end

    def self.embed(text, html)
      id = text[%r{vimeo\.com/(\d+)}, 1]

      Nokogiri::XML::Node.new("iframe", html).tap do |iframe|
        iframe["src"] = "https://player.vimeo.com/video/#{id}"
        iframe["width"] = "100%"
        iframe["height"] = "400"
        iframe["allowfullscreen"] = "true"
      end
    end
  end
end

_
end

file "app/processors/embed_processor/youtube.rb" do
<<~"_"
class EmbedProcessor
  class Youtube
    def self.matches?(text)
      text.match?(%r{https?://(?:www\.)?(?:youtube\.com/watch\?v=|youtu\.be/)})
    end

    def self.embed(text, html)
      id = text[/(?:v=|youtu\.be\/)([^&?\s]+)/, 1]

      Nokogiri::XML::Node.new("iframe", html).tap do |iframe|
        iframe["src"] = "https://www.youtube.com/embed/#{id}"
        iframe["width"] = "100%"
        iframe["height"] = "400"
        iframe["allowfullscreen"] = "true"
      end
    end
  end
end

_
end

end