ruby-on-rails - 如何使用 ActionText 显示嵌入视频

标签 ruby-on-rails ruby trix

我正在尝试在 WYSIWYG Trix 和呈现的内容中显示带有 ActionText on Rails 6 的嵌入式视频。但是 ActionText 渲染器过滤所有原始 html 代码并强制我使用 JS 在渲染内容中显示 iframe,这在 Trix 中不起作用。

我遵循了 Basecamp 的一位开发人员在此处给出的说明:https://github.com/rails/actiontext/issues/37#issuecomment-451627370 .第 1 步到第 3 步有效,但是当 ActionText 呈现我的部分时,它会过滤 iframe。

创建所见即所得的表单

= form_for(article, url: url, method: method) do |a|
  = a.label :content
  = a.rich_text_area :content, data: { controller: "articles", target: "articles.field", embeds_path: editorial_publication_embeds_path(@publication, format: :json) }
  = a.submit submit_text, class:"btn full"

添加嵌入功能的 Stimulus Controller (迫切需要重构)

import { Controller } from "stimulus";
import Trix from "trix";

$.ajaxSetup({
  headers: {
    "X-CSRF-Token": $('meta[name="csrf-token"]').attr("content"),
  },
});

export default class extends Controller {
  static targets = ["field"];

  connect() {
    this.editor = this.fieldTarget.editor; 

    const buttonHTML =
      '<button type="button" class="trix-button" data-trix-attribute="embed" data-trix-action="embed" title="Embed" tabindex="-1">Media</button>';
    const buttonGroup = this.fieldTarget.toolbarElement.querySelector(
      ".trix-button-group--block-tools"
    );
    const dialogHml = `<div class="trix-dialog trix-dialog--link" data-trix-dialog="embed" data-trix-dialog-attribute="embed">
    <div class="trix-dialog__link-fields">
      <input type="text" name="embed" class="trix-input trix-input--dialog" placeholder="Paste your video or sound url" aria-label="embed code" required="" data-trix-input="" disabled="disabled">
      <div class="trix-button-group">
        <input type="button" class="trix-button trix-button--dialog" data-trix-custom="add-embed" value="Add">
      </div>
    </div>
  </div>`;
    const dialogGroup = this.fieldTarget.toolbarElement.querySelector(
      ".trix-dialogs"
    );
    buttonGroup.insertAdjacentHTML("beforeend", buttonHTML);
    dialogGroup.insertAdjacentHTML("beforeend", dialogHml);
    document
      .querySelector('[data-trix-action="embed"]')
      .addEventListener("click", event => {
        const dialog = document.querySelector('[data-trix-dialog="embed"]');
        const embedInput = document.querySelector('[name="embed"]');
        if (event.target.classList.contains("trix-active")) {
          event.target.classList.remove("trix-active");
          dialog.classList.remove("trix-active");
          delete dialog.dataset.trixActive;
          embedInput.setAttribute("disabled", "disabled");
        } else {
          event.target.classList.add("trix-active");
          dialog.classList.add("trix-active");
          dialog.dataset.trixActive = "";
          embedInput.removeAttribute("disabled");
          embedInput.focus();
        }
      });
    document
      .querySelector('[data-trix-custom="add-embed"]')
      .addEventListener("click", event => {
        const content = document.querySelector('[name="embed"]').value;
        if (content) {
          $.ajax({
            method: "POST",
            url: document.querySelector("[data-embeds-path]").dataset
              .embedsPath,
            data: {
              embed: {
                content,
              },
            },
            success: ({ content, sgid }) => {
              const attachment = new Trix.Attachment({
                content,
                sgid,
              });
              this.editor.insertAttachment(attachment);
              this.editor.insertLineBreak();
            },
          });
        }
      });
  }
}

嵌入模型

class Embed < ApplicationRecord
  include ActionText::Attachable

  validates :content, presence: true

  after_validation :fetch_oembed_data

  def to_partial_path
    "editorial/embeds/embed"
  end

  def fetch_oembed_data
    url =
      case content
      when /youtube/
        "https://www.youtube.com/oembed?url=#{content}&format=json"
      when /soundcloud/
        "https://soundcloud.com/oembed?url=#{content}&format=json"
      when /twitter/
        "https://publish.twitter.com/oembed?url=#{content}"
      end
    res = RestClient.get url
    json = JSON.parse(res.body, object_class: OpenStruct)
    self.height = json.height
    self.author_url = json.author_url
    self.thumbnail_url = json.thumbnail_url
    self.width = json.width
    self.author_name = json.author_name
    self.thumbnail_height = json.thumbnail_height
    self.title = json.title
    self.version = json.version
    self.provider_url = json.provider_url
    self.thumbnail_width = json.thumbnail_width
    self.embed_type = json.type
    self.provider_name = json.provider_name
    self.html = json.html
  end
end

创建嵌入的 Controller

  def create
    @embed = Embed.create!(params.require(:embed).permit(:content))
    respond_to do |format|
      format.json
    end
  end

jbuilder View 响应 ajax 调用以创建嵌入

json.extract! @embed, :content

json.sgid @embed.attachable_sgid
json.content render(partial: "editorial/embeds/embed", locals: { embed: @embed }, formats: [:html])

嵌入 HTML 部分( slim )

.youtube-embed.embed
  .content
    = image_tag(embed.thumbnail_url) if embed.thumbnail_url.present?
    p = "Embed from #{embed.provider_name} (#{embed.content})"
    p.embed-html = embed.html

最后是在显示带有嵌入的文章内容时显示 iframe 的 JS 代码

$(document).ready(() => {
  $(".embed").each(function(i, embed) {
    const $embed = $(embed);
    const p = $embed
      .find(".content")
      .replaceWith($embed.find(".embed-html").text());
  });
});

如果我将嵌入部分更改为

== embed.html

它在 WYSIWYG 中正确显示,但在渲染 View 中显示不正确。

最佳答案

需要在allowed_tags中添加iframe,在application.rb中添加如下代码:

config.to_prepare do
  ActionText::ContentHelper.allowed_tags << "iframe"
end

关于ruby-on-rails - 如何使用 ActionText 显示嵌入视频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56316549/

相关文章:

ruby - 如何将 sinatra 作为 websocket 服务器运行?

ruby-on-rails - 为什么 "render ' new'“改变我的 URL?(Ruby On Rails)

ruby-on-rails - 如何 self [:name] works rails

ruby-on-rails - 使用 erb 渲染一个变量

ruby-on-rails - 如何(替换|创建)rails 2.0 迁移中的枚举字段?

angular - 如何将 trix-editor 集成到 Angular 2 应用程序中?

javascript - Trix 编辑器定义自定义附件样式

javascript - 带有 Trix 编辑器的 At.js : error "The given range isn' t in document.“

ruby-on-rails - ActiveRecord `.references` 加入比必要更多的表? (并导致错误)

mysql - mysql 查询 ruby​​/mysql 的大小限制