actiontext 8.0.0.beta1 → 8.0.0.rc2

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: 47681928e4eb5de7fb4d7958ec7071174c8671e9750049693f8bc6a4742d90be
4
- data.tar.gz: 162c998b362b84e68c0a404014c227a04925c3554de18ad66563dd3b00759040
3
+ metadata.gz: 0fb1c41942d8f04edd36197c2a38e64c7c38a45fab448e19c2dd988269a2944a
4
+ data.tar.gz: c158dc686084f3d979d0c75dfe006a37bb676c1d8a560ee90080f48fe2fb8384
5
5
  SHA512:
6
- metadata.gz: 13900860666132a1931d50ce22c8cb65f5a39f09a65f7fcc893aece5c55b292d7c7c63735450da6181d3736944e1ce4610cb2407a24e6740991ddf0c30f2a3fe
7
- data.tar.gz: 02ed293526d7691e072e5f8711e8fd69dabcf6c7aaa3dcaf01d07c29d09d43629acf60f6aa65d22a67727a1f5622ef4c3cfbc8bc69108cd8240fcbb1c960d9d8
6
+ metadata.gz: f12951a6b0fb650048fe5a82ef70a58710291fc135c6bf30014ac968d014e26fd2a2f5ddcfd852c6b6c3c7ee51a24eb5c18004c9f5eb0153c54be5cd0b0f08e8
7
+ data.tar.gz: 0f2d467666f82845e31463973756e87b6959b39dace55e44552dd1aafa9b75eaec265a86d1b37566a6685631d58ee3823221897cdb4f4d4eb64625acafea4052
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## Rails 8.0.0.rc2 (October 30, 2024) ##
2
+
3
+ * No changes.
4
+
5
+
6
+ ## Rails 8.0.0.rc1 (October 19, 2024) ##
7
+
8
+ * No changes.
9
+
10
+
1
11
  ## Rails 8.0.0.beta1 (September 26, 2024) ##
2
12
 
3
13
  * Dispatch direct-upload events on attachment uploads
@@ -1,5 +1,5 @@
1
1
  /*
2
- Trix 2.1.1
2
+ Trix 2.1.7
3
3
  Copyright © 2024 37signals, LLC
4
4
  */
