@37signals/lexxy 1.0.0 → 1.0.1

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.
Files changed (2) hide show
  1. package/dist/lexxy.esm.js +35 -5
  2. package/package.json +1 -1
package/dist/lexxy.esm.js CHANGED
@@ -2474,14 +2474,14 @@ function extendTextNodeConversion(conversionName, ...callbacks) {
2474
2474
  ...conversionOutput,
2475
2475
  forChild: (lexicalNode, parentNode) => {
2476
2476
  const originalForChild = conversionOutput?.forChild ?? (x => x);
2477
- let childNode = originalForChild(lexicalNode, parentNode);
2478
-
2477
+ const childNode = originalForChild(lexicalNode, parentNode);
2479
2478
 
2480
2479
  if ($isTextNode(childNode)) {
2481
- childNode = callbacks.reduce(
2480
+ return callbacks.reduce(
2482
2481
  (childNode, callback) => callback(childNode, element) ?? childNode,
2483
2482
  childNode
2484
- );
2483
+ )
2484
+ } else {
2485
2485
  return childNode
2486
2486
  }
2487
2487
  }
@@ -6844,6 +6844,7 @@ class PastedContentFormatter {
6844
6844
  format() {
6845
6845
  this.#inlinePreservableStyles();
6846
6846
  this.#stripStyleElements();
6847
+ this.#stripInterchangeNewlines();
6847
6848
  this.#unwrapPlaceholderAnchors();
6848
6849
  this.#stripTableCellColorStyles();
6849
6850
  new OfficeFormatter(this.doc).format();
@@ -6879,6 +6880,35 @@ class PastedContentFormatter {
6879
6880
  }
6880
6881
  }
6881
6882
 
6883
+ // Chrome and Safari append <br class="Apple-interchange-newline"> when the
6884
+ // copied selection ends at a line end (Google Docs does this on every copy).
6885
+ // It marks the end of the selection, not a line the author wrote, so left in
6886
+ // place it pastes as an extra empty paragraph. Only the trailing marker goes:
6887
+ // one at the start of the fragment is a real line boundary.
6888
+ #stripInterchangeNewlines() {
6889
+ for (const br of this.doc.querySelectorAll("br.Apple-interchange-newline")) {
6890
+ if (this.#isAtEndOfBody(br)) {
6891
+ br.remove();
6892
+ }
6893
+ }
6894
+ }
6895
+
6896
+ #isAtEndOfBody(node) {
6897
+ for (let current = node; current && current !== this.doc.body; current = current.parentNode) {
6898
+ for (let sibling = current.nextSibling; sibling; sibling = sibling.nextSibling) {
6899
+ if (!this.#isIgnorableTrailingNode(sibling)) return false
6900
+ }
6901
+ }
6902
+ return true
6903
+ }
6904
+
6905
+ #isIgnorableTrailingNode(node) {
6906
+ if (node.nodeType === Node.COMMENT_NODE) {
6907
+ return true
6908
+ }
6909
+ return node.nodeType === Node.TEXT_NODE && node.textContent.trim() === ""
6910
+ }
6911
+
6882
6912
  // Anchors with non-meaningful hrefs (e.g. "#", "") appear in content copied
6883
6913
  // from rendered views where mentions and interactive elements are wrapped in
6884
6914
  // <a href="#"> tags. Unwrap them so their text content pastes as plain text
@@ -8654,7 +8684,7 @@ class TrixContentExtension extends LexxyExtension {
8654
8684
  priority: 1
8655
8685
  }),
8656
8686
  span: (element) => onlyStyledElements(element, {
8657
- conversion: extendTextNodeConversion("mark", $applyHighlightStyle),
8687
+ conversion: extendTextNodeConversion("span", $applyHighlightStyle),
8658
8688
  priority: 1
8659
8689
  }),
8660
8690
  strong: (element) => onlyStyledElements(element, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@37signals/lexxy",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Lexxy - A modern rich text editor for Rails.",
5
5
  "module": "dist/lexxy.esm.js",
6
6
  "type": "module",