actiontext 7.1.5 → 7.2.0.beta1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actiontext might be problematic. Click here for more details.

Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +19 -129
  3. data/app/assets/javascripts/actiontext.esm.js +3 -3
  4. data/app/assets/javascripts/actiontext.js +3 -3
  5. data/app/helpers/action_text/content_helper.rb +2 -9
  6. data/app/helpers/action_text/tag_helper.rb +38 -28
  7. data/app/models/action_text/encrypted_rich_text.rb +2 -2
  8. data/app/models/action_text/record.rb +2 -0
  9. data/app/models/action_text/rich_text.rb +58 -26
  10. data/db/migrate/20180528164100_create_action_text_tables.rb +1 -1
  11. data/lib/action_text/attachable.rb +35 -33
  12. data/lib/action_text/attachables/content_attachment.rb +2 -0
  13. data/lib/action_text/attachables/missing_attachable.rb +2 -0
  14. data/lib/action_text/attachables/remote_image.rb +2 -0
  15. data/lib/action_text/attachment.rb +27 -25
  16. data/lib/action_text/attachment_gallery.rb +2 -0
  17. data/lib/action_text/attachments/caching.rb +2 -0
  18. data/lib/action_text/attachments/minification.rb +2 -0
  19. data/lib/action_text/attachments/trix_conversion.rb +2 -0
  20. data/lib/action_text/attribute.rb +36 -22
  21. data/lib/action_text/content.rb +47 -31
  22. data/lib/action_text/deprecator.rb +2 -0
  23. data/lib/action_text/encryption.rb +2 -0
  24. data/lib/action_text/engine.rb +2 -0
  25. data/lib/action_text/fixture_set.rb +34 -34
  26. data/lib/action_text/fragment.rb +4 -0
  27. data/lib/action_text/gem_version.rb +6 -4
  28. data/lib/action_text/html_conversion.rb +2 -0
  29. data/lib/action_text/plain_text_conversion.rb +3 -6
  30. data/lib/action_text/rendering.rb +2 -0
  31. data/lib/action_text/serialization.rb +2 -0
  32. data/lib/action_text/system_test_helper.rb +20 -17
  33. data/lib/action_text/trix_attachment.rb +2 -0
  34. data/lib/action_text/version.rb +3 -1
  35. data/lib/generators/action_text/install/install_generator.rb +10 -3
  36. data/lib/rails/generators/test_unit/install_generator.rb +2 -0
  37. data/package.json +1 -1
  38. metadata +18 -18
@@ -1,19 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "active_support/core_ext/object/try"
4
6
 
5
7
  module ActionText
6
- # = Action Text \Attachment
8
+ # # Action Text Attachment
7
9
  #
8
10
  # Attachments serialize attachables to HTML or plain text.
9
11
  #
10
- # class Person < ApplicationRecord
11
- # include ActionText::Attachable
12
- # end
12
+ # class Person < ApplicationRecord
13
+ # include ActionText::Attachable
14
+ # end
13
15
  #
14
- # attachable = Person.create! name: "Javan"
15
- # attachment = ActionText::Attachment.from_attachable(attachable)
16
- # attachment.to_html # => "<action-text-attachment sgid=\"BAh7CEk..."
16
+ # attachable = Person.create! name: "Javan"
17
+ # attachment = ActionText::Attachment.from_attachable(attachable)
18
+ # attachment.to_html # => "<action-text-attachment sgid=\"BAh7CEk..."
17
19
  class Attachment
18
20
  include Attachments::TrixConversion, Attachments::Minification, Attachments::Caching
19
21
 
@@ -82,29 +84,29 @@ module ActionText
82
84
 
83
85
  # Converts the attachment to plain text.
84
86
  #
