@sendbird/actionbook-core 0.8.1 → 0.9.3
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/LICENSE +13 -0
- package/README.md +2 -2
- package/dist/index.d.ts +37 -3
- package/dist/index.js +505 -34
- package/dist/index.js.map +1 -1
- package/dist/{types-rEXLrfo_.d.ts → types-DK_GhIWZ.d.ts} +17 -5
- package/dist/ui/index.d.ts +42 -15
- package/dist/ui/index.js +1760 -709
- package/dist/ui/index.js.map +1 -1
- package/package.json +5 -5
package/dist/ui/index.js
CHANGED
|
@@ -32,12 +32,9 @@ var actionbookSchema = new Schema({
|
|
|
32
32
|
bulletList: {
|
|
33
33
|
content: "listItem+",
|
|
34
34
|
group: "block",
|
|
35
|
-
parseDOM: [
|
|
36
|
-
{ tag: "div.ab-bullet-list" },
|
|
37
|
-
{ tag: "ul" }
|
|
38
|
-
],
|
|
35
|
+
parseDOM: [{ tag: "ul" }],
|
|
39
36
|
toDOM() {
|
|
40
|
-
return ["
|
|
37
|
+
return ["ul", 0];
|
|
41
38
|
}
|
|
42
39
|
},
|
|
43
40
|
orderedList: {
|
|
@@ -45,12 +42,6 @@ var actionbookSchema = new Schema({
|
|
|
45
42
|
group: "block",
|
|
46
43
|
attrs: { start: { default: 1 } },
|
|
47
44
|
parseDOM: [
|
|
48
|
-
{
|
|
49
|
-
tag: "div.ab-ordered-list",
|
|
50
|
-
getAttrs(dom) {
|
|
51
|
-
return { start: Number(dom.dataset.start) || 1 };
|
|
52
|
-
}
|
|
53
|
-
},
|
|
54
45
|
{
|
|
55
46
|
tag: "ol",
|
|
56
47
|
getAttrs(dom) {
|
|
@@ -59,25 +50,13 @@ var actionbookSchema = new Schema({
|
|
|
59
50
|
}
|
|
60
51
|
],
|
|
61
52
|
toDOM(node) {
|
|
62
|
-
|
|
63
|
-
if (node.attrs.start !== 1) attrs["data-start"] = String(node.attrs.start);
|
|
64
|
-
return ["div", attrs, 0];
|
|
53
|
+
return node.attrs.start === 1 ? ["ol", 0] : ["ol", { start: node.attrs.start }, 0];
|
|
65
54
|
}
|
|
66
55
|
},
|
|
67
56
|
listItem: {
|
|
68
57
|
content: "block+",
|
|
69
58
|
attrs: { checked: { default: null } },
|
|
70
59
|
parseDOM: [
|
|
71
|
-
{
|
|
72
|
-
tag: "div.ab-list-item",
|
|
73
|
-
getAttrs(dom) {
|
|
74
|
-
const el = dom;
|
|
75
|
-
if (el.dataset.checked != null) {
|
|
76
|
-
return { checked: el.dataset.checked === "true" };
|
|
77
|
-
}
|
|
78
|
-
return { checked: null };
|
|
79
|
-
}
|
|
80
|
-
},
|
|
81
60
|
{
|
|
82
61
|
tag: "li",
|
|
83
62
|
getAttrs(dom) {
|
|
@@ -94,12 +73,10 @@ var actionbookSchema = new Schema({
|
|
|
94
73
|
}
|
|
95
74
|
],
|
|
96
75
|
toDOM(node) {
|
|
97
|
-
const attrs = { class: "ab-list-item", role: "listitem" };
|
|
98
76
|
if (node.attrs.checked != null) {
|
|
99
|
-
|
|
100
|
-
attrs["data-checked"] = String(node.attrs.checked);
|
|
77
|
+
return ["li", { class: "todo-item", "data-checked": String(node.attrs.checked) }, 0];
|
|
101
78
|
}
|
|
102
|
-
return ["
|
|
79
|
+
return ["li", 0];
|
|
103
80
|
},
|
|
104
81
|
defining: true
|
|
105
82
|
},
|
|
@@ -119,22 +96,25 @@ var actionbookSchema = new Schema({
|
|
|
119
96
|
defining: true,
|
|
120
97
|
marks: "",
|
|
121
98
|
attrs: { language: { default: null } },
|
|
122
|
-
parseDOM: [
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
const code3 = dom.querySelector("code");
|
|
128
|
-
return { language: code3?.getAttribute("data-language") || null };
|
|
129
|
-
}
|
|
99
|
+
parseDOM: [{
|
|
100
|
+
tag: "pre",
|
|
101
|
+
preserveWhitespace: "full",
|
|
102
|
+
getAttrs(dom) {
|
|
103
|
+
return { language: dom.getAttribute("data-language") || null };
|
|
130
104
|
}
|
|
131
|
-
],
|
|
105
|
+
}],
|
|
132
106
|
toDOM(node) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
107
|
+
return ["pre", { "data-language": node.attrs.language || void 0 }, ["code", 0]];
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
horizontalRule: {
|
|
111
|
+
group: "block",
|
|
112
|
+
parseDOM: [{ tag: "hr" }],
|
|
113
|
+
toDOM() {
|
|
114
|
+
return ["hr"];
|
|
136
115
|
}
|
|
137
116
|
},
|
|
117
|
+
// ── Jinja conditional block ──
|
|
138
118
|
jinjaIfBlock: {
|
|
139
119
|
content: "jinjaIfBranch+",
|
|
140
120
|
group: "block",
|
|
@@ -151,6 +131,7 @@ var actionbookSchema = new Schema({
|
|
|
151
131
|
defining: true,
|
|
152
132
|
attrs: {
|
|
153
133
|
branchType: { default: "if" },
|
|
134
|
+
// 'if' | 'elif' | 'else'
|
|
154
135
|
condition: { default: "" }
|
|
155
136
|
},
|
|
156
137
|
parseDOM: [
|
|
@@ -178,11 +159,14 @@ var actionbookSchema = new Schema({
|
|
|
178
159
|
];
|
|
179
160
|
}
|
|
180
161
|
},
|
|
181
|
-
|
|
162
|
+
noteBlock: {
|
|
163
|
+
content: "block+",
|
|
182
164
|
group: "block",
|
|
183
|
-
|
|
165
|
+
defining: true,
|
|
166
|
+
isolating: true,
|
|
167
|
+
parseDOM: [{ tag: "div[data-note-block]" }],
|
|
184
168
|
toDOM() {
|
|
185
|
-
return ["
|
|
169
|
+
return ["div", { "data-note-block": "", class: "ab-note-block" }, 0];
|
|
186
170
|
}
|
|
187
171
|
},
|
|
188
172
|
// ── Table nodes ──
|
|
@@ -472,6 +456,205 @@ function createPluginArray(plugins) {
|
|
|
472
456
|
// src/ui/components/ActionbookRenderer.tsx
|
|
473
457
|
import React from "react";
|
|
474
458
|
|
|
459
|
+
// src/jinja/conditionHighlighter.ts
|
|
460
|
+
var KEYWORDS = {
|
|
461
|
+
and: "AND",
|
|
462
|
+
or: "OR",
|
|
463
|
+
not: "NOT",
|
|
464
|
+
in: "IN",
|
|
465
|
+
is: "IS",
|
|
466
|
+
True: "BOOL",
|
|
467
|
+
False: "BOOL",
|
|
468
|
+
true: "BOOL",
|
|
469
|
+
false: "BOOL",
|
|
470
|
+
None: "NONE",
|
|
471
|
+
null: "NONE"
|
|
472
|
+
};
|
|
473
|
+
var CATEGORY_BY_TYPE = {
|
|
474
|
+
STRING: "value",
|
|
475
|
+
NUMBER: "value",
|
|
476
|
+
BOOL: "value",
|
|
477
|
+
NONE: "value",
|
|
478
|
+
IDENT: "variable",
|
|
479
|
+
AND: "operator",
|
|
480
|
+
OR: "operator",
|
|
481
|
+
NOT: "operator",
|
|
482
|
+
IN: "operator",
|
|
483
|
+
IS: "operator",
|
|
484
|
+
EQ: "operator",
|
|
485
|
+
NEQ: "operator",
|
|
486
|
+
LT: "operator",
|
|
487
|
+
GT: "operator",
|
|
488
|
+
LTE: "operator",
|
|
489
|
+
GTE: "operator",
|
|
490
|
+
LPAREN: "punctuation",
|
|
491
|
+
RPAREN: "punctuation"
|
|
492
|
+
};
|
|
493
|
+
var NEGATIVE_NUMBER_PRECEDERS = /* @__PURE__ */ new Set([
|
|
494
|
+
"AND",
|
|
495
|
+
"OR",
|
|
496
|
+
"NOT",
|
|
497
|
+
"IN",
|
|
498
|
+
"IS",
|
|
499
|
+
"EQ",
|
|
500
|
+
"NEQ",
|
|
501
|
+
"LT",
|
|
502
|
+
"GT",
|
|
503
|
+
"LTE",
|
|
504
|
+
"GTE",
|
|
505
|
+
"LPAREN"
|
|
506
|
+
]);
|
|
507
|
+
function canStartNegativeNumber(tokens) {
|
|
508
|
+
if (tokens.length === 0) {
|
|
509
|
+
return true;
|
|
510
|
+
}
|
|
511
|
+
const previous = tokens[tokens.length - 1];
|
|
512
|
+
return NEGATIVE_NUMBER_PRECEDERS.has(previous.type);
|
|
513
|
+
}
|
|
514
|
+
function finalizeTokens(input, rawTokens) {
|
|
515
|
+
const highlighted = [];
|
|
516
|
+
for (let i = 0; i < rawTokens.length; i++) {
|
|
517
|
+
const token = rawTokens[i];
|
|
518
|
+
const next = rawTokens[i + 1];
|
|
519
|
+
if (token.type === "IS" && next?.type === "NOT") {
|
|
520
|
+
highlighted.push({
|
|
521
|
+
text: input.slice(token.start, next.end),
|
|
522
|
+
start: token.start,
|
|
523
|
+
end: next.end,
|
|
524
|
+
category: "operator"
|
|
525
|
+
});
|
|
526
|
+
i++;
|
|
527
|
+
continue;
|
|
528
|
+
}
|
|
529
|
+
highlighted.push({
|
|
530
|
+
text: token.text,
|
|
531
|
+
start: token.start,
|
|
532
|
+
end: token.end,
|
|
533
|
+
category: CATEGORY_BY_TYPE[token.type]
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
return highlighted;
|
|
537
|
+
}
|
|
538
|
+
function tokenizeCondition(input) {
|
|
539
|
+
const rawTokens = [];
|
|
540
|
+
let i = 0;
|
|
541
|
+
while (i < input.length) {
|
|
542
|
+
const char = input[i];
|
|
543
|
+
if (/\s/.test(char)) {
|
|
544
|
+
i++;
|
|
545
|
+
continue;
|
|
546
|
+
}
|
|
547
|
+
if (char === '"' || char === "'") {
|
|
548
|
+
const start = i;
|
|
549
|
+
const quote = char;
|
|
550
|
+
i++;
|
|
551
|
+
while (i < input.length) {
|
|
552
|
+
if (input[i] === "\\" && i + 1 < input.length) {
|
|
553
|
+
i += 2;
|
|
554
|
+
continue;
|
|
555
|
+
}
|
|
556
|
+
if (input[i] === quote) {
|
|
557
|
+
i++;
|
|
558
|
+
rawTokens.push({
|
|
559
|
+
type: "STRING",
|
|
560
|
+
text: input.slice(start, i),
|
|
561
|
+
start,
|
|
562
|
+
end: i
|
|
563
|
+
});
|
|
564
|
+
break;
|
|
565
|
+
}
|
|
566
|
+
i++;
|
|
567
|
+
}
|
|
568
|
+
if (rawTokens[rawTokens.length - 1]?.start !== start) {
|
|
569
|
+
return finalizeTokens(input, rawTokens);
|
|
570
|
+
}
|
|
571
|
+
continue;
|
|
572
|
+
}
|
|
573
|
+
if (/[0-9]/.test(char) || char === "-" && i + 1 < input.length && /[0-9]/.test(input[i + 1]) && canStartNegativeNumber(rawTokens)) {
|
|
574
|
+
const start = i;
|
|
575
|
+
if (input[i] === "-") {
|
|
576
|
+
i++;
|
|
577
|
+
}
|
|
578
|
+
while (i < input.length && /[0-9]/.test(input[i])) {
|
|
579
|
+
i++;
|
|
580
|
+
}
|
|
581
|
+
if (i < input.length && input[i] === ".") {
|
|
582
|
+
i++;
|
|
583
|
+
while (i < input.length && /[0-9]/.test(input[i])) {
|
|
584
|
+
i++;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
rawTokens.push({
|
|
588
|
+
type: "NUMBER",
|
|
589
|
+
text: input.slice(start, i),
|
|
590
|
+
start,
|
|
591
|
+
end: i
|
|
592
|
+
});
|
|
593
|
+
continue;
|
|
594
|
+
}
|
|
595
|
+
if (/[a-zA-Z_]/.test(char)) {
|
|
596
|
+
const start = i;
|
|
597
|
+
i++;
|
|
598
|
+
while (i < input.length && /[a-zA-Z0-9_.]/.test(input[i])) {
|
|
599
|
+
i++;
|
|
600
|
+
}
|
|
601
|
+
const text2 = input.slice(start, i);
|
|
602
|
+
rawTokens.push({
|
|
603
|
+
type: KEYWORDS[text2] ?? "IDENT",
|
|
604
|
+
text: text2,
|
|
605
|
+
start,
|
|
606
|
+
end: i
|
|
607
|
+
});
|
|
608
|
+
continue;
|
|
609
|
+
}
|
|
610
|
+
if (i + 1 < input.length) {
|
|
611
|
+
const twoChar = input.slice(i, i + 2);
|
|
612
|
+
if (twoChar === "==") {
|
|
613
|
+
rawTokens.push({ type: "EQ", text: twoChar, start: i, end: i + 2 });
|
|
614
|
+
i += 2;
|
|
615
|
+
continue;
|
|
616
|
+
}
|
|
617
|
+
if (twoChar === "!=") {
|
|
618
|
+
rawTokens.push({ type: "NEQ", text: twoChar, start: i, end: i + 2 });
|
|
619
|
+
i += 2;
|
|
620
|
+
continue;
|
|
621
|
+
}
|
|
622
|
+
if (twoChar === "<=") {
|
|
623
|
+
rawTokens.push({ type: "LTE", text: twoChar, start: i, end: i + 2 });
|
|
624
|
+
i += 2;
|
|
625
|
+
continue;
|
|
626
|
+
}
|
|
627
|
+
if (twoChar === ">=") {
|
|
628
|
+
rawTokens.push({ type: "GTE", text: twoChar, start: i, end: i + 2 });
|
|
629
|
+
i += 2;
|
|
630
|
+
continue;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
if (char === "<") {
|
|
634
|
+
rawTokens.push({ type: "LT", text: char, start: i, end: i + 1 });
|
|
635
|
+
i++;
|
|
636
|
+
continue;
|
|
637
|
+
}
|
|
638
|
+
if (char === ">") {
|
|
639
|
+
rawTokens.push({ type: "GT", text: char, start: i, end: i + 1 });
|
|
640
|
+
i++;
|
|
641
|
+
continue;
|
|
642
|
+
}
|
|
643
|
+
if (char === "(") {
|
|
644
|
+
rawTokens.push({ type: "LPAREN", text: char, start: i, end: i + 1 });
|
|
645
|
+
i++;
|
|
646
|
+
continue;
|
|
647
|
+
}
|
|
648
|
+
if (char === ")") {
|
|
649
|
+
rawTokens.push({ type: "RPAREN", text: char, start: i, end: i + 1 });
|
|
650
|
+
i++;
|
|
651
|
+
continue;
|
|
652
|
+
}
|
|
653
|
+
return finalizeTokens(input, rawTokens);
|
|
654
|
+
}
|
|
655
|
+
return finalizeTokens(input, rawTokens);
|
|
656
|
+
}
|
|
657
|
+
|
|
475
658
|
// src/ui/components/icons.tsx
|
|
476
659
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
477
660
|
function IconTool({ size = 16, fill = "currentColor", style }) {
|
|
@@ -578,6 +761,12 @@ function IconTimeDiff({ size = 16, fill = "currentColor", style }) {
|
|
|
578
761
|
}
|
|
579
762
|
);
|
|
580
763
|
}
|
|
764
|
+
function IconStop({ size = 16, fill = "currentColor", style }) {
|
|
765
|
+
return /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 8 8", width: size, height: size, fill: "none", style, children: [
|
|
766
|
+
/* @__PURE__ */ jsx("path", { d: "M5.4375 3.375L2.0625 3.375V4.125L5.4375 4.125V3.375Z", fill }),
|
|
767
|
+
/* @__PURE__ */ jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M3.75 7.5C5.82107 7.5 7.5 5.82107 7.5 3.75C7.5 1.67893 5.82107 0 3.75 0C1.67893 0 0 1.67893 0 3.75C0 5.82107 1.67893 7.5 3.75 7.5ZM6.75 3.75C6.75 5.40685 5.40685 6.75 3.75 6.75C2.09315 6.75 0.75 5.40685 0.75 3.75C0.75 2.09315 2.09315 0.75 3.75 0.75C5.40685 0.75 6.75 2.09315 6.75 3.75Z", fill })
|
|
768
|
+
] });
|
|
769
|
+
}
|
|
581
770
|
function IconAnchor({ size = 16, fill = "currentColor", style }) {
|
|
582
771
|
return /* @__PURE__ */ jsxs(
|
|
583
772
|
"svg",
|
|
@@ -753,27 +942,193 @@ function renderInline(node, key2, renderNode) {
|
|
|
753
942
|
function renderInlineContent(content, keyPrefix, renderNode) {
|
|
754
943
|
return content.map((node, i) => renderInline(node, `${keyPrefix}-${i}`, renderNode));
|
|
755
944
|
}
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
945
|
+
var JINJA_RENDERER_STYLE_ID = "ab-renderer-jinja-styles";
|
|
946
|
+
var JINJA_RENDERER_STYLES = `
|
|
947
|
+
.ab-r-jinja-block {
|
|
948
|
+
margin: 8px 0;
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
.ab-r-jinja-branch {
|
|
952
|
+
position: relative;
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
.ab-r-jinja-header {
|
|
956
|
+
display: flex;
|
|
957
|
+
align-items: center;
|
|
958
|
+
gap: 12px;
|
|
959
|
+
padding: 8px;
|
|
960
|
+
border: 1px solid #E0E0E0;
|
|
961
|
+
border-radius: 4px;
|
|
962
|
+
background: #FFFFFF;
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
.ab-r-jinja-badge {
|
|
966
|
+
display: inline-flex;
|
|
967
|
+
align-items: center;
|
|
968
|
+
justify-content: center;
|
|
969
|
+
height: 32px;
|
|
970
|
+
padding: 0 8px;
|
|
971
|
+
border-radius: 4px;
|
|
972
|
+
font-family: "Roboto Mono", monospace;
|
|
973
|
+
font-size: 13px;
|
|
974
|
+
font-weight: 700;
|
|
975
|
+
line-height: 20px;
|
|
976
|
+
letter-spacing: -0.3px;
|
|
977
|
+
white-space: nowrap;
|
|
978
|
+
flex-shrink: 0;
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
.ab-r-jinja-badge-if,
|
|
982
|
+
.ab-r-jinja-badge-elif {
|
|
983
|
+
background: #E7F1FF;
|
|
984
|
+
color: #0D0D0D;
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
.ab-r-jinja-badge-else {
|
|
988
|
+
background: #F7F7F7;
|
|
989
|
+
color: #424242;
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
.ab-r-jinja-condition {
|
|
993
|
+
flex: 1;
|
|
994
|
+
min-width: 0;
|
|
995
|
+
display: flex;
|
|
996
|
+
flex-wrap: wrap;
|
|
997
|
+
gap: 8px;
|
|
998
|
+
align-items: center;
|
|
999
|
+
font-family: "Roboto Mono", monospace;
|
|
1000
|
+
font-size: 13px;
|
|
1001
|
+
line-height: 20px;
|
|
1002
|
+
letter-spacing: -0.3px;
|
|
1003
|
+
color: #0D0D0D;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
.ab-r-jinja-otherwise {
|
|
1007
|
+
flex: 1;
|
|
1008
|
+
color: #858585;
|
|
1009
|
+
font-family: "Roboto Mono", monospace;
|
|
1010
|
+
font-size: 13px;
|
|
1011
|
+
line-height: 20px;
|
|
1012
|
+
letter-spacing: -0.3px;
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
.ab-r-jinja-body {
|
|
1016
|
+
display: flex;
|
|
1017
|
+
gap: 12px;
|
|
1018
|
+
padding: 0 8px;
|
|
1019
|
+
min-height: 32px;
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
.ab-r-jinja-divider-col {
|
|
1023
|
+
width: 32px;
|
|
1024
|
+
flex-shrink: 0;
|
|
1025
|
+
display: flex;
|
|
1026
|
+
align-items: stretch;
|
|
1027
|
+
justify-content: center;
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
.ab-r-jinja-divider {
|
|
1031
|
+
width: 1px;
|
|
1032
|
+
background: #E0E0E0;
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
.ab-r-jinja-branch-last .ab-r-jinja-divider-col {
|
|
1036
|
+
align-items: flex-start;
|
|
1037
|
+
padding-left: 16px;
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
.ab-r-jinja-branch-last .ab-r-jinja-divider {
|
|
1041
|
+
width: 16px;
|
|
1042
|
+
height: 28px;
|
|
1043
|
+
background: none;
|
|
1044
|
+
border-left: 1px solid #E0E0E0;
|
|
1045
|
+
border-bottom: 1px solid #E0E0E0;
|
|
1046
|
+
border-bottom-left-radius: 8px;
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
.ab-r-jinja-content {
|
|
1050
|
+
flex: 1;
|
|
1051
|
+
min-width: 0;
|
|
1052
|
+
padding: 12px 0;
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
.ab-r-jinja-token-variable { color: #4141B2; }
|
|
1056
|
+
.ab-r-jinja-token-operator { color: #858585; }
|
|
1057
|
+
.ab-r-jinja-token-value { color: #0D0D0D; }
|
|
1058
|
+
.ab-r-jinja-token-punctuation { color: #858585; }
|
|
1059
|
+
`;
|
|
1060
|
+
var jinjaRendererStyleRefCount = 0;
|
|
1061
|
+
var jinjaRendererStyleEl = null;
|
|
1062
|
+
function ensureJinjaRendererStyles() {
|
|
1063
|
+
if (jinjaRendererStyleRefCount++ > 0) return;
|
|
1064
|
+
if (typeof document === "undefined") return;
|
|
1065
|
+
const existing = document.getElementById(JINJA_RENDERER_STYLE_ID);
|
|
1066
|
+
if (existing instanceof HTMLStyleElement) {
|
|
1067
|
+
jinjaRendererStyleEl = existing;
|
|
1068
|
+
return;
|
|
1069
|
+
}
|
|
1070
|
+
jinjaRendererStyleEl = document.createElement("style");
|
|
1071
|
+
jinjaRendererStyleEl.id = JINJA_RENDERER_STYLE_ID;
|
|
1072
|
+
jinjaRendererStyleEl.textContent = JINJA_RENDERER_STYLES;
|
|
1073
|
+
document.head.appendChild(jinjaRendererStyleEl);
|
|
1074
|
+
}
|
|
1075
|
+
function renderConditionTokens(condition) {
|
|
1076
|
+
const tokens = tokenizeCondition(condition);
|
|
1077
|
+
return tokens.map((token, i) => /* @__PURE__ */ jsx2("span", { className: `ab-r-jinja-token-${token.category}`, children: token.text }, `t-${i}-${token.start}`));
|
|
1078
|
+
}
|
|
1079
|
+
function renderJinjaBranch(branch, key2, isLast, renderNode) {
|
|
1080
|
+
const branchType = branch.branchType;
|
|
1081
|
+
const badgeLabel = branchType === "elif" ? "ELSE IF" : branchType.toUpperCase();
|
|
1082
|
+
return /* @__PURE__ */ jsxs2(
|
|
1083
|
+
"div",
|
|
1084
|
+
{
|
|
1085
|
+
className: `ab-r-jinja-branch${isLast ? " ab-r-jinja-branch-last" : ""}`,
|
|
1086
|
+
children: [
|
|
1087
|
+
/* @__PURE__ */ jsxs2("div", { className: "ab-r-jinja-header", children: [
|
|
1088
|
+
/* @__PURE__ */ jsx2("span", { className: `ab-r-jinja-badge ab-r-jinja-badge-${branchType}`, children: badgeLabel }),
|
|
1089
|
+
branchType === "else" ? /* @__PURE__ */ jsx2("span", { className: "ab-r-jinja-otherwise", children: "otherwise" }) : /* @__PURE__ */ jsx2("span", { className: "ab-r-jinja-condition", children: branch.condition ? renderConditionTokens(branch.condition) : null })
|
|
1090
|
+
] }),
|
|
1091
|
+
/* @__PURE__ */ jsxs2("div", { className: "ab-r-jinja-body", children: [
|
|
1092
|
+
/* @__PURE__ */ jsx2("div", { className: "ab-r-jinja-divider-col", children: /* @__PURE__ */ jsx2("div", { className: "ab-r-jinja-divider" }) }),
|
|
1093
|
+
/* @__PURE__ */ jsx2("div", { className: "ab-r-jinja-content", children: branch.content.map((child, i) => renderBlock(child, `${key2}-c${i}`, renderNode)) })
|
|
1094
|
+
] })
|
|
1095
|
+
]
|
|
1096
|
+
},
|
|
1097
|
+
key2
|
|
1098
|
+
);
|
|
1099
|
+
}
|
|
1100
|
+
function renderJinjaIfBlock(node, key2, renderNode) {
|
|
1101
|
+
ensureJinjaRendererStyles();
|
|
1102
|
+
return /* @__PURE__ */ jsx2("div", { className: "ab-r-jinja-block", children: node.branches.map(
|
|
1103
|
+
(branch, i) => renderJinjaBranch(
|
|
1104
|
+
branch,
|
|
1105
|
+
`${key2}-b${i}`,
|
|
1106
|
+
i === node.branches.length - 1,
|
|
1107
|
+
renderNode
|
|
1108
|
+
)
|
|
1109
|
+
) }, key2);
|
|
1110
|
+
}
|
|
1111
|
+
function renderBlock(node, key2, renderNode) {
|
|
1112
|
+
const defaultRender = () => {
|
|
1113
|
+
switch (node.type) {
|
|
1114
|
+
case "paragraph":
|
|
1115
|
+
return /* @__PURE__ */ jsx2("p", { children: renderInlineContent(node.content, key2, renderNode) }, key2);
|
|
1116
|
+
case "heading": {
|
|
1117
|
+
const Tag = `h${node.level}`;
|
|
1118
|
+
return /* @__PURE__ */ jsx2(Tag, { children: renderInlineContent(node.content, key2, renderNode) }, key2);
|
|
1119
|
+
}
|
|
1120
|
+
case "bulletList":
|
|
1121
|
+
return /* @__PURE__ */ jsx2("ul", { children: node.content.map((item, i) => renderBlock(item, `${key2}-${i}`, renderNode)) }, key2);
|
|
1122
|
+
case "orderedList":
|
|
1123
|
+
return /* @__PURE__ */ jsx2("ol", { start: node.start !== 1 ? node.start : void 0, children: node.content.map((item, i) => renderBlock(item, `${key2}-${i}`, renderNode)) }, key2);
|
|
1124
|
+
case "listItem":
|
|
1125
|
+
if (node.checked != null) {
|
|
1126
|
+
return /* @__PURE__ */ jsxs2("li", { style: { display: "flex", alignItems: "flex-start", listStyle: "none" }, children: [
|
|
1127
|
+
/* @__PURE__ */ jsx2(
|
|
1128
|
+
"input",
|
|
1129
|
+
{
|
|
1130
|
+
type: "checkbox",
|
|
1131
|
+
checked: node.checked,
|
|
777
1132
|
readOnly: true,
|
|
778
1133
|
style: { marginRight: 6, marginTop: 4, flexShrink: 0 }
|
|
779
1134
|
}
|
|
@@ -784,6 +1139,8 @@ function renderBlock(node, key2, renderNode) {
|
|
|
784
1139
|
return /* @__PURE__ */ jsx2("li", { children: node.content.map((child, i) => renderBlock(child, `${key2}-${i}`, renderNode)) }, key2);
|
|
785
1140
|
case "blockquote":
|
|
786
1141
|
return /* @__PURE__ */ jsx2("blockquote", { children: node.content.map((child, i) => renderBlock(child, `${key2}-${i}`, renderNode)) }, key2);
|
|
1142
|
+
case "jinjaIfBlock":
|
|
1143
|
+
return renderJinjaIfBlock(node, key2, renderNode);
|
|
787
1144
|
case "horizontalRule":
|
|
788
1145
|
return /* @__PURE__ */ jsx2("hr", {}, key2);
|
|
789
1146
|
case "table":
|
|
@@ -816,21 +1173,24 @@ var ReactNodeViewImpl = class {
|
|
|
816
1173
|
dom;
|
|
817
1174
|
root;
|
|
818
1175
|
component;
|
|
1176
|
+
wrapper;
|
|
819
1177
|
_node;
|
|
820
1178
|
_view;
|
|
821
1179
|
_getPos;
|
|
822
1180
|
_selected = false;
|
|
823
1181
|
_decorations = [];
|
|
824
|
-
constructor(node, view, getPos, options) {
|
|
1182
|
+
constructor(node, view, getPos, decorations, options) {
|
|
825
1183
|
this._node = node;
|
|
826
1184
|
this._view = view;
|
|
827
1185
|
this._getPos = getPos;
|
|
1186
|
+
this._decorations = decorations;
|
|
828
1187
|
this.component = options.component;
|
|
1188
|
+
this.wrapper = options.wrapper;
|
|
829
1189
|
const tag = options.as ?? (options.inline !== false ? "span" : "div");
|
|
830
1190
|
this.dom = document.createElement(tag);
|
|
831
1191
|
if (options.inline !== false) {
|
|
832
|
-
this.dom.style.display = "inline
|
|
833
|
-
this.dom.style.verticalAlign = "
|
|
1192
|
+
this.dom.style.display = "inline";
|
|
1193
|
+
this.dom.style.verticalAlign = "baseline";
|
|
834
1194
|
}
|
|
835
1195
|
if (options.className) {
|
|
836
1196
|
this.dom.className = options.className;
|
|
@@ -839,14 +1199,15 @@ var ReactNodeViewImpl = class {
|
|
|
839
1199
|
this.render();
|
|
840
1200
|
}
|
|
841
1201
|
render() {
|
|
1202
|
+
const element = createElement(this.component, {
|
|
1203
|
+
node: this._node,
|
|
1204
|
+
view: this._view,
|
|
1205
|
+
getPos: this._getPos,
|
|
1206
|
+
selected: this._selected,
|
|
1207
|
+
decorations: this._decorations
|
|
1208
|
+
});
|
|
842
1209
|
this.root.render(
|
|
843
|
-
createElement(this.
|
|
844
|
-
node: this._node,
|
|
845
|
-
view: this._view,
|
|
846
|
-
getPos: this._getPos,
|
|
847
|
-
selected: this._selected,
|
|
848
|
-
decorations: this._decorations
|
|
849
|
-
})
|
|
1210
|
+
this.wrapper ? createElement(this.wrapper, null, element) : element
|
|
850
1211
|
);
|
|
851
1212
|
}
|
|
852
1213
|
update(node, decorations, _innerDecorations) {
|
|
@@ -875,7 +1236,7 @@ var ReactNodeViewImpl = class {
|
|
|
875
1236
|
}
|
|
876
1237
|
};
|
|
877
1238
|
function createReactNodeView(options) {
|
|
878
|
-
return (node, view, getPos) => new ReactNodeViewImpl(node, view, getPos, options);
|
|
1239
|
+
return (node, view, getPos, decorations) => new ReactNodeViewImpl(node, view, getPos, decorations, options);
|
|
879
1240
|
}
|
|
880
1241
|
|
|
881
1242
|
// src/ui/hooks/useEditorView.ts
|
|
@@ -884,9 +1245,19 @@ import { EditorState } from "prosemirror-state";
|
|
|
884
1245
|
import { EditorView } from "prosemirror-view";
|
|
885
1246
|
import { Node as PMNode } from "prosemirror-model";
|
|
886
1247
|
|
|
1248
|
+
// src/ast/types.ts
|
|
1249
|
+
var RESOURCE_TAG_TYPES = ["tool", "manual", "agent_message_template", "handoff", "time_diff", "time_difference"];
|
|
1250
|
+
|
|
887
1251
|
// src/compat/prosemirror.ts
|
|
888
1252
|
var MAX_DEPTH = 128;
|
|
889
1253
|
var ALLOWED_URL_PROTOCOLS = /^(https?:|mailto:|tel:|#|\/)/i;
|
|
1254
|
+
var LIST_TYPES = /* @__PURE__ */ new Set(["bulletList", "orderedList"]);
|
|
1255
|
+
function isLooseList(items) {
|
|
1256
|
+
return items.some((li) => {
|
|
1257
|
+
const nonListBlocks = li.content.filter((b) => !LIST_TYPES.has(b.type));
|
|
1258
|
+
return nonListBlocks.length > 1;
|
|
1259
|
+
});
|
|
1260
|
+
}
|
|
890
1261
|
function convertPMMark(mark) {
|
|
891
1262
|
switch (mark.type) {
|
|
892
1263
|
case "bold":
|
|
@@ -925,12 +1296,17 @@ function convertPMInline(node, depth) {
|
|
|
925
1296
|
}
|
|
926
1297
|
case "inlineToolTag": {
|
|
927
1298
|
const attrs = node.attrs ?? {};
|
|
1299
|
+
const tagType = attrs.type ?? "tool";
|
|
1300
|
+
const text2 = attrs.text ?? "";
|
|
1301
|
+
if (!RESOURCE_TAG_TYPES.includes(tagType)) {
|
|
1302
|
+
return text2 ? [{ type: "text", text: text2 }] : [];
|
|
1303
|
+
}
|
|
928
1304
|
return [
|
|
929
1305
|
{
|
|
930
1306
|
type: "resourceTag",
|
|
931
|
-
tagType
|
|
1307
|
+
tagType,
|
|
932
1308
|
resourceId: attrs.resourceId ?? "",
|
|
933
|
-
text:
|
|
1309
|
+
text: text2
|
|
934
1310
|
}
|
|
935
1311
|
];
|
|
936
1312
|
}
|
|
@@ -961,20 +1337,27 @@ function convertPMBlock(node, depth = 0) {
|
|
|
961
1337
|
const level = node.attrs?.level ?? 1;
|
|
962
1338
|
return [{ type: "heading", level, content: children.flatMap((c) => convertPMInline(c, depth + 1)) }];
|
|
963
1339
|
}
|
|
964
|
-
case "bulletList":
|
|
1340
|
+
case "bulletList": {
|
|
1341
|
+
const items = children.map((c) => convertPMListItem(c, depth + 1));
|
|
1342
|
+
const spread = isLooseList(items);
|
|
965
1343
|
return [
|
|
966
1344
|
{
|
|
967
1345
|
type: "bulletList",
|
|
968
|
-
|
|
1346
|
+
...spread ? { spread: true } : {},
|
|
1347
|
+
content: items.map((li) => spread ? { ...li, spread: true } : li)
|
|
969
1348
|
}
|
|
970
1349
|
];
|
|
1350
|
+
}
|
|
971
1351
|
case "orderedList": {
|
|
972
1352
|
const start = node.attrs?.start ?? 1;
|
|
1353
|
+
const items = children.map((c) => convertPMListItem(c, depth + 1));
|
|
1354
|
+
const spread = isLooseList(items);
|
|
973
1355
|
return [
|
|
974
1356
|
{
|
|
975
1357
|
type: "orderedList",
|
|
976
1358
|
start,
|
|
977
|
-
|
|
1359
|
+
...spread ? { spread: true } : {},
|
|
1360
|
+
content: items.map((li) => spread ? { ...li, spread: true } : li)
|
|
978
1361
|
}
|
|
979
1362
|
];
|
|
980
1363
|
}
|
|
@@ -985,6 +1368,12 @@ function convertPMBlock(node, depth = 0) {
|
|
|
985
1368
|
return [{ type: "blockquote", content: children.flatMap((c) => convertPMBlock(c, depth + 1)) }];
|
|
986
1369
|
case "horizontalRule":
|
|
987
1370
|
return [{ type: "horizontalRule" }];
|
|
1371
|
+
case "codeBlock": {
|
|
1372
|
+
const textContent2 = children.map((c) => c.text ?? "").join("");
|
|
1373
|
+
return [{ type: "codeBlock", content: textContent2, ...node.attrs?.language ? { language: node.attrs.language } : {} }];
|
|
1374
|
+
}
|
|
1375
|
+
case "noteBlock":
|
|
1376
|
+
return [{ type: "noteBlock", content: children.flatMap((c) => convertPMBlock(c, depth + 1)) }];
|
|
988
1377
|
case "table": {
|
|
989
1378
|
const rows = children.map((rowNode) => {
|
|
990
1379
|
const cells = (rowNode.content ?? []).map((cellNode) => {
|
|
@@ -1001,6 +1390,22 @@ function convertPMBlock(node, depth = 0) {
|
|
|
1001
1390
|
});
|
|
1002
1391
|
return [{ type: "table", content: rows }];
|
|
1003
1392
|
}
|
|
1393
|
+
case "jinjaIfBlock": {
|
|
1394
|
+
const branches = children.map((branchNode) => {
|
|
1395
|
+
const branchType = branchNode.attrs?.branchType ?? "if";
|
|
1396
|
+
const condition = branchNode.attrs?.condition;
|
|
1397
|
+
const branchContent = (branchNode.content ?? []).flatMap((c) => convertPMBlock(c, depth + 2));
|
|
1398
|
+
return {
|
|
1399
|
+
branchType,
|
|
1400
|
+
...branchType !== "else" && condition ? { condition } : {},
|
|
1401
|
+
content: branchContent
|
|
1402
|
+
};
|
|
1403
|
+
});
|
|
1404
|
+
if (branches.length === 0) return [];
|
|
1405
|
+
return [{ type: "jinjaIfBlock", branches }];
|
|
1406
|
+
}
|
|
1407
|
+
case "jinjaIfBranch":
|
|
1408
|
+
return children.flatMap((c) => convertPMBlock(c, depth + 1));
|
|
1004
1409
|
default:
|
|
1005
1410
|
if (children.length > 0) {
|
|
1006
1411
|
return children.flatMap((c) => convertPMBlock(c, depth + 1));
|
|
@@ -1012,11 +1417,11 @@ function convertPMListItem(node, depth = 0) {
|
|
|
1012
1417
|
if (depth > MAX_DEPTH) return { type: "listItem", content: [{ type: "paragraph", content: [] }] };
|
|
1013
1418
|
const children = node.content ?? [];
|
|
1014
1419
|
const content = children.flatMap((c) => convertPMBlock(c, depth + 1));
|
|
1015
|
-
const checked = node.attrs?.checked;
|
|
1016
1420
|
const base = {
|
|
1017
1421
|
type: "listItem",
|
|
1018
1422
|
content: content.length > 0 ? content : [{ type: "paragraph", content: [] }]
|
|
1019
1423
|
};
|
|
1424
|
+
const checked = node.attrs?.checked;
|
|
1020
1425
|
if (typeof checked === "boolean") {
|
|
1021
1426
|
base.checked = checked;
|
|
1022
1427
|
}
|
|
@@ -1580,7 +1985,7 @@ function listItemWithTaskListItem(node, parent, state, info) {
|
|
|
1580
1985
|
|
|
1581
1986
|
// src/markdown/plugins/resourceTag.ts
|
|
1582
1987
|
var RESOURCE_TAG_RE = /\{\{([^:}]+):([^:}]*):([^}]+)\}\}/g;
|
|
1583
|
-
var VALID_TYPES = /* @__PURE__ */ new Set(["tool", "manual", "agent_message_template", "handoff", "time_diff"]);
|
|
1988
|
+
var VALID_TYPES = /* @__PURE__ */ new Set(["tool", "manual", "agent_message_template", "handoff", "end_call", "time_diff"]);
|
|
1584
1989
|
function splitTextWithResourceTags(text2) {
|
|
1585
1990
|
const results = [];
|
|
1586
1991
|
let lastIndex = 0;
|
|
@@ -1743,10 +2148,11 @@ function convertBlock(node, depth = 0) {
|
|
|
1743
2148
|
case "list": {
|
|
1744
2149
|
const list = node;
|
|
1745
2150
|
const items = list.children.map((li) => convertListItem(li, depth + 1));
|
|
2151
|
+
const spread = list.spread ?? false;
|
|
1746
2152
|
if (list.ordered) {
|
|
1747
|
-
return [{ type: "orderedList", start: list.start ?? 1, content: items }];
|
|
2153
|
+
return [{ type: "orderedList", start: list.start ?? 1, spread, content: items }];
|
|
1748
2154
|
}
|
|
1749
|
-
return [{ type: "bulletList", content: items }];
|
|
2155
|
+
return [{ type: "bulletList", spread, content: items }];
|
|
1750
2156
|
}
|
|
1751
2157
|
case "blockquote": {
|
|
1752
2158
|
const bq = node;
|
|
@@ -1755,6 +2161,10 @@ function convertBlock(node, depth = 0) {
|
|
|
1755
2161
|
}
|
|
1756
2162
|
case "thematicBreak":
|
|
1757
2163
|
return [{ type: "horizontalRule" }];
|
|
2164
|
+
case "code": {
|
|
2165
|
+
const codeNode = node;
|
|
2166
|
+
return [{ type: "codeBlock", content: codeNode.value, ...codeNode.lang ? { language: codeNode.lang } : {} }];
|
|
2167
|
+
}
|
|
1758
2168
|
case "jinjaIfBlockMdast": {
|
|
1759
2169
|
const jNode = node;
|
|
1760
2170
|
const branches = jNode.branches.map((b) => ({
|
|
@@ -1795,7 +2205,11 @@ function convertBlock(node, depth = 0) {
|
|
|
1795
2205
|
function convertListItem(node, depth = 0) {
|
|
1796
2206
|
if (depth > MAX_DEPTH2) throw new DepthError(depth);
|
|
1797
2207
|
const content = node.children.flatMap((child) => convertBlock(child, depth + 1));
|
|
1798
|
-
const base = {
|
|
2208
|
+
const base = {
|
|
2209
|
+
type: "listItem",
|
|
2210
|
+
spread: node.spread ?? false,
|
|
2211
|
+
content: content.length > 0 ? content : [{ type: "paragraph", content: [] }]
|
|
2212
|
+
};
|
|
1799
2213
|
if (typeof node.checked === "boolean") {
|
|
1800
2214
|
return { ...base, checked: node.checked };
|
|
1801
2215
|
}
|
|
@@ -1894,31 +2308,39 @@ function blockToMdast(node, depth = 0) {
|
|
|
1894
2308
|
return [{ type: "paragraph", children: node.content.flatMap((c) => inlineToMdast(c, depth + 1)) }];
|
|
1895
2309
|
case "heading":
|
|
1896
2310
|
return [{ type: "heading", depth: node.level, children: node.content.flatMap((c) => inlineToMdast(c, depth + 1)) }];
|
|
1897
|
-
case "bulletList":
|
|
2311
|
+
case "bulletList": {
|
|
2312
|
+
const items = node.content.map((li) => listItemToMdast(li, depth + 1));
|
|
1898
2313
|
return [
|
|
1899
2314
|
{
|
|
1900
2315
|
type: "list",
|
|
1901
2316
|
ordered: false,
|
|
1902
|
-
spread: false,
|
|
1903
|
-
children:
|
|
2317
|
+
spread: node.spread ?? false,
|
|
2318
|
+
children: items
|
|
1904
2319
|
}
|
|
1905
2320
|
];
|
|
1906
|
-
|
|
2321
|
+
}
|
|
2322
|
+
case "orderedList": {
|
|
2323
|
+
const items = node.content.map((li) => listItemToMdast(li, depth + 1));
|
|
1907
2324
|
return [
|
|
1908
2325
|
{
|
|
1909
2326
|
type: "list",
|
|
1910
2327
|
ordered: true,
|
|
1911
2328
|
start: node.start,
|
|
1912
|
-
spread: false,
|
|
1913
|
-
children:
|
|
2329
|
+
spread: node.spread ?? false,
|
|
2330
|
+
children: items
|
|
1914
2331
|
}
|
|
1915
2332
|
];
|
|
2333
|
+
}
|
|
1916
2334
|
case "listItem":
|
|
1917
2335
|
return listItemToMdast(node, depth).children.flatMap((child) => [child]);
|
|
1918
2336
|
case "blockquote":
|
|
1919
2337
|
return [{ type: "blockquote", children: node.content.flatMap((c) => blockToMdast(c, depth + 1)) }];
|
|
1920
2338
|
case "horizontalRule":
|
|
1921
2339
|
return [{ type: "thematicBreak" }];
|
|
2340
|
+
case "codeBlock": {
|
|
2341
|
+
const cb = node;
|
|
2342
|
+
return [{ type: "code", value: cb.content, ...cb.language ? { lang: cb.language } : {} }];
|
|
2343
|
+
}
|
|
1922
2344
|
case "jinjaIfBlock": {
|
|
1923
2345
|
const jNode = node;
|
|
1924
2346
|
const result = [];
|
|
@@ -1942,14 +2364,18 @@ function blockToMdast(node, depth = 0) {
|
|
|
1942
2364
|
}));
|
|
1943
2365
|
return [{ type: "table", children: rows }];
|
|
1944
2366
|
}
|
|
2367
|
+
case "noteBlock":
|
|
2368
|
+
return [];
|
|
1945
2369
|
}
|
|
1946
2370
|
}
|
|
1947
2371
|
function listItemToMdast(node, depth = 0) {
|
|
1948
2372
|
if (depth > MAX_DEPTH2) throw new DepthError(depth);
|
|
2373
|
+
const children = node.content.flatMap((child) => blockToMdast(child, depth + 1));
|
|
2374
|
+
const isSpread = node.spread ?? false;
|
|
1949
2375
|
const result = {
|
|
1950
2376
|
type: "listItem",
|
|
1951
|
-
spread:
|
|
1952
|
-
children
|
|
2377
|
+
spread: isSpread,
|
|
2378
|
+
children
|
|
1953
2379
|
};
|
|
1954
2380
|
if (typeof node.checked === "boolean") {
|
|
1955
2381
|
result.checked = node.checked;
|
|
@@ -1982,12 +2408,20 @@ function textHandler(node, parent, state, info) {
|
|
|
1982
2408
|
state.unsafe = originalUnsafe;
|
|
1983
2409
|
return result;
|
|
1984
2410
|
}
|
|
2411
|
+
function linkHandler(node, parent, state, info) {
|
|
2412
|
+
const childrenText = state.containerPhrasing(node, { ...info, before: "[", after: "]" });
|
|
2413
|
+
const url = node.url ?? "";
|
|
2414
|
+
const title = node.title;
|
|
2415
|
+
const titlePart = title ? ` "${title.replace(/"/g, '\\"')}"` : "";
|
|
2416
|
+
return `[${childrenText}](${url}${titlePart})`;
|
|
2417
|
+
}
|
|
1985
2418
|
function serializeToMarkdown(doc2) {
|
|
1986
2419
|
const mdastTree = toMdast(doc2);
|
|
1987
|
-
const
|
|
2420
|
+
const raw = toMarkdown(mdastTree, {
|
|
1988
2421
|
bullet: "-",
|
|
1989
2422
|
rule: "-",
|
|
1990
2423
|
listItemIndent: "one",
|
|
2424
|
+
incrementListMarker: true,
|
|
1991
2425
|
emphasis: "*",
|
|
1992
2426
|
strong: "*",
|
|
1993
2427
|
resourceLink: true,
|
|
@@ -1999,11 +2433,13 @@ function serializeToMarkdown(doc2) {
|
|
|
1999
2433
|
],
|
|
2000
2434
|
handlers: {
|
|
2001
2435
|
text: textHandler,
|
|
2436
|
+
link: linkHandler,
|
|
2002
2437
|
...resourceTagToMarkdown().handlers,
|
|
2003
2438
|
...jumpPointToMarkdown().handlers
|
|
2004
2439
|
},
|
|
2005
2440
|
extensions: [gfmNoAutolinkToMarkdown()]
|
|
2006
2441
|
});
|
|
2442
|
+
let result = raw.replace(/^(\s*)\\>/gm, "$1>").replace(/(\S) *>/g, (match, pre) => `${pre} >`).replace(/\\\[([^\]]*)\]/g, "\\[$1\\]").replace(/ /g, " ");
|
|
2007
2443
|
return result;
|
|
2008
2444
|
}
|
|
2009
2445
|
|
|
@@ -2087,20 +2523,23 @@ function convertInline2(node) {
|
|
|
2087
2523
|
}
|
|
2088
2524
|
function convertBlockToArray(node) {
|
|
2089
2525
|
if (node.type === "jinjaIfBlock") {
|
|
2090
|
-
|
|
2091
|
-
const result = [];
|
|
2092
|
-
for (const branch of jNode.branches) {
|
|
2093
|
-
const tagText = branch.branchType === "else" ? "{% else %}" : `{% ${branch.branchType} ${branch.condition ?? ""} %}`.trim();
|
|
2094
|
-
result.push({ type: "paragraph", content: [{ type: "text", text: tagText }] });
|
|
2095
|
-
for (const child of branch.content) {
|
|
2096
|
-
result.push(...convertBlockToArray(child));
|
|
2097
|
-
}
|
|
2098
|
-
}
|
|
2099
|
-
result.push({ type: "paragraph", content: [{ type: "text", text: "{% endif %}" }] });
|
|
2100
|
-
return result;
|
|
2526
|
+
return [convertJinjaIfBlock(node)];
|
|
2101
2527
|
}
|
|
2102
2528
|
return [convertBlock2(node)];
|
|
2103
2529
|
}
|
|
2530
|
+
function convertJinjaIfBlock(node) {
|
|
2531
|
+
return {
|
|
2532
|
+
type: "jinjaIfBlock",
|
|
2533
|
+
content: node.branches.map((branch) => ({
|
|
2534
|
+
type: "jinjaIfBranch",
|
|
2535
|
+
attrs: {
|
|
2536
|
+
branchType: branch.branchType,
|
|
2537
|
+
condition: branch.condition ?? ""
|
|
2538
|
+
},
|
|
2539
|
+
content: branch.content.length > 0 ? branch.content.flatMap(convertBlockToArray) : [{ type: "paragraph", content: [] }]
|
|
2540
|
+
}))
|
|
2541
|
+
};
|
|
2542
|
+
}
|
|
2104
2543
|
function convertBlock2(node) {
|
|
2105
2544
|
switch (node.type) {
|
|
2106
2545
|
case "paragraph":
|
|
@@ -2142,6 +2581,19 @@ function convertBlock2(node) {
|
|
|
2142
2581
|
};
|
|
2143
2582
|
case "horizontalRule":
|
|
2144
2583
|
return { type: "horizontalRule" };
|
|
2584
|
+
case "codeBlock": {
|
|
2585
|
+
const cb = node;
|
|
2586
|
+
return {
|
|
2587
|
+
type: "codeBlock",
|
|
2588
|
+
attrs: { language: cb.language ?? null },
|
|
2589
|
+
content: cb.content ? [{ type: "text", text: cb.content }] : void 0
|
|
2590
|
+
};
|
|
2591
|
+
}
|
|
2592
|
+
case "noteBlock":
|
|
2593
|
+
return {
|
|
2594
|
+
type: "noteBlock",
|
|
2595
|
+
content: node.content.flatMap(convertBlockToArray)
|
|
2596
|
+
};
|
|
2145
2597
|
case "table":
|
|
2146
2598
|
return {
|
|
2147
2599
|
type: "table",
|
|
@@ -2153,19 +2605,8 @@ function convertBlock2(node) {
|
|
|
2153
2605
|
}))
|
|
2154
2606
|
}))
|
|
2155
2607
|
};
|
|
2156
|
-
case "jinjaIfBlock":
|
|
2157
|
-
|
|
2158
|
-
const result = [];
|
|
2159
|
-
for (const branch of jNode.branches) {
|
|
2160
|
-
const tagText = branch.branchType === "else" ? "{% else %}" : `{% ${branch.branchType} ${branch.condition ?? ""} %}`.trim();
|
|
2161
|
-
result.push({ type: "paragraph", content: [{ type: "text", text: tagText }] });
|
|
2162
|
-
for (const child of branch.content) {
|
|
2163
|
-
result.push(...convertBlockToArray(child));
|
|
2164
|
-
}
|
|
2165
|
-
}
|
|
2166
|
-
result.push({ type: "paragraph", content: [{ type: "text", text: "{% endif %}" }] });
|
|
2167
|
-
return result[0] ?? { type: "paragraph", content: [] };
|
|
2168
|
-
}
|
|
2608
|
+
case "jinjaIfBlock":
|
|
2609
|
+
return convertJinjaIfBlock(node);
|
|
2169
2610
|
default:
|
|
2170
2611
|
return assertNever(node);
|
|
2171
2612
|
}
|
|
@@ -2197,16 +2638,30 @@ function pmDocToAST(pmDoc) {
|
|
|
2197
2638
|
return fromProseMirrorJSON(json);
|
|
2198
2639
|
}
|
|
2199
2640
|
function useEditorView(config) {
|
|
2200
|
-
const viewRef = useRef(null);
|
|
2201
2641
|
const viewInstanceRef = useRef(null);
|
|
2642
|
+
const containerRef = useRef(null);
|
|
2202
2643
|
const [, forceUpdate] = useState(0);
|
|
2203
2644
|
const configRef = useRef(config);
|
|
2204
2645
|
configRef.current = config;
|
|
2205
2646
|
useEffect(() => {
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2647
|
+
return () => {
|
|
2648
|
+
viewInstanceRef.current?.destroy();
|
|
2649
|
+
viewInstanceRef.current = null;
|
|
2650
|
+
};
|
|
2651
|
+
}, []);
|
|
2652
|
+
const viewRef = useCallback((container) => {
|
|
2653
|
+
if (container === containerRef.current) return;
|
|
2654
|
+
if (viewInstanceRef.current) {
|
|
2655
|
+
viewInstanceRef.current.destroy();
|
|
2656
|
+
viewInstanceRef.current = null;
|
|
2657
|
+
}
|
|
2658
|
+
containerRef.current = container;
|
|
2659
|
+
if (!container) {
|
|
2660
|
+
forceUpdate((n) => n + 1);
|
|
2661
|
+
return;
|
|
2662
|
+
}
|
|
2663
|
+
const { pmPlugins, nodeViews } = createPluginArray(configRef.current.plugins ?? []);
|
|
2664
|
+
const state = docToState(configRef.current.content, pmPlugins);
|
|
2210
2665
|
const view = new EditorView(container, {
|
|
2211
2666
|
state,
|
|
2212
2667
|
nodeViews,
|
|
@@ -2223,10 +2678,6 @@ function useEditorView(config) {
|
|
|
2223
2678
|
});
|
|
2224
2679
|
viewInstanceRef.current = view;
|
|
2225
2680
|
forceUpdate((n) => n + 1);
|
|
2226
|
-
return () => {
|
|
2227
|
-
view.destroy();
|
|
2228
|
-
viewInstanceRef.current = null;
|
|
2229
|
-
};
|
|
2230
2681
|
}, []);
|
|
2231
2682
|
const getAST = useCallback(() => {
|
|
2232
2683
|
const view = viewInstanceRef.current;
|
|
@@ -2244,6 +2695,7 @@ function useEditorView(config) {
|
|
|
2244
2695
|
const pmJSON = toProseMirrorJSON(doc2);
|
|
2245
2696
|
const pmDoc = PMNode.fromJSON(actionbookSchema, pmJSON);
|
|
2246
2697
|
const tr = view.state.tr.replaceWith(0, view.state.doc.content.size, pmDoc.content);
|
|
2698
|
+
tr.setMeta("addToHistory", false);
|
|
2247
2699
|
view.dispatch(tr);
|
|
2248
2700
|
}, []);
|
|
2249
2701
|
const focus = useCallback(() => {
|
|
@@ -2253,9 +2705,11 @@ function useEditorView(config) {
|
|
|
2253
2705
|
viewInstanceRef.current?.destroy();
|
|
2254
2706
|
viewInstanceRef.current = null;
|
|
2255
2707
|
}, []);
|
|
2708
|
+
const getView = useCallback(() => viewInstanceRef.current, []);
|
|
2256
2709
|
return {
|
|
2257
2710
|
viewRef,
|
|
2258
2711
|
view: viewInstanceRef.current,
|
|
2712
|
+
getView,
|
|
2259
2713
|
getAST,
|
|
2260
2714
|
getMarkdown,
|
|
2261
2715
|
setContent,
|
|
@@ -2264,20 +2718,16 @@ function useEditorView(config) {
|
|
|
2264
2718
|
};
|
|
2265
2719
|
}
|
|
2266
2720
|
|
|
2267
|
-
// src/ui/plugin/historyPlugin.ts
|
|
2268
|
-
import { history } from "prosemirror-history";
|
|
2269
|
-
function createHistoryPlugin() {
|
|
2270
|
-
return {
|
|
2271
|
-
name: "history",
|
|
2272
|
-
plugins: () => [history()]
|
|
2273
|
-
};
|
|
2274
|
-
}
|
|
2275
|
-
|
|
2276
2721
|
// src/ui/plugin/inputRulesPlugin.ts
|
|
2277
|
-
import { InputRule, wrappingInputRule } from "prosemirror-inputrules";
|
|
2722
|
+
import { InputRule, textblockTypeInputRule, wrappingInputRule } from "prosemirror-inputrules";
|
|
2723
|
+
import { TextSelection } from "prosemirror-state";
|
|
2724
|
+
var HEADING_RE = /^(#{1,6})\s$/;
|
|
2725
|
+
var BLOCKQUOTE_RE = /^\s*>\s$/;
|
|
2726
|
+
var CODE_BLOCK_RE = /^```([a-zA-Z0-9]*)$/;
|
|
2727
|
+
var HR_RE = /^([-*_])\1{2,}$/;
|
|
2278
2728
|
var BULLET_LIST_RE = /^\s*([-*])\s$/;
|
|
2279
2729
|
var ORDERED_LIST_RE = /^(\d+)\.\s$/;
|
|
2280
|
-
var JUMP_POINT_RE2 = /\^([A-Za-z_]
|
|
2730
|
+
var JUMP_POINT_RE2 = /\^([A-Za-z_]+)\^$/;
|
|
2281
2731
|
var BOLD_STAR_RE = /(?:^|[^*])\*\*([^*]+)\*\*$/;
|
|
2282
2732
|
var BOLD_UNDER_RE = /(?:^|[^_])__([^_]+)__$/;
|
|
2283
2733
|
var ITALIC_STAR_RE = /(?:^|[^*])\*([^*]+)\*$/;
|
|
@@ -2288,11 +2738,14 @@ function markInputRule(pattern, markType, markerLen) {
|
|
|
2288
2738
|
return new InputRule(pattern, (state, match, start, end) => {
|
|
2289
2739
|
const textContent2 = match[1];
|
|
2290
2740
|
const fullMatch = match[0];
|
|
2291
|
-
const
|
|
2741
|
+
const markedLength = markerLen * 2 + textContent2.length;
|
|
2742
|
+
const prefixLen = fullMatch.length - markedLength;
|
|
2743
|
+
const deleteFrom = start + prefixLen;
|
|
2292
2744
|
const tr = state.tr;
|
|
2293
|
-
tr.delete(
|
|
2745
|
+
tr.delete(deleteFrom, end);
|
|
2294
2746
|
const textNode = state.schema.text(textContent2, [markType.create()]);
|
|
2295
|
-
tr.insert(
|
|
2747
|
+
tr.insert(deleteFrom, textNode);
|
|
2748
|
+
tr.removeStoredMark(markType);
|
|
2296
2749
|
return tr;
|
|
2297
2750
|
});
|
|
2298
2751
|
}
|
|
@@ -2301,12 +2754,41 @@ function createInputRulesPlugin() {
|
|
|
2301
2754
|
name: "inputRules",
|
|
2302
2755
|
inputRules: () => {
|
|
2303
2756
|
const rules = [];
|
|
2304
|
-
rules.push(wrappingInputRule(BULLET_LIST_RE, actionbookSchema.nodes.bulletList));
|
|
2305
2757
|
rules.push(
|
|
2306
|
-
|
|
2307
|
-
|
|
2758
|
+
textblockTypeInputRule(HEADING_RE, actionbookSchema.nodes.heading, (match) => ({
|
|
2759
|
+
level: match[1].length
|
|
2308
2760
|
}))
|
|
2309
2761
|
);
|
|
2762
|
+
rules.push(wrappingInputRule(BLOCKQUOTE_RE, actionbookSchema.nodes.blockquote));
|
|
2763
|
+
rules.push(
|
|
2764
|
+
new InputRule(CODE_BLOCK_RE, (state, match, start, end) => {
|
|
2765
|
+
const language = match[1] || null;
|
|
2766
|
+
const $start = state.doc.resolve(start);
|
|
2767
|
+
const blockStart = $start.before($start.depth);
|
|
2768
|
+
const blockEnd = $start.after($start.depth);
|
|
2769
|
+
const tr = state.tr;
|
|
2770
|
+
tr.replaceWith(
|
|
2771
|
+
blockStart,
|
|
2772
|
+
blockEnd,
|
|
2773
|
+
actionbookSchema.nodes.codeBlock.create({ language })
|
|
2774
|
+
);
|
|
2775
|
+
return tr;
|
|
2776
|
+
})
|
|
2777
|
+
);
|
|
2778
|
+
rules.push(
|
|
2779
|
+
new InputRule(HR_RE, (state, _match, start, end) => {
|
|
2780
|
+
const { horizontalRule: hrType, paragraph: pType } = actionbookSchema.nodes;
|
|
2781
|
+
const $start = state.doc.resolve(start);
|
|
2782
|
+
const blockStart = $start.before($start.depth);
|
|
2783
|
+
const blockEnd = $start.after($start.depth);
|
|
2784
|
+
const tr = state.tr;
|
|
2785
|
+
tr.replaceWith(blockStart, blockEnd, [hrType.create(), pType.create()]);
|
|
2786
|
+
tr.setSelection(
|
|
2787
|
+
TextSelection.near(tr.doc.resolve(blockStart + hrType.createAndFill().nodeSize + 1))
|
|
2788
|
+
);
|
|
2789
|
+
return tr;
|
|
2790
|
+
})
|
|
2791
|
+
);
|
|
2310
2792
|
rules.push(
|
|
2311
2793
|
new InputRule(/^\s*[-*]\s\[([ xX])\]\s$/, (state, match, start, end) => {
|
|
2312
2794
|
const checked = match[1] !== " ";
|
|
@@ -2316,6 +2798,12 @@ function createInputRulesPlugin() {
|
|
|
2316
2798
|
return state.tr.delete(start, end).insert(start, list);
|
|
2317
2799
|
})
|
|
2318
2800
|
);
|
|
2801
|
+
rules.push(wrappingInputRule(BULLET_LIST_RE, actionbookSchema.nodes.bulletList));
|
|
2802
|
+
rules.push(
|
|
2803
|
+
wrappingInputRule(ORDERED_LIST_RE, actionbookSchema.nodes.orderedList, (match) => ({
|
|
2804
|
+
start: +match[1]
|
|
2805
|
+
}))
|
|
2806
|
+
);
|
|
2319
2807
|
const jumpPointType = actionbookSchema.nodes.jumpPoint;
|
|
2320
2808
|
rules.push(
|
|
2321
2809
|
new InputRule(JUMP_POINT_RE2, (state, match, start, end) => {
|
|
@@ -2342,24 +2830,85 @@ function createInputRulesPlugin() {
|
|
|
2342
2830
|
};
|
|
2343
2831
|
}
|
|
2344
2832
|
|
|
2833
|
+
// src/ui/plugin/historyPlugin.ts
|
|
2834
|
+
import { history, undo, redo } from "prosemirror-history";
|
|
2835
|
+
import { keymap as keymap2 } from "prosemirror-keymap";
|
|
2836
|
+
function createHistoryPlugin() {
|
|
2837
|
+
return {
|
|
2838
|
+
name: "history",
|
|
2839
|
+
plugins: () => [
|
|
2840
|
+
history(),
|
|
2841
|
+
keymap2({ "Mod-z": undo, "Mod-Shift-z": redo, "Mod-y": redo })
|
|
2842
|
+
]
|
|
2843
|
+
};
|
|
2844
|
+
}
|
|
2845
|
+
|
|
2345
2846
|
// src/ui/plugin/keymapPlugin.ts
|
|
2346
|
-
import { chainCommands, newlineInCode, createParagraphNear, liftEmptyBlock, splitBlock, toggleMark } from "prosemirror-commands";
|
|
2847
|
+
import { baseKeymap, chainCommands, newlineInCode, createParagraphNear, liftEmptyBlock, splitBlock, toggleMark, setBlockType, joinBackward } from "prosemirror-commands";
|
|
2848
|
+
import { keymap as keymap3 } from "prosemirror-keymap";
|
|
2347
2849
|
import { liftListItem, sinkListItem, splitListItem, wrapInList } from "prosemirror-schema-list";
|
|
2348
2850
|
var TAB_CHAR = " ";
|
|
2349
|
-
var { listItem, bulletList, orderedList, hardBreak } = actionbookSchema.nodes;
|
|
2851
|
+
var { listItem, bulletList, orderedList, hardBreak, heading, paragraph, horizontalRule, blockquote } = actionbookSchema.nodes;
|
|
2350
2852
|
var { bold: boldMark, italic: italicMark, underline: underlineMark, strikethrough: strikethroughMark, code: codeMark } = actionbookSchema.marks;
|
|
2351
2853
|
function cursorDirectlyInListItem(state) {
|
|
2352
2854
|
const { $from } = state.selection;
|
|
2353
2855
|
return $from.depth >= 2 && $from.node($from.depth - 1).type === listItem;
|
|
2354
2856
|
}
|
|
2355
|
-
var
|
|
2857
|
+
var backspaceAfterList = (state, dispatch) => {
|
|
2858
|
+
const { $from } = state.selection;
|
|
2859
|
+
if (!state.selection.empty) return false;
|
|
2860
|
+
if ($from.parentOffset !== 0) return false;
|
|
2861
|
+
if ($from.parent.type !== paragraph) return false;
|
|
2862
|
+
if ($from.parent.content.size !== 0) return false;
|
|
2863
|
+
const parentDepth = $from.depth - 1;
|
|
2864
|
+
if (parentDepth < 0) return false;
|
|
2865
|
+
const indexInParent = $from.index(parentDepth);
|
|
2866
|
+
if (indexInParent === 0) return false;
|
|
2867
|
+
const prevNode = $from.node(parentDepth).child(indexInParent - 1);
|
|
2868
|
+
const isList = prevNode.type === bulletList || prevNode.type === orderedList;
|
|
2869
|
+
if (!isList) return false;
|
|
2870
|
+
if (dispatch) {
|
|
2871
|
+
const from = $from.before($from.depth);
|
|
2872
|
+
const to = $from.after($from.depth);
|
|
2873
|
+
const tr = state.tr.delete(from, to);
|
|
2874
|
+
dispatch(tr.scrollIntoView());
|
|
2875
|
+
}
|
|
2876
|
+
return true;
|
|
2877
|
+
};
|
|
2878
|
+
var backspaceAfterLeafBlock = (state, dispatch) => {
|
|
2356
2879
|
const { $from } = state.selection;
|
|
2357
2880
|
if (!state.selection.empty) return false;
|
|
2358
2881
|
if ($from.parentOffset !== 0) return false;
|
|
2359
|
-
if (
|
|
2360
|
-
if ($from.
|
|
2361
|
-
|
|
2882
|
+
if ($from.parent.type !== paragraph) return false;
|
|
2883
|
+
if ($from.parent.content.size !== 0) return false;
|
|
2884
|
+
const parentDepth = $from.depth - 1;
|
|
2885
|
+
if (parentDepth < 0) return false;
|
|
2886
|
+
const indexInParent = $from.index(parentDepth);
|
|
2887
|
+
if (indexInParent === 0) return false;
|
|
2888
|
+
const prevNode = $from.node(parentDepth).child(indexInParent - 1);
|
|
2889
|
+
if (prevNode.type !== horizontalRule) return false;
|
|
2890
|
+
if (dispatch) {
|
|
2891
|
+
const hrPos = $from.posAtIndex(indexInParent - 1, parentDepth);
|
|
2892
|
+
dispatch(state.tr.delete(hrPos, hrPos + prevNode.nodeSize).scrollIntoView());
|
|
2893
|
+
}
|
|
2894
|
+
return true;
|
|
2362
2895
|
};
|
|
2896
|
+
var backspaceCommand = chainCommands(
|
|
2897
|
+
backspaceAfterList,
|
|
2898
|
+
backspaceAfterLeafBlock,
|
|
2899
|
+
(state, dispatch) => {
|
|
2900
|
+
const { $from } = state.selection;
|
|
2901
|
+
if (!state.selection.empty) return false;
|
|
2902
|
+
if ($from.parentOffset !== 0) return false;
|
|
2903
|
+
if ($from.parent.type === heading) {
|
|
2904
|
+
return setBlockType(paragraph)(state, dispatch);
|
|
2905
|
+
}
|
|
2906
|
+
if (!cursorDirectlyInListItem(state)) return false;
|
|
2907
|
+
if ($from.index($from.depth - 1) !== 0) return false;
|
|
2908
|
+
return liftListItem(listItem)(state, dispatch);
|
|
2909
|
+
},
|
|
2910
|
+
joinBackward
|
|
2911
|
+
);
|
|
2363
2912
|
var tabCommand = (state, dispatch) => {
|
|
2364
2913
|
const { $from } = state.selection;
|
|
2365
2914
|
if (cursorDirectlyInListItem(state) && $from.parentOffset === 0) {
|
|
@@ -2412,12 +2961,13 @@ function createKeymapPlugin() {
|
|
|
2412
2961
|
"Mod-e": toggleMark(codeMark),
|
|
2413
2962
|
"Mod-Shift-7": wrapInList(bulletList),
|
|
2414
2963
|
"Mod-Shift-8": wrapInList(orderedList)
|
|
2415
|
-
})
|
|
2964
|
+
}),
|
|
2965
|
+
plugins: () => [keymap3(baseKeymap)]
|
|
2416
2966
|
};
|
|
2417
2967
|
}
|
|
2418
2968
|
|
|
2419
2969
|
// src/ui/plugin/markdownClipboard.ts
|
|
2420
|
-
import { Fragment, Slice } from "prosemirror-model";
|
|
2970
|
+
import { DOMParser as ProseMirrorDOMParser, Fragment, Slice } from "prosemirror-model";
|
|
2421
2971
|
import { Plugin, PluginKey } from "prosemirror-state";
|
|
2422
2972
|
|
|
2423
2973
|
// src/ast/traverse.ts
|
|
@@ -2433,6 +2983,7 @@ function getChildren(node) {
|
|
|
2433
2983
|
case "doc":
|
|
2434
2984
|
case "blockquote":
|
|
2435
2985
|
case "listItem":
|
|
2986
|
+
case "noteBlock":
|
|
2436
2987
|
return node.content;
|
|
2437
2988
|
case "paragraph":
|
|
2438
2989
|
case "heading":
|
|
@@ -3904,6 +4455,23 @@ var gfmNoAutolinkFromMarkdown = () => [
|
|
|
3904
4455
|
gfmTaskListItemFromMarkdown()
|
|
3905
4456
|
];
|
|
3906
4457
|
var MAX_DEPTH5 = 128;
|
|
4458
|
+
var BRACKET_LINK_RE = /\[([^\]]+)\]\(([^)]*\s[^)]*)\)/g;
|
|
4459
|
+
function splitTextWithBracketLinks(value) {
|
|
4460
|
+
const results = [];
|
|
4461
|
+
let lastIndex = 0;
|
|
4462
|
+
for (const m of value.matchAll(BRACKET_LINK_RE)) {
|
|
4463
|
+
const idx = m.index;
|
|
4464
|
+
if (idx > lastIndex) results.push({ type: "text", value: value.slice(lastIndex, idx) });
|
|
4465
|
+
results.push({
|
|
4466
|
+
type: "link",
|
|
4467
|
+
url: m[2],
|
|
4468
|
+
children: [{ type: "text", value: m[1] }]
|
|
4469
|
+
});
|
|
4470
|
+
lastIndex = idx + m[0].length;
|
|
4471
|
+
}
|
|
4472
|
+
if (lastIndex < value.length) results.push({ type: "text", value: value.slice(lastIndex) });
|
|
4473
|
+
return results;
|
|
4474
|
+
}
|
|
3907
4475
|
function combinedTokensFromMarkdown(node, depth = 0) {
|
|
3908
4476
|
if (depth > MAX_DEPTH5) return;
|
|
3909
4477
|
if (!node.children) return;
|
|
@@ -3915,16 +4483,23 @@ function combinedTokensFromMarkdown(node, depth = 0) {
|
|
|
3915
4483
|
for (const child of node.children) {
|
|
3916
4484
|
const c = child;
|
|
3917
4485
|
if (c.type === "text") {
|
|
3918
|
-
const
|
|
3919
|
-
for (const
|
|
3920
|
-
if (
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
} else {
|
|
3924
|
-
newChildren.push(part);
|
|
4486
|
+
const afterLinks = splitTextWithBracketLinks(child.value);
|
|
4487
|
+
for (const linkPart of afterLinks) {
|
|
4488
|
+
if (linkPart.type !== "text") {
|
|
4489
|
+
newChildren.push(linkPart);
|
|
4490
|
+
continue;
|
|
3925
4491
|
}
|
|
3926
|
-
|
|
3927
|
-
|
|
4492
|
+
const afterResourceTags = splitTextWithResourceTags(linkPart.value);
|
|
4493
|
+
for (const part of afterResourceTags) {
|
|
4494
|
+
if (part.type === "text") {
|
|
4495
|
+
const afterJumpPoints = splitTextWithJumpPoints(part.value);
|
|
4496
|
+
newChildren.push(...afterJumpPoints);
|
|
4497
|
+
} else {
|
|
4498
|
+
newChildren.push(part);
|
|
4499
|
+
}
|
|
4500
|
+
}
|
|
4501
|
+
}
|
|
4502
|
+
} else {
|
|
3928
4503
|
newChildren.push(child);
|
|
3929
4504
|
}
|
|
3930
4505
|
}
|
|
@@ -4128,8 +4703,198 @@ function analyzeJinjaBlocks(doc2) {
|
|
|
4128
4703
|
});
|
|
4129
4704
|
}
|
|
4130
4705
|
|
|
4706
|
+
// src/tree/documentTree.ts
|
|
4707
|
+
var MAX_DEPTH6 = 128;
|
|
4708
|
+
function extractInlineItems(content, blockIndex) {
|
|
4709
|
+
const items = [];
|
|
4710
|
+
for (const node of content) {
|
|
4711
|
+
if (node.type === "jumpPoint") {
|
|
4712
|
+
items.push({
|
|
4713
|
+
type: "jumpPoint",
|
|
4714
|
+
label: node.id,
|
|
4715
|
+
blockIndex,
|
|
4716
|
+
children: []
|
|
4717
|
+
});
|
|
4718
|
+
} else if (node.type === "resourceTag") {
|
|
4719
|
+
const isEndAction = node.tagType === "handoff";
|
|
4720
|
+
items.push({
|
|
4721
|
+
type: isEndAction ? "endAction" : "resourceTag",
|
|
4722
|
+
label: isEndAction ? `End ${node.text}` : node.text,
|
|
4723
|
+
blockIndex,
|
|
4724
|
+
children: [],
|
|
4725
|
+
meta: { tagType: node.tagType, resourceId: node.resourceId }
|
|
4726
|
+
});
|
|
4727
|
+
}
|
|
4728
|
+
}
|
|
4729
|
+
return items;
|
|
4730
|
+
}
|
|
4731
|
+
function extractBlockItems(blocks, startIndex, depth) {
|
|
4732
|
+
if (depth > MAX_DEPTH6) return [];
|
|
4733
|
+
const items = [];
|
|
4734
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
4735
|
+
const block = blocks[i];
|
|
4736
|
+
const blockIndex = startIndex + i;
|
|
4737
|
+
switch (block.type) {
|
|
4738
|
+
case "heading": {
|
|
4739
|
+
const label = textContent(block) || `Heading ${block.level}`;
|
|
4740
|
+
const inlineItems = extractInlineItems(block.content, blockIndex);
|
|
4741
|
+
items.push({
|
|
4742
|
+
type: "heading",
|
|
4743
|
+
label,
|
|
4744
|
+
blockIndex,
|
|
4745
|
+
children: inlineItems,
|
|
4746
|
+
meta: { level: block.level }
|
|
4747
|
+
});
|
|
4748
|
+
break;
|
|
4749
|
+
}
|
|
4750
|
+
case "paragraph": {
|
|
4751
|
+
const inlineItems = extractInlineItems(block.content, blockIndex);
|
|
4752
|
+
items.push(...inlineItems);
|
|
4753
|
+
break;
|
|
4754
|
+
}
|
|
4755
|
+
case "jinjaIfBlock": {
|
|
4756
|
+
const branches = block.branches.map((branch) => {
|
|
4757
|
+
const branchLabel = branch.branchType === "else" ? "ELSE" : `${branch.branchType.toUpperCase()} ${branch.condition || ""}`.trim();
|
|
4758
|
+
const branchChildren = extractBlockItems(branch.content, blockIndex, depth + 1);
|
|
4759
|
+
return {
|
|
4760
|
+
type: "jinjaBranch",
|
|
4761
|
+
label: branchLabel,
|
|
4762
|
+
blockIndex,
|
|
4763
|
+
children: branchChildren
|
|
4764
|
+
};
|
|
4765
|
+
});
|
|
4766
|
+
items.push({
|
|
4767
|
+
type: "jinjaIf",
|
|
4768
|
+
label: "Jinja if",
|
|
4769
|
+
blockIndex,
|
|
4770
|
+
children: branches
|
|
4771
|
+
});
|
|
4772
|
+
break;
|
|
4773
|
+
}
|
|
4774
|
+
case "noteBlock": {
|
|
4775
|
+
const noteContent = textContent(block);
|
|
4776
|
+
items.push({
|
|
4777
|
+
type: "noteBlock",
|
|
4778
|
+
label: noteContent ? `Note: ${noteContent.slice(0, 30)}` : "Note",
|
|
4779
|
+
blockIndex,
|
|
4780
|
+
children: []
|
|
4781
|
+
});
|
|
4782
|
+
break;
|
|
4783
|
+
}
|
|
4784
|
+
case "bulletList":
|
|
4785
|
+
case "orderedList": {
|
|
4786
|
+
for (const li of block.content) {
|
|
4787
|
+
const childItems = extractBlockItems(li.content, blockIndex, depth + 1);
|
|
4788
|
+
items.push(...childItems);
|
|
4789
|
+
}
|
|
4790
|
+
break;
|
|
4791
|
+
}
|
|
4792
|
+
case "blockquote": {
|
|
4793
|
+
const childItems = extractBlockItems(block.content, blockIndex, depth + 1);
|
|
4794
|
+
items.push(...childItems);
|
|
4795
|
+
break;
|
|
4796
|
+
}
|
|
4797
|
+
default:
|
|
4798
|
+
break;
|
|
4799
|
+
}
|
|
4800
|
+
}
|
|
4801
|
+
return items;
|
|
4802
|
+
}
|
|
4803
|
+
function buildDocumentTree(doc2) {
|
|
4804
|
+
const items = extractBlockItems(doc2.content, 0, 0);
|
|
4805
|
+
try {
|
|
4806
|
+
const structures = analyzeJinjaBlocks(doc2);
|
|
4807
|
+
if (structures.length > 0) {
|
|
4808
|
+
const hasStructuredJinja = items.some((n) => n.type === "jinjaIf");
|
|
4809
|
+
if (!hasStructuredJinja) {
|
|
4810
|
+
for (const s of structures) {
|
|
4811
|
+
const branches = s.branches.map((b) => ({
|
|
4812
|
+
type: "jinjaBranch",
|
|
4813
|
+
label: b.type === "else" ? "ELSE" : `${b.type.toUpperCase()} ${b.condition || ""}`.trim(),
|
|
4814
|
+
blockIndex: b.tagBlockIndex,
|
|
4815
|
+
children: []
|
|
4816
|
+
}));
|
|
4817
|
+
const jinjaNode = {
|
|
4818
|
+
type: "jinjaIf",
|
|
4819
|
+
label: "Jinja if",
|
|
4820
|
+
blockIndex: s.ifTagBlockIndex,
|
|
4821
|
+
children: branches
|
|
4822
|
+
};
|
|
4823
|
+
let inserted = false;
|
|
4824
|
+
for (let i = 0; i < items.length; i++) {
|
|
4825
|
+
if (items[i].blockIndex > s.ifTagBlockIndex) {
|
|
4826
|
+
items.splice(i, 0, jinjaNode);
|
|
4827
|
+
inserted = true;
|
|
4828
|
+
break;
|
|
4829
|
+
}
|
|
4830
|
+
}
|
|
4831
|
+
if (!inserted) items.push(jinjaNode);
|
|
4832
|
+
}
|
|
4833
|
+
}
|
|
4834
|
+
}
|
|
4835
|
+
} catch {
|
|
4836
|
+
}
|
|
4837
|
+
return items;
|
|
4838
|
+
}
|
|
4839
|
+
|
|
4131
4840
|
// src/ui/plugin/markdownClipboard.ts
|
|
4132
4841
|
var key = new PluginKey("markdownClipboard");
|
|
4842
|
+
var MAX_PASTE_LIST_DEPTH = 3;
|
|
4843
|
+
var MAX_FLATTEN_DEPTH = 128;
|
|
4844
|
+
function flattenDeepLists(node, listDepth = 0, _recurseDepth = 0) {
|
|
4845
|
+
if (_recurseDepth > MAX_FLATTEN_DEPTH) return node;
|
|
4846
|
+
const isList = node.type.name === "bulletList" || node.type.name === "orderedList";
|
|
4847
|
+
const currentDepth = isList ? listDepth + 1 : listDepth;
|
|
4848
|
+
if (isList && currentDepth >= MAX_PASTE_LIST_DEPTH) {
|
|
4849
|
+
const flatItems = [];
|
|
4850
|
+
node.forEach((li) => {
|
|
4851
|
+
const nonListBlocks = [];
|
|
4852
|
+
li.forEach((block) => {
|
|
4853
|
+
if (block.type.name !== "bulletList" && block.type.name !== "orderedList") {
|
|
4854
|
+
nonListBlocks.push(block);
|
|
4855
|
+
}
|
|
4856
|
+
});
|
|
4857
|
+
if (nonListBlocks.length > 0) {
|
|
4858
|
+
flatItems.push(li.type.create(li.attrs, nonListBlocks));
|
|
4859
|
+
}
|
|
4860
|
+
});
|
|
4861
|
+
if (flatItems.length === 0) return node;
|
|
4862
|
+
return node.copy(Fragment.fromArray(flatItems));
|
|
4863
|
+
}
|
|
4864
|
+
const children = [];
|
|
4865
|
+
let changed = false;
|
|
4866
|
+
node.forEach((child) => {
|
|
4867
|
+
const flattened = flattenDeepLists(child, currentDepth, _recurseDepth + 1);
|
|
4868
|
+
if (flattened !== child) changed = true;
|
|
4869
|
+
children.push(flattened);
|
|
4870
|
+
});
|
|
4871
|
+
if (!changed) return node;
|
|
4872
|
+
return node.copy(Fragment.fromArray(children));
|
|
4873
|
+
}
|
|
4874
|
+
function htmlToSlice(html) {
|
|
4875
|
+
if (typeof document === "undefined") return null;
|
|
4876
|
+
try {
|
|
4877
|
+
const domParser = new DOMParser();
|
|
4878
|
+
const parsed = domParser.parseFromString(html, "text/html");
|
|
4879
|
+
const body = parsed.body;
|
|
4880
|
+
if (!body || !body.childNodes.length) return null;
|
|
4881
|
+
const pmParser = ProseMirrorDOMParser.fromSchema(actionbookSchema);
|
|
4882
|
+
const doc2 = pmParser.parse(body);
|
|
4883
|
+
const flattened = flattenDeepLists(doc2);
|
|
4884
|
+
const content = flattened.content;
|
|
4885
|
+
let hasContent = false;
|
|
4886
|
+
content.forEach((node) => {
|
|
4887
|
+
if (node.type.name !== "paragraph" || node.content.size > 0) {
|
|
4888
|
+
hasContent = true;
|
|
4889
|
+
}
|
|
4890
|
+
});
|
|
4891
|
+
if (!hasContent) return null;
|
|
4892
|
+
const openDepth = content.childCount === 1 && content.firstChild?.type.name === "paragraph" ? 1 : 0;
|
|
4893
|
+
return new Slice(content, openDepth, openDepth);
|
|
4894
|
+
} catch {
|
|
4895
|
+
return null;
|
|
4896
|
+
}
|
|
4897
|
+
}
|
|
4133
4898
|
function textToSlice(text2, view) {
|
|
4134
4899
|
try {
|
|
4135
4900
|
const existingIds = /* @__PURE__ */ new Set();
|
|
@@ -4156,7 +4921,15 @@ function createPlugin() {
|
|
|
4156
4921
|
key,
|
|
4157
4922
|
props: {
|
|
4158
4923
|
handlePaste(view, event) {
|
|
4924
|
+
const html = event.clipboardData?.getData("text/html");
|
|
4159
4925
|
const text2 = event.clipboardData?.getData("text/plain");
|
|
4926
|
+
if (html) {
|
|
4927
|
+
const htmlSlice = htmlToSlice(html);
|
|
4928
|
+
if (htmlSlice) {
|
|
4929
|
+
view.dispatch(view.state.tr.replaceSelection(htmlSlice));
|
|
4930
|
+
return true;
|
|
4931
|
+
}
|
|
4932
|
+
}
|
|
4160
4933
|
if (!text2) return false;
|
|
4161
4934
|
const slice = textToSlice(text2, view);
|
|
4162
4935
|
if (!slice) return false;
|
|
@@ -4172,9 +4945,14 @@ function createPlugin() {
|
|
|
4172
4945
|
}
|
|
4173
4946
|
return slice;
|
|
4174
4947
|
},
|
|
4175
|
-
//
|
|
4176
|
-
|
|
4177
|
-
|
|
4948
|
+
// Transform pasted HTML: keep structure but flatten deep lists
|
|
4949
|
+
// to prevent Chrome contentEditable hanging
|
|
4950
|
+
transformPasted(slice) {
|
|
4951
|
+
const nodes = [];
|
|
4952
|
+
slice.content.forEach((node) => {
|
|
4953
|
+
nodes.push(flattenDeepLists(node));
|
|
4954
|
+
});
|
|
4955
|
+
return new Slice(Fragment.fromArray(nodes), slice.openStart, slice.openEnd);
|
|
4178
4956
|
},
|
|
4179
4957
|
clipboardTextSerializer(slice) {
|
|
4180
4958
|
try {
|
|
@@ -4197,7 +4975,7 @@ function createMarkdownClipboardPlugin() {
|
|
|
4197
4975
|
}
|
|
4198
4976
|
|
|
4199
4977
|
// src/ui/plugin/jumpPointPlugin.ts
|
|
4200
|
-
import { Plugin as Plugin2, PluginKey as PluginKey2, TextSelection } from "prosemirror-state";
|
|
4978
|
+
import { Plugin as Plugin2, PluginKey as PluginKey2, TextSelection as TextSelection2 } from "prosemirror-state";
|
|
4201
4979
|
import { Decoration, DecorationSet } from "prosemirror-view";
|
|
4202
4980
|
var adjacentKey = new PluginKey2("jumpPointAdjacent");
|
|
4203
4981
|
var JUMP_POINT_ADJACENT_SPEC = { jumpPointAdjacent: true };
|
|
@@ -4268,8 +5046,15 @@ function createJumpPointEditPlugin() {
|
|
|
4268
5046
|
}
|
|
4269
5047
|
});
|
|
4270
5048
|
}
|
|
4271
|
-
function
|
|
5049
|
+
function jumpPointAtOrBefore(state) {
|
|
4272
5050
|
const { selection } = state;
|
|
5051
|
+
if ("node" in selection) {
|
|
5052
|
+
const node = selection.node;
|
|
5053
|
+
if (node?.type?.name === "jumpPoint") {
|
|
5054
|
+
return { id: node.attrs.id, nodeStart: selection.from, nodeEnd: selection.to };
|
|
5055
|
+
}
|
|
5056
|
+
return null;
|
|
5057
|
+
}
|
|
4273
5058
|
if (!selection.empty) return null;
|
|
4274
5059
|
const { $from } = selection;
|
|
4275
5060
|
const nodeBefore = $from.nodeBefore;
|
|
@@ -4279,23 +5064,23 @@ function jumpPointBefore(state) {
|
|
|
4279
5064
|
return { id: nodeBefore.attrs.id, nodeStart, nodeEnd };
|
|
4280
5065
|
}
|
|
4281
5066
|
function explodeOnBackspace(state) {
|
|
4282
|
-
const info =
|
|
5067
|
+
const info = jumpPointAtOrBefore(state);
|
|
4283
5068
|
if (!info) return null;
|
|
4284
5069
|
const { id, nodeStart, nodeEnd } = info;
|
|
4285
5070
|
const rawText = `^${id}`;
|
|
4286
5071
|
const tr = state.tr.replaceWith(nodeStart, nodeEnd, state.schema.text(rawText));
|
|
4287
5072
|
const cursorPos = Math.min(nodeStart + rawText.length, tr.doc.content.size);
|
|
4288
|
-
tr.setSelection(
|
|
5073
|
+
tr.setSelection(TextSelection2.near(tr.doc.resolve(cursorPos)));
|
|
4289
5074
|
return tr;
|
|
4290
5075
|
}
|
|
4291
5076
|
function explodeOnArrowLeft(state) {
|
|
4292
|
-
const info =
|
|
5077
|
+
const info = jumpPointAtOrBefore(state);
|
|
4293
5078
|
if (!info) return null;
|
|
4294
5079
|
const { id, nodeStart, nodeEnd } = info;
|
|
4295
5080
|
const rawText = `^${id}^`;
|
|
4296
5081
|
const tr = state.tr.replaceWith(nodeStart, nodeEnd, state.schema.text(rawText));
|
|
4297
5082
|
const cursorPos = Math.min(nodeStart + 1 + id.length, tr.doc.content.size);
|
|
4298
|
-
tr.setSelection(
|
|
5083
|
+
tr.setSelection(TextSelection2.near(tr.doc.resolve(cursorPos)));
|
|
4299
5084
|
tr.setMeta(jumpPointEditKey, { from: nodeStart, to: nodeStart + rawText.length });
|
|
4300
5085
|
return tr;
|
|
4301
5086
|
}
|
|
@@ -4342,6 +5127,7 @@ function createJumpPointAdjacentPlugin() {
|
|
|
4342
5127
|
}
|
|
4343
5128
|
|
|
4344
5129
|
// src/ui/plugin/jumpPointNodeViewPlugin.tsx
|
|
5130
|
+
import { useCallback as useCallback2, useState as useState2 } from "react";
|
|
4345
5131
|
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
4346
5132
|
var JUMP_POINT_STYLE = {
|
|
4347
5133
|
display: "inline-flex",
|
|
@@ -4349,31 +5135,118 @@ var JUMP_POINT_STYLE = {
|
|
|
4349
5135
|
backgroundColor: "#FFF2B6",
|
|
4350
5136
|
border: "1px solid #FFC233",
|
|
4351
5137
|
color: "#AA5D04",
|
|
4352
|
-
borderRadius: "
|
|
4353
|
-
padding: "
|
|
4354
|
-
fontSize: "
|
|
4355
|
-
lineHeight:
|
|
5138
|
+
borderRadius: "2px",
|
|
5139
|
+
padding: "2px",
|
|
5140
|
+
fontSize: "12px",
|
|
5141
|
+
lineHeight: "16px",
|
|
4356
5142
|
userSelect: "none",
|
|
4357
5143
|
cursor: "default",
|
|
4358
|
-
boxSizing: "border-box"
|
|
5144
|
+
boxSizing: "border-box",
|
|
5145
|
+
height: "20px",
|
|
5146
|
+
overflow: "hidden"
|
|
4359
5147
|
};
|
|
4360
5148
|
var JUMP_POINT_ADJACENT_STYLE = {
|
|
4361
5149
|
...JUMP_POINT_STYLE,
|
|
4362
5150
|
backgroundColor: "#FFE680",
|
|
4363
5151
|
borderColor: "#FF9500"
|
|
4364
5152
|
};
|
|
4365
|
-
|
|
5153
|
+
var JUMP_POINT_DUPLICATE_STYLE = {
|
|
5154
|
+
...JUMP_POINT_STYLE,
|
|
5155
|
+
backgroundColor: "#FFD9DD",
|
|
5156
|
+
borderColor: "#D9352C",
|
|
5157
|
+
color: "#9D091E"
|
|
5158
|
+
};
|
|
5159
|
+
var LABEL_STYLE = {
|
|
5160
|
+
padding: "0 4px",
|
|
5161
|
+
whiteSpace: "nowrap"
|
|
5162
|
+
};
|
|
5163
|
+
var CLOSE_BTN_STYLE = {
|
|
5164
|
+
display: "inline-flex",
|
|
5165
|
+
alignItems: "center",
|
|
5166
|
+
justifyContent: "center",
|
|
5167
|
+
width: "16px",
|
|
5168
|
+
height: "16px",
|
|
5169
|
+
padding: 0,
|
|
5170
|
+
border: "none",
|
|
5171
|
+
background: "transparent",
|
|
5172
|
+
cursor: "pointer",
|
|
5173
|
+
borderRadius: "1px",
|
|
5174
|
+
flexShrink: 0,
|
|
5175
|
+
color: "inherit",
|
|
5176
|
+
fontSize: "10px",
|
|
5177
|
+
lineHeight: 1
|
|
5178
|
+
};
|
|
5179
|
+
var TOOLTIP_STYLE = {
|
|
5180
|
+
position: "absolute",
|
|
5181
|
+
bottom: "calc(100% + 8px)",
|
|
5182
|
+
left: "50%",
|
|
5183
|
+
transform: "translateX(-50%)",
|
|
5184
|
+
backgroundColor: "#fff",
|
|
5185
|
+
border: "1px solid #CCC",
|
|
5186
|
+
borderRadius: "4px",
|
|
5187
|
+
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)",
|
|
5188
|
+
padding: "16px 20px",
|
|
5189
|
+
fontSize: "14px",
|
|
5190
|
+
lineHeight: "20px",
|
|
5191
|
+
color: "#0D0D0D",
|
|
5192
|
+
whiteSpace: "nowrap",
|
|
5193
|
+
zIndex: 100,
|
|
5194
|
+
pointerEvents: "none"
|
|
5195
|
+
};
|
|
5196
|
+
function JumpPointNodeViewComponent({ node, view, getPos, decorations }) {
|
|
4366
5197
|
const id = node.attrs.id;
|
|
4367
5198
|
const isAdjacent = decorations?.some((d) => d.spec?.jumpPointAdjacent === true) ?? false;
|
|
5199
|
+
const isDuplicate = decorations?.some((d) => d.spec?.jumpPointDuplicate === true) ?? false;
|
|
5200
|
+
const [showTooltip, setShowTooltip] = useState2(false);
|
|
5201
|
+
const handleDelete2 = useCallback2(() => {
|
|
5202
|
+
const pos = getPos();
|
|
5203
|
+
if (pos == null) return;
|
|
5204
|
+
const tr = view.state.tr.delete(pos, pos + node.nodeSize);
|
|
5205
|
+
view.dispatch(tr);
|
|
5206
|
+
view.focus();
|
|
5207
|
+
}, [view, getPos, node.nodeSize]);
|
|
5208
|
+
if (isDuplicate) {
|
|
5209
|
+
return /* @__PURE__ */ jsxs3(
|
|
5210
|
+
"span",
|
|
5211
|
+
{
|
|
5212
|
+
style: { ...JUMP_POINT_DUPLICATE_STYLE, position: "relative" },
|
|
5213
|
+
id: `jp-${id}`,
|
|
5214
|
+
onMouseEnter: () => setShowTooltip(true),
|
|
5215
|
+
onMouseLeave: () => setShowTooltip(false),
|
|
5216
|
+
children: [
|
|
5217
|
+
/* @__PURE__ */ jsx4(IconAnchor, { size: 12, fill: "#9D091E", style: { paddingLeft: "2px", flexShrink: 0 } }),
|
|
5218
|
+
/* @__PURE__ */ jsx4("span", { style: LABEL_STYLE, children: id }),
|
|
5219
|
+
/* @__PURE__ */ jsx4(
|
|
5220
|
+
"button",
|
|
5221
|
+
{
|
|
5222
|
+
style: CLOSE_BTN_STYLE,
|
|
5223
|
+
onMouseDown: (e) => {
|
|
5224
|
+
e.preventDefault();
|
|
5225
|
+
e.stopPropagation();
|
|
5226
|
+
handleDelete2();
|
|
5227
|
+
},
|
|
5228
|
+
title: "Remove anchor",
|
|
5229
|
+
children: "\u2715"
|
|
5230
|
+
}
|
|
5231
|
+
),
|
|
5232
|
+
showTooltip && /* @__PURE__ */ jsxs3("span", { style: TOOLTIP_STYLE, children: [
|
|
5233
|
+
"\u201C",
|
|
5234
|
+
id,
|
|
5235
|
+
"\u201D is already used as an anchor"
|
|
5236
|
+
] })
|
|
5237
|
+
]
|
|
5238
|
+
}
|
|
5239
|
+
);
|
|
5240
|
+
}
|
|
4368
5241
|
if (isAdjacent) {
|
|
4369
5242
|
return /* @__PURE__ */ jsxs3("span", { style: JUMP_POINT_ADJACENT_STYLE, id: `jp-${id}`, children: [
|
|
4370
|
-
/* @__PURE__ */ jsx4(IconAnchor, { size: 12, fill: "#AA5D04", style: {
|
|
4371
|
-
`^${id}^`
|
|
5243
|
+
/* @__PURE__ */ jsx4(IconAnchor, { size: 12, fill: "#AA5D04", style: { paddingLeft: "2px", flexShrink: 0 } }),
|
|
5244
|
+
/* @__PURE__ */ jsx4("span", { style: LABEL_STYLE, children: `^${id}^` })
|
|
4372
5245
|
] });
|
|
4373
5246
|
}
|
|
4374
5247
|
return /* @__PURE__ */ jsxs3("span", { style: JUMP_POINT_STYLE, id: `jp-${id}`, children: [
|
|
4375
|
-
/* @__PURE__ */ jsx4(IconAnchor, { size: 12, fill: "#AA5D04", style: {
|
|
4376
|
-
id
|
|
5248
|
+
/* @__PURE__ */ jsx4(IconAnchor, { size: 12, fill: "#AA5D04", style: { paddingLeft: "2px", flexShrink: 0 } }),
|
|
5249
|
+
/* @__PURE__ */ jsx4("span", { style: LABEL_STYLE, children: id })
|
|
4377
5250
|
] });
|
|
4378
5251
|
}
|
|
4379
5252
|
function createJumpPointNodeViewPlugin() {
|
|
@@ -4388,108 +5261,100 @@ function createJumpPointNodeViewPlugin() {
|
|
|
4388
5261
|
// src/ui/plugin/jumpPointValidationPlugin.ts
|
|
4389
5262
|
import { Plugin as Plugin3, PluginKey as PluginKey3 } from "prosemirror-state";
|
|
4390
5263
|
import { Decoration as Decoration2, DecorationSet as DecorationSet2 } from "prosemirror-view";
|
|
4391
|
-
var
|
|
4392
|
-
function
|
|
4393
|
-
const
|
|
4394
|
-
|
|
4395
|
-
doc2.descendants((node, pos) => {
|
|
5264
|
+
var pluginKey = new PluginKey3("jumpPointValidation");
|
|
5265
|
+
function collectJumpPointIds(state) {
|
|
5266
|
+
const ids = /* @__PURE__ */ new Set();
|
|
5267
|
+
state.doc.descendants((node) => {
|
|
4396
5268
|
if (node.type.name === "jumpPoint") {
|
|
4397
|
-
|
|
4398
|
-
if (!jumpPointIds.has(id)) jumpPointIds.set(id, []);
|
|
4399
|
-
jumpPointIds.get(id).push(pos);
|
|
4400
|
-
}
|
|
4401
|
-
if (node.isText && node.marks) {
|
|
4402
|
-
for (const mark of node.marks) {
|
|
4403
|
-
if (mark.type.name === "link") {
|
|
4404
|
-
const href = mark.attrs.href;
|
|
4405
|
-
if (href?.startsWith("#")) {
|
|
4406
|
-
anchorRefs.push({ from: pos, to: pos + node.nodeSize, id: href.slice(1) });
|
|
4407
|
-
}
|
|
4408
|
-
}
|
|
4409
|
-
}
|
|
5269
|
+
ids.add(node.attrs.id);
|
|
4410
5270
|
}
|
|
4411
5271
|
});
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
5272
|
+
return ids;
|
|
5273
|
+
}
|
|
5274
|
+
function findDuplicatePositions(state) {
|
|
5275
|
+
const idCount = /* @__PURE__ */ new Map();
|
|
5276
|
+
const nodes = [];
|
|
5277
|
+
state.doc.descendants((node, pos) => {
|
|
5278
|
+
if (node.type.name === "jumpPoint") {
|
|
5279
|
+
const id = node.attrs.id;
|
|
5280
|
+
idCount.set(id, (idCount.get(id) ?? 0) + 1);
|
|
5281
|
+
nodes.push({ id, pos, size: node.nodeSize });
|
|
4420
5282
|
}
|
|
4421
|
-
}
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
4426
|
-
|
|
5283
|
+
});
|
|
5284
|
+
return nodes.filter((n) => (idCount.get(n.id) ?? 0) > 1);
|
|
5285
|
+
}
|
|
5286
|
+
function findBrokenAnchorRefs(state, existingIds) {
|
|
5287
|
+
const broken = [];
|
|
5288
|
+
const linkMarkType = state.schema.marks.link;
|
|
5289
|
+
if (!linkMarkType) return broken;
|
|
5290
|
+
state.doc.descendants((node, pos) => {
|
|
5291
|
+
if (!node.isText) return;
|
|
5292
|
+
const linkMark2 = node.marks.find((m) => m.type === linkMarkType);
|
|
5293
|
+
if (!linkMark2) return;
|
|
5294
|
+
const href = linkMark2.attrs.href;
|
|
5295
|
+
if (!href || !href.startsWith("#")) return;
|
|
5296
|
+
const refId = href.slice(1);
|
|
5297
|
+
if (refId && !existingIds.has(refId)) {
|
|
5298
|
+
broken.push({ from: pos, to: pos + node.nodeSize, refId });
|
|
4427
5299
|
}
|
|
4428
|
-
}
|
|
4429
|
-
return
|
|
5300
|
+
});
|
|
5301
|
+
return broken;
|
|
5302
|
+
}
|
|
5303
|
+
function hasDuplicateJumpPoints(state) {
|
|
5304
|
+
return findDuplicatePositions(state).length > 0;
|
|
5305
|
+
}
|
|
5306
|
+
function hasBrokenAnchorRefs(state) {
|
|
5307
|
+
const ids = collectJumpPointIds(state);
|
|
5308
|
+
return findBrokenAnchorRefs(state, ids).length > 0;
|
|
4430
5309
|
}
|
|
4431
5310
|
function createJumpPointValidationPlugin() {
|
|
4432
5311
|
return {
|
|
4433
5312
|
name: "jumpPointValidation",
|
|
4434
5313
|
plugins: () => [
|
|
4435
5314
|
new Plugin3({
|
|
4436
|
-
key:
|
|
5315
|
+
key: pluginKey,
|
|
4437
5316
|
state: {
|
|
4438
5317
|
init(_, state) {
|
|
4439
|
-
return
|
|
5318
|
+
return buildDecorations2(state);
|
|
4440
5319
|
},
|
|
4441
|
-
apply(tr,
|
|
4442
|
-
if (
|
|
4443
|
-
|
|
5320
|
+
apply(tr, oldSet, _oldState, newState) {
|
|
5321
|
+
if (tr.docChanged) {
|
|
5322
|
+
return buildDecorations2(newState);
|
|
5323
|
+
}
|
|
5324
|
+
return oldSet.map(tr.mapping, tr.doc);
|
|
4444
5325
|
}
|
|
4445
5326
|
},
|
|
4446
5327
|
props: {
|
|
4447
5328
|
decorations(state) {
|
|
4448
|
-
return
|
|
5329
|
+
return pluginKey.getState(state) ?? DecorationSet2.empty;
|
|
4449
5330
|
}
|
|
4450
5331
|
}
|
|
4451
5332
|
})
|
|
4452
5333
|
]
|
|
4453
5334
|
};
|
|
4454
5335
|
}
|
|
4455
|
-
function
|
|
4456
|
-
const
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
let hasBroken = false;
|
|
4478
|
-
state.doc.descendants((node) => {
|
|
4479
|
-
if (hasBroken) return false;
|
|
4480
|
-
if (node.isText && node.marks) {
|
|
4481
|
-
for (const mark of node.marks) {
|
|
4482
|
-
if (mark.type.name === "link") {
|
|
4483
|
-
const href = mark.attrs.href;
|
|
4484
|
-
if (href?.startsWith("#") && !jumpPointIds.has(href.slice(1))) {
|
|
4485
|
-
hasBroken = true;
|
|
4486
|
-
return false;
|
|
4487
|
-
}
|
|
4488
|
-
}
|
|
4489
|
-
}
|
|
4490
|
-
}
|
|
4491
|
-
});
|
|
4492
|
-
return hasBroken;
|
|
5336
|
+
function buildDecorations2(state) {
|
|
5337
|
+
const decos = [];
|
|
5338
|
+
const duplicates = findDuplicatePositions(state);
|
|
5339
|
+
for (const { pos, size } of duplicates) {
|
|
5340
|
+
decos.push(
|
|
5341
|
+
Decoration2.node(pos, pos + size, { class: "jump-point-duplicate" }, { jumpPointDuplicate: true })
|
|
5342
|
+
);
|
|
5343
|
+
}
|
|
5344
|
+
const existingIds = collectJumpPointIds(state);
|
|
5345
|
+
const brokenRefs = findBrokenAnchorRefs(state, existingIds);
|
|
5346
|
+
for (const { from, to, refId } of brokenRefs) {
|
|
5347
|
+
decos.push(
|
|
5348
|
+
Decoration2.inline(from, to, {
|
|
5349
|
+
class: "broken-anchor-ref",
|
|
5350
|
+
"data-broken-ref": refId,
|
|
5351
|
+
title: `Anchor "${refId}" no longer exists`,
|
|
5352
|
+
style: "color: #D9352C; text-decoration-color: #D9352C;"
|
|
5353
|
+
})
|
|
5354
|
+
);
|
|
5355
|
+
}
|
|
5356
|
+
if (decos.length === 0) return DecorationSet2.empty;
|
|
5357
|
+
return DecorationSet2.create(state.doc, decos);
|
|
4493
5358
|
}
|
|
4494
5359
|
|
|
4495
5360
|
// src/ui/plugin/inlineToolTagNodeViewPlugin.tsx
|
|
@@ -4510,9 +5375,12 @@ var RESOURCE_TAG_ICONS2 = {
|
|
|
4510
5375
|
time_diff: IconTimeDiff
|
|
4511
5376
|
};
|
|
4512
5377
|
var DEFAULT_ICON = IconTool;
|
|
5378
|
+
var RESOURCE_ID_OVERRIDES = {
|
|
5379
|
+
"close-happy-tiger": { color: "#0D0D0D", icon: IconStop }
|
|
5380
|
+
};
|
|
4513
5381
|
var OUTER_STYLE = {
|
|
4514
5382
|
display: "inline-flex",
|
|
4515
|
-
padding: "
|
|
5383
|
+
padding: "2px",
|
|
4516
5384
|
border: "1px solid #CCCCCC",
|
|
4517
5385
|
borderRadius: "2px",
|
|
4518
5386
|
alignItems: "center",
|
|
@@ -4532,16 +5400,19 @@ var ICON_BLOCK_BASE = {
|
|
|
4532
5400
|
};
|
|
4533
5401
|
var LABEL_BASE = {
|
|
4534
5402
|
padding: "0 4px",
|
|
4535
|
-
fontSize: "
|
|
4536
|
-
lineHeight:
|
|
5403
|
+
fontSize: "12px",
|
|
5404
|
+
lineHeight: "16px",
|
|
4537
5405
|
userSelect: "none"
|
|
4538
5406
|
};
|
|
4539
|
-
function InlineToolTagNodeViewComponent({ node }) {
|
|
5407
|
+
function InlineToolTagNodeViewComponent({ node, selected }) {
|
|
4540
5408
|
const type = node.attrs.type;
|
|
4541
5409
|
const text2 = node.attrs.text;
|
|
4542
|
-
const
|
|
4543
|
-
const
|
|
4544
|
-
|
|
5410
|
+
const resourceId = node.attrs.resourceId;
|
|
5411
|
+
const override = RESOURCE_ID_OVERRIDES[resourceId];
|
|
5412
|
+
const color = override?.color ?? RESOURCE_TAG_COLORS2[type] ?? DEFAULT_COLOR;
|
|
5413
|
+
const Icon = override?.icon ?? RESOURCE_TAG_ICONS2[type] ?? DEFAULT_ICON;
|
|
5414
|
+
const style = selected ? { ...OUTER_STYLE, boxShadow: `inset 0 0 0 1px ${color}` } : OUTER_STYLE;
|
|
5415
|
+
return /* @__PURE__ */ jsxs4("span", { style, "data-type": type, "data-resource-id": node.attrs.resourceId, children: [
|
|
4545
5416
|
/* @__PURE__ */ jsx5("span", { style: { ...ICON_BLOCK_BASE, backgroundColor: color }, children: /* @__PURE__ */ jsx5(Icon, { size: 9, fill: "white" }) }),
|
|
4546
5417
|
/* @__PURE__ */ jsx5("span", { style: { ...LABEL_BASE, color }, children: text2 })
|
|
4547
5418
|
] });
|
|
@@ -4576,292 +5447,103 @@ function addInlineChipDecorations(doc2, decorations) {
|
|
|
4576
5447
|
JINJA_TAG_RE.lastIndex = 0;
|
|
4577
5448
|
let match;
|
|
4578
5449
|
while ((match = JINJA_TAG_RE.exec(text2)) !== null) {
|
|
4579
|
-
const from = pos + match.index;
|
|
4580
|
-
const to = from + match[0].length;
|
|
4581
|
-
const keyword = match[1];
|
|
4582
|
-
decorations.push(
|
|
4583
|
-
Decoration3.inline(from, to, {
|
|
4584
|
-
class: `jinja-chip jinja-chip-${keyword}`
|
|
4585
|
-
})
|
|
4586
|
-
);
|
|
4587
|
-
}
|
|
4588
|
-
});
|
|
4589
|
-
}
|
|
4590
|
-
function addStructureBorderDecorations(doc2, blocks, decorations) {
|
|
4591
|
-
const json = doc2.toJSON();
|
|
4592
|
-
let ast;
|
|
4593
|
-
try {
|
|
4594
|
-
ast = fromProseMirrorJSON(json);
|
|
4595
|
-
} catch {
|
|
4596
|
-
return;
|
|
4597
|
-
}
|
|
4598
|
-
const structures = analyzeJinjaBlocks(ast);
|
|
4599
|
-
for (const structure of structures) {
|
|
4600
|
-
const blockBranchType = /* @__PURE__ */ new Map();
|
|
4601
|
-
for (const branch of structure.branches) {
|
|
4602
|
-
blockBranchType.set(branch.tagBlockIndex, branch.type);
|
|
4603
|
-
for (let i = branch.blockStartIndex; i < branch.blockEndIndex; i++) {
|
|
4604
|
-
if (!blockBranchType.has(i)) {
|
|
4605
|
-
blockBranchType.set(i, branch.type);
|
|
4606
|
-
}
|
|
4607
|
-
}
|
|
4608
|
-
}
|
|
4609
|
-
const lastBranch = structure.branches[structure.branches.length - 1];
|
|
4610
|
-
if (lastBranch && !blockBranchType.has(structure.endifTagBlockIndex)) {
|
|
4611
|
-
blockBranchType.set(structure.endifTagBlockIndex, lastBranch.type);
|
|
4612
|
-
}
|
|
4613
|
-
const first = structure.ifTagBlockIndex;
|
|
4614
|
-
const last = structure.endifTagBlockIndex;
|
|
4615
|
-
for (let i = first; i <= last; i++) {
|
|
4616
|
-
const block = blocks[i];
|
|
4617
|
-
if (!block) continue;
|
|
4618
|
-
const branchType = blockBranchType.get(i) || "if";
|
|
4619
|
-
const prevType = i > first ? blockBranchType.get(i - 1) : void 0;
|
|
4620
|
-
const nextType = i < last ? blockBranchType.get(i + 1) : void 0;
|
|
4621
|
-
const classes = ["jinja-bar", `jinja-bar-${branchType}`];
|
|
4622
|
-
if (i === first || prevType !== branchType) classes.push("jinja-bar-first");
|
|
4623
|
-
if (i === last || nextType !== branchType) classes.push("jinja-bar-last");
|
|
4624
|
-
decorations.push(Decoration3.node(block.from, block.to, { class: classes.join(" ") }));
|
|
4625
|
-
}
|
|
4626
|
-
}
|
|
4627
|
-
}
|
|
4628
|
-
function buildDecorations2(doc2) {
|
|
4629
|
-
const blocks = getBlockPositions(doc2);
|
|
4630
|
-
const decorations = [];
|
|
4631
|
-
addInlineChipDecorations(doc2, decorations);
|
|
4632
|
-
addStructureBorderDecorations(doc2, blocks, decorations);
|
|
4633
|
-
if (decorations.length === 0) return DecorationSet3.empty;
|
|
4634
|
-
return DecorationSet3.create(doc2, decorations);
|
|
4635
|
-
}
|
|
4636
|
-
function createJinjaDecorationPlugin() {
|
|
4637
|
-
return {
|
|
4638
|
-
name: "jinjaDecoration",
|
|
4639
|
-
plugins: () => [
|
|
4640
|
-
new Plugin4({
|
|
4641
|
-
key: jinjaPluginKey,
|
|
4642
|
-
state: {
|
|
4643
|
-
init(_, state) {
|
|
4644
|
-
return buildDecorations2(state.doc);
|
|
4645
|
-
},
|
|
4646
|
-
apply(tr, oldDecos) {
|
|
4647
|
-
if (!tr.docChanged) return oldDecos;
|
|
4648
|
-
return buildDecorations2(tr.doc);
|
|
4649
|
-
}
|
|
4650
|
-
},
|
|
4651
|
-
props: {
|
|
4652
|
-
decorations(state) {
|
|
4653
|
-
return jinjaPluginKey.getState(state);
|
|
4654
|
-
}
|
|
4655
|
-
}
|
|
4656
|
-
})
|
|
4657
|
-
]
|
|
4658
|
-
};
|
|
4659
|
-
}
|
|
4660
|
-
|
|
4661
|
-
// src/ui/plugin/jinjaIfBlockPlugin.tsx
|
|
4662
|
-
import { useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
|
|
4663
|
-
import { createRoot as createRoot2 } from "react-dom/client";
|
|
4664
|
-
|
|
4665
|
-
// src/jinja/conditionHighlighter.ts
|
|
4666
|
-
var KEYWORDS = {
|
|
4667
|
-
and: "AND",
|
|
4668
|
-
or: "OR",
|
|
4669
|
-
not: "NOT",
|
|
4670
|
-
in: "IN",
|
|
4671
|
-
is: "IS",
|
|
4672
|
-
True: "BOOL",
|
|
4673
|
-
False: "BOOL",
|
|
4674
|
-
true: "BOOL",
|
|
4675
|
-
false: "BOOL",
|
|
4676
|
-
None: "NONE",
|
|
4677
|
-
null: "NONE"
|
|
4678
|
-
};
|
|
4679
|
-
var CATEGORY_BY_TYPE = {
|
|
4680
|
-
STRING: "value",
|
|
4681
|
-
NUMBER: "value",
|
|
4682
|
-
BOOL: "value",
|
|
4683
|
-
NONE: "value",
|
|
4684
|
-
IDENT: "variable",
|
|
4685
|
-
AND: "operator",
|
|
4686
|
-
OR: "operator",
|
|
4687
|
-
NOT: "operator",
|
|
4688
|
-
IN: "operator",
|
|
4689
|
-
IS: "operator",
|
|
4690
|
-
EQ: "operator",
|
|
4691
|
-
NEQ: "operator",
|
|
4692
|
-
LT: "operator",
|
|
4693
|
-
GT: "operator",
|
|
4694
|
-
LTE: "operator",
|
|
4695
|
-
GTE: "operator",
|
|
4696
|
-
LPAREN: "punctuation",
|
|
4697
|
-
RPAREN: "punctuation"
|
|
4698
|
-
};
|
|
4699
|
-
var NEGATIVE_NUMBER_PRECEDERS = /* @__PURE__ */ new Set([
|
|
4700
|
-
"AND",
|
|
4701
|
-
"OR",
|
|
4702
|
-
"NOT",
|
|
4703
|
-
"IN",
|
|
4704
|
-
"IS",
|
|
4705
|
-
"EQ",
|
|
4706
|
-
"NEQ",
|
|
4707
|
-
"LT",
|
|
4708
|
-
"GT",
|
|
4709
|
-
"LTE",
|
|
4710
|
-
"GTE",
|
|
4711
|
-
"LPAREN"
|
|
4712
|
-
]);
|
|
4713
|
-
function canStartNegativeNumber(tokens) {
|
|
4714
|
-
if (tokens.length === 0) {
|
|
4715
|
-
return true;
|
|
4716
|
-
}
|
|
4717
|
-
const previous = tokens[tokens.length - 1];
|
|
4718
|
-
return NEGATIVE_NUMBER_PRECEDERS.has(previous.type);
|
|
4719
|
-
}
|
|
4720
|
-
function finalizeTokens(input, rawTokens) {
|
|
4721
|
-
const highlighted = [];
|
|
4722
|
-
for (let i = 0; i < rawTokens.length; i++) {
|
|
4723
|
-
const token = rawTokens[i];
|
|
4724
|
-
const next = rawTokens[i + 1];
|
|
4725
|
-
if (token.type === "IS" && next?.type === "NOT") {
|
|
4726
|
-
highlighted.push({
|
|
4727
|
-
text: input.slice(token.start, next.end),
|
|
4728
|
-
start: token.start,
|
|
4729
|
-
end: next.end,
|
|
4730
|
-
category: "operator"
|
|
4731
|
-
});
|
|
4732
|
-
i++;
|
|
4733
|
-
continue;
|
|
4734
|
-
}
|
|
4735
|
-
highlighted.push({
|
|
4736
|
-
text: token.text,
|
|
4737
|
-
start: token.start,
|
|
4738
|
-
end: token.end,
|
|
4739
|
-
category: CATEGORY_BY_TYPE[token.type]
|
|
4740
|
-
});
|
|
4741
|
-
}
|
|
4742
|
-
return highlighted;
|
|
4743
|
-
}
|
|
4744
|
-
function tokenizeCondition(input) {
|
|
4745
|
-
const rawTokens = [];
|
|
4746
|
-
let i = 0;
|
|
4747
|
-
while (i < input.length) {
|
|
4748
|
-
const char = input[i];
|
|
4749
|
-
if (/\s/.test(char)) {
|
|
4750
|
-
i++;
|
|
4751
|
-
continue;
|
|
4752
|
-
}
|
|
4753
|
-
if (char === '"' || char === "'") {
|
|
4754
|
-
const start = i;
|
|
4755
|
-
const quote = char;
|
|
4756
|
-
i++;
|
|
4757
|
-
while (i < input.length) {
|
|
4758
|
-
if (input[i] === "\\" && i + 1 < input.length) {
|
|
4759
|
-
i += 2;
|
|
4760
|
-
continue;
|
|
4761
|
-
}
|
|
4762
|
-
if (input[i] === quote) {
|
|
4763
|
-
i++;
|
|
4764
|
-
rawTokens.push({
|
|
4765
|
-
type: "STRING",
|
|
4766
|
-
text: input.slice(start, i),
|
|
4767
|
-
start,
|
|
4768
|
-
end: i
|
|
4769
|
-
});
|
|
4770
|
-
break;
|
|
4771
|
-
}
|
|
4772
|
-
i++;
|
|
4773
|
-
}
|
|
4774
|
-
if (rawTokens[rawTokens.length - 1]?.start !== start) {
|
|
4775
|
-
return finalizeTokens(input, rawTokens);
|
|
4776
|
-
}
|
|
4777
|
-
continue;
|
|
4778
|
-
}
|
|
4779
|
-
if (/[0-9]/.test(char) || char === "-" && i + 1 < input.length && /[0-9]/.test(input[i + 1]) && canStartNegativeNumber(rawTokens)) {
|
|
4780
|
-
const start = i;
|
|
4781
|
-
if (input[i] === "-") {
|
|
4782
|
-
i++;
|
|
4783
|
-
}
|
|
4784
|
-
while (i < input.length && /[0-9]/.test(input[i])) {
|
|
4785
|
-
i++;
|
|
4786
|
-
}
|
|
4787
|
-
if (i < input.length && input[i] === ".") {
|
|
4788
|
-
i++;
|
|
4789
|
-
while (i < input.length && /[0-9]/.test(input[i])) {
|
|
4790
|
-
i++;
|
|
4791
|
-
}
|
|
4792
|
-
}
|
|
4793
|
-
rawTokens.push({
|
|
4794
|
-
type: "NUMBER",
|
|
4795
|
-
text: input.slice(start, i),
|
|
4796
|
-
start,
|
|
4797
|
-
end: i
|
|
4798
|
-
});
|
|
4799
|
-
continue;
|
|
4800
|
-
}
|
|
4801
|
-
if (/[a-zA-Z_]/.test(char)) {
|
|
4802
|
-
const start = i;
|
|
4803
|
-
i++;
|
|
4804
|
-
while (i < input.length && /[a-zA-Z0-9_.]/.test(input[i])) {
|
|
4805
|
-
i++;
|
|
4806
|
-
}
|
|
4807
|
-
const text2 = input.slice(start, i);
|
|
4808
|
-
rawTokens.push({
|
|
4809
|
-
type: KEYWORDS[text2] ?? "IDENT",
|
|
4810
|
-
text: text2,
|
|
4811
|
-
start,
|
|
4812
|
-
end: i
|
|
4813
|
-
});
|
|
4814
|
-
continue;
|
|
4815
|
-
}
|
|
4816
|
-
if (i + 1 < input.length) {
|
|
4817
|
-
const twoChar = input.slice(i, i + 2);
|
|
4818
|
-
if (twoChar === "==") {
|
|
4819
|
-
rawTokens.push({ type: "EQ", text: twoChar, start: i, end: i + 2 });
|
|
4820
|
-
i += 2;
|
|
4821
|
-
continue;
|
|
4822
|
-
}
|
|
4823
|
-
if (twoChar === "!=") {
|
|
4824
|
-
rawTokens.push({ type: "NEQ", text: twoChar, start: i, end: i + 2 });
|
|
4825
|
-
i += 2;
|
|
4826
|
-
continue;
|
|
4827
|
-
}
|
|
4828
|
-
if (twoChar === "<=") {
|
|
4829
|
-
rawTokens.push({ type: "LTE", text: twoChar, start: i, end: i + 2 });
|
|
4830
|
-
i += 2;
|
|
4831
|
-
continue;
|
|
4832
|
-
}
|
|
4833
|
-
if (twoChar === ">=") {
|
|
4834
|
-
rawTokens.push({ type: "GTE", text: twoChar, start: i, end: i + 2 });
|
|
4835
|
-
i += 2;
|
|
4836
|
-
continue;
|
|
4837
|
-
}
|
|
4838
|
-
}
|
|
4839
|
-
if (char === "<") {
|
|
4840
|
-
rawTokens.push({ type: "LT", text: char, start: i, end: i + 1 });
|
|
4841
|
-
i++;
|
|
4842
|
-
continue;
|
|
5450
|
+
const from = pos + match.index;
|
|
5451
|
+
const to = from + match[0].length;
|
|
5452
|
+
const keyword = match[1];
|
|
5453
|
+
decorations.push(
|
|
5454
|
+
Decoration3.inline(from, to, {
|
|
5455
|
+
class: `jinja-chip jinja-chip-${keyword}`
|
|
5456
|
+
})
|
|
5457
|
+
);
|
|
4843
5458
|
}
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
5459
|
+
});
|
|
5460
|
+
}
|
|
5461
|
+
function addStructureBorderDecorations(doc2, blocks, decorations) {
|
|
5462
|
+
const json = doc2.toJSON();
|
|
5463
|
+
let ast;
|
|
5464
|
+
try {
|
|
5465
|
+
ast = fromProseMirrorJSON(json);
|
|
5466
|
+
} catch {
|
|
5467
|
+
return;
|
|
5468
|
+
}
|
|
5469
|
+
const structures = analyzeJinjaBlocks(ast);
|
|
5470
|
+
for (const structure of structures) {
|
|
5471
|
+
const blockBranchType = /* @__PURE__ */ new Map();
|
|
5472
|
+
for (const branch of structure.branches) {
|
|
5473
|
+
blockBranchType.set(branch.tagBlockIndex, branch.type);
|
|
5474
|
+
for (let i = branch.blockStartIndex; i < branch.blockEndIndex; i++) {
|
|
5475
|
+
if (!blockBranchType.has(i)) {
|
|
5476
|
+
blockBranchType.set(i, branch.type);
|
|
5477
|
+
}
|
|
5478
|
+
}
|
|
4848
5479
|
}
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
continue;
|
|
5480
|
+
const lastBranch = structure.branches[structure.branches.length - 1];
|
|
5481
|
+
if (lastBranch && !blockBranchType.has(structure.endifTagBlockIndex)) {
|
|
5482
|
+
blockBranchType.set(structure.endifTagBlockIndex, lastBranch.type);
|
|
4853
5483
|
}
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
5484
|
+
const first = structure.ifTagBlockIndex;
|
|
5485
|
+
const last = structure.endifTagBlockIndex;
|
|
5486
|
+
for (let i = first; i <= last; i++) {
|
|
5487
|
+
const block = blocks[i];
|
|
5488
|
+
if (!block) continue;
|
|
5489
|
+
const branchType = blockBranchType.get(i) || "if";
|
|
5490
|
+
const prevType = i > first ? blockBranchType.get(i - 1) : void 0;
|
|
5491
|
+
const nextType = i < last ? blockBranchType.get(i + 1) : void 0;
|
|
5492
|
+
const classes = ["jinja-bar", `jinja-bar-${branchType}`];
|
|
5493
|
+
if (i === first || prevType !== branchType) classes.push("jinja-bar-first");
|
|
5494
|
+
if (i === last || nextType !== branchType) classes.push("jinja-bar-last");
|
|
5495
|
+
decorations.push(Decoration3.node(block.from, block.to, { class: classes.join(" ") }));
|
|
4858
5496
|
}
|
|
4859
|
-
return finalizeTokens(input, rawTokens);
|
|
4860
5497
|
}
|
|
4861
|
-
|
|
5498
|
+
}
|
|
5499
|
+
function hasJinjaTags(doc2) {
|
|
5500
|
+
let found = false;
|
|
5501
|
+
doc2.descendants((node) => {
|
|
5502
|
+
if (found) return false;
|
|
5503
|
+
if (node.isText && node.text.includes("{%")) {
|
|
5504
|
+
found = true;
|
|
5505
|
+
return false;
|
|
5506
|
+
}
|
|
5507
|
+
});
|
|
5508
|
+
return found;
|
|
5509
|
+
}
|
|
5510
|
+
function buildDecorations3(doc2) {
|
|
5511
|
+
if (!hasJinjaTags(doc2)) return DecorationSet3.empty;
|
|
5512
|
+
const blocks = getBlockPositions(doc2);
|
|
5513
|
+
const decorations = [];
|
|
5514
|
+
addInlineChipDecorations(doc2, decorations);
|
|
5515
|
+
addStructureBorderDecorations(doc2, blocks, decorations);
|
|
5516
|
+
if (decorations.length === 0) return DecorationSet3.empty;
|
|
5517
|
+
return DecorationSet3.create(doc2, decorations);
|
|
5518
|
+
}
|
|
5519
|
+
function createJinjaDecorationPlugin() {
|
|
5520
|
+
return {
|
|
5521
|
+
name: "jinjaDecoration",
|
|
5522
|
+
plugins: () => [
|
|
5523
|
+
new Plugin4({
|
|
5524
|
+
key: jinjaPluginKey,
|
|
5525
|
+
state: {
|
|
5526
|
+
init(_, state) {
|
|
5527
|
+
return buildDecorations3(state.doc);
|
|
5528
|
+
},
|
|
5529
|
+
apply(tr, oldDecos) {
|
|
5530
|
+
if (!tr.docChanged) return oldDecos;
|
|
5531
|
+
return buildDecorations3(tr.doc);
|
|
5532
|
+
}
|
|
5533
|
+
},
|
|
5534
|
+
props: {
|
|
5535
|
+
decorations(state) {
|
|
5536
|
+
return jinjaPluginKey.getState(state);
|
|
5537
|
+
}
|
|
5538
|
+
}
|
|
5539
|
+
})
|
|
5540
|
+
]
|
|
5541
|
+
};
|
|
4862
5542
|
}
|
|
4863
5543
|
|
|
4864
5544
|
// src/ui/plugin/jinjaIfBlockPlugin.tsx
|
|
5545
|
+
import { useEffect as useEffect2, useRef as useRef2, useState as useState3 } from "react";
|
|
5546
|
+
import { createRoot as createRoot2 } from "react-dom/client";
|
|
4865
5547
|
import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
4866
5548
|
var PLACEHOLDER_TEXT = "Describe what AI agent should do when this condition is met";
|
|
4867
5549
|
var CONDITION_PLACEHOLDER = "Write a condition in natural language";
|
|
@@ -5312,8 +5994,8 @@ function ConditionDisplay({
|
|
|
5312
5994
|
editable = true,
|
|
5313
5995
|
onConditionChange
|
|
5314
5996
|
}) {
|
|
5315
|
-
const [isEditing, setIsEditing] =
|
|
5316
|
-
const [draftValue, setDraftValue] =
|
|
5997
|
+
const [isEditing, setIsEditing] = useState3(false);
|
|
5998
|
+
const [draftValue, setDraftValue] = useState3(condition);
|
|
5317
5999
|
const inputRef = useRef2(null);
|
|
5318
6000
|
useEffect2(() => {
|
|
5319
6001
|
if (!isEditing) {
|
|
@@ -5419,7 +6101,7 @@ function JinjaBranchHeader({
|
|
|
5419
6101
|
isLastBranch,
|
|
5420
6102
|
hasElseBranch
|
|
5421
6103
|
}) {
|
|
5422
|
-
const [menuSource, setMenuSource] =
|
|
6104
|
+
const [menuSource, setMenuSource] = useState3(null);
|
|
5423
6105
|
const kebabRef = useRef2(null);
|
|
5424
6106
|
const footerRef = useRef2(null);
|
|
5425
6107
|
useEffect2(() => {
|
|
@@ -5699,7 +6381,7 @@ function createJinjaIfBlockPlugin() {
|
|
|
5699
6381
|
|
|
5700
6382
|
// src/ui/plugin/linkPlugin.ts
|
|
5701
6383
|
import { InputRule as InputRule2, inputRules as inputRules2 } from "prosemirror-inputrules";
|
|
5702
|
-
import { Plugin as Plugin5, PluginKey as PluginKey5, TextSelection as
|
|
6384
|
+
import { Plugin as Plugin5, PluginKey as PluginKey5, TextSelection as TextSelection3 } from "prosemirror-state";
|
|
5703
6385
|
var LINK_INPUT_RE = /\[([^\]]*)\]\(([^)\s]*?)(?:\s+"([^"]*)")?\)$/;
|
|
5704
6386
|
var LINK_FULL_RE = /^\[([^\]]*)\]\(([^)\s]*?)(?:\s+"([^"]*)")?\)$/;
|
|
5705
6387
|
var linkEditKey = new PluginKey5("linkEdit");
|
|
@@ -5745,7 +6427,7 @@ function explodeLinkToRaw(state) {
|
|
|
5745
6427
|
const tr = state.tr;
|
|
5746
6428
|
tr.replaceWith(from, to, schema.text(rawText));
|
|
5747
6429
|
const newPos = Math.min(from + rawCursorOffset, tr.doc.content.size);
|
|
5748
|
-
tr.setSelection(
|
|
6430
|
+
tr.setSelection(TextSelection3.near(tr.doc.resolve(newPos)));
|
|
5749
6431
|
tr.setMeta(linkEditKey, { from, to: from + rawText.length });
|
|
5750
6432
|
return tr;
|
|
5751
6433
|
}
|
|
@@ -5891,11 +6573,11 @@ var STYLES = (
|
|
|
5891
6573
|
--ab-dh-color-idle: transparent;
|
|
5892
6574
|
--ab-dh-color-hover: #c4c4c4;
|
|
5893
6575
|
--ab-dh-color-visible: #8b8b8b;
|
|
5894
|
-
--ab-dh-color-accent:
|
|
5895
|
-
--ab-dh-bg-hover: rgba(
|
|
5896
|
-
--ab-dh-bg-active: rgba(
|
|
6576
|
+
--ab-dh-color-accent: rgba(1,156,110,0.8);
|
|
6577
|
+
--ab-dh-bg-hover: rgba(13,13,13,0.04);
|
|
6578
|
+
--ab-dh-bg-active: rgba(13,13,13,0.04);
|
|
5897
6579
|
--ab-dh-dragging-opacity: 0.4;
|
|
5898
|
-
--ab-dh-handle-size:
|
|
6580
|
+
--ab-dh-handle-size: 24px;
|
|
5899
6581
|
--ab-dh-handle-radius: 4px;
|
|
5900
6582
|
--ab-dh-transition-duration: 0.15s;
|
|
5901
6583
|
|
|
@@ -5912,15 +6594,19 @@ var STYLES = (
|
|
|
5912
6594
|
align-items: center;
|
|
5913
6595
|
justify-content: center;
|
|
5914
6596
|
cursor: grab;
|
|
5915
|
-
color:
|
|
6597
|
+
color: transparent;
|
|
5916
6598
|
border-radius: var(--ab-dh-handle-radius);
|
|
5917
|
-
transition: color var(--ab-dh-transition-duration), background var(--ab-dh-transition-duration);
|
|
6599
|
+
transition: color var(--ab-dh-transition-duration), background var(--ab-dh-transition-duration), opacity var(--ab-dh-transition-duration);
|
|
5918
6600
|
user-select: none;
|
|
5919
6601
|
pointer-events: auto;
|
|
5920
6602
|
touch-action: none;
|
|
6603
|
+
opacity: 0;
|
|
6604
|
+
pointer-events: none;
|
|
5921
6605
|
}
|
|
5922
|
-
.ab-drag-handle
|
|
5923
|
-
|
|
6606
|
+
.ab-drag-handle.ab-dh-active {
|
|
6607
|
+
opacity: 1;
|
|
6608
|
+
pointer-events: auto;
|
|
6609
|
+
color: var(--ab-dh-color-visible);
|
|
5924
6610
|
}
|
|
5925
6611
|
.ab-drag-handle:hover {
|
|
5926
6612
|
color: var(--ab-dh-color-visible) !important;
|
|
@@ -5934,18 +6620,20 @@ var STYLES = (
|
|
|
5934
6620
|
.ab-drop-indicator {
|
|
5935
6621
|
position: absolute;
|
|
5936
6622
|
left: 0; right: 0;
|
|
5937
|
-
height:
|
|
5938
|
-
background:
|
|
5939
|
-
border
|
|
6623
|
+
height: 4px;
|
|
6624
|
+
background: rgba(1,156,110,0.4);
|
|
6625
|
+
border: 1px solid rgba(1,156,110,0.6);
|
|
6626
|
+
border-radius: 12px;
|
|
5940
6627
|
pointer-events: none;
|
|
5941
6628
|
z-index: 20;
|
|
6629
|
+
box-sizing: border-box;
|
|
5942
6630
|
transition: top 60ms ease-out;
|
|
5943
6631
|
}
|
|
5944
6632
|
.ab-block-dragging {
|
|
5945
6633
|
opacity: var(--ab-dh-dragging-opacity, 0.4);
|
|
5946
6634
|
}
|
|
5947
6635
|
@keyframes ab-block-flash {
|
|
5948
|
-
from { background: rgba(
|
|
6636
|
+
from { background: rgba(1,156,110,0.08); }
|
|
5949
6637
|
to { background: transparent; }
|
|
5950
6638
|
}
|
|
5951
6639
|
.ab-block-just-moved {
|
|
@@ -6101,23 +6789,25 @@ var DragHandleController = class {
|
|
|
6101
6789
|
this.liveRegion.setAttribute("aria-live", "assertive");
|
|
6102
6790
|
this.liveRegion.setAttribute("aria-atomic", "true");
|
|
6103
6791
|
parent.appendChild(this.liveRegion);
|
|
6104
|
-
|
|
6105
|
-
|
|
6106
|
-
};
|
|
6107
|
-
const onLeave = () => {
|
|
6108
|
-
if (!this.drag) delete this.layer.dataset.hover;
|
|
6109
|
-
};
|
|
6110
|
-
parent.addEventListener("mouseenter", onEnter);
|
|
6111
|
-
parent.addEventListener("mouseleave", onLeave);
|
|
6112
|
-
this.hoverBound = { enter: onEnter, leave: onLeave };
|
|
6792
|
+
this.hoverBound = { enter: () => {
|
|
6793
|
+
}, leave: () => {
|
|
6794
|
+
} };
|
|
6113
6795
|
this.scrollContainer = this.findScrollContainer(view.dom);
|
|
6114
6796
|
this.scrollContainer.addEventListener("scroll", this.onScroll, { passive: true });
|
|
6115
6797
|
this.resizeObserver = new ResizeObserver(() => this.scheduleUpdate());
|
|
6116
6798
|
this.resizeObserver.observe(view.dom);
|
|
6799
|
+
if (!view.editable) {
|
|
6800
|
+
this.layer.style.display = "none";
|
|
6801
|
+
}
|
|
6117
6802
|
this.rebuildHandles();
|
|
6118
6803
|
}
|
|
6119
6804
|
update(view, prevState) {
|
|
6120
6805
|
this.view = view;
|
|
6806
|
+
if (!view.editable) {
|
|
6807
|
+
this.layer.style.display = "none";
|
|
6808
|
+
return;
|
|
6809
|
+
}
|
|
6810
|
+
this.layer.style.display = "";
|
|
6121
6811
|
if (this.drag) {
|
|
6122
6812
|
this.pendingUpdate = true;
|
|
6123
6813
|
return;
|
|
@@ -6125,6 +6815,21 @@ var DragHandleController = class {
|
|
|
6125
6815
|
if (!view.state.doc.eq(prevState.doc)) {
|
|
6126
6816
|
this.scheduleUpdate();
|
|
6127
6817
|
}
|
|
6818
|
+
if (!view.state.selection.eq(prevState.selection) || !view.state.doc.eq(prevState.doc)) {
|
|
6819
|
+
this.updateActiveHandle();
|
|
6820
|
+
}
|
|
6821
|
+
}
|
|
6822
|
+
/** Show only the handle for the block containing the cursor. */
|
|
6823
|
+
updateActiveHandle() {
|
|
6824
|
+
const { $from } = this.view.state.selection;
|
|
6825
|
+
const cursorBlockOffset = $from.start(1) - 1;
|
|
6826
|
+
for (const h of this.handles) {
|
|
6827
|
+
if (h.block.offset === cursorBlockOffset) {
|
|
6828
|
+
h.el.classList.add("ab-dh-active");
|
|
6829
|
+
} else {
|
|
6830
|
+
h.el.classList.remove("ab-dh-active");
|
|
6831
|
+
}
|
|
6832
|
+
}
|
|
6128
6833
|
}
|
|
6129
6834
|
destroy() {
|
|
6130
6835
|
this.cancelDrag();
|
|
@@ -6216,6 +6921,7 @@ var DragHandleController = class {
|
|
|
6216
6921
|
el.setAttribute("role", "button");
|
|
6217
6922
|
el.setAttribute("aria-roledescription", "drag handle");
|
|
6218
6923
|
el.setAttribute("aria-label", `\uBE14\uB85D ${idx + 1} \uC774\uB3D9`);
|
|
6924
|
+
el.setAttribute("title", "Drag to move");
|
|
6219
6925
|
el.setAttribute("tabindex", "-1");
|
|
6220
6926
|
el.innerHTML = GRIP_SVG;
|
|
6221
6927
|
el.style.left = `${handleLeft}px`;
|
|
@@ -6226,6 +6932,7 @@ var DragHandleController = class {
|
|
|
6226
6932
|
}
|
|
6227
6933
|
this.handles = newHandles;
|
|
6228
6934
|
this.prevBlocks = newBlocks;
|
|
6935
|
+
this.updateActiveHandle();
|
|
6229
6936
|
}
|
|
6230
6937
|
bindHandleEvents(el, index) {
|
|
6231
6938
|
let currentIndex = index;
|
|
@@ -6296,7 +7003,8 @@ var DragHandleController = class {
|
|
|
6296
7003
|
pointerId: e.pointerId,
|
|
6297
7004
|
startX: e.clientX,
|
|
6298
7005
|
startY: e.clientY,
|
|
6299
|
-
activated: false
|
|
7006
|
+
activated: false,
|
|
7007
|
+
ghost: null
|
|
6300
7008
|
};
|
|
6301
7009
|
this.addGlobalDragListeners(e.pointerId);
|
|
6302
7010
|
}
|
|
@@ -6305,6 +7013,22 @@ var DragHandleController = class {
|
|
|
6305
7013
|
this.drag.activated = true;
|
|
6306
7014
|
this.drag.handle.classList.add("dragging");
|
|
6307
7015
|
this.drag.blockDom.classList.add("ab-block-dragging");
|
|
7016
|
+
const blockRect = this.drag.blockDom.getBoundingClientRect();
|
|
7017
|
+
const ghost = this.drag.blockDom.cloneNode(true);
|
|
7018
|
+
ghost.className = "ab-drag-ghost";
|
|
7019
|
+
ghost.style.cssText = `
|
|
7020
|
+
position: fixed;
|
|
7021
|
+
top: ${blockRect.top}px;
|
|
7022
|
+
left: ${blockRect.left}px;
|
|
7023
|
+
width: ${blockRect.width}px;
|
|
7024
|
+
opacity: 0.4;
|
|
7025
|
+
pointer-events: none;
|
|
7026
|
+
z-index: 9999;
|
|
7027
|
+
transition: none;
|
|
7028
|
+
`;
|
|
7029
|
+
document.body.appendChild(ghost);
|
|
7030
|
+
this.drag.ghost = ghost;
|
|
7031
|
+
this.drag._ghostOffsetY = this.drag.startY - blockRect.top;
|
|
6308
7032
|
const parent = this.view.dom.parentNode;
|
|
6309
7033
|
this.dropIndicator = document.createElement("div");
|
|
6310
7034
|
this.dropIndicator.className = "ab-drop-indicator";
|
|
@@ -6344,6 +7068,10 @@ var DragHandleController = class {
|
|
|
6344
7068
|
this.activateDrag();
|
|
6345
7069
|
}
|
|
6346
7070
|
this.drag.pointerY = e.clientY;
|
|
7071
|
+
if (this.drag.ghost) {
|
|
7072
|
+
const offsetY = this.drag._ghostOffsetY ?? 0;
|
|
7073
|
+
this.drag.ghost.style.top = `${e.clientY - offsetY}px`;
|
|
7074
|
+
}
|
|
6347
7075
|
this.updateDropTarget();
|
|
6348
7076
|
}
|
|
6349
7077
|
updateDropTarget() {
|
|
@@ -6415,6 +7143,10 @@ var DragHandleController = class {
|
|
|
6415
7143
|
this.cleaningUp = true;
|
|
6416
7144
|
this.drag.handle.classList.remove("dragging");
|
|
6417
7145
|
this.drag.blockDom.classList.remove("ab-block-dragging");
|
|
7146
|
+
if (this.drag.ghost) {
|
|
7147
|
+
this.drag.ghost.remove();
|
|
7148
|
+
this.drag.ghost = null;
|
|
7149
|
+
}
|
|
6418
7150
|
try {
|
|
6419
7151
|
this.drag.handle.releasePointerCapture(this.drag.pointerId);
|
|
6420
7152
|
} catch {
|
|
@@ -6620,6 +7352,124 @@ function createTodoNodeViewPlugin() {
|
|
|
6620
7352
|
};
|
|
6621
7353
|
}
|
|
6622
7354
|
|
|
7355
|
+
// src/ui/plugin/noteBlockPlugin.tsx
|
|
7356
|
+
import { Selection } from "prosemirror-state";
|
|
7357
|
+
var NoteBlockView = class {
|
|
7358
|
+
dom;
|
|
7359
|
+
contentDOM;
|
|
7360
|
+
constructor(_node, _view, _getPos) {
|
|
7361
|
+
this.dom = document.createElement("div");
|
|
7362
|
+
this.dom.setAttribute("data-note-block", "");
|
|
7363
|
+
this.dom.className = "ab-note-block";
|
|
7364
|
+
this.dom.style.cssText = [
|
|
7365
|
+
"position: relative",
|
|
7366
|
+
"margin: 8px 0",
|
|
7367
|
+
"padding: 16px 24px",
|
|
7368
|
+
"background: #fff",
|
|
7369
|
+
"border: 1px dashed #ccc",
|
|
7370
|
+
"border-radius: 4px",
|
|
7371
|
+
"display: flex",
|
|
7372
|
+
"flex-direction: column",
|
|
7373
|
+
"gap: 4px"
|
|
7374
|
+
].join(";");
|
|
7375
|
+
const label = document.createElement("span");
|
|
7376
|
+
label.contentEditable = "false";
|
|
7377
|
+
label.textContent = "Note";
|
|
7378
|
+
label.style.cssText = [
|
|
7379
|
+
"display: inline-flex",
|
|
7380
|
+
"align-items: center",
|
|
7381
|
+
"justify-content: center",
|
|
7382
|
+
"align-self: flex-start",
|
|
7383
|
+
"font-size: 12px",
|
|
7384
|
+
"font-weight: 400",
|
|
7385
|
+
"font-style: normal",
|
|
7386
|
+
"line-height: 16px",
|
|
7387
|
+
"color: #858585",
|
|
7388
|
+
"background: #f7f7f7",
|
|
7389
|
+
"border: 1px solid #e0e0e0",
|
|
7390
|
+
"border-radius: 4px",
|
|
7391
|
+
"padding: 2px 4px",
|
|
7392
|
+
"user-select: none"
|
|
7393
|
+
].join(";");
|
|
7394
|
+
this.dom.appendChild(label);
|
|
7395
|
+
this.contentDOM = document.createElement("div");
|
|
7396
|
+
this.contentDOM.className = "ab-note-block-content";
|
|
7397
|
+
this.contentDOM.style.cssText = [
|
|
7398
|
+
"font-size: 14px",
|
|
7399
|
+
"font-style: italic",
|
|
7400
|
+
"font-weight: 400",
|
|
7401
|
+
"line-height: 20px",
|
|
7402
|
+
"letter-spacing: -0.1px",
|
|
7403
|
+
"color: #858585"
|
|
7404
|
+
].join(";");
|
|
7405
|
+
this.dom.appendChild(this.contentDOM);
|
|
7406
|
+
}
|
|
7407
|
+
};
|
|
7408
|
+
var emptyEnterCount = 0;
|
|
7409
|
+
var lastEnterTime = 0;
|
|
7410
|
+
var exitNoteBlockOnEnter = (state, dispatch) => {
|
|
7411
|
+
const { $from } = state.selection;
|
|
7412
|
+
let noteBlockDepth = -1;
|
|
7413
|
+
for (let d = $from.depth; d > 0; d--) {
|
|
7414
|
+
if ($from.node(d).type.name === "noteBlock") {
|
|
7415
|
+
noteBlockDepth = d;
|
|
7416
|
+
break;
|
|
7417
|
+
}
|
|
7418
|
+
}
|
|
7419
|
+
if (noteBlockDepth < 0) {
|
|
7420
|
+
emptyEnterCount = 0;
|
|
7421
|
+
return false;
|
|
7422
|
+
}
|
|
7423
|
+
const parentNode = $from.parent;
|
|
7424
|
+
if (parentNode.type.name !== "paragraph" || parentNode.content.size !== 0) {
|
|
7425
|
+
emptyEnterCount = 0;
|
|
7426
|
+
return false;
|
|
7427
|
+
}
|
|
7428
|
+
const now = Date.now();
|
|
7429
|
+
if (now - lastEnterTime > 2e3) {
|
|
7430
|
+
emptyEnterCount = 0;
|
|
7431
|
+
}
|
|
7432
|
+
lastEnterTime = now;
|
|
7433
|
+
emptyEnterCount++;
|
|
7434
|
+
if (emptyEnterCount < 2) {
|
|
7435
|
+
return false;
|
|
7436
|
+
}
|
|
7437
|
+
emptyEnterCount = 0;
|
|
7438
|
+
if (!dispatch) return true;
|
|
7439
|
+
const paragraphStart = $from.before($from.depth);
|
|
7440
|
+
const paragraphEnd = $from.after($from.depth);
|
|
7441
|
+
const tr = state.tr.delete(paragraphStart, paragraphEnd);
|
|
7442
|
+
const mappedFrom = tr.mapping.map($from.before($from.depth));
|
|
7443
|
+
const $mapped = tr.doc.resolve(Math.min(mappedFrom, tr.doc.content.size));
|
|
7444
|
+
for (let d = $mapped.depth; d > 0; d--) {
|
|
7445
|
+
if ($mapped.node(d).type.name === "noteBlock") {
|
|
7446
|
+
const lastChild = $mapped.node(d).lastChild;
|
|
7447
|
+
if (lastChild && lastChild.type.name === "paragraph" && lastChild.content.size === 0) {
|
|
7448
|
+
const lastChildPos = $mapped.end(d) - lastChild.nodeSize;
|
|
7449
|
+
tr.delete(lastChildPos, lastChildPos + lastChild.nodeSize);
|
|
7450
|
+
}
|
|
7451
|
+
break;
|
|
7452
|
+
}
|
|
7453
|
+
}
|
|
7454
|
+
const noteBlockEnd = tr.mapping.map($from.after(noteBlockDepth));
|
|
7455
|
+
const newParagraph = state.schema.nodes.paragraph.create();
|
|
7456
|
+
tr.insert(noteBlockEnd, newParagraph);
|
|
7457
|
+
tr.setSelection(Selection.near(tr.doc.resolve(noteBlockEnd + 1)));
|
|
7458
|
+
dispatch(tr.scrollIntoView());
|
|
7459
|
+
return true;
|
|
7460
|
+
};
|
|
7461
|
+
function createNoteBlockPlugin() {
|
|
7462
|
+
return {
|
|
7463
|
+
name: "noteBlockNodeView",
|
|
7464
|
+
keymap: () => ({
|
|
7465
|
+
Enter: exitNoteBlockOnEnter
|
|
7466
|
+
}),
|
|
7467
|
+
nodeViews: () => ({
|
|
7468
|
+
noteBlock: (node, view, getPos) => new NoteBlockView(node, view, getPos)
|
|
7469
|
+
})
|
|
7470
|
+
};
|
|
7471
|
+
}
|
|
7472
|
+
|
|
6623
7473
|
// src/ui/plugin/slashCommandPlugin.ts
|
|
6624
7474
|
import { Plugin as Plugin7, PluginKey as PluginKey7 } from "prosemirror-state";
|
|
6625
7475
|
var slashCommandKey = new PluginKey7("slashCommand");
|
|
@@ -6689,17 +7539,37 @@ function createSlashCommandPlugin() {
|
|
|
6689
7539
|
}
|
|
6690
7540
|
|
|
6691
7541
|
// src/ui/components/SlashCommandMenu.tsx
|
|
6692
|
-
import { useEffect as useEffect3, useRef as useRef3, useState as
|
|
7542
|
+
import React4, { useEffect as useEffect3, useLayoutEffect, useRef as useRef3, useState as useState4 } from "react";
|
|
6693
7543
|
import { createPortal } from "react-dom";
|
|
6694
|
-
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
7544
|
+
import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
6695
7545
|
function filterItems(items, query) {
|
|
6696
7546
|
if (!query) return items;
|
|
6697
|
-
const
|
|
6698
|
-
|
|
6699
|
-
|
|
7547
|
+
const colonIdx = query.indexOf(":");
|
|
7548
|
+
const searchPart = colonIdx >= 0 ? query.slice(colonIdx + 1).trim() : query;
|
|
7549
|
+
if (!searchPart) return items;
|
|
7550
|
+
const words = searchPart.toLowerCase().split(/\s+/);
|
|
7551
|
+
const filtered = items.filter(
|
|
7552
|
+
({ title, description }) => {
|
|
7553
|
+
const hay = (title + " " + (description ?? "")).toLowerCase();
|
|
7554
|
+
return words.every((w) => hay.includes(w));
|
|
7555
|
+
}
|
|
6700
7556
|
);
|
|
7557
|
+
return filtered.length > 0 ? filtered : items;
|
|
7558
|
+
}
|
|
7559
|
+
var SCROLLBAR_STYLE_ID = "ab-slash-menu-scrollbar";
|
|
7560
|
+
function injectScrollbarStyle() {
|
|
7561
|
+
if (document.getElementById(SCROLLBAR_STYLE_ID)) return;
|
|
7562
|
+
const style = document.createElement("style");
|
|
7563
|
+
style.id = SCROLLBAR_STYLE_ID;
|
|
7564
|
+
style.textContent = `
|
|
7565
|
+
.ab-slash-menu::-webkit-scrollbar { width: 6px; }
|
|
7566
|
+
.ab-slash-menu::-webkit-scrollbar-track { background: transparent; }
|
|
7567
|
+
.ab-slash-menu::-webkit-scrollbar-thumb { background: #c4c4c4; border-radius: 3px; }
|
|
7568
|
+
.ab-slash-menu::-webkit-scrollbar-thumb:hover { background: #999; }
|
|
7569
|
+
`;
|
|
7570
|
+
document.head.appendChild(style);
|
|
6701
7571
|
}
|
|
6702
|
-
var POPUP_SHADOW = "0
|
|
7572
|
+
var POPUP_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)";
|
|
6703
7573
|
var BTN_RESET = {
|
|
6704
7574
|
border: "none",
|
|
6705
7575
|
padding: 0,
|
|
@@ -6712,11 +7582,14 @@ var BTN_RESET = {
|
|
|
6712
7582
|
width: "100%"
|
|
6713
7583
|
};
|
|
6714
7584
|
var VPORT_MARGIN = 8;
|
|
6715
|
-
var MENU_WIDTH =
|
|
6716
|
-
var MAX_MENU_H =
|
|
7585
|
+
var MENU_WIDTH = 440;
|
|
7586
|
+
var MAX_MENU_H = 400;
|
|
6717
7587
|
function SlashCommandMenu({ view, editorState, items }) {
|
|
6718
|
-
const [selectedIndex, setSelectedIndex] =
|
|
7588
|
+
const [selectedIndex, setSelectedIndex] = useState4(0);
|
|
6719
7589
|
const listRef = useRef3(null);
|
|
7590
|
+
useLayoutEffect(() => {
|
|
7591
|
+
injectScrollbarStyle();
|
|
7592
|
+
}, []);
|
|
6720
7593
|
const pluginState = editorState ? slashCommandKey.getState(editorState) : void 0;
|
|
6721
7594
|
const active = pluginState?.active ?? false;
|
|
6722
7595
|
const range = pluginState?.range ?? null;
|
|
@@ -6728,7 +7601,7 @@ function SlashCommandMenu({ view, editorState, items }) {
|
|
|
6728
7601
|
useEffect3(() => {
|
|
6729
7602
|
const list = listRef.current;
|
|
6730
7603
|
if (!list) return;
|
|
6731
|
-
const item = list.
|
|
7604
|
+
const item = list.querySelector(`[data-slash-index="${selectedIndex}"]`);
|
|
6732
7605
|
item?.scrollIntoView({ block: "nearest" });
|
|
6733
7606
|
}, [selectedIndex]);
|
|
6734
7607
|
useEffect3(() => {
|
|
@@ -6770,6 +7643,7 @@ function SlashCommandMenu({ view, editorState, items }) {
|
|
|
6770
7643
|
/* @__PURE__ */ jsx7(
|
|
6771
7644
|
"div",
|
|
6772
7645
|
{
|
|
7646
|
+
className: "ab-slash-menu",
|
|
6773
7647
|
style: {
|
|
6774
7648
|
position: "fixed",
|
|
6775
7649
|
top,
|
|
@@ -6777,10 +7651,12 @@ function SlashCommandMenu({ view, editorState, items }) {
|
|
|
6777
7651
|
width: MENU_WIDTH,
|
|
6778
7652
|
maxHeight: MAX_MENU_H,
|
|
6779
7653
|
overflowY: "auto",
|
|
7654
|
+
scrollbarWidth: "thin",
|
|
7655
|
+
scrollbarColor: "#c4c4c4 transparent",
|
|
6780
7656
|
background: "#fff",
|
|
6781
|
-
borderRadius:
|
|
7657
|
+
borderRadius: 4,
|
|
6782
7658
|
boxShadow: POPUP_SHADOW,
|
|
6783
|
-
padding:
|
|
7659
|
+
padding: "8px 0",
|
|
6784
7660
|
zIndex: 1100,
|
|
6785
7661
|
animation: "ab-float-in 0.12s ease"
|
|
6786
7662
|
},
|
|
@@ -6794,100 +7670,103 @@ function SlashCommandMenu({ view, editorState, items }) {
|
|
|
6794
7670
|
},
|
|
6795
7671
|
children: "No results"
|
|
6796
7672
|
}
|
|
6797
|
-
) : filtered.map((item, i) =>
|
|
6798
|
-
|
|
6799
|
-
|
|
6800
|
-
|
|
6801
|
-
|
|
6802
|
-
|
|
6803
|
-
|
|
6804
|
-
|
|
6805
|
-
|
|
6806
|
-
|
|
6807
|
-
|
|
7673
|
+
) : filtered.map((item, i) => {
|
|
7674
|
+
const prevGroup = i > 0 ? filtered[i - 1].group : void 0;
|
|
7675
|
+
const showGroupHeader = item.group && item.group !== prevGroup;
|
|
7676
|
+
return /* @__PURE__ */ jsxs6(React4.Fragment, { children: [
|
|
7677
|
+
showGroupHeader && /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
7678
|
+
i > 0 && /* @__PURE__ */ jsx7("div", { style: { height: 1, background: "rgba(0,0,0,0.06)", margin: "4px 10px" } }),
|
|
7679
|
+
/* @__PURE__ */ jsx7(
|
|
7680
|
+
"div",
|
|
7681
|
+
{
|
|
7682
|
+
style: {
|
|
7683
|
+
padding: "8px 16px 4px",
|
|
7684
|
+
fontSize: 13,
|
|
7685
|
+
fontWeight: 400,
|
|
7686
|
+
color: "#5e5e5e"
|
|
7687
|
+
},
|
|
7688
|
+
children: item.group
|
|
7689
|
+
}
|
|
7690
|
+
)
|
|
7691
|
+
] }),
|
|
7692
|
+
/* @__PURE__ */ jsx7(
|
|
7693
|
+
SlashMenuItem,
|
|
7694
|
+
{
|
|
7695
|
+
item,
|
|
7696
|
+
index: i,
|
|
7697
|
+
selected: i === selectedIndex,
|
|
7698
|
+
onMouseEnter: () => setSelectedIndex(i),
|
|
7699
|
+
onMouseDown: (e) => {
|
|
7700
|
+
e.preventDefault();
|
|
7701
|
+
if (range) {
|
|
7702
|
+
item.command({ view, range });
|
|
7703
|
+
view.focus();
|
|
7704
|
+
}
|
|
7705
|
+
}
|
|
6808
7706
|
}
|
|
6809
|
-
|
|
6810
|
-
},
|
|
6811
|
-
|
|
6812
|
-
)) })
|
|
7707
|
+
)
|
|
7708
|
+
] }, item.id ?? item.title);
|
|
7709
|
+
}) })
|
|
6813
7710
|
}
|
|
6814
7711
|
),
|
|
6815
7712
|
document.body
|
|
6816
7713
|
);
|
|
6817
7714
|
}
|
|
6818
|
-
function SlashMenuItem({ item, selected, onMouseEnter, onMouseDown }) {
|
|
7715
|
+
function SlashMenuItem({ item, index, selected, onMouseEnter, onMouseDown }) {
|
|
6819
7716
|
return /* @__PURE__ */ jsxs6(
|
|
6820
7717
|
"button",
|
|
6821
7718
|
{
|
|
7719
|
+
"data-slash-index": index,
|
|
6822
7720
|
style: {
|
|
6823
7721
|
...BTN_RESET,
|
|
6824
7722
|
display: "flex",
|
|
6825
7723
|
alignItems: "center",
|
|
6826
|
-
gap:
|
|
6827
|
-
padding: "
|
|
6828
|
-
|
|
6829
|
-
background: selected ? "rgba(99,102,241,0.07)" : "transparent",
|
|
7724
|
+
gap: 12,
|
|
7725
|
+
padding: "6px 16px",
|
|
7726
|
+
background: selected ? "rgba(13,13,13,0.04)" : "transparent",
|
|
6830
7727
|
transition: "background 0.08s"
|
|
6831
7728
|
},
|
|
6832
7729
|
onMouseEnter,
|
|
6833
7730
|
onMouseDown,
|
|
6834
7731
|
children: [
|
|
6835
|
-
item.icon !== void 0 && /* @__PURE__ */ jsx7(
|
|
7732
|
+
item.icon !== void 0 && /* @__PURE__ */ jsx7("span", { style: { flexShrink: 0, display: "flex", alignItems: "center" }, children: item.icon }),
|
|
7733
|
+
/* @__PURE__ */ jsx7(
|
|
6836
7734
|
"span",
|
|
6837
7735
|
{
|
|
6838
7736
|
style: {
|
|
6839
|
-
|
|
6840
|
-
|
|
6841
|
-
|
|
6842
|
-
|
|
6843
|
-
|
|
6844
|
-
|
|
6845
|
-
|
|
6846
|
-
background: "rgba(0,0,0,0.04)",
|
|
6847
|
-
fontSize: 13,
|
|
6848
|
-
fontWeight: 700,
|
|
6849
|
-
color: "#6366f1",
|
|
6850
|
-
fontFamily: "monospace"
|
|
7737
|
+
fontSize: 14,
|
|
7738
|
+
fontWeight: 400,
|
|
7739
|
+
color: "#0d0d0d",
|
|
7740
|
+
whiteSpace: "nowrap",
|
|
7741
|
+
overflow: "hidden",
|
|
7742
|
+
textOverflow: "ellipsis",
|
|
7743
|
+
minWidth: 0
|
|
6851
7744
|
},
|
|
6852
|
-
children: item.
|
|
7745
|
+
children: item.title
|
|
6853
7746
|
}
|
|
6854
7747
|
),
|
|
6855
|
-
/* @__PURE__ */
|
|
6856
|
-
|
|
6857
|
-
|
|
6858
|
-
|
|
6859
|
-
|
|
6860
|
-
|
|
6861
|
-
|
|
6862
|
-
|
|
6863
|
-
|
|
6864
|
-
|
|
6865
|
-
|
|
6866
|
-
|
|
6867
|
-
|
|
6868
|
-
|
|
6869
|
-
|
|
6870
|
-
item.description && /* @__PURE__ */ jsx7(
|
|
6871
|
-
"span",
|
|
6872
|
-
{
|
|
6873
|
-
style: {
|
|
6874
|
-
fontSize: 11,
|
|
6875
|
-
color: "#9ca3af",
|
|
6876
|
-
whiteSpace: "nowrap",
|
|
6877
|
-
overflow: "hidden",
|
|
6878
|
-
textOverflow: "ellipsis"
|
|
6879
|
-
},
|
|
6880
|
-
children: item.description
|
|
6881
|
-
}
|
|
6882
|
-
)
|
|
6883
|
-
] })
|
|
7748
|
+
/* @__PURE__ */ jsx7("span", { style: { flex: 1 } }),
|
|
7749
|
+
(item.description || item.shortcut) && /* @__PURE__ */ jsx7(
|
|
7750
|
+
"span",
|
|
7751
|
+
{
|
|
7752
|
+
style: {
|
|
7753
|
+
fontSize: 12,
|
|
7754
|
+
color: "#5e5e5e",
|
|
7755
|
+
whiteSpace: "nowrap",
|
|
7756
|
+
flexShrink: 0,
|
|
7757
|
+
textAlign: "right",
|
|
7758
|
+
fontFamily: item.shortcut ? "monospace" : "inherit"
|
|
7759
|
+
},
|
|
7760
|
+
children: item.shortcut ?? item.description
|
|
7761
|
+
}
|
|
7762
|
+
)
|
|
6884
7763
|
]
|
|
6885
7764
|
}
|
|
6886
7765
|
);
|
|
6887
7766
|
}
|
|
6888
7767
|
|
|
6889
7768
|
// src/ui/components/JinjaTreeView.tsx
|
|
6890
|
-
import { useState as
|
|
7769
|
+
import { useState as useState5 } from "react";
|
|
6891
7770
|
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
6892
7771
|
var BRANCH_COLORS = {
|
|
6893
7772
|
if: "#6366f1",
|
|
@@ -6932,7 +7811,7 @@ function BranchNode({
|
|
|
6932
7811
|
] });
|
|
6933
7812
|
}
|
|
6934
7813
|
function StructureNode({ structure, doc: doc2 }) {
|
|
6935
|
-
const [expanded, setExpanded] =
|
|
7814
|
+
const [expanded, setExpanded] = useState5(true);
|
|
6936
7815
|
const firstBranch = structure.branches[0];
|
|
6937
7816
|
const label = firstBranch?.condition ? `if ${firstBranch.condition}` : "if";
|
|
6938
7817
|
return /* @__PURE__ */ jsxs7("div", { className: "jinja-tree-structure", children: [
|
|
@@ -6965,13 +7844,179 @@ function JinjaTreeView({ doc: doc2, className }) {
|
|
|
6965
7844
|
return /* @__PURE__ */ jsx8("div", { className: `jinja-tree ${className || ""}`, children: structures.map((structure) => /* @__PURE__ */ jsx8(StructureNode, { structure, doc: doc2 }, structure.id)) });
|
|
6966
7845
|
}
|
|
6967
7846
|
|
|
7847
|
+
// src/ui/components/DocumentTreeView.tsx
|
|
7848
|
+
import { useState as useState6 } from "react";
|
|
7849
|
+
import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
7850
|
+
var ICONS = {
|
|
7851
|
+
heading: "H",
|
|
7852
|
+
jumpPoint: "\u2299",
|
|
7853
|
+
jinjaIf: "\u2325",
|
|
7854
|
+
jinjaBranch: "\u2387",
|
|
7855
|
+
resourceTag: "\u229B",
|
|
7856
|
+
noteBlock: "\u270D",
|
|
7857
|
+
endAction: "\u2192"
|
|
7858
|
+
};
|
|
7859
|
+
var COLORS = {
|
|
7860
|
+
heading: "#333",
|
|
7861
|
+
jumpPoint: "#d97706",
|
|
7862
|
+
jinjaIf: "#6366f1",
|
|
7863
|
+
jinjaBranch: "#8b5cf6",
|
|
7864
|
+
resourceTag: "#059669",
|
|
7865
|
+
noteBlock: "#999",
|
|
7866
|
+
endAction: "#059669"
|
|
7867
|
+
};
|
|
7868
|
+
function TreeNodeItem({
|
|
7869
|
+
node,
|
|
7870
|
+
onNavigate,
|
|
7871
|
+
depth,
|
|
7872
|
+
selectedPath,
|
|
7873
|
+
onSelect,
|
|
7874
|
+
path
|
|
7875
|
+
}) {
|
|
7876
|
+
const [collapsed, setCollapsed] = useState6(false);
|
|
7877
|
+
const hasChildren = node.children.length > 0;
|
|
7878
|
+
const icon = ICONS[node.type] || "\u2022";
|
|
7879
|
+
const color = COLORS[node.type] || "#666";
|
|
7880
|
+
const isSelected = selectedPath === path;
|
|
7881
|
+
const headingLevel = node.meta?.level;
|
|
7882
|
+
const headingLabel = headingLevel ? `H${headingLevel}` : icon;
|
|
7883
|
+
return /* @__PURE__ */ jsxs8("div", { style: { paddingLeft: depth > 0 ? 16 : 0 }, children: [
|
|
7884
|
+
/* @__PURE__ */ jsxs8(
|
|
7885
|
+
"div",
|
|
7886
|
+
{
|
|
7887
|
+
className: "doc-tree-node",
|
|
7888
|
+
style: {
|
|
7889
|
+
display: "flex",
|
|
7890
|
+
alignItems: "center",
|
|
7891
|
+
gap: 6,
|
|
7892
|
+
padding: "3px 6px",
|
|
7893
|
+
borderRadius: 4,
|
|
7894
|
+
cursor: onNavigate ? "pointer" : "default",
|
|
7895
|
+
fontSize: 13,
|
|
7896
|
+
lineHeight: "1.5",
|
|
7897
|
+
background: isSelected ? "rgba(99, 102, 241, 0.1)" : "transparent",
|
|
7898
|
+
transition: "background 0.12s ease"
|
|
7899
|
+
},
|
|
7900
|
+
onClick: (e) => {
|
|
7901
|
+
e.stopPropagation();
|
|
7902
|
+
if (hasChildren) setCollapsed(!collapsed);
|
|
7903
|
+
onSelect(path);
|
|
7904
|
+
onNavigate?.(node.blockIndex);
|
|
7905
|
+
},
|
|
7906
|
+
onMouseEnter: (e) => {
|
|
7907
|
+
if (!isSelected) e.currentTarget.style.background = "#f3f4f6";
|
|
7908
|
+
},
|
|
7909
|
+
onMouseLeave: (e) => {
|
|
7910
|
+
if (!isSelected) e.currentTarget.style.background = "transparent";
|
|
7911
|
+
},
|
|
7912
|
+
children: [
|
|
7913
|
+
hasChildren && /* @__PURE__ */ jsx9(
|
|
7914
|
+
"span",
|
|
7915
|
+
{
|
|
7916
|
+
style: {
|
|
7917
|
+
width: 14,
|
|
7918
|
+
textAlign: "center",
|
|
7919
|
+
fontSize: 10,
|
|
7920
|
+
color: "#999",
|
|
7921
|
+
flexShrink: 0,
|
|
7922
|
+
userSelect: "none"
|
|
7923
|
+
},
|
|
7924
|
+
children: collapsed ? "\u25B8" : "\u25BE"
|
|
7925
|
+
}
|
|
7926
|
+
),
|
|
7927
|
+
!hasChildren && /* @__PURE__ */ jsx9("span", { style: { width: 14, flexShrink: 0 } }),
|
|
7928
|
+
/* @__PURE__ */ jsx9(
|
|
7929
|
+
"span",
|
|
7930
|
+
{
|
|
7931
|
+
style: {
|
|
7932
|
+
display: "inline-flex",
|
|
7933
|
+
alignItems: "center",
|
|
7934
|
+
justifyContent: "center",
|
|
7935
|
+
width: 22,
|
|
7936
|
+
height: 18,
|
|
7937
|
+
borderRadius: 3,
|
|
7938
|
+
fontSize: 10,
|
|
7939
|
+
fontWeight: 700,
|
|
7940
|
+
color: isSelected ? "#6366f1" : color,
|
|
7941
|
+
background: isSelected ? "rgba(99, 102, 241, 0.15)" : `${color}11`,
|
|
7942
|
+
border: `1px solid ${isSelected ? "rgba(99, 102, 241, 0.3)" : `${color}33`}`,
|
|
7943
|
+
flexShrink: 0
|
|
7944
|
+
},
|
|
7945
|
+
children: node.type === "heading" ? headingLabel : icon
|
|
7946
|
+
}
|
|
7947
|
+
),
|
|
7948
|
+
/* @__PURE__ */ jsx9(
|
|
7949
|
+
"span",
|
|
7950
|
+
{
|
|
7951
|
+
style: {
|
|
7952
|
+
overflow: "hidden",
|
|
7953
|
+
textOverflow: "ellipsis",
|
|
7954
|
+
whiteSpace: "nowrap",
|
|
7955
|
+
color: isSelected ? "#6366f1" : node.type === "noteBlock" ? "#999" : node.type === "endAction" ? "#059669" : "#333",
|
|
7956
|
+
fontStyle: node.type === "noteBlock" ? "italic" : "normal",
|
|
7957
|
+
fontWeight: isSelected ? 600 : node.type === "heading" && headingLevel && headingLevel <= 2 ? 600 : 400
|
|
7958
|
+
},
|
|
7959
|
+
children: node.label
|
|
7960
|
+
}
|
|
7961
|
+
),
|
|
7962
|
+
node.meta?.tagType != null && /* @__PURE__ */ jsx9(
|
|
7963
|
+
"span",
|
|
7964
|
+
{
|
|
7965
|
+
style: {
|
|
7966
|
+
fontSize: 10,
|
|
7967
|
+
padding: "1px 5px",
|
|
7968
|
+
borderRadius: 999,
|
|
7969
|
+
background: node.type === "endAction" ? "rgba(5, 150, 105, 0.1)" : "rgba(0, 0, 0, 0.04)",
|
|
7970
|
+
color: node.type === "endAction" ? "#059669" : "#999",
|
|
7971
|
+
fontWeight: 500
|
|
7972
|
+
},
|
|
7973
|
+
children: String(node.meta.tagType)
|
|
7974
|
+
}
|
|
7975
|
+
)
|
|
7976
|
+
]
|
|
7977
|
+
}
|
|
7978
|
+
),
|
|
7979
|
+
hasChildren && !collapsed && /* @__PURE__ */ jsx9("div", { children: node.children.map((child, i) => /* @__PURE__ */ jsx9(
|
|
7980
|
+
TreeNodeItem,
|
|
7981
|
+
{
|
|
7982
|
+
node: child,
|
|
7983
|
+
onNavigate,
|
|
7984
|
+
depth: depth + 1,
|
|
7985
|
+
selectedPath,
|
|
7986
|
+
onSelect,
|
|
7987
|
+
path: `${path}/${i}`
|
|
7988
|
+
},
|
|
7989
|
+
`${child.type}-${child.blockIndex}-${i}`
|
|
7990
|
+
)) })
|
|
7991
|
+
] });
|
|
7992
|
+
}
|
|
7993
|
+
function DocumentTreeView({ doc: doc2, className, onNavigate }) {
|
|
7994
|
+
const tree = buildDocumentTree(doc2);
|
|
7995
|
+
const [selectedPath, setSelectedPath] = useState6(null);
|
|
7996
|
+
if (tree.length === 0) {
|
|
7997
|
+
return /* @__PURE__ */ jsx9("div", { className, style: { color: "#999", fontSize: 13, padding: 16 }, children: "No document structure to display." });
|
|
7998
|
+
}
|
|
7999
|
+
return /* @__PURE__ */ jsx9("div", { className, style: { padding: "8px 0", fontFamily: "Inter, sans-serif" }, children: tree.map((node, i) => /* @__PURE__ */ jsx9(
|
|
8000
|
+
TreeNodeItem,
|
|
8001
|
+
{
|
|
8002
|
+
node,
|
|
8003
|
+
onNavigate,
|
|
8004
|
+
depth: 0,
|
|
8005
|
+
selectedPath,
|
|
8006
|
+
onSelect: setSelectedPath,
|
|
8007
|
+
path: `${i}`
|
|
8008
|
+
},
|
|
8009
|
+
`${node.type}-${node.blockIndex}-${i}`
|
|
8010
|
+
)) });
|
|
8011
|
+
}
|
|
8012
|
+
|
|
6968
8013
|
// src/ui/components/FloatingMenu.tsx
|
|
6969
|
-
import { useCallback as
|
|
8014
|
+
import { useCallback as useCallback3, useEffect as useEffect4, useRef as useRef4, useState as useState7 } from "react";
|
|
6970
8015
|
import { createPortal as createPortal2 } from "react-dom";
|
|
6971
|
-
import { setBlockType, toggleMark as toggleMark2, wrapIn } from "prosemirror-commands";
|
|
8016
|
+
import { setBlockType as setBlockType2, toggleMark as toggleMark2, wrapIn } from "prosemirror-commands";
|
|
6972
8017
|
import { wrapInList as wrapInList2 } from "prosemirror-schema-list";
|
|
6973
|
-
import { Fragment as
|
|
6974
|
-
var { paragraph:
|
|
8018
|
+
import { Fragment as Fragment4, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
8019
|
+
var { paragraph: paragraph3, heading: heading3, bulletList: bulletList3, orderedList: orderedList3, blockquote: blockquote3 } = actionbookSchema.nodes;
|
|
6975
8020
|
var {
|
|
6976
8021
|
bold: bold2,
|
|
6977
8022
|
italic: italic2,
|
|
@@ -6993,7 +8038,7 @@ function hasMark(state, type) {
|
|
|
6993
8038
|
function activeHeadingLevel(state) {
|
|
6994
8039
|
const { $from } = state.selection;
|
|
6995
8040
|
const node = $from.parent;
|
|
6996
|
-
if (node.type ===
|
|
8041
|
+
if (node.type === heading3) return node.attrs.level;
|
|
6997
8042
|
return null;
|
|
6998
8043
|
}
|
|
6999
8044
|
function activeListType(state) {
|
|
@@ -7027,7 +8072,7 @@ function currentBlockLabel(state) {
|
|
|
7027
8072
|
if (lt === "ordered") return "1. List";
|
|
7028
8073
|
const { $from } = state.selection;
|
|
7029
8074
|
for (let d = $from.depth; d > 0; d--) {
|
|
7030
|
-
if ($from.node(d).type ===
|
|
8075
|
+
if ($from.node(d).type === blockquote3) return "Quote";
|
|
7031
8076
|
}
|
|
7032
8077
|
return "Text";
|
|
7033
8078
|
}
|
|
@@ -7036,7 +8081,7 @@ function emptyBlockCursorPos(state) {
|
|
|
7036
8081
|
if (!selection.empty) return null;
|
|
7037
8082
|
const { $from } = selection;
|
|
7038
8083
|
const parent = $from.parent;
|
|
7039
|
-
if ((parent.type ===
|
|
8084
|
+
if ((parent.type === paragraph3 || parent.type === heading3) && parent.content.size === 0) {
|
|
7040
8085
|
return selection.from;
|
|
7041
8086
|
}
|
|
7042
8087
|
return null;
|
|
@@ -7058,8 +8103,8 @@ var BTN_RESET2 = {
|
|
|
7058
8103
|
lineHeight: 1
|
|
7059
8104
|
};
|
|
7060
8105
|
function TBtn({ children, active, title, onMouseDown, style }) {
|
|
7061
|
-
const [hover, setHover] =
|
|
7062
|
-
return /* @__PURE__ */
|
|
8106
|
+
const [hover, setHover] = useState7(false);
|
|
8107
|
+
return /* @__PURE__ */ jsx10(
|
|
7063
8108
|
"button",
|
|
7064
8109
|
{
|
|
7065
8110
|
...{ [FLOAT_ATTR]: "" },
|
|
@@ -7090,12 +8135,12 @@ function TBtn({ children, active, title, onMouseDown, style }) {
|
|
|
7090
8135
|
);
|
|
7091
8136
|
}
|
|
7092
8137
|
function Divider() {
|
|
7093
|
-
return /* @__PURE__ */
|
|
8138
|
+
return /* @__PURE__ */ jsx10("div", { style: { width: 1, height: 18, background: "rgba(0,0,0,0.07)", margin: "0 2px", flexShrink: 0 } });
|
|
7094
8139
|
}
|
|
7095
8140
|
function BlockTypeDropdown({ view, state, label }) {
|
|
7096
|
-
const [open, setOpen] =
|
|
8141
|
+
const [open, setOpen] = useState7(false);
|
|
7097
8142
|
const btnRef = useRef4(null);
|
|
7098
|
-
const [hover, setHover] =
|
|
8143
|
+
const [hover, setHover] = useState7(false);
|
|
7099
8144
|
useEffect4(() => {
|
|
7100
8145
|
if (!open) return;
|
|
7101
8146
|
const onDown = (e) => {
|
|
@@ -7110,19 +8155,19 @@ function BlockTypeDropdown({ view, state, label }) {
|
|
|
7110
8155
|
const listType = activeListType(state);
|
|
7111
8156
|
const items = [
|
|
7112
8157
|
{ label: "Text", shortLabel: "\xB6", active: !headingLevel && !listType, run: () => {
|
|
7113
|
-
|
|
8158
|
+
setBlockType2(paragraph3)(view.state, view.dispatch);
|
|
7114
8159
|
view.focus();
|
|
7115
8160
|
} },
|
|
7116
8161
|
{ label: "Heading 1", shortLabel: "H1", active: headingLevel === 1, run: () => {
|
|
7117
|
-
|
|
8162
|
+
setBlockType2(heading3, { level: 1 })(view.state, view.dispatch);
|
|
7118
8163
|
view.focus();
|
|
7119
8164
|
} },
|
|
7120
8165
|
{ label: "Heading 2", shortLabel: "H2", active: headingLevel === 2, run: () => {
|
|
7121
|
-
|
|
8166
|
+
setBlockType2(heading3, { level: 2 })(view.state, view.dispatch);
|
|
7122
8167
|
view.focus();
|
|
7123
8168
|
} },
|
|
7124
8169
|
{ label: "Heading 3", shortLabel: "H3", active: headingLevel === 3, run: () => {
|
|
7125
|
-
|
|
8170
|
+
setBlockType2(heading3, { level: 3 })(view.state, view.dispatch);
|
|
7126
8171
|
view.focus();
|
|
7127
8172
|
} },
|
|
7128
8173
|
{ label: "Bullet List", shortLabel: "\u2022", active: listType === "bullet", run: () => {
|
|
@@ -7144,13 +8189,17 @@ function BlockTypeDropdown({ view, state, label }) {
|
|
|
7144
8189
|
view.focus();
|
|
7145
8190
|
} },
|
|
7146
8191
|
{ label: "Quote", shortLabel: ">", active: false, run: () => {
|
|
7147
|
-
|
|
8192
|
+
const { $from } = view.state.selection;
|
|
8193
|
+
for (let d = $from.depth; d > 0; d--) {
|
|
8194
|
+
if ($from.node(d).type.name === "listItem") return;
|
|
8195
|
+
}
|
|
8196
|
+
wrapIn(blockquote3)(view.state, view.dispatch);
|
|
7148
8197
|
view.focus();
|
|
7149
8198
|
} }
|
|
7150
8199
|
];
|
|
7151
8200
|
const btnRect = btnRef.current?.getBoundingClientRect();
|
|
7152
|
-
return /* @__PURE__ */
|
|
7153
|
-
/* @__PURE__ */
|
|
8201
|
+
return /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
8202
|
+
/* @__PURE__ */ jsxs9(
|
|
7154
8203
|
"button",
|
|
7155
8204
|
{
|
|
7156
8205
|
ref: btnRef,
|
|
@@ -7178,12 +8227,12 @@ function BlockTypeDropdown({ view, state, label }) {
|
|
|
7178
8227
|
},
|
|
7179
8228
|
children: [
|
|
7180
8229
|
label,
|
|
7181
|
-
/* @__PURE__ */
|
|
8230
|
+
/* @__PURE__ */ jsx10("span", { style: { fontSize: 8, opacity: 0.6 }, children: "\u25BE" })
|
|
7182
8231
|
]
|
|
7183
8232
|
}
|
|
7184
8233
|
),
|
|
7185
8234
|
open && btnRect && createPortal2(
|
|
7186
|
-
/* @__PURE__ */
|
|
8235
|
+
/* @__PURE__ */ jsx10(
|
|
7187
8236
|
"div",
|
|
7188
8237
|
{
|
|
7189
8238
|
...{ [FLOAT_ATTR]: "" },
|
|
@@ -7199,7 +8248,7 @@ function BlockTypeDropdown({ view, state, label }) {
|
|
|
7199
8248
|
minWidth: 168,
|
|
7200
8249
|
animation: "ab-float-in 0.12s ease"
|
|
7201
8250
|
},
|
|
7202
|
-
children: items.map((item) => /* @__PURE__ */
|
|
8251
|
+
children: items.map((item) => /* @__PURE__ */ jsx10(DropdownItem, { item, onRun: () => setOpen(false) }, item.label))
|
|
7203
8252
|
}
|
|
7204
8253
|
),
|
|
7205
8254
|
document.body
|
|
@@ -7207,8 +8256,8 @@ function BlockTypeDropdown({ view, state, label }) {
|
|
|
7207
8256
|
] });
|
|
7208
8257
|
}
|
|
7209
8258
|
function DropdownItem({ item, onRun }) {
|
|
7210
|
-
const [hover, setHover] =
|
|
7211
|
-
return /* @__PURE__ */
|
|
8259
|
+
const [hover, setHover] = useState7(false);
|
|
8260
|
+
return /* @__PURE__ */ jsxs9(
|
|
7212
8261
|
"button",
|
|
7213
8262
|
{
|
|
7214
8263
|
...{ [FLOAT_ATTR]: "" },
|
|
@@ -7235,15 +8284,15 @@ function DropdownItem({ item, onRun }) {
|
|
|
7235
8284
|
transition: "background 0.1s"
|
|
7236
8285
|
},
|
|
7237
8286
|
children: [
|
|
7238
|
-
/* @__PURE__ */
|
|
8287
|
+
/* @__PURE__ */ jsx10("span", { style: { width: 24, flexShrink: 0, textAlign: "center", fontWeight: 700, fontSize: 12, fontFamily: "monospace", color: "#6366f1" }, children: item.shortLabel }),
|
|
7239
8288
|
item.label
|
|
7240
8289
|
]
|
|
7241
8290
|
}
|
|
7242
8291
|
);
|
|
7243
8292
|
}
|
|
7244
8293
|
function SelectionToolbar({ view, state, selectionRect }) {
|
|
7245
|
-
const [linkMode, setLinkMode] =
|
|
7246
|
-
const [linkHref, setLinkHref] =
|
|
8294
|
+
const [linkMode, setLinkMode] = useState7(false);
|
|
8295
|
+
const [linkHref, setLinkHref] = useState7("");
|
|
7247
8296
|
const inputRef = useRef4(null);
|
|
7248
8297
|
const isBold = hasMark(state, bold2);
|
|
7249
8298
|
const isItalic = hasMark(state, italic2);
|
|
@@ -7259,7 +8308,7 @@ function SelectionToolbar({ view, state, selectionRect }) {
|
|
|
7259
8308
|
if (top < VPORT_MARGIN2) top = selectionRect.bottom + TOOLBAR_GAP;
|
|
7260
8309
|
left = Math.max(VPORT_MARGIN2, Math.min(left, window.innerWidth - toolbarW - VPORT_MARGIN2));
|
|
7261
8310
|
top = Math.max(VPORT_MARGIN2, Math.min(top, window.innerHeight - toolbarH - VPORT_MARGIN2));
|
|
7262
|
-
const run =
|
|
8311
|
+
const run = useCallback3(
|
|
7263
8312
|
(cmd) => {
|
|
7264
8313
|
cmd(view.state, view.dispatch);
|
|
7265
8314
|
view.focus();
|
|
@@ -7296,10 +8345,10 @@ function SelectionToolbar({ view, state, selectionRect }) {
|
|
|
7296
8345
|
view.dispatch(view.state.tr.removeMark(from, to, linkMark));
|
|
7297
8346
|
view.focus();
|
|
7298
8347
|
};
|
|
7299
|
-
return /* @__PURE__ */
|
|
8348
|
+
return /* @__PURE__ */ jsx10(
|
|
7300
8349
|
"div",
|
|
7301
8350
|
{
|
|
7302
|
-
...{ [FLOAT_ATTR]: "" },
|
|
8351
|
+
...{ [FLOAT_ATTR]: "selection-toolbar" },
|
|
7303
8352
|
style: {
|
|
7304
8353
|
position: "fixed",
|
|
7305
8354
|
left,
|
|
@@ -7319,9 +8368,9 @@ function SelectionToolbar({ view, state, selectionRect }) {
|
|
|
7319
8368
|
},
|
|
7320
8369
|
children: linkMode ? (
|
|
7321
8370
|
/* ── Link input mode ── */
|
|
7322
|
-
/* @__PURE__ */
|
|
7323
|
-
/* @__PURE__ */
|
|
7324
|
-
/* @__PURE__ */
|
|
8371
|
+
/* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
8372
|
+
/* @__PURE__ */ jsx10("span", { style: { fontSize: 13, color: "#9ca3af", paddingLeft: 4, flexShrink: 0 }, children: "\u2197" }),
|
|
8373
|
+
/* @__PURE__ */ jsx10(
|
|
7325
8374
|
"input",
|
|
7326
8375
|
{
|
|
7327
8376
|
ref: inputRef,
|
|
@@ -7352,7 +8401,7 @@ function SelectionToolbar({ view, state, selectionRect }) {
|
|
|
7352
8401
|
}
|
|
7353
8402
|
}
|
|
7354
8403
|
),
|
|
7355
|
-
/* @__PURE__ */
|
|
8404
|
+
/* @__PURE__ */ jsx10(
|
|
7356
8405
|
TBtn,
|
|
7357
8406
|
{
|
|
7358
8407
|
title: "Apply (Enter)",
|
|
@@ -7364,7 +8413,7 @@ function SelectionToolbar({ view, state, selectionRect }) {
|
|
|
7364
8413
|
children: "\u21B5"
|
|
7365
8414
|
}
|
|
7366
8415
|
),
|
|
7367
|
-
/* @__PURE__ */
|
|
8416
|
+
/* @__PURE__ */ jsx10(
|
|
7368
8417
|
TBtn,
|
|
7369
8418
|
{
|
|
7370
8419
|
title: "Cancel (Esc)",
|
|
@@ -7380,8 +8429,8 @@ function SelectionToolbar({ view, state, selectionRect }) {
|
|
|
7380
8429
|
] })
|
|
7381
8430
|
) : (
|
|
7382
8431
|
/* ── Normal toolbar mode ── */
|
|
7383
|
-
/* @__PURE__ */
|
|
7384
|
-
/* @__PURE__ */
|
|
8432
|
+
/* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
8433
|
+
/* @__PURE__ */ jsx10(
|
|
7385
8434
|
TBtn,
|
|
7386
8435
|
{
|
|
7387
8436
|
active: isBold,
|
|
@@ -7391,7 +8440,7 @@ function SelectionToolbar({ view, state, selectionRect }) {
|
|
|
7391
8440
|
children: "B"
|
|
7392
8441
|
}
|
|
7393
8442
|
),
|
|
7394
|
-
/* @__PURE__ */
|
|
8443
|
+
/* @__PURE__ */ jsx10(
|
|
7395
8444
|
TBtn,
|
|
7396
8445
|
{
|
|
7397
8446
|
active: isItalic,
|
|
@@ -7401,7 +8450,7 @@ function SelectionToolbar({ view, state, selectionRect }) {
|
|
|
7401
8450
|
children: "I"
|
|
7402
8451
|
}
|
|
7403
8452
|
),
|
|
7404
|
-
/* @__PURE__ */
|
|
8453
|
+
/* @__PURE__ */ jsx10(
|
|
7405
8454
|
TBtn,
|
|
7406
8455
|
{
|
|
7407
8456
|
active: isUnderline,
|
|
@@ -7411,7 +8460,7 @@ function SelectionToolbar({ view, state, selectionRect }) {
|
|
|
7411
8460
|
children: "U"
|
|
7412
8461
|
}
|
|
7413
8462
|
),
|
|
7414
|
-
/* @__PURE__ */
|
|
8463
|
+
/* @__PURE__ */ jsx10(
|
|
7415
8464
|
TBtn,
|
|
7416
8465
|
{
|
|
7417
8466
|
active: isStrike,
|
|
@@ -7421,7 +8470,7 @@ function SelectionToolbar({ view, state, selectionRect }) {
|
|
|
7421
8470
|
children: "S"
|
|
7422
8471
|
}
|
|
7423
8472
|
),
|
|
7424
|
-
/* @__PURE__ */
|
|
8473
|
+
/* @__PURE__ */ jsx10(
|
|
7425
8474
|
TBtn,
|
|
7426
8475
|
{
|
|
7427
8476
|
active: isCode,
|
|
@@ -7431,7 +8480,7 @@ function SelectionToolbar({ view, state, selectionRect }) {
|
|
|
7431
8480
|
children: "`\xB7`"
|
|
7432
8481
|
}
|
|
7433
8482
|
),
|
|
7434
|
-
/* @__PURE__ */
|
|
8483
|
+
/* @__PURE__ */ jsx10(
|
|
7435
8484
|
TBtn,
|
|
7436
8485
|
{
|
|
7437
8486
|
active: isLink,
|
|
@@ -7441,8 +8490,8 @@ function SelectionToolbar({ view, state, selectionRect }) {
|
|
|
7441
8490
|
children: "\u2197"
|
|
7442
8491
|
}
|
|
7443
8492
|
),
|
|
7444
|
-
/* @__PURE__ */
|
|
7445
|
-
/* @__PURE__ */
|
|
8493
|
+
/* @__PURE__ */ jsx10(Divider, {}),
|
|
8494
|
+
/* @__PURE__ */ jsx10(BlockTypeDropdown, { view, state, label: blockLabel })
|
|
7446
8495
|
] })
|
|
7447
8496
|
)
|
|
7448
8497
|
}
|
|
@@ -7453,7 +8502,7 @@ var BLOCK_ITEMS = [
|
|
|
7453
8502
|
shortLabel: "\xB6",
|
|
7454
8503
|
label: "Text",
|
|
7455
8504
|
run: (v) => {
|
|
7456
|
-
|
|
8505
|
+
setBlockType2(paragraph3)(v.state, v.dispatch);
|
|
7457
8506
|
v.focus();
|
|
7458
8507
|
}
|
|
7459
8508
|
},
|
|
@@ -7461,7 +8510,7 @@ var BLOCK_ITEMS = [
|
|
|
7461
8510
|
shortLabel: "H1",
|
|
7462
8511
|
label: "Heading 1",
|
|
7463
8512
|
run: (v) => {
|
|
7464
|
-
|
|
8513
|
+
setBlockType2(heading3, { level: 1 })(v.state, v.dispatch);
|
|
7465
8514
|
v.focus();
|
|
7466
8515
|
}
|
|
7467
8516
|
},
|
|
@@ -7469,7 +8518,7 @@ var BLOCK_ITEMS = [
|
|
|
7469
8518
|
shortLabel: "H2",
|
|
7470
8519
|
label: "Heading 2",
|
|
7471
8520
|
run: (v) => {
|
|
7472
|
-
|
|
8521
|
+
setBlockType2(heading3, { level: 2 })(v.state, v.dispatch);
|
|
7473
8522
|
v.focus();
|
|
7474
8523
|
}
|
|
7475
8524
|
},
|
|
@@ -7477,7 +8526,7 @@ var BLOCK_ITEMS = [
|
|
|
7477
8526
|
shortLabel: "H3",
|
|
7478
8527
|
label: "Heading 3",
|
|
7479
8528
|
run: (v) => {
|
|
7480
|
-
|
|
8529
|
+
setBlockType2(heading3, { level: 3 })(v.state, v.dispatch);
|
|
7481
8530
|
v.focus();
|
|
7482
8531
|
}
|
|
7483
8532
|
},
|
|
@@ -7512,7 +8561,7 @@ var BLOCK_ITEMS = [
|
|
|
7512
8561
|
shortLabel: "\u275D",
|
|
7513
8562
|
label: "Quote",
|
|
7514
8563
|
run: (v) => {
|
|
7515
|
-
wrapIn(
|
|
8564
|
+
wrapIn(blockquote3)(v.state, v.dispatch);
|
|
7516
8565
|
v.focus();
|
|
7517
8566
|
}
|
|
7518
8567
|
},
|
|
@@ -7532,7 +8581,7 @@ var BLOCK_ITEMS = [
|
|
|
7532
8581
|
}
|
|
7533
8582
|
];
|
|
7534
8583
|
function EmptyParaHandle({ view, cursorPos }) {
|
|
7535
|
-
const [menuOpen, setMenuOpen] =
|
|
8584
|
+
const [menuOpen, setMenuOpen] = useState7(false);
|
|
7536
8585
|
const coords = view.coordsAtPos(cursorPos);
|
|
7537
8586
|
const lineH = Math.max(coords.bottom - coords.top, 18);
|
|
7538
8587
|
const btnSize = 22;
|
|
@@ -7550,8 +8599,8 @@ function EmptyParaHandle({ view, cursorPos }) {
|
|
|
7550
8599
|
document.addEventListener("mousedown", onDown, true);
|
|
7551
8600
|
return () => document.removeEventListener("mousedown", onDown, true);
|
|
7552
8601
|
}, [menuOpen]);
|
|
7553
|
-
return /* @__PURE__ */
|
|
7554
|
-
/* @__PURE__ */
|
|
8602
|
+
return /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
8603
|
+
/* @__PURE__ */ jsx10(
|
|
7555
8604
|
"button",
|
|
7556
8605
|
{
|
|
7557
8606
|
...{ [FLOAT_ATTR]: "" },
|
|
@@ -7583,7 +8632,7 @@ function EmptyParaHandle({ view, cursorPos }) {
|
|
|
7583
8632
|
children: "+"
|
|
7584
8633
|
}
|
|
7585
8634
|
),
|
|
7586
|
-
menuOpen && /* @__PURE__ */
|
|
8635
|
+
menuOpen && /* @__PURE__ */ jsx10(
|
|
7587
8636
|
"div",
|
|
7588
8637
|
{
|
|
7589
8638
|
...{ [FLOAT_ATTR]: "" },
|
|
@@ -7599,7 +8648,7 @@ function EmptyParaHandle({ view, cursorPos }) {
|
|
|
7599
8648
|
minWidth: 168,
|
|
7600
8649
|
animation: "ab-float-in 0.12s ease"
|
|
7601
8650
|
},
|
|
7602
|
-
children: BLOCK_ITEMS.map((item) => /* @__PURE__ */
|
|
8651
|
+
children: BLOCK_ITEMS.map((item) => /* @__PURE__ */ jsx10(
|
|
7603
8652
|
BlockMenuItem,
|
|
7604
8653
|
{
|
|
7605
8654
|
item,
|
|
@@ -7617,8 +8666,8 @@ function BlockMenuItem({
|
|
|
7617
8666
|
view,
|
|
7618
8667
|
onRun
|
|
7619
8668
|
}) {
|
|
7620
|
-
const [hover, setHover] =
|
|
7621
|
-
return /* @__PURE__ */
|
|
8669
|
+
const [hover, setHover] = useState7(false);
|
|
8670
|
+
return /* @__PURE__ */ jsxs9(
|
|
7622
8671
|
"button",
|
|
7623
8672
|
{
|
|
7624
8673
|
...{ [FLOAT_ATTR]: "" },
|
|
@@ -7644,7 +8693,7 @@ function BlockMenuItem({
|
|
|
7644
8693
|
transition: "background 0.1s"
|
|
7645
8694
|
},
|
|
7646
8695
|
children: [
|
|
7647
|
-
/* @__PURE__ */
|
|
8696
|
+
/* @__PURE__ */ jsx10(
|
|
7648
8697
|
"span",
|
|
7649
8698
|
{
|
|
7650
8699
|
style: {
|
|
@@ -7665,10 +8714,10 @@ function BlockMenuItem({
|
|
|
7665
8714
|
);
|
|
7666
8715
|
}
|
|
7667
8716
|
function FloatingMenu({ view, editorState }) {
|
|
7668
|
-
const [showEmptyHandle, setShowEmptyHandle] =
|
|
8717
|
+
const [showEmptyHandle, setShowEmptyHandle] = useState7(false);
|
|
7669
8718
|
const dwellTimerRef = useRef4(null);
|
|
7670
8719
|
const lastEmptyPosRef = useRef4(null);
|
|
7671
|
-
const [, setScrollTick] =
|
|
8720
|
+
const [, setScrollTick] = useState7(0);
|
|
7672
8721
|
useEffect4(() => {
|
|
7673
8722
|
const editorDom = view?.dom;
|
|
7674
8723
|
if (!editorDom) return;
|
|
@@ -7708,8 +8757,8 @@ function FloatingMenu({ view, editorState }) {
|
|
|
7708
8757
|
}
|
|
7709
8758
|
const selectionRect = hasSelection ? getSelectionDOMRect() : null;
|
|
7710
8759
|
return createPortal2(
|
|
7711
|
-
/* @__PURE__ */
|
|
7712
|
-
hasSelection && selectionRect && /* @__PURE__ */
|
|
8760
|
+
/* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
8761
|
+
hasSelection && selectionRect && /* @__PURE__ */ jsx10(
|
|
7713
8762
|
SelectionToolbar,
|
|
7714
8763
|
{
|
|
7715
8764
|
view,
|
|
@@ -7717,7 +8766,7 @@ function FloatingMenu({ view, editorState }) {
|
|
|
7717
8766
|
selectionRect
|
|
7718
8767
|
}
|
|
7719
8768
|
),
|
|
7720
|
-
!hasSelection && showEmptyHandle && emptyPos !== null && /* @__PURE__ */
|
|
8769
|
+
!hasSelection && showEmptyHandle && emptyPos !== null && /* @__PURE__ */ jsx10(EmptyParaHandle, { view, cursorPos: emptyPos })
|
|
7721
8770
|
] }),
|
|
7722
8771
|
document.body
|
|
7723
8772
|
);
|
|
@@ -7886,6 +8935,7 @@ function createInlineSuggestPlugin(provider, endpoint, options) {
|
|
|
7886
8935
|
}
|
|
7887
8936
|
export {
|
|
7888
8937
|
ActionbookRenderer,
|
|
8938
|
+
DocumentTreeView,
|
|
7889
8939
|
EditorShell,
|
|
7890
8940
|
FloatingMenu,
|
|
7891
8941
|
JUMP_POINT_ADJACENT_SPEC,
|
|
@@ -7908,6 +8958,7 @@ export {
|
|
|
7908
8958
|
createKeymapPlugin,
|
|
7909
8959
|
createLinkPlugin,
|
|
7910
8960
|
createMarkdownClipboardPlugin,
|
|
8961
|
+
createNoteBlockPlugin,
|
|
7911
8962
|
createPluginArray,
|
|
7912
8963
|
createReactNodeView,
|
|
7913
8964
|
createSlashCommandPlugin,
|