5
5
  (function (global, factory) {
@@ -9,7 +9,7 @@ Copyright © 2024 37signals, LLC
9
9
  })(this, (function () { 'use strict';
10
10
 
11
11
  var name = "trix";
12
- var version = "2.1.1";
12
+ var version = "2.1.7";
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";
@@ -1037,7 +1037,11 @@ $\
1037
1037
  const getCSPNonce = function () {
1038
1038
  const element = getMetaElement("trix-csp-nonce") || getMetaElement("csp-nonce");
1039
1039
  if (element) {
1040
- return element.getAttribute("content");
1040
+ const {
1041
+ nonce,
1042
+ content
1043
+ } = element;
1044
+ return nonce == "" ? content : nonce;
1041
1045
  }
1042
1046
  };
1043
1047
  const getMetaElement = name => document.head.querySelector("meta[name=".concat(name, "]"));
@@ -1059,6 +1063,12 @@ $\
1059
1063
  return text === null || text === void 0 ? void 0 : text.length;
1060
1064
  }
1061
1065
  };
1066
+ const dataTransferIsMsOfficePaste = _ref => {
1067
+ let {
1068
+ dataTransfer
1069
+ } = _ref;
1070
+ return dataTransfer.types.includes("Files") && dataTransfer.types.includes("text/html") && dataTransfer.getData("text/html").includes("urn:schemas-microsoft-com:office:office");
1071
+ };
1062
1072
  const dataTransferIsWritable = function (dataTransfer) {
1063
1073
  if (!(dataTransfer !== null && dataTransfer !== void 0 && dataTransfer.setData)) return false;
1064
1074
  for (const key in testTransferData) {
@@ -1707,6 +1717,116 @@ $\
1707
1717
  }
1708
1718
  }
1709
1719
 
1720
+ const DEFAULT_ALLOWED_ATTRIBUTES = "style href src width height language class".split(" ");
1721
+ const DEFAULT_FORBIDDEN_PROTOCOLS = "javascript:".split(" ");
1722
+ const DEFAULT_FORBIDDEN_ELEMENTS = "script iframe form noscript".split(" ");
1723
+ class HTMLSanitizer extends BasicObject {
1724
+ static setHTML(element, html) {
1725
+ const sanitizedElement = new this(html).sanitize();
1726
+ const sanitizedHtml = sanitizedElement.getHTML ? sanitizedElement.getHTML() : sanitizedElement.outerHTML;
1727
+ element.innerHTML = sanitizedHtml;
1728
+ }
1729
+ static sanitize(html, options) {
1730
+ const sanitizer = new this(html, options);
1731
+ sanitizer.sanitize();
1732
+ return sanitizer;
1733
+ }
1734
+ constructor(html) {
1735
+ let {
1736
+ allowedAttributes,
1737
+ forbiddenProtocols,
1738
+ forbiddenElements
1739
+ } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1740
+ super(...arguments);
1741
+ this.allowedAttributes = allowedAttributes || DEFAULT_ALLOWED_ATTRIBUTES;
1742
+ this.forbiddenProtocols = forbiddenProtocols || DEFAULT_FORBIDDEN_PROTOCOLS;
1743
+ this.forbiddenElements = forbiddenElements || DEFAULT_FORBIDDEN_ELEMENTS;
1744
+ this.body = createBodyElementForHTML(html);
1745
+ }
1746
+ sanitize() {
1747
+ this.sanitizeElements();
1748
+ return this.normalizeListElementNesting();
1749
+ }
1750
+ getHTML() {
1751
+ return this.body.innerHTML;
1752
+ }
1753
+ getBody() {
1754
+ return this.body;
1755
+ }
1756
+
1757
+ // Private
1758
+
1759
+ sanitizeElements() {
1760
+ const walker = walkTree(this.body);
1761
+ const nodesToRemove = [];
1762
+ while (walker.nextNode()) {
1763
+ const node = walker.currentNode;
1764
+ switch (node.nodeType) {
1765
+ case Node.ELEMENT_NODE:
1766
+ if (this.elementIsRemovable(node)) {
1767
+ nodesToRemove.push(node);
1768
+ } else {
1769
+ this.sanitizeElement(node);
1770
+ }
1771
+ break;
1772
+ case Node.COMMENT_NODE:
1773
+ nodesToRemove.push(node);
1774
+ break;
1775
+ }
1776
+ }
1777
+ nodesToRemove.forEach(node => removeNode(node));
1778
+ return this.body;
1779
+ }
1780
+ sanitizeElement(element) {
1781
+ if (element.hasAttribute("href")) {
1782
+ if (this.forbiddenProtocols.includes(element.protocol)) {
1783
+ element.removeAttribute("href");
1784
+ }
1785
+ }
1786
+ Array.from(element.attributes).forEach(_ref => {
1787
+ let {
1788
+ name
1789
+ } = _ref;
1790
+ if (!this.allowedAttributes.includes(name) && name.indexOf("data-trix") !== 0) {
1791
+ element.removeAttribute(name);
1792
+ }
1793
+ });
1794
+ return element;
1795
+ }
1796
+ normalizeListElementNesting() {
1797
+ Array.from(this.body.querySelectorAll("ul,ol")).forEach(listElement => {
1798
+ const previousElement = listElement.previousElementSibling;
1799
+ if (previousElement) {
1800
+ if (tagName(previousElement) === "li") {
1801
+ previousElement.appendChild(listElement);
1802
+ }
1803
+ }
1804
+ });
1805
+ return this.body;
1806
+ }
1807
+ elementIsRemovable(element) {
1808
+ if ((element === null || element === void 0 ? void 0 : element.nodeType) !== Node.ELEMENT_NODE) return;
1809
+ return this.elementIsForbidden(element) || this.elementIsntSerializable(element);
1810
+ }
1811
+ elementIsForbidden(element) {
1812
+ return this.forbiddenElements.includes(tagName(element));
1813
+ }
1814
+ elementIsntSerializable(element) {
1815
+ return element.getAttribute("data-trix-serialize") === "false" && !nodeIsAttachmentElement(element);
1816
+ }
1817
+ }
1818
+ const createBodyElementForHTML = function () {
1819
+ let html = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "";
1820
+ // Remove everything after </html>
1821
+ html = html.replace(/<\/html[^>]*>[^]*$/i, "</html>");
1822
+ const doc = document.implementation.createHTMLDocument("");
1823
+ doc.documentElement.innerHTML = html;
1824
+ Array.from(doc.head.querySelectorAll("style")).forEach(element => {
1825
+ doc.body.appendChild(element);
1826
+ });
1827
+ return doc.body;
1828
+ };
1829
+
1710
1830
  const {
1711
1831
  css: css$2
1712
1832
  } = config;
@@ -1741,7 +1861,7 @@ $\
1741
1861
  figure.appendChild(innerElement);
1742
1862
  }
1743
1863
  if (this.attachment.hasContent()) {
1744
- innerElement.innerHTML = this.attachment.getContent();
1864
+ HTMLSanitizer.setHTML(innerElement, this.attachment.getContent());
1745
1865
  } else {
1746
1866
  this.createContentNodes().forEach(node => {
1747
1867
  innerElement.appendChild(node);
@@ -1869,7 +1989,7 @@ $\
1869
1989
  });
1870
1990
  const htmlContainsTagName = function (html, tagName) {
1871
1991
  const div = makeElement("div");
1872
- div.innerHTML = html || "";
1992
+ HTMLSanitizer.setHTML(div, html || "");
1873
1993
  return div.querySelector(tagName);
1874
1994
  };
1875
1995
 
@@ -6816,111 +6936,6 @@ $\
6816
6936
  return attributes;
6817
6937
  };
6818
6938
 