85
- # attachable = ActiveStorage::Blob.find_by filename: "racecar.jpg"
86
- # attachment = ActionText::Attachment.from_attachable(attachable)
87
- # attachment.to_plain_text # => "[racecar.jpg]"
87
+ # attachable = ActiveStorage::Blob.find_by filename: "racecar.jpg"
88
+ # attachment = ActionText::Attachment.from_attachable(attachable)
89
+ # attachment.to_plain_text # => "[racecar.jpg]"
88
90
  #
89
- # Use the +caption+ when set:
91
+ # Use the `caption` when set:
90
92
  #
91
- # attachment = ActionText::Attachment.from_attachable(attachable, caption: "Vroom vroom")
92
- # attachment.to_plain_text # => "[Vroom vroom]"
93
+ # attachment = ActionText::Attachment.from_attachable(attachable, caption: "Vroom vroom")
94
+ # attachment.to_plain_text # => "[Vroom vroom]"
93
95
  #
94
96
  # The presentation can be overridden by implementing the
95
- # +attachable_plain_text_representation+ method:
97
+ # `attachable_plain_text_representation` method:
96
98
  #
97
- # class Person < ApplicationRecord
98
- # include ActionText::Attachable
99
+ # class Person < ApplicationRecord
100
+ # include ActionText::Attachable
99
101
  #
100
- # def attachable_plain_text_representation
101
- # "[#{name}]"
102
+ # def attachable_plain_text_representation
103
+ # "[#{name}]"
104
+ # end
102
105
  # end
103
- # end
104
106
  #
105
- # attachable = Person.create! name: "Javan"
106
- # attachment = ActionText::Attachment.from_attachable(attachable)
107
- # attachment.to_plain_text # => "[Javan]"
107
+ # attachable = Person.create! name: "Javan"
108
+ # attachment = ActionText::Attachment.from_attachable(attachable)
109
+ # attachment.to_plain_text # => "[Javan]"
108
110
  def to_plain_text
109
111
  if respond_to?(:attachable_plain_text_representation)
110
112
  attachable_plain_text_representation(caption)
@@ -115,9 +117,9 @@ module ActionText
115
117
 
116
118
  # Converts the attachment to HTML.
117
119
  #
118
- # attachable = Person.create! name: "Javan"
119
- # attachment = ActionText::Attachment.from_attachable(attachable)
120
- # attachment.to_html # => "<action-text-attachment sgid=\"BAh7CEk...
120
+ # attachable = Person.create! name: "Javan"
121
+ # attachment = ActionText::Attachment.from_attachable(attachable)
122
+ # attachment.to_html # => "<action-text-attachment sgid=\"BAh7CEk...
121
123
  def to_html
122
124
  HtmlConversion.node_to_html(node)
123
125
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionText
4
6
  class AttachmentGallery
5
7
  include ActiveModel::Model
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionText
4
6
  module Attachments
5
7
  module Caching
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionText
4
6
  module Attachments
5
7
  module Minification
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "active_support/core_ext/object/try"
4
6
 
5
7
  module ActionText
@@ -1,39 +1,52 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionText
4
6
  module Attribute
5
7
  extend ActiveSupport::Concern
6
8
 
7
9
  class_methods do
8
- # Provides access to a dependent RichText model that holds the body and attachments for a single named rich text attribute.
9
- # This dependent attribute is lazily instantiated and will be auto-saved when it's been changed. Example:
10
+ # Provides access to a dependent RichText model that holds the body and
11
+ # attachments for a single named rich text attribute. This dependent attribute
12
+ # is lazily instantiated and will be auto-saved when it's been changed. Example:
13
+ #
14
+ # class Message < ActiveRecord::Base
15
+ # has_rich_text :content
16
+ # end
17
+ #
18
+ # message = Message.create!(content: "<h1>Funny times!</h1>")
19
+ # message.content? #=> true
20
+ # message.content.to_s # => "<h1>Funny times!</h1>"
21
+ # message.content.to_plain_text # => "Funny times!"
10
22
  #
11
- # class Message < ActiveRecord::Base
12
- # has_rich_text :content
13
- # end
23
+ # The dependent RichText model will also automatically process attachments links
24
+ # as sent via the Trix-powered editor. These attachments are associated with the
25
+ # RichText model using Active Storage.
14
26
  #
