diff --git a/actiontext/CHANGELOG.md b/actiontext/CHANGELOG.md index 5853a0e4d2..8a2c1b3586 100644 --- a/actiontext/CHANGELOG.md +++ b/actiontext/CHANGELOG.md @@ -1,3 +1,7 @@ +* Add `config.action_text.attachment_tag_name`, to specify the HTML tag that contains attachments. + + *Mark VanLandingham* + * Expose how we render the HTML _surrounding_ rich text content as an extensible `layouts/action_view/contents/_content.html.erb` template to encourage user-land customizations, while retaining private API control over how diff --git a/actiontext/app/helpers/action_text/content_helper.rb b/actiontext/app/helpers/action_text/content_helper.rb index d7c32a470d..f0f3521ccd 100644 --- a/actiontext/app/helpers/action_text/content_helper.rb +++ b/actiontext/app/helpers/action_text/content_helper.rb @@ -5,7 +5,7 @@ require "rails-html-sanitizer" module ActionText module ContentHelper mattr_accessor(:sanitizer) { Rails::Html::Sanitizer.safe_list_sanitizer.new } - mattr_accessor(:allowed_tags) { sanitizer.class.allowed_tags + [ ActionText::Attachment::TAG_NAME, "figure", "figcaption" ] } + mattr_accessor(:allowed_tags) { sanitizer.class.allowed_tags + [ ActionText::Attachment.tag_name, "figure", "figcaption" ] } mattr_accessor(:allowed_attributes) { sanitizer.class.allowed_attributes + ActionText::Attachment::ATTRIBUTES } mattr_accessor(:scrubber) diff --git a/actiontext/lib/action_text/attachment.rb b/actiontext/lib/action_text/attachment.rb index 4bd537c7c2..b91d6133bc 100644 --- a/actiontext/lib/action_text/attachment.rb +++ b/actiontext/lib/action_text/attachment.rb @@ -6,8 +6,8 @@ module ActionText class Attachment include Attachments::TrixConversion, Attachments::Minification, Attachments::Caching - TAG_NAME = "action-text-attachment" - SELECTOR = TAG_NAME + mattr_accessor :tag_name, default: "action-text-attachment" + ATTRIBUTES = %w( sgid content-type url href filename filesize width height previewable presentation caption ) class << self @@ -38,7 +38,7 @@ module ActionText private def node_from_attributes(attributes) if attributes = process_attributes(attributes).presence - ActionText::HtmlConversion.create_element(TAG_NAME, attributes) + ActionText::HtmlConversion.create_element(tag_name, attributes) end end diff --git a/actiontext/lib/action_text/attachment_gallery.rb b/actiontext/lib/action_text/attachment_gallery.rb index 48ba9f830c..a3c1c33f80 100644 --- a/actiontext/lib/action_text/attachment_gallery.rb +++ b/actiontext/lib/action_text/attachment_gallery.rb @@ -57,7 +57,7 @@ module ActionText end TAG_NAME = "div" - ATTACHMENT_SELECTOR = "#{ActionText::Attachment::SELECTOR}[presentation=gallery]" + ATTACHMENT_SELECTOR = "#{ActionText::Attachment.tag_name}[presentation=gallery]" SELECTOR = "#{TAG_NAME}:has(#{ATTACHMENT_SELECTOR} + #{ATTACHMENT_SELECTOR})" private_constant :TAG_NAME, :ATTACHMENT_SELECTOR, :SELECTOR diff --git a/actiontext/lib/action_text/attachments/minification.rb b/actiontext/lib/action_text/attachments/minification.rb index edc8f876d6..75a113163f 100644 --- a/actiontext/lib/action_text/attachments/minification.rb +++ b/actiontext/lib/action_text/attachments/minification.rb @@ -7,7 +7,7 @@ module ActionText class_methods do def fragment_by_minifying_attachments(content) - Fragment.wrap(content).replace(ActionText::Attachment::SELECTOR) do |node| + Fragment.wrap(content).replace(ActionText::Attachment.tag_name) do |node| node.tap { |n| n.inner_html = "" } end end diff --git a/actiontext/lib/action_text/content.rb b/actiontext/lib/action_text/content.rb index de43880a0c..c238d0266c 100644 --- a/actiontext/lib/action_text/content.rb +++ b/actiontext/lib/action_text/content.rb @@ -58,7 +58,7 @@ module ActionText end def render_attachments(**options, &block) - content = fragment.replace(ActionText::Attachment::SELECTOR) do |node| + content = fragment.replace(ActionText::Attachment.tag_name) do |node| block.call(attachment_for_node(node, **options)) end self.class.new(content, canonicalize: false) @@ -111,7 +111,7 @@ module ActionText private def attachment_nodes - @attachment_nodes ||= fragment.find_all(ActionText::Attachment::SELECTOR) + @attachment_nodes ||= fragment.find_all(ActionText::Attachment.tag_name) end def attachment_gallery_nodes diff --git a/actiontext/lib/action_text/engine.rb b/actiontext/lib/action_text/engine.rb index e78c95b69b..46a2a23789 100644 --- a/actiontext/lib/action_text/engine.rb +++ b/actiontext/lib/action_text/engine.rb @@ -12,6 +12,9 @@ module ActionText isolate_namespace ActionText config.eager_load_namespaces << ActionText + config.action_text = ActiveSupport::OrderedOptions.new + config.action_text.attachment_tag_name = "action-text-attachment" + initializer "action_text.attribute" do ActiveSupport.on_load(:active_record) do include ActionText::Attribute @@ -64,5 +67,9 @@ module ActionText include ActionText::SystemTestHelper end end + + initializer "action_text.configure" do |app| + ActionText::Attachment.tag_name = app.config.action_text.attachment_tag_name + end end end diff --git a/actiontext/test/unit/content_test.rb b/actiontext/test/unit/content_test.rb index dc9d4a1141..c275e523f3 100644 --- a/actiontext/test/unit/content_test.rb +++ b/actiontext/test/unit/content_test.rb @@ -78,6 +78,15 @@ class ActionText::ContentTest < ActiveSupport::TestCase assert_equal '', content.to_html end + test "converts Trix-formatted attachments with custom tag name" do + with_attachment_tag_name("arbitrary-tag") do + html = %Q(
) + content = content_from_html(html) + assert_equal 1, content.attachments.size + assert_equal '', content.to_html + end + end + test "ignores Trix-formatted attachments with malformed JSON" do html = %Q(
) content = content_from_html(html) @@ -131,4 +140,13 @@ class ActionText::ContentTest < ActiveSupport::TestCase assert_nothing_raised { content.to_s } end end + + def with_attachment_tag_name(tag_name) + previous_tag_name = ActionText::Attachment.tag_name + ActionText::Attachment.tag_name = tag_name + + yield + ensure + ActionText::Attachment.tag_name = previous_tag_name + end end diff --git a/guides/source/configuring.md b/guides/source/configuring.md index bce5bf9601..6ffe699532 100644 --- a/guides/source/configuring.md +++ b/guides/source/configuring.md @@ -1043,6 +1043,10 @@ text/javascript image/svg+xml application/postscript application/x-shockwave-fla The default is `:rails_storage_redirect`. +### Configuring Action Text + +* `config.action_text.attachment_tag_name` accepts a string for the HTML tag used to wrap attachments. Defaults to `"action-text-attachment"`. + ### Results of `config.load_defaults` `config.load_defaults` sets new defaults up to and including the version passed. Such that passing, say, `6.0` also gets the new defaults from every version before it. diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb index c6f4100e9c..374edcdee0 100644 --- a/railties/test/application/configuration_test.rb +++ b/railties/test/application/configuration_test.rb @@ -2760,6 +2760,30 @@ module ApplicationTests assert_kind_of ActiveSupport::HashWithIndifferentAccess, ActionCable.server.config.cable end + test "action_text.config.attachment_tag_name is 'action-text-attachment' with Rails 6 defaults" do + add_to_config 'config.load_defaults "6.1"' + + app "development" + + assert_equal "action-text-attachment", ActionText::Attachment.tag_name + end + + test "action_text.config.attachment_tag_name is 'action-text-attachment' without defaults" do + remove_from_config '.*config\.load_defaults.*\n' + + app "development" + + assert_equal "action-text-attachment", ActionText::Attachment.tag_name + end + + test "action_text.config.attachment_tag_name is can be overriden" do + add_to_config "config.action_text.attachment_tag_name = 'link'" + + app "development" + + assert_equal "link", ActionText::Attachment.tag_name + end + test "ActionMailbox.logger is Rails.logger by default" do app "development"