6819
- const DEFAULT_ALLOWED_ATTRIBUTES = "style href src width height language class".split(" ");
6820
- const DEFAULT_FORBIDDEN_PROTOCOLS = "javascript:".split(" ");
6821
- const DEFAULT_FORBIDDEN_ELEMENTS = "script iframe form noscript".split(" ");
6822
- class HTMLSanitizer extends BasicObject {
6823
- static sanitize(html, options) {
6824
- const sanitizer = new this(html, options);
6825
- sanitizer.sanitize();
6826
- return sanitizer;
6827
- }
6828
- constructor(html) {
6829
- let {
6830
- allowedAttributes,
6831
- forbiddenProtocols,
6832
- forbiddenElements
6833
- } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
6834
- super(...arguments);
6835
- this.allowedAttributes = allowedAttributes || DEFAULT_ALLOWED_ATTRIBUTES;
6836
- this.forbiddenProtocols = forbiddenProtocols || DEFAULT_FORBIDDEN_PROTOCOLS;
6837
- this.forbiddenElements = forbiddenElements || DEFAULT_FORBIDDEN_ELEMENTS;
6838
- this.body = createBodyElementForHTML(html);
6839
- }
6840
- sanitize() {
6841
- this.sanitizeElements();
6842
- return this.normalizeListElementNesting();
6843
- }
6844
- getHTML() {
6845
- return this.body.innerHTML;
6846
- }
6847
- getBody() {
6848
- return this.body;
6849
- }
6850
-
6851
- // Private
6852
-
6853
- sanitizeElements() {
6854
- const walker = walkTree(this.body);
6855
- const nodesToRemove = [];
6856
- while (walker.nextNode()) {
6857
- const node = walker.currentNode;
6858
- switch (node.nodeType) {
6859
- case Node.ELEMENT_NODE:
6860
- if (this.elementIsRemovable(node)) {
6861
- nodesToRemove.push(node);
6862
- } else {
6863
- this.sanitizeElement(node);
6864
- }
6865
- break;
6866
- case Node.COMMENT_NODE:
6867
- nodesToRemove.push(node);
6868
- break;
6869
- }
6870
- }
6871
- nodesToRemove.forEach(node => removeNode(node));
6872
- return this.body;
6873
- }
6874
- sanitizeElement(element) {
6875
- if (element.hasAttribute("href")) {
6876
- if (this.forbiddenProtocols.includes(element.protocol)) {
6877
- element.removeAttribute("href");
6878
- }
6879
- }
6880
- Array.from(element.attributes).forEach(_ref => {
6881
- let {
6882
- name
6883
- } = _ref;
6884
- if (!this.allowedAttributes.includes(name) && name.indexOf("data-trix") !== 0) {
6885
- element.removeAttribute(name);
6886
- }
6887
- });
6888
- return element;
6889
- }
6890
- normalizeListElementNesting() {
6891
- Array.from(this.body.querySelectorAll("ul,ol")).forEach(listElement => {
6892
- const previousElement = listElement.previousElementSibling;
6893
- if (previousElement) {
6894
- if (tagName(previousElement) === "li") {
6895
- previousElement.appendChild(listElement);
6896
- }
6897
- }
6898
- });
6899
- return this.body;
6900
- }
6901
- elementIsRemovable(element) {
6902
- if ((element === null || element === void 0 ? void 0 : element.nodeType) !== Node.ELEMENT_NODE) return;
6903
- return this.elementIsForbidden(element) || this.elementIsntSerializable(element);
6904
- }
6905
- elementIsForbidden(element) {
6906
- return this.forbiddenElements.includes(tagName(element));
6907
- }
6908
- elementIsntSerializable(element) {
6909
- return element.getAttribute("data-trix-serialize") === "false" && !nodeIsAttachmentElement(element);
6910
- }
6911
- }
6912
- const createBodyElementForHTML = function () {
6913
- let html = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "";
6914
- // Remove everything after </html>
6915
- html = html.replace(/<\/html[^>]*>[^]*$/i, "</html>");
6916
- const doc = document.implementation.createHTMLDocument("");
6917
- doc.documentElement.innerHTML = html;
6918
- Array.from(doc.head.querySelectorAll("style")).forEach(element => {
6919
- doc.body.appendChild(element);
6920
- });
6921
- return doc.body;
6922
- };
6923
-
6924
6939
  /* eslint-disable
6925
6940
  no-case-declarations,
6926
6941
  no-irregular-whitespace,
@@ -6956,11 +6971,7 @@ $\
6956
6971
  };
6957
6972
  const parseTrixDataAttribute = (element, name) => {
6958
6973
  try {
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;
6974
+ return JSON.parse(element.getAttribute("data-trix-".concat(name)));
6964
6975
  } catch (error) {
6965
6976
  return {};
6966
6977
  }
@@ -7003,8 +7014,7 @@ $\
7003
7014
  parse() {
7004
7015
  try {
7005
7016
  this.createHiddenContainer();
7006
- const html = HTMLSanitizer.sanitize(this.html).getHTML();
7007
- this.containerElement.innerHTML = html;
7017
+ HTMLSanitizer.setHTML(this.containerElement, this.html);
7008
7018
  const walker = walkTree(this.containerElement, {
7009
7019
  usingFilter: nodeFilter
7010
7020
  });
@@ -10527,7 +10537,7 @@ $\
10527
10537
  return (_this$responder4 = this.responder) === null || _this$responder4 === void 0 ? void 0 : _this$responder4.deleteInDirection(direction);
10528
10538
  };
10529
10539
  const domRange = this.getTargetDOMRange({
10530
- minLength: 2
10540
+ minLength: this.composing ? 1 : 2
10531
10541
  });
10532
10542
  if (domRange) {
10533
10543
  return this.withTargetDOMRange(domRange, perform);
@@ -10641,6 +10651,11 @@ $\
10641
10651
  },
10642
10652
  beforeinput(event) {
10643
10653
  const handler = this.constructor.inputTypes[event.inputType];
10654
+
10655
+ // Handles bug with Siri dictation on iOS 18+.
10656
+ if (!event.inputType) {
10657
+ this.render();
10658
+ }
10644
10659
  if (handler) {
10645
10660
  this.withEvent(event, handler);
10646
10661
  this.scheduleRender();
@@ -10905,7 +10920,6 @@ $\
10905
10920
  }
10906
10921
  },
10907
10922
  insertFromPaste() {
10908
- var _dataTransfer$files;
10909
10923
  const {
10910
10924
  dataTransfer
10911
10925
  } = this.event;
@@ -10948,28 +10962,28 @@ $\
10948
10962
  var _this$delegate21;
10949
10963
  return (_this$delegate21 = this.delegate) === null || _this$delegate21 === void 0 ? void 0 : _this$delegate21.inputControllerDidPaste(paste);
10950
10964
  };
10951
- } else if (html) {
10965
+ } else if (processableFilePaste(this.event)) {
10952
10966
  var _this$delegate22;
10953
- this.event.preventDefault();
10954
- paste.type = "text/html";
10955
- paste.html = html;
10967
+ paste.type = "File";
10968
+ paste.file = dataTransfer.files[0];
10956
10969
  (_this$delegate22 = this.delegate) === null || _this$delegate22 === void 0 || _this$delegate22.inputControllerWillPaste(paste);
10957
10970
  this.withTargetDOMRange(function () {
10958
10971
  var _this$responder34;
10959
- return (_this$responder34 = this.responder) === null || _this$responder34 === void 0 ? void 0 : _this$responder34.insertHTML(paste.html);
10972
+ return (_this$responder34 = this.responder) === null || _this$responder34 === void 0 ? void 0 : _this$responder34.insertFile(paste.file);
10960
10973
  });
10961
10974
  this.afterRender = () => {
10962
10975
  var _this$delegate23;
10963
10976
  return (_this$delegate23 = this.delegate) === null || _this$delegate23 === void 0 ? void 0 : _this$delegate23.inputControllerDidPaste(paste);
10964
10977
  };
10965
- } else if ((_dataTransfer$files = dataTransfer.files) !== null && _dataTransfer$files !== void 0 && _dataTransfer$files.length) {
10978
+ } else if (html) {
10966
10979
  var _this$delegate24;
10967
- paste.type = "File";
10968
- paste.file = dataTransfer.files[0];
10980
+ this.event.preventDefault();
10981
+ paste.type = "text/html";
10982
+ paste.html = html;
10969
10983
  (_this$delegate24 = this.delegate) === null || _this$delegate24 === void 0 || _this$delegate24.inputControllerWillPaste(paste);
10970
10984
  this.withTargetDOMRange(function () {
10971
10985
  var _this$responder35;
10972
- return (_this$responder35 = this.responder) === null || _this$responder35 === void 0 ? void 0 : _this$responder35.insertFile(paste.file);
10986
+ return (_this$responder35 = this.responder) === null || _this$responder35 === void 0 ? void 0 : _this$responder35.insertHTML(paste.html);
10973
10987
  });
10974
10988
  this.afterRender = () => {
10975
10989
  var _this$delegate25;
@@ -11030,10 +11044,20 @@ $\
11030
11044
  var _event$dataTransfer;
11031
11045
  return Array.from(((_event$dataTransfer = event.dataTransfer) === null || _event$dataTransfer === void 0 ? void 0 : _event$dataTransfer.types) || []).includes("Files");
11032
11046
  };
11047
+ const processableFilePaste = event => {
11048
+ var _event$dataTransfer$f;
11049
+ // Paste events that only have files are handled by the paste event handler,
11050
+ // to work around Safari not supporting beforeinput.insertFromPaste for files.
11051
+
11052
+ // MS Office text pastes include a file with a screenshot of the text, but we should
11053
+ // handle them as text pastes.
11054
+ return ((_event$dataTransfer$f = event.dataTransfer.files) === null || _event$dataTransfer$f === void 0 ? void 0 : _event$dataTransfer$f[0]) && !pasteEventHasFilesOnly(event) && !dataTransferIsMsOfficePaste(event);
11055
+ };
11033
11056
  const pasteEventHasFilesOnly = function (event) {
11034
11057
  const clipboard = event.clipboardData;
11035
11058
  if (clipboard) {
11036
- return clipboard.types.includes("Files") && clipboard.types.length === 1 && clipboard.files.length >= 1;
11059
+ const fileTypes = Array.from(clipboard.types).filter(type => type.match(/file/i)); // "Files", "application/x-moz-file"
11060
+ return fileTypes.length === clipboard.types.length && clipboard.files.length >= 1;
11037
11061
  }
11038
11062
  };
11039
11063
  const pasteEventHasPlainTextOnly = function (event) {
@@ -11699,7 +11723,7 @@ $\
11699
11723
  updateInputElement() {
11700
11724
  const element = this.compositionController.getSerializableElement();
11701
11725
  const value = serializeToContentType(element, "text/html");
11702
- return this.editorElement.setInputElementValue(value);
11726
+ return this.editorElement.setFormValue(value);
11703
11727
  }
11704
11728
  notifyEditorElement(message, data) {
11705
11729
  switch (message) {
@@ -11956,8 +11980,187 @@ $\
11956
11980
  };
11957
11981
  }
11958
11982
  }();
11959
- installDefaultCSSForTagName("trix-editor", "%t {\n display: block;\n}\n\n%t:empty:not(:focus)::before {\n content: attr(placeholder);\n color: graytext;\n cursor: text;\n pointer-events: none;\n white-space: pre-line;\n}\n\n%t a[contenteditable=false] {\n cursor: text;\n}\n\n%t img {\n max-width: 100%;\n height: auto;\n}\n\n%t ".concat(attachmentSelector, " figcaption textarea {\n resize: none;\n}\n\n%t ").concat(attachmentSelector, " figcaption textarea.trix-autoresize-clone {\n position: absolute;\n left: -9999px;\n max-height: 0px;\n}\n\n%t ").concat(attachmentSelector, " figcaption[data-trix-placeholder]:empty::before {\n content: attr(data-trix-placeholder);\n color: graytext;\n}\n\n%t [data-trix-cursor-target] {\n display: ").concat(cursorTargetStyles.display, " !important;\n width: ").concat(cursorTargetStyles.width, " !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n}\n\n%t [data-trix-cursor-target=left] {\n vertical-align: top !important;\n margin-left: -1px !important;\n}\n\n%t [data-trix-cursor-target=right] {\n vertical-align: bottom !important;\n margin-right: -1px !important;\n}"));
11983
+ installDefaultCSSForTagName("trix-editor", "%t {\n display: block;\n}\n\n%t:empty::before {\n content: attr(placeholder);\n color: graytext;\n cursor: text;\n pointer-events: none;\n white-space: pre-line;\n}\n\n%t a[contenteditable=false] {\n cursor: text;\n}\n\n%t img {\n max-width: 100%;\n height: auto;\n}\n\n%t ".concat(attachmentSelector, " figcaption textarea {\n resize: none;\n}\n\n%t ").concat(attachmentSelector, " figcaption textarea.trix-autoresize-clone {\n position: absolute;\n left: -9999px;\n max-height: 0px;\n}\n\n%t ").concat(attachmentSelector, " figcaption[data-trix-placeholder]:empty::before {\n content: attr(data-trix-placeholder);\n color: graytext;\n}\n\n%t [data-trix-cursor-target] {\n display: ").concat(cursorTargetStyles.display, " !important;\n width: ").concat(cursorTargetStyles.width, " !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n}\n\n%t [data-trix-cursor-target=left] {\n vertical-align: top !important;\n margin-left: -1px !important;\n}\n\n%t [data-trix-cursor-target=right] {\n vertical-align: bottom !important;\n margin-right: -1px !important;\n}"));
11984
+ var _internals = /*#__PURE__*/new WeakMap();
11985
+ var _validate = /*#__PURE__*/new WeakSet();
11986
+ class ElementInternalsDelegate {
11987
+ constructor(element) {
11988
+ _classPrivateMethodInitSpec(this, _validate);
11989
+ _classPrivateFieldInitSpec(this, _internals, {
11990
+ writable: true,
11991
+ value: void 0
11992
+ });
11993
+ this.element = element;
11994
+ _classPrivateFieldSet(this, _internals, element.attachInternals());
11995
+ }
11996
+ connectedCallback() {
11997
+ _classPrivateMethodGet(this, _validate, _validate2).call(this);
11998
+ }
11999
+ disconnectedCallback() {}
12000
+ get labels() {
12001
+ return _classPrivateFieldGet(this, _internals).labels;
12002
+ }
12003
+ get disabled() {
12004
+ var _this$element$inputEl;
12005
+ return (_this$element$inputEl = this.element.inputElement) === null || _this$element$inputEl === void 0 ? void 0 : _this$element$inputEl.disabled;
12006
+ }
12007
+ set disabled(value) {
12008
+ this.element.toggleAttribute("disabled", value);
12009
+ }
12010
+ get required() {
12011
+ return this.element.hasAttribute("required");
12012
+ }
12013
+ set required(value) {
12014
+ this.element.toggleAttribute("required", value);
12015
+ _classPrivateMethodGet(this, _validate, _validate2).call(this);
12016
+ }
12017
+ get validity() {
12018
+ return _classPrivateFieldGet(this, _internals).validity;
12019
+ }
12020
+ get validationMessage() {
12021
+ return _classPrivateFieldGet(this, _internals).validationMessage;
12022
+ }
12023
+ get willValidate() {
12024
+ return _classPrivateFieldGet(this, _internals).willValidate;
12025
+ }
12026
+ setFormValue(value) {
12027
+ _classPrivateMethodGet(this, _validate, _validate2).call(this);
12028
+ }
12029
+ checkValidity() {
12030
+ return _classPrivateFieldGet(this, _internals).checkValidity();
12031
+ }
12032
+ reportValidity() {
12033
+ return _classPrivateFieldGet(this, _internals).reportValidity();
12034
+ }
12035
+ setCustomValidity(validationMessage) {
12036
+ _classPrivateMethodGet(this, _validate, _validate2).call(this, validationMessage);
12037
+ }
12038
+ }
12039
+ function _validate2() {
12040
+ let customValidationMessage = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "";
12041
+ const {
12042
+ required,
12043
+ value
12044
+ } = this.element;
12045
+ const valueMissing = required && !value;
12046
+ const customError = !!customValidationMessage;
12047
+ const input = makeElement("input", {
12048
+ required
12049
+ });
12050
+ const validationMessage = customValidationMessage || input.validationMessage;
12051
+ _classPrivateFieldGet(this, _internals).setValidity({
12052
+ valueMissing,
12053
+ customError
12054
+ }, validationMessage);
12055
+ }
12056
+ var _focusHandler = /*#__PURE__*/new WeakMap();
12057
+ var _resetBubbled = /*#__PURE__*/new WeakMap();
12058
+ var _clickBubbled = /*#__PURE__*/new WeakMap();
12059
+ class LegacyDelegate {
12060
+ constructor(element) {
12061
+ _classPrivateFieldInitSpec(this, _focusHandler, {
12062
+ writable: true,
12063
+ value: void 0
12064
+ });
12065
+ _classPrivateFieldInitSpec(this, _resetBubbled, {
12066
+ writable: true,
12067
+ value: event => {
12068
+ if (event.defaultPrevented) return;
12069
+ if (event.target !== this.element.form) return;
12070
+ this.element.reset();
12071
+ }
12072
+ });
12073
+ _classPrivateFieldInitSpec(this, _clickBubbled, {
12074
+ writable: true,
12075
+ value: event => {
12076
+ if (event.defaultPrevented) return;
12077
+ if (this.element.contains(event.target)) return;
12078
+ const label = findClosestElementFromNode(event.target, {
12079
+ matchingSelector: "label"
12080
+ });
12081
+ if (!label) return;
12082
+ if (!Array.from(this.labels).includes(label)) return;
12083
+ this.element.focus();
12084
+ }
12085
+ });
12086
+ this.element = element;
12087
+ }
12088
+ connectedCallback() {
12089
+ _classPrivateFieldSet(this, _focusHandler, ensureAriaLabel(this.element));
12090
+ window.addEventListener("reset", _classPrivateFieldGet(this, _resetBubbled), false);
12091
+ window.addEventListener("click", _classPrivateFieldGet(this, _clickBubbled), false);
12092
+ }
12093
+ disconnectedCallback() {
12094
+ var _classPrivateFieldGet2;
12095
+ (_classPrivateFieldGet2 = _classPrivateFieldGet(this, _focusHandler)) === null || _classPrivateFieldGet2 === void 0 || _classPrivateFieldGet2.destroy();
12096
+ window.removeEventListener("reset", _classPrivateFieldGet(this, _resetBubbled), false);
12097
+ window.removeEventListener("click", _classPrivateFieldGet(this, _clickBubbled), false);
12098
+ }
12099
+ get labels() {
12100
+ const labels = [];
12101
+ if (this.element.id && this.element.ownerDocument) {
12102
+ labels.push(...Array.from(this.element.ownerDocument.querySelectorAll("label[for='".concat(this.element.id, "']")) || []));
12103
+ }
12104
+ const label = findClosestElementFromNode(this.element, {
12105
+ matchingSelector: "label"
12106
+ });
12107
+ if (label) {
12108
+ if ([this.element, null].includes(label.control)) {
12109
+ labels.push(label);
12110
+ }
12111
+ }
12112
+ return labels;
12113
+ }
12114
+ get disabled() {
12115
+ console.warn("This browser does not support the [disabled] attribute for trix-editor elements.");
12116
+ return false;
12117
+ }
12118
+ set disabled(value) {
12119
+ console.warn("This browser does not support the [disabled] attribute for trix-editor elements.");
12120
+ }
12121
+ get required() {
12122
+ console.warn("This browser does not support the [required] attribute for trix-editor elements.");
12123
+ return false;
12124
+ }
12125
+ set required(value) {
12126
+ console.warn("This browser does not support the [required] attribute for trix-editor elements.");
12127
+ }
12128
+ get validity() {
12129
+ console.warn("This browser does not support the validity property for trix-editor elements.");
12130
+ return null;
12131
+ }
12132
+ get validationMessage() {
12133
+ console.warn("This browser does not support the validationMessage property for trix-editor elements.");
12134
+ return "";
12135
+ }
12136
+ get willValidate() {
12137
+ console.warn("This browser does not support the willValidate property for trix-editor elements.");
12138
+ return false;
12139
+ }
12140
+ setFormValue(value) {}
12141
+ checkValidity() {
12142
+ console.warn("This browser does not support checkValidity() for trix-editor elements.");
12143
+ return true;
12144
+ }
12145
+ reportValidity() {
12146
+ console.warn("This browser does not support reportValidity() for trix-editor elements.");
12147
+ return true;
12148
+ }
12149
+ setCustomValidity(validationMessage) {
12150
+ console.warn("This browser does not support setCustomValidity(validationMessage) for trix-editor elements.");
12151
+ }
12152
+ }
12153
+ var _delegate = /*#__PURE__*/new WeakMap();
11960
12154
  class TrixEditorElement extends HTMLElement {
12155
+ constructor() {
12156
+ super();
12157
+ _classPrivateFieldInitSpec(this, _delegate, {
12158
+ writable: true,
12159
+ value: void 0
12160
+ });
12161
+ _classPrivateFieldSet(this, _delegate, this.constructor.formAssociated ? new ElementInternalsDelegate(this) : new LegacyDelegate(this));
12162
+ }
12163
+
11961
12164
  // Properties
11962
12165
 
11963
12166
  get trixId() {
@@ -11969,19 +12172,31 @@ $\
11969
12172
  }
11970
12173
  }
