actiontext 7.2.2.1 → 8.1.2

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: ae880abbc66a8b853cce05dc41d2962a78d7ce409fb7329a58f39bb1621cf4b2
4
- data.tar.gz: 0eed3fd02e87093e9520e90577fe1fd560e0ef7da9eaa7ccb1e49751d50362ba
3
+ metadata.gz: 5b092ec1c0802a3bde54aa34e486bc4e943559d80c7a5b848dfef6520886d791
4
+ data.tar.gz: '08edc788a5dac28c6de1186100be082f6f5b87d641983784fa0635040e8a40bc'
5
5
  SHA512:
6
- metadata.gz: 9d2628de4f89b6f688536e657b1e89d058ae119b5c4f253b836cf51b96a35949bccc673e9a86f9e1dbc35013d66651534e1bb94460ce7374b88ef6575f22d5fa
7
- data.tar.gz: ad9de254ed7ab1ceb550c44fbae23a594e2abbcaf3533460eb9ecb0544eda5024c6f7c7d3d576c13511bfc11ada6b69f5a75bbf3e1c31cd6afcb1d6121733977
6
+ metadata.gz: 2f8c3814fc94289ccd59710e97b88377845d816f3e5576f9f6f56a270e4d688a09588874b973868502ca77b043e012f84f91ebf55775e3196de585a20976fe95
7
+ data.tar.gz: ed2d48e94658668d0bbe2b6073e0f23659a79c92c491811975b2b0b6c4275622c0c83f693b4388056a51d026c934f79605e348dc8cbaa0f2b922e7acb6962b24
data/CHANGELOG.md CHANGED
@@ -1,85 +1,73 @@
1
- ## Rails 7.2.2.1 (December 10, 2024) ##
2
-
3
- * Update vendored trix version to 2.1.10
4
-
5
- *John Hawthorn*
6
-
7
-
8
- ## Rails 7.2.2 (October 30, 2024) ##
1
+ ## Rails 8.1.2 (January 08, 2026) ##
9
2
 
10
3
  * No changes.
11
4
 
12
5
 
13
- ## Rails 7.2.1.2 (October 23, 2024) ##
6
+ ## Rails 8.1.1 (October 28, 2025) ##
14
7
 
15
8
  * No changes.
16
9
 
17
10
 
18
- ## Rails 7.2.1.1 (October 15, 2024) ##
19
-
20
- * Avoid backtracing in plain_text_for_blockquote_node
21
-
22
- [CVE-2024-47888]
11
+ ## Rails 8.1.0 (October 22, 2025) ##
23
12
 
24
- *John Hawthorn*
13
+ * De-couple `@rails/actiontext/attachment_upload.js` from `Trix.Attachment`
25
14
 
26
- ## Rails 7.2.1 (August 22, 2024) ##
15
+ Implement `@rails/actiontext/index.js` with a `direct-upload:progress` event
16
+ listeners and `Promise` resolution.
27
17
 
28
- * Strip `content` attribute if the key is present but the value is empty
29
-
30
- *Jeremy Green*
31
-
32
-
33
- ## Rails 7.2.0 (August 09, 2024) ##
34
- * Only sanitize `content` attribute when present in attachments.
18
+ *Sean Doyle*
35
19
 
36
- *Petrik de Heus*
20
+ * Capture block content for form helper methods
21
+
22
+ ```erb
23
+ <%= rich_textarea_tag :content, nil do %>
24
+ <h1>hello world</h1>
25
+ <% end %>
26
+ <!-- <input type="hidden" name="content" id="trix_input_1" value="&lt;h1&gt;hello world&lt;/h1&gt;"/><trix-editor … -->
27
+
28
+ <%= rich_textarea :message, :content, input: "trix_input_1" do %>
29
+ <h1>hello world</h1>
30
+ <% end %>
31
+ <!-- <input type="hidden" name="message[content]" id="trix_input_1" value="&lt;h1&gt;hello world&lt;/h1&gt;"/><trix-editor … -->
32
+
33
+ <%= form_with model: Message.new do |form| %>
34
+ <%= form.rich_textarea :content do %>
35
+ <h1>hello world</h1>
36
+ <% end %>
37
+ <% end %>
38
+ <!-- <form action="/messages" accept-charset="UTF-8" method="post"><input type="hidden" name="message[content]" id="message_content_trix_input_message" value="&lt;h1&gt;hello world&lt;/h1&gt;"/><trix-editor … -->
39
+ ```
37
40
 