15
- # message = Message.create!(content: "<h1>Funny times!</h1>")
16
- # message.content? #=> true
17
- # message.content.to_s # => "<h1>Funny times!</h1>"
18
- # message.content.to_plain_text # => "Funny times!"
27
+ # If you wish to preload the dependent RichText model, you can use the named
28
+ # scope:
19
29
  #
20
- # The dependent RichText model will also automatically process attachments links as sent via the Trix-powered editor.
21
- # These attachments are associated with the RichText model using Active Storage.
30
+ # Message.all.with_rich_text_content # Avoids N+1 queries when you just want the body, not the attachments.
31
+ # Message.all.with_rich_text_content_and_embeds # Avoids N+1 queries when you just want the body and attachments.
32
+ # Message.all.with_all_rich_text # Loads all rich text associations.
22
33
  #
23
- # If you wish to preload the dependent RichText model, you can use the named scope:
34
+ # #### Options
24
35
  #
25
- # Message.all.with_rich_text_content # Avoids N+1 queries when you just want the body, not the attachments.
26
- # Message.all.with_rich_text_content_and_embeds # Avoids N+1 queries when you just want the body and attachments.
27
- # Message.all.with_all_rich_text # Loads all rich text associations.
36
+ # * `:encrypted` - Pass true to encrypt the rich text attribute. The
37
+ # encryption will be non-deterministic. See
38
+ # `ActiveRecord::Encryption::EncryptableRecord.encrypts`. Default: false.
28
39
  #
29
- # ==== Options
40
+ # * `:strict_loading` - Pass true to force strict loading. When omitted,
41
+ # `strict_loading:` will be set to the value of the
42
+ # `strict_loading_by_default` class attribute (false by default).
30
43
  #
31
- # * <tt>:encrypted</tt> - Pass true to encrypt the rich text attribute. The encryption will be non-deterministic. See
32
- # +ActiveRecord::Encryption::EncryptableRecord.encrypts+. Default: false.
33
44
  #
34
- # * <tt>:strict_loading</tt> - Pass true to force strict loading. When
35
- # omitted, <tt>strict_loading:</tt> will be set to the value of the
36
- # <tt>strict_loading_by_default</tt> class attribute (false by default).
45
+ # Note: Action Text relies on polymorphic associations, which in turn store
46
+ # class names in the database. When renaming classes that use `has_rich_text`,
47
+ # make sure to also update the class names in the
48
+ # `action_text_rich_texts.record_type` polymorphic type column of the
49
+ # corresponding rows.
37
50
  def has_rich_text(name, encrypted: false, strict_loading: strict_loading_by_default)
38
51
  class_eval <<-CODE, __FILE__, __LINE__ + 1
39
52
  def #{name}
@@ -60,9 +73,10 @@ module ActionText
60
73
 
61
74
  # Eager load all dependent RichText models in bulk.
62
75
  def with_all_rich_text
63
- eager_load(rich_text_association_names)
76
+ includes(rich_text_association_names)
64
77
  end
65
78
 
79
+ # Returns the names of all rich text associations.
66
80
  def rich_text_association_names
67
81
  reflect_on_all_associations(:has_one).collect(&:name).select { |n| n.start_with?("rich_text_") }
68
82
  end
@@ -1,29 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionText
4
- # = Action Text \Content
6
+ # # Action Text Content
5
7
  #
6
- # The +ActionText::Content+ class wraps an HTML fragment to add support for
8
+ # The `ActionText::Content` class wraps an HTML fragment to add support for
7
9
  # parsing, rendering and serialization. It can be used to extract links and
8
- # attachments, convert the fragment to plain text, or serialize the fragment
9
- # to the database.
10
+ # attachments, convert the fragment to plain text, or serialize the fragment to
11
+ # the database.
10
12
  #