11971
12174
  get labels() {
11972
- const labels = [];
11973
- if (this.id && this.ownerDocument) {
11974
- labels.push(...Array.from(this.ownerDocument.querySelectorAll("label[for='".concat(this.id, "']")) || []));
11975
- }
11976
- const label = findClosestElementFromNode(this, {
11977
- matchingSelector: "label"
11978
- });
11979
- if (label) {
11980
- if ([this, null].includes(label.control)) {
11981
- labels.push(label);
11982
- }
11983
- }
11984
- return labels;
12175
+ return _classPrivateFieldGet(this, _delegate).labels;
12176
+ }
12177
+ get disabled() {
12178
+ return _classPrivateFieldGet(this, _delegate).disabled;
12179
+ }
12180
+ set disabled(value) {
12181
+ _classPrivateFieldGet(this, _delegate).disabled = value;
12182
+ }
12183
+ get required() {
12184
+ return _classPrivateFieldGet(this, _delegate).required;
12185
+ }
12186
+ set required(value) {
12187
+ _classPrivateFieldGet(this, _delegate).required = value;
12188
+ }
12189
+ get validity() {
12190
+ return _classPrivateFieldGet(this, _delegate).validity;
12191
+ }
12192
+ get validationMessage() {
12193
+ return _classPrivateFieldGet(this, _delegate).validationMessage;
12194
+ }
12195
+ get willValidate() {
12196
+ return _classPrivateFieldGet(this, _delegate).willValidate;
12197
+ }
12198
+ get type() {
12199
+ return this.localName;
11985
12200
  }