38
- * Sanitize ActionText HTML ContentAttachment in Trix edit view
39
- [CVE-2024-32464]
41
+ *Sean Doyle*
40
42
 
41
- *Aaron Patterson*, *Zack Deveau*
43
+ * Generalize `:rich_text_area` Capybara selector
42
44
 
43
- * Use `includes` instead of `eager_load` for `with_all_rich_text`.
45
+ Prepare for more Action Text-capable WYSIWYG editors by making
46
+ `:rich_text_area` rely on the presence of `[role="textbox"]` and
47
+ `[contenteditable]` HTML attributes rather than a `<trix-editor>` element.
44
48
 
45
- *Petrik de Heus*
49
+ *Sean Doyle*
46
50
 
47
- * Delegate `ActionText::Content#deconstruct` to `Nokogiri::XML::DocumentFragment#elements`.
51
+ * Forward `fill_in_rich_text_area` options to Capybara
48
52
 
49
53
  ```ruby
50
- content = ActionText::Content.new <<~HTML
51
- <h1>Hello, world</h1>
52
-
53
- <div>The body</div>
54
- HTML
55
-
56
- content => [h1, div]
57
-
58
- assert_pattern { h1 => { content: "Hello, world" } }
59
- assert_pattern { div => { content: "The body" } }
54
+ fill_in_rich_textarea "Rich text editor", id: "trix_editor_1", with: "Hello world!"
60
55
  ```
61
56
 
62
57
  *Sean Doyle*
63
58
 
64
- * Fix all Action Text database related models to respect
65
- `ActiveRecord::Base.table_name_prefix` configuration.
59
+ * Attachment upload progress accounts for server processing time.
66
60
 
67
- *Chedli Bourguiba*
61
+ *Jeremy Daer*
68
62
 
69
- * Compile ESM package that can be used directly in the browser as actiontext.esm.js
63
+ * The Trix dependency is now satisfied by a gem, `action_text-trix`, rather than vendored
64
+ files. This allows applications to bump Trix versions independently of Rails
65
+ releases. Effectively this also upgrades Trix to `>= 2.1.15`.
70
66
 
71
- *Matias Grunberg*
67
+ *Mike Dalessio*
72
68
 
73
- * Fix using actiontext.js with Sprockets.
69
+ * Change `ActionText::RichText#embeds` assignment from `before_save` to `before_validation`
74
70
 
75
- *Matias Grunberg*
76
-
77
- * Upgrade Trix to 2.0.7
78
-
79
- *Hartley McGuire*
80
-
81
- * Fix using Trix with Sprockets.
82
-
83
- *Hartley McGuire*
71
+ *Sean Doyle*
84
72
 
85
- Please check [7-1-stable](https://github.com/rails/rails/blob/7-1-stable/actiontext/CHANGELOG.md) for previous changes.
73
+ Please check [8-0-stable](https://github.com/rails/rails/blob/8-0-stable/actiontext/CHANGELOG.md) for previous changes.
@@ -672,7 +672,7 @@ class DirectUploadController {
672
672
  }));
673
673
  }
