actiontext 7.2.0 → 8.0.0.beta1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3d77dbdf62d70a0ee5468ec4b03146cec33d5326dbdd73f3dca7008e516ca751
4
- data.tar.gz: 40ef3f337c58d72213a1655f978793e195d03ad9fecf283115b24af2d4ee359a
3
+ metadata.gz: 47681928e4eb5de7fb4d7958ec7071174c8671e9750049693f8bc6a4742d90be
4
+ data.tar.gz: 162c998b362b84e68c0a404014c227a04925c3554de18ad66563dd3b00759040
5
5
  SHA512:
6
- metadata.gz: ca3c5b6008ad562a0c98cf0534fbfaadfd5e79fa97a18c7f3f5ba94e78cd782492ccc380a6a798d2e34b820f26667a01276cd4059460da157e5103d8f67ffd14
7
- data.tar.gz: 9b1190da576e6742190168cdadede33cfa915572e25ef661fcd2b29794122b91860164bc1dd4095e7d18bfa136cd05f77ecf2db36a5bb54264bb0bc172de7d91
6
+ metadata.gz: 13900860666132a1931d50ce22c8cb65f5a39f09a65f7fcc893aece5c55b292d7c7c63735450da6181d3736944e1ce4610cb2407a24e6740991ddf0c30f2a3fe
7
+ data.tar.gz: 02ed293526d7691e072e5f8711e8fd69dabcf6c7aaa3dcaf01d07c29d09d43629acf60f6aa65d22a67727a1f5622ef4c3cfbc8bc69108cd8240fcbb1c960d9d8
data/CHANGELOG.md CHANGED
@@ -1,54 +1,44 @@
1
- ## Rails 7.2.0 (August 09, 2024) ##
1
+ ## Rails 8.0.0.beta1 (September 26, 2024) ##
2
2
 
3
- * Only sanitize `content` attribute when present in attachments.
4
-
5
- *Petrik de Heus*
3
+ * Dispatch direct-upload events on attachment uploads
6
4
 
7
- * Sanitize ActionText HTML ContentAttachment in Trix edit view
8
- [CVE-2024-32464]
5
+ When using Action Text's rich textarea, it's possible to attach files to the
6
+ editor. Previously, that action didn't dispatch any events, which made it hard
7
+ to react to the file uploads. For instance, if an upload failed, there was no
8
+ way to notify the user about it, or remove the attachment from the editor.
9
9
 
10
- *Aaron Patterson*, *Zack Deveau*
10
+ This commits adds new events - `direct-upload:start`, `direct-upload:progress`,
11
+ and `direct-upload:end` - similar to how Active Storage's direct uploads work.
11
12
 
12
- * Use `includes` instead of `eager_load` for `with_all_rich_text`.
13
+ *Matheus Richard*, *Brad Rees*
13
14
 
14
- *Petrik de Heus*
15
+ * Add `store_if_blank` option to `has_rich_text`
15
16
 
16
- * Delegate `ActionText::Content#deconstruct` to `Nokogiri::XML::DocumentFragment#elements`.
17
+ Pass `store_if_blank: false` to not create `ActionText::RichText` records when saving with a blank attribute, such as from an optional form parameter.
17
18
 
18
19
  ```ruby
19
- content = ActionText::Content.new <<~HTML
20
- <h1>Hello, world</h1>
20
+ class Message
21
+ has_rich_text :content, store_if_blank: false
22
+ end
21
23
 
22
- <div>The body</div>
23
- HTML
24
-
25
- content => [h1, div]
26
-
27
- assert_pattern { h1 => { content: "Hello, world" } }
28
- assert_pattern { div => { content: "The body" } }
24
+ Message.create(content: "hi") # creates an ActionText::RichText
25
+ Message.create(content: "") # does not create an ActionText::RichText
29
26
  ```
30
27
 
31
- *Sean Doyle*
28
+ *Alex Ghiculescu*
32
29
 
33
- * Fix all Action Text database related models to respect
34
- `ActiveRecord::Base.table_name_prefix` configuration.
30
+ * Strip `content` attribute if the key is present but the value is empty
35
31
 
36
- *Chedli Bourguiba*
32
+ *Jeremy Green*
37
33
 
38
- * Compile ESM package that can be used directly in the browser as actiontext.esm.js
34
+ * Rename `rich_text_area` methods into `rich_textarea`
39
35
 
40
- *Matias Grunberg*
36
+ Old names are still available as aliases.
41
37
 
42
- * Fix using actiontext.js with Sprockets.
43
-
44
- *Matias Grunberg*
45
-
46
- * Upgrade Trix to 2.0.7
47
-
48
- *Hartley McGuire*
38
+ *Sean Doyle*
49
39
 
50
- * Fix using Trix with Sprockets.
40
+ * Only sanitize `content` attribute when present in attachments.
51
41
 
52
- *Hartley McGuire*
42
+ *Petrik de Heus*
53
43
 