11986
12201
  get toolbarElement() {
11987
12202
  if (this.hasAttribute("toolbar")) {
@@ -12048,9 +12263,10 @@ $\
12048
12263
  });
12049
12264
  }
12050
12265
  }
12051
- setInputElementValue(value) {
12266
+ setFormValue(value) {
12052
12267
  if (this.inputElement) {
12053
12268
  this.inputElement.value = value;
12269
+ _classPrivateFieldGet(this, _delegate).setFormValue(value);
12054
12270
  }
12055
12271
  }
12056
12272
 
@@ -12060,7 +12276,6 @@ $\
12060
12276
  if (!this.hasAttribute("data-trix-internal")) {
12061
12277
  makeEditable(this);
12062
12278
  addAccessibilityRole(this);
12063
- ensureAriaLabel(this);
12064
12279
  if (!this.editorController) {
12065
12280
  triggerEvent("trix-before-initialize", {
12066
12281
  onElement: this
@@ -12074,53 +12289,41 @@ $\
12074
12289
  }));
12075
12290
  }
12076
12291
  this.editorController.registerSelectionManager();
12077
- this.registerResetListener();
12078
- this.registerClickListener();
12292
+ _classPrivateFieldGet(this, _delegate).connectedCallback();
12079
12293
  autofocus(this);
12080
12294
  }
12081
12295
  }
12082
12296
  disconnectedCallback() {
12083
12297
  var _this$editorControlle2;
12084
12298
  (_this$editorControlle2 = this.editorController) === null || _this$editorControlle2 === void 0 || _this$editorControlle2.unregisterSelectionManager();
12085
- this.unregisterResetListener();
12086
- return this.unregisterClickListener();
12299
+ _classPrivateFieldGet(this, _delegate).disconnectedCallback();
12087
12300
  }
12088
12301
 
12089
12302
  // Form support
12090
12303
 
12091
- registerResetListener() {
12092
- this.resetListener = this.resetBubbled.bind(this);
12093
- return window.addEventListener("reset", this.resetListener, false);
12094
- }
12095
- unregisterResetListener() {
12096
- return window.removeEventListener("reset", this.resetListener, false);
12304
+ checkValidity() {
12305
+ return _classPrivateFieldGet(this, _delegate).checkValidity();
12097
12306
  }
12098
- registerClickListener() {
12099
- this.clickListener = this.clickBubbled.bind(this);
12100
- return window.addEventListener("click", this.clickListener, false);
12307
+ reportValidity() {
12308
+ return _classPrivateFieldGet(this, _delegate).reportValidity();
12101
12309
  }
12102
- unregisterClickListener() {
12103
- return window.removeEventListener("click", this.clickListener, false);
12310
+ setCustomValidity(validationMessage) {
12311
+ _classPrivateFieldGet(this, _delegate).setCustomValidity(validationMessage);
12104
12312
  }
12105
- resetBubbled(event) {
12106
- if (event.defaultPrevented) return;
12107
- if (event.target !== this.form) return;
12108
- return this.reset();
12313
+ formDisabledCallback(disabled) {
12314
+ if (this.inputElement) {
12315
+ this.inputElement.disabled = disabled;
12316
+ }
12317
+ this.toggleAttribute("contenteditable", !disabled);
12109
12318
  }
12110
- clickBubbled(event) {
12111
- if (event.defaultPrevented) return;
12112
- if (this.contains(event.target)) return;
12113
- const label = findClosestElementFromNode(event.target, {
12114
- matchingSelector: "label"
12115
- });
12116
- if (!label) return;
12117
- if (!Array.from(this.labels).includes(label)) return;
12118
- return this.focus();
12319
+ formResetCallback() {
12320
+ this.reset();
12119
12321
  }
12120
12322
  reset() {
12121
12323
  this.value = this.defaultValue;
12122
12324
  }
12123
12325
  }
12326
+ _defineProperty(TrixEditorElement, "formAssociated", "ElementInternals" in window);
12124
12327
 
12125
12328
  var elements = /*#__PURE__*/Object.freeze({
12126
12329
  __proto__: null,
@@ -12,7 +12,7 @@ module ActionText
12
12
  MAJOR = 8
13
13
  MINOR = 0
14
14
  TINY = 0
15
- PRE = "beta1"
15
+ PRE = "rc2"
16
16
 
17
17
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
18
18
  end
@@ -65,7 +65,12 @@ module ActionText
65
65
 
66
66
  def plain_text_for_blockquote_node(node, index)
67
67
  text = plain_text_for_block(node)
68
- text.sub(/\A(\s*)(.+?)(\s*)\Z/m, '\1“\2”\3')
68
+ return "“”" if text.blank?
69
+
70
+ text = text.dup
71
+ text.insert(text.rindex(/\S/) + 1, "”")
72
+ text.insert(text.index(/\S/), "“")
73
+ text
69
74
  end
70
75
 
71
76
  def plain_text_for_li_node(node, index)
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rails/actiontext",
3
- "version": "8.0.0-beta1",
3
+ "version": "8.0.0-rc2",
4
4
  "description": "Edit and display rich text in Rails applications",
5
5
  "module": "app/assets/javascripts/actiontext.esm.js",
6
6
  "main": "app/assets/javascripts/actiontext.js",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: actiontext
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.0.0.beta1
4
+ version: 8.0.0.rc2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Javan Makhmali
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2024-09-26 00:00:00.000000000 Z
13
+ date: 2024-10-30 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
@@ -18,56 +18,56 @@ dependencies:
18
18
  requirements:
19
19
  - - '='
20
20
  - !ruby/object:Gem::Version
21
- version: 8.0.0.beta1
21
+ version: 8.0.0.rc2
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
26
  - - '='
27
27
  - !ruby/object:Gem::Version
28
- version: 8.0.0.beta1
28
+ version: 8.0.0.rc2
29
29
  - !ruby/object:Gem::Dependency
30
30
  name: activerecord
31
31
  requirement: !ruby/object:Gem::Requirement
32
32
  requirements:
33
33
  - - '='
34
34
  - !ruby/object:Gem::Version
35
- version: 8.0.0.beta1
35
+ version: 8.0.0.rc2
36
36
  type: :runtime
37
37
  prerelease: false
38
38
  version_requirements: !ruby/object:Gem::Requirement
39
39
  requirements:
40
40
  - - '='
41
41
  - !ruby/object:Gem::Version
42
- version: 8.0.0.beta1
42
+ version: 8.0.0.rc2
43
43
  - !ruby/object:Gem::Dependency
44
44
  name: activestorage
45
45
  requirement: !ruby/object:Gem::Requirement
46
46
  requirements:
47
47
  - - '='
48
48
  - !ruby/object:Gem::Version
49
- version: 8.0.0.beta1
49
+ version: 8.0.0.rc2
50
50
  type: :runtime
51
51
  prerelease: false
52
52
  version_requirements: !ruby/object:Gem::Requirement
53
53
  requirements:
54
54
  - - '='
55
55
  - !ruby/object:Gem::Version
56
- version: 8.0.0.beta1
56
+ version: 8.0.0.rc2
57
57
  - !ruby/object:Gem::Dependency
58
58
  name: actionpack
59
59
  requirement: !ruby/object:Gem::Requirement
60
60
  requirements:
61
61
  - - '='
62
62
  - !ruby/object:Gem::Version
63
- version: 8.0.0.beta1
63
+ version: 8.0.0.rc2
64
64
  type: :runtime
65
65
  prerelease: false
66
66
  version_requirements: !ruby/object:Gem::Requirement
67
67
  requirements:
68
68
  - - '='
69
69
  - !ruby/object:Gem::Version
70
- version: 8.0.0.beta1
70
+ version: 8.0.0.rc2
71
71
  - !ruby/object:Gem::Dependency
72
72
  name: nokogiri
73
73
  requirement: !ruby/object:Gem::Requirement
@@ -163,10 +163,10 @@ licenses:
163
163
  - MIT
164
164
  metadata:
165
165
  bug_tracker_uri: https://github.com/rails/rails/issues
166
- changelog_uri: https://github.com/rails/rails/blob/v8.0.0.beta1/actiontext/CHANGELOG.md
167
- documentation_uri: https://api.rubyonrails.org/v8.0.0.beta1/
166
+ changelog_uri: https://github.com/rails/rails/blob/v8.0.0.rc2/actiontext/CHANGELOG.md
167
+ documentation_uri: https://api.rubyonrails.org/v8.0.0.rc2/
168
168
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
169
- source_code_uri: https://github.com/rails/rails/tree/v8.0.0.beta1/actiontext
169
+ source_code_uri: https://github.com/rails/rails/tree/v8.0.0.rc2/actiontext
170
170
  rubygems_mfa_required: 'true'
171
171
  post_install_message:
172
172
  rdoc_options: []