actiontext 7.1.3.2 → 7.2.0.beta1

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

Potentially problematic release.


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

Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -88
  3. data/app/assets/javascripts/actiontext.esm.js +3 -3
  4. data/app/assets/javascripts/actiontext.js +3 -3
  5. data/app/assets/javascripts/trix.js +92 -30
  6. data/app/assets/stylesheets/trix.css +3 -1
  7. data/app/helpers/action_text/content_helper.rb +2 -0
  8. data/app/helpers/action_text/tag_helper.rb +38 -28
  9. data/app/models/action_text/encrypted_rich_text.rb +2 -2
  10. data/app/models/action_text/record.rb +2 -0
  11. data/app/models/action_text/rich_text.rb +58 -26
  12. data/db/migrate/20180528164100_create_action_text_tables.rb +1 -1
  13. data/lib/action_text/attachable.rb +35 -33
  14. data/lib/action_text/attachables/content_attachment.rb +2 -0
  15. data/lib/action_text/attachables/missing_attachable.rb +2 -0
  16. data/lib/action_text/attachables/remote_image.rb +2 -0
  17. data/lib/action_text/attachment.rb +27 -25
  18. data/lib/action_text/attachment_gallery.rb +2 -0
  19. data/lib/action_text/attachments/caching.rb +2 -0
  20. data/lib/action_text/attachments/minification.rb +2 -0
  21. data/lib/action_text/attachments/trix_conversion.rb +2 -0
  22. data/lib/action_text/attribute.rb +36 -22
  23. data/lib/action_text/content.rb +46 -26
  24. data/lib/action_text/deprecator.rb +2 -0
  25. data/lib/action_text/encryption.rb +2 -0
  26. data/lib/action_text/engine.rb +2 -0
  27. data/lib/action_text/fixture_set.rb +34 -34
  28. data/lib/action_text/fragment.rb +4 -0
  29. data/lib/action_text/gem_version.rb +6 -4
  30. data/lib/action_text/html_conversion.rb +2 -0
  31. data/lib/action_text/plain_text_conversion.rb +2 -0
  32. data/lib/action_text/rendering.rb +2 -0
  33. data/lib/action_text/serialization.rb +2 -0
  34. data/lib/action_text/system_test_helper.rb +20 -17
  35. data/lib/action_text/trix_attachment.rb +2 -0
  36. data/lib/action_text/version.rb +3 -1
  37. data/lib/action_text.rb +1 -1
  38. data/lib/generators/action_text/install/install_generator.rb +10 -3
  39. data/lib/rails/generators/test_unit/install_generator.rb +2 -0
  40. data/package.json +1 -1
  41. metadata +15 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ce8b2b2628c11a9dd67e83a7ba948df06d10e616756d6ce8e509c96b356e060c
4
- data.tar.gz: 1ac97fa71f50ac3e568f81a5c57f05a3d81387a47233104e7a16ea823830a296
3
+ metadata.gz: d497d50205633b66005bfcfe850ee8d5404c0b3b9f953a14356bb912c8b3b4d5
4
+ data.tar.gz: '099e3d4dca02f13983f06b8ffcf6c49a1bb2f3cb66ae94e8534c0764f8b56700'
5
5
  SHA512:
6
- metadata.gz: 919197c2541430986c06da4c8d5fd069d6007092e73ed051af06452ceda46a4e807d6a877fb4e4338d2c9fc42fada5881e5a45317e8dba69a381e2e538718269
7
- data.tar.gz: 2012b4fc3f3fd5f725e1ffecdb050be22555ac3a67136bc0a10dabe5f41559784d69983085041a6fb2a71cbdd82bfd45d5e29b64cd821df55eb3a676d31c17ac
6
+ metadata.gz: e9acfe56af6ec22cf0448fc42c7dc3cba769bbbce316efa926869ac083db8491a547366ae5beede3da8a02b75c1cbb6f7a8e252c0519fbd7c282af841835a644
7
+ data.tar.gz: 9beaaede36bf8158e2fee2e6d5f2fb02dbaabeb86a279ee7ca0e9ef87b5cc710d3ea454ae3e8723235eb8b2d2bc2586e540f89623c2609fd3620207e2785c042
data/CHANGELOG.md CHANGED
@@ -1,21 +1,32 @@
1
- ## Rails 7.1.3.2 (February 21, 2024) ##
1
+ ## Rails 7.2.0.beta1 (May 29, 2024) ##
2
2
 