11
13
  # The ActionText::RichText record serializes the `body` attribute as
12
- # +ActionText::Content+.
14
+ # `ActionText::Content`.
13
15
  #
14
- # class Message < ActiveRecord::Base
15
- # has_rich_text :content
16
- # end
16
+ # class Message < ActiveRecord::Base
17
+ # has_rich_text :content
18
+ # end
17
19
  #
18
- # message = Message.create!(content: "<h1>Funny times!</h1>")
19
- # body = message.content.body # => #<ActionText::Content "<div class=\"trix-conte...">
20
- # body.to_s # => "<h1>Funny times!</h1>"
21
- # body.to_plain_text # => "Funny times!"
20
+ # message = Message.create!(content: "<h1>Funny times!</h1>")
21
+ # body = message.content.body # => #<ActionText::Content "<div class=\"trix-conte...">
22
+ # body.to_s # => "<h1>Funny times!</h1>"
23
+ # body.to_plain_text # => "Funny times!"
22
24
  class Content
23
- include Rendering, Serialization, ContentHelper
25
+ include Rendering, Serialization
24
26
 
25
27
  attr_reader :fragment
26
28
 
29
+ delegate :deconstruct, to: :fragment
27
30
  delegate :blank?, :empty?, :html_safe, :present?, to: :to_html # Delegating to to_html to avoid including the layout
28
31
 
29
32
  class << self
@@ -46,19 +49,19 @@ module ActionText
46
49
 
47
50
  # Extracts links from the HTML fragment:
48
51
  #
49
- # html = '<a href="http://example.com/">Example</a>'
50
- # content = ActionText::Content.new(html)
51
- # content.links # => ["http://example.com/"]
52
+ # html = '<a href="http://example.com/">Example</a>'
53
+ # content = ActionText::Content.new(html)
54
+ # content.links # => ["http://example.com/"]
52
55
  def links
53
56
  @links ||= fragment.find_all("a[href]").map { |a| a["href"] }.uniq
54
57
  end
55
58
 
56
59
  # Extracts +ActionText::Attachment+s from the HTML fragment:
57
60
  #
58
- # attachable = ActiveStorage::Blob.first
59
- # html = %Q(<action-text-attachment sgid="#{attachable.attachable_sgid}" caption="Captioned"></action-text-attachment>)
60
- # content = ActionText::Content.new(html)
61
- # content.attachments # => [#<ActionText::Attachment attachable=#<ActiveStorage::Blob...
61
+ # attachable = ActiveStorage::Blob.first
62
+ # html = %Q(<action-text-attachment sgid="#{attachable.attachable_sgid}" caption="Captioned"></action-text-attachment>)
63
+ # content = ActionText::Content.new(html)
64
+ # content.attachments # => [#<ActionText::Attachment attachable=#<ActiveStorage::Blob...
62
65
  def attachments
63
66
  @attachments ||= attachment_nodes.map do |node|
64
67
  attachment_for_node(node)
@@ -77,10 +80,10 @@ module ActionText
77
80
 
78
81
  # Extracts +ActionText::Attachable+s from the HTML fragment:
79
82
  #
80
- # attachable = ActiveStorage::Blob.first
81
- # html = %Q(<action-text-attachment sgid="#{attachable.attachable_sgid}" caption="Captioned"></action-text-attachment>)
82
- # content = ActionText::Content.new(html)
83
- # content.attachables # => [attachable]
83
+ # attachable = ActiveStorage::Blob.first
84
+ # html = %Q(<action-text-attachment sgid="#{attachable.attachable_sgid}" caption="Captioned"></action-text-attachment>)
85
+ # content = ActionText::Content.new(html)
86
+ # content.attachables # => [attachable]
84
87
  def attachables
85
88
  @attachables ||= attachment_nodes.map do |node|
86
89
  ActionText::Attachable.from_node(node)
@@ -94,10 +97,6 @@ module ActionText
94
97
 
95
98
  def render_attachments(**options, &block)