54
- Please check [7-1-stable](https://github.com/rails/rails/blob/7-1-stable/actiontext/CHANGELOG.md) for previous changes.
44
+ Please check [7-2-stable](https://github.com/rails/rails/blob/7-2-stable/actiontext/CHANGELOG.md) for previous changes.
@@ -853,25 +853,47 @@ class AttachmentUpload {
853
853
  }
854
854
  start() {
855
855
  this.directUpload.create(this.directUploadDidComplete.bind(this));
856
+ this.dispatch("start");
856
857
  }
857
858
  directUploadWillStoreFileWithXHR(xhr) {
858
859
  xhr.upload.addEventListener("progress", (event => {
859
860
  const progress = event.loaded / event.total * 100;
860
861
  this.attachment.setUploadProgress(progress);
862
+ if (progress) {
863
+ this.dispatch("progress", {
864
+ progress: progress
865
+ });
866
+ }
861
867
  }));
862
868
  }
863
869
  directUploadDidComplete(error, attributes) {
864
870
  if (error) {
865
- throw new Error(`Direct upload failed: ${error}`);
871
+ this.dispatchError(error);
872
+ } else {
873
+ this.attachment.setAttributes({
874
+ sgid: attributes.attachable_sgid,
875
+ url: this.createBlobUrl(attributes.signed_id, attributes.filename)
876
+ });
877
+ this.dispatch("end");
866
878
  }
867
- this.attachment.setAttributes({
868
- sgid: attributes.attachable_sgid,
869
- url: this.createBlobUrl(attributes.signed_id, attributes.filename)
870
- });
871
879
  }
872
880
  createBlobUrl(signedId, filename) {
873
881
  return this.blobUrlTemplate.replace(":signed_id", signedId).replace(":filename", encodeURIComponent(filename));
874
882
  }
883
+ dispatch(name, detail = {}) {
884
+ detail.attachment = this.attachment;
885
+ return dispatchEvent(this.element, `direct-upload:${name}`, {
886
+ detail: detail
887
+ });
888
+ }
889
+ dispatchError(error) {
890
+ const event = this.dispatch("error", {
891
+ error: error
892
+ });
893
+ if (!event.defaultPrevented) {
894
+ alert(error);
895
+ }
896
+ }
875
897
  get directUploadUrl() {
876
898
  return this.element.dataset.directUploadUrl;
877
899
  }
@@ -826,25 +826,47 @@
826
826
  }
827
827
  start() {
828
828
  this.directUpload.create(this.directUploadDidComplete.bind(this));
829
+ this.dispatch("start");
829
830
  }
830
831
  directUploadWillStoreFileWithXHR(xhr) {
831
832
  xhr.upload.addEventListener("progress", (event => {
832
833
  const progress = event.loaded / event.total * 100;
833
834
  this.attachment.setUploadProgress(progress);
835
+ if (progress) {
836
+ this.dispatch("progress", {
837
+ progress: progress
838
+ });
839
+ }
834
840
  }));
835
841
  }
836
842
  directUploadDidComplete(error, attributes) {
837
843
  if (error) {
838
- throw new Error(`Direct upload failed: ${error}`);
844
+ this.dispatchError(error);
845
+ } else {
846
+ this.attachment.setAttributes({
847
+ sgid: attributes.attachable_sgid,
848
+ url: this.createBlobUrl(attributes.signed_id, attributes.filename)
849
+ });
850
+ this.dispatch("end");
839
851
  }
840
- this.attachment.setAttributes({
841
- sgid: attributes.attachable_sgid,
842
- url: this.createBlobUrl(attributes.signed_id, attributes.filename)
843
- });
844
852
  }
845
853
  createBlobUrl(signedId, filename) {
846
854
  return this.blobUrlTemplate.replace(":signed_id", signedId).replace(":filename", encodeURIComponent(filename));
847
855
  }
856
+ dispatch(name, detail = {}) {
857
+ detail.attachment = this.attachment;
858
+ return dispatchEvent(this.element, `direct-upload:${name}`, {
859
+ detail: detail
860
+ });
861
+ }
862
+ dispatchError(error) {
863
+ const event = this.dispatch("error", {
864
+ error: error
865
+ });
866
+ if (!event.defaultPrevented) {
867
+ alert(error);
868
+ }
869
+ }
848
870
  get directUploadUrl() {
849
871
  return this.element.dataset.directUploadUrl;
850
872
  }
@@ -24,10 +24,10 @@ module ActionText
24
24
  #
25
25
  # #### Example
26
26
  #
27
- # rich_text_area_tag "content", message.content
27
+ # rich_textarea_tag "content", message.content
28
28
  # # <input type="hidden" name="content" id="trix_input_post_1">
29
29
  # # <trix-editor id="content" input="trix_input_post_1" class="trix-content" ...></trix-editor>
30
- def rich_text_area_tag(name, value = nil, options = {})
30
+ def rich_textarea_tag(name, value = nil, options = {})
31
31
  options = options.symbolize_keys
32
32
  form = options.delete(:form)
33
33
 
@@ -43,6 +43,7 @@ module ActionText
43
43
 
44
44
  input_tag + editor_tag
45
45
  end
46
+ alias_method :rich_text_area_tag, :rich_textarea_tag
46
47
  end
47
48
  end
48
49
 
@@ -56,7 +57,7 @@ module ActionView::Helpers
56
57
  options = @options.stringify_keys
57
58
  add_default_name_and_id(options)
58
59
  options["input"] ||= dom_id(object, [options["id"], :trix_input].compact.join("_")) if object
59
- html_tag = @template_object.rich_text_area_tag(options.delete("name"), options.fetch("value") { value }, options.except("value"))
60
+ html_tag = @template_object.rich_textarea_tag(options.delete("name"), options.fetch("value") { value }, options.except("value"))
60
61
  error_wrapping(html_tag)
61
62
  end
62
63
  end
@@ -76,28 +77,30 @@ module ActionView::Helpers
76
77
  #
77
78
  #
78
79
  # #### Example
79
- # rich_text_area :message, :content
80
+ # rich_textarea :message, :content
80
81
  # # <input type="hidden" name="message[content]" id="message_content_trix_input_message_1">
81
82
  # # <trix-editor id="content" input="message_content_trix_input_message_1" class="trix-content" ...></trix-editor>
82
83
  #
83
- # rich_text_area :message, :content, value: "<h1>Default message</h1>"
84
+ # rich_textarea :message, :content, value: "<h1>Default message</h1>"
84
85
  # # <input type="hidden" name="message[content]" id="message_content_trix_input_message_1" value="<h1>Default message</h1>">
85
86
  # # <trix-editor id="content" input="message_content_trix_input_message_1" class="trix-content" ...></trix-editor>
86
- def rich_text_area(object_name, method, options = {})
87
+ def rich_textarea(object_name, method, options = {})
87
88
  Tags::ActionText.new(object_name, method, self, options).render
88
89
  end
90
+ alias_method :rich_text_area, :rich_textarea
89
91
  end
90
92
 
91
93
  class FormBuilder
92
- # Wraps ActionView::Helpers::FormHelper#rich_text_area for form builders:
94
+ # Wraps ActionView::Helpers::FormHelper#rich_textarea for form builders:
93
95
  #
94
96
  # <%= form_with model: @message do |f| %>
95
- # <%= f.rich_text_area :content %>
97
+ # <%= f.rich_textarea :content %>
96
98
  # <% end %>
97
99
  #
98
100
  # Please refer to the documentation of the base helper for details.
99
- def rich_text_area(method, options = {})
100
- @template.rich_text_area(@object_name, method, objectify_options(options))
101
+ def rich_textarea(method, options = {})
102
+ @template.rich_textarea(@object_name, method, objectify_options(options))
101
103
  end
104
+ alias_method :rich_text_area, :rich_textarea
102
105
  end
103
106
  end
@@ -1,4 +1,4 @@
1
- import { DirectUpload } from "@rails/activestorage"
1
+ import { DirectUpload, dispatchEvent } from "@rails/activestorage"
2
2
 
3
3
  export class AttachmentUpload {
4
4
  constructor(attachment, element) {
@@ -9,24 +9,29 @@ export class AttachmentUpload {
9
9
 
10
10
  start() {
11
11
  this.directUpload.create(this.directUploadDidComplete.bind(this))
12
+ this.dispatch("start")
12
13
  }
13
14
 
14
15
  directUploadWillStoreFileWithXHR(xhr) {
15
16
  xhr.upload.addEventListener("progress", event => {
16
17
  const progress = event.loaded / event.total * 100
17
18
  this.attachment.setUploadProgress(progress)
19
+ if (progress) {
20
+ this.dispatch("progress", { progress: progress })
21
+ }
18
22
  })
19
23
  }
20
24
 
21
25
  directUploadDidComplete(error, attributes) {
22
26
  if (error) {
23
- throw new Error(`Direct upload failed: ${error}`)
27
+ this.dispatchError(error)
28
+ } else {
29
+ this.attachment.setAttributes({
30
+ sgid: attributes.attachable_sgid,
31
+ url: this.createBlobUrl(attributes.signed_id, attributes.filename)
32
+ })
33
+ this.dispatch("end")
24
34
  }
25
-
26
- this.attachment.setAttributes({
27
- sgid: attributes.attachable_sgid,
28
- url: this.createBlobUrl(attributes.signed_id, attributes.filename)
29
- })
30
35
  }
31
36
 
32
37
  createBlobUrl(signedId, filename) {
@@ -35,6 +40,18 @@ export class AttachmentUpload {
35
40
  .replace(":filename", encodeURIComponent(filename))
36
41
  }
37
42
 
43
+ dispatch(name, detail = {}) {
44
+ detail.attachment = this.attachment
45
+ return dispatchEvent(this.element, `direct-upload:${name}`, { detail })
46
+ }
47
+
48
+ dispatchError(error) {
49
+ const event = this.dispatch("error", { error })
50
+ if (!event.defaultPrevented) {
51
+ alert(error);
52
+ }
53
+ }
54
+
38
55
  get directUploadUrl() {
39
56
  return this.element.dataset.directUploadUrl
40
57
  }
@@ -41,13 +41,16 @@ module ActionText
41
41
  # `strict_loading:` will be set to the value of the
42
42
  # `strict_loading_by_default` class attribute (false by default).
43
43
  #
44
+ # * `:store_if_blank` - Pass false to not create RichText records with empty values,
45
+ # if a blank value is provided. Default: true.
46
+ #
44
47
  #
45
48
  # Note: Action Text relies on polymorphic associations, which in turn store
46
49
  # class names in the database. When renaming classes that use `has_rich_text`,
47
50
  # make sure to also update the class names in the
48
51
  # `action_text_rich_texts.record_type` polymorphic type column of the
49
52
  # corresponding rows.
50
- def has_rich_text(name, encrypted: false, strict_loading: strict_loading_by_default)
53
+ def has_rich_text(name, encrypted: false, strict_loading: strict_loading_by_default, store_if_blank: true)
51
54
  class_eval <<-CODE, __FILE__, __LINE__ + 1
52
55
  def #{name}
53
56
  rich_text_#{name} || build_rich_text_#{name}
@@ -56,12 +59,29 @@ module ActionText
56
59
  def #{name}?
57
60
  rich_text_#{name}.present?
58
61
  end
59
-
60
- def #{name}=(body)
61
- self.#{name}.body = body
62
- end
63
62
  CODE
64
63
 
64
+ if store_if_blank
65
+ class_eval <<-CODE, __FILE__, __LINE__ + 1
66
+ def #{name}=(body)
67
+ self.#{name}.body = body
68
+ end
69
+ CODE
70
+ else
71
+ class_eval <<-CODE, __FILE__, __LINE__ + 1
72
+ def #{name}=(body)
73
+ if body.present?
74
+ self.#{name}.body = body
75
+ else
76
+ if #{name}?
77
+ self.#{name}.body = body
78
+ self.#{name}.mark_for_destruction
79
+ end
80
+ end
81
+ end
82
+ CODE
83
+ end
84
+
65
85
  rich_text_class_name = encrypted ? "ActionText::EncryptedRichText" : "ActionText::RichText"
66
86
  has_one :"rich_text_#{name}", -> { where(name: name) },
67
87
  class_name: rich_text_class_name, as: :record, inverse_of: :record, autosave: true, dependent: :destroy,
@@ -97,8 +97,9 @@ module ActionText
97
97
 
98
98
  def render_attachments(**options, &block)
99
99
  content = fragment.replace(ActionText::Attachment.tag_name) do |node|
100
- if node.key? "content"
101
- node["content"] = sanitize_content_attachment(node["content"])
100
+ if node.key?("content")
101
+ sanitized_content = sanitize_content_attachment(node.remove_attribute("content").to_s)
102
+ node["content"] = sanitized_content if sanitized_content.present?
102
103
  end
103
104
  block.call(attachment_for_node(node, **options))
104
105
  end
@@ -9,10 +9,10 @@ module ActionText
9
9
  end
10
10
 
11
11
  module VERSION
12
- MAJOR = 7
13
- MINOR = 2
12
+ MAJOR = 8
13
+ MINOR = 0
14
14
  TINY = 0
15
- PRE = nil
15
+ PRE = "beta1"
16
16
 
17
17
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
18
18
  end
@@ -17,42 +17,45 @@ module ActionText
17
17
  # Examples:
18
18
  #
19
19
  # # <trix-editor id="message_content" ...></trix-editor>
20
- # fill_in_rich_text_area "message_content", with: "Hello <em>world!</em>"
20
+ # fill_in_rich_textarea "message_content", with: "Hello <em>world!</em>"
21
21
  #
22
22
  # # <trix-editor placeholder="Your message here" ...></trix-editor>
23
- # fill_in_rich_text_area "Your message here", with: "Hello <em>world!</em>"
23
+ # fill_in_rich_textarea "Your message here", with: "Hello <em>world!</em>"
24
24
  #
25
25
  # # <label for="message_content">Message content</label>
26
26
  # # <trix-editor id="message_content" ...></trix-editor>
27
- # fill_in_rich_text_area "Message content", with: "Hello <em>world!</em>"
27
+ # fill_in_rich_textarea "Message content", with: "Hello <em>world!</em>"
28
28
  #
29
29
  # # <trix-editor aria-label="Message content" ...></trix-editor>
30
- # fill_in_rich_text_area "Message content", with: "Hello <em>world!</em>"
30
+ # fill_in_rich_textarea "Message content", with: "Hello <em>world!</em>"
31
31
  #
32
32
  # # <input id="trix_input_1" name="message[content]" type="hidden">
33
33
  # # <trix-editor input="trix_input_1"></trix-editor>
34
- # fill_in_rich_text_area "message[content]", with: "Hello <em>world!</em>"
35
- def fill_in_rich_text_area(locator = nil, with:)
36
- find(:rich_text_area, locator).execute_script("this.editor.loadHTML(arguments[0])", with.to_s)
34
+ # fill_in_rich_textarea "message[content]", with: "Hello <em>world!</em>"
35
+ def fill_in_rich_textarea(locator = nil, with:)
36
+ find(:rich_textarea, locator).execute_script("this.editor.loadHTML(arguments[0])", with.to_s)
37
37
  end
38
+ alias_method :fill_in_rich_text_area, :fill_in_rich_textarea
38
39
  end
39
40
  end
40
41
 
41
- Capybara.add_selector :rich_text_area do
42
- label "rich-text area"
43
- xpath do |locator|
44
- if locator.nil?
45
- XPath.descendant(:"trix-editor")
46
- else
47
- input_located_by_name = XPath.anywhere(:input).where(XPath.attr(:name) == locator).attr(:id)
48
- input_located_by_label = XPath.anywhere(:label).where(XPath.string.n.is(locator)).attr(:for)
42
+ %i[rich_textarea rich_text_area].each do |rich_textarea|
43
+ Capybara.add_selector rich_textarea do
44
+ label "rich-text area"
45
+ xpath do |locator|
46
+ if locator.nil?
47
+ XPath.descendant(:"trix-editor")
48
+ else
49
+ input_located_by_name = XPath.anywhere(:input).where(XPath.attr(:name) == locator).attr(:id)
50
+ input_located_by_label = XPath.anywhere(:label).where(XPath.string.n.is(locator)).attr(:for)
49
51
 
50
- XPath.descendant(:"trix-editor").where \
51
- XPath.attr(:id).equals(locator) |
52
- XPath.attr(:placeholder).equals(locator) |
53
- XPath.attr(:"aria-label").equals(locator) |
54
- XPath.attr(:input).equals(input_located_by_name) |
55
- XPath.attr(:id).equals(input_located_by_label)
52
+ XPath.descendant(:"trix-editor").where \
53
+ XPath.attr(:id).equals(locator) |
54
+ XPath.attr(:placeholder).equals(locator) |
55
+ XPath.attr(:"aria-label").equals(locator) |
56
+ XPath.attr(:input).equals(input_located_by_name) |
57
+ XPath.attr(:id).equals(input_located_by_label)
58
+ end
56
59
  end
57
60
  end
58
61
  end
@@ -36,20 +36,8 @@ module ActionText
36
36
  end
37
37
 
38
38
  def create_actiontext_files
39
- destination = Pathname(destination_root)
40
-
41
39
  template "actiontext.css", "app/assets/stylesheets/actiontext.css"
42
40
 
43
- unless destination.join("app/assets/application.css").exist?
44
- if (stylesheets = Dir.glob "#{destination_root}/app/assets/stylesheets/application.*.{scss,css}").length > 0
45
- insert_into_file stylesheets.first.to_s, %(@import 'actiontext.css';)
46
- else
47
- say <<~INSTRUCTIONS, :green
48
- To use the Trix editor, you must require 'app/assets/stylesheets/actiontext.css' in your base stylesheet.
49
- INSTRUCTIONS
50
- end
51
- end
52
-
53
41
  gem_root = "#{__dir__}/../../../.."
54
42
 
55
43
  copy_file "#{gem_root}/app/views/active_storage/blobs/_blob.html.erb",
@@ -1,11 +1,420 @@
1
1
  /*
2
- * Provides a drop-in pointer for the default Trix stylesheet that will format the toolbar and
3
- * the trix-editor content (whether displayed or under editing). Feel free to incorporate this
4
- * inclusion directly in any other asset bundle and remove this file.
5
- *
6
- *= require trix
2
+ * Default Trix editor styles. See Action Text overwrites below.
7
3
  */
8
4
 
5
+ trix-editor {
6
+ border: 1px solid #bbb;
7
+ border-radius: 3px;
8
+ margin: 0;
9
+ padding: 0.4em 0.6em;
10
+ min-height: 5em;
11
+ outline: none; }
12
+
13
+ trix-toolbar * {
14
+ box-sizing: border-box; }
15
+
16
+ trix-toolbar .trix-button-row {
17
+ display: flex;
18
+ flex-wrap: nowrap;
19
+ justify-content: space-between;
20
+ overflow-x: auto; }
21
+
22
+ trix-toolbar .trix-button-group {
23
+ display: flex;
24
+ margin-bottom: 10px;
25
+ border: 1px solid #bbb;
26
+ border-top-color: #ccc;
27
+ border-bottom-color: #888;
28
+ border-radius: 3px; }
29
+ trix-toolbar .trix-button-group:not(:first-child) {
30
+ margin-left: 1.5vw; }
31
+ @media (max-width: 768px) {
32
+ trix-toolbar .trix-button-group:not(:first-child) {
33
+ margin-left: 0; } }
34
+
35
+ trix-toolbar .trix-button-group-spacer {
36
+ flex-grow: 1; }
37
+ @media (max-width: 768px) {
38
+ trix-toolbar .trix-button-group-spacer {
39
+ display: none; } }
40
+
41
+ trix-toolbar .trix-button {
42
+ position: relative;
43
+ float: left;
44
+ color: rgba(0, 0, 0, 0.6);
45
+ font-size: 0.75em;
46
+ font-weight: 600;
47
+ white-space: nowrap;
48
+ padding: 0 0.5em;
49
+ margin: 0;
50
+ outline: none;
51
+ border: none;
52
+ border-bottom: 1px solid #ddd;
53
+ border-radius: 0;
54
+ background: transparent; }
55
+ trix-toolbar .trix-button:not(:first-child) {
56
+ border-left: 1px solid #ccc; }
57
+ trix-toolbar .trix-button.trix-active {
58
+ background: #cbeefa;
59
+ color: black; }
60
+ trix-toolbar .trix-button:not(:disabled) {
61
+ cursor: pointer; }
62
+ trix-toolbar .trix-button:disabled {
63
+ color: rgba(0, 0, 0, 0.125); }
64
+ @media (max-width: 768px) {
65
+ trix-toolbar .trix-button {
66
+ letter-spacing: -0.01em;
67
+ padding: 0 0.3em; } }
68
+
69
+ trix-toolbar .trix-button--icon {
70
+ font-size: inherit;
71
+ width: 2.6em;
72
+ height: 1.6em;
73
+ max-width: calc(0.8em + 4vw);
74
+ text-indent: -9999px; }
75
+ @media (max-width: 768px) {
76
+ trix-toolbar .trix-button--icon {
77
+ height: 2em;
78
+ max-width: calc(0.8em + 3.5vw); } }
79
+ trix-toolbar .trix-button--icon::before {
80
+ display: inline-block;
81
+ position: absolute;
82
+ top: 0;
83
+ right: 0;
84
+ bottom: 0;
85
+ left: 0;
86
+ opacity: 0.6;
87
+ content: "";
88
+ background-position: center;
89
+ background-repeat: no-repeat;
90
+ background-size: contain; }
91
+ @media (max-width: 768px) {
92
+ trix-toolbar .trix-button--icon::before {
93
+ right: 6%;
94
+ left: 6%; } }
95
+ trix-toolbar .trix-button--icon.trix-active::before {
96
+ opacity: 1; }
97
+ trix-toolbar .trix-button--icon:disabled::before {
98
+ opacity: 0.125; }
99
+
100
+ trix-toolbar .trix-button--icon-attach::before {
101
+ background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M10.5%2018V7.5c0-2.25%203-2.25%203%200V18c0%204.125-6%204.125-6%200V7.5c0-6.375%209-6.375%209%200V18%22%20stroke%3D%22%23000%22%20stroke-width%3D%222%22%20stroke-miterlimit%3D%2210%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%2F%3E%3C%2Fsvg%3E");
102
+ top: 8%;
103
+ bottom: 4%; }
104
+
105
+ trix-toolbar .trix-button--icon-bold::before {
106
+ background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M6.522%2019.242a.5.5%200%200%201-.5-.5V5.35a.5.5%200%200%201%20.5-.5h5.783c1.347%200%202.46.345%203.24.982.783.64%201.216%201.562%201.216%202.683%200%201.13-.587%202.129-1.476%202.71a.35.35%200%200%200%20.049.613c1.259.56%202.101%201.742%202.101%203.22%200%201.282-.483%202.334-1.363%203.063-.876.726-2.132%201.12-3.66%201.12h-5.89ZM9.27%207.347v3.362h1.97c.766%200%201.347-.17%201.733-.464.38-.291.587-.716.587-1.27%200-.53-.183-.928-.513-1.198-.334-.273-.838-.43-1.505-.43H9.27Zm0%205.606v3.791h2.389c.832%200%201.448-.177%201.853-.497.399-.315.614-.786.614-1.423%200-.62-.22-1.077-.63-1.385-.418-.313-1.053-.486-1.905-.486H9.27Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
107
+
108
+ trix-toolbar .trix-button--icon-italic::before {
109
+ background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M9%205h6.5v2h-2.23l-2.31%2010H13v2H6v-2h2.461l2.306-10H9V5Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
110
+
111
+ trix-toolbar .trix-button--icon-link::before {
112
+ background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M18.948%205.258a4.337%204.337%200%200%200-6.108%200L11.217%206.87a.993.993%200%200%200%200%201.41c.392.39%201.027.39%201.418%200l1.623-1.613a2.323%202.323%200%200%201%203.271%200%202.29%202.29%200%200%201%200%203.251l-2.393%202.38a3.021%203.021%200%200%201-4.255%200l-.05-.049a1.007%201.007%200%200%200-1.418%200%20.993.993%200%200%200%200%201.41l.05.049a5.036%205.036%200%200%200%207.091%200l2.394-2.38a4.275%204.275%200%200%200%200-6.072Zm-13.683%2013.6a4.337%204.337%200%200%200%206.108%200l1.262-1.255a.993.993%200%200%200%200-1.41%201.007%201.007%200%200%200-1.418%200L9.954%2017.45a2.323%202.323%200%200%201-3.27%200%202.29%202.29%200%200%201%200-3.251l2.344-2.331a2.579%202.579%200%200%201%203.631%200c.392.39%201.027.39%201.419%200a.993.993%200%200%200%200-1.41%204.593%204.593%200%200%200-6.468%200l-2.345%202.33a4.275%204.275%200%200%200%200%206.072Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
113
+
114
+ trix-toolbar .trix-button--icon-strike::before {
115
+ background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M6%2014.986c.088%202.647%202.246%204.258%205.635%204.258%203.496%200%205.713-1.728%205.713-4.463%200-.275-.02-.536-.062-.781h-3.461c.398.293.573.654.573%201.123%200%201.035-1.074%201.787-2.646%201.787-1.563%200-2.773-.762-2.91-1.924H6ZM6.432%2010h3.763c-.632-.314-.914-.715-.914-1.273%200-1.045.977-1.739%202.432-1.739%201.475%200%202.52.723%202.617%201.914h2.764c-.05-2.548-2.11-4.238-5.39-4.238-3.145%200-5.392%201.719-5.392%204.316%200%20.363.04.703.12%201.02ZM4%2011a1%201%200%201%200%200%202h15a1%201%200%201%200%200-2H4Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
116
+
117
+ trix-toolbar .trix-button--icon-quote::before {
118
+ background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M4.581%208.471c.44-.5%201.056-.834%201.758-.995C8.074%207.17%209.201%207.822%2010%208.752c1.354%201.578%201.33%203.555.394%205.277-.941%201.731-2.788%203.163-4.988%203.56a.622.622%200%200%201-.653-.317c-.113-.205-.121-.49.16-.764.294-.286.567-.566.791-.835.222-.266.413-.54.524-.815.113-.28.156-.597.026-.908-.128-.303-.39-.524-.72-.69a3.02%203.02%200%200%201-1.674-2.7c0-.905.283-1.59.72-2.088Zm9.419%200c.44-.5%201.055-.834%201.758-.995%201.734-.306%202.862.346%203.66%201.276%201.355%201.578%201.33%203.555.395%205.277-.941%201.731-2.789%203.163-4.988%203.56a.622.622%200%200%201-.653-.317c-.113-.205-.122-.49.16-.764.294-.286.567-.566.791-.835.222-.266.412-.54.523-.815.114-.28.157-.597.026-.908-.127-.303-.39-.524-.72-.69a3.02%203.02%200%200%201-1.672-2.701c0-.905.283-1.59.72-2.088Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
119
+
120
+ trix-toolbar .trix-button--icon-heading-1::before {
121
+ background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M21.5%207.5v-3h-12v3H14v13h3v-13h4.5ZM9%2013.5h3.5v-3h-10v3H6v7h3v-7Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
122
+
123
+ trix-toolbar .trix-button--icon-code::before {
124
+ background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M3.293%2011.293a1%201%200%200%200%200%201.414l4%204a1%201%200%201%200%201.414-1.414L5.414%2012l3.293-3.293a1%201%200%200%200-1.414-1.414l-4%204Zm13.414%205.414%204-4a1%201%200%200%200%200-1.414l-4-4a1%201%200%201%200-1.414%201.414L18.586%2012l-3.293%203.293a1%201%200%200%200%201.414%201.414Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
125
+
126
+ trix-toolbar .trix-button--icon-bullet-list::before {
127
+ background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M5%207.5a1.5%201.5%200%201%200%200-3%201.5%201.5%200%200%200%200%203ZM8%206a1%201%200%200%201%201-1h11a1%201%200%201%201%200%202H9a1%201%200%200%201-1-1Zm1%205a1%201%200%201%200%200%202h11a1%201%200%201%200%200-2H9Zm0%206a1%201%200%201%200%200%202h11a1%201%200%201%200%200-2H9Zm-2.5-5a1.5%201.5%200%201%201-3%200%201.5%201.5%200%200%201%203%200ZM5%2019.5a1.5%201.5%200%201%200%200-3%201.5%201.5%200%200%200%200%203Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
128
+
129
+ trix-toolbar .trix-button--icon-number-list::before {
130
+ background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M3%204h2v4H4V5H3V4Zm5%202a1%201%200%200%201%201-1h11a1%201%200%201%201%200%202H9a1%201%200%200%201-1-1Zm1%205a1%201%200%201%200%200%202h11a1%201%200%201%200%200-2H9Zm0%206a1%201%200%201%200%200%202h11a1%201%200%201%200%200-2H9Zm-3.5-7H6v1l-1.5%202H6v1H3v-1l1.667-2H3v-1h2.5ZM3%2017v-1h3v4H3v-1h2v-.5H4v-1h1V17H3Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
131
+
132
+ trix-toolbar .trix-button--icon-undo::before {
133
+ background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M3%2014a1%201%200%200%200%201%201h6a1%201%200%201%200%200-2H6.257c2.247-2.764%205.151-3.668%207.579-3.264%202.589.432%204.739%202.356%205.174%205.405a1%201%200%200%200%201.98-.283c-.564-3.95-3.415-6.526-6.825-7.095C11.084%207.25%207.63%208.377%205%2011.39V8a1%201%200%200%200-2%200v6Zm2-1Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
134
+
135
+ trix-toolbar .trix-button--icon-redo::before {
136
+ background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M21%2014a1%201%200%200%201-1%201h-6a1%201%200%201%201%200-2h3.743c-2.247-2.764-5.151-3.668-7.579-3.264-2.589.432-4.739%202.356-5.174%205.405a1%201%200%200%201-1.98-.283c.564-3.95%203.415-6.526%206.826-7.095%203.08-.513%206.534.614%209.164%203.626V8a1%201%200%201%201%202%200v6Zm-2-1Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
137
+
138
+ trix-toolbar .trix-button--icon-decrease-nesting-level::before {
139
+ background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M5%206a1%201%200%200%201%201-1h12a1%201%200%201%201%200%202H6a1%201%200%200%201-1-1Zm4%205a1%201%200%201%200%200%202h9a1%201%200%201%200%200-2H9Zm-3%206a1%201%200%201%200%200%202h12a1%201%200%201%200%200-2H6Zm-3.707-5.707a1%201%200%200%200%200%201.414l2%202a1%201%200%201%200%201.414-1.414L4.414%2012l1.293-1.293a1%201%200%200%200-1.414-1.414l-2%202Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
140
+
141
+ trix-toolbar .trix-button--icon-increase-nesting-level::before {
142
+ background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M5%206a1%201%200%200%201%201-1h12a1%201%200%201%201%200%202H6a1%201%200%200%201-1-1Zm4%205a1%201%200%201%200%200%202h9a1%201%200%201%200%200-2H9Zm-3%206a1%201%200%201%200%200%202h12a1%201%200%201%200%200-2H6Zm-2.293-2.293%202-2a1%201%200%200%200%200-1.414l-2-2a1%201%200%201%200-1.414%201.414L3.586%2012l-1.293%201.293a1%201%200%201%200%201.414%201.414Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
143
+
144
+ trix-toolbar .trix-dialogs {
145
+ position: relative; }
146
+
147
+ trix-toolbar .trix-dialog {
148
+ position: absolute;
149
+ top: 0;
150
+ left: 0;
151
+ right: 0;
152
+ font-size: 0.75em;
153
+ padding: 15px 10px;
154
+ background: #fff;
155
+ box-shadow: 0 0.3em 1em #ccc;
156
+ border-top: 2px solid #888;
157
+ border-radius: 5px;
158
+ z-index: 5; }
159
+
160
+ trix-toolbar .trix-input--dialog {
161
+ font-size: inherit;
162
+ font-weight: normal;
163
+ padding: 0.5em 0.8em;
164
+ margin: 0 10px 0 0;
165
+ border-radius: 3px;
166
+ border: 1px solid #bbb;
167
+ background-color: #fff;
168
+ box-shadow: none;
169
+ outline: none;
170
+ -webkit-appearance: none;
171
+ -moz-appearance: none; }
172
+ trix-toolbar .trix-input--dialog.validate:invalid {
173
+ box-shadow: #F00 0px 0px 1.5px 1px; }
174
+
175
+ trix-toolbar .trix-button--dialog {
176
+ font-size: inherit;
177
+ padding: 0.5em;
178
+ border-bottom: none; }
179
+
180
+ trix-toolbar .trix-dialog--link {
181
+ max-width: 600px; }
182
+
183
+ trix-toolbar .trix-dialog__link-fields {
184
+ display: flex;
185
+ align-items: baseline; }
186
+ trix-toolbar .trix-dialog__link-fields .trix-input {
187
+ flex: 1; }
188
+ trix-toolbar .trix-dialog__link-fields .trix-button-group {
189
+ flex: 0 0 content;
190
+ margin: 0; }
191
+
192
+ trix-editor [data-trix-mutable]:not(.attachment__caption-editor) {
193
+ -webkit-user-select: none;
194
+ -moz-user-select: none;
195
+ -ms-user-select: none;
196
+ user-select: none; }
197
+
198
+ trix-editor [data-trix-mutable]::-moz-selection,
199
+ trix-editor [data-trix-cursor-target]::-moz-selection, trix-editor [data-trix-mutable] ::-moz-selection {
200
+ background: none; }
201
+
202
+ trix-editor [data-trix-mutable]::selection,
203
+ trix-editor [data-trix-cursor-target]::selection, trix-editor [data-trix-mutable] ::selection {
204
+ background: none; }
205
+
206
+ trix-editor .attachment__caption-editor:focus[data-trix-mutable]::-moz-selection {
207
+ background: highlight; }
208
+
209
+ trix-editor .attachment__caption-editor:focus[data-trix-mutable]::selection {
210
+ background: highlight; }
211
+
212
+ trix-editor [data-trix-mutable].attachment.attachment--file {
213
+ box-shadow: 0 0 0 2px highlight;
214
+ border-color: transparent; }
215
+
216
+ trix-editor [data-trix-mutable].attachment img {
217
+ box-shadow: 0 0 0 2px highlight; }
218
+
219
+ trix-editor .attachment {
220
+ position: relative; }
221
+ trix-editor .attachment:hover {
222
+ cursor: default; }
223
+
224
+ trix-editor .attachment--preview .attachment__caption:hover {
225
+ cursor: text; }
226
+
227
+ trix-editor .attachment__progress {
228
+ position: absolute;
229
+ z-index: 1;
230
+ height: 20px;
231
+ top: calc(50% - 10px);
232
+ left: 5%;
233
+ width: 90%;
234
+ opacity: 0.9;
235
+ transition: opacity 200ms ease-in; }
236
+ trix-editor .attachment__progress[value="100"] {
237
+ opacity: 0; }
238
+
239
+ trix-editor .attachment__caption-editor {
240
+ display: inline-block;
241
+ width: 100%;
242
+ margin: 0;
243
+ padding: 0;
244
+ font-size: inherit;
245
+ font-family: inherit;
246
+ line-height: inherit;
247
+ color: inherit;
248
+ text-align: center;
249
+ vertical-align: top;
250
+ border: none;
251
+ outline: none;
252
+ -webkit-appearance: none;
253
+ -moz-appearance: none; }
254
+
255
+ trix-editor .attachment__toolbar {
256
+ position: absolute;
257
+ z-index: 1;
258
+ top: -0.9em;
259
+ left: 0;
260
+ width: 100%;
261
+ text-align: center; }
262
+
263
+ trix-editor .trix-button-group {
264
+ display: inline-flex; }
265
+
266
+ trix-editor .trix-button {
267
+ position: relative;
268
+ float: left;
269
+ color: #666;
270
+ white-space: nowrap;
271
+ font-size: 80%;
272
+ padding: 0 0.8em;
273
+ margin: 0;
274
+ outline: none;
275
+ border: none;
276
+ border-radius: 0;
277
+ background: transparent; }
278
+ trix-editor .trix-button:not(:first-child) {
279
+ border-left: 1px solid #ccc; }
280
+ trix-editor .trix-button.trix-active {
281
+ background: #cbeefa; }
282
+ trix-editor .trix-button:not(:disabled) {
283
+ cursor: pointer; }
284
+
285
+ trix-editor .trix-button--remove {
286
+ text-indent: -9999px;
287
+ display: inline-block;
288
+ padding: 0;
289
+ outline: none;
290
+ width: 1.8em;
291
+ height: 1.8em;
292
+ line-height: 1.8em;
293
+ border-radius: 50%;
294
+ background-color: #fff;
295
+ border: 2px solid highlight;
296
+ box-shadow: 1px 1px 6px rgba(0, 0, 0, 0.25); }
297
+ trix-editor .trix-button--remove::before {
298
+ display: inline-block;
299
+ position: absolute;
300
+ top: 0;
301
+ right: 0;
302
+ bottom: 0;
303
+ left: 0;
304
+ opacity: 0.7;
305
+ content: "";
306
+ background-image: url("data:image/svg+xml,%3Csvg%20height%3D%2224%22%20width%3D%2224%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M19%206.41%2017.59%205%2012%2010.59%206.41%205%205%206.41%2010.59%2012%205%2017.59%206.41%2019%2012%2013.41%2017.59%2019%2019%2017.59%2013.41%2012z%22%2F%3E%3Cpath%20d%3D%22M0%200h24v24H0z%22%20fill%3D%22none%22%2F%3E%3C%2Fsvg%3E");
307
+ background-position: center;
308
+ background-repeat: no-repeat;
309
+ background-size: 90%; }
310
+ trix-editor .trix-button--remove:hover {
311
+ border-color: #333; }
312
+ trix-editor .trix-button--remove:hover::before {
313
+ opacity: 1; }
314
+
315
+ trix-editor .attachment__metadata-container {
316
+ position: relative; }
317
+
318
+ trix-editor .attachment__metadata {
319
+ position: absolute;
320
+ left: 50%;
321
+ top: 2em;
322
+ transform: translate(-50%, 0);
323
+ max-width: 90%;
324
+ padding: 0.1em 0.6em;
325
+ font-size: 0.8em;
326
+ color: #fff;
327
+ background-color: rgba(0, 0, 0, 0.7);
328
+ border-radius: 3px; }
329
+ trix-editor .attachment__metadata .attachment__name {
330
+ display: inline-block;
331
+ max-width: 100%;
332
+ vertical-align: bottom;
333
+ overflow: hidden;
334
+ text-overflow: ellipsis;
335
+ white-space: nowrap; }
336
+ trix-editor .attachment__metadata .attachment__size {
337
+ margin-left: 0.2em;
338
+ white-space: nowrap; }
339
+
340
+ .trix-content {
341
+ line-height: 1.5;
342
+ overflow-wrap: break-word;
343
+ word-break: break-word; }
344
+ .trix-content * {
345
+ box-sizing: border-box;
346
+ margin: 0;
347
+ padding: 0; }
348
+ .trix-content h1 {
349
+ font-size: 1.2em;
350
+ line-height: 1.2; }
351
+ .trix-content blockquote {
352
+ border: 0 solid #ccc;
353
+ border-left-width: 0.3em;
354
+ margin-left: 0.3em;
355
+ padding-left: 0.6em; }
356
+ .trix-content [dir=rtl] blockquote,
357
+ .trix-content blockquote[dir=rtl] {
358
+ border-width: 0;
359
+ border-right-width: 0.3em;
360
+ margin-right: 0.3em;
361
+ padding-right: 0.6em; }
362
+ .trix-content li {
363
+ margin-left: 1em; }
364
+ .trix-content [dir=rtl] li {
365
+ margin-right: 1em; }
366
+ .trix-content pre {
367
+ display: inline-block;
368
+ width: 100%;
369
+ vertical-align: top;
370
+ font-family: monospace;
371
+ font-size: 0.9em;
372
+ padding: 0.5em;
373
+ white-space: pre;
374
+ background-color: #eee;
375
+ overflow-x: auto; }
376
+ .trix-content img {
377
+ max-width: 100%;
378
+ height: auto; }
379
+ .trix-content .attachment {
380
+ display: inline-block;
381
+ position: relative;
382
+ max-width: 100%; }
383
+ .trix-content .attachment a {
384
+ color: inherit;
385
+ text-decoration: none; }
386
+ .trix-content .attachment a:hover, .trix-content .attachment a:visited:hover {
387
+ color: inherit; }
388
+ .trix-content .attachment__caption {
389
+ text-align: center; }
390
+ .trix-content .attachment__caption .attachment__name + .attachment__size::before {
391
+ content: ' \2022 '; }
392
+ .trix-content .attachment--preview {
393
+ width: 100%;
394
+ text-align: center; }
395
+ .trix-content .attachment--preview .attachment__caption {
396
+ color: #666;
397
+ font-size: 0.9em;
398
+ line-height: 1.2; }
399
+ .trix-content .attachment--file {
400
+ color: #333;
401
+ line-height: 1;
402
+ margin: 0 2px 2px 2px;
403
+ padding: 0.4em 1em;
404
+ border: 1px solid #bbb;
405
+ border-radius: 5px; }
406
+ .trix-content .attachment-gallery {
407
+ display: flex;
408
+ flex-wrap: wrap;
409
+ position: relative; }
410
+ .trix-content .attachment-gallery .attachment {
411
+ flex: 1 0 33%;
412
+ padding: 0 0.5em;
413
+ max-width: 33%; }
414
+ .trix-content .attachment-gallery.attachment-gallery--2 .attachment, .trix-content .attachment-gallery.attachment-gallery--4 .attachment {
415
+ flex-basis: 50%;
416
+ max-width: 50%; }
417
+
9
418
  /*
10
419
  * We need to override trix.css’s image gallery styles to accommodate the
11
420
  * <action-text-attachment> element we wrap around attachments. Otherwise,
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rails/actiontext",
3
- "version": "7.2.0",
3
+ "version": "8.0.0-beta1",
4
4
  "description": "Edit and display rich text in Rails applications",
5
5
  "module": "app/assets/javascripts/actiontext.esm.js",
6
6
  "main": "app/assets/javascripts/actiontext.js",
@@ -22,7 +22,7 @@
22
22
  ],
23
23
  "license": "MIT",
24
24
  "dependencies": {
25
- "@rails/activestorage": ">= 7.2.0-alpha"
25
+ "@rails/activestorage": ">= 8.0.0-alpha"
26
26
  },
27
27
  "peerDependencies": {
28
28
  "trix": "^2.0.0"
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: actiontext
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.2.0
4
+ version: 8.0.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Javan Makhmali
8
8
  - Sam Stephenson
9
9
  - David Heinemeier Hansson
10
- autorequire:
10
+ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2024-08-09 00:00:00.000000000 Z
13
+ date: 2024-09-26 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
@@ -18,56 +18,56 @@ dependencies:
18
18
  requirements:
19
19
  - - '='
20
20
  - !ruby/object:Gem::Version
21
- version: 7.2.0
21
+ version: 8.0.0.beta1
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
26
  - - '='
27
27
  - !ruby/object:Gem::Version
28
- version: 7.2.0
28
+ version: 8.0.0.beta1
29
29
  - !ruby/object:Gem::Dependency
30
30
  name: activerecord
31
31
  requirement: !ruby/object:Gem::Requirement
32
32
  requirements:
33
33
  - - '='
34
34
  - !ruby/object:Gem::Version
35
- version: 7.2.0
35
+ version: 8.0.0.beta1
36
36
  type: :runtime
37
37
  prerelease: false
38
38
  version_requirements: !ruby/object:Gem::Requirement
39
39
  requirements:
40
40
  - - '='
41
41
  - !ruby/object:Gem::Version
42
- version: 7.2.0
42
+ version: 8.0.0.beta1
43
43
  - !ruby/object:Gem::Dependency
44
44
  name: activestorage
45
45
  requirement: !ruby/object:Gem::Requirement
46
46
  requirements:
47
47
  - - '='
48
48
  - !ruby/object:Gem::Version
49
- version: 7.2.0
49
+ version: 8.0.0.beta1
50
50
  type: :runtime
51
51
  prerelease: false
52
52
  version_requirements: !ruby/object:Gem::Requirement
53
53
  requirements:
54
54
  - - '='
55
55
  - !ruby/object:Gem::Version
56
- version: 7.2.0
56
+ version: 8.0.0.beta1
57
57
  - !ruby/object:Gem::Dependency
58
58
  name: actionpack
59
59
  requirement: !ruby/object:Gem::Requirement
60
60
  requirements:
61
61
  - - '='
62
62
  - !ruby/object:Gem::Version
63
- version: 7.2.0
63
+ version: 8.0.0.beta1
64
64
  type: :runtime
65
65
  prerelease: false
66
66
  version_requirements: !ruby/object:Gem::Requirement
67
67
  requirements:
68
68
  - - '='
69
69
  - !ruby/object:Gem::Version
70
- version: 7.2.0
70
+ version: 8.0.0.beta1
71
71
  - !ruby/object:Gem::Dependency
72
72
  name: nokogiri
73
73
  requirement: !ruby/object:Gem::Requirement
@@ -163,12 +163,12 @@ licenses:
163
163
  - MIT
164
164
  metadata:
165
165
  bug_tracker_uri: https://github.com/rails/rails/issues
166
- changelog_uri: https://github.com/rails/rails/blob/v7.2.0/actiontext/CHANGELOG.md
167
- documentation_uri: https://api.rubyonrails.org/v7.2.0/
166
+ changelog_uri: https://github.com/rails/rails/blob/v8.0.0.beta1/actiontext/CHANGELOG.md
167
+ documentation_uri: https://api.rubyonrails.org/v8.0.0.beta1/
168
168
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
169
- source_code_uri: https://github.com/rails/rails/tree/v7.2.0/actiontext
169
+ source_code_uri: https://github.com/rails/rails/tree/v8.0.0.beta1/actiontext
170
170
  rubygems_mfa_required: 'true'
171
- post_install_message:
171
+ post_install_message:
172
172
  rdoc_options: []
173
173
  require_paths:
174
174
  - lib
@@ -176,15 +176,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
176
176
  requirements:
177
177
  - - ">="
178
178
  - !ruby/object:Gem::Version
179
- version: 3.1.0
179
+ version: 3.2.0
180
180
  required_rubygems_version: !ruby/object:Gem::Requirement
181
181
  requirements:
182
182
  - - ">="
183
183
  - !ruby/object:Gem::Version
184
184
  version: '0'
185
185
  requirements: []
186
- rubygems_version: 3.5.11
187
- signing_key:
186
+ rubygems_version: 3.5.16
187
+ signing_key:
188
188
  specification_version: 4
189
189
  summary: Rich text framework.
190
190
  test_files: []