3
- * No changes.
3
+ * Use `includes` instead of `eager_load` for `with_all_rich_text`.
4
4
 
5
+ *Petrik de Heus*
5
6
 
6
- ## Rails 7.1.3.1 (February 21, 2024) ##
7
+ * Delegate `ActionText::Content#deconstruct` to `Nokogiri::XML::DocumentFragment#elements`.
7
8
 
8
- * No changes.
9
+ ```ruby
10
+ content = ActionText::Content.new <<~HTML
11
+ <h1>Hello, world</h1>
9
12
 
13
+ <div>The body</div>
14
+ HTML
10
15
 
11
- ## Rails 7.1.3 (January 16, 2024) ##
16
+ content => [h1, div]
12
17
 
13
- * No changes.
18
+ assert_pattern { h1 => { content: "Hello, world" } }
19
+ assert_pattern { div => { content: "The body" } }
20
+ ```
14
21
 
22
+ *Sean Doyle*
23
+
24
+ * Fix all Action Text database related models to respect
25
+ `ActiveRecord::Base.table_name_prefix` configuration.
15
26
 
16
- ## Rails 7.1.2 (November 10, 2023) ##
27
+ *Chedli Bourguiba*
17
28
 
18
- * Compile ESM package that can be used directly in the browser as `actiontext.esm.js`.
29
+ * Compile ESM package that can be used directly in the browser as actiontext.esm.js
19
30
 
20
31
  *Matias Grunberg*
21
32
 
@@ -23,7 +34,7 @@
23
34
 
24
35
  *Matias Grunberg*
25
36
 
26
- * Upgrade Trix to 2.0.7.
37
+ * Upgrade Trix to 2.0.7
27
38
 
28
39
  *Hartley McGuire*
29
40
 
@@ -31,82 +42,4 @@
31
42
 
32
43
  *Hartley McGuire*
33
44
 