96
99
  content = fragment.replace(ActionText::Attachment.tag_name) do |node|
97
- if node.key?("content")
98
- sanitized_content = sanitize_content_attachment(node.remove_attribute("content").to_s)
99
- node["content"] = sanitized_content if sanitized_content.present?
100
- end
101
100
  block.call(attachment_for_node(node, **options))
102
101
  end
103
102
  self.class.new(content, canonicalize: false)
@@ -110,10 +109,20 @@ module ActionText
110
109
  self.class.new(content, canonicalize: false)
111
110
  end
112
111
 
113
- # Returns the content as plain text with all HTML tags removed.
112
+ # Returns a plain-text version of the markup contained by the content, with tags
113
+ # removed but HTML entities encoded.
114
+ #
115
+ # content = ActionText::Content.new("<h1>Funny times!</h1>")
116
+ # content.to_plain_text # => "Funny times!"
117
+ #
118
+ # content = ActionText::Content.new("<div onclick='action()'>safe<script>unsafe</script></div>")
119
+ # content.to_plain_text # => "safeunsafe"
114
120
  #
115
- # content = ActionText::Content.new("<h1>Funny times!</h1>")
116
- # content.to_plain_text # => "Funny times!"
121
+ # NOTE: that the returned string is not HTML safe and should not be rendered in
122
+ # browsers.
123
+ #
124
+ # content = ActionText::Content.new("&lt;script&gt;alert()&lt;/script&gt;")
125
+ # content.to_plain_text # => "<script>alert()</script>"
117
126
  def to_plain_text
118
127
  render_attachments(with_full_attributes: false, &:to_plain_text).fragment.to_plain_text
119
128
  end
@@ -134,6 +143,13 @@ module ActionText
134
143
  "action_text/contents/content"
135
144
  end
136
145
 
146
+ # Safely transforms Content into an HTML String.
147
+ #
148
+ # content = ActionText::Content.new(content: "<h1>Funny times!</h1>")
149
+ # content.to_s # => "<h1>Funny times!</h1>"
150
+ #
151
+ # content = ActionText::Content.new("<div onclick='action()'>safe<script>unsafe</script></div>")
152
+ # content.to_s # => "<div>safeunsafe</div>"
137
153
  def to_s
138
154
  to_rendered_html_with_layout
139
155
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionText
4
6
  def self.deprecator # :nodoc:
5
7
  @deprecator ||= ActiveSupport::Deprecation.new
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionText
4
6
  module Encryption
5
7
  def encrypt
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "rails"
4
6
  require "action_controller/railtie"
5
7
  require "active_record/railtie"
@@ -1,62 +1,62 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionText
4
- # = Action Text \FixtureSet
6
+ # # Action Text FixtureSet
5
7
  #
6
- # Fixtures are a way of organizing data that you want to test against; in
7
- # short, sample data.
8
+ # Fixtures are a way of organizing data that you want to test against; in short,
9
+ # sample data.
8
10
  #
9
11
  # To learn more about fixtures, read the ActiveRecord::FixtureSet documentation.
10
12
  #
11
- # === YAML
13
+ # ### YAML
12
14
  #
13
15
  # Like other Active Record-backed models, ActionText::RichText records inherit
14
- # from ActiveRecord::Base instances and can therefore be populated by
15
- # fixtures.
16
+ # from ActiveRecord::Base instances and can therefore be populated by fixtures.
16
17
  #
17
- # Consider an <tt>Article</tt> class:
18
+ # Consider an `Article` class:
18
19
  #
19
- # class Article < ApplicationRecord
20
- # has_rich_text :content
21
- # end
20
+ # class Article < ApplicationRecord
21
+ # has_rich_text :content
22
+ # end
22
23
  #
23
- # To declare fixture data for the related <tt>content</tt>, first declare fixture
24
- # data for <tt>Article</tt> instances in <tt>test/fixtures/articles.yml</tt>:
24
+ # To declare fixture data for the related `content`, first declare fixture data
25
+ # for `Article` instances in `test/fixtures/articles.yml`:
25
26
  #
