actiontext 7.1.3 → 7.2.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +37 -73
- data/app/assets/javascripts/trix.js +92 -30
- data/app/assets/stylesheets/trix.css +3 -1
- data/app/helpers/action_text/content_helper.rb +11 -0
- data/app/helpers/action_text/tag_helper.rb +38 -28
- data/app/models/action_text/encrypted_rich_text.rb +2 -2
- data/app/models/action_text/record.rb +2 -0
- data/app/models/action_text/rich_text.rb +58 -26
- data/db/migrate/20180528164100_create_action_text_tables.rb +1 -1
- data/lib/action_text/attachable.rb +35 -33
- data/lib/action_text/attachables/content_attachment.rb +2 -0
- data/lib/action_text/attachables/missing_attachable.rb +2 -0
- data/lib/action_text/attachables/remote_image.rb +2 -0
- data/lib/action_text/attachment.rb +27 -25
- data/lib/action_text/attachment_gallery.rb +2 -0
- data/lib/action_text/attachments/caching.rb +2 -0
- data/lib/action_text/attachments/minification.rb +2 -0
- data/lib/action_text/attachments/trix_conversion.rb +2 -0
- data/lib/action_text/attribute.rb +36 -22
- data/lib/action_text/content.rb +51 -27
- data/lib/action_text/deprecator.rb +2 -0
- data/lib/action_text/encryption.rb +2 -0
- data/lib/action_text/engine.rb +2 -0
- data/lib/action_text/fixture_set.rb +34 -34
- data/lib/action_text/fragment.rb +4 -0
- data/lib/action_text/gem_version.rb +6 -4
- data/lib/action_text/html_conversion.rb +2 -0
- data/lib/action_text/plain_text_conversion.rb +8 -1
- data/lib/action_text/rendering.rb +2 -0
- data/lib/action_text/serialization.rb +2 -0
- data/lib/action_text/system_test_helper.rb +20 -17
- data/lib/action_text/trix_attachment.rb +2 -0
- data/lib/action_text/version.rb +3 -1
- data/lib/action_text.rb +1 -1
- data/lib/generators/action_text/install/install_generator.rb +10 -3
- data/lib/rails/generators/test_unit/install_generator.rb +2 -0
- data/package.json +2 -2
- metadata +18 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dff22ea29340985c645f24023a493f071bb20b46bf7219adce5116af1cb2ce09
|
4
|
+
data.tar.gz: e8d8db93776bf73f40814736dc238d5643b62434b85ddcffe1c0d9d096d1c940
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3e6e30b5e160f1f7a3475653fd2cafca61e1ddf94320a5937cb8afe2d58feaca027885a37260f2fe96840433428a4b77f8a69435481d24eec27c3b0e9e82e407
|
7
|
+
data.tar.gz: 827a4e32168d54371c23143c469674421217b6411bedb180e7c639e643b500f44236afbf47996a82d7f5b09559838c032aaa1c296b4444265a979b15b7fcb7be
|
data/CHANGELOG.md
CHANGED
@@ -1,102 +1,66 @@
|
|
1
|
-
## Rails 7.1.
|
1
|
+
## Rails 7.2.1.1 (October 15, 2024) ##
|
2
2
|
|
3
|
-
*
|
3
|
+
* Avoid backtracing in plain_text_for_blockquote_node
|
4
4
|
|
5
|
+
[CVE-2024-47888]
|
5
6
|
|
6
|
-
## Rails 7.1
|
7
|
+
## Rails 7.2.1 (August 22, 2024) ##
|
7
8
|
|
8
|
-
*
|
9
|
-
|
10
|
-
*Matias Grunberg*
|
11
|
-
|
12
|
-
* Fix using actiontext.js with Sprockets.
|
13
|
-
|
14
|
-
*Matias Grunberg*
|
15
|
-
|
16
|
-
* Upgrade Trix to 2.0.7.
|
17
|
-
|
18
|
-
*Hartley McGuire*
|
19
|
-
|
20
|
-
* Fix using Trix with Sprockets.
|
21
|
-
|
22
|
-
*Hartley McGuire*
|
23
|
-
|
24
|
-
|
25
|
-
## Rails 7.1.1 (October 11, 2023) ##
|
26
|
-
|
27
|
-
* No changes.
|
9
|
+
* Strip `content` attribute if the key is present but the value is empty
|
28
10
|
|
11
|
+
*Jeremy Green*
|
29
12
|
|
30
|
-
## Rails 7.1.0 (October 05, 2023) ##
|
31
13
|
|
32
|
-
|
14
|
+
## Rails 7.2.0 (August 09, 2024) ##
|
15
|
+
* Only sanitize `content` attribute when present in attachments.
|
33
16
|
|
17
|
+
*Petrik de Heus*
|
34
18
|
|
35
|
-
|
19
|
+
* Sanitize ActionText HTML ContentAttachment in Trix edit view
|
20
|
+
[CVE-2024-32464]
|
36
21
|
|
37
|
-
*
|
22
|
+
*Aaron Patterson*, *Zack Deveau*
|
38
23
|
|
24
|
+
* Use `includes` instead of `eager_load` for `with_all_rich_text`.
|
39
25
|
|
40
|
-
|
26
|
+
*Petrik de Heus*
|
41
27
|
|
42
|
-
*
|
28
|
+
* Delegate `ActionText::Content#deconstruct` to `Nokogiri::XML::DocumentFragment#elements`.
|
43
29
|
|
30
|
+
```ruby
|
31
|
+
content = ActionText::Content.new <<~HTML
|
32
|
+
<h1>Hello, world</h1>
|
44
33
|
|
45
|
-
|
34
|
+
<div>The body</div>
|
35
|
+
HTML
|
46
36
|
|
47
|
-
|
48
|
-
supported.
|
37
|
+
content => [h1, div]
|
49
38
|
|
50
|
-
|
51
|
-
|
52
|
-
|
39
|
+
assert_pattern { h1 => { content: "Hello, world" } }
|
40
|
+
assert_pattern { div => { content: "The body" } }
|
41
|
+
```
|
53
42
|
|
54
|
-
|
55
|
-
fall back to `Rails::HTML4::Sanitizer`. Previous configurations default to
|
56
|
-
`Rails::HTML4::Sanitizer`.
|
57
|
-
|
58
|
-
As a result of this change, the defaults for `ActionText::ContentHelper.allowed_tags` and
|
59
|
-
`.allowed_attributes` are applied at runtime, so the value of these attributes is now 'nil'
|
60
|
-
unless set by the application. You may call `sanitizer_allowed_tags` or
|
61
|
-
`sanitizer_allowed_attributes` to inspect the tags and attributes being allowed by the
|
62
|
-
sanitizer.
|
63
|
-
|
64
|
-
*Mike Dalessio*
|
65
|
-
|
66
|
-
* Attachables now can override default attachment missing template.
|
67
|
-
|
68
|
-
When rendering Action Text attachments where the underlying attachable model has
|
69
|
-
been removed, a fallback template is used. You now can override this template on
|
70
|
-
a per-model basis. For example, you could render a placeholder image for a file
|
71
|
-
attachment or the text "Deleted User" for a User attachment.
|
72
|
-
|
73
|
-
*Matt Swanson*, *Joel Drapper*
|
74
|
-
|
75
|
-
* Update bundled Trix version from `1.3.1` to `2.0.4`.
|
76
|
-
|
77
|
-
*Sarah Ridge*, *Sean Doyle*
|
43
|
+
*Sean Doyle*
|
78
44
|
|
79
|
-
*
|
45
|
+
* Fix all Action Text database related models to respect
|
46
|
+
`ActiveRecord::Base.table_name_prefix` configuration.
|
80
47
|
|
81
|
-
*
|
48
|
+
*Chedli Bourguiba*
|
82
49
|
|
83
|
-
*
|
84
|
-
Streams) now use `Rails.application.default_url_options` and
|
85
|
-
`Rails.application.config.force_ssl` instead of `http://example.org`.
|
50
|
+
* Compile ESM package that can be used directly in the browser as actiontext.esm.js
|
86
51
|
|
87
|
-
*
|
52
|
+
*Matias Grunberg*
|
88
53
|
|
89
|
-
*
|
54
|
+
* Fix using actiontext.js with Sprockets.
|
90
55
|
|
91
|
-
*
|
56
|
+
*Matias Grunberg*
|
92
57
|
|
93
|
-
*
|
58
|
+
* Upgrade Trix to 2.0.7
|
94
59
|
|
95
|
-
*
|
60
|
+
*Hartley McGuire*
|
96
61
|
|
97
|
-
* Fix
|
98
|
-
rich_text field was updated.
|
62
|
+
* Fix using Trix with Sprockets.
|
99
63
|
|
100
|
-
*
|
64
|
+
*Hartley McGuire*
|
101
65
|
|
102
|
-
Please check [7-
|
66
|
+
Please check [7-1-stable](https://github.com/rails/rails/blob/7-1-stable/actiontext/CHANGELOG.md) for previous changes.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
|
-
Trix 2.
|
3
|
-
Copyright ©
|
2
|
+
Trix 2.1.1
|
3
|
+
Copyright © 2024 37signals, LLC
|
4
4
|
*/
|
5
5
|
(function (global, factory) {
|
6
6
|
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
@@ -9,7 +9,7 @@ Copyright © 2023 37signals, LLC
|
|
9
9
|
})(this, (function () { 'use strict';
|
10
10
|
|
11
11
|
var name = "trix";
|
12
|
-
var version = "2.
|
12
|
+
var version = "2.1.1";
|
13
13
|
var description = "A rich text editor for everyday writing";
|
14
14
|
var main = "dist/trix.umd.min.js";
|
15
15
|
var module = "dist/trix.esm.min.js";
|
@@ -17,6 +17,7 @@ Copyright © 2023 37signals, LLC
|
|
17
17
|
var files = [
|
18
18
|
"dist/*.css",
|
19
19
|
"dist/*.js",
|
20
|
+
"dist/*.map",
|
20
21
|
"src/{inspector,trix}/*.js"
|
21
22
|
];
|
22
23
|
var repository = {
|
@@ -130,6 +131,7 @@ Copyright © 2023 37signals, LLC
|
|
130
131
|
code: {
|
131
132
|
tagName: "pre",
|
132
133
|
terminal: true,
|
134
|
+
htmlAttributes: ["language"],
|
133
135
|
text: {
|
134
136
|
plaintext: true
|
135
137
|
}
|
@@ -1215,7 +1217,7 @@ $\
|
|
1215
1217
|
no-useless-escape,
|
1216
1218
|
*/
|
1217
1219
|
const normalizeSpaces = string => string.replace(new RegExp("".concat(ZERO_WIDTH_SPACE), "g"), "").replace(new RegExp("".concat(NON_BREAKING_SPACE), "g"), " ");
|
1218
|
-
const normalizeNewlines = string => string.replace(/\r\n
|
1220
|
+
const normalizeNewlines = string => string.replace(/\r\n?/g, "\n");
|
1219
1221
|
const breakableWhitespacePattern = new RegExp("[^\\S".concat(NON_BREAKING_SPACE, "]"));
|
1220
1222
|
const squishBreakableWhitespace = string => string
|
1221
1223
|
// Replace all breakable whitespace characters with a space
|
@@ -2144,20 +2146,28 @@ $\
|
|
2144
2146
|
}
|
2145
2147
|
}
|
2146
2148
|
createContainerElement(depth) {
|
2147
|
-
|
2149
|
+
const attributes = {};
|
2150
|
+
let className;
|
2148
2151
|
const attributeName = this.attributes[depth];
|
2149
2152
|
const {
|
2150
|
-
tagName
|
2153
|
+
tagName,
|
2154
|
+
htmlAttributes = []
|
2151
2155
|
} = getBlockConfig(attributeName);
|
2152
2156
|
if (depth === 0 && this.block.isRTL()) {
|
2153
|
-
attributes
|
2157
|
+
Object.assign(attributes, {
|
2154
2158
|
dir: "rtl"
|
2155
|
-
};
|
2159
|
+
});
|
2156
2160
|
}
|
2157
2161
|
if (attributeName === "attachmentGallery") {
|
2158
2162
|
const size = this.block.getBlockBreakPosition();
|
2159
2163
|
className = "".concat(css$1.attachmentGallery, " ").concat(css$1.attachmentGallery, "--").concat(size);
|
2160
2164
|
}
|
2165
|
+
Object.entries(this.block.htmlAttributes).forEach(_ref => {
|
2166
|
+
let [name, value] = _ref;
|
2167
|
+
if (htmlAttributes.includes(name)) {
|
2168
|
+
attributes[name] = value;
|
2169
|
+
}
|
2170
|
+
});
|
2161
2171
|
return makeElement({
|
2162
2172
|
tagName,
|
2163
2173
|
className,
|
@@ -5828,28 +5838,29 @@ $\
|
|
5828
5838
|
class Block extends TrixObject {
|
5829
5839
|
static fromJSON(blockJSON) {
|
5830
5840
|
const text = Text.fromJSON(blockJSON.text);
|
5831
|
-
return new this(text, blockJSON.attributes);
|
5841
|
+
return new this(text, blockJSON.attributes, blockJSON.htmlAttributes);
|
5832
5842
|
}
|
5833
|
-
constructor(text, attributes) {
|
5843
|
+
constructor(text, attributes, htmlAttributes) {
|
5834
5844
|
super(...arguments);
|
5835
5845
|
this.text = applyBlockBreakToText(text || new Text());
|
5836
5846
|
this.attributes = attributes || [];
|
5847
|
+
this.htmlAttributes = htmlAttributes || {};
|
5837
5848
|
}
|
5838
5849
|
isEmpty() {
|
5839
5850
|
return this.text.isBlockBreak();
|
5840
5851
|
}
|
5841
5852
|
isEqualTo(block) {
|
5842
5853
|
if (super.isEqualTo(block)) return true;
|
5843
|
-
return this.text.isEqualTo(block === null || block === void 0 ? void 0 : block.text) && arraysAreEqual(this.attributes, block === null || block === void 0 ? void 0 : block.attributes);
|
5854
|
+
return this.text.isEqualTo(block === null || block === void 0 ? void 0 : block.text) && arraysAreEqual(this.attributes, block === null || block === void 0 ? void 0 : block.attributes) && objectsAreEqual(this.htmlAttributes, block === null || block === void 0 ? void 0 : block.htmlAttributes);
|
5844
5855
|
}
|
5845
5856
|
copyWithText(text) {
|
5846
|
-
return new Block(text, this.attributes);
|
5857
|
+
return new Block(text, this.attributes, this.htmlAttributes);
|
5847
5858
|
}
|
5848
5859
|
copyWithoutText() {
|
5849
5860
|
return this.copyWithText(null);
|
5850
5861
|
}
|
5851
5862
|
copyWithAttributes(attributes) {
|
5852
|
-
return new Block(this.text, attributes);
|
5863
|
+
return new Block(this.text, attributes, this.htmlAttributes);
|
5853
5864
|
}
|
5854
5865
|
copyWithoutAttributes() {
|
5855
5866
|
return this.copyWithAttributes(null);
|
@@ -5866,6 +5877,12 @@ $\
|
|
5866
5877
|
const attributes = this.attributes.concat(expandAttribute(attribute));
|
5867
5878
|
return this.copyWithAttributes(attributes);
|
5868
5879
|
}
|
5880
|
+
addHTMLAttribute(attribute, value) {
|
5881
|
+
const htmlAttributes = Object.assign({}, this.htmlAttributes, {
|
5882
|
+
[attribute]: value
|
5883
|
+
});
|
5884
|
+
return new Block(this.text, this.attributes, htmlAttributes);
|
5885
|
+
}
|
5869
5886
|
removeAttribute(attribute) {
|
5870
5887
|
const {
|
5871
5888
|
listAttribute
|
@@ -5962,7 +5979,8 @@ $\
|
|
5962
5979
|
toJSON() {
|
5963
5980
|
return {
|
5964
5981
|
text: this.text,
|
5965
|
-
attributes: this.attributes
|
5982
|
+
attributes: this.attributes,
|
5983
|
+
htmlAttributes: this.htmlAttributes
|
5966
5984
|
};
|
5967
5985
|
}
|
5968
5986
|
|
@@ -6325,6 +6343,11 @@ $\
|
|
6325
6343
|
const range = this.getRangeOfAttachment(attachment);
|
6326
6344
|
return this.removeAttributeAtRange(attribute, range);
|
6327
6345
|
}
|
6346
|
+
setHTMLAttributeAtPosition(position, name, value) {
|
6347
|
+
const block = this.getBlockAtPosition(position);
|
6348
|
+
const updatedBlock = block.addHTMLAttribute(name, value);
|
6349
|
+
return this.replaceBlock(block, updatedBlock);
|
6350
|
+
}
|
6328
6351
|
insertBlockBreakAtRange(range) {
|
6329
6352
|
let blocks;
|
6330
6353
|
range = normalizeRange(range);
|
@@ -6793,9 +6816,9 @@ $\
|
|
6793
6816
|
return attributes;
|
6794
6817
|
};
|
6795
6818
|
|
6796
|
-
const DEFAULT_ALLOWED_ATTRIBUTES = "style href src width height class".split(" ");
|
6819
|
+
const DEFAULT_ALLOWED_ATTRIBUTES = "style href src width height language class".split(" ");
|
6797
6820
|
const DEFAULT_FORBIDDEN_PROTOCOLS = "javascript:".split(" ");
|
6798
|
-
const DEFAULT_FORBIDDEN_ELEMENTS = "script iframe form".split(" ");
|
6821
|
+
const DEFAULT_FORBIDDEN_ELEMENTS = "script iframe form noscript".split(" ");
|
6799
6822
|
class HTMLSanitizer extends BasicObject {
|
6800
6823
|
static sanitize(html, options) {
|
6801
6824
|
const sanitizer = new this(html, options);
|
@@ -6923,15 +6946,21 @@ $\
|
|
6923
6946
|
};
|
6924
6947
|
const blockForAttributes = function () {
|
6925
6948
|
let attributes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
6949
|
+
let htmlAttributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
6926
6950
|
const text = [];
|
6927
6951
|
return {
|
6928
6952
|
text,
|
6929
|
-
attributes
|
6953
|
+
attributes,
|
6954
|
+
htmlAttributes
|
6930
6955
|
};
|
6931
6956
|
};
|
6932
6957
|
const parseTrixDataAttribute = (element, name) => {
|
6933
6958
|
try {
|
6934
|
-
|
6959
|
+
const data = JSON.parse(element.getAttribute("data-trix-".concat(name)));
|
6960
|
+
if (data.contentType === "text/html" && data.content) {
|
6961
|
+
data.content = HTMLSanitizer.sanitize(data.content).getHTML();
|
6962
|
+
}
|
6963
|
+
return data;
|
6935
6964
|
} catch (error) {
|
6936
6965
|
return {};
|
6937
6966
|
}
|
@@ -7027,8 +7056,9 @@ $\
|
|
7027
7056
|
} else if (element === this.containerElement || this.isBlockElement(element)) {
|
7028
7057
|
var _this$currentBlock;
|
7029
7058
|
const attributes = this.getBlockAttributes(element);
|
7059
|
+
const htmlAttributes = this.getBlockHTMLAttributes(element);
|
7030
7060
|
if (!arraysAreEqual(attributes, (_this$currentBlock = this.currentBlock) === null || _this$currentBlock === void 0 ? void 0 : _this$currentBlock.attributes)) {
|
7031
|
-
this.currentBlock = this.appendBlockForAttributesWithElement(attributes, element);
|
7061
|
+
this.currentBlock = this.appendBlockForAttributesWithElement(attributes, element, htmlAttributes);
|
7032
7062
|
this.currentBlockElement = element;
|
7033
7063
|
}
|
7034
7064
|
}
|
@@ -7039,9 +7069,10 @@ $\
|
|
7039
7069
|
if (elementIsBlockElement && !this.isBlockElement(element.firstChild)) {
|
7040
7070
|
if (!this.isInsignificantTextNode(element.firstChild) || !this.isBlockElement(element.firstElementChild)) {
|
7041
7071
|
const attributes = this.getBlockAttributes(element);
|
7072
|
+
const htmlAttributes = this.getBlockHTMLAttributes(element);
|
7042
7073
|
if (element.firstChild) {
|
7043
7074
|
if (!(currentBlockContainsElement && arraysAreEqual(attributes, this.currentBlock.attributes))) {
|
7044
|
-
this.currentBlock = this.appendBlockForAttributesWithElement(attributes, element);
|
7075
|
+
this.currentBlock = this.appendBlockForAttributesWithElement(attributes, element, htmlAttributes);
|
7045
7076
|
this.currentBlockElement = element;
|
7046
7077
|
} else {
|
7047
7078
|
return this.appendStringWithAttributes("\n");
|
@@ -7129,8 +7160,9 @@ $\
|
|
7129
7160
|
// Document construction
|
7130
7161
|
|
7131
7162
|
appendBlockForAttributesWithElement(attributes, element) {
|
7163
|
+
let htmlAttributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
7132
7164
|
this.blockElements.push(element);
|
7133
|
-
const block = blockForAttributes(attributes);
|
7165
|
+
const block = blockForAttributes(attributes, htmlAttributes);
|
7134
7166
|
this.blocks.push(block);
|
7135
7167
|
return block;
|
7136
7168
|
}
|
@@ -7235,6 +7267,17 @@ $\
|
|
7235
7267
|
}
|
7236
7268
|
return attributes$1.reverse();
|
7237
7269
|
}
|
7270
|
+
getBlockHTMLAttributes(element) {
|
7271
|
+
const attributes$1 = {};
|
7272
|
+
const blockConfig = Object.values(attributes).find(settings => settings.tagName === tagName(element));
|
7273
|
+
const allowedAttributes = (blockConfig === null || blockConfig === void 0 ? void 0 : blockConfig.htmlAttributes) || [];
|
7274
|
+
allowedAttributes.forEach(attribute => {
|
7275
|
+
if (element.hasAttribute(attribute)) {
|
7276
|
+
attributes$1[attribute] = element.getAttribute(attribute);
|
7277
|
+
}
|
7278
|
+
});
|
7279
|
+
return attributes$1;
|
7280
|
+
}
|
7238
7281
|
findBlockElementAncestors(element) {
|
7239
7282
|
const ancestors = [];
|
7240
7283
|
while (element && element !== this.containerElement) {
|
@@ -7830,6 +7873,15 @@ $\
|
|
7830
7873
|
return this.notifyDelegateOfCurrentAttributesChange();
|
7831
7874
|
}
|
7832
7875
|
}
|
7876
|
+
setHTMLAtributeAtPosition(position, attributeName, value) {
|
7877
|
+
var _getBlockConfig;
|
7878
|
+
const block = this.document.getBlockAtPosition(position);
|
7879
|
+
const allowedHTMLAttributes = (_getBlockConfig = getBlockConfig(block.getLastAttribute())) === null || _getBlockConfig === void 0 ? void 0 : _getBlockConfig.htmlAttributes;
|
7880
|
+
if (block && allowedHTMLAttributes !== null && allowedHTMLAttributes !== void 0 && allowedHTMLAttributes.includes(attributeName)) {
|
7881
|
+
const newDocument = this.document.setHTMLAttributeAtPosition(position, attributeName, value);
|
7882
|
+
this.setDocument(newDocument);
|
7883
|
+
}
|
7884
|
+
}
|
7833
7885
|
setTextAttribute(attributeName, value) {
|
7834
7886
|
const selectedRange = this.getSelectedRange();
|
7835
7887
|
if (!selectedRange) return;
|
@@ -7877,10 +7929,10 @@ $\
|
|
7877
7929
|
return ((_this$getBlock = this.getBlock()) === null || _this$getBlock === void 0 ? void 0 : _this$getBlock.getNestingLevel()) > 0;
|
7878
7930
|
}
|
7879
7931
|
canIncreaseNestingLevel() {
|
7880
|
-
var
|
7932
|
+
var _getBlockConfig2;
|
7881
7933
|
const block = this.getBlock();
|
7882
7934
|
if (!block) return;
|
7883
|
-
if ((
|
7935
|
+
if ((_getBlockConfig2 = getBlockConfig(block.getLastNestableAttribute())) !== null && _getBlockConfig2 !== void 0 && _getBlockConfig2.listAttribute) {
|
7884
7936
|
const previousBlock = this.getPreviousBlock();
|
7885
7937
|
if (previousBlock) {
|
7886
7938
|
return arrayStartsWith(previousBlock.getListItemAttributes(), block.getListItemAttributes());
|
@@ -8521,6 +8573,11 @@ $\
|
|
8521
8573
|
return this.composition.removeCurrentAttribute(name);
|
8522
8574
|
}
|
8523
8575
|
|
8576
|
+
// HTML attributes
|
8577
|
+
setHTMLAtributeAtPosition(position, name, value) {
|
8578
|
+
this.composition.setHTMLAtributeAtPosition(position, name, value);
|
8579
|
+
}
|
8580
|
+
|
8524
8581
|
// Nesting level
|
8525
8582
|
|
8526
8583
|
canDecreaseNestingLevel() {
|
@@ -10941,8 +10998,12 @@ $\
|
|
10941
10998
|
});
|
10942
10999
|
},
|
10943
11000
|
insertReplacementText() {
|
10944
|
-
|
10945
|
-
|
11001
|
+
const replacement = this.event.dataTransfer.getData("text/plain");
|
11002
|
+
const domRange = this.event.getTargetRanges()[0];
|
11003
|
+
this.withTargetDOMRange(domRange, () => {
|
11004
|
+
this.insertString(replacement, {
|
11005
|
+
updatePosition: false
|
11006
|
+
});
|
10946
11007
|
});
|
10947
11008
|
},
|
10948
11009
|
insertText() {
|
@@ -11064,7 +11125,7 @@ $\
|
|
11064
11125
|
return this.toggleDialog(actionName);
|
11065
11126
|
} else {
|
11066
11127
|
var _this$delegate2;
|
11067
|
-
return (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 ? void 0 : _this$delegate2.toolbarDidInvokeAction(actionName);
|
11128
|
+
return (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 ? void 0 : _this$delegate2.toolbarDidInvokeAction(actionName, element);
|
11068
11129
|
}
|
11069
11130
|
}
|
11070
11131
|
didClickAttributeButton(event, element) {
|
@@ -11509,8 +11570,8 @@ $\
|
|
11509
11570
|
});
|
11510
11571
|
}
|
11511
11572
|
}
|
11512
|
-
toolbarDidInvokeAction(actionName) {
|
11513
|
-
return this.invokeAction(actionName);
|
11573
|
+
toolbarDidInvokeAction(actionName, invokingElement) {
|
11574
|
+
return this.invokeAction(actionName, invokingElement);
|
11514
11575
|
}
|
11515
11576
|
toolbarDidToggleAttribute(attributeName) {
|
11516
11577
|
this.recordFormattingUndoEntry(attributeName);
|
@@ -11579,10 +11640,11 @@ $\
|
|
11579
11640
|
return !!((_this$actions$actionN = this.actions[actionName]) !== null && _this$actions$actionN !== void 0 && (_this$actions$actionN = _this$actions$actionN.test) !== null && _this$actions$actionN !== void 0 && _this$actions$actionN.call(this));
|
11580
11641
|
}
|
11581
11642
|
}
|
11582
|
-
invokeAction(actionName) {
|
11643
|
+
invokeAction(actionName, invokingElement) {
|
11583
11644
|
if (this.actionIsExternal(actionName)) {
|
11584
11645
|
return this.notifyEditorElement("action-invoke", {
|
11585
|
-
actionName
|
11646
|
+
actionName,
|
11647
|
+
invokingElement
|
11586
11648
|
});
|
11587
11649
|
} else {
|
11588
11650
|
var _this$actions$actionN2;
|
@@ -334,7 +334,9 @@ trix-editor .attachment__metadata {
|
|
334
334
|
white-space: nowrap; }
|
335
335
|
|
336
336
|
.trix-content {
|
337
|
-
line-height: 1.5;
|
337
|
+
line-height: 1.5;
|
338
|
+
overflow-wrap: break-word;
|
339
|
+
word-break: break-word; }
|
338
340
|
.trix-content * {
|
339
341
|
box-sizing: border-box;
|
340
342
|
margin: 0;
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# :markup: markdown
|
4
|
+
|
3
5
|
require "rails-html-sanitizer"
|
4
6
|
|
5
7
|
module ActionText
|
@@ -14,6 +16,15 @@ module ActionText
|
|
14
16
|
sanitize_action_text_content(render_action_text_attachments(content))
|
15
17
|
end
|
16
18
|
|
19
|
+
def sanitize_content_attachment(content_attachment)
|
20
|
+
sanitizer.sanitize(
|
21
|
+
content_attachment,
|
22
|
+
tags: sanitizer_allowed_tags,
|
23
|
+
attributes: sanitizer_allowed_attributes,
|
24
|
+
scrubber: scrubber,
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
17
28
|
def sanitize_action_text_content(content)
|
18
29
|
sanitizer.sanitize(
|
19
30
|
content.to_html,
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# :markup: markdown
|
4
|
+
|
3
5
|
require "active_support/core_ext/object/try"
|
4
6
|
require "action_view/helpers/tags/placeholderable"
|
5
7
|
|
@@ -7,20 +9,24 @@ module ActionText
|
|
7
9
|
module TagHelper
|
8
10
|
cattr_accessor(:id, instance_accessor: false) { 0 }
|
9
11
|
|
10
|
-
# Returns a
|
11
|
-
# that Trix will write to on changes, so the content will
|
12
|
+
# Returns a `trix-editor` tag that instantiates the Trix JavaScript editor as
|
13
|
+
# well as a hidden field that Trix will write to on changes, so the content will
|
14
|
+
# be sent on form submissions.
|
15
|
+
#
|
16
|
+
# #### Options
|
17
|
+
# * `:class` - Defaults to "trix-content" so that default styles will be
|
18
|
+
# applied. Setting this to a different value will prevent default styles
|
19
|
+
# from being applied.
|
20
|
+
# * `[:data][:direct_upload_url]` - Defaults to `rails_direct_uploads_url`.
|
21
|
+
# * `[:data][:blob_url_template]` - Defaults to
|
22
|
+
# `rails_service_blob_url(":signed_id", ":filename")`.
|
12
23
|
#
|
13
|
-
# ==== Options
|
14
|
-
# * <tt>:class</tt> - Defaults to "trix-content" so that default styles will be applied.
|
15
|
-
# Setting this to a different value will prevent default styles from being applied.
|
16
|
-
# * <tt>[:data][:direct_upload_url]</tt> - Defaults to +rails_direct_uploads_url+.
|
17
|
-
# * <tt>[:data][:blob_url_template]</tt> - Defaults to <tt>rails_service_blob_url(":signed_id", ":filename")</tt>.
|
18
24
|
#
|
19
|
-
#
|
25
|
+
# #### Example
|
20
26
|
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
27
|
+
# rich_text_area_tag "content", message.content
|
28
|
+
# # <input type="hidden" name="content" id="trix_input_post_1">
|
29
|
+
# # <trix-editor id="content" input="trix_input_post_1" class="trix-content" ...></trix-editor>
|
24
30
|
def rich_text_area_tag(name, value = nil, options = {})
|
25
31
|
options = options.symbolize_keys
|
26
32
|
form = options.delete(:form)
|
@@ -56,23 +62,27 @@ module ActionView::Helpers
|
|
56
62
|
end
|
57
63
|
|
58
64
|
module FormHelper
|
59
|
-
# Returns a
|
60
|
-
# that Trix will write to on changes, so the content will
|
65
|
+
# Returns a `trix-editor` tag that instantiates the Trix JavaScript editor as
|
66
|
+
# well as a hidden field that Trix will write to on changes, so the content will
|
67
|
+
# be sent on form submissions.
|
68
|
+
#
|
69
|
+
# #### Options
|
70
|
+
# * `:class` - Defaults to "trix-content" which ensures default styling is
|
71
|
+
# applied.
|
72
|
+
# * `:value` - Adds a default value to the HTML input tag.
|
73
|
+
# * `[:data][:direct_upload_url]` - Defaults to `rails_direct_uploads_url`.
|
74
|
+
# * `[:data][:blob_url_template]` - Defaults to
|
75
|
+
# `rails_service_blob_url(":signed_id", ":filename")`.
|
61
76
|
#
|
62
|
-
# ==== Options
|
63
|
-
# * <tt>:class</tt> - Defaults to "trix-content" which ensures default styling is applied.
|
64
|
-
# * <tt>:value</tt> - Adds a default value to the HTML input tag.
|
65
|
-
# * <tt>[:data][:direct_upload_url]</tt> - Defaults to +rails_direct_uploads_url+.
|
66
|
-
# * <tt>[:data][:blob_url_template]</tt> - Defaults to <tt>rails_service_blob_url(":signed_id", ":filename")</tt>.
|
67
77
|
#
|
68
|
-
#
|
69
|
-
#
|
70
|
-
#
|
71
|
-
#
|
78
|
+
# #### Example
|
79
|
+
# rich_text_area :message, :content
|
80
|
+
# # <input type="hidden" name="message[content]" id="message_content_trix_input_message_1">
|
81
|
+
# # <trix-editor id="content" input="message_content_trix_input_message_1" class="trix-content" ...></trix-editor>
|
72
82
|
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
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>">
|
85
|
+
# # <trix-editor id="content" input="message_content_trix_input_message_1" class="trix-content" ...></trix-editor>
|
76
86
|
def rich_text_area(object_name, method, options = {})
|
77
87
|
Tags::ActionText.new(object_name, method, self, options).render
|
78
88
|
end
|
@@ -81,9 +91,9 @@ module ActionView::Helpers
|
|
81
91
|
class FormBuilder
|
82
92
|
# Wraps ActionView::Helpers::FormHelper#rich_text_area for form builders:
|
83
93
|
#
|
84
|
-
#
|
85
|
-
#
|
86
|
-
#
|
94
|
+
# <%= form_with model: @message do |f| %>
|
95
|
+
# <%= f.rich_text_area :content %>
|
96
|
+
# <% end %>
|
87
97
|
#
|
88
98
|
# Please refer to the documentation of the base helper for details.
|
89
99
|
def rich_text_area(method, options = {})
|