lexxy 0.9.19 → 0.9.21

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: b6868388203b7cfd6a7026208872b75268aafab61e5e29abc57ed35825dfdb8d
4
- data.tar.gz: cdbb2c3702b5d204c2820a8a0fdf5c2c851c4d8272b1aa32e9dd8680adae409d
3
+ metadata.gz: 9a161b79f6c66266f236c0bae71c3ea540237a2a403fb2e047d43828e395bfda
4
+ data.tar.gz: '030840a6e183bc84837825ff7b8f646ebfb74fdd2d582c93c3475b38b88e633e'
5
5
  SHA512:
6
- metadata.gz: 6a0ced04355235c795d5329b620f75e39ead9abfb64e4111939c2ce40c0a099b6d8aeed6222105d9e17aa909be1cc1e7a83037b2b9ff2fc8c49849f61f21a346
7
- data.tar.gz: 26d5669519354092c672bc86bfe37f0939c16bc24336f3242e87ef4d9a5e7416bd856b275238c1bca32b5dd20a98f2c20784aee6c064a86033cc6edb34ced695
6
+ metadata.gz: 1c03106f2eed700e7521b00a937ace2b854459633b99ee93f6ef99eb323fd017d95fd9d348d174decc8a5e9e3b028fe9b470f5943066563b3ba6a55d03871c2b
7
+ data.tar.gz: b1d3121c8bc34f2b560192523f0e9a5ec885d869df2b9bdf56da88bd16829b8a5b9c0b0e99fa95507c06b65a1ca381665678df5f74dca94501b81937c658189a
@@ -6348,8 +6348,8 @@ function dispatch(element, eventName, detail = null, cancelable = false) {
6348
6348
  }
6349
6349
 
