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 +4 -4
- data/CHANGELOG.md +44 -56
- data/app/assets/javascripts/actiontext.esm.js +114 -14
- data/app/assets/javascripts/actiontext.js +120 -17
- data/app/helpers/action_text/tag_helper.rb +30 -14
- data/app/javascript/actiontext/attachment_upload.js +78 -12
- data/app/javascript/actiontext/index.js +10 -1
- data/app/models/action_text/rich_text.rb +5 -2
- data/lib/action_text/attribute.rb +25 -5
- data/lib/action_text/content.rb +4 -3
- data/lib/action_text/engine.rb +5 -2
- data/lib/action_text/fixture_set.rb +1 -1
- data/lib/action_text/gem_version.rb +3 -3
- data/lib/action_text/plain_text_conversion.rb +63 -28
- data/lib/action_text/rendering.rb +0 -1
- data/lib/action_text/system_test_helper.rb +37 -21
- data/lib/generators/action_text/install/install_generator.rb +0 -24
- data/lib/generators/action_text/install/templates/actiontext.css +414 -5
- data/package.json +3 -2
- metadata +29 -20
- data/app/assets/javascripts/trix.js +0 -13720
- data/app/assets/stylesheets/trix.css +0 -412
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5b092ec1c0802a3bde54aa34e486bc4e943559d80c7a5b848dfef6520886d791
|
|
4
|
+
data.tar.gz: '08edc788a5dac28c6de1186100be082f6f5b87d641983784fa0635040e8a40bc'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2f8c3814fc94289ccd59710e97b88377845d816f3e5576f9f6f56a270e4d688a09588874b973868502ca77b043e012f84f91ebf55775e3196de585a20976fe95
|
|
7
|
+
data.tar.gz: ed2d48e94658668d0bbe2b6073e0f23659a79c92c491811975b2b0b6c4275622c0c83f693b4388056a51d026c934f79605e348dc8cbaa0f2b922e7acb6962b24
|
data/CHANGELOG.md
CHANGED
|
@@ -1,85 +1,73 @@
|
|
|
1
|
-
## Rails
|
|
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
|
|
6
|
+
## Rails 8.1.1 (October 28, 2025) ##
|
|
14
7
|
|
|
15
8
|
* No changes.
|
|
16
9
|
|
|
17
10
|
|
|
18
|
-
## Rails
|
|
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
|
-
|
|
13
|
+
* De-couple `@rails/actiontext/attachment_upload.js` from `Trix.Attachment`
|
|
25
14
|
|
|
26
|
-
|
|
15
|
+
Implement `@rails/actiontext/index.js` with a `direct-upload:progress` event
|
|
16
|
+
listeners and `Promise` resolution.
|
|
27
17
|
|
|
28
|
-
*
|
|
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
|
-
|
|
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="<h1>hello world</h1>"/><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="<h1>hello world</h1>"/><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="<h1>hello world</h1>"/><trix-editor … -->
|
|
39
|
+
```
|
|
37
40
|
|
|
38
|
-
*
|
|
39
|
-
[CVE-2024-32464]
|
|
41
|
+
*Sean Doyle*
|
|
40
42
|
|
|
41
|
-
|
|
43
|
+
* Generalize `:rich_text_area` Capybara selector
|
|
42
44
|
|
|
43
|
-
|
|
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
|
-
*
|
|
49
|
+
*Sean Doyle*
|
|
46
50
|
|
|
47
|
-
*
|
|
51
|
+
* Forward `fill_in_rich_text_area` options to Capybara
|
|
48
52
|
|
|
49
53
|
```ruby
|
|
50
|
-
|
|
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
|
-
*
|
|
65
|
-
`ActiveRecord::Base.table_name_prefix` configuration.
|
|
59
|
+
* Attachment upload progress accounts for server processing time.
|
|
66
60
|
|
|
67
|
-
*
|
|
61
|
+
*Jeremy Daer*
|
|
68
62
|
|
|
69
|
-
*
|
|
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
|
-
*
|
|
67
|
+
*Mike Dalessio*
|
|
72
68
|
|
|
73
|
-
*
|
|
69
|
+
* Change `ActionText::RichText#embeds` assignment from `before_save` to `before_validation`
|
|
74
70
|
|
|
75
|
-
*
|
|
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 [
|
|
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 *
|
|
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(
|
|
888
|
+
this.directUpload = new DirectUpload(file, this.directUploadUrl, this);
|
|
889
|
+
this.file = file;
|
|
853
890
|
}
|
|
854
891
|
start() {
|
|
855
|
-
|
|
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 *
|
|
860
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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) :
|
|
3
|
-
})
|
|
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 *
|
|
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(
|
|
862
|
+
this.directUpload = new DirectUpload(file, this.directUploadUrl, this);
|
|
863
|
+
this.file = file;
|
|
826
864
|
}
|
|
827
865
|
start() {
|
|
828
|
-
|
|
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 *
|
|
833
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
#
|
|
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
|
-
|
|
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="<h1>Default content</h1>">
|
|
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
|
-
|
|
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.
|
|
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
|
-
#
|
|
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
|
-
#
|
|
84
|
-
# # <input type="hidden" name="message[content]" id="message_content_trix_input_message_1" value="
|
|
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="<h1>Default message</h1>">
|
|
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="<h1>Default message</h1>">
|
|
85
99
|
# # <trix-editor id="content" input="message_content_trix_input_message_1" class="trix-content" ...></trix-editor>
|
|
86
|
-
def
|
|
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#
|
|
107
|
+
# Wraps ActionView::Helpers::FormHelper#rich_textarea for form builders:
|
|
93
108
|
#
|
|
94
109
|
# <%= form_with model: @message do |f| %>
|
|
95
|
-
# <%= f.
|
|
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
|
|
100
|
-
@template.
|
|
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
|