674
674
  uploadRequestDidProgress(event) {
675
- const progress = event.loaded / event.total * 100;
675
+ const progress = event.loaded / event.total * 90;
676
676
  if (progress) {
677
677
  this.dispatch("progress", {
678
678
  progress: progress
@@ -707,6 +707,42 @@ class DirectUploadController {
707
707
  xhr: xhr
708
708
  });
709
709
  xhr.upload.addEventListener("progress", (event => this.uploadRequestDidProgress(event)));
710
+ xhr.upload.addEventListener("loadend", (() => {
711
+ this.simulateResponseProgress(xhr);
712
+ }));
713
+ }
714
+ simulateResponseProgress(xhr) {
715
+ let progress = 90;
716
+ const startTime = Date.now();
717
+ const updateProgress = () => {
718
+ const elapsed = Date.now() - startTime;
719
+ const estimatedResponseTime = this.estimateResponseTime();
720
+ const responseProgress = Math.min(elapsed / estimatedResponseTime, 1);
721
+ progress = 90 + responseProgress * 9;
722
+ this.dispatch("progress", {
723
+ progress: progress
724
+ });
725
+ if (xhr.readyState !== XMLHttpRequest.DONE && progress < 99) {
726
+ requestAnimationFrame(updateProgress);
727
+ }
728
+ };
729
+ xhr.addEventListener("loadend", (() => {
730
+ this.dispatch("progress", {
731
+ progress: 100
732
+ });
733
+ }));
734
+ requestAnimationFrame(updateProgress);
735
+ }
736
+ estimateResponseTime() {
737
+ const fileSize = this.file.size;
738
+ const MB = 1024 * 1024;
739
+ if (fileSize < MB) {
740
+ return 1e3;
741
+ } else if (fileSize < 10 * MB) {
742
+ return 2e3;
743
+ } else {
744
+ return 3e3 + fileSize / MB * 50;
745
+ }
710
746
  }
711
747
  }
712
748
 
@@ -846,32 +882,92 @@ function autostart() {
846
882
  setTimeout(autostart, 1);
847
883
 
848
884
  class AttachmentUpload {
849
- constructor(attachment, element) {
885
+ constructor(attachment, element, file = attachment.file) {
850
886
  this.attachment = attachment;
851
887
  this.element = element;
852
- this.directUpload = new DirectUpload(attachment.file, this.directUploadUrl, this);
888
+ this.directUpload = new DirectUpload(file, this.directUploadUrl, this);
889
+ this.file = file;
853
890
  }
854
891
  start() {
855
- this.directUpload.create(this.directUploadDidComplete.bind(this));
892
+ return new Promise(((resolve, reject) => {
893
+ this.directUpload.create(((error, attributes) => this.directUploadDidComplete(error, attributes, resolve, reject)));
894
+ this.dispatch("start");
895
+ }));
856
896
  }
857
897
  directUploadWillStoreFileWithXHR(xhr) {
858
898
  xhr.upload.addEventListener("progress", (event => {
859
- const progress = event.loaded / event.total * 100;
860
- this.attachment.setUploadProgress(progress);
899
+ const progress = event.loaded / event.total * 90;
900
+ if (progress) {
901
+ this.dispatch("progress", {
902
+ progress: progress
903
+ });
904
+ }
905
+ }));
906
+ xhr.upload.addEventListener("loadend", (() => {
907
+ this.simulateResponseProgress(xhr);
908
+ }));
909
+ }
910
+ simulateResponseProgress(xhr) {
911
+ let progress = 90;
912
+ const startTime = Date.now();
913
+ const updateProgress = () => {
914
+ const elapsed = Date.now() - startTime;
915
+ const estimatedResponseTime = this.estimateResponseTime();
916
+ const responseProgress = Math.min(elapsed / estimatedResponseTime, 1);
917
+ progress = 90 + responseProgress * 9;
918
+ this.dispatch("progress", {
919
+ progress: progress
920
+ });
921
+ if (xhr.readyState !== XMLHttpRequest.DONE && progress < 99) {
922
+ requestAnimationFrame(updateProgress);
923
+ }
924
+ };
925
+ xhr.addEventListener("loadend", (() => {
926
+ this.dispatch("progress", {
927
+ progress: 100
928
+ });
861
929
  }));
930
+ requestAnimationFrame(updateProgress);
931
+ }
932
+ estimateResponseTime() {
933
+ const fileSize = this.file.size;
934
+ const MB = 1024 * 1024;
935
+ if (fileSize < MB) {
936
+ return 1e3;
937
+ } else if (fileSize < 10 * MB) {
938
+ return 2e3;
939
+ } else {
940
+ return 3e3 + fileSize / MB * 50;
941
+ }
862
942
  }
863
- directUploadDidComplete(error, attributes) {
943
+ directUploadDidComplete(error, attributes, resolve, reject) {
864
944
  if (error) {
865
- throw new Error(`Direct upload failed: ${error}`);
945
+ this.dispatchError(error, reject);
946
+ } else {
947
+ resolve({
948
+ sgid: attributes.attachable_sgid,
949
+ url: this.createBlobUrl(attributes.signed_id, attributes.filename)
950
+ });
951
+ this.dispatch("end");
866
952
  }
867
- this.attachment.setAttributes({
868
- sgid: attributes.attachable_sgid,
869
- url: this.createBlobUrl(attributes.signed_id, attributes.filename)
870
- });
871
953
  }
872
954
  createBlobUrl(signedId, filename) {
873
955
  return this.blobUrlTemplate.replace(":signed_id", signedId).replace(":filename", encodeURIComponent(filename));
874
956
  }
957
+ dispatch(name, detail = {}) {
958
+ detail.attachment = this.attachment;
959
+ return dispatchEvent(this.element, `direct-upload:${name}`, {
960
+ detail: detail
961
+ });
962
+ }
963
+ dispatchError(error, reject) {
964
+ const event = this.dispatch("error", {
965
+ error: error
966
+ });
967
+ if (!event.defaultPrevented) {
968
+ reject(error);
969
+ }
970
+ }
875
971
  get directUploadUrl() {
876
972
  return this.element.dataset.directUploadUrl;
877
973
  }
@@ -883,7 +979,11 @@ class AttachmentUpload {
883
979
  addEventListener("trix-attachment-add", (event => {
884
980
  const {attachment: attachment, target: target} = event;
885
981
  if (attachment.file) {
886
- const upload = new AttachmentUpload(attachment, target);
887
- upload.start();
982
+ const upload = new AttachmentUpload(attachment, target, attachment.file);
983
+ const onProgress = event => attachment.setUploadProgress(event.detail.progress);
984
+ target.addEventListener("direct-upload:progress", onProgress);
985
+ upload.start().then((attributes => attachment.setAttributes(attributes))).catch((error => alert(error))).finally((() => target.removeEventListener("direct-upload:progress", onProgress)));
888
986
  }
889
987
  }));
988
+
989
+ export { AttachmentUpload };
@@ -1,6 +1,7 @@
1
- (function(factory) {
2
- typeof define === "function" && define.amd ? define(factory) : factory();
3
- })((function() {
1
+ (function(global, factory) {
2
+ typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define([ "exports" ], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self,
3
+ factory(global.ActionText = {}));
4
+ })(this, (function(exports) {
4
5
  "use strict";
5
6
  var sparkMd5 = {
6
7
  exports: {}
@@ -661,7 +662,7 @@
661
662
  }));
662
663
  }
663
664
  uploadRequestDidProgress(event) {
664
- const progress = event.loaded / event.total * 100;
665
+ const progress = event.loaded / event.total * 90;
665
666
  if (progress) {
666
667
  this.dispatch("progress", {
667
668
  progress: progress
@@ -696,6 +697,42 @@
696
697
  xhr: xhr
697
698
  });
698
699
  xhr.upload.addEventListener("progress", (event => this.uploadRequestDidProgress(event)));
700
+ xhr.upload.addEventListener("loadend", (() => {
701
+ this.simulateResponseProgress(xhr);
702
+ }));
703
+ }
704
+ simulateResponseProgress(xhr) {
705
+ let progress = 90;
706
+ const startTime = Date.now();
707
+ const updateProgress = () => {
708
+ const elapsed = Date.now() - startTime;
709
+ const estimatedResponseTime = this.estimateResponseTime();
710
+ const responseProgress = Math.min(elapsed / estimatedResponseTime, 1);
711
+ progress = 90 + responseProgress * 9;
712
+ this.dispatch("progress", {
713
+ progress: progress
714
+ });
715
+ if (xhr.readyState !== XMLHttpRequest.DONE && progress < 99) {
716
+ requestAnimationFrame(updateProgress);
717
+ }
718
+ };
719
+ xhr.addEventListener("loadend", (() => {
720
+ this.dispatch("progress", {
721
+ progress: 100
722
+ });
723
+ }));
724
+ requestAnimationFrame(updateProgress);
725
+ }
726
+ estimateResponseTime() {
727
+ const fileSize = this.file.size;
728
+ const MB = 1024 * 1024;
729
+ if (fileSize < MB) {
730
+ return 1e3;
731
+ } else if (fileSize < 10 * MB) {
732
+ return 2e3;
733
+ } else {
734
+ return 3e3 + fileSize / MB * 50;
735
+ }
699
736
  }
700
737
  }
701
738
  const inputSelector = "input[type=file][data-direct-upload-url]:not([disabled])";
@@ -819,32 +856,92 @@
819
856
  }
820
857
  setTimeout(autostart, 1);
821
858
  class AttachmentUpload {
822
- constructor(attachment, element) {
859
+ constructor(attachment, element, file = attachment.file) {
823
860
  this.attachment = attachment;
824
861
  this.element = element;
825
- this.directUpload = new DirectUpload(attachment.file, this.directUploadUrl, this);
862
+ this.directUpload = new DirectUpload(file, this.directUploadUrl, this);
863
+ this.file = file;
826
864
  }
827
865
  start() {
828
- this.directUpload.create(this.directUploadDidComplete.bind(this));
866
+ return new Promise(((resolve, reject) => {
867
+ this.directUpload.create(((error, attributes) => this.directUploadDidComplete(error, attributes, resolve, reject)));
868
+ this.dispatch("start");
869
+ }));
829
870
  }
830
871
  directUploadWillStoreFileWithXHR(xhr) {
831
872
  xhr.upload.addEventListener("progress", (event => {
832
- const progress = event.loaded / event.total * 100;
833
- this.attachment.setUploadProgress(progress);
873
+ const progress = event.loaded / event.total * 90;
874
+ if (progress) {
875
+ this.dispatch("progress", {
876
+ progress: progress
877
+ });
878
+ }
879
+ }));
880
+ xhr.upload.addEventListener("loadend", (() => {
881
+ this.simulateResponseProgress(xhr);
834
882
  }));
835
883
  }
836
- directUploadDidComplete(error, attributes) {
884
+ simulateResponseProgress(xhr) {
885
+ let progress = 90;
886
+ const startTime = Date.now();
887
+ const updateProgress = () => {
888
+ const elapsed = Date.now() - startTime;
889
+ const estimatedResponseTime = this.estimateResponseTime();
890
+ const responseProgress = Math.min(elapsed / estimatedResponseTime, 1);
891
+ progress = 90 + responseProgress * 9;
892
+ this.dispatch("progress", {
893
+ progress: progress
894
+ });
895
+ if (xhr.readyState !== XMLHttpRequest.DONE && progress < 99) {
896
+ requestAnimationFrame(updateProgress);
897
+ }
898
+ };
899
+ xhr.addEventListener("loadend", (() => {
900
+ this.dispatch("progress", {
901
+ progress: 100
902
+ });
903
+ }));
904
+ requestAnimationFrame(updateProgress);
905
+ }
906
+ estimateResponseTime() {
907
+ const fileSize = this.file.size;
908
+ const MB = 1024 * 1024;
909
+ if (fileSize < MB) {
910
+ return 1e3;
911
+ } else if (fileSize < 10 * MB) {
912
+ return 2e3;
913
+ } else {
914
+ return 3e3 + fileSize / MB * 50;
915
+ }
916
+ }
917
+ directUploadDidComplete(error, attributes, resolve, reject) {
837
918
  if (error) {
838
- throw new Error(`Direct upload failed: ${error}`);
919
+ this.dispatchError(error, reject);
920
+ } else {
921
+ resolve({
922
+ sgid: attributes.attachable_sgid,
923
+ url: this.createBlobUrl(attributes.signed_id, attributes.filename)
924
+ });
925
+ this.dispatch("end");
839
926
  }
840
- this.attachment.setAttributes({
841
- sgid: attributes.attachable_sgid,
842
- url: this.createBlobUrl(attributes.signed_id, attributes.filename)
843
- });
844
927
  }
845
928
  createBlobUrl(signedId, filename) {
846
929
  return this.blobUrlTemplate.replace(":signed_id", signedId).replace(":filename", encodeURIComponent(filename));
847
930
  }
931
+ dispatch(name, detail = {}) {
932
+ detail.attachment = this.attachment;
933
+ return dispatchEvent(this.element, `direct-upload:${name}`, {
934
+ detail: detail
935
+ });
936
+ }
937
+ dispatchError(error, reject) {
938
+ const event = this.dispatch("error", {
939
+ error: error
940
+ });
941
+ if (!event.defaultPrevented) {
942
+ reject(error);
943
+ }
944
+ }
848
945
  get directUploadUrl() {
849
946
  return this.element.dataset.directUploadUrl;
850
947
  }
@@ -855,8 +952,14 @@
855
952
  addEventListener("trix-attachment-add", (event => {
856
953
  const {attachment: attachment, target: target} = event;
857
954
  if (attachment.file) {
858
- const upload = new AttachmentUpload(attachment, target);
859
- upload.start();
955
+ const upload = new AttachmentUpload(attachment, target, attachment.file);
956
+ const onProgress = event => attachment.setUploadProgress(event.detail.progress);
957
+ target.addEventListener("direct-upload:progress", onProgress);
958
+ upload.start().then((attributes => attachment.setAttributes(attributes))).catch((error => alert(error))).finally((() => target.removeEventListener("direct-upload:progress", onProgress)));
860
959
  }
861
960
  }));
961
+ exports.AttachmentUpload = AttachmentUpload;
962
+ Object.defineProperty(exports, "__esModule", {
963
+ value: true
964
+ });
862
965
  }));
@@ -24,10 +24,17 @@ 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
+ #
31
+ # rich_textarea_tag "content", nil do
32
+ # "<h1>Default content</h1>"
33
+ # end
34
+ # # <input type="hidden" name="content" id="trix_input_post_1" value="&lt;h1&gt;Default content&lt;/h1&gt;">
35
+ # # <trix-editor id="content" input="trix_input_post_1" class="trix-content" ...></trix-editor>
36
+ def rich_textarea_tag(name, value = nil, options = {}, &block)
37
+ value = capture(&block) if value.nil? && block_given?
31
38
  options = options.symbolize_keys
32
39
  form = options.delete(:form)
33
40
 
@@ -43,6 +50,7 @@ module ActionText
43
50
 
44
51
  input_tag + editor_tag
45
52
  end
53
+ alias_method :rich_text_area_tag, :rich_textarea_tag
46
54
  end
47
55
  end
48
56
 
@@ -52,11 +60,11 @@ module ActionView::Helpers
52
60
 
53
61
  delegate :dom_id, to: ActionView::RecordIdentifier
54
62
 
55
- def render
63
+ def render(&block)
56
64
  options = @options.stringify_keys
57
- add_default_name_and_id(options)
65
+ add_default_name_and_field(options)
58
66
  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"))
67
+ html_tag = @template_object.rich_textarea_tag(options.delete("name"), options.fetch("value") { value }, options.except("value"), &block)
60
68
  error_wrapping(html_tag)
61
69
  end
62
70
  end
@@ -76,28 +84,36 @@ module ActionView::Helpers
76
84
  #
77
85
  #
78
86
  # #### Example
79
- # rich_text_area :message, :content
87
+ # rich_textarea :message, :content
80
88
  # # <input type="hidden" name="message[content]" id="message_content_trix_input_message_1">
81
89
  # # <trix-editor id="content" input="message_content_trix_input_message_1" class="trix-content" ...></trix-editor>
82
90
  #
83
- # rich_text_area :message, :content, value: "<h1>Default message</h1>"
84
- # # <input type="hidden" name="message[content]" id="message_content_trix_input_message_1" value="<h1>Default message</h1>">
91
+ # rich_textarea :message, :content, value: "<h1>Default message</h1>"
92
+ # # <input type="hidden" name="message[content]" id="message_content_trix_input_message_1" value="&lt;h1&gt;Default message&lt;/h1&gt;">
93
+ # # <trix-editor id="content" input="message_content_trix_input_message_1" class="trix-content" ...></trix-editor>
94
+ #
95
+ # rich_textarea :message, :content do
96
+ # "<h1>Default message</h1>"
97
+ # end
98
+ # # <input type="hidden" name="message[content]" id="message_content_trix_input_message_1" value="&lt;h1&gt;Default message&lt;/h1&gt;">
85
99
  # # <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
- Tags::ActionText.new(object_name, method, self, options).render
100
+ def rich_textarea(object_name, method, options = {}, &block)
101
+ Tags::ActionText.new(object_name, method, self, options).render(&block)
88
102
  end
103
+ alias_method :rich_text_area, :rich_textarea
89
104
  end
90
105
 
91
106
  class FormBuilder
92
- # Wraps ActionView::Helpers::FormHelper#rich_text_area for form builders:
107
+ # Wraps ActionView::Helpers::FormHelper#rich_textarea for form builders:
93
108
  #
94
109
  # <%= form_with model: @message do |f| %>
95
- # <%= f.rich_text_area :content %>
110
+ # <%= f.rich_textarea :content %>
96
111
  # <% end %>
97
112
  #
98
113
  # 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))
114
+ def rich_textarea(method, options = {}, &block)
115
+ @template.rich_textarea(@object_name, method, objectify_options(options), &block)
101
116
  end
117
+ alias_method :rich_text_area, :rich_textarea
102
118
  end
103
119
  end