@sendbird/actionbook-core 0.10.5 → 0.10.7
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.
- package/dist/index.d.ts +2 -2
- package/dist/index.js +33 -6
- package/dist/index.js.map +1 -1
- package/dist/{types-DK_GhIWZ.d.ts → types-BQ95zx4j.d.ts} +1 -0
- package/dist/ui/index.d.ts +23 -2
- package/dist/ui/index.js +719 -263
- package/dist/ui/index.js.map +1 -1
- package/package.json +1 -1
package/dist/ui/index.js
CHANGED
|
@@ -55,7 +55,7 @@ var actionbookSchema = new Schema({
|
|
|
55
55
|
},
|
|
56
56
|
listItem: {
|
|
57
57
|
content: "block+",
|
|
58
|
-
attrs: { checked: { default: null } },
|
|
58
|
+
attrs: { checked: { default: null }, value: { default: null } },
|
|
59
59
|
parseDOM: [
|
|
60
60
|
{
|
|
61
61
|
tag: "li",
|
|
@@ -63,20 +63,25 @@ var actionbookSchema = new Schema({
|
|
|
63
63
|
const el = dom;
|
|
64
64
|
const checkbox = el.querySelector('input[type="checkbox"]');
|
|
65
65
|
if (checkbox) {
|
|
66
|
-
return { checked: checkbox.checked };
|
|
66
|
+
return { checked: checkbox.checked, value: el.value || null };
|
|
67
67
|
}
|
|
68
68
|
if (el.dataset.checked != null) {
|
|
69
|
-
return { checked: el.dataset.checked === "true" };
|
|
69
|
+
return { checked: el.dataset.checked === "true", value: el.value || null };
|
|
70
70
|
}
|
|
71
|
-
return { checked: null };
|
|
71
|
+
return { checked: null, value: el.value || null };
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
],
|
|
75
75
|
toDOM(node) {
|
|
76
|
+
const liAttrs = {};
|
|
76
77
|
if (node.attrs.checked != null) {
|
|
77
|
-
|
|
78
|
+
liAttrs.class = "todo-item";
|
|
79
|
+
liAttrs["data-checked"] = String(node.attrs.checked);
|
|
78
80
|
}
|
|
79
|
-
|
|
81
|
+
if (node.attrs.value != null) {
|
|
82
|
+
liAttrs.value = String(node.attrs.value);
|
|
83
|
+
}
|
|
84
|
+
return Object.keys(liAttrs).length > 0 ? ["li", liAttrs, 0] : ["li", 0];
|
|
80
85
|
},
|
|
81
86
|
defining: true
|
|
82
87
|
},
|
|
@@ -1250,7 +1255,7 @@ var RESOURCE_TAG_TYPES = ["tool", "manual", "agent_message_template", "handoff",
|
|
|
1250
1255
|
|
|
1251
1256
|
// src/compat/prosemirror.ts
|
|
1252
1257
|
var MAX_DEPTH = 128;
|
|
1253
|
-
var ALLOWED_URL_PROTOCOLS = /^(https?:|mailto:|tel
|
|
1258
|
+
var ALLOWED_URL_PROTOCOLS = /^(https?:|mailto:|tel:|#|\/|www\.)/i;
|
|
1254
1259
|
var LIST_TYPES = /* @__PURE__ */ new Set(["bulletList", "orderedList"]);
|
|
1255
1260
|
function isLooseList(items) {
|
|
1256
1261
|
return items.some((li) => {
|
|
@@ -1425,6 +1430,10 @@ function convertPMListItem(node, depth = 0) {
|
|
|
1425
1430
|
if (typeof checked === "boolean") {
|
|
1426
1431
|
base.checked = checked;
|
|
1427
1432
|
}
|
|
1433
|
+
const value = node.attrs?.value;
|
|
1434
|
+
if (value != null) {
|
|
1435
|
+
base.value = value;
|
|
1436
|
+
}
|
|
1428
1437
|
return base;
|
|
1429
1438
|
}
|
|
1430
1439
|
function fromProseMirrorJSON(pmJSON) {
|
|
@@ -2055,7 +2064,7 @@ function jumpPointToMarkdown() {
|
|
|
2055
2064
|
|
|
2056
2065
|
// src/markdown/mdastAdapter.ts
|
|
2057
2066
|
var MAX_DEPTH2 = 128;
|
|
2058
|
-
var ALLOWED_URL_PROTOCOLS2 = /^(https?:|mailto:|tel
|
|
2067
|
+
var ALLOWED_URL_PROTOCOLS2 = /^(https?:|mailto:|tel:|#|\/|www\.)/i;
|
|
2059
2068
|
function sanitizeUrl(url) {
|
|
2060
2069
|
if (ALLOWED_URL_PROTOCOLS2.test(url)) return url;
|
|
2061
2070
|
return "";
|
|
@@ -2320,13 +2329,21 @@ function blockToMdast(node, depth = 0) {
|
|
|
2320
2329
|
];
|
|
2321
2330
|
}
|
|
2322
2331
|
case "orderedList": {
|
|
2323
|
-
const
|
|
2332
|
+
const spread = node.spread ?? false;
|
|
2333
|
+
let counter = node.start;
|
|
2334
|
+
const items = node.content.map((li) => {
|
|
2335
|
+
const mdastLi = listItemToMdast(li, depth + 1);
|
|
2336
|
+
if (li.value != null) counter = li.value;
|
|
2337
|
+
mdastLi._ordinalValue = counter;
|
|
2338
|
+
counter++;
|
|
2339
|
+
return mdastLi;
|
|
2340
|
+
});
|
|
2324
2341
|
return [
|
|
2325
2342
|
{
|
|
2326
2343
|
type: "list",
|
|
2327
2344
|
ordered: true,
|
|
2328
|
-
start: node.start,
|
|
2329
|
-
spread
|
|
2345
|
+
start: node.content[0]?.value ?? node.start,
|
|
2346
|
+
spread,
|
|
2330
2347
|
children: items
|
|
2331
2348
|
}
|
|
2332
2349
|
];
|
|
@@ -2415,10 +2432,24 @@ function linkHandler(node, parent, state, info) {
|
|
|
2415
2432
|
const titlePart = title ? ` "${title.replace(/"/g, '\\"')}"` : "";
|
|
2416
2433
|
return `[${childrenText}](${url}${titlePart})`;
|
|
2417
2434
|
}
|
|
2435
|
+
function listItemHandler(node, parent, state, info) {
|
|
2436
|
+
const value = node._ordinalValue;
|
|
2437
|
+
if (value != null && parent && parent.ordered) {
|
|
2438
|
+
const list = parent;
|
|
2439
|
+
const savedStart = list.start;
|
|
2440
|
+
const idx = list.children.indexOf(node);
|
|
2441
|
+
list.start = value - idx;
|
|
2442
|
+
const result = defaultHandlers3.listItem(node, parent, state, info);
|
|
2443
|
+
list.start = savedStart;
|
|
2444
|
+
return result;
|
|
2445
|
+
}
|
|
2446
|
+
return defaultHandlers3.listItem(node, parent, state, info);
|
|
2447
|
+
}
|
|
2418
2448
|
function serializeToMarkdown(doc2) {
|
|
2419
2449
|
const mdastTree = toMdast(doc2);
|
|
2420
2450
|
const raw = toMarkdown(mdastTree, {
|
|
2421
2451
|
bullet: "-",
|
|
2452
|
+
bulletOrdered: ".",
|
|
2422
2453
|
rule: "-",
|
|
2423
2454
|
listItemIndent: "one",
|
|
2424
2455
|
incrementListMarker: true,
|
|
@@ -2434,6 +2465,7 @@ function serializeToMarkdown(doc2) {
|
|
|
2434
2465
|
handlers: {
|
|
2435
2466
|
text: textHandler,
|
|
2436
2467
|
link: linkHandler,
|
|
2468
|
+
listItem: listItemHandler,
|
|
2437
2469
|
...resourceTagToMarkdown().handlers,
|
|
2438
2470
|
...jumpPointToMarkdown().handlers
|
|
2439
2471
|
},
|
|
@@ -2444,7 +2476,7 @@ function serializeToMarkdown(doc2) {
|
|
|
2444
2476
|
}
|
|
2445
2477
|
|
|
2446
2478
|
// src/ui/bridge/toProseMirrorJSON.ts
|
|
2447
|
-
var ALLOWED_URL_PROTOCOLS3 = /^(https?:|mailto:|tel
|
|
2479
|
+
var ALLOWED_URL_PROTOCOLS3 = /^(https?:|mailto:|tel:|#|\/|www\.)/i;
|
|
2448
2480
|
function assertNever(value) {
|
|
2449
2481
|
throw new Error(`Unexpected AST node: ${JSON.stringify(value)}`);
|
|
2450
2482
|
}
|
|
@@ -2569,8 +2601,11 @@ function convertBlock2(node) {
|
|
|
2569
2601
|
type: "listItem",
|
|
2570
2602
|
content: node.content.flatMap(convertBlockToArray)
|
|
2571
2603
|
};
|
|
2572
|
-
if (node.checked != null) {
|
|
2573
|
-
result.attrs = {
|
|
2604
|
+
if (node.checked != null || node.value != null) {
|
|
2605
|
+
result.attrs = {
|
|
2606
|
+
...node.checked != null ? { checked: node.checked } : {},
|
|
2607
|
+
...node.value != null ? { value: node.value } : {}
|
|
2608
|
+
};
|
|
2574
2609
|
}
|
|
2575
2610
|
return result;
|
|
2576
2611
|
}
|
|
@@ -2627,7 +2662,184 @@ function astNodesToJSONContent(nodes) {
|
|
|
2627
2662
|
return nodes.flatMap(convertBlockToArray);
|
|
2628
2663
|
}
|
|
2629
2664
|
|
|
2665
|
+
// src/ui/styles/editorTextStyles.ts
|
|
2666
|
+
var EDITOR_TEXT_STYLES = `
|
|
2667
|
+
/* \u2500\u2500 CSS custom properties (override on .ProseMirror to customize) \u2500\u2500 */
|
|
2668
|
+
.ProseMirror {
|
|
2669
|
+
/* Font families */
|
|
2670
|
+
--ab-font-heading: 'Gellix', sans-serif;
|
|
2671
|
+
--ab-font-body: 'SF Pro Text', -apple-system, BlinkMacSystemFont, sans-serif;
|
|
2672
|
+
--ab-font-code: 'Roboto Mono', monospace;
|
|
2673
|
+
|
|
2674
|
+
/* Body text */
|
|
2675
|
+
--ab-body-size: 14px;
|
|
2676
|
+
--ab-body-weight: 400;
|
|
2677
|
+
--ab-body-line-height: 20px;
|
|
2678
|
+
--ab-body-letter-spacing: -0.1px;
|
|
2679
|
+
--ab-color-body: #0d0d0d;
|
|
2680
|
+
|
|
2681
|
+
/* H1 */
|
|
2682
|
+
--ab-h1-size: 24px;
|
|
2683
|
+
--ab-h1-weight: 700;
|
|
2684
|
+
--ab-h1-line-height: 32px;
|
|
2685
|
+
--ab-h1-letter-spacing: -0.25px;
|
|
2686
|
+
|
|
2687
|
+
/* H2 */
|
|
2688
|
+
--ab-h2-size: 20px;
|
|
2689
|
+
--ab-h2-weight: 700;
|
|
2690
|
+
--ab-h2-line-height: 24px;
|
|
2691
|
+
--ab-h2-letter-spacing: -0.25px;
|
|
2692
|
+
|
|
2693
|
+
/* H3 */
|
|
2694
|
+
--ab-h3-size: 18px;
|
|
2695
|
+
--ab-h3-weight: 700;
|
|
2696
|
+
--ab-h3-line-height: 24px;
|
|
2697
|
+
--ab-h3-letter-spacing: -0.25px;
|
|
2698
|
+
|
|
2699
|
+
/* Inline code */
|
|
2700
|
+
--ab-code-size: 13px;
|
|
2701
|
+
--ab-code-weight: 400;
|
|
2702
|
+
--ab-code-line-height: 20px;
|
|
2703
|
+
--ab-code-letter-spacing: -0.3px;
|
|
2704
|
+
--ab-code-bg: #ececec;
|
|
2705
|
+
--ab-code-padding: 0 8px;
|
|
2706
|
+
--ab-code-radius: 2px;
|
|
2707
|
+
|
|
2708
|
+
/* Code block */
|
|
2709
|
+
--ab-pre-bg: #ececec;
|
|
2710
|
+
--ab-pre-radius: 4px;
|
|
2711
|
+
--ab-pre-padding: 16px 8px 16px 24px;
|
|
2712
|
+
|
|
2713
|
+
/* Link */
|
|
2714
|
+
--ab-link-color: #6210cc;
|
|
2715
|
+
--ab-link-weight: 500;
|
|
2716
|
+
|
|
2717
|
+
/* Blockquote */
|
|
2718
|
+
--ab-blockquote-border-color: #0d0d0d;
|
|
2719
|
+
|
|
2720
|
+
/* HR */
|
|
2721
|
+
--ab-hr-color: #e0e0e0;
|
|
2722
|
+
|
|
2723
|
+
/* Block spacing */
|
|
2724
|
+
--ab-block-gap: 16px;
|
|
2725
|
+
}
|
|
2726
|
+
|
|
2727
|
+
/* \u2500\u2500 Base text \u2500\u2500 */
|
|
2728
|
+
.ProseMirror {
|
|
2729
|
+
font-family: var(--ab-font-body);
|
|
2730
|
+
font-size: var(--ab-body-size);
|
|
2731
|
+
font-weight: var(--ab-body-weight);
|
|
2732
|
+
line-height: var(--ab-body-line-height);
|
|
2733
|
+
letter-spacing: var(--ab-body-letter-spacing);
|
|
2734
|
+
color: var(--ab-color-body);
|
|
2735
|
+
}
|
|
2736
|
+
|
|
2737
|
+
.ProseMirror > * + * {
|
|
2738
|
+
margin-top: var(--ab-block-gap);
|
|
2739
|
+
}
|
|
2740
|
+
|
|
2741
|
+
/* \u2500\u2500 Headings \u2500\u2500 */
|
|
2742
|
+
.ProseMirror h1 {
|
|
2743
|
+
font-family: var(--ab-font-heading);
|
|
2744
|
+
font-size: var(--ab-h1-size);
|
|
2745
|
+
font-weight: var(--ab-h1-weight);
|
|
2746
|
+
line-height: var(--ab-h1-line-height);
|
|
2747
|
+
letter-spacing: var(--ab-h1-letter-spacing);
|
|
2748
|
+
}
|
|
2749
|
+
|
|
2750
|
+
.ProseMirror h2 {
|
|
2751
|
+
font-family: var(--ab-font-heading);
|
|
2752
|
+
font-size: var(--ab-h2-size);
|
|
2753
|
+
font-weight: var(--ab-h2-weight);
|
|
2754
|
+
line-height: var(--ab-h2-line-height);
|
|
2755
|
+
letter-spacing: var(--ab-h2-letter-spacing);
|
|
2756
|
+
}
|
|
2757
|
+
|
|
2758
|
+
.ProseMirror h3 {
|
|
2759
|
+
font-family: var(--ab-font-heading);
|
|
2760
|
+
font-size: var(--ab-h3-size);
|
|
2761
|
+
font-weight: var(--ab-h3-weight);
|
|
2762
|
+
line-height: var(--ab-h3-line-height);
|
|
2763
|
+
letter-spacing: var(--ab-h3-letter-spacing);
|
|
2764
|
+
}
|
|
2765
|
+
|
|
2766
|
+
/* \u2500\u2500 Inline code \u2500\u2500 */
|
|
2767
|
+
.ProseMirror code {
|
|
2768
|
+
font-family: var(--ab-font-code);
|
|
2769
|
+
font-size: var(--ab-code-size);
|
|
2770
|
+
font-weight: var(--ab-code-weight);
|
|
2771
|
+
line-height: var(--ab-code-line-height);
|
|
2772
|
+
letter-spacing: var(--ab-code-letter-spacing);
|
|
2773
|
+
background: var(--ab-code-bg);
|
|
2774
|
+
padding: var(--ab-code-padding);
|
|
2775
|
+
border-radius: var(--ab-code-radius);
|
|
2776
|
+
}
|
|
2777
|
+
|
|
2778
|
+
/* \u2500\u2500 Code block \u2500\u2500 */
|
|
2779
|
+
.ProseMirror pre {
|
|
2780
|
+
font-family: var(--ab-font-code);
|
|
2781
|
+
font-size: var(--ab-code-size);
|
|
2782
|
+
font-weight: var(--ab-code-weight);
|
|
2783
|
+
line-height: var(--ab-code-line-height);
|
|
2784
|
+
letter-spacing: var(--ab-code-letter-spacing);
|
|
2785
|
+
color: var(--ab-color-body);
|
|
2786
|
+
background: var(--ab-pre-bg);
|
|
2787
|
+
border-radius: var(--ab-pre-radius);
|
|
2788
|
+
padding: var(--ab-pre-padding);
|
|
2789
|
+
overflow-x: auto;
|
|
2790
|
+
white-space: pre;
|
|
2791
|
+
}
|
|
2792
|
+
|
|
2793
|
+
.ProseMirror pre code {
|
|
2794
|
+
background: transparent;
|
|
2795
|
+
padding: 0;
|
|
2796
|
+
border-radius: 0;
|
|
2797
|
+
font-size: inherit;
|
|
2798
|
+
}
|
|
2799
|
+
|
|
2800
|
+
/* \u2500\u2500 Link \u2500\u2500 */
|
|
2801
|
+
.ProseMirror a {
|
|
2802
|
+
color: var(--ab-link-color);
|
|
2803
|
+
font-weight: var(--ab-link-weight);
|
|
2804
|
+
text-decoration: none;
|
|
2805
|
+
}
|
|
2806
|
+
|
|
2807
|
+
.ProseMirror a:hover {
|
|
2808
|
+
text-decoration: none;
|
|
2809
|
+
}
|
|
2810
|
+
|
|
2811
|
+
/* \u2500\u2500 Blockquote \u2500\u2500 */
|
|
2812
|
+
.ProseMirror blockquote {
|
|
2813
|
+
border-left: 2px solid var(--ab-blockquote-border-color);
|
|
2814
|
+
border-radius: 0;
|
|
2815
|
+
padding-left: 20px;
|
|
2816
|
+
color: var(--ab-color-body);
|
|
2817
|
+
}
|
|
2818
|
+
|
|
2819
|
+
/* \u2500\u2500 HR \u2500\u2500 */
|
|
2820
|
+
.ProseMirror hr {
|
|
2821
|
+
border: none;
|
|
2822
|
+
height: 1px;
|
|
2823
|
+
background: var(--ab-hr-color);
|
|
2824
|
+
margin: 8px 0;
|
|
2825
|
+
}
|
|
2826
|
+
`;
|
|
2827
|
+
|
|
2630
2828
|
// src/ui/hooks/useEditorView.ts
|
|
2829
|
+
var TEXT_STYLE_ID = "ab-editor-text-styles";
|
|
2830
|
+
var textStyleRefCount = 0;
|
|
2831
|
+
function acquireTextStyles() {
|
|
2832
|
+
if (textStyleRefCount++ > 0) return;
|
|
2833
|
+
if (document.getElementById(TEXT_STYLE_ID)) return;
|
|
2834
|
+
const el = document.createElement("style");
|
|
2835
|
+
el.id = TEXT_STYLE_ID;
|
|
2836
|
+
el.textContent = EDITOR_TEXT_STYLES;
|
|
2837
|
+
document.head.appendChild(el);
|
|
2838
|
+
}
|
|
2839
|
+
function releaseTextStyles() {
|
|
2840
|
+
if (--textStyleRefCount > 0) return;
|
|
2841
|
+
document.getElementById(TEXT_STYLE_ID)?.remove();
|
|
2842
|
+
}
|
|
2631
2843
|
function docToState(doc2, plugins) {
|
|
2632
2844
|
const pmJSON = doc2 ? toProseMirrorJSON(doc2) : { type: "doc", content: [{ type: "paragraph" }] };
|
|
2633
2845
|
const pmDoc = PMNode.fromJSON(actionbookSchema, pmJSON);
|
|
@@ -2666,17 +2878,20 @@ function useEditorView(config) {
|
|
|
2666
2878
|
if (viewInstanceRef.current) {
|
|
2667
2879
|
viewInstanceRef.current.destroy();
|
|
2668
2880
|
viewInstanceRef.current = null;
|
|
2881
|
+
releaseTextStyles();
|
|
2669
2882
|
}
|
|
2670
2883
|
containerRef.current = container;
|
|
2671
2884
|
if (!container) {
|
|
2672
2885
|
forceUpdate((n) => n + 1);
|
|
2673
2886
|
return;
|
|
2674
2887
|
}
|
|
2888
|
+
acquireTextStyles();
|
|
2675
2889
|
const { pmPlugins, nodeViews } = createPluginArray(configRef.current.plugins ?? []);
|
|
2676
2890
|
const state = docToState(configRef.current.content, pmPlugins);
|
|
2677
2891
|
const view = new EditorView(container, {
|
|
2678
2892
|
state,
|
|
2679
2893
|
nodeViews,
|
|
2894
|
+
attributes: { spellcheck: "false" },
|
|
2680
2895
|
editable: () => configRef.current.editable === true,
|
|
2681
2896
|
dispatchTransaction(tr) {
|
|
2682
2897
|
const newState = view.state.apply(tr);
|
|
@@ -2714,8 +2929,11 @@ function useEditorView(config) {
|
|
|
2714
2929
|
viewInstanceRef.current?.focus();
|
|
2715
2930
|
}, []);
|
|
2716
2931
|
const destroy = useCallback(() => {
|
|
2717
|
-
viewInstanceRef.current
|
|
2718
|
-
|
|
2932
|
+
if (viewInstanceRef.current) {
|
|
2933
|
+
viewInstanceRef.current.destroy();
|
|
2934
|
+
viewInstanceRef.current = null;
|
|
2935
|
+
releaseTextStyles();
|
|
2936
|
+
}
|
|
2719
2937
|
}, []);
|
|
2720
2938
|
const getView = useCallback(() => viewInstanceRef.current, []);
|
|
2721
2939
|
return {
|
|
@@ -2736,6 +2954,7 @@ import { TextSelection } from "prosemirror-state";
|
|
|
2736
2954
|
|
|
2737
2955
|
// src/ui/plugin/slashCommandPlugin.ts
|
|
2738
2956
|
import { Plugin, PluginKey } from "prosemirror-state";
|
|
2957
|
+
import { Decoration, DecorationSet } from "prosemirror-view";
|
|
2739
2958
|
var slashCommandKey = new PluginKey("slashCommand");
|
|
2740
2959
|
var TRIGGER_RE = /(?:^|\s)(\/[^\s]*)$/;
|
|
2741
2960
|
function deriveState(state, dismissedFrom) {
|
|
@@ -2784,9 +3003,30 @@ function createSlashCommandPlugin() {
|
|
|
2784
3003
|
const derived = deriveState(newState, dismissedFrom);
|
|
2785
3004
|
return { ...derived, _dismissedFrom: dismissedFrom };
|
|
2786
3005
|
}
|
|
3006
|
+
},
|
|
3007
|
+
props: {
|
|
3008
|
+
decorations(state) {
|
|
3009
|
+
const s = plugin.getState(state);
|
|
3010
|
+
if (!s?.active || !s.range) return DecorationSet.empty;
|
|
3011
|
+
const decos = [
|
|
3012
|
+
// Inline highlight for the slash command text
|
|
3013
|
+
Decoration.inline(s.range.from, s.range.to, {
|
|
3014
|
+
class: "ab-slash-trigger"
|
|
3015
|
+
})
|
|
3016
|
+
];
|
|
3017
|
+
if (s.query.endsWith(":")) {
|
|
3018
|
+
decos.push(
|
|
3019
|
+
Decoration.widget(s.range.to, () => {
|
|
3020
|
+
const span = document.createElement("span");
|
|
3021
|
+
span.className = "ab-slash-trigger-placeholder";
|
|
3022
|
+
span.textContent = "Type a name";
|
|
3023
|
+
return span;
|
|
3024
|
+
}, { side: 1 })
|
|
3025
|
+
);
|
|
3026
|
+
}
|
|
3027
|
+
return DecorationSet.create(state.doc, decos);
|
|
3028
|
+
}
|
|
2787
3029
|
}
|
|
2788
|
-
// Expose only the public fields via the key
|
|
2789
|
-
// (InternalState is a superset of SlashCommandState so reads work fine)
|
|
2790
3030
|
});
|
|
2791
3031
|
return {
|
|
2792
3032
|
name: "slashCommand",
|
|
@@ -2814,23 +3054,28 @@ var HR_RE = /^([-*_])\1{2,}$/;
|
|
|
2814
3054
|
var BULLET_LIST_RE = /^\s*([-*])\s$/;
|
|
2815
3055
|
var ORDERED_LIST_RE = /^(\d+)\.\s$/;
|
|
2816
3056
|
var JUMP_POINT_RE2 = /\^([\p{L}\p{N}_-]+)\^$/u;
|
|
2817
|
-
var
|
|
2818
|
-
var
|
|
2819
|
-
var ITALIC_STAR_RE = /(?:^|[^*])\*([^*]+)\*$/;
|
|
2820
|
-
var ITALIC_UNDER_RE = /(?:^|[^_])_([^_]+)_$/;
|
|
3057
|
+
var BOLD_RE = /(?:^|[^*])\*\*([^*]+)\*\*$/;
|
|
3058
|
+
var ITALIC_RE = /(?:^|[^_])__([^_]+)__$/;
|
|
2821
3059
|
var STRIKE_RE = /(?:^|[^~])~~([^~]+)~~$/;
|
|
2822
3060
|
var CODE_RE = /(?:^|[^`])`([^`]+)`$/;
|
|
2823
3061
|
function findParentList(state, pos) {
|
|
2824
3062
|
const $pos = state.doc.resolve(pos);
|
|
2825
|
-
const { bulletList: blType, orderedList: olType } = actionbookSchema.nodes;
|
|
2826
3063
|
for (let d = $pos.depth; d > 0; d--) {
|
|
2827
3064
|
const node = $pos.node(d);
|
|
2828
|
-
|
|
3065
|
+
const name = node.type.name;
|
|
3066
|
+
if (name === "bulletList" || name === "orderedList") {
|
|
2829
3067
|
return { depth: d, node };
|
|
2830
3068
|
}
|
|
2831
3069
|
}
|
|
2832
3070
|
return null;
|
|
2833
3071
|
}
|
|
3072
|
+
function isInsideList(state, pos) {
|
|
3073
|
+
const $pos = state.doc.resolve(pos);
|
|
3074
|
+
for (let d = $pos.depth; d > 0; d--) {
|
|
3075
|
+
if ($pos.node(d).type.name === "listItem") return true;
|
|
3076
|
+
}
|
|
3077
|
+
return false;
|
|
3078
|
+
}
|
|
2834
3079
|
var NOOP = /* @__PURE__ */ Symbol("noop");
|
|
2835
3080
|
function handleListInputRule(state, start, end, listType, attrs) {
|
|
2836
3081
|
const resolvePos = Math.max(start, end - 1);
|
|
@@ -2841,27 +3086,46 @@ function handleListInputRule(state, start, end, listType, attrs) {
|
|
|
2841
3086
|
const paraContentSize = $from.parent.content.size;
|
|
2842
3087
|
const matchedLen = end - start;
|
|
2843
3088
|
const isMarkerOnly = paraContentSize === matchedLen;
|
|
2844
|
-
if (listNode.type === listType) {
|
|
2845
|
-
if (
|
|
2846
|
-
const
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
3089
|
+
if (listNode.type.name === listType.name) {
|
|
3090
|
+
if (listType.name === "orderedList" && attrs?.start != null) {
|
|
3091
|
+
const newValue = attrs.start;
|
|
3092
|
+
let liDepth2 = -1;
|
|
3093
|
+
for (let d = $from.depth; d > 0; d--) {
|
|
3094
|
+
if ($from.node(d).type.name === "listItem") {
|
|
3095
|
+
liDepth2 = d;
|
|
3096
|
+
break;
|
|
3097
|
+
}
|
|
3098
|
+
}
|
|
3099
|
+
if (liDepth2 > 0) {
|
|
3100
|
+
const liIndex2 = $from.index(listDepth);
|
|
3101
|
+
const listStartNum = listNode.attrs.start ?? 1;
|
|
3102
|
+
const naturalNumber = listStartNum + liIndex2;
|
|
3103
|
+
const currentValue = $from.node(liDepth2).attrs.value;
|
|
3104
|
+
if (currentValue === newValue || currentValue == null && newValue === naturalNumber) {
|
|
3105
|
+
const tr3 = state.tr.delete(start, end);
|
|
3106
|
+
tr3.setSelection(TextSelection.near(tr3.doc.resolve(tr3.mapping.map(start))));
|
|
3107
|
+
return tr3;
|
|
3108
|
+
}
|
|
2850
3109
|
const tr2 = state.tr.delete(start, end);
|
|
2851
|
-
tr2.
|
|
2852
|
-
|
|
2853
|
-
|
|
3110
|
+
const $afterDelete = tr2.doc.resolve(tr2.mapping.map(resolvePos));
|
|
3111
|
+
for (let d = $afterDelete.depth; d > 0; d--) {
|
|
3112
|
+
if ($afterDelete.node(d).type.name === "listItem") {
|
|
3113
|
+
const pos = $afterDelete.before(d);
|
|
3114
|
+
const node = $afterDelete.node(d);
|
|
3115
|
+
tr2.setNodeMarkup(pos, void 0, { ...node.attrs, value: newValue });
|
|
3116
|
+
tr2.setSelection(TextSelection.near(tr2.doc.resolve(tr2.mapping.map(start))));
|
|
3117
|
+
return tr2;
|
|
3118
|
+
}
|
|
3119
|
+
}
|
|
2854
3120
|
}
|
|
2855
3121
|
}
|
|
2856
3122
|
return NOOP;
|
|
2857
3123
|
}
|
|
2858
|
-
if (!isMarkerOnly) return NOOP;
|
|
2859
|
-
const { listItem: liType } = actionbookSchema.nodes;
|
|
2860
3124
|
const tr = state.tr.delete(start, end);
|
|
2861
3125
|
const $pos = tr.doc.resolve(tr.mapping.map(resolvePos));
|
|
2862
3126
|
let liDepth = -1;
|
|
2863
3127
|
for (let d = $pos.depth; d > 0; d--) {
|
|
2864
|
-
if ($pos.node(d).type ===
|
|
3128
|
+
if ($pos.node(d).type.name === "listItem") {
|
|
2865
3129
|
liDepth = d;
|
|
2866
3130
|
break;
|
|
2867
3131
|
}
|
|
@@ -2917,9 +3181,16 @@ function createInputRulesPlugin() {
|
|
|
2917
3181
|
level: match[1].length
|
|
2918
3182
|
}))
|
|
2919
3183
|
);
|
|
2920
|
-
rules.push(
|
|
3184
|
+
rules.push(
|
|
3185
|
+
new InputRule(BLOCKQUOTE_RE, (state, match, start, end) => {
|
|
3186
|
+
if (isInsideList(state, start)) return null;
|
|
3187
|
+
const fallback = wrappingInputRule(BLOCKQUOTE_RE, actionbookSchema.nodes.blockquote);
|
|
3188
|
+
return fallback.handler(state, match, start, end);
|
|
3189
|
+
})
|
|
3190
|
+
);
|
|
2921
3191
|
rules.push(
|
|
2922
3192
|
new InputRule(CODE_BLOCK_RE, (state, match, start, end) => {
|
|
3193
|
+
if (isInsideList(state, start)) return null;
|
|
2923
3194
|
const language = match[1] || null;
|
|
2924
3195
|
const $start = state.doc.resolve(start);
|
|
2925
3196
|
const blockStart = $start.before($start.depth);
|
|
@@ -2935,6 +3206,7 @@ function createInputRulesPlugin() {
|
|
|
2935
3206
|
);
|
|
2936
3207
|
rules.push(
|
|
2937
3208
|
new InputRule(HR_RE, (state, _match, start, end) => {
|
|
3209
|
+
if (isInsideList(state, start)) return null;
|
|
2938
3210
|
const { horizontalRule: hrType, paragraph: pType } = actionbookSchema.nodes;
|
|
2939
3211
|
const $start = state.doc.resolve(start);
|
|
2940
3212
|
const blockStart = $start.before($start.depth);
|
|
@@ -2974,9 +3246,29 @@ function createInputRulesPlugin() {
|
|
|
2974
3246
|
const fallback = wrappingInputRule(ORDERED_LIST_RE, olType, (m) => ({ start: +m[1] }));
|
|
2975
3247
|
rules.push(
|
|
2976
3248
|
new InputRule(ORDERED_LIST_RE, (state, match, start, end) => {
|
|
2977
|
-
const
|
|
2978
|
-
|
|
2979
|
-
|
|
3249
|
+
const typedNumber = +match[1];
|
|
3250
|
+
const resolvePos = Math.max(start, end - 1);
|
|
3251
|
+
const parentList = findParentList(state, resolvePos);
|
|
3252
|
+
if (parentList) {
|
|
3253
|
+
const { node: listNode } = parentList;
|
|
3254
|
+
if (listNode.type.name === "orderedList") {
|
|
3255
|
+
const tr = state.tr.delete(start, end);
|
|
3256
|
+
const $after = tr.doc.resolve(tr.mapping.map(resolvePos));
|
|
3257
|
+
for (let d = $after.depth; d > 0; d--) {
|
|
3258
|
+
if ($after.node(d).type.name === "listItem") {
|
|
3259
|
+
const liPos = $after.before(d);
|
|
3260
|
+
const liNode = $after.node(d);
|
|
3261
|
+
tr.setNodeMarkup(liPos, void 0, { ...liNode.attrs, value: typedNumber });
|
|
3262
|
+
tr.setSelection(TextSelection.near(tr.doc.resolve(tr.mapping.map(start))));
|
|
3263
|
+
return tr;
|
|
3264
|
+
}
|
|
3265
|
+
}
|
|
3266
|
+
return null;
|
|
3267
|
+
}
|
|
3268
|
+
const result = handleListInputRule(state, start, end, olType, { start: typedNumber });
|
|
3269
|
+
if (result === NOOP) return null;
|
|
3270
|
+
if (result) return result;
|
|
3271
|
+
}
|
|
2980
3272
|
const handler = fallback.handler;
|
|
2981
3273
|
return handler(state, match, start, end);
|
|
2982
3274
|
})
|
|
@@ -2994,10 +3286,8 @@ function createInputRulesPlugin() {
|
|
|
2994
3286
|
return tr;
|
|
2995
3287
|
})
|
|
2996
3288
|
);
|
|
2997
|
-
rules.push(markInputRule(
|
|
2998
|
-
rules.push(markInputRule(
|
|
2999
|
-
rules.push(markInputRule(ITALIC_STAR_RE, actionbookSchema.marks.italic, 1));
|
|
3000
|
-
rules.push(markInputRule(ITALIC_UNDER_RE, actionbookSchema.marks.italic, 1));
|
|
3289
|
+
rules.push(markInputRule(BOLD_RE, actionbookSchema.marks.bold, 2));
|
|
3290
|
+
rules.push(markInputRule(ITALIC_RE, actionbookSchema.marks.italic, 2));
|
|
3001
3291
|
rules.push(markInputRule(STRIKE_RE, actionbookSchema.marks.strikethrough, 2));
|
|
3002
3292
|
rules.push(markInputRule(CODE_RE, actionbookSchema.marks.code, 1));
|
|
3003
3293
|
return rules;
|
|
@@ -3020,7 +3310,7 @@ function createHistoryPlugin() {
|
|
|
3020
3310
|
|
|
3021
3311
|
// src/ui/plugin/keymapPlugin.ts
|
|
3022
3312
|
import { baseKeymap, chainCommands, newlineInCode, createParagraphNear, liftEmptyBlock, splitBlock, toggleMark, setBlockType, joinBackward } from "prosemirror-commands";
|
|
3023
|
-
import { Plugin as Plugin2, TextSelection as TextSelection2 } from "prosemirror-state";
|
|
3313
|
+
import { AllSelection, Plugin as Plugin2, TextSelection as TextSelection2 } from "prosemirror-state";
|
|
3024
3314
|
import { keymap as keymap3 } from "prosemirror-keymap";
|
|
3025
3315
|
import { liftListItem, sinkListItem, splitListItem, wrapInList } from "prosemirror-schema-list";
|
|
3026
3316
|
|
|
@@ -3417,6 +3707,19 @@ function createEmptyDocGuardPlugin() {
|
|
|
3417
3707
|
}
|
|
3418
3708
|
});
|
|
3419
3709
|
}
|
|
3710
|
+
var selectAllCommand = (state, dispatch) => {
|
|
3711
|
+
const { $from, from, to } = state.selection;
|
|
3712
|
+
const depth = Math.min($from.depth, 1);
|
|
3713
|
+
const blockStart = $from.start(depth);
|
|
3714
|
+
const blockEnd = $from.end(depth);
|
|
3715
|
+
const blockFullySelected = from <= blockStart && to >= blockEnd;
|
|
3716
|
+
if (blockFullySelected) {
|
|
3717
|
+
if (dispatch) dispatch(state.tr.setSelection(new AllSelection(state.doc)));
|
|
3718
|
+
return true;
|
|
3719
|
+
}
|
|
3720
|
+
if (dispatch) dispatch(state.tr.setSelection(TextSelection2.create(state.doc, blockStart, blockEnd)));
|
|
3721
|
+
return true;
|
|
3722
|
+
};
|
|
3420
3723
|
function createKeymapPlugin() {
|
|
3421
3724
|
return {
|
|
3422
3725
|
name: "keymapPlugin",
|
|
@@ -3426,10 +3729,11 @@ function createKeymapPlugin() {
|
|
|
3426
3729
|
"Shift-Tab": shiftTabCommand,
|
|
3427
3730
|
Enter: enterCommand,
|
|
3428
3731
|
"Shift-Enter": shiftEnterCommand,
|
|
3732
|
+
"Mod-a": selectAllCommand,
|
|
3429
3733
|
"Mod-b": toggleMark(boldMark),
|
|
3430
3734
|
"Mod-i": toggleMark(italicMark),
|
|
3431
3735
|
"Mod-u": toggleMark(underlineMark),
|
|
3432
|
-
"Mod-Shift-
|
|
3736
|
+
"Mod-Shift-s": toggleMark(strikethroughMark),
|
|
3433
3737
|
"Mod-e": toggleMark(codeMark),
|
|
3434
3738
|
"Mod-Shift-7": wrapInList(bulletList),
|
|
3435
3739
|
"Mod-Shift-8": wrapInList(orderedList)
|
|
@@ -5638,7 +5942,7 @@ function buildDocumentTree(doc2) {
|
|
|
5638
5942
|
|
|
5639
5943
|
// src/ui/plugin/markdownClipboard.ts
|
|
5640
5944
|
var key = new PluginKey2("markdownClipboard");
|
|
5641
|
-
var MAX_PASTE_LIST_DEPTH =
|
|
5945
|
+
var MAX_PASTE_LIST_DEPTH = 15;
|
|
5642
5946
|
var MAX_FLATTEN_DEPTH = 128;
|
|
5643
5947
|
function flattenDeepLists(node, listDepth = 0, _recurseDepth = 0) {
|
|
5644
5948
|
if (_recurseDepth > MAX_FLATTEN_DEPTH) return node;
|
|
@@ -5716,13 +6020,47 @@ function textToSlice(text2, view) {
|
|
|
5716
6020
|
}
|
|
5717
6021
|
}
|
|
5718
6022
|
var URL_RE = /^https?:\/\/[^\s]+$/i;
|
|
6023
|
+
var shiftHeld = false;
|
|
5719
6024
|
function createPlugin() {
|
|
5720
6025
|
return new Plugin3({
|
|
5721
6026
|
key,
|
|
5722
6027
|
props: {
|
|
6028
|
+
handleDOMEvents: {
|
|
6029
|
+
keydown(_view, event) {
|
|
6030
|
+
shiftHeld = event.shiftKey;
|
|
6031
|
+
return false;
|
|
6032
|
+
},
|
|
6033
|
+
keyup() {
|
|
6034
|
+
shiftHeld = false;
|
|
6035
|
+
return false;
|
|
6036
|
+
},
|
|
6037
|
+
paste(view, event) {
|
|
6038
|
+
if (shiftHeld) return false;
|
|
6039
|
+
const clipboardData = event.clipboardData;
|
|
6040
|
+
const text2 = clipboardData?.getData("text/plain");
|
|
6041
|
+
if (!text2 || !URL_RE.test(text2.trim())) return false;
|
|
6042
|
+
const { from, to } = view.state.selection;
|
|
6043
|
+
if (from >= to) return false;
|
|
6044
|
+
const selectedText = view.state.doc.textBetween(from, to);
|
|
6045
|
+
if (!selectedText) return false;
|
|
6046
|
+
event.preventDefault();
|
|
6047
|
+
const linkType = view.state.schema.marks.link;
|
|
6048
|
+
if (!linkType) return false;
|
|
6049
|
+
const linkMark2 = linkType.create({ href: text2.trim() });
|
|
6050
|
+
view.dispatch(view.state.tr.addMark(from, to, linkMark2));
|
|
6051
|
+
return true;
|
|
6052
|
+
}
|
|
6053
|
+
},
|
|
5723
6054
|
handlePaste(view, event) {
|
|
5724
|
-
const html = event.clipboardData?.getData("text/html");
|
|
5725
6055
|
const text2 = event.clipboardData?.getData("text/plain");
|
|
6056
|
+
if (shiftHeld) {
|
|
6057
|
+
if (!text2) return false;
|
|
6058
|
+
const textNode = actionbookSchema.text(text2);
|
|
6059
|
+
const slice2 = new Slice(Fragment.from(textNode), 0, 0);
|
|
6060
|
+
view.dispatch(view.state.tr.replaceSelection(slice2));
|
|
6061
|
+
return true;
|
|
6062
|
+
}
|
|
6063
|
+
const html = event.clipboardData?.getData("text/html");
|
|
5726
6064
|
if (html) {
|
|
5727
6065
|
const htmlSlice = htmlToSlice(html);
|
|
5728
6066
|
if (htmlSlice) {
|
|
@@ -5784,22 +6122,22 @@ function createMarkdownClipboardPlugin() {
|
|
|
5784
6122
|
|
|
5785
6123
|
// src/ui/plugin/jumpPointPlugin.ts
|
|
5786
6124
|
import { Plugin as Plugin4, PluginKey as PluginKey3, TextSelection as TextSelection3 } from "prosemirror-state";
|
|
5787
|
-
import { Decoration, DecorationSet } from "prosemirror-view";
|
|
6125
|
+
import { Decoration as Decoration2, DecorationSet as DecorationSet2 } from "prosemirror-view";
|
|
5788
6126
|
var adjacentKey = new PluginKey3("jumpPointAdjacent");
|
|
5789
6127
|
var JUMP_POINT_ADJACENT_SPEC = { jumpPointAdjacent: true };
|
|
5790
6128
|
function buildDecorations(state) {
|
|
5791
6129
|
const { selection } = state;
|
|
5792
|
-
if (!selection.empty) return
|
|
6130
|
+
if (!selection.empty) return DecorationSet2.empty;
|
|
5793
6131
|
const cursorPos = selection.$from.pos;
|
|
5794
6132
|
const decorations = [];
|
|
5795
6133
|
state.doc.descendants((node, pos) => {
|
|
5796
6134
|
if (node.type.name !== "jumpPoint") return;
|
|
5797
6135
|
const nodeEnd = pos + node.nodeSize;
|
|
5798
6136
|
if (cursorPos === pos || cursorPos === nodeEnd) {
|
|
5799
|
-
decorations.push(
|
|
6137
|
+
decorations.push(Decoration2.node(pos, nodeEnd, {}, JUMP_POINT_ADJACENT_SPEC));
|
|
5800
6138
|
}
|
|
5801
6139
|
});
|
|
5802
|
-
return
|
|
6140
|
+
return DecorationSet2.create(state.doc, decorations);
|
|
5803
6141
|
}
|
|
5804
6142
|
var jumpPointEditKey = new PluginKey3("jumpPointEdit");
|
|
5805
6143
|
var JUMP_POINT_FULL_RE = /^\^([\p{L}\p{N}_-]+)\^$/u;
|
|
@@ -5930,7 +6268,8 @@ function createJumpPointAdjacentPlugin() {
|
|
|
5930
6268
|
}
|
|
5931
6269
|
|
|
5932
6270
|
// src/ui/plugin/jumpPointNodeViewPlugin.tsx
|
|
5933
|
-
import { useCallback as useCallback2, useState as useState2 } from "react";
|
|
6271
|
+
import { useCallback as useCallback2, useRef as useRef2, useState as useState2 } from "react";
|
|
6272
|
+
import { createPortal } from "react-dom";
|
|
5934
6273
|
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
5935
6274
|
function IconDiamondAlert({ size = 12, fill = "#D9352C" }) {
|
|
5936
6275
|
return /* @__PURE__ */ jsxs3("svg", { width: size, height: size, viewBox: "0 0 12 12", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
@@ -5958,9 +6297,7 @@ var JUMP_POINT_STYLE = {
|
|
|
5958
6297
|
// are set via CSS class .ab-jump-point for heading-level overrides
|
|
5959
6298
|
};
|
|
5960
6299
|
var JUMP_POINT_ADJACENT_STYLE = {
|
|
5961
|
-
...JUMP_POINT_STYLE
|
|
5962
|
-
backgroundColor: "#FFE680",
|
|
5963
|
-
borderColor: "#FF9500"
|
|
6300
|
+
...JUMP_POINT_STYLE
|
|
5964
6301
|
};
|
|
5965
6302
|
var JUMP_POINT_DUPLICATE_STYLE = {
|
|
5966
6303
|
...JUMP_POINT_STYLE,
|
|
@@ -5989,64 +6326,71 @@ var CLOSE_BTN_STYLE = {
|
|
|
5989
6326
|
lineHeight: 1
|
|
5990
6327
|
};
|
|
5991
6328
|
var TOOLTIP_STYLE = {
|
|
5992
|
-
position: "
|
|
5993
|
-
|
|
5994
|
-
|
|
5995
|
-
|
|
6329
|
+
position: "fixed",
|
|
6330
|
+
display: "flex",
|
|
6331
|
+
flexDirection: "column",
|
|
6332
|
+
alignItems: "flex-start",
|
|
6333
|
+
alignSelf: "stretch",
|
|
6334
|
+
padding: "16px 20px",
|
|
5996
6335
|
backgroundColor: "#fff",
|
|
5997
6336
|
border: "1px solid #CCC",
|
|
5998
6337
|
borderRadius: "4px",
|
|
5999
6338
|
boxShadow: "0 8px 10px rgba(13,13,13,0.12), 0 3px 14px rgba(13,13,13,0.08), 0 3px 5px rgba(13,13,13,0.04)",
|
|
6000
|
-
padding: "16px 20px",
|
|
6001
6339
|
fontSize: "14px",
|
|
6002
6340
|
lineHeight: "20px",
|
|
6003
6341
|
color: "#0D0D0D",
|
|
6004
6342
|
maxWidth: "240px",
|
|
6005
|
-
zIndex:
|
|
6343
|
+
zIndex: 1100,
|
|
6006
6344
|
pointerEvents: "none"
|
|
6007
6345
|
};
|
|
6008
|
-
|
|
6346
|
+
var TOOLTIP_ARROW_STYLE = {
|
|
6347
|
+
position: "absolute",
|
|
6348
|
+
bottom: "-6px",
|
|
6349
|
+
left: "50%",
|
|
6350
|
+
transform: "translateX(-50%) rotate(45deg)",
|
|
6351
|
+
width: "10px",
|
|
6352
|
+
height: "10px",
|
|
6353
|
+
backgroundColor: "#fff",
|
|
6354
|
+
border: "1px solid #CCC",
|
|
6355
|
+
borderTop: "none",
|
|
6356
|
+
borderLeft: "none"
|
|
6357
|
+
};
|
|
6358
|
+
function JumpPointNodeViewComponent({ node, decorations }) {
|
|
6009
6359
|
const id = node.attrs.id;
|
|
6010
6360
|
const isAdjacent = decorations?.some((d) => d.spec?.jumpPointAdjacent === true) ?? false;
|
|
6011
6361
|
const isDuplicate = decorations?.some((d) => d.spec?.jumpPointDuplicate === true) ?? false;
|
|
6012
6362
|
const [showTooltip, setShowTooltip] = useState2(false);
|
|
6013
|
-
const
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
|
|
6363
|
+
const spanRef = useRef2(null);
|
|
6364
|
+
const [tooltipPos, setTooltipPos] = useState2(null);
|
|
6365
|
+
const handleMouseEnter = useCallback2(() => {
|
|
6366
|
+
if (!spanRef.current) return;
|
|
6367
|
+
const rect = spanRef.current.getBoundingClientRect();
|
|
6368
|
+
setTooltipPos({ top: rect.top - 8, left: rect.left + rect.width / 2 });
|
|
6369
|
+
setShowTooltip(true);
|
|
6370
|
+
}, []);
|
|
6020
6371
|
if (isDuplicate) {
|
|
6021
6372
|
return /* @__PURE__ */ jsxs3(
|
|
6022
6373
|
"span",
|
|
6023
6374
|
{
|
|
6375
|
+
ref: spanRef,
|
|
6024
6376
|
className: "ab-jump-point ab-jump-point-duplicate",
|
|
6025
|
-
style:
|
|
6377
|
+
style: JUMP_POINT_DUPLICATE_STYLE,
|
|
6026
6378
|
id: `jp-${id}`,
|
|
6027
|
-
onMouseEnter:
|
|
6379
|
+
onMouseEnter: handleMouseEnter,
|
|
6028
6380
|
onMouseLeave: () => setShowTooltip(false),
|
|
6029
6381
|
children: [
|
|
6030
6382
|
/* @__PURE__ */ jsx4("span", { className: "ab-jp-icon", children: /* @__PURE__ */ jsx4(IconAnchor, { size: 12, fill: "#9D091E", style: { paddingLeft: "2px", flexShrink: 0 } }) }),
|
|
6031
6383
|
/* @__PURE__ */ jsx4("span", { className: "ab-jp-label", style: LABEL_STYLE, children: id }),
|
|
6032
|
-
/* @__PURE__ */ jsx4(
|
|
6033
|
-
|
|
6034
|
-
{
|
|
6035
|
-
|
|
6036
|
-
|
|
6037
|
-
|
|
6038
|
-
|
|
6039
|
-
|
|
6040
|
-
|
|
6041
|
-
|
|
6042
|
-
children: /* @__PURE__ */ jsx4(IconDiamondAlert, { size: 12, fill: "#D9352C" })
|
|
6043
|
-
}
|
|
6044
|
-
),
|
|
6045
|
-
showTooltip && /* @__PURE__ */ jsxs3("span", { style: TOOLTIP_STYLE, children: [
|
|
6046
|
-
"\u201C",
|
|
6047
|
-
id,
|
|
6048
|
-
"\u201D is already used as an anchor"
|
|
6049
|
-
] })
|
|
6384
|
+
/* @__PURE__ */ jsx4("span", { style: { ...CLOSE_BTN_STYLE, cursor: "default" }, children: /* @__PURE__ */ jsx4(IconDiamondAlert, { size: 12, fill: "#D9352C" }) }),
|
|
6385
|
+
showTooltip && tooltipPos && createPortal(
|
|
6386
|
+
/* @__PURE__ */ jsxs3("span", { style: { ...TOOLTIP_STYLE, top: tooltipPos.top, left: tooltipPos.left, transform: "translate(-50%, -100%)" }, children: [
|
|
6387
|
+
"\u201C",
|
|
6388
|
+
id,
|
|
6389
|
+
"\u201D is already used as an anchor",
|
|
6390
|
+
/* @__PURE__ */ jsx4("span", { style: TOOLTIP_ARROW_STYLE })
|
|
6391
|
+
] }),
|
|
6392
|
+
document.body
|
|
6393
|
+
)
|
|
6050
6394
|
]
|
|
6051
6395
|
}
|
|
6052
6396
|
);
|
|
@@ -6073,7 +6417,7 @@ function createJumpPointNodeViewPlugin() {
|
|
|
6073
6417
|
|
|
6074
6418
|
// src/ui/plugin/jumpPointValidationPlugin.ts
|
|
6075
6419
|
import { Plugin as Plugin5, PluginKey as PluginKey4 } from "prosemirror-state";
|
|
6076
|
-
import { Decoration as
|
|
6420
|
+
import { Decoration as Decoration3, DecorationSet as DecorationSet3 } from "prosemirror-view";
|
|
6077
6421
|
var pluginKey = new PluginKey4("jumpPointValidation");
|
|
6078
6422
|
function collectJumpPointIds(state) {
|
|
6079
6423
|
const ids = /* @__PURE__ */ new Set();
|
|
@@ -6139,40 +6483,104 @@ function createJumpPointValidationPlugin() {
|
|
|
6139
6483
|
},
|
|
6140
6484
|
props: {
|
|
6141
6485
|
decorations(state) {
|
|
6142
|
-
return pluginKey.getState(state) ??
|
|
6486
|
+
return pluginKey.getState(state) ?? DecorationSet3.empty;
|
|
6143
6487
|
}
|
|
6144
6488
|
}
|
|
6145
6489
|
})
|
|
6146
6490
|
]
|
|
6147
6491
|
};
|
|
6148
6492
|
}
|
|
6493
|
+
function createBrokenRefIcon(refId) {
|
|
6494
|
+
const wrapper = document.createElement("span");
|
|
6495
|
+
wrapper.style.cssText = "position: relative; display: inline-flex; align-items: center; cursor: help;";
|
|
6496
|
+
wrapper.contentEditable = "false";
|
|
6497
|
+
const ns = "http://www.w3.org/2000/svg";
|
|
6498
|
+
const svg = document.createElementNS(ns, "svg");
|
|
6499
|
+
svg.setAttribute("width", "14");
|
|
6500
|
+
svg.setAttribute("height", "14");
|
|
6501
|
+
svg.setAttribute("viewBox", "0 0 16 16");
|
|
6502
|
+
svg.setAttribute("fill", "none");
|
|
6503
|
+
const path = document.createElementNS(ns, "path");
|
|
6504
|
+
path.setAttribute("fill-rule", "evenodd");
|
|
6505
|
+
path.setAttribute("clip-rule", "evenodd");
|
|
6506
|
+
path.setAttribute("d", "M8.00002 0.666626L15.3334 7.99996L8.00002 15.3333L0.666687 7.99996L8.00002 0.666626ZM7.33335 8.66663V4.66663H8.66669V8.66663H7.33335ZM8.00002 11.3333C8.46026 11.3333 8.83335 10.9602 8.83335 10.5C8.83335 10.0397 8.46026 9.66663 8.00002 9.66663C7.53978 9.66663 7.16669 10.0397 7.16669 10.5C7.16669 10.9602 7.53978 11.3333 8.00002 11.3333Z");
|
|
6507
|
+
path.setAttribute("fill", "#D9352C");
|
|
6508
|
+
svg.appendChild(path);
|
|
6509
|
+
const iconSpan = document.createElement("span");
|
|
6510
|
+
iconSpan.style.cssText = "display: inline-flex; margin-left: 2px; vertical-align: middle;";
|
|
6511
|
+
iconSpan.appendChild(svg);
|
|
6512
|
+
const tooltip = document.createElement("span");
|
|
6513
|
+
tooltip.textContent = `Anchor "${refId}" no longer exists`;
|
|
6514
|
+
tooltip.style.cssText = [
|
|
6515
|
+
"display:none",
|
|
6516
|
+
"position:fixed",
|
|
6517
|
+
"z-index:1100",
|
|
6518
|
+
"pointer-events:none",
|
|
6519
|
+
"padding:16px 20px",
|
|
6520
|
+
"background:#fff",
|
|
6521
|
+
"border:1px solid #CCC",
|
|
6522
|
+
"border-radius:4px",
|
|
6523
|
+
"box-shadow:0 8px 10px rgba(13,13,13,0.12),0 3px 14px rgba(13,13,13,0.08),0 3px 5px rgba(13,13,13,0.04)",
|
|
6524
|
+
"font-size:14px",
|
|
6525
|
+
"line-height:20px",
|
|
6526
|
+
"color:#0D0D0D",
|
|
6527
|
+
"max-width:240px",
|
|
6528
|
+
"white-space:normal"
|
|
6529
|
+
].join(";");
|
|
6530
|
+
const arrow = document.createElement("span");
|
|
6531
|
+
arrow.style.cssText = [
|
|
6532
|
+
"position:absolute",
|
|
6533
|
+
"bottom:-6px",
|
|
6534
|
+
"left:50%",
|
|
6535
|
+
"transform:translateX(-50%) rotate(45deg)",
|
|
6536
|
+
"width:10px",
|
|
6537
|
+
"height:10px",
|
|
6538
|
+
"background:#fff",
|
|
6539
|
+
"border:1px solid #CCC",
|
|
6540
|
+
"border-top:none",
|
|
6541
|
+
"border-left:none"
|
|
6542
|
+
].join(";");
|
|
6543
|
+
tooltip.appendChild(arrow);
|
|
6544
|
+
wrapper.addEventListener("mouseenter", () => {
|
|
6545
|
+
const rect = wrapper.getBoundingClientRect();
|
|
6546
|
+
tooltip.style.left = `${rect.left + rect.width / 2}px`;
|
|
6547
|
+
tooltip.style.top = `${rect.top - 8}px`;
|
|
6548
|
+
tooltip.style.transform = "translate(-50%, -100%)";
|
|
6549
|
+
tooltip.style.display = "flex";
|
|
6550
|
+
tooltip.style.flexDirection = "column";
|
|
6551
|
+
tooltip.style.alignItems = "flex-start";
|
|
6552
|
+
document.body.appendChild(tooltip);
|
|
6553
|
+
});
|
|
6554
|
+
wrapper.addEventListener("mouseleave", () => {
|
|
6555
|
+
tooltip.style.display = "none";
|
|
6556
|
+
if (tooltip.parentElement === document.body) document.body.removeChild(tooltip);
|
|
6557
|
+
});
|
|
6558
|
+
wrapper.appendChild(iconSpan);
|
|
6559
|
+
return wrapper;
|
|
6560
|
+
}
|
|
6149
6561
|
function buildDecorations2(state) {
|
|
6150
6562
|
const decos = [];
|
|
6151
6563
|
const duplicates = findDuplicatePositions(state);
|
|
6152
6564
|
for (const { pos, size } of duplicates) {
|
|
6153
6565
|
decos.push(
|
|
6154
|
-
|
|
6566
|
+
Decoration3.node(pos, pos + size, { class: "jump-point-duplicate" }, { jumpPointDuplicate: true })
|
|
6155
6567
|
);
|
|
6156
6568
|
}
|
|
6157
6569
|
const existingIds = collectJumpPointIds(state);
|
|
6158
6570
|
const brokenRefs = findBrokenAnchorRefs(state, existingIds);
|
|
6159
6571
|
for (const { from, to, refId } of brokenRefs) {
|
|
6160
6572
|
decos.push(
|
|
6161
|
-
|
|
6573
|
+
Decoration3.inline(from, to, {
|
|
6162
6574
|
class: "broken-anchor-ref",
|
|
6163
6575
|
"data-broken-ref": refId,
|
|
6164
|
-
|
|
6165
|
-
style: "color: #D9352C; font-weight: 500; text-decoration: none;"
|
|
6576
|
+
spellcheck: "false",
|
|
6577
|
+
style: "color: #D9352C; font-weight: 500; text-decoration: none !important; text-decoration-line: none !important;"
|
|
6166
6578
|
})
|
|
6167
6579
|
);
|
|
6168
|
-
|
|
6169
|
-
icon.textContent = " \u26A0";
|
|
6170
|
-
icon.style.cssText = "color: #D9352C; font-size: 14px; vertical-align: middle;";
|
|
6171
|
-
icon.setAttribute("aria-hidden", "true");
|
|
6172
|
-
decos.push(Decoration2.widget(to, icon, { side: 1 }));
|
|
6580
|
+
decos.push(Decoration3.widget(to, () => createBrokenRefIcon(refId), { side: -1 }));
|
|
6173
6581
|
}
|
|
6174
|
-
if (decos.length === 0) return
|
|
6175
|
-
return
|
|
6582
|
+
if (decos.length === 0) return DecorationSet3.empty;
|
|
6583
|
+
return DecorationSet3.create(state.doc, decos);
|
|
6176
6584
|
}
|
|
6177
6585
|
|
|
6178
6586
|
// src/ui/plugin/inlineToolTagNodeViewPlugin.tsx
|
|
@@ -6246,7 +6654,7 @@ function createInlineToolTagNodeViewPlugin() {
|
|
|
6246
6654
|
|
|
6247
6655
|
// src/ui/plugin/jinjaDecoration.ts
|
|
6248
6656
|
import { Plugin as Plugin6, PluginKey as PluginKey5 } from "prosemirror-state";
|
|
6249
|
-
import { Decoration as
|
|
6657
|
+
import { Decoration as Decoration4, DecorationSet as DecorationSet4 } from "prosemirror-view";
|
|
6250
6658
|
var jinjaPluginKey = new PluginKey5("jinjaDecoration");
|
|
6251
6659
|
var JINJA_TAG_RE = /\{%\s*(if|elif|else|endif)\s*([^%]*?)\s*%\}/g;
|
|
6252
6660
|
function getBlockPositions(doc2) {
|
|
@@ -6269,7 +6677,7 @@ function addInlineChipDecorations(doc2, decorations) {
|
|
|
6269
6677
|
const to = from + match[0].length;
|
|
6270
6678
|
const keyword = match[1];
|
|
6271
6679
|
decorations.push(
|
|
6272
|
-
|
|
6680
|
+
Decoration4.inline(from, to, {
|
|
6273
6681
|
class: `jinja-chip jinja-chip-${keyword}`
|
|
6274
6682
|
})
|
|
6275
6683
|
);
|
|
@@ -6310,7 +6718,7 @@ function addStructureBorderDecorations(doc2, blocks, decorations) {
|
|
|
6310
6718
|
const classes = ["jinja-bar", `jinja-bar-${branchType}`];
|
|
6311
6719
|
if (i === first || prevType !== branchType) classes.push("jinja-bar-first");
|
|
6312
6720
|
if (i === last || nextType !== branchType) classes.push("jinja-bar-last");
|
|
6313
|
-
decorations.push(
|
|
6721
|
+
decorations.push(Decoration4.node(block.from, block.to, { class: classes.join(" ") }));
|
|
6314
6722
|
}
|
|
6315
6723
|
}
|
|
6316
6724
|
}
|
|
@@ -6326,13 +6734,13 @@ function hasJinjaTags(doc2) {
|
|
|
6326
6734
|
return found;
|
|
6327
6735
|
}
|
|
6328
6736
|
function buildDecorations3(doc2) {
|
|
6329
|
-
if (!hasJinjaTags(doc2)) return
|
|
6737
|
+
if (!hasJinjaTags(doc2)) return DecorationSet4.empty;
|
|
6330
6738
|
const blocks = getBlockPositions(doc2);
|
|
6331
6739
|
const decorations = [];
|
|
6332
6740
|
addInlineChipDecorations(doc2, decorations);
|
|
6333
6741
|
addStructureBorderDecorations(doc2, blocks, decorations);
|
|
6334
|
-
if (decorations.length === 0) return
|
|
6335
|
-
return
|
|
6742
|
+
if (decorations.length === 0) return DecorationSet4.empty;
|
|
6743
|
+
return DecorationSet4.create(doc2, decorations);
|
|
6336
6744
|
}
|
|
6337
6745
|
function createJinjaDecorationPlugin() {
|
|
6338
6746
|
return {
|
|
@@ -6360,7 +6768,7 @@ function createJinjaDecorationPlugin() {
|
|
|
6360
6768
|
}
|
|
6361
6769
|
|
|
6362
6770
|
// src/ui/plugin/jinjaIfBlockPlugin.tsx
|
|
6363
|
-
import { useEffect as useEffect2, useRef as
|
|
6771
|
+
import { useEffect as useEffect2, useRef as useRef3, useState as useState3 } from "react";
|
|
6364
6772
|
import { createRoot as createRoot2 } from "react-dom/client";
|
|
6365
6773
|
import { Plugin as Plugin7, TextSelection as TextSelection4 } from "prosemirror-state";
|
|
6366
6774
|
import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
@@ -6377,7 +6785,9 @@ var JINJA_STYLES = `
|
|
|
6377
6785
|
display: grid;
|
|
6378
6786
|
grid-template-areas:
|
|
6379
6787
|
"header"
|
|
6788
|
+
"error"
|
|
6380
6789
|
"body"
|
|
6790
|
+
"body-error"
|
|
6381
6791
|
"footer";
|
|
6382
6792
|
gap: 0;
|
|
6383
6793
|
}
|
|
@@ -6467,6 +6877,7 @@ var JINJA_STYLES = `
|
|
|
6467
6877
|
}
|
|
6468
6878
|
|
|
6469
6879
|
.jinja-condition-error {
|
|
6880
|
+
grid-area: error;
|
|
6470
6881
|
display: flex;
|
|
6471
6882
|
align-items: center;
|
|
6472
6883
|
padding: 4px 0 4px 52px;
|
|
@@ -6475,6 +6886,16 @@ var JINJA_STYLES = `
|
|
|
6475
6886
|
line-height: 16px;
|
|
6476
6887
|
}
|
|
6477
6888
|
|
|
6889
|
+
.jinja-body-error {
|
|
6890
|
+
grid-area: body-error;
|
|
6891
|
+
display: flex;
|
|
6892
|
+
align-items: center;
|
|
6893
|
+
padding: 0 0 4px 52px;
|
|
6894
|
+
color: #D9352C;
|
|
6895
|
+
font-size: 12px;
|
|
6896
|
+
line-height: 16px;
|
|
6897
|
+
}
|
|
6898
|
+
|
|
6478
6899
|
.jinja-token-variable {
|
|
6479
6900
|
color: #4141B2;
|
|
6480
6901
|
}
|
|
@@ -6787,60 +7208,18 @@ function deleteBranch(view, nodePos, branchType) {
|
|
|
6787
7208
|
const context = getBranchContext(view, nodePos);
|
|
6788
7209
|
if (!context) return false;
|
|
6789
7210
|
const { branchNode, branchPos, branchIndex, blockNode, blockPos } = context;
|
|
6790
|
-
const branchContent = branchNode.content;
|
|
6791
7211
|
if (branchType === "if") {
|
|
6792
|
-
|
|
6793
|
-
|
|
6794
|
-
|
|
6795
|
-
|
|
6796
|
-
tr2.setSelection(TextSelection4.near(tr2.doc.resolve(blockPos)));
|
|
6797
|
-
} else {
|
|
6798
|
-
tr2.replaceWith(blockPos, blockPos + blockNode.nodeSize, branchContent);
|
|
6799
|
-
tr2.setSelection(TextSelection4.near(tr2.doc.resolve(blockPos)));
|
|
6800
|
-
}
|
|
6801
|
-
view.dispatch(tr2.scrollIntoView());
|
|
6802
|
-
view.focus();
|
|
6803
|
-
return true;
|
|
6804
|
-
}
|
|
6805
|
-
const nextBranch = blockNode.child(branchIndex + 1);
|
|
6806
|
-
const promotedCondition = typeof nextBranch.attrs.condition === "string" ? nextBranch.attrs.condition : "";
|
|
6807
|
-
const tr = view.state.tr;
|
|
6808
|
-
if (!isBranchBodyEmpty(branchNode)) {
|
|
6809
|
-
const nextBranchPos = branchPos + branchNode.nodeSize;
|
|
6810
|
-
const nextBranchContentStart = nextBranchPos + 1;
|
|
6811
|
-
for (let i = branchContent.childCount - 1; i >= 0; i--) {
|
|
6812
|
-
tr.insert(nextBranchContentStart, branchContent.child(i));
|
|
6813
|
-
}
|
|
6814
|
-
}
|
|
6815
|
-
const mappedBranchPos = tr.mapping.map(branchPos);
|
|
6816
|
-
const mappedBranchEnd = tr.mapping.map(branchPos + branchNode.nodeSize);
|
|
6817
|
-
tr.delete(mappedBranchPos, mappedBranchEnd);
|
|
6818
|
-
tr.setNodeMarkup(mappedBranchPos, void 0, {
|
|
6819
|
-
...nextBranch.attrs,
|
|
6820
|
-
branchType: "if",
|
|
6821
|
-
condition: promotedCondition
|
|
6822
|
-
});
|
|
6823
|
-
view.dispatch(tr.scrollIntoView());
|
|
7212
|
+
const tr2 = view.state.tr;
|
|
7213
|
+
tr2.replaceWith(blockPos, blockPos + blockNode.nodeSize, view.state.schema.nodes.paragraph.create());
|
|
7214
|
+
tr2.setSelection(TextSelection4.near(tr2.doc.resolve(blockPos)));
|
|
7215
|
+
view.dispatch(tr2.scrollIntoView());
|
|
6824
7216
|
view.focus();
|
|
6825
7217
|
return true;
|
|
6826
7218
|
}
|
|
6827
|
-
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
const tr = view.state.tr;
|
|
6832
|
-
for (let i = 0; i < branchContent.childCount; i++) {
|
|
6833
|
-
tr.insert(prevBranchContentEnd + i, branchContent.child(i));
|
|
6834
|
-
}
|
|
6835
|
-
const mappedBranchPos = tr.mapping.map(branchPos);
|
|
6836
|
-
const mappedBranchEnd = tr.mapping.map(branchPos + branchNode.nodeSize);
|
|
6837
|
-
tr.delete(mappedBranchPos, mappedBranchEnd);
|
|
6838
|
-
tr.setSelection(TextSelection4.near(tr.doc.resolve(tr.mapping.map(prevBranchContentEnd)), -1));
|
|
6839
|
-
view.dispatch(tr.scrollIntoView());
|
|
6840
|
-
view.focus();
|
|
6841
|
-
return true;
|
|
6842
|
-
}
|
|
6843
|
-
view.dispatch(view.state.tr.delete(branchPos, branchPos + branchNode.nodeSize).scrollIntoView());
|
|
7219
|
+
const tr = view.state.tr;
|
|
7220
|
+
tr.delete(branchPos, branchPos + branchNode.nodeSize);
|
|
7221
|
+
tr.setSelection(TextSelection4.near(tr.doc.resolve(tr.mapping.map(branchPos)), -1));
|
|
7222
|
+
view.dispatch(tr.scrollIntoView());
|
|
6844
7223
|
view.focus();
|
|
6845
7224
|
return true;
|
|
6846
7225
|
}
|
|
@@ -6865,8 +7244,8 @@ function ConditionDisplay({
|
|
|
6865
7244
|
}) {
|
|
6866
7245
|
const [isEditing, setIsEditing] = useState3(false);
|
|
6867
7246
|
const [draftValue, setDraftValue] = useState3(condition);
|
|
6868
|
-
const inputRef =
|
|
6869
|
-
const autoFocusedRef =
|
|
7247
|
+
const inputRef = useRef3(null);
|
|
7248
|
+
const autoFocusedRef = useRef3(false);
|
|
6870
7249
|
useEffect2(() => {
|
|
6871
7250
|
if (!isEditing) {
|
|
6872
7251
|
setDraftValue(condition);
|
|
@@ -6888,11 +7267,11 @@ function ConditionDisplay({
|
|
|
6888
7267
|
return /* @__PURE__ */ jsx6("span", { className: "jinja-otherwise", children: "Otherwise" });
|
|
6889
7268
|
}
|
|
6890
7269
|
const commit = () => {
|
|
6891
|
-
setIsEditing(false);
|
|
6892
|
-
onConditionBlur?.();
|
|
6893
7270
|
if (draftValue !== condition) {
|
|
6894
7271
|
onConditionChange(draftValue);
|
|
6895
7272
|
}
|
|
7273
|
+
setIsEditing(false);
|
|
7274
|
+
onConditionBlur?.();
|
|
6896
7275
|
};
|
|
6897
7276
|
const cancel = () => {
|
|
6898
7277
|
setDraftValue(condition);
|
|
@@ -6976,6 +7355,8 @@ function JinjaBranchHeader({
|
|
|
6976
7355
|
branchType,
|
|
6977
7356
|
condition,
|
|
6978
7357
|
editable = true,
|
|
7358
|
+
isBodyEmpty,
|
|
7359
|
+
isBodyTouched,
|
|
6979
7360
|
onConditionChange,
|
|
6980
7361
|
onDelete,
|
|
6981
7362
|
onAddBranch,
|
|
@@ -6983,8 +7364,8 @@ function JinjaBranchHeader({
|
|
|
6983
7364
|
hasElseBranch
|
|
6984
7365
|
}) {
|
|
6985
7366
|
const [menuSource, setMenuSource] = useState3(null);
|
|
6986
|
-
const kebabRef =
|
|
6987
|
-
const footerRef =
|
|
7367
|
+
const kebabRef = useRef3(null);
|
|
7368
|
+
const footerRef = useRef3(null);
|
|
6988
7369
|
useEffect2(() => {
|
|
6989
7370
|
if (!menuSource) return;
|
|
6990
7371
|
const handlePointerDown = (event) => {
|
|
@@ -7008,24 +7389,9 @@ function JinjaBranchHeader({
|
|
|
7008
7389
|
};
|
|
7009
7390
|
}, [menuSource]);
|
|
7010
7391
|
const menuItems = [];
|
|
7011
|
-
const isOnlyIfBranch = branchType === "if" && isLastBranch && !hasElseBranch;
|
|
7012
|
-
const canAddElif = editable && branchType !== "else" && (branchType === "elif" || isLastBranch);
|
|
7013
|
-
const canAddElse = editable && branchType !== "else" && isLastBranch && !hasElseBranch;
|
|
7014
|
-
if (canAddElif) {
|
|
7015
|
-
menuItems.push({
|
|
7016
|
-
label: "Else if",
|
|
7017
|
-
onSelect: () => onAddBranch("elif")
|
|
7018
|
-
});
|
|
7019
|
-
}
|
|
7020
|
-
if (canAddElse) {
|
|
7021
|
-
menuItems.push({
|
|
7022
|
-
label: "Else",
|
|
7023
|
-
onSelect: () => onAddBranch("else")
|
|
7024
|
-
});
|
|
7025
|
-
}
|
|
7026
7392
|
if (editable) {
|
|
7027
7393
|
menuItems.push({
|
|
7028
|
-
label:
|
|
7394
|
+
label: "Delete",
|
|
7029
7395
|
onSelect: onDelete
|
|
7030
7396
|
});
|
|
7031
7397
|
}
|
|
@@ -7090,6 +7456,7 @@ function JinjaBranchHeader({
|
|
|
7090
7456
|
] }) : null
|
|
7091
7457
|
] }),
|
|
7092
7458
|
conditionError && /* @__PURE__ */ jsx6("div", { className: "jinja-condition-error", children: conditionError }),
|
|
7459
|
+
isBodyEmpty && isBodyTouched && editable && /* @__PURE__ */ jsx6("div", { className: "jinja-body-error", children: "This field is required." }),
|
|
7093
7460
|
isLastBranch && editable ? /* @__PURE__ */ jsx6("div", { className: "jinja-add-footer", children: /* @__PURE__ */ jsx6("div", { className: "jinja-add-footer-col", children: /* @__PURE__ */ jsxs5("div", { className: "jinja-add-footer-actions", ref: footerRef, children: [
|
|
7094
7461
|
/* @__PURE__ */ jsx6(
|
|
7095
7462
|
"button",
|
|
@@ -7155,6 +7522,7 @@ var JinjaIfBranchView = class {
|
|
|
7155
7522
|
node;
|
|
7156
7523
|
view;
|
|
7157
7524
|
getPos;
|
|
7525
|
+
bodyTouched = false;
|
|
7158
7526
|
constructor(node, view, getPos) {
|
|
7159
7527
|
this.node = node;
|
|
7160
7528
|
this.view = view;
|
|
@@ -7179,6 +7547,12 @@ var JinjaIfBranchView = class {
|
|
|
7179
7547
|
this.contentDOM.setAttribute("data-placeholder", PLACEHOLDER_TEXT);
|
|
7180
7548
|
body.appendChild(dividerColumn);
|
|
7181
7549
|
body.appendChild(this.contentDOM);
|
|
7550
|
+
this.contentDOM.addEventListener("focusout", () => {
|
|
7551
|
+
if (!this.bodyTouched && isBranchBodyEmpty(this.node)) {
|
|
7552
|
+
this.bodyTouched = true;
|
|
7553
|
+
this.render();
|
|
7554
|
+
}
|
|
7555
|
+
});
|
|
7182
7556
|
this.root = createRoot2(this.headerContainer);
|
|
7183
7557
|
this._onSiblingsChanged = () => this.render();
|
|
7184
7558
|
this.dom.addEventListener("jinja-siblings-changed", this._onSiblingsChanged);
|
|
@@ -7226,6 +7600,8 @@ var JinjaIfBranchView = class {
|
|
|
7226
7600
|
branchType,
|
|
7227
7601
|
condition,
|
|
7228
7602
|
editable: this.view.editable && this.view.dom.getAttribute("contenteditable") !== "false",
|
|
7603
|
+
isBodyEmpty: isBranchBodyEmpty(this.node),
|
|
7604
|
+
isBodyTouched: this.bodyTouched,
|
|
7229
7605
|
isLastBranch: showAddButton,
|
|
7230
7606
|
hasElseBranch: context && nodePos != null ? getElseBranch(this.view, nodePos) : false,
|
|
7231
7607
|
onConditionChange: (value) => {
|
|
@@ -8326,6 +8702,7 @@ function createDragHandlePlugin() {
|
|
|
8326
8702
|
}
|
|
8327
8703
|
|
|
8328
8704
|
// src/ui/plugin/todoNodeViewPlugin.tsx
|
|
8705
|
+
import { Plugin as Plugin10 } from "prosemirror-state";
|
|
8329
8706
|
function createCheckboxDOM(checked) {
|
|
8330
8707
|
const el = document.createElement("span");
|
|
8331
8708
|
el.contentEditable = "false";
|
|
@@ -8408,14 +8785,63 @@ var TodoListItemView = class {
|
|
|
8408
8785
|
return true;
|
|
8409
8786
|
}
|
|
8410
8787
|
};
|
|
8788
|
+
function createListItemValueResetPlugin() {
|
|
8789
|
+
return new Plugin10({
|
|
8790
|
+
appendTransaction(trs, oldState, newState) {
|
|
8791
|
+
if (!trs.some((tr2) => tr2.docChanged)) return null;
|
|
8792
|
+
const oldCount = oldState.doc.childCount;
|
|
8793
|
+
let hasNewListItems = false;
|
|
8794
|
+
newState.doc.descendants((node) => {
|
|
8795
|
+
if (hasNewListItems) return false;
|
|
8796
|
+
if (node.type.name === "listItem" && node.attrs.value != null) {
|
|
8797
|
+
hasNewListItems = true;
|
|
8798
|
+
}
|
|
8799
|
+
});
|
|
8800
|
+
if (!hasNewListItems) return null;
|
|
8801
|
+
let tr = newState.tr;
|
|
8802
|
+
let changed = false;
|
|
8803
|
+
newState.doc.descendants((node, pos) => {
|
|
8804
|
+
if (node.type.name !== "orderedList") return;
|
|
8805
|
+
let prevValue = null;
|
|
8806
|
+
node.forEach((li, offset) => {
|
|
8807
|
+
const liValue = li.attrs.value;
|
|
8808
|
+
if (liValue != null && liValue === prevValue) {
|
|
8809
|
+
const liPos = pos + 1 + offset;
|
|
8810
|
+
tr = tr.setNodeMarkup(liPos, void 0, { ...li.attrs, value: null });
|
|
8811
|
+
changed = true;
|
|
8812
|
+
}
|
|
8813
|
+
prevValue = liValue;
|
|
8814
|
+
});
|
|
8815
|
+
});
|
|
8816
|
+
return changed ? tr : null;
|
|
8817
|
+
}
|
|
8818
|
+
});
|
|
8819
|
+
}
|
|
8411
8820
|
function createTodoNodeViewPlugin() {
|
|
8412
8821
|
return {
|
|
8413
8822
|
name: "todoNodeView",
|
|
8823
|
+
plugins: () => [createListItemValueResetPlugin()],
|
|
8414
8824
|
nodeViews: () => ({
|
|
8415
8825
|
listItem: ((node, view, getPos) => {
|
|
8416
8826
|
if (node.attrs.checked == null) {
|
|
8417
8827
|
const li = document.createElement("li");
|
|
8418
|
-
|
|
8828
|
+
if (node.attrs.value != null) {
|
|
8829
|
+
li.value = node.attrs.value;
|
|
8830
|
+
}
|
|
8831
|
+
return {
|
|
8832
|
+
dom: li,
|
|
8833
|
+
contentDOM: li,
|
|
8834
|
+
update(updatedNode) {
|
|
8835
|
+
if (updatedNode.type.name !== "listItem") return false;
|
|
8836
|
+
if (updatedNode.attrs.checked != null) return false;
|
|
8837
|
+
if (updatedNode.attrs.value != null) {
|
|
8838
|
+
li.value = updatedNode.attrs.value;
|
|
8839
|
+
} else {
|
|
8840
|
+
li.removeAttribute("value");
|
|
8841
|
+
}
|
|
8842
|
+
return true;
|
|
8843
|
+
}
|
|
8844
|
+
};
|
|
8419
8845
|
}
|
|
8420
8846
|
return new TodoListItemView(node, view, getPos);
|
|
8421
8847
|
})
|
|
@@ -8424,35 +8850,36 @@ function createTodoNodeViewPlugin() {
|
|
|
8424
8850
|
}
|
|
8425
8851
|
|
|
8426
8852
|
// src/ui/plugin/placeholderPlugin.ts
|
|
8427
|
-
import { Plugin as
|
|
8428
|
-
import { Decoration as
|
|
8853
|
+
import { Plugin as Plugin11, PluginKey as PluginKey8 } from "prosemirror-state";
|
|
8854
|
+
import { Decoration as Decoration5, DecorationSet as DecorationSet5 } from "prosemirror-view";
|
|
8429
8855
|
var pluginKey2 = new PluginKey8("placeholder");
|
|
8430
8856
|
function buildDecorations4(state) {
|
|
8431
8857
|
const { doc: doc2, selection } = state;
|
|
8432
|
-
if (!selection.empty) return
|
|
8858
|
+
if (!selection.empty) return DecorationSet5.empty;
|
|
8433
8859
|
const $from = selection.$from;
|
|
8434
8860
|
const parent = $from.parent;
|
|
8435
8861
|
if (parent.type.name !== "paragraph" || parent.content.size !== 0) {
|
|
8436
|
-
return
|
|
8862
|
+
return DecorationSet5.empty;
|
|
8437
8863
|
}
|
|
8438
8864
|
const EXCLUDED_ANCESTORS = /* @__PURE__ */ new Set(["noteBlock", "blockquote", "jinjaIfBranch"]);
|
|
8439
8865
|
for (let d = $from.depth - 1; d > 0; d--) {
|
|
8440
8866
|
if (EXCLUDED_ANCESTORS.has($from.node(d).type.name)) {
|
|
8441
|
-
return
|
|
8867
|
+
return DecorationSet5.empty;
|
|
8442
8868
|
}
|
|
8443
8869
|
}
|
|
8444
8870
|
const pos = $from.before($from.depth);
|
|
8445
|
-
const deco =
|
|
8446
|
-
class: "ab-empty-paragraph"
|
|
8871
|
+
const deco = Decoration5.node(pos, pos + parent.nodeSize, {
|
|
8872
|
+
class: "ab-empty-paragraph",
|
|
8873
|
+
"data-placeholder": "Type to start writing, or press / to insert an action."
|
|
8447
8874
|
});
|
|
8448
|
-
return
|
|
8875
|
+
return DecorationSet5.create(doc2, [deco]);
|
|
8449
8876
|
}
|
|
8450
8877
|
function createPlaceholderPlugin() {
|
|
8451
8878
|
let isEditable = true;
|
|
8452
8879
|
return {
|
|
8453
8880
|
name: "placeholder",
|
|
8454
8881
|
plugins: () => [
|
|
8455
|
-
new
|
|
8882
|
+
new Plugin11({
|
|
8456
8883
|
key: pluginKey2,
|
|
8457
8884
|
view(editorView) {
|
|
8458
8885
|
isEditable = editorView.editable;
|
|
@@ -8475,8 +8902,8 @@ function createPlaceholderPlugin() {
|
|
|
8475
8902
|
},
|
|
8476
8903
|
props: {
|
|
8477
8904
|
decorations(state) {
|
|
8478
|
-
if (!isEditable) return
|
|
8479
|
-
return pluginKey2.getState(state) ??
|
|
8905
|
+
if (!isEditable) return DecorationSet5.empty;
|
|
8906
|
+
return pluginKey2.getState(state) ?? DecorationSet5.empty;
|
|
8480
8907
|
}
|
|
8481
8908
|
}
|
|
8482
8909
|
})
|
|
@@ -8485,8 +8912,8 @@ function createPlaceholderPlugin() {
|
|
|
8485
8912
|
}
|
|
8486
8913
|
|
|
8487
8914
|
// src/ui/components/SlashCommandMenu.tsx
|
|
8488
|
-
import React4, { useEffect as useEffect3, useLayoutEffect, useRef as
|
|
8489
|
-
import { createPortal } from "react-dom";
|
|
8915
|
+
import React4, { useEffect as useEffect3, useLayoutEffect, useRef as useRef4, useState as useState4 } from "react";
|
|
8916
|
+
import { createPortal as createPortal2 } from "react-dom";
|
|
8490
8917
|
import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
8491
8918
|
function filterItems(items, query) {
|
|
8492
8919
|
if (!query) return items;
|
|
@@ -8513,7 +8940,7 @@ function injectScrollbarStyle() {
|
|
|
8513
8940
|
`;
|
|
8514
8941
|
document.head.appendChild(style);
|
|
8515
8942
|
}
|
|
8516
|
-
var POPUP_SHADOW = "0
|
|
8943
|
+
var POPUP_SHADOW = "0 3px 5px -3px rgba(13,13,13,0.04), 0 3px 14px 2px rgba(13,13,13,0.08), 0 8px 10px 1px rgba(13,13,13,0.12)";
|
|
8517
8944
|
var BTN_RESET = {
|
|
8518
8945
|
border: "none",
|
|
8519
8946
|
padding: 0,
|
|
@@ -8530,7 +8957,7 @@ var MENU_WIDTH = 440;
|
|
|
8530
8957
|
var MAX_MENU_H = 400;
|
|
8531
8958
|
function SlashCommandMenu({ view, editorState, items }) {
|
|
8532
8959
|
const [selectedIndex, setSelectedIndex] = useState4(0);
|
|
8533
|
-
const listRef =
|
|
8960
|
+
const listRef = useRef4(null);
|
|
8534
8961
|
useLayoutEffect(() => {
|
|
8535
8962
|
injectScrollbarStyle();
|
|
8536
8963
|
}, []);
|
|
@@ -8549,7 +8976,7 @@ function SlashCommandMenu({ view, editorState, items }) {
|
|
|
8549
8976
|
item?.scrollIntoView({ block: "nearest" });
|
|
8550
8977
|
}, [selectedIndex]);
|
|
8551
8978
|
useEffect3(() => {
|
|
8552
|
-
if (!active || !view) return;
|
|
8979
|
+
if (!active || !view || filtered.length === 0) return;
|
|
8553
8980
|
const onKeyDown = (e) => {
|
|
8554
8981
|
if (e.key === "ArrowDown") {
|
|
8555
8982
|
e.preventDefault();
|
|
@@ -8571,66 +8998,76 @@ function SlashCommandMenu({ view, editorState, items }) {
|
|
|
8571
8998
|
view.focus();
|
|
8572
8999
|
}
|
|
8573
9000
|
}
|
|
9001
|
+
if (e.key === "Escape") {
|
|
9002
|
+
e.preventDefault();
|
|
9003
|
+
e.stopPropagation();
|
|
9004
|
+
if (range) {
|
|
9005
|
+
view.dispatch(view.state.tr.delete(range.from, range.to));
|
|
9006
|
+
}
|
|
9007
|
+
view.focus();
|
|
9008
|
+
}
|
|
8574
9009
|
};
|
|
8575
9010
|
document.addEventListener("keydown", onKeyDown, true);
|
|
8576
9011
|
return () => document.removeEventListener("keydown", onKeyDown, true);
|
|
8577
9012
|
}, [active, view, filtered, selectedIndex, range]);
|
|
8578
|
-
|
|
8579
|
-
const
|
|
8580
|
-
|
|
8581
|
-
|
|
8582
|
-
|
|
8583
|
-
|
|
8584
|
-
|
|
8585
|
-
|
|
8586
|
-
|
|
9013
|
+
const [menuPos, setMenuPos] = useState4(null);
|
|
9014
|
+
const menuRef = useRef4(null);
|
|
9015
|
+
useLayoutEffect(() => {
|
|
9016
|
+
if (!active || !view || !range || filtered.length === 0) {
|
|
9017
|
+
setMenuPos(null);
|
|
9018
|
+
return;
|
|
9019
|
+
}
|
|
9020
|
+
try {
|
|
9021
|
+
const coords = view.coordsAtPos(range.to);
|
|
9022
|
+
let left = coords.left;
|
|
9023
|
+
left = Math.max(VPORT_MARGIN, Math.min(left, window.innerWidth - MENU_WIDTH - VPORT_MARGIN));
|
|
9024
|
+
const menuHeight = menuRef.current?.offsetHeight ?? MAX_MENU_H;
|
|
9025
|
+
let top = coords.bottom + 4;
|
|
9026
|
+
if (top + menuHeight > window.innerHeight - VPORT_MARGIN) {
|
|
9027
|
+
top = coords.top - menuHeight - 4;
|
|
9028
|
+
}
|
|
9029
|
+
setMenuPos({ top, left });
|
|
9030
|
+
} catch {
|
|
9031
|
+
}
|
|
9032
|
+
});
|
|
9033
|
+
if (!active || !view || !range || filtered.length === 0 || !menuPos) return null;
|
|
9034
|
+
return createPortal2(
|
|
8587
9035
|
/* @__PURE__ */ jsx7(
|
|
8588
9036
|
"div",
|
|
8589
9037
|
{
|
|
9038
|
+
ref: menuRef,
|
|
8590
9039
|
className: "ab-slash-menu",
|
|
8591
9040
|
style: {
|
|
8592
9041
|
position: "fixed",
|
|
8593
|
-
top,
|
|
8594
|
-
left,
|
|
9042
|
+
top: menuPos.top,
|
|
9043
|
+
left: menuPos.left,
|
|
8595
9044
|
width: MENU_WIDTH,
|
|
8596
9045
|
maxHeight: MAX_MENU_H,
|
|
8597
9046
|
overflowY: "auto",
|
|
8598
9047
|
background: "#fff",
|
|
8599
|
-
borderRadius:
|
|
9048
|
+
borderRadius: 4,
|
|
8600
9049
|
boxShadow: POPUP_SHADOW,
|
|
8601
|
-
padding: "
|
|
9050
|
+
padding: "8px 0",
|
|
8602
9051
|
zIndex: 1100,
|
|
8603
9052
|
animation: "ab-float-in 0.12s ease"
|
|
8604
9053
|
},
|
|
8605
|
-
children: /* @__PURE__ */ jsx7("div", { ref: listRef, children: filtered.
|
|
8606
|
-
"div",
|
|
8607
|
-
{
|
|
8608
|
-
style: {
|
|
8609
|
-
padding: "8px 12px",
|
|
8610
|
-
fontSize: 13,
|
|
8611
|
-
color: "#9ca3af"
|
|
8612
|
-
},
|
|
8613
|
-
children: "No results"
|
|
8614
|
-
}
|
|
8615
|
-
) : filtered.map((item, i) => {
|
|
9054
|
+
children: /* @__PURE__ */ jsx7("div", { ref: listRef, children: filtered.map((item, i) => {
|
|
8616
9055
|
const prevGroup = i > 0 ? filtered[i - 1].group : void 0;
|
|
8617
9056
|
const showGroupHeader = item.group && item.group !== prevGroup;
|
|
8618
9057
|
return /* @__PURE__ */ jsxs6(React4.Fragment, { children: [
|
|
8619
|
-
showGroupHeader && /* @__PURE__ */
|
|
8620
|
-
|
|
8621
|
-
|
|
8622
|
-
|
|
8623
|
-
|
|
8624
|
-
|
|
8625
|
-
|
|
8626
|
-
|
|
8627
|
-
|
|
8628
|
-
|
|
8629
|
-
|
|
8630
|
-
|
|
8631
|
-
|
|
8632
|
-
)
|
|
8633
|
-
] }),
|
|
9058
|
+
showGroupHeader && /* @__PURE__ */ jsx7(Fragment3, { children: /* @__PURE__ */ jsx7(
|
|
9059
|
+
"div",
|
|
9060
|
+
{
|
|
9061
|
+
style: {
|
|
9062
|
+
padding: "16px 16px 4px",
|
|
9063
|
+
fontSize: 12,
|
|
9064
|
+
fontWeight: 600,
|
|
9065
|
+
lineHeight: "12px",
|
|
9066
|
+
color: "#858585"
|
|
9067
|
+
},
|
|
9068
|
+
children: item.group
|
|
9069
|
+
}
|
|
9070
|
+
) }),
|
|
8634
9071
|
/* @__PURE__ */ jsx7(
|
|
8635
9072
|
SlashMenuItem,
|
|
8636
9073
|
{
|
|
@@ -8664,20 +9101,22 @@ function SlashMenuItem({ item, index, selected, onMouseEnter, onMouseDown }) {
|
|
|
8664
9101
|
display: "flex",
|
|
8665
9102
|
alignItems: "center",
|
|
8666
9103
|
gap: 12,
|
|
8667
|
-
padding: "6px
|
|
8668
|
-
background: selected ? "rgba(
|
|
9104
|
+
padding: "6px 16px",
|
|
9105
|
+
background: selected ? "rgba(13, 13, 13, 0.04)" : "transparent",
|
|
8669
9106
|
transition: "background 0.08s"
|
|
8670
9107
|
},
|
|
8671
9108
|
onMouseEnter,
|
|
8672
9109
|
onMouseDown,
|
|
8673
9110
|
children: [
|
|
8674
|
-
item.icon !== void 0 && /* @__PURE__ */ jsx7("span", { style: { flexShrink: 0, display: "flex", alignItems: "center" }, children: item.icon }),
|
|
8675
9111
|
/* @__PURE__ */ jsx7(
|
|
8676
9112
|
"span",
|
|
8677
9113
|
{
|
|
8678
9114
|
style: {
|
|
9115
|
+
flex: "1 0 0",
|
|
8679
9116
|
fontSize: 14,
|
|
8680
9117
|
fontWeight: 400,
|
|
9118
|
+
lineHeight: "20px",
|
|
9119
|
+
letterSpacing: "-0.1px",
|
|
8681
9120
|
color: "#0d0d0d",
|
|
8682
9121
|
whiteSpace: "nowrap",
|
|
8683
9122
|
overflow: "hidden",
|
|
@@ -8687,17 +9126,16 @@ function SlashMenuItem({ item, index, selected, onMouseEnter, onMouseDown }) {
|
|
|
8687
9126
|
children: item.title
|
|
8688
9127
|
}
|
|
8689
9128
|
),
|
|
8690
|
-
/* @__PURE__ */ jsx7("span", { style: { flex: 1 } }),
|
|
8691
9129
|
(item.description || item.shortcut) && /* @__PURE__ */ jsx7(
|
|
8692
9130
|
"span",
|
|
8693
9131
|
{
|
|
8694
9132
|
style: {
|
|
8695
9133
|
fontSize: 12,
|
|
9134
|
+
lineHeight: "16px",
|
|
8696
9135
|
color: "#5e5e5e",
|
|
8697
9136
|
whiteSpace: "nowrap",
|
|
8698
9137
|
flexShrink: 0,
|
|
8699
|
-
textAlign: "right"
|
|
8700
|
-
fontFamily: item.shortcut ? "monospace" : "inherit"
|
|
9138
|
+
textAlign: "right"
|
|
8701
9139
|
},
|
|
8702
9140
|
children: item.shortcut ?? item.description
|
|
8703
9141
|
}
|
|
@@ -8953,8 +9391,8 @@ function DocumentTreeView({ doc: doc2, className, onNavigate }) {
|
|
|
8953
9391
|
}
|
|
8954
9392
|
|
|
8955
9393
|
// src/ui/components/FloatingMenu.tsx
|
|
8956
|
-
import { useCallback as useCallback3, useEffect as useEffect4, useRef as
|
|
8957
|
-
import { createPortal as
|
|
9394
|
+
import { useCallback as useCallback3, useEffect as useEffect4, useRef as useRef5, useState as useState7 } from "react";
|
|
9395
|
+
import { createPortal as createPortal3 } from "react-dom";
|
|
8958
9396
|
import { TextSelection as TextSelection6 } from "prosemirror-state";
|
|
8959
9397
|
import { setBlockType as setBlockType2, toggleMark as toggleMark2, wrapIn } from "prosemirror-commands";
|
|
8960
9398
|
import { wrapInList as wrapInList2 } from "prosemirror-schema-list";
|
|
@@ -9132,7 +9570,7 @@ function Divider() {
|
|
|
9132
9570
|
}
|
|
9133
9571
|
function BlockTypeDropdown({ view, state, label }) {
|
|
9134
9572
|
const [open, setOpen] = useState7(false);
|
|
9135
|
-
const btnRef =
|
|
9573
|
+
const btnRef = useRef5(null);
|
|
9136
9574
|
const [hover, setHover] = useState7(false);
|
|
9137
9575
|
useEffect4(() => {
|
|
9138
9576
|
if (!open) return;
|
|
@@ -9224,7 +9662,7 @@ function BlockTypeDropdown({ view, state, label }) {
|
|
|
9224
9662
|
]
|
|
9225
9663
|
}
|
|
9226
9664
|
),
|
|
9227
|
-
open && btnRect &&
|
|
9665
|
+
open && btnRect && createPortal3(
|
|
9228
9666
|
/* @__PURE__ */ jsx10(
|
|
9229
9667
|
"div",
|
|
9230
9668
|
{
|
|
@@ -9286,7 +9724,7 @@ function DropdownItem({ item, onRun }) {
|
|
|
9286
9724
|
function SelectionToolbar({ view, state, selectionRect }) {
|
|
9287
9725
|
const [linkMode, setLinkMode] = useState7(false);
|
|
9288
9726
|
const [linkHref, setLinkHref] = useState7("");
|
|
9289
|
-
const inputRef =
|
|
9727
|
+
const inputRef = useRef5(null);
|
|
9290
9728
|
const isBold = hasMark(state, bold2);
|
|
9291
9729
|
const isItalic = hasMark(state, italic2);
|
|
9292
9730
|
const isUnderline = hasMark(state, underline2);
|
|
@@ -9502,7 +9940,7 @@ function LinkHoverTooltip({ view, link: link2, onEdit }) {
|
|
|
9502
9940
|
VPORT_MARGIN2 + tooltipHalfW,
|
|
9503
9941
|
Math.min((linkLeft + linkRight) / 2, window.innerWidth - VPORT_MARGIN2 - tooltipHalfW)
|
|
9504
9942
|
);
|
|
9505
|
-
return
|
|
9943
|
+
return createPortal3(
|
|
9506
9944
|
/* @__PURE__ */ jsxs9(
|
|
9507
9945
|
"div",
|
|
9508
9946
|
{
|
|
@@ -9616,7 +10054,7 @@ function LinkHoverTooltip({ view, link: link2, onEdit }) {
|
|
|
9616
10054
|
function LinkEditDialog({ view, link: link2, onClose }) {
|
|
9617
10055
|
const [textValue, setTextValue] = useState7(link2.text);
|
|
9618
10056
|
const [hrefValue, setHrefValue] = useState7(link2.href);
|
|
9619
|
-
const textInputRef =
|
|
10057
|
+
const textInputRef = useRef5(null);
|
|
9620
10058
|
useEffect4(() => {
|
|
9621
10059
|
setTextValue(link2.text);
|
|
9622
10060
|
setHrefValue(link2.href);
|
|
@@ -9714,7 +10152,7 @@ function LinkEditDialog({ view, link: link2, onClose }) {
|
|
|
9714
10152
|
saveLink();
|
|
9715
10153
|
}
|
|
9716
10154
|
};
|
|
9717
|
-
return
|
|
10155
|
+
return createPortal3(
|
|
9718
10156
|
/* @__PURE__ */ jsxs9(
|
|
9719
10157
|
"div",
|
|
9720
10158
|
{
|
|
@@ -9903,7 +10341,7 @@ var INSERT_LINK_EVENT = "ab-insert-link";
|
|
|
9903
10341
|
function LinkInsertDialog({ view, cursorPos, onClose }) {
|
|
9904
10342
|
const [textValue, setTextValue] = useState7("");
|
|
9905
10343
|
const [hrefValue, setHrefValue] = useState7("");
|
|
9906
|
-
const textInputRef =
|
|
10344
|
+
const textInputRef = useRef5(null);
|
|
9907
10345
|
useEffect4(() => {
|
|
9908
10346
|
setTimeout(() => textInputRef.current?.focus(), 0);
|
|
9909
10347
|
}, []);
|
|
@@ -9954,7 +10392,7 @@ function LinkInsertDialog({ view, cursorPos, onClose }) {
|
|
|
9954
10392
|
saveLink();
|
|
9955
10393
|
}
|
|
9956
10394
|
};
|
|
9957
|
-
return
|
|
10395
|
+
return createPortal3(
|
|
9958
10396
|
/* @__PURE__ */ jsxs9(
|
|
9959
10397
|
"div",
|
|
9960
10398
|
{
|
|
@@ -10302,8 +10740,8 @@ function FloatingMenu({ view, editorState }) {
|
|
|
10302
10740
|
const [showEmptyHandle, setShowEmptyHandle] = useState7(false);
|
|
10303
10741
|
const [editingLink, setEditingLink] = useState7(null);
|
|
10304
10742
|
const [insertLinkPos, setInsertLinkPos] = useState7(null);
|
|
10305
|
-
const dwellTimerRef =
|
|
10306
|
-
const lastEmptyPosRef =
|
|
10743
|
+
const dwellTimerRef = useRef5(null);
|
|
10744
|
+
const lastEmptyPosRef = useRef5(null);
|
|
10307
10745
|
useEffect4(() => {
|
|
10308
10746
|
const dom = view?.dom;
|
|
10309
10747
|
if (!dom) return;
|
|
@@ -10360,7 +10798,7 @@ function FloatingMenu({ view, editorState }) {
|
|
|
10360
10798
|
}
|
|
10361
10799
|
}
|
|
10362
10800
|
const selectionRect = hasSelection ? getSelectionDOMRect() : null;
|
|
10363
|
-
return
|
|
10801
|
+
return createPortal3(
|
|
10364
10802
|
/* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
10365
10803
|
hasSelection && selectionRect && /* @__PURE__ */ jsx10(
|
|
10366
10804
|
SelectionToolbar,
|
|
@@ -10401,8 +10839,8 @@ function FloatingMenu({ view, editorState }) {
|
|
|
10401
10839
|
}
|
|
10402
10840
|
|
|
10403
10841
|
// src/ui/plugin/inlineSuggestPlugin.ts
|
|
10404
|
-
import { Plugin as
|
|
10405
|
-
import { Decoration as
|
|
10842
|
+
import { Plugin as Plugin12, PluginKey as PluginKey9 } from "prosemirror-state";
|
|
10843
|
+
import { Decoration as Decoration6, DecorationSet as DecorationSet6 } from "prosemirror-view";
|
|
10406
10844
|
var inlineSuggestKey = new PluginKey9("inlineSuggest");
|
|
10407
10845
|
var DEBOUNCE_MS = 600;
|
|
10408
10846
|
function createInlineSuggestPlugin(provider, endpoint, options) {
|
|
@@ -10410,7 +10848,7 @@ function createInlineSuggestPlugin(provider, endpoint, options) {
|
|
|
10410
10848
|
return {
|
|
10411
10849
|
name: "inlineSuggest",
|
|
10412
10850
|
plugins: () => [
|
|
10413
|
-
new
|
|
10851
|
+
new Plugin12({
|
|
10414
10852
|
key: inlineSuggestKey,
|
|
10415
10853
|
state: {
|
|
10416
10854
|
init: () => ({ suggestion: null, anchorPos: null }),
|
|
@@ -10426,13 +10864,13 @@ function createInlineSuggestPlugin(provider, endpoint, options) {
|
|
|
10426
10864
|
props: {
|
|
10427
10865
|
decorations(state) {
|
|
10428
10866
|
const ps = inlineSuggestKey.getState(state);
|
|
10429
|
-
if (!ps?.suggestion || !state.selection.empty) return
|
|
10867
|
+
if (!ps?.suggestion || !state.selection.empty) return DecorationSet6.empty;
|
|
10430
10868
|
const ghost = document.createElement("span");
|
|
10431
10869
|
ghost.textContent = ps.suggestion;
|
|
10432
10870
|
ghost.style.cssText = "color: rgba(0,0,0,0.3); pointer-events: none; user-select: none;";
|
|
10433
10871
|
ghost.setAttribute("aria-hidden", "true");
|
|
10434
|
-
return
|
|
10435
|
-
|
|
10872
|
+
return DecorationSet6.create(state.doc, [
|
|
10873
|
+
Decoration6.widget(state.selection.from, ghost, {
|
|
10436
10874
|
side: 1,
|
|
10437
10875
|
key: "inline-suggest"
|
|
10438
10876
|
})
|
|
@@ -10577,9 +11015,26 @@ function hasInvalidJinjaConditions(state) {
|
|
|
10577
11015
|
});
|
|
10578
11016
|
return found;
|
|
10579
11017
|
}
|
|
11018
|
+
function hasEmptyJinjaBranches(state) {
|
|
11019
|
+
let found = false;
|
|
11020
|
+
state.doc.descendants((node) => {
|
|
11021
|
+
if (found) return false;
|
|
11022
|
+
if (node.type.name === "jinjaIfBranch") {
|
|
11023
|
+
if (node.childCount === 1) {
|
|
11024
|
+
const first = node.firstChild;
|
|
11025
|
+
if (first?.type.name === "paragraph" && first.content.size === 0) {
|
|
11026
|
+
found = true;
|
|
11027
|
+
}
|
|
11028
|
+
}
|
|
11029
|
+
return false;
|
|
11030
|
+
}
|
|
11031
|
+
});
|
|
11032
|
+
return found;
|
|
11033
|
+
}
|
|
10580
11034
|
export {
|
|
10581
11035
|
ActionbookRenderer,
|
|
10582
11036
|
DocumentTreeView,
|
|
11037
|
+
EDITOR_TEXT_STYLES,
|
|
10583
11038
|
EditorShell,
|
|
10584
11039
|
FloatingMenu,
|
|
10585
11040
|
INSERT_LINK_EVENT,
|
|
@@ -10611,6 +11066,7 @@ export {
|
|
|
10611
11066
|
createTodoNodeViewPlugin,
|
|
10612
11067
|
hasBrokenAnchorRefs,
|
|
10613
11068
|
hasDuplicateJumpPoints,
|
|
11069
|
+
hasEmptyJinjaBranches,
|
|
10614
11070
|
hasInvalidJinjaConditions,
|
|
10615
11071
|
inlineSuggestKey,
|
|
10616
11072
|
slashCommandKey,
|