actiontext5 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitattributes +2 -0
- data/.gitignore +13 -0
- data/.travis.yml +17 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +140 -0
- data/LICENSE +21 -0
- data/README.md +1 -0
- data/Rakefile +27 -0
- data/actiontext.gemspec +29 -0
- data/app/helpers/action_text/content_helper.rb +30 -0
- data/app/helpers/action_text/tag_helper.rb +75 -0
- data/app/javascript/actiontext/attachment_upload.js +45 -0
- data/app/javascript/actiontext/index.js +11 -0
- data/app/models/action_text/rich_text.rb +25 -0
- data/app/views/action_text/attachables/_missing_attachable.html.erb +1 -0
- data/app/views/action_text/attachables/_remote_image.html.erb +8 -0
- data/app/views/action_text/attachment_galleries/_attachment_gallery.html.erb +3 -0
- data/app/views/action_text/content/_layout.html.erb +3 -0
- data/app/views/active_storage/blobs/_blob.html.erb +14 -0
- data/bin/test +6 -0
- data/bin/webpack +29 -0
- data/bin/webpack-dev-server +29 -0
- data/db/migrate/201805281641_create_action_text_tables.rb +14 -0
- data/lib/action_text/attachable.rb +82 -0
- data/lib/action_text/attachables/content_attachment.rb +38 -0
- data/lib/action_text/attachables/missing_attachable.rb +11 -0
- data/lib/action_text/attachables/remote_image.rb +46 -0
- data/lib/action_text/attachment.rb +103 -0
- data/lib/action_text/attachment_gallery.rb +65 -0
- data/lib/action_text/attachments/caching.rb +16 -0
- data/lib/action_text/attachments/minification.rb +17 -0
- data/lib/action_text/attachments/trix_conversion.rb +34 -0
- data/lib/action_text/attribute.rb +48 -0
- data/lib/action_text/content.rb +126 -0
- data/lib/action_text/engine.rb +45 -0
- data/lib/action_text/fragment.rb +57 -0
- data/lib/action_text/html_conversion.rb +24 -0
- data/lib/action_text/plain_text_conversion.rb +81 -0
- data/lib/action_text/serialization.rb +34 -0
- data/lib/action_text/trix_attachment.rb +92 -0
- data/lib/action_text/version.rb +5 -0
- data/lib/action_text.rb +38 -0
- data/lib/actiontext5.rb +1 -0
- data/lib/tasks/actiontext.rake +20 -0
- data/lib/templates/actiontext.scss +36 -0
- data/lib/templates/fixtures.yml +4 -0
- data/lib/templates/installer.rb +22 -0
- data/package.json +21 -0
- data/test/dummy/.babelrc +18 -0
- data/test/dummy/.postcssrc.yml +3 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/config/manifest.js +3 -0
- data/test/dummy/app/assets/images/.keep +0 -0
- data/test/dummy/app/assets/stylesheets/application.css +16 -0
- data/test/dummy/app/assets/stylesheets/messages.css +4 -0
- data/test/dummy/app/assets/stylesheets/scaffold.css +80 -0
- data/test/dummy/app/channels/application_cable/channel.rb +4 -0
- data/test/dummy/app/channels/application_cable/connection.rb +4 -0
- data/test/dummy/app/controllers/application_controller.rb +2 -0
- data/test/dummy/app/controllers/concerns/.keep +0 -0
- data/test/dummy/app/controllers/messages_controller.rb +58 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/helpers/messages_helper.rb +2 -0
- data/test/dummy/app/javascript/packs/application.js +1 -0
- data/test/dummy/app/jobs/application_job.rb +2 -0
- data/test/dummy/app/mailers/application_mailer.rb +4 -0
- data/test/dummy/app/models/application_record.rb +3 -0
- data/test/dummy/app/models/concerns/.keep +0 -0
- data/test/dummy/app/models/message.rb +4 -0
- data/test/dummy/app/models/person.rb +7 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/app/views/layouts/mailer.html.erb +13 -0
- data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
- data/test/dummy/app/views/messages/_form.html.erb +27 -0
- data/test/dummy/app/views/messages/edit.html.erb +6 -0
- data/test/dummy/app/views/messages/index.html.erb +29 -0
- data/test/dummy/app/views/messages/new.html.erb +5 -0
- data/test/dummy/app/views/messages/show.html.erb +13 -0
- data/test/dummy/app/views/people/_trix_content_attachment.html.erb +3 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +36 -0
- data/test/dummy/bin/update +31 -0
- data/test/dummy/bin/yarn +11 -0
- data/test/dummy/config/application.rb +19 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/cable.yml +10 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +63 -0
- data/test/dummy/config/environments/production.rb +96 -0
- data/test/dummy/config/environments/test.rb +46 -0
- data/test/dummy/config/initializers/application_controller_renderer.rb +8 -0
- data/test/dummy/config/initializers/assets.rb +14 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/content_security_policy.rb +22 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +33 -0
- data/test/dummy/config/puma.rb +34 -0
- data/test/dummy/config/routes.rb +4 -0
- data/test/dummy/config/spring.rb +6 -0
- data/test/dummy/config/storage.yml +35 -0
- data/test/dummy/config/webpack/development.js +3 -0
- data/test/dummy/config/webpack/environment.js +3 -0
- data/test/dummy/config/webpack/production.js +3 -0
- data/test/dummy/config/webpack/test.js +3 -0
- data/test/dummy/config/webpacker.yml +65 -0
- data/test/dummy/config.ru +5 -0
- data/test/dummy/db/migrate/20180208205311_create_messages.rb +8 -0
- data/test/dummy/db/migrate/20180212164506_create_active_storage_tables.active_storage.rb +26 -0
- data/test/dummy/db/migrate/2018052816_create_action_text_tables.rb +14 -0
- data/test/dummy/db/migrate/20181003185713_create_people.rb +9 -0
- data/test/dummy/db/schema.rb +58 -0
- data/test/dummy/lib/assets/.keep +0 -0
- data/test/dummy/log/.keep +0 -0
- data/test/dummy/package.json +11 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/apple-touch-icon-precomposed.png +0 -0
- data/test/dummy/public/apple-touch-icon.png +0 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/storage/.keep +0 -0
- data/test/dummy/tmp/.keep +0 -0
- data/test/dummy/tmp/storage/.keep +0 -0
- data/test/dummy/yarn.lock +6071 -0
- data/test/fixtures/files/racecar.jpg +0 -0
- data/test/template/form_helper_test.rb +71 -0
- data/test/test_helper.rb +30 -0
- data/test/unit/attachment_test.rb +60 -0
- data/test/unit/content_test.rb +116 -0
- data/test/unit/model_test.rb +47 -0
- data/test/unit/plain_text_conversion_test.rb +94 -0
- data/test/unit/trix_attachment_test.rb +83 -0
- data/yarn.lock +11 -0
- metadata +372 -0
|
Binary file
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
|
|
5
|
+
class ActionText::FormHelperTest < ActionView::TestCase
|
|
6
|
+
tests ActionText::TagHelper
|
|
7
|
+
|
|
8
|
+
test "form with rich text area" do
|
|
9
|
+
form_with model: Message.new, scope: :message do |form|
|
|
10
|
+
form.rich_text_area :content
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
assert_dom_equal \
|
|
14
|
+
'<form action="/messages" accept-charset="UTF-8" data-remote="true" method="post">' \
|
|
15
|
+
'<input name="utf8" type="hidden" value="✓" />' \
|
|
16
|
+
'<input type="hidden" name="message[content]" id="message_content_trix_input_message" />' \
|
|
17
|
+
'<trix-editor id="message_content" input="message_content_trix_input_message" class="trix-content" data-direct-upload-url="http://test.host/rails/active_storage/direct_uploads" data-blob-url-template="http://test.host/rails/active_storage/blobs/:signed_id/:filename">' \
|
|
18
|
+
'</trix-editor>' \
|
|
19
|
+
'</form>',
|
|
20
|
+
output_buffer
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
test "form with rich text area having class" do
|
|
24
|
+
form_with model: Message.new, scope: :message do |form|
|
|
25
|
+
form.rich_text_area :content, class: "custom-class"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
assert_dom_equal \
|
|
29
|
+
'<form action="/messages" accept-charset="UTF-8" data-remote="true" method="post">' \
|
|
30
|
+
'<input name="utf8" type="hidden" value="✓" />' \
|
|
31
|
+
'<input type="hidden" name="message[content]" id="message_content_trix_input_message" />' \
|
|
32
|
+
'<trix-editor id="message_content" input="message_content_trix_input_message" class="custom-class" data-direct-upload-url="http://test.host/rails/active_storage/direct_uploads" data-blob-url-template="http://test.host/rails/active_storage/blobs/:signed_id/:filename">' \
|
|
33
|
+
'</trix-editor>' \
|
|
34
|
+
'</form>',
|
|
35
|
+
output_buffer
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
test "form with rich text area for non-attribute" do
|
|
39
|
+
form_with model: Message.new, scope: :message do |form|
|
|
40
|
+
form.rich_text_area :not_an_attribute
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
assert_dom_equal \
|
|
44
|
+
'<form action="/messages" accept-charset="UTF-8" data-remote="true" method="post">' \
|
|
45
|
+
'<input name="utf8" type="hidden" value="✓" />' \
|
|
46
|
+
'<input type="hidden" name="message[not_an_attribute]" id="message_not_an_attribute_trix_input_message" />' \
|
|
47
|
+
'<trix-editor id="message_not_an_attribute" input="message_not_an_attribute_trix_input_message" class="trix-content" data-direct-upload-url="http://test.host/rails/active_storage/direct_uploads" data-blob-url-template="http://test.host/rails/active_storage/blobs/:signed_id/:filename">' \
|
|
48
|
+
'</trix-editor>' \
|
|
49
|
+
'</form>',
|
|
50
|
+
output_buffer
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
test "modelless form with rich text area" do
|
|
54
|
+
form_with url: "/messages", scope: :message do |form|
|
|
55
|
+
form.rich_text_area :content
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
assert_dom_equal \
|
|
59
|
+
'<form action="/messages" accept-charset="UTF-8" data-remote="true" method="post">' \
|
|
60
|
+
'<input name="utf8" type="hidden" value="✓" />' \
|
|
61
|
+
'<input type="hidden" name="message[content]" id="trix_input_1" />' \
|
|
62
|
+
'<trix-editor id="message_content" input="trix_input_1" class="trix-content" data-direct-upload-url="http://test.host/rails/active_storage/direct_uploads" data-blob-url-template="http://test.host/rails/active_storage/blobs/:signed_id/:filename">' \
|
|
63
|
+
'</trix-editor>' \
|
|
64
|
+
'</form>',
|
|
65
|
+
output_buffer
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def form_with(*)
|
|
69
|
+
@output_buffer = super
|
|
70
|
+
end
|
|
71
|
+
end
|
data/test/test_helper.rb
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Configure Rails Environment
|
|
4
|
+
ENV["RAILS_ENV"] = "test"
|
|
5
|
+
|
|
6
|
+
require_relative "../test/dummy/config/environment"
|
|
7
|
+
ActiveRecord::Migrator.migrations_paths = [File.expand_path("../test/dummy/db/migrate", __dir__)]
|
|
8
|
+
require "rails/test_help"
|
|
9
|
+
|
|
10
|
+
# Filter out Minitest backtrace while allowing backtrace from other libraries
|
|
11
|
+
# to be shown.
|
|
12
|
+
Minitest.backtrace_filter = Minitest::BacktraceFilter.new
|
|
13
|
+
|
|
14
|
+
require "rails/test_unit/reporter"
|
|
15
|
+
Rails::TestUnitReporter.executable = 'bin/test'
|
|
16
|
+
|
|
17
|
+
# Load fixtures from the engine
|
|
18
|
+
if ActiveSupport::TestCase.respond_to?(:fixture_path=)
|
|
19
|
+
ActiveSupport::TestCase.fixture_path = File.expand_path("fixtures", __dir__)
|
|
20
|
+
ActionDispatch::IntegrationTest.fixture_path = ActiveSupport::TestCase.fixture_path
|
|
21
|
+
ActiveSupport::TestCase.file_fixture_path = ActiveSupport::TestCase.fixture_path + "/files"
|
|
22
|
+
ActiveSupport::TestCase.fixtures :all
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
class ActiveSupport::TestCase
|
|
26
|
+
private
|
|
27
|
+
def create_file_blob(filename:, content_type:, metadata: nil)
|
|
28
|
+
ActiveStorage::Blob.create_after_upload! io: file_fixture(filename).open, filename: filename, content_type: content_type, metadata: metadata
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
|
|
5
|
+
class ActionText::AttachmentTest < ActiveSupport::TestCase
|
|
6
|
+
test "from_attachable" do
|
|
7
|
+
attachment = ActionText::Attachment.from_attachable(attachable, caption: "Captioned")
|
|
8
|
+
assert_equal attachable, attachment.attachable
|
|
9
|
+
assert_equal "Captioned", attachment.caption
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
test "proxies missing methods to attachable" do
|
|
13
|
+
attachable.instance_eval { def proxied; "proxied"; end }
|
|
14
|
+
attachment = ActionText::Attachment.from_attachable(attachable)
|
|
15
|
+
assert_equal "proxied", attachment.proxied
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
test "proxies #to_param to attachable" do
|
|
19
|
+
attachment = ActionText::Attachment.from_attachable(attachable)
|
|
20
|
+
assert_equal attachable.to_param, attachment.to_param
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
test "converts to TrixAttachment" do
|
|
24
|
+
attachment = attachment_from_html(%Q(<action-text-attachment sgid="#{attachable.attachable_sgid}" caption="Captioned"></action-text-attachment>))
|
|
25
|
+
|
|
26
|
+
trix_attachment = attachment.to_trix_attachment
|
|
27
|
+
assert_kind_of ActionText::TrixAttachment, trix_attachment
|
|
28
|
+
|
|
29
|
+
assert_equal attachable.attachable_sgid, trix_attachment.attributes["sgid"]
|
|
30
|
+
assert_equal attachable.attachable_content_type, trix_attachment.attributes["contentType"]
|
|
31
|
+
assert_equal attachable.filename.to_s, trix_attachment.attributes["filename"]
|
|
32
|
+
assert_equal attachable.byte_size, trix_attachment.attributes["filesize"]
|
|
33
|
+
assert_equal "Captioned", trix_attachment.attributes["caption"]
|
|
34
|
+
|
|
35
|
+
assert_nil trix_attachment.attributes["content"]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
test "converts to TrixAttachment with content" do
|
|
39
|
+
attachable = Person.create! name: "Javan"
|
|
40
|
+
attachment = attachment_from_html(%Q(<action-text-attachment sgid="#{attachable.attachable_sgid}"></action-text-attachment>))
|
|
41
|
+
|
|
42
|
+
trix_attachment = attachment.to_trix_attachment
|
|
43
|
+
assert_kind_of ActionText::TrixAttachment, trix_attachment
|
|
44
|
+
|
|
45
|
+
assert_equal attachable.attachable_sgid, trix_attachment.attributes["sgid"]
|
|
46
|
+
assert_equal attachable.attachable_content_type, trix_attachment.attributes["contentType"]
|
|
47
|
+
|
|
48
|
+
assert_not_nil attachable.to_trix_content_attachment_partial_path
|
|
49
|
+
assert_not_nil trix_attachment.attributes["content"]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
def attachment_from_html(html)
|
|
54
|
+
ActionText::Content.new(html).attachments.first
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def attachable
|
|
58
|
+
@attachment ||= create_file_blob(filename: "racecar.jpg", content_type: "image/jpg")
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
|
|
5
|
+
class ActionText::ContentTest < ActiveSupport::TestCase
|
|
6
|
+
test "equality" do
|
|
7
|
+
html = %Q(<div>test</div>)
|
|
8
|
+
content = content_from_html(html)
|
|
9
|
+
assert_equal content, content_from_html(html)
|
|
10
|
+
assert_not_equal content, html
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
test "marshal serialization" do
|
|
14
|
+
content = content_from_html("Hello!")
|
|
15
|
+
assert_equal content, Marshal.load(Marshal.dump(content))
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
test "roundtrips HTML without additional newlines" do
|
|
19
|
+
html = %Q(<div>a<br></div>)
|
|
20
|
+
content = content_from_html(html)
|
|
21
|
+
assert_equal html, content.to_html
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
test "extracts links" do
|
|
25
|
+
html = %Q(<a href="http://example.com/1">1</a><br><a href="http://example.com/1">1</a>)
|
|
26
|
+
content = content_from_html(html)
|
|
27
|
+
assert_equal ["http://example.com/1"], content.links
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
test "extracts attachables" do
|
|
31
|
+
attachable = create_file_blob(filename: "racecar.jpg", content_type: "image/jpg")
|
|
32
|
+
html = %Q(<action-text-attachment sgid="#{attachable.attachable_sgid}" caption="Captioned"></action-text-attachment>)
|
|
33
|
+
|
|
34
|
+
content = content_from_html(html)
|
|
35
|
+
assert_equal 1, content.attachments.size
|
|
36
|
+
|
|
37
|
+
attachment = content.attachments.first
|
|
38
|
+
assert_equal "Captioned", attachment.caption
|
|
39
|
+
assert_equal attachable, attachment.attachable
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
test "extracts remote image attachables" do
|
|
43
|
+
html = %Q(<action-text-attachment content-type="image" url="http://example.com/cat.jpg" width="100" height="100" caption="Captioned"></action-text-attachment>)
|
|
44
|
+
|
|
45
|
+
content = content_from_html(html)
|
|
46
|
+
assert_equal 1, content.attachments.size
|
|
47
|
+
|
|
48
|
+
attachment = content.attachments.first
|
|
49
|
+
assert_equal "Captioned", attachment.caption
|
|
50
|
+
|
|
51
|
+
attachable = attachment.attachable
|
|
52
|
+
assert_kind_of ActionText::Attachables::RemoteImage, attachable
|
|
53
|
+
assert_equal "http://example.com/cat.jpg", attachable.url
|
|
54
|
+
assert_equal "100", attachable.width
|
|
55
|
+
assert_equal "100", attachable.height
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
test "identifies destroyed attachables as missing" do
|
|
59
|
+
attachable = create_file_blob(filename: "racecar.jpg", content_type: "image/jpg")
|
|
60
|
+
html = %Q(<action-text-attachment sgid="#{attachable.attachable_sgid}"></action-text-attachment>)
|
|
61
|
+
attachable.destroy!
|
|
62
|
+
content = content_from_html(html)
|
|
63
|
+
assert_equal 1, content.attachments.size
|
|
64
|
+
assert_equal ActionText::Attachables::MissingAttachable, content.attachments.first.attachable
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
test "extracts missing attachables" do
|
|
68
|
+
html = %Q(<action-text-attachment sgid="missing"></action-text-attachment>)
|
|
69
|
+
content = content_from_html(html)
|
|
70
|
+
assert_equal 1, content.attachments.size
|
|
71
|
+
assert_equal ActionText::Attachables::MissingAttachable, content.attachments.first.attachable
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
test "converts Trix-formatted attachments" do
|
|
75
|
+
html = %Q(<figure data-trix-attachment='{"sgid":"123","contentType":"text/plain","width":100,"height":100}' data-trix-attributes='{"caption":"Captioned"}'></figure>)
|
|
76
|
+
content = content_from_html(html)
|
|
77
|
+
assert_equal 1, content.attachments.size
|
|
78
|
+
assert_equal %Q(<action-text-attachment sgid="123" content-type="text/plain" width="100" height="100" caption="Captioned"></action-text-attachment>), content.to_html
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
test "ignores Trix-formatted attachments with malformed JSON" do
|
|
82
|
+
html = %Q(<div data-trix-attachment='{"sgid":"garbage...'></div>)
|
|
83
|
+
content = content_from_html(html)
|
|
84
|
+
assert_equal 0, content.attachments.size
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
test "minifies attachment markup" do
|
|
88
|
+
html = %Q(<action-text-attachment sgid="123"><div>HTML</div></action-text-attachment>)
|
|
89
|
+
assert_equal %Q(<action-text-attachment sgid="123"></action-text-attachment>), content_from_html(html).to_html
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
test "canonicalizes attachment gallery markup" do
|
|
93
|
+
attachment_html = %Q(<action-text-attachment sgid="1" presentation="gallery"></action-text-attachment><action-text-attachment sgid="2" presentation="gallery"></action-text-attachment>)
|
|
94
|
+
html = %Q(<div class="attachment-gallery attachment-gallery--2">#{attachment_html}</div>)
|
|
95
|
+
assert_equal %Q(<div>#{attachment_html}</div>), content_from_html(html).to_html
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
test "canonicalizes attachment gallery markup with whitespace" do
|
|
99
|
+
attachment_html = %Q(\n <action-text-attachment sgid="1" presentation="gallery"></action-text-attachment>\n <action-text-attachment sgid="2" presentation="gallery"></action-text-attachment>\n)
|
|
100
|
+
html = %Q(<div class="attachment-gallery attachment-gallery--2">#{attachment_html}</div>)
|
|
101
|
+
assert_equal %Q(<div>#{attachment_html}</div>), content_from_html(html).to_html
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
test "canonicalizes nested attachment gallery markup" do
|
|
105
|
+
attachment_html = %Q(<action-text-attachment sgid="1" presentation="gallery"></action-text-attachment><action-text-attachment sgid="2" presentation="gallery"></action-text-attachment>)
|
|
106
|
+
html = %Q(<blockquote><div class="attachment-gallery attachment-gallery--2">#{attachment_html}</div></blockquote>)
|
|
107
|
+
assert_equal %Q(<blockquote><div>#{attachment_html}</div></blockquote>), content_from_html(html).to_html
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
private
|
|
111
|
+
def content_from_html(html)
|
|
112
|
+
ActionText::Content.new(html).tap do |content|
|
|
113
|
+
assert_nothing_raised { content.to_s }
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
|
|
5
|
+
class ActionText::ModelTest < ActiveSupport::TestCase
|
|
6
|
+
test "html conversion" do
|
|
7
|
+
message = Message.new(subject: "Greetings", content: "<h1>Hello world</h1>")
|
|
8
|
+
assert_equal %Q(<div class="trix-content">\n <h1>Hello world</h1>\n</div>\n), "#{message.content}"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
test "plain text conversion" do
|
|
12
|
+
message = Message.new(subject: "Greetings", content: "<h1>Hello world</h1>")
|
|
13
|
+
assert_equal "Hello world", message.content.to_plain_text
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
test "without content" do
|
|
17
|
+
message = Message.create!(subject: "Greetings")
|
|
18
|
+
assert message.content.nil?
|
|
19
|
+
assert message.content.blank?
|
|
20
|
+
assert message.content.empty?
|
|
21
|
+
assert_not message.content.present?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
test "with blank content" do
|
|
25
|
+
message = Message.create!(subject: "Greetings", content: "")
|
|
26
|
+
assert_not message.content.nil?
|
|
27
|
+
assert message.content.blank?
|
|
28
|
+
assert message.content.empty?
|
|
29
|
+
assert_not message.content.present?
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
test "embed extraction" do
|
|
33
|
+
blob = create_file_blob(filename: "racecar.jpg", content_type: "image/jpg")
|
|
34
|
+
message = Message.create!(subject: "Greetings", content: ActionText::Content.new("Hello world").append_attachables(blob))
|
|
35
|
+
assert_equal "racecar.jpg", message.content.embeds.first.filename.to_s
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
test "saving content" do
|
|
39
|
+
message = Message.create!(subject: "Greetings", content: "<h1>Hello world</h1>")
|
|
40
|
+
assert_equal "Hello world", message.content.to_plain_text
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
test "save body" do
|
|
44
|
+
message = Message.create(subject: "Greetings", body: "<h1>Hello world</h1>")
|
|
45
|
+
assert_equal "Hello world", message.body.to_plain_text
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
|
|
5
|
+
class ActionText::PlainTextConversionTest < ActiveSupport::TestCase
|
|
6
|
+
test "<p> tags are separated by two new lines" do
|
|
7
|
+
assert_converted_to(
|
|
8
|
+
"Hello world!\n\nHow are you?",
|
|
9
|
+
"<p>Hello world!</p><p>How are you?</p>"
|
|
10
|
+
)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
test "<blockquote> tags are separated by two new lines" do
|
|
14
|
+
assert_converted_to(
|
|
15
|
+
"“Hello world!”\n\n“How are you?”",
|
|
16
|
+
"<blockquote>Hello world!</blockquote><blockquote>How are you?</blockquote>"
|
|
17
|
+
)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
test "<ol> tags are separated by two new lines" do
|
|
21
|
+
assert_converted_to(
|
|
22
|
+
"Hello world!\n\n1. list1\n\n1. list2\n\nHow are you?",
|
|
23
|
+
"<p>Hello world!</p><ol><li>list1</li></ol><ol><li>list2</li></ol><p>How are you?</p>"
|
|
24
|
+
)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
test "<ul> tags are separated by two new lines" do
|
|
28
|
+
assert_converted_to(
|
|
29
|
+
"Hello world!\n\n• list1\n\n• list2\n\nHow are you?",
|
|
30
|
+
"<p>Hello world!</p><ul><li>list1</li></ul><ul><li>list2</li></ul><p>How are you?</p>"
|
|
31
|
+
)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
test "<h1> tags are separated by two new lines" do
|
|
35
|
+
assert_converted_to(
|
|
36
|
+
"Hello world!\n\nHow are you?",
|
|
37
|
+
"<h1>Hello world!</h1><div>How are you?</div>"
|
|
38
|
+
)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
test "<li> tags are separated by one new line" do
|
|
42
|
+
assert_converted_to(
|
|
43
|
+
"• one\n• two\n• three",
|
|
44
|
+
"<ul><li>one</li><li>two</li><li>three</li></ul>"
|
|
45
|
+
)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
test "<li> tags without a parent list" do
|
|
49
|
+
assert_converted_to(
|
|
50
|
+
"• one\n• two\n• three",
|
|
51
|
+
"<li>one</li><li>two</li><li>three</li>"
|
|
52
|
+
)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
test "<br> tags are separated by one new line" do
|
|
56
|
+
assert_converted_to(
|
|
57
|
+
"Hello world!\none\ntwo\nthree",
|
|
58
|
+
"<p>Hello world!<br>one<br>two<br>three</p>"
|
|
59
|
+
)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
test "<div> tags are separated by one new line" do
|
|
63
|
+
assert_converted_to(
|
|
64
|
+
"Hello world!\nHow are you?",
|
|
65
|
+
"<div>Hello world!</div><div>How are you?</div>"
|
|
66
|
+
)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
test "<action-text-attachment> tags are converted to their plain-text representation" do
|
|
70
|
+
assert_converted_to(
|
|
71
|
+
"Hello world! [Cat]",
|
|
72
|
+
%Q(Hello world! <action-text-attachment url="http://example.com/cat.jpg" content-type="image" caption="Cat"></action-text-attachment>)
|
|
73
|
+
)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
test "preserves non-linebreak whitespace after text" do
|
|
77
|
+
assert_converted_to(
|
|
78
|
+
"Hello world!",
|
|
79
|
+
%Q(<div><strong>Hello </strong>world!</div>)
|
|
80
|
+
)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
test "preserves trailing linebreaks after text" do
|
|
84
|
+
assert_converted_to(
|
|
85
|
+
"Hello\nHow are you?",
|
|
86
|
+
"<strong>Hello<br></strong>How are you?"
|
|
87
|
+
)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
private
|
|
91
|
+
def assert_converted_to(plain_text, html)
|
|
92
|
+
assert_equal plain_text, ActionText::Content.new(html).to_plain_text
|
|
93
|
+
end
|
|
94
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
|
|
5
|
+
class ActionText::TrixAttachmentTest < ActiveSupport::TestCase
|
|
6
|
+
test "from_attributes" do
|
|
7
|
+
attributes = {
|
|
8
|
+
"data-trix-attachment" => {
|
|
9
|
+
"sgid" => "123",
|
|
10
|
+
"contentType" => "text/plain",
|
|
11
|
+
"href" => "http://example.com/",
|
|
12
|
+
"filename" => "example.txt",
|
|
13
|
+
"filesize" => 12345,
|
|
14
|
+
"previewable" => true
|
|
15
|
+
},
|
|
16
|
+
"data-trix-attributes" => {
|
|
17
|
+
"caption" => "hello"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
attachment = attachment(
|
|
22
|
+
sgid: "123",
|
|
23
|
+
content_type: "text/plain",
|
|
24
|
+
href: "http://example.com/",
|
|
25
|
+
filename: "example.txt",
|
|
26
|
+
filesize: "12345",
|
|
27
|
+
previewable: "true",
|
|
28
|
+
caption: "hello"
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
assert_attachment_json_attributes(attachment, attributes)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
test "previewable is typecast" do
|
|
35
|
+
assert_attachment_attribute(attachment(previewable: ""), "previewable", false)
|
|
36
|
+
assert_attachment_attribute(attachment(previewable: false), "previewable", false)
|
|
37
|
+
assert_attachment_attribute(attachment(previewable: "false"), "previewable", false)
|
|
38
|
+
assert_attachment_attribute(attachment(previewable: "garbage"), "previewable", false)
|
|
39
|
+
assert_attachment_attribute(attachment(previewable: true), "previewable", true)
|
|
40
|
+
assert_attachment_attribute(attachment(previewable: "true"), "previewable", true)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
test "filesize is typecast when integer-like" do
|
|
44
|
+
assert_attachment_attribute(attachment(filesize: 123), "filesize", 123)
|
|
45
|
+
assert_attachment_attribute(attachment(filesize: "123"), "filesize", 123)
|
|
46
|
+
assert_attachment_attribute(attachment(filesize: "3.5 MB"), "filesize", "3.5 MB")
|
|
47
|
+
assert_attachment_attribute(attachment(filesize: nil), "filesize", nil)
|
|
48
|
+
assert_attachment_attribute(attachment(filesize: ""), "filesize", "")
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
test "#attributes strips unmappable attributes" do
|
|
52
|
+
attributes = {
|
|
53
|
+
"sgid" => "123",
|
|
54
|
+
"caption" => "hello"
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
attachment = attachment(sgid: "123", caption: "hello", nonexistent: "garbage")
|
|
58
|
+
assert_attachment_attributes(attachment, attributes)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def assert_attachment_attribute(attachment, name, value)
|
|
62
|
+
if value.nil?
|
|
63
|
+
assert_nil(attachment.attributes[name])
|
|
64
|
+
else
|
|
65
|
+
assert_equal(value, attachment.attributes[name])
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def assert_attachment_attributes(attachment, attributes)
|
|
70
|
+
assert_equal(attributes, attachment.attributes)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def assert_attachment_json_attributes(attachment, attributes)
|
|
74
|
+
attributes.each do |name, expected|
|
|
75
|
+
actual = JSON.parse(attachment.node[name])
|
|
76
|
+
assert_equal(expected, actual)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def attachment(**attributes)
|
|
81
|
+
ActionText::TrixAttachment.from_attributes(attributes)
|
|
82
|
+
end
|
|
83
|
+
end
|
data/yarn.lock
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
|
2
|
+
# yarn lockfile v1
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
"activestorage@>= 5.2.0-rc1":
|
|
6
|
+
version "5.2.0-rc1"
|
|
7
|
+
resolved "https://registry.yarnpkg.com/activestorage/-/activestorage-5.2.0-rc1.tgz#79898996eceb0f13575eff41fb109051fbfa49b0"
|
|
8
|
+
|
|
9
|
+
trix@^0.11.1:
|
|
10
|
+
version "0.11.1"
|
|
11
|
+
resolved "https://registry.yarnpkg.com/trix/-/trix-0.11.1.tgz#ffe54f2757c2c2385b8424fd5c5d2ab712a09acc"
|