26
- # first:
27
- # title: An Article
27
+ # first:
28
+ # title: An Article
28
29
  #
29
30
  # Then declare the ActionText::RichText fixture data in
30
- # <tt>test/fixtures/action_text/rich_texts.yml</tt>, making sure to declare
31
- # each entry's <tt>record:</tt> key as a polymorphic relationship:
31
+ # `test/fixtures/action_text/rich_texts.yml`, making sure to declare each
32
+ # entry's `record:` key as a polymorphic relationship:
32
33
  #
33
- # first:
34
- # record: first (Article)
35
- # name: content
36
- # body: <div>Hello, world.</div>
34
+ # first:
35
+ # record: first (Article)
36
+ # name: content
37
+ # body: <div>Hello, world.</div>
37
38
  #
38
39
  # When processed, Active Record will insert database records for each fixture
39
40
  # entry and will ensure the Action Text relationship is intact.
40
41
  class FixtureSet
41
- # Fixtures support Action Text attachments as part of their <tt>body</tt>
42
- # HTML.
42
+ # Fixtures support Action Text attachments as part of their `body` HTML.
43
43
  #
44
- # === Examples
44
+ # ### Examples
45
45
  #
46
- # For example, consider a second <tt>Article</tt> fixture declared in
47
- # <tt>test/fixtures/articles.yml</tt>:
46
+ # For example, consider a second `Article` fixture declared in
47
+ # `test/fixtures/articles.yml`:
48
48
  #
49
- # second:
50
- # title: Another Article
49
+ # second:
50
+ # title: Another Article
51
51
  #
52
- # You can attach a mention of <tt>articles(:first)</tt> to <tt>second</tt>'s
53
- # <tt>content</tt> by embedding a call to <tt>ActionText::FixtureSet.attachment</tt>
54
- # in the <tt>body:</tt> value in <tt>test/fixtures/action_text/rich_texts.yml</tt>:
52
+ # You can attach a mention of `articles(:first)` to `second`'s `content` by
53
+ # embedding a call to `ActionText::FixtureSet.attachment` in the `body:` value
54
+ # in `test/fixtures/action_text/rich_texts.yml`:
55
55
  #
56
- # second:
57
- # record: second (Article)
58
- # name: content
59
- # body: <div>Hello, <%= ActionText::FixtureSet.attachment("articles", :first) %></div>
56
+ # second:
57
+ # record: second (Article)
58
+ # name: content
59
+ # body: <div>Hello, <%= ActionText::FixtureSet.attachment("articles", :first) %></div>
60
60
  #
61
61
  def self.attachment(fixture_set_name, label, column_type: :integer)
62
62
  signed_global_id = ActiveRecord::FixtureSet.signed_global_id fixture_set_name, label,
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionText
4
6
  class Fragment
5
7
  class << self
@@ -21,6 +23,8 @@ module ActionText
21
23
 
22
24
  attr_reader :source
23
25
 
26
+ delegate :deconstruct, to: "source.elements"
27
+
24
28
  def initialize(source)
25
29
  @source = source
26
30
  end
@@ -1,16 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionText
4
- # Returns the currently loaded version of Action Text as a +Gem::Version+.
6
+ # Returns the currently loaded version of Action Text as a `Gem::Version`.
5
7
  def self.gem_version
6
8
  Gem::Version.new VERSION::STRING
7
9
  end
8
10
 
9
11
  module VERSION
10
12
  MAJOR = 7
11
- MINOR = 1
12
- TINY = 5
13
- PRE = nil
13
+ MINOR = 2
14
+ TINY = 0
15
+ PRE = "beta1"
14
16
 
15
17
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
18
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionText
4
6
  module HtmlConversion
5
7
  extend self
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionText
4
6
  module PlainTextConversion
5
7
  extend self
@@ -63,12 +65,7 @@ module ActionText
63
65
 
64
66
  def plain_text_for_blockquote_node(node, index)
65
67
  text = plain_text_for_block(node)
66
- return "“”" if text.blank?
67
-
68
- text = text.dup
69
- text.insert(text.rindex(/\S/) + 1, "”")
70
- text.insert(text.index(/\S/), "“")
71
- text
68
+ text.sub(/\A(\s*)(.+?)(\s*)\Z/m, '\1“\2”\3')
72
69
  end
73
70
 
74
71
  def plain_text_for_li_node(node, index)
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "active_support/concern"
4
6
  require "active_support/core_ext/module/attribute_accessors_per_thread"
5
7
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionText
4
6
  module Serialization
5
7
  extend ActiveSupport::Concern
@@ -1,34 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionText
4
6
  module SystemTestHelper
5
7
  # Locates a Trix editor and fills it in with the given HTML.
6
8
  #
7
9
  # The editor can be found by:
8
- # * its +id+
9
- # * its +placeholder+
10
- # * the text from its +label+ element
11
- # * its +aria-label+
12
- # * the +name+ of its input
10
+ # * its `id`
11
+ # * its `placeholder`
12
+ # * the text from its `label` element
13
+ # * its `aria-label`
14
+ # * the `name` of its input
15
+ #
13
16
  #
14
17
  # Examples:
15
18
  #
16
- # # <trix-editor id="message_content" ...></trix-editor>
17
- # fill_in_rich_text_area "message_content", with: "Hello <em>world!</em>"
19
+ # # <trix-editor id="message_content" ...></trix-editor>
20
+ # fill_in_rich_text_area "message_content", with: "Hello <em>world!</em>"
18
21
  #
19
- # # <trix-editor placeholder="Your message here" ...></trix-editor>
20
- # fill_in_rich_text_area "Your message here", with: "Hello <em>world!</em>"
22
+ # # <trix-editor placeholder="Your message here" ...></trix-editor>
23
+ # fill_in_rich_text_area "Your message here", with: "Hello <em>world!</em>"
21
24
  #
22
- # # <label for="message_content">Message content</label>
23
- # # <trix-editor id="message_content" ...></trix-editor>
24
- # fill_in_rich_text_area "Message content", with: "Hello <em>world!</em>"
25
+ # # <label for="message_content">Message content</label>
26
+ # # <trix-editor id="message_content" ...></trix-editor>
27
+ # fill_in_rich_text_area "Message content", with: "Hello <em>world!</em>"
25
28
  #
26
- # # <trix-editor aria-label="Message content" ...></trix-editor>
27
- # fill_in_rich_text_area "Message content", with: "Hello <em>world!</em>"
29
+ # # <trix-editor aria-label="Message content" ...></trix-editor>
30
+ # fill_in_rich_text_area "Message content", with: "Hello <em>world!</em>"
28
31
  #
29
- # # <input id="trix_input_1" name="message[content]" type="hidden">
30
- # # <trix-editor input="trix_input_1"></trix-editor>
31
- # fill_in_rich_text_area "message[content]", with: "Hello <em>world!</em>"
32
+ # # <input id="trix_input_1" name="message[content]" type="hidden">
33
+ # # <trix-editor input="trix_input_1"></trix-editor>
34
+ # fill_in_rich_text_area "message[content]", with: "Hello <em>world!</em>"
32
35
  def fill_in_rich_text_area(locator = nil, with:)
33
36
  find(:rich_text_area, locator).execute_script("this.editor.loadHTML(arguments[0])", with.to_s)
34
37
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionText
4
6
  class TrixAttachment
5
7
  TAG_NAME = "figure"
@@ -1,9 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require_relative "gem_version"
4
6
 
5
7
  module ActionText
6
- # Returns the currently loaded version of Action Text as a +Gem::Version+.
8
+ # Returns the currently loaded version of Action Text as a `Gem::Version`.
7
9
  def self.version
8
10
  gem_version
9
11
  end