lexxy 0.9.14.beta → 0.9.15.alpha.2
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 -32
- 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/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 86b63d9156e8846e2eaab83979bf9fc696eb37743e560cbe590f8d91f7448bd7
|
|
4
|
+
data.tar.gz: 375a9d775564689646650622857495a59239d65c2e1b6fd48e861f74abddcd84
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fff91b9c87fcabab97ae5375233a3819f5aa7097c913df32dea9dd914952451f889cb29c98888c1d6173c67ba3ae67732422952afc13812af25c81bec66e1afe
|
|
7
|
+
data.tar.gz: bbde40f03c4a7e950e99d0ac2e018b7e1c8251e0a53246bcffdde5a7141117ed860f9b22f2b75fb242a58ed8dbafe0992e24badb07d167028ac6925f1e03896a
|
|
@@ -7803,14 +7803,15 @@ function $isShadowRoot(node) {
|
|
|
7803
7803
|
return Wi(node) && Is(node) && !Vi(node)
|
|
7804
7804
|
}
|
|
7805
7805
|
|
|
7806
|
+
function $isSafeForRoot(node) {
|
|
7807
|
+
return (Wi(node) || ji(node)) && !node.isParentRequired()
|
|
7808
|
+
}
|
|
7809
|
+
|
|
7806
7810
|
function $makeSafeForRoot(node) {
|
|
7807
|
-
if (
|
|
7808
|
-
return Tt$4(node, eo)
|
|
7809
|
-
} else if (node.isParentRequired()) {
|
|
7810
|
-
const parent = node.createRequiredParent();
|
|
7811
|
-
return Tt$4(node, parent)
|
|
7812
|
-
} else {
|
|
7811
|
+
if ($isSafeForRoot(node)) {
|
|
7813
7812
|
return node
|
|
7813
|
+
} else {
|
|
7814
|
+
return Tt$4(node, () => node.createParentElementNode())
|
|
7814
7815
|
}
|
|
7815
7816
|
}
|
|
7816
7817
|
|
|
@@ -7925,6 +7926,39 @@ function $isListItemStructurallyEmpty(listItem) {
|
|
|
7925
7926
|
return true
|
|
7926
7927
|
}
|
|
7927
7928
|
|
|
7929
|
+
// Returns the document text up to `offset` inside `targetNode`. Non-inline
|
|
7930
|
+
// element siblings are joined with `\n\n`, matching Lexical's own
|
|
7931
|
+
// ElementNode.getTextContent behavior.
|
|
7932
|
+
function $textBeforeOffset(targetNode, offset) {
|
|
7933
|
+
const parts = [];
|
|
7934
|
+
let done = false;
|
|
7935
|
+
|
|
7936
|
+
function visit(node) {
|
|
7937
|
+
if (done) return
|
|
7938
|
+
if (node === targetNode) {
|
|
7939
|
+
parts.push(node.getTextContent().slice(0, offset));
|
|
7940
|
+
done = true;
|
|
7941
|
+
return
|
|
7942
|
+
}
|
|
7943
|
+
if (Wi(node)) {
|
|
7944
|
+
const children = node.getChildren();
|
|
7945
|
+
for (let i = 0; i < children.length; i++) {
|
|
7946
|
+
visit(children[i]);
|
|
7947
|
+
if (done) return
|
|
7948
|
+
const child = children[i];
|
|
7949
|
+
if (Wi(child) && !child.isInline() && i < children.length - 1) {
|
|
7950
|
+
parts.push("\n\n");
|
|
7951
|
+
}
|
|
7952
|
+
}
|
|
7953
|
+
} else {
|
|
7954
|
+
parts.push(node.getTextContent());
|
|
7955
|
+
}
|
|
7956
|
+
}
|
|
7957
|
+
|
|
7958
|
+
visit(Zo());
|
|
7959
|
+
return parts.join("")
|
|
7960
|
+
}
|
|
7961
|
+
|
|
7928
7962
|
function isAttachmentSpacerTextNode(node, previousNode, index, childCount) {
|
|
7929
7963
|
return Tr(node)
|
|
7930
7964
|
&& node.getTextContent() === " "
|
|
@@ -8210,6 +8244,11 @@ function safeCloneEditorState(editorState) {
|
|
|
8210
8244
|
return clone
|
|
8211
8245
|
}
|
|
8212
8246
|
|
|
8247
|
+
const INITIAL_PREVIEW_POLL_DELAY_MS = 3000;
|
|
8248
|
+
const MAX_PREVIEW_POLL_DELAY_MS = 120000;
|
|
8249
|
+
const MAX_PREVIEW_POLL_ATTEMPTS = 20;
|
|
8250
|
+
|
|
8251
|
+
|
|
8213
8252
|
class ActionTextAttachmentNode extends Ji {
|
|
8214
8253
|
static getType() {
|
|
8215
8254
|
return "action_text_attachment"
|
|
@@ -8284,7 +8323,7 @@ class ActionTextAttachmentNode extends Ji {
|
|
|
8284
8323
|
return Lexxy.global.get("attachmentTagName")
|
|
8285
8324
|
}
|
|
8286
8325
|
|
|
8287
|
-
constructor({ tagName, sgid, src, previewSrc, previewable, pendingPreview, altText, caption, contentType, fileName, fileSize, width, height, uploadError }, key) {
|
|
8326
|
+
constructor({ tagName, sgid, src, previewSrc, previewable, previewStatusUrl, pendingPreview, altText, caption, contentType, fileName, fileSize, width, height, uploadError }, key) {
|
|
8288
8327
|
super(key);
|
|
8289
8328
|
|
|
8290
8329
|
this.tagName = tagName || ActionTextAttachmentNode.TAG_NAME;
|
|
@@ -8292,6 +8331,7 @@ class ActionTextAttachmentNode extends Ji {
|
|
|
8292
8331
|
this.src = src;
|
|
8293
8332
|
this.previewSrc = previewSrc;
|
|
8294
8333
|
this.previewable = parseBoolean(previewable);
|
|
8334
|
+
this.previewStatusUrl = previewStatusUrl;
|
|
8295
8335
|
this.pendingPreview = pendingPreview;
|
|
8296
8336
|
this.altText = altText || "";
|
|
8297
8337
|
this.caption = caption || "";
|
|
@@ -8370,6 +8410,8 @@ class ActionTextAttachmentNode extends Ji {
|
|
|
8370
8410
|
sgid: this.sgid,
|
|
8371
8411
|
src: this.src,
|
|
8372
8412
|
previewable: this.previewable,
|
|
8413
|
+
previewStatusUrl: this.previewStatusUrl,
|
|
8414
|
+
pendingPreview: this.pendingPreview,
|
|
8373
8415
|
altText: this.altText,
|
|
8374
8416
|
caption: this.caption,
|
|
8375
8417
|
contentType: this.contentType,
|
|
@@ -8488,41 +8530,61 @@ class ActionTextAttachmentNode extends Ji {
|
|
|
8488
8530
|
});
|
|
8489
8531
|
}
|
|
8490
8532
|
|
|
8533
|
+
// While the file-icon is shown, watch for the preview to become ready.
|
|
8534
|
+
// With a status URL, poll it (2xx = processing, anything else = ready).
|
|
8535
|
+
// Without one, preload the preview URL once and swap on load.
|
|
8491
8536
|
#pollForPreview(figure) {
|
|
8537
|
+
if (this.previewStatusUrl) {
|
|
8538
|
+
this.#waitForPreviewByPollingStatus(figure);
|
|
8539
|
+
} else {
|
|
8540
|
+
this.#waitForPreviewByPreloadingImage(figure);
|
|
8541
|
+
}
|
|
8542
|
+
}
|
|
8543
|
+
|
|
8544
|
+
#waitForPreviewByPollingStatus(figure) {
|
|
8492
8545
|
let attempt = 0;
|
|
8493
|
-
const maxAttempts = 10;
|
|
8494
8546
|
|
|
8495
|
-
const
|
|
8547
|
+
const tryStatus = async () => {
|
|
8496
8548
|
if (!this.editor.read(() => this.isAttached())) return
|
|
8497
8549
|
|
|
8498
|
-
|
|
8499
|
-
|
|
8550
|
+
try {
|
|
8551
|
+
// redirect: "manual" prevents fetch from transparently following a
|
|
8552
|
+
// 3xx response — without it, a status endpoint that redirected to,
|
|
8553
|
+
// say, the preview URL would resolve to a 200 and look like
|
|
8554
|
+
// "still processing." The contract is "any non-2xx means done."
|
|
8555
|
+
const response = await fetch(this.previewStatusUrl, { credentials: "include", redirect: "manual" });
|
|
8500
8556
|
|
|
8501
|
-
img.onload = () => {
|
|
8502
8557
|
if (!this.editor.read(() => this.isAttached())) return
|
|
8503
8558
|
|
|
8504
|
-
|
|
8505
|
-
// generated from PDF/video content is significantly larger.
|
|
8506
|
-
if (img.naturalWidth > 150 && img.naturalHeight > 150) {
|
|
8507
|
-
this.#swapToPreviewDOM(figure, cacheBustedSrc);
|
|
8508
|
-
} else {
|
|
8559
|
+
if (response.ok) {
|
|
8509
8560
|
retry();
|
|
8561
|
+
} else {
|
|
8562
|
+
this.#swapToPreviewDOM(figure, this.src);
|
|
8510
8563
|
}
|
|
8511
|
-
}
|
|
8512
|
-
|
|
8513
|
-
|
|
8564
|
+
} catch {
|
|
8565
|
+
retry();
|
|
8566
|
+
}
|
|
8514
8567
|
};
|
|
8515
8568
|
|
|
8516
8569
|
const retry = () => {
|
|
8517
8570
|
attempt++;
|
|
8518
|
-
if (attempt <
|
|
8519
|
-
const delay = Math.min(2000 * Math.pow(1.5, attempt),
|
|
8520
|
-
setTimeout(
|
|
8571
|
+
if (attempt < MAX_PREVIEW_POLL_ATTEMPTS && this.editor.read(() => this.isAttached())) {
|
|
8572
|
+
const delay = Math.min(2000 * Math.pow(1.5, attempt), MAX_PREVIEW_POLL_DELAY_MS);
|
|
8573
|
+
setTimeout(tryStatus, delay);
|
|
8521
8574
|
}
|
|
8522
8575
|
};
|
|
8523
8576
|
|
|
8524
8577
|
// Give the server time to start processing before the first attempt
|
|
8525
|
-
setTimeout(
|
|
8578
|
+
setTimeout(tryStatus, INITIAL_PREVIEW_POLL_DELAY_MS);
|
|
8579
|
+
}
|
|
8580
|
+
|
|
8581
|
+
#waitForPreviewByPreloadingImage(figure) {
|
|
8582
|
+
const img = new Image();
|
|
8583
|
+
img.onload = () => {
|
|
8584
|
+
if (!this.editor.read(() => this.isAttached())) return
|
|
8585
|
+
this.#swapToPreviewDOM(figure, this.src);
|
|
8586
|
+
};
|
|
8587
|
+
img.src = this.src;
|
|
8526
8588
|
}
|
|
8527
8589
|
|
|
8528
8590
|
#swapToPreviewDOM(figure, previewSrc) {
|
|
@@ -11151,7 +11213,7 @@ class ImageGalleryNode extends Bi {
|
|
|
11151
11213
|
replaceWithSingularChild() {
|
|
11152
11214
|
if (this.#hasSingularChild) {
|
|
11153
11215
|
const child = this.getFirstChild();
|
|
11154
|
-
return this.replace(child)
|
|
11216
|
+
return this.replace($makeSafeForRoot(child))
|
|
11155
11217
|
}
|
|
11156
11218
|
}
|
|
11157
11219
|
|
|
@@ -11579,6 +11641,7 @@ class AttachmentNodeConversion {
|
|
|
11579
11641
|
fileName: blob.filename,
|
|
11580
11642
|
fileSize: blob.byte_size,
|
|
11581
11643
|
previewable: blob.previewable,
|
|
11644
|
+
previewStatusUrl: blob.preview_status_url
|
|
11582
11645
|
}
|
|
11583
11646
|
}
|
|
11584
11647
|
|
|
@@ -14950,6 +15013,9 @@ class RemoteFilterSource extends BaseSource {
|
|
|
14950
15013
|
const NOTHING_FOUND_DEFAULT_MESSAGE = "Nothing found";
|
|
14951
15014
|
const FILTER_DEBOUNCE_INTERVAL = 50;
|
|
14952
15015
|
|
|
15016
|
+
// Start of line, or after a space or newline.
|
|
15017
|
+
const DEFAULT_ONLY_AT_PATTERN = "^|[ \\n]";
|
|
15018
|
+
|
|
14953
15019
|
class LexicalPromptElement extends HTMLElement {
|
|
14954
15020
|
#globalListeners = new ListenerBin()
|
|
14955
15021
|
#popoverListeners = new ListenerBin()
|
|
@@ -14995,6 +15061,10 @@ class LexicalPromptElement extends HTMLElement {
|
|
|
14995
15061
|
return this.hasAttribute("supports-space-in-searches")
|
|
14996
15062
|
}
|
|
14997
15063
|
|
|
15064
|
+
get onlyAt() {
|
|
15065
|
+
return this.getAttribute("only-at")
|
|
15066
|
+
}
|
|
15067
|
+
|
|
14998
15068
|
get open() {
|
|
14999
15069
|
return this.popoverElement?.classList?.contains("lexxy-prompt-menu--visible")
|
|
15000
15070
|
}
|
|
@@ -15038,14 +15108,10 @@ class LexicalPromptElement extends HTMLElement {
|
|
|
15038
15108
|
if (offset >= triggerLength) {
|
|
15039
15109
|
const textBeforeCursor = fullText.slice(offset - triggerLength, offset);
|
|
15040
15110
|
|
|
15041
|
-
// Check if trigger is at the start of the text node (new line case) or preceded by space or newline
|
|
15042
15111
|
if (textBeforeCursor === this.trigger) {
|
|
15043
|
-
const
|
|
15112
|
+
const textBeforeTrigger = $textBeforeOffset(node, offset - triggerLength);
|
|
15044
15113
|
|
|
15045
|
-
|
|
15046
|
-
const isPrecededBySpaceOrNewline = charBeforeTrigger === " " || charBeforeTrigger === "\n";
|
|
15047
|
-
|
|
15048
|
-
if (isAtStart || isPrecededBySpaceOrNewline) {
|
|
15114
|
+
if (this.#onlyAtRegExp.test(textBeforeTrigger)) {
|
|
15049
15115
|
this.#popoverListeners.dispose();
|
|
15050
15116
|
this.#showPopover();
|
|
15051
15117
|
}
|
|
@@ -15056,7 +15122,15 @@ class LexicalPromptElement extends HTMLElement {
|
|
|
15056
15122
|
}));
|
|
15057
15123
|
}
|
|
15058
15124
|
|
|
15125
|
+
get #onlyAtRegExp() {
|
|
15126
|
+
return new RegExp(`(?:${this.onlyAt ?? DEFAULT_ONLY_AT_PATTERN})$`)
|
|
15127
|
+
}
|
|
15128
|
+
|
|
15059
15129
|
get #promptContentTypePermitted() {
|
|
15130
|
+
// `insert-editable-text` prompts never create attachments, so the
|
|
15131
|
+
// editor's attachment support and content-type allowlist don't apply.
|
|
15132
|
+
if (this.hasAttribute("insert-editable-text")) return true
|
|
15133
|
+
|
|
15060
15134
|
const el = this.#editorElement;
|
|
15061
15135
|
if (!el.supportsAttachments) {
|
|
15062
15136
|
return false
|
|
@@ -15219,7 +15293,7 @@ class LexicalPromptElement extends HTMLElement {
|
|
|
15219
15293
|
|
|
15220
15294
|
const popoverRect = this.popoverElement.getBoundingClientRect();
|
|
15221
15295
|
|
|
15222
|
-
if (popoverRect.right >
|
|
15296
|
+
if (popoverRect.right > editorRect.right) {
|
|
15223
15297
|
this.popoverElement.toggleAttribute("data-clipped-at-right", true);
|
|
15224
15298
|
}
|
|
15225
15299
|
|
|
Binary file
|
|
Binary file
|