lexxy 0.9.17 → 0.9.19.alpha.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.
- checksums.yaml +4 -4
- data/app/assets/javascript/lexxy.js +106 -22
- data/app/assets/javascript/lexxy.js.br +0 -0
- data/app/assets/javascript/lexxy.js.gz +0 -0
- data/app/assets/javascript/lexxy.js.map +1 -1
- data/app/assets/javascript/lexxy.min.js +1 -1
- data/app/assets/javascript/lexxy.min.js.br +0 -0
- data/app/assets/javascript/lexxy.min.js.gz +0 -0
- data/lib/lexxy/engine.rb +1 -1
- data/lib/lexxy/version.rb +1 -1
- metadata +1 -9
- data/app/assets/javascript/bundle-stats.html +0 -2
- data/app/assets/javascript/lexical.js +0 -4218
- data/app/assets/javascript/lexical.js.br +0 -0
- data/app/assets/javascript/lexical.js.gz +0 -0
- data/app/assets/javascript/lexical.js.map +0 -1
- data/app/assets/javascript/lexical.min.js +0 -9
- data/app/assets/javascript/lexical.min.js.br +0 -0
- data/app/assets/javascript/lexical.min.js.gz +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f6b15ddc26ce7b82fd871ed3f5dfa96598b84278da3af81c7c8e7ed1c7d8135b
|
|
4
|
+
data.tar.gz: eedb6f7b9cca87c16c1737c6db392b2fb8a38f560ca20f3c615dbd865afafbfc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6945b89f20390bc1f407d95de1f365ef97508b8e7c8ac4c8960d48df6a8d53e39cfcc39795988e8e4e77b37d2d4e60819ffc0faf0a8f1035b3acedaede71d978
|
|
7
|
+
data.tar.gz: 791d8ac7ffebbe6987fc70571bb04450e17e93571f89bd10abdcbf7586b0b3deed48208a0e035b66eceeb5cb42db373399894b2aead182c19139ab3cc0f11d5b
|
|
@@ -10357,9 +10357,12 @@ class Selection {
|
|
|
10357
10357
|
}
|
|
10358
10358
|
|
|
10359
10359
|
get isOnPreviewableImage() {
|
|
10360
|
-
|
|
10361
|
-
|
|
10362
|
-
|
|
10360
|
+
return this.previewableImageNode != null
|
|
10361
|
+
}
|
|
10362
|
+
|
|
10363
|
+
get previewableImageNode() {
|
|
10364
|
+
const firstNode = Qr()?.getNodes().at(0);
|
|
10365
|
+
return $isActionTextAttachmentNode(firstNode) && firstNode.isPreviewableImage ? firstNode : null
|
|
10363
10366
|
}
|
|
10364
10367
|
|
|
10365
10368
|
get isAtNodeStart() {
|
|
@@ -11334,7 +11337,10 @@ class GalleryUploader extends Uploader {
|
|
|
11334
11337
|
|
|
11335
11338
|
#findOrCreateGallery() {
|
|
11336
11339
|
if (this.selection.isOnPreviewableImage) {
|
|
11337
|
-
|
|
11340
|
+
// Resolve from the previewable image itself (the selection's first node), not from
|
|
11341
|
+
// #selectedNode (the anchor) — those differ when the selection runs from an image
|
|
11342
|
+
// into following text, and the anchor text node can't join a gallery (returns null).
|
|
11343
|
+
this.#gallery = $findOrCreateGalleryForImage(this.selection.previewableImageNode);
|
|
11338
11344
|
} else if (this.#selectionIsAfterGalleryEdge) {
|
|
11339
11345
|
this.#gallery = $findOrCreateGalleryForImage(this.selection.nodeBeforeCursor);
|
|
11340
11346
|
} else {
|
|
@@ -11671,7 +11677,8 @@ class NodeInserter {
|
|
|
11671
11677
|
const INSERTERS = [
|
|
11672
11678
|
CodeNodeInserter,
|
|
11673
11679
|
ShadowRootNodeInserter,
|
|
11674
|
-
NodeSelectionNodeInserter
|
|
11680
|
+
NodeSelectionNodeInserter,
|
|
11681
|
+
BlockContainerNodeInserter
|
|
11675
11682
|
];
|
|
11676
11683
|
const Inserter = INSERTERS.find(inserter => inserter.handles(selection));
|
|
11677
11684
|
return Inserter ? new Inserter(selection) : selection
|
|
@@ -11697,14 +11704,40 @@ class CodeNodeInserter extends NodeInserter {
|
|
|
11697
11704
|
|
|
11698
11705
|
const caret = lc(codeNode, insertionIndex + 1, "previous");
|
|
11699
11706
|
|
|
11707
|
+
// Nodes that are already in the document come from the format-toggle path (existing
|
|
11708
|
+
// content converted into this code block). Brand-new nodes (dropped/pasted content)
|
|
11709
|
+
// were never attached.
|
|
11710
|
+
const existingNodes = new Set(nodes.filter(node => node.isAttached()));
|
|
11711
|
+
const trailingNodes = [];
|
|
11712
|
+
|
|
11700
11713
|
for (const node of nodes) {
|
|
11701
|
-
if (
|
|
11702
|
-
|
|
11714
|
+
if (existingNodes.has(node)) {
|
|
11715
|
+
if (!node.isAttached()) continue // already pulled in when a converted ancestor was removed
|
|
11716
|
+
} else if (!this.#canJoinCodeBlock(node)) {
|
|
11717
|
+
trailingNodes.push(node); // e.g. a dropped attachment, which a code block can't hold
|
|
11718
|
+
continue
|
|
11719
|
+
}
|
|
11703
11720
|
|
|
11721
|
+
if (caret.getNodeAtCaret() && Wi(node)) { caret.insert(or()); }
|
|
11704
11722
|
caret.insert(this.#convertNodeToCodeChild(node));
|
|
11705
11723
|
}
|
|
11706
11724
|
|
|
11707
|
-
|
|
11725
|
+
const lastTrailingNode = this.#insertAfterCodeBlock(codeNode, trailingNodes);
|
|
11726
|
+
const nodeToSelect = lastTrailingNode ?? caret.getNodeAtCaret();
|
|
11727
|
+
nodeToSelect?.selectEnd();
|
|
11728
|
+
}
|
|
11729
|
+
|
|
11730
|
+
#canJoinCodeBlock(node) {
|
|
11731
|
+
return Tr(node) || sr(node)
|
|
11732
|
+
}
|
|
11733
|
+
|
|
11734
|
+
#insertAfterCodeBlock(codeNode, nodes) {
|
|
11735
|
+
let previousNode = codeNode;
|
|
11736
|
+
for (const node of nodes) {
|
|
11737
|
+
previousNode.insertAfter(node);
|
|
11738
|
+
previousNode = node;
|
|
11739
|
+
}
|
|
11740
|
+
return nodes.at(-1)
|
|
11708
11741
|
}
|
|
11709
11742
|
|
|
11710
11743
|
#convertNodeToCodeChild(node) {
|
|
@@ -11720,7 +11753,7 @@ class CodeNodeInserter extends NodeInserter {
|
|
|
11720
11753
|
|
|
11721
11754
|
class ShadowRootNodeInserter extends NodeInserter {
|
|
11722
11755
|
static handles(selection) {
|
|
11723
|
-
return $isShadowRoot(selection?.anchor
|
|
11756
|
+
return $isShadowRoot(selection?.anchor?.getNode())
|
|
11724
11757
|
}
|
|
11725
11758
|
|
|
11726
11759
|
insertNodes(nodes) {
|
|
@@ -11749,6 +11782,31 @@ class NodeSelectionNodeInserter extends NodeInserter {
|
|
|
11749
11782
|
}
|
|
11750
11783
|
}
|
|
11751
11784
|
|
|
11785
|
+
// Lexical's RangeSelection.insertNodes requires every selection point to have a block
|
|
11786
|
+
// ancestor with inline children. An element point on a container of block nodes — e.g.
|
|
11787
|
+
// a quote holding paragraphs — has none, so Lexical throws invariant #211 or #212.
|
|
11788
|
+
// Descend such points to a leaf position before inserting.
|
|
11789
|
+
class BlockContainerNodeInserter extends NodeInserter {
|
|
11790
|
+
static handles(selection) {
|
|
11791
|
+
return Fr(selection) &&
|
|
11792
|
+
[ selection.anchor, selection.focus ].some($isPointOnBlockContainer)
|
|
11793
|
+
}
|
|
11794
|
+
|
|
11795
|
+
insertNodes(nodes) {
|
|
11796
|
+
St$3(this.selection);
|
|
11797
|
+
this.selection.insertNodes(nodes);
|
|
11798
|
+
}
|
|
11799
|
+
}
|
|
11800
|
+
|
|
11801
|
+
function $isPointOnBlockContainer(point) {
|
|
11802
|
+
if (point.type === "element") {
|
|
11803
|
+
const firstChild = point.getNode().getFirstChild();
|
|
11804
|
+
return (Wi(firstChild) || ji(firstChild)) && !firstChild.isInline()
|
|
11805
|
+
} else {
|
|
11806
|
+
return false
|
|
11807
|
+
}
|
|
11808
|
+
}
|
|
11809
|
+
|
|
11752
11810
|
class Contents {
|
|
11753
11811
|
constructor(editorElement) {
|
|
11754
11812
|
this.editorElement = editorElement;
|
|
@@ -11845,7 +11903,7 @@ class Contents {
|
|
|
11845
11903
|
blockElements.forEach(node => this.#unwrapCodeBlock(node));
|
|
11846
11904
|
} else {
|
|
11847
11905
|
$expandSelectionToLineBreaksAndSplitAtEdges(selection);
|
|
11848
|
-
const elements = this.#blockLevelElementsInSelection(selection);
|
|
11906
|
+
const elements = this.#outermostElements(this.#blockLevelElementsInSelection(selection));
|
|
11849
11907
|
if (elements.length === 0) return
|
|
11850
11908
|
|
|
11851
11909
|
const codeNode = I$1("plain");
|
|
@@ -11981,6 +12039,8 @@ class Contents {
|
|
|
11981
12039
|
}
|
|
11982
12040
|
|
|
11983
12041
|
uploadFiles(files, { selectLast } = {}) {
|
|
12042
|
+
if (!this.editorElement) return // Disposed (e.g. on turbo:before-cache); a late drop can still land here
|
|
12043
|
+
|
|
11984
12044
|
if (!this.editorElement.supportsAttachments) {
|
|
11985
12045
|
console.warn("This editor does not supports attachments (it's configured with [attachments=false])");
|
|
11986
12046
|
return
|
|
@@ -12171,6 +12231,18 @@ class Contents {
|
|
|
12171
12231
|
return Array.from(elements)
|
|
12172
12232
|
}
|
|
12173
12233
|
|
|
12234
|
+
// Selections spanning nested structures (a quote and its inner paragraphs,
|
|
12235
|
+
// nested list items) yield both an element and its ancestor. Converting the
|
|
12236
|
+
// ancestor detaches its whole subtree — including a node freshly inserted
|
|
12237
|
+
// inside it — which can leave the selection on removed nodes (Lexical
|
|
12238
|
+
// invariant #19). The outermost elements already cover their descendants'
|
|
12239
|
+
// text content, so keep only those.
|
|
12240
|
+
#outermostElements(elements) {
|
|
12241
|
+
return elements.filter((element) => {
|
|
12242
|
+
return elements.every((other) => other === element || !element.getParents().includes(other))
|
|
12243
|
+
})
|
|
12244
|
+
}
|
|
12245
|
+
|
|
12174
12246
|
#insertUploadNodes(nodes) {
|
|
12175
12247
|
if (nodes.every($isActionTextAttachmentNode)) {
|
|
12176
12248
|
const uploader = Uploader.for(this.editorElement, []);
|
|
@@ -13770,12 +13842,23 @@ class EarlyEscapeListItemNode extends ge$2 {
|
|
|
13770
13842
|
return super.insertNewAfter(selection, restoreSelection)
|
|
13771
13843
|
}
|
|
13772
13844
|
|
|
13845
|
+
get #isInBlockquote() {
|
|
13846
|
+
return Boolean(At$2(this, At$1))
|
|
13847
|
+
}
|
|
13848
|
+
|
|
13773
13849
|
#shouldEscape(selection) {
|
|
13774
|
-
if (!
|
|
13775
|
-
|
|
13850
|
+
if (this.#isInPasteOperation() || !this.#isInBlockquote) {
|
|
13851
|
+
return false
|
|
13852
|
+
} else if ($isBlankNode(this)) {
|
|
13853
|
+
return true
|
|
13854
|
+
} else {
|
|
13855
|
+
const paragraph = At$2(selection.anchor.getNode(), Zi);
|
|
13856
|
+
return paragraph && $isBlankNode(paragraph) && pe$2(paragraph.getParent())
|
|
13857
|
+
}
|
|
13858
|
+
}
|
|
13776
13859
|
|
|
13777
|
-
|
|
13778
|
-
return
|
|
13860
|
+
#isInPasteOperation() {
|
|
13861
|
+
return Es(jn)
|
|
13779
13862
|
}
|
|
13780
13863
|
|
|
13781
13864
|
#escapeFromList() {
|
|
@@ -13823,7 +13906,7 @@ class FormatEscapeExtension extends LexxyExtension {
|
|
|
13823
13906
|
}
|
|
13824
13907
|
|
|
13825
13908
|
get allowedElements() {
|
|
13826
|
-
return [ { tag: "li", attributes: [ "value" ] } ]
|
|
13909
|
+
return [ { tag: "ol", attributes: [ "start" ] }, { tag: "li", attributes: [ "value" ] } ]
|
|
13827
13910
|
}
|
|
13828
13911
|
|
|
13829
13912
|
get lexicalExtension() {
|
|
@@ -14296,8 +14379,8 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
14296
14379
|
return this.#historyState.redo
|
|
14297
14380
|
}
|
|
14298
14381
|
|
|
14299
|
-
#readSanitizedEditorValue(
|
|
14300
|
-
return editor?.read(() => {
|
|
14382
|
+
#readSanitizedEditorValue() {
|
|
14383
|
+
return this.editor?.read(() => {
|
|
14301
14384
|
return sanitize(ht$1(this.editor, null))
|
|
14302
14385
|
}) ?? null
|
|
14303
14386
|
}
|
|
@@ -14331,7 +14414,6 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
14331
14414
|
}
|
|
14332
14415
|
|
|
14333
14416
|
#initialize() {
|
|
14334
|
-
this.#synchronizeWithChanges();
|
|
14335
14417
|
this.#registerComponents();
|
|
14336
14418
|
this.#handleEnter();
|
|
14337
14419
|
this.#registerFocusEvents();
|
|
@@ -14340,6 +14422,9 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
14340
14422
|
this.#attachDebugHooks();
|
|
14341
14423
|
this.#attachToolbar();
|
|
14342
14424
|
this.#resetBeforeTurboCaches();
|
|
14425
|
+
|
|
14426
|
+
this.#setInternalFormValue(this.value, { suppressEvent: true });
|
|
14427
|
+
this.#synchronizeWithChanges();
|
|
14343
14428
|
}
|
|
14344
14429
|
|
|
14345
14430
|
#registerFileAcceptFilter() {
|
|
@@ -14367,7 +14452,6 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
14367
14452
|
$initialEditorState: (editor) => {
|
|
14368
14453
|
this.#configureSanitizer(editor);
|
|
14369
14454
|
this.#loadInitialValue(editor);
|
|
14370
|
-
this.#setInternalFormValue(this.#readSanitizedEditorValue(editor));
|
|
14371
14455
|
},
|
|
14372
14456
|
},
|
|
14373
14457
|
...this.extensions.lexicalExtensions
|
|
@@ -14435,13 +14519,13 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
14435
14519
|
return Array.from(this.attributes).filter(attribute => attribute.name.startsWith("aria-"))
|
|
14436
14520
|
}
|
|
14437
14521
|
|
|
14438
|
-
#setInternalFormValue(html) {
|
|
14439
|
-
const changed =
|
|
14522
|
+
#setInternalFormValue(html, { suppressEvent = false } = {}) {
|
|
14523
|
+
const changed = html !== this.#previousInternalFormValue;
|
|
14440
14524
|
|
|
14441
14525
|
this.internals.setFormValue(html);
|
|
14442
14526
|
this.#previousInternalFormValue = html;
|
|
14443
14527
|
|
|
14444
|
-
if (changed) {
|
|
14528
|
+
if (changed && !suppressEvent) {
|
|
14445
14529
|
dispatch(this, "lexxy:change");
|
|
14446
14530
|
}
|
|
14447
14531
|
}
|
|
Binary file
|
|
Binary file
|