34
-
35
- ## Rails 7.1.1 (October 11, 2023) ##
36
-
37
- * No changes.
38
-
39
-
40
- ## Rails 7.1.0 (October 05, 2023) ##
41
-
42
- * No changes.
43
-
44
-
45
- ## Rails 7.1.0.rc2 (October 01, 2023) ##
46
-
47
- * No changes.
48
-
49
-
50
- ## Rails 7.1.0.rc1 (September 27, 2023) ##
51
-
52
- * No changes.
53
-
54
-
55
- ## Rails 7.1.0.beta1 (September 13, 2023) ##
56
-
57
- * Use `Rails::HTML5::SafeListSanitizer` by default in the Rails 7.1 configuration if it is
58
- supported.
59
-
60
- Action Text's sanitizer can be configured by setting
61
- `config.action_text.sanitizer_vendor`. Supported values are `Rails::HTML4::Sanitizer` or
62
- `Rails::HTML5::Sanitizer`.
63
-
64
- The Rails 7.1 configuration will set this to `Rails::HTML5::Sanitizer` when it is supported, and
65
- fall back to `Rails::HTML4::Sanitizer`. Previous configurations default to
66
- `Rails::HTML4::Sanitizer`.
67
-
68
- As a result of this change, the defaults for `ActionText::ContentHelper.allowed_tags` and
69
- `.allowed_attributes` are applied at runtime, so the value of these attributes is now 'nil'
70
- unless set by the application. You may call `sanitizer_allowed_tags` or
71
- `sanitizer_allowed_attributes` to inspect the tags and attributes being allowed by the
72
- sanitizer.
73
-
74
- *Mike Dalessio*
75
-
76
- * Attachables now can override default attachment missing template.
77
-
78
- When rendering Action Text attachments where the underlying attachable model has
79
- been removed, a fallback template is used. You now can override this template on
80
- a per-model basis. For example, you could render a placeholder image for a file
81
- attachment or the text "Deleted User" for a User attachment.
82
-
83
- *Matt Swanson*, *Joel Drapper*
84
-
85
- * Update bundled Trix version from `1.3.1` to `2.0.4`.
86
-
87
- *Sarah Ridge*, *Sean Doyle*
88
-
89
- * Apply `field_error_proc` to `rich_text_area` form fields.
90
-
91
- *Kaíque Kandy Koga*
92
-
93
- * Action Text attachment URLs rendered in a background job (a la Turbo
94
- Streams) now use `Rails.application.default_url_options` and
95
- `Rails.application.config.force_ssl` instead of `http://example.org`.
96
-
97
- *Jonathan Hefner*
98
-
99
- * Support `strict_loading:` option for `has_rich_text` declaration
100
-
101
- *Sean Doyle*
102
-
103
- * Update ContentAttachment so that it can encapsulate arbitrary HTML content in a document.
104
-
105
- *Jamis Buck*
106
-
107
- * Fix an issue that caused the content layout to render multiple times when a
108
- rich_text field was updated.
109
-
110
- *Jacob Herrington*
111
-
112
- Please check [7-0-stable](https://github.com/rails/rails/blob/7-0-stable/actiontext/CHANGELOG.md) for previous changes.
45
+ Please check [7-1-stable](https://github.com/rails/rails/blob/7-1-stable/actiontext/CHANGELOG.md) for previous changes.
@@ -771,9 +771,9 @@ function start() {
771
771
  }
772
772
 
773
773
  function didClick(event) {
774
- const button = event.target.closest("button, input");
775
- if (button && button.type === "submit" && button.form) {
776
- submitButtonsByForm.set(button.form, button);
774
+ const {target: target} = event;
775
+ if ((target.tagName == "INPUT" || target.tagName == "BUTTON") && target.type == "submit" && target.form) {
776
+ submitButtonsByForm.set(target.form, target);
777
777
  }
778
778
  }
779
779
 
@@ -753,9 +753,9 @@
753
753
  }
754
754
  }
755
755
  function didClick(event) {
756
- const button = event.target.closest("button, input");
757
- if (button && button.type === "submit" && button.form) {
758
- submitButtonsByForm.set(button.form, button);
756
+ const {target: target} = event;
757
+ if ((target.tagName == "INPUT" || target.tagName == "BUTTON") && target.type == "submit" && target.form) {
758
+ submitButtonsByForm.set(target.form, target);
759
759
  }
760
760
  }
761
761
  function didSubmitForm(event) {
@@ -1,6 +1,6 @@
1
1
  /*
2
- Trix 2.0.7
3
- Copyright © 2023 37signals, LLC
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.0.7";
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/g, "\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
- let attributes, className;
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
- return JSON.parse(element.getAttribute("data-trix-".concat(name)));
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 _getBlockConfig;
7932
+ var _getBlockConfig2;
7881
7933
  const block = this.getBlock();
7882
7934
  if (!block) return;
7883
- if ((_getBlockConfig = getBlockConfig(block.getLastNestableAttribute())) !== null && _getBlockConfig !== void 0 && _getBlockConfig.listAttribute) {
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
- return this.insertString(this.event.dataTransfer.getData("text/plain"), {
10945
- updatePosition: false
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
@@ -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 +trix-editor+ tag that instantiates the Trix JavaScript editor as well as a hidden field
11
- # that Trix will write to on changes, so the content will be sent on form submissions.
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
- # ==== Example
25
+ # #### Example
20
26
  #
21
- # rich_text_area_tag "content", message.content
22
- # # <input type="hidden" name="content" id="trix_input_post_1">
23
- # # <trix-editor id="content" input="trix_input_post_1" class="trix-content" ...></trix-editor>
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 +trix-editor+ tag that instantiates the Trix JavaScript editor as well as a hidden field
60
- # that Trix will write to on changes, so the content will be sent on form submissions.
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
- # ==== Example
69
- # rich_text_area :message, :content
70
- # # <input type="hidden" name="message[content]" id="message_content_trix_input_message_1">
71
- # # <trix-editor id="content" input="message_content_trix_input_message_1" class="trix-content" ...></trix-editor>
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
- # rich_text_area :message, :content, value: "<h1>Default message</h1>"
74
- # # <input type="hidden" name="message[content]" id="message_content_trix_input_message_1" value="<h1>Default message</h1>">
75
- # # <trix-editor id="content" input="message_content_trix_input_message_1" class="trix-content" ...></trix-editor>
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
- # <%= form_with model: @message do |f| %>
85
- # <%= f.rich_text_area :content %>
86
- # <% end %>
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 = {})
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionText
4
6
  class EncryptedRichText < RichText
5
- self.table_name = "action_text_rich_texts"
6
-
7
7
  encrypts :body
8
8
  end
9
9
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionText
4
6
  class Record < ActiveRecord::Base # :nodoc:
5
7
  self.abstract_class = true