6350
6350
  function addBlockSpacing(doc) {
6351
- const blocks = doc.querySelectorAll("body > :not(h1, h2, h3, h4, h5, h6) + *");
6352
- for (const block of blocks) {
6351
+ const selector = "body > :not(h1, h2, h3, h4, h5, h6) + *, blockquote > :not(h1, h2, h3, h4, h5, h6) + *";
6352
+ for (const block of doc.querySelectorAll(selector)) {
6353
6353
  const spacer = doc.createElement("p");
6354
6354
  spacer.appendChild(doc.createElement("br"));
6355
6355
  block.before(spacer);
@@ -8018,6 +8018,7 @@ function $splitSelectedParagraphsAtInnerLineBreaks(selection) {
8018
8018
 
8019
8019
  function $expandSelectionToLineBreaksAndSplitAtEdges(selection, fallbackAncestor = (node) => node.getTopLevelElement()) {
8020
8020
  j$6(selection);
8021
+ $shrinkSelectionPastBlockEdges(selection);
8021
8022
 
8022
8023
  const focusCaret = ql(selection.focus, "next");
8023
8024
  const anchorCaret = ql(selection.anchor, "previous");
@@ -8049,6 +8050,52 @@ function $expandSelectionToLineBreaksAndSplitAtEdges(selection, fallbackAncestor
8049
8050
  ));
8050
8051
  }
8051
8052
 
8053
+ // A selection whose anchor sits at the very end of one block while its focus
8054
+ // lives in a later block (e.g. selecting a pasted paragraph when the browser
8055
+ // anchors at the end of the line above) contributes nothing from the anchor's
8056
+ // block. Pull each endpoint that is flush against a block edge into the block
8057
+ // that actually holds the selected content, so we don't wrap the empty edge
8058
+ // block too.
8059
+ function $shrinkSelectionPastBlockEdges(selection) {
8060
+ if (selection.isCollapsed()) return
8061
+
8062
+ const anchorBlock = selection.anchor.getNode().getTopLevelElement();
8063
+ const focusBlock = selection.focus.getNode().getTopLevelElement();
8064
+ if (!anchorBlock || !focusBlock || anchorBlock.is(focusBlock)) return
8065
+
8066
+ if ($isAtBlockEnd(selection.anchor, anchorBlock)) {
8067
+ const nextBlock = anchorBlock.getNextSibling();
8068
+ if (nextBlock) selection.anchor.set(nextBlock.getKey(), 0, "element");
8069
+ }
8070
+
8071
+ if ($isAtBlockStart(selection.focus, focusBlock)) {
8072
+ const previousBlock = focusBlock.getPreviousSibling();
8073
+ if (previousBlock) selection.focus.set(previousBlock.getKey(), previousBlock.getChildrenSize(), "element");
8074
+ }
8075
+ }
8076
+
8077
+ function $isAtBlockEnd(point, block) {
8078
+ return $isAtBlockBoundary(ql(point, "next"), block)
8079
+ }
8080
+
8081
+ function $isAtBlockStart(point, block) {
8082
+ return $isAtBlockBoundary(ql(point, "previous"), block)
8083
+ }
8084
+
8085
+ // A text point sitting mid-node still has content ahead of it in the caret's
8086
+ // direction, even though that content is not a sibling node. $getNodeAtCaret
8087
+ // only sees siblings, so check the text edge before walking the block.
8088
+ function $isAtBlockBoundary(caret, block) {
8089
+ if (vl(caret) && ic(caret)) return false
8090
+
8091
+ let cursor = rc(caret);
8092
+ while (cursor && block.isParentOf(cursor.origin)) {
8093
+ if (cursor.getNodeAtCaret()) return false
8094
+ cursor = cursor.getParentCaret();
8095
+ }
8096
+ return true
8097
+ }
8098
+
8052
8099
  function $getCaretAtLineBreakBoundary(caret, skipInwardEdge = false) {
8053
8100
  const paragraph = caret.origin.getTopLevelElement();
8054
8101
  if (!paragraph || !no(paragraph)) return null
@@ -9469,7 +9516,7 @@ function $registerPreConversion(editor) {
9469
9516
  // and applied after retokenization via a mutation listener.
9470
9517
  function $preConversionWithHighlightsFactory(editor) {
9471
9518
  return function $preConversionWithHighlights(domNode) {
9472
- const highlights = extractHighlightRanges$1(domNode);
9519
+ const highlights = extractHighlightRanges(domNode);
9473
9520
  if (highlights.length === 0) return null
9474
9521
 
9475
9522
  return {
@@ -9486,7 +9533,7 @@ function $preConversionWithHighlightsFactory(editor) {
9486
9533
 
9487
9534
  // Walk the DOM tree inside a <pre> element and build a list of
9488
9535
  // { start, end, style } ranges for every <mark> element found.
9489
- function extractHighlightRanges$1(preElement) {
9536
+ function extractHighlightRanges(preElement) {
9490
9537
  const ranges = [];
9491
9538
  const codeElement = preElement.querySelector("code") || preElement;
9492
9539
 
@@ -12019,6 +12066,7 @@ class PastedContentFormatter {
12019
12066
  format() {
12020
12067
  this.#unwrapPlaceholderAnchors();
12021
12068
  this.#stripTableCellColorStyles();
12069
+ this.#nestStrayListChildren();
12022
12070
  this.#stripStrayListChildren();
12023
12071
  return this.doc
12024
12072
  }
@@ -12047,6 +12095,22 @@ class PastedContentFormatter {
12047
12095
  }
12048
12096
  }
12049
12097
 
12098
+ // Some sources (e.g. Gmail) nest a sublist as a direct child of the parent
12099
+ // <ol>/<ul> instead of inside a <li>. Move each nested list into its
12100
+ // preceding <li> so the import preserves the nesting instead of dropping it.
12101
+ #nestStrayListChildren() {
12102
+ for (const list of this.doc.querySelectorAll("ol, ul")) {
12103
+ for (const child of Array.from(list.children)) {
12104
+ if (child.tagName !== "OL" && child.tagName !== "UL") continue
12105
+
12106
+ const previousItem = child.previousElementSibling;
12107
+ if (previousItem && previousItem.tagName === "LI") {
12108
+ previousItem.appendChild(child);
12109
+ }
12110
+ }
12111
+ }
12112
+ }
12113
+
12050
12114
  // Only <li> is a valid child of a list; drop stray <br>/whitespace so the
12051
12115
  // import doesn't wrap them into an empty leading item.
12052
12116
  #stripStrayListChildren() {
@@ -12090,7 +12154,11 @@ class Contents {
12090
12154
 
12091
12155
  insertText(text, { tag } = {}) {
12092
12156
  this.editor.update(() => {
12093
- const paragraph = eo().append(kr(text));
12157
+ const paragraph = eo();
12158
+ text.split("\n").forEach((line, index) => {
12159
+ if (index > 0) paragraph.append(or());
12160
+ paragraph.append(kr(line));
12161
+ });
12094
12162
  this.insertAtCursor(paragraph);
12095
12163
  }, { tag });
12096
12164
  }
@@ -12816,7 +12884,7 @@ class Clipboard {
12816
12884
  }
12817
12885
 
12818
12886
  if (this.#isPlainTextOrURLPasted(clipboardData)) {
12819
- this.#pastePlainText(clipboardData);
12887
+ this.#pastePlainTextOrURL(clipboardData);
12820
12888
  event.preventDefault();
12821
12889
  return true
12822
12890
  }
@@ -12854,14 +12922,34 @@ class Clipboard {
12854
12922
  return types.length === 1 && types[0] === "text/plain"
12855
12923
  }
12856
12924
 
12925
+ // Browsers expose a copied URL in several shapes:
12926
+ // Safari [ text/plain, text/uri-list ]
12927
+ // App ShareSheet [ text/uri-list ]
12928
+ // Chromium macOS [ text/plain, text/html, (?:text/link-preview) ]
12857
12929
  #isOnlyURLPasted(clipboardData) {
12858
- // Safari URLs are copied as a text/plain + text/uri-list object
12859
- // App ShareSheet URLs are copied as solo text/uri-list object
12930
+ if (this.#isLexicalClipboardData(clipboardData)) return false
12931
+
12860
12932
  const types = Array.from(clipboardData.types);
12861
- return types.length
12862
- && types.length <= 2
12863
- && types.includes("text/uri-list")
12864
- && (types.length < 2 || types.includes("text/plain"))
12933
+ if (types.includes("text/uri-list")) {
12934
+ return types.every(type => type === "text/plain" || type === "text/uri-list")
12935
+ }
12936
+
12937
+ if (clipboardData.files.length) return false
12938
+
12939
+ const text = clipboardData.getData("text/plain").trim();
12940
+ if (!isAutolinkableURL(text)) return false
12941
+
12942
+ const html = clipboardData.getData("text/html");
12943
+ return !html || this.#htmlIsBareLinkToURL(html, text)
12944
+ }
12945
+
12946
+ #htmlIsBareLinkToURL(html, url) {
12947
+ const doc = parseHtml(html);
12948
+ if (doc.body.textContent.trim() !== url) return false
12949
+
12950
+ const links = doc.body.querySelectorAll("a");
12951
+ if (links.length === 0) return true
12952
+ return links.length === 1 && links[0].getAttribute("href") === url
12865
12953
  }
12866
12954
 
12867
12955
  #isPastingIntoCodeBlock() {
@@ -12895,14 +12983,12 @@ class Clipboard {
12895
12983
  }, { tag: jn });
12896
12984
  }
12897
12985
 
12898
- #pastePlainText(clipboardData) {
12899
- const item = clipboardData.items[0];
12986
+ #pastePlainTextOrURL(clipboardData) {
12987
+ const item = this.#plainTextOrURLItem(clipboardData);
12900
12988
  item.getAsString((text) => {
12901
- if (isAutolinkableURL(text) && this.contents.hasSelectedText()) {
12902
- this.contents.createLinkWithSelectedText(text);
12903
- } else if (isAutolinkableURL(text)) {
12904
- const nodeKey = this.contents.createLink(text);
12905
- this.#dispatchLinkInsertEvent(nodeKey, { url: text });
12989
+ const url = text.trim();
12990
+ if (isAutolinkableURL(url)) {
12991
+ this.#pasteURL(url);
12906
12992
  } else if (this.editorElement.supportsMarkdown) {
12907
12993
  this.#pasteMarkdown(text);
12908
12994
  } else {
@@ -12911,6 +12997,20 @@ class Clipboard {
12911
12997
  });
12912
12998
  }
12913
12999
 
13000
+ #plainTextOrURLItem(clipboardData) {
13001
+ const items = Array.from(clipboardData.items);
13002
+ return items.find((item) => item.type === "text/plain") || items.find((item) => item.type === "text/uri-list")
13003
+ }
13004
+
13005
+ #pasteURL(url) {
13006
+ if (this.contents.hasSelectedText()) {
13007
+ this.contents.createLinkWithSelectedText(url);
13008
+ } else {
13009
+ const nodeKey = this.contents.createLink(url);
13010
+ this.#dispatchLinkInsertEvent(nodeKey, { url });
13011
+ }
13012
+ }
13013
+
12914
13014
  #insertSingleLinkAt(selection, url) {
12915
13015
  if (!Fr(selection)) return
12916
13016
 
@@ -12958,14 +13058,16 @@ class Clipboard {
12958
13058
 
12959
13059
  // Markdown conversion collapses runs of whitespace and unescapes backslashes,
12960
13060
  // silently corrupting plain text such as Windows/UNC file paths. When the text
12961
- // carries no Markdown structure, paste it verbatim instead.
13061
+ // carries no Markdown structure, paste it verbatim instead. A path that wrapped
13062
+ // across lines renders as a single paragraph with <br> line breaks (marked runs
13063
+ // with breaks: true), which is still plain text we should preserve untouched.
12962
13064
  #isPlainTextWithoutMarkdown(doc) {
12963
13065
  const elements = Array.from(doc.body.children);
12964
13066
  if (elements.length !== 1) return false
12965
13067
 
12966
13068
  const paragraph = elements[0];
12967
13069
  return paragraph.nodeName === "P"
12968
- && Array.from(paragraph.childNodes).every((node) => node.nodeType === Node.TEXT_NODE)
13070
+ && Array.from(paragraph.childNodes).every((node) => node.nodeType === Node.TEXT_NODE || node.nodeName === "BR")
12969
13071
  }
12970
13072
 
12971
13073
  #pasteRichText(clipboardData) {
@@ -14253,24 +14355,46 @@ class FormatEscapeExtension extends LexxyExtension {
14253
14355
  }
14254
14356
 
14255
14357
  function $escapeFromBlockquote() {
14358
+ return $escapeBeforeBlockquoteStart() || $escapeFromBlankBlockquoteParagraph()
14359
+ }
14360
+
14361
+ function $escapeBeforeBlockquoteStart() {
14362
+ const selection = Qr();
14363
+ if (!Fr(selection) || !selection.isCollapsed() || selection.anchor.offset !== 0) return false
14364
+
14365
+ const paragraph = At$2(selection.anchor.getNode(), Zi);
14366
+ if (paragraph && !$isBlankNode(paragraph) && !paragraph.getPreviousSibling()) {
14367
+ const blockquote = paragraph.getParent();
14368
+ if (Mt$2(blockquote)) {
14369
+ blockquote.insertBefore(eo());
14370
+ return true
14371
+ }
14372
+ }
14373
+
14374
+ return false
14375
+ }
14376
+
14377
+ function $escapeFromBlankBlockquoteParagraph() {
14256
14378
  const anchorNode = Qr().anchor.getNode();
14257
14379
 
14258
14380
  const paragraph = At$2(anchorNode, Zi);
14259
14381
  if (!paragraph || !$isBlankNode(paragraph)) return false
14260
14382
 
14261
14383
  const blockquote = paragraph.getParent();
14262
- if (!blockquote || !Mt$2(blockquote)) return false
14384
+ if (Mt$2(blockquote)) {
14385
+ const nonEmptySiblings = paragraph.getNextSiblings().filter(sibling => !$isBlankNode(sibling));
14263
14386
 
14264
- const nonEmptySiblings = paragraph.getNextSiblings().filter(sibling => !$isBlankNode(sibling));
14387
+ if (nonEmptySiblings.length > 0) {
14388
+ $splitQuoteNode(blockquote, paragraph);
14389
+ } else {
14390
+ blockquote.insertAfter(paragraph);
14391
+ paragraph.selectStart();
14392
+ }
14265
14393
 
14266
- if (nonEmptySiblings.length > 0) {
14267
- $splitQuoteNode(blockquote, paragraph);
14268
- } else {
14269
- blockquote.insertAfter(paragraph);
14270
- paragraph.selectStart();
14394
+ return true
14271
14395
  }
14272
14396
 
14273
- return true
14397
+ return false
14274
14398
  }
14275
14399
 
14276
14400
  function $splitQuoteNode(node, paragraph) {
@@ -14528,6 +14652,15 @@ class CustomAttachmentDragAndDrop {
14528
14652
  // they only drop onto an existing line, so snap to the nearest one.
14529
14653
  if (caret.node === rootElement) {
14530
14654
  return this.#nearestLineCaret(rootElement, event.clientY)
14655
+ }
14656
+
14657
+ // When mentions sit next to each other with no text between them, the caret
14658
+ // lands inside the neighbouring decorator's DOM. Lexical can't resolve a point
14659
+ // inside a decorator to an editable position, and the cursor has no business
14660
+ // showing there anyway, so snap to just before or after that mention.
14661
+ const decorator = this.#decoratorElementContaining(caret.node);
14662
+ if (decorator) {
14663
+ return this.#dropPointBesideDecorator(decorator, event.clientX)
14531
14664
  } else {
14532
14665
  return caret
14533
14666
  }
@@ -14556,24 +14689,55 @@ class CustomAttachmentDragAndDrop {
14556
14689
  }
14557
14690
  }
14558
14691
 
14692
+ #decoratorElementContaining(node) {
14693
+ const element = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
14694
+ return element?.closest("[data-lexxy-decorator][data-lexical-node-key]")
14695
+ }
14696
+
14697
+ #dropPointBesideDecorator(decorator, clientX) {
14698
+ const rect = decorator.getBoundingClientRect();
14699
+ const placement = clientX > rect.left + rect.width / 2 ? "after" : "before";
14700
+ return { decoratorKey: decorator.dataset.lexicalNodeKey, placement }
14701
+ }
14702
+
14559
14703
  #moveAttachment(draggedKey, dropPoint) {
14560
14704
  this.#editor.update(() => {
14561
14705
  const draggedNode = Yo(draggedKey);
14562
14706
  if (!$isCustomActionTextAttachmentNode(draggedNode)) return
14563
14707
 
14564
- const selection = Gr({
14565
- anchorNode: dropPoint.node,
14566
- anchorOffset: dropPoint.offset,
14567
- focusNode: dropPoint.node,
14568
- focusOffset: dropPoint.offset
14569
- }, this.#editor);
14570
- if (!selection) return
14708
+ if (dropPoint.decoratorKey) {
14709
+ this.#moveBesideNode(draggedNode, dropPoint);
14710
+ } else {
14711
+ this.#moveToCaret(draggedNode, dropPoint);
14712
+ }
14713
+ });
14714
+ }
14571
14715
 
14572
- es(selection);
14716
+ #moveBesideNode(draggedNode, { decoratorKey, placement }) {
14717
+ const targetNode = Yo(decoratorKey);
14718
+ if (!targetNode || targetNode === draggedNode) return
14573
14719
 
14574
- draggedNode.remove();
14575
- selection.insertNodes([ draggedNode ]);
14576
- });
14720
+ draggedNode.remove();
14721
+ if (placement === "after") {
14722
+ targetNode.insertAfter(draggedNode);
14723
+ } else {
14724
+ targetNode.insertBefore(draggedNode);
14725
+ }
14726
+ }
14727
+
14728
+ #moveToCaret(draggedNode, dropPoint) {
14729
+ const selection = Gr({
14730
+ anchorNode: dropPoint.node,
14731
+ anchorOffset: dropPoint.offset,
14732
+ focusNode: dropPoint.node,
14733
+ focusOffset: dropPoint.offset
14734
+ }, this.#editor);
14735
+ if (!selection) return
14736
+
14737
+ es(selection);
14738
+
14739
+ draggedNode.remove();
14740
+ selection.insertNodes([ draggedNode ]);
14577
14741
  }
14578
14742
 
14579
14743
  #updateDropIndicator(event) {
@@ -14583,7 +14747,12 @@ class CustomAttachmentDragAndDrop {
14583
14747
  if (dropPoint) this.#showCaret(this.#caretRectFor(dropPoint));
14584
14748
  }
14585
14749
 
14586
- #caretRectFor({ node, offset }) {
14750
+ #caretRectFor(dropPoint) {
14751
+ if (dropPoint.decoratorKey) {
14752
+ return this.#decoratorEdgeRect(dropPoint)
14753
+ }
14754
+
14755
+ const { node, offset } = dropPoint;
14587
14756
  const rect = caretRect(node, offset);
14588
14757
  if (rect) return rect
14589
14758
 
@@ -14595,6 +14764,15 @@ class CustomAttachmentDragAndDrop {
14595
14764
  return { left: lineRect.left, top: lineRect.top, height: lineRect.height }
14596
14765
  }
14597
14766
 
14767
+ #decoratorEdgeRect({ decoratorKey, placement }) {
14768
+ const decorator = this.#editor.getRootElement()?.querySelector(`[data-lexical-node-key="${decoratorKey}"]`);
14769
+ if (!decorator) return null
14770
+
14771
+ const rect = decorator.getBoundingClientRect();
14772
+ const left = placement === "after" ? rect.right : rect.left;
14773
+ return { left, top: rect.top, height: rect.height }
14774
+ }
14775
+
14598
14776
  #showCaret(rect) {
14599
14777
  if (!rect) return
14600
14778
 
@@ -17209,16 +17387,16 @@ function highlightElement(preElement) {
17209
17387
  if (preElement.dataset.highlighted === "true") return
17210
17388
 
17211
17389
  const language = preElement.getAttribute("data-language");
17212
- let code = preElement.innerHTML.replace(/<br\s*\/?>/gi, "\n");
17213
17390
 
17214
17391
  const grammar = Prism$1.languages?.[language];
17215
17392
  if (!grammar) return
17216
17393
 
17217
- // Extract highlight ranges before Prism destroys <mark> elements
17218
- const highlights = extractHighlightRanges(preElement);
17219
-
17220
- // unescape HTML entities in the code block
17221
- code = new DOMParser().parseFromString(code, "text/html").body.textContent || "";
17394
+ // Read the source text and <mark> ranges in a single walk, before Prism
17395
+ // rewrites the element. Sharing one traversal keeps the highlight offsets
17396
+ // aligned with the code string and preserves leading whitespace — deriving
17397
+ // either of them separately (e.g. textContent through DOMParser) collapses
17398
+ // leading whitespace and shifts every range, re-indenting the rendered block.
17399
+ const { code, highlights } = extractCodeAndHighlights(preElement);
17222
17400
 
17223
17401
  const highlightedHtml = Prism$1.highlight(code, grammar, language);
17224
17402
  preElement.innerHTML = highlightedHtml;
@@ -17230,34 +17408,35 @@ function highlightElement(preElement) {
17230
17408
  preElement.dataset.highlighted = "true";
17231
17409
  }
17232
17410
 
17233
- // Walk the DOM tree inside a <pre> element and build a list of
17234
- // { start, end, style } ranges for every <mark> element found.
17235
- function extractHighlightRanges(preElement) {
17236
- const ranges = [];
17411
+ // Walk the <pre> once, building Prism's source text and the <mark> ranges
17412
+ // together: a text node contributes its text verbatim, a <br> contributes a
17413
+ // newline, and a <mark> records the slice of code it covers. Because both
17414
+ // outputs come from the same walk, every range offset is just a position in
17415
+ // `code` — so the highlights can't drift out of sync with the source, and the
17416
+ // block's leading whitespace survives (HTML parsing would collapse it).
17417
+ function extractCodeAndHighlights(preElement) {
17237
17418
  const root = preElement.querySelector("code") || preElement;
17238
-
17239
- let offset = 0;
17419
+ const highlights = [];
17420
+ let code = "";
17240
17421
 
17241
17422
  function walk(node) {
17242
17423
  if (node.nodeType === Node.TEXT_NODE) {
17243
- offset += node.textContent.length;
17424
+ code += node.textContent;
17244
17425
  } else if (node.nodeType === Node.ELEMENT_NODE) {
17245
17426
  if (node.tagName === "BR") {
17246
- offset += 1;
17247
- return
17248
- }
17249
-
17250
- const isMark = node.tagName === "MARK";
17251
- const start = offset;
17252
-
17253
- for (const child of node.childNodes) {
17254
- walk(child);
17255
- }
17256
-
17257
- if (isMark) {
17427
+ code += "\n";
17428
+ } else if (node.tagName === "MARK") {
17429
+ const start = code.length;
17430
+ for (const child of node.childNodes) {
17431
+ walk(child);
17432
+ }
17258
17433
  const style = extractStyle(node);
17259
17434
  if (style) {
17260
- ranges.push({ start, end: offset, style });
17435
+ highlights.push({ start, end: code.length, style });
17436
+ }
17437
+ } else {
17438
+ for (const child of node.childNodes) {
17439
+ walk(child);
17261
17440
  }
17262
17441
  }
17263
17442
  }
@@ -17267,7 +17446,7 @@ function extractHighlightRanges(preElement) {
17267
17446
  walk(child);
17268
17447
  }
17269
17448
 
17270
- return ranges
17449
+ return { code, highlights }
17271
17450
  }
17272
17451
 
17273
17452
  function extractStyle(element) {
@@ -17436,5 +17615,5 @@ const configure = Lexxy.configure;
17436
17615
  // Pushing elements definition to after the current call stack to allow global configuration to take place first
17437
17616
  setTimeout(defineElements, 0);
17438
17617
 
17439
- export { $createActionTextAttachmentNode, $createActionTextAttachmentUploadNode, $isActionTextAttachmentNode, $isCustomActionTextAttachmentNode, ActionTextAttachmentNode, ActionTextAttachmentUploadNode, CustomActionTextAttachmentNode, LexxyExtension as Extension, HorizontalDividerNode, NativeAdapter, configure, highlightCode, highlightElement };
17618
+ export { $createActionTextAttachmentNode, $createActionTextAttachmentUploadNode, $isActionTextAttachmentNode, $isCustomActionTextAttachmentNode, ActionTextAttachmentNode, ActionTextAttachmentUploadNode, CustomActionTextAttachmentNode, LexxyExtension as Extension, HorizontalDividerNode, NativeAdapter, REWRITE_HISTORY_COMMAND, configure, highlightCode, highlightElement };
17440
17619
  //# sourceMappingURL=lexxy.js.map
Binary file
Binary file