Action Text Video Support
Action Text
Here’s a quick post just to document how I got video uploads working in Action Text, again mostly for “future me”, but hopefully helpful for others!
Let me say, I love Action Text and Trix. For me at least its exactly what I need for simple text input that users can format and also upload images. I won’t go into the details of how to set it up as there are countless great sources for that, the primary one of course being the Rails Guides which are great.
File uploads
One of the killer features of Action Text in my opinion is the way it handles file uploads so simply with a WYSIWYG interface.
This is great for images but I couldn’t figure out why I couldn’t play uploaded .mov
video files. And I really needed
this for my use case of sharing technical issues and bug reports.
Default Templates
When you install Action Text with bin/rails action_text:install
the default template for representing attachments will be
generated in app/views/active_storage/blobs/_blob.html.erb
and looks like this (Rails 8.0.0.alpha)
<figure class="attachment attachment--<%= blob.representable? ? "preview" : "file" %> attachment--<%= blob.filename.extension %>">
<% if blob.representable? %>
<%= image_tag blob.representation(resize_to_limit: local_assigns[:in_gallery] ? [ 800, 600 ] : [ 1024, 768 ]) %>
<% end %>
<figcaption class="attachment__caption">
<% if caption = blob.try(:caption) %>
<%= caption %>
<% else %>
<span class="attachment__name"><%= blob.filename %></span>
<span class="attachment__size"><%= number_to_human_size blob.byte_size %></span>
<% end %>
</figcaption>
</figure>
I found that a thumbnail of the video was generated and displayed when I rendered out the content but I wanted to play the video!
I expected adding something like this using the AssetTagHelper
for video would render accordingly:
<% if blob.video? %>
<%= video_tag url_for(blob), controls: true, preload: "metadata", class: "attachment__video" %>
...
but while I got a great preview still image of the video, I couldn’t play it…
Sanitization
Finally after a lot of head scratching I discovered that the tags were being sanitized away. Sanitizing the form input is critical since users may try all kinds of nefarious exploits to compromise our sites, but in this case supporting video seemed to be an ok trade-off.
The trick then is to allow the video related tags in the HTML to be rendered when showing Action Text content. To do this we need to
add the following initializer in config/initializers/action_text.rb
:
Rails.application.config.after_initialize do
default_allowed_attributes = Rails::HTML5::Sanitizer.safe_list_sanitizer.allowed_attributes + ActionText::Attachment::ATTRIBUTES.to_set
custom_allowed_attributes = Set.new(%w[controls])
ActionText::ContentHelper.allowed_attributes = (default_allowed_attributes + custom_allowed_attributes).freeze
default_allowed_tags = Rails::HTML5::Sanitizer.safe_list_sanitizer.allowed_tags + Set.new([ ActionText::Attachment.tag_name, "figure", "figcaption" ])
custom_allowed_tags = Set.new(%w[audio video source])
ActionText::ContentHelper.allowed_tags = (default_allowed_tags + custom_allowed_tags).freeze
end
What this is doing is telling Action Text to allow a “controls” HTML attribute and “audio”, “video” and “source” tags to be rendered from user uploaded content.
After restarting the server.. voila! You should see a video play button and scrub control!
Wrap Up
As always, don’t hesitate to drop me a note via twitter or any other channels listed here.