actiontext 8.0.0.beta1 → 8.0.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
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: []