@sendbird/actionbook-core 0.8.1 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +13 -0
- package/README.md +2 -2
- package/dist/index.d.ts +37 -3
- package/dist/index.js +484 -33
- 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 +1531 -717
- 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 ──
|
|
@@ -578,6 +562,12 @@ function IconTimeDiff({ size = 16, fill = "currentColor", style }) {
|
|
|
578
562
|
}
|
|
579
563
|
);
|
|
580
564
|
}
|
|
565
|
+
function IconStop({ size = 16, fill = "currentColor", style }) {
|
|
566
|
+
return /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 8 8", width: size, height: size, fill: "none", style, children: [
|
|
567
|
+
/* @__PURE__ */ jsx("path", { d: "M5.4375 3.375L2.0625 3.375V4.125L5.4375 4.125V3.375Z", fill }),
|
|
568
|
+
/* @__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 })
|
|
569
|
+
] });
|
|
570
|
+
}
|
|
581
571
|
function IconAnchor({ size = 16, fill = "currentColor", style }) {
|
|
582
572
|
return /* @__PURE__ */ jsxs(
|
|
583
573
|
"svg",
|
|
@@ -816,21 +806,24 @@ var ReactNodeViewImpl = class {
|
|
|
816
806
|
dom;
|
|
817
807
|
root;
|
|
818
808
|
component;
|
|
809
|
+
wrapper;
|
|
819
810
|
_node;
|
|
820
811
|
_view;
|
|
821
812
|
_getPos;
|
|
822
813
|
_selected = false;
|
|
823
814
|
_decorations = [];
|
|
824
|
-
constructor(node, view, getPos, options) {
|
|
815
|
+
constructor(node, view, getPos, decorations, options) {
|
|
825
816
|
this._node = node;
|
|
826
817
|
this._view = view;
|
|
827
818
|
this._getPos = getPos;
|
|
819
|
+
this._decorations = decorations;
|
|
828
820
|
this.component = options.component;
|
|
821
|
+
this.wrapper = options.wrapper;
|
|
829
822
|
const tag = options.as ?? (options.inline !== false ? "span" : "div");
|
|
830
823
|
this.dom = document.createElement(tag);
|
|
831
824
|
if (options.inline !== false) {
|
|
832
|
-
this.dom.style.display = "inline
|
|
833
|
-
this.dom.style.verticalAlign = "
|
|
825
|
+
this.dom.style.display = "inline";
|
|
826
|
+
this.dom.style.verticalAlign = "baseline";
|
|
834
827
|
}
|
|
835
828
|
if (options.className) {
|
|
836
829
|
this.dom.className = options.className;
|
|
@@ -839,14 +832,15 @@ var ReactNodeViewImpl = class {
|
|
|
839
832
|
this.render();
|
|
840
833
|
}
|
|
841
834
|
render() {
|
|
835
|
+
const element = createElement(this.component, {
|
|
836
|
+
node: this._node,
|
|
837
|
+
view: this._view,
|
|
838
|
+
getPos: this._getPos,
|
|
839
|
+
selected: this._selected,
|
|
840
|
+
decorations: this._decorations
|
|
841
|
+
});
|
|
842
842
|
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
|
-
})
|
|
843
|
+
this.wrapper ? createElement(this.wrapper, null, element) : element
|
|
850
844
|
);
|
|
851
845
|
}
|
|
852
846
|
update(node, decorations, _innerDecorations) {
|
|
@@ -875,7 +869,7 @@ var ReactNodeViewImpl = class {
|
|
|
875
869
|
}
|
|
876
870
|
};
|
|
877
871
|
function createReactNodeView(options) {
|
|
878
|
-
return (node, view, getPos) => new ReactNodeViewImpl(node, view, getPos, options);
|
|
872
|
+
return (node, view, getPos, decorations) => new ReactNodeViewImpl(node, view, getPos, decorations, options);
|
|
879
873
|
}
|
|
880
874
|
|
|
881
875
|
// src/ui/hooks/useEditorView.ts
|
|
@@ -884,9 +878,19 @@ import { EditorState } from "prosemirror-state";
|
|
|
884
878
|
import { EditorView } from "prosemirror-view";
|
|
885
879
|
import { Node as PMNode } from "prosemirror-model";
|
|
886
880
|
|
|
881
|
+
// src/ast/types.ts
|
|
882
|
+
var RESOURCE_TAG_TYPES = ["tool", "manual", "agent_message_template", "handoff", "time_diff", "time_difference"];
|
|
883
|
+
|
|
887
884
|
// src/compat/prosemirror.ts
|
|
888
885
|
var MAX_DEPTH = 128;
|
|
889
886
|
var ALLOWED_URL_PROTOCOLS = /^(https?:|mailto:|tel:|#|\/)/i;
|
|
887
|
+
var LIST_TYPES = /* @__PURE__ */ new Set(["bulletList", "orderedList"]);
|
|
888
|
+
function isLooseList(items) {
|
|
889
|
+
return items.some((li) => {
|
|
890
|
+
const nonListBlocks = li.content.filter((b) => !LIST_TYPES.has(b.type));
|
|
891
|
+
return nonListBlocks.length > 1;
|
|
892
|
+
});
|
|
893
|
+
}
|
|
890
894
|
function convertPMMark(mark) {
|
|
891
895
|
switch (mark.type) {
|
|
892
896
|
case "bold":
|
|
@@ -925,12 +929,17 @@ function convertPMInline(node, depth) {
|
|
|
925
929
|
}
|
|
926
930
|
case "inlineToolTag": {
|
|
927
931
|
const attrs = node.attrs ?? {};
|
|
932
|
+
const tagType = attrs.type ?? "tool";
|
|
933
|
+
const text2 = attrs.text ?? "";
|
|
934
|
+
if (!RESOURCE_TAG_TYPES.includes(tagType)) {
|
|
935
|
+
return text2 ? [{ type: "text", text: text2 }] : [];
|
|
936
|
+
}
|
|
928
937
|
return [
|
|
929
938
|
{
|
|
930
939
|
type: "resourceTag",
|
|
931
|
-
tagType
|
|
940
|
+
tagType,
|
|
932
941
|
resourceId: attrs.resourceId ?? "",
|
|
933
|
-
text:
|
|
942
|
+
text: text2
|
|
934
943
|
}
|
|
935
944
|
];
|
|
936
945
|
}
|
|
@@ -961,20 +970,27 @@ function convertPMBlock(node, depth = 0) {
|
|
|
961
970
|
const level = node.attrs?.level ?? 1;
|
|
962
971
|
return [{ type: "heading", level, content: children.flatMap((c) => convertPMInline(c, depth + 1)) }];
|
|
963
972
|
}
|
|
964
|
-
case "bulletList":
|
|
973
|
+
case "bulletList": {
|
|
974
|
+
const items = children.map((c) => convertPMListItem(c, depth + 1));
|
|
975
|
+
const spread = isLooseList(items);
|
|
965
976
|
return [
|
|
966
977
|
{
|
|
967
978
|
type: "bulletList",
|
|
968
|
-
|
|
979
|
+
...spread ? { spread: true } : {},
|
|
980
|
+
content: items.map((li) => spread ? { ...li, spread: true } : li)
|
|
969
981
|
}
|
|
970
982
|
];
|
|
983
|
+
}
|
|
971
984
|
case "orderedList": {
|
|
972
985
|
const start = node.attrs?.start ?? 1;
|
|
986
|
+
const items = children.map((c) => convertPMListItem(c, depth + 1));
|
|
987
|
+
const spread = isLooseList(items);
|
|
973
988
|
return [
|
|
974
989
|
{
|
|
975
990
|
type: "orderedList",
|
|
976
991
|
start,
|
|
977
|
-
|
|
992
|
+
...spread ? { spread: true } : {},
|
|
993
|
+
content: items.map((li) => spread ? { ...li, spread: true } : li)
|
|
978
994
|
}
|
|
979
995
|
];
|
|
980
996
|
}
|
|
@@ -985,6 +1001,12 @@ function convertPMBlock(node, depth = 0) {
|
|
|
985
1001
|
return [{ type: "blockquote", content: children.flatMap((c) => convertPMBlock(c, depth + 1)) }];
|
|
986
1002
|
case "horizontalRule":
|
|
987
1003
|
return [{ type: "horizontalRule" }];
|
|
1004
|
+
case "codeBlock": {
|
|
1005
|
+
const textContent2 = children.map((c) => c.text ?? "").join("");
|
|
1006
|
+
return [{ type: "codeBlock", content: textContent2, ...node.attrs?.language ? { language: node.attrs.language } : {} }];
|
|
1007
|
+
}
|
|
1008
|
+
case "noteBlock":
|
|
1009
|
+
return [{ type: "noteBlock", content: children.flatMap((c) => convertPMBlock(c, depth + 1)) }];
|
|
988
1010
|
case "table": {
|
|
989
1011
|
const rows = children.map((rowNode) => {
|
|
990
1012
|
const cells = (rowNode.content ?? []).map((cellNode) => {
|
|
@@ -1001,6 +1023,22 @@ function convertPMBlock(node, depth = 0) {
|
|
|
1001
1023
|
});
|
|
1002
1024
|
return [{ type: "table", content: rows }];
|
|
1003
1025
|
}
|
|
1026
|
+
case "jinjaIfBlock": {
|
|
1027
|
+
const branches = children.map((branchNode) => {
|
|
1028
|
+
const branchType = branchNode.attrs?.branchType ?? "if";
|
|
1029
|
+
const condition = branchNode.attrs?.condition;
|
|
1030
|
+
const branchContent = (branchNode.content ?? []).flatMap((c) => convertPMBlock(c, depth + 2));
|
|
1031
|
+
return {
|
|
1032
|
+
branchType,
|
|
1033
|
+
...branchType !== "else" && condition ? { condition } : {},
|
|
1034
|
+
content: branchContent
|
|
1035
|
+
};
|
|
1036
|
+
});
|
|
1037
|
+
if (branches.length === 0) return [];
|
|
1038
|
+
return [{ type: "jinjaIfBlock", branches }];
|
|
1039
|
+
}
|
|
1040
|
+
case "jinjaIfBranch":
|
|
1041
|
+
return children.flatMap((c) => convertPMBlock(c, depth + 1));
|
|
1004
1042
|
default:
|
|
1005
1043
|
if (children.length > 0) {
|
|
1006
1044
|
return children.flatMap((c) => convertPMBlock(c, depth + 1));
|
|
@@ -1012,11 +1050,11 @@ function convertPMListItem(node, depth = 0) {
|
|
|
1012
1050
|
if (depth > MAX_DEPTH) return { type: "listItem", content: [{ type: "paragraph", content: [] }] };
|
|
1013
1051
|
const children = node.content ?? [];
|
|
1014
1052
|
const content = children.flatMap((c) => convertPMBlock(c, depth + 1));
|
|
1015
|
-
const checked = node.attrs?.checked;
|
|
1016
1053
|
const base = {
|
|
1017
1054
|
type: "listItem",
|
|
1018
1055
|
content: content.length > 0 ? content : [{ type: "paragraph", content: [] }]
|
|
1019
1056
|
};
|
|
1057
|
+
const checked = node.attrs?.checked;
|
|
1020
1058
|
if (typeof checked === "boolean") {
|
|
1021
1059
|
base.checked = checked;
|
|
1022
1060
|
}
|
|
@@ -1580,7 +1618,7 @@ function listItemWithTaskListItem(node, parent, state, info) {
|
|
|
1580
1618
|
|
|
1581
1619
|
// src/markdown/plugins/resourceTag.ts
|
|
1582
1620
|
var RESOURCE_TAG_RE = /\{\{([^:}]+):([^:}]*):([^}]+)\}\}/g;
|
|
1583
|
-
var VALID_TYPES = /* @__PURE__ */ new Set(["tool", "manual", "agent_message_template", "handoff", "time_diff"]);
|
|
1621
|
+
var VALID_TYPES = /* @__PURE__ */ new Set(["tool", "manual", "agent_message_template", "handoff", "end_call", "time_diff"]);
|
|
1584
1622
|
function splitTextWithResourceTags(text2) {
|
|
1585
1623
|
const results = [];
|
|
1586
1624
|
let lastIndex = 0;
|
|
@@ -1743,10 +1781,11 @@ function convertBlock(node, depth = 0) {
|
|
|
1743
1781
|
case "list": {
|
|
1744
1782
|
const list = node;
|
|
1745
1783
|
const items = list.children.map((li) => convertListItem(li, depth + 1));
|
|
1784
|
+
const spread = list.spread ?? false;
|
|
1746
1785
|
if (list.ordered) {
|
|
1747
|
-
return [{ type: "orderedList", start: list.start ?? 1, content: items }];
|
|
1786
|
+
return [{ type: "orderedList", start: list.start ?? 1, spread, content: items }];
|
|
1748
1787
|
}
|
|
1749
|
-
return [{ type: "bulletList", content: items }];
|
|
1788
|
+
return [{ type: "bulletList", spread, content: items }];
|
|
1750
1789
|
}
|
|
1751
1790
|
case "blockquote": {
|
|
1752
1791
|
const bq = node;
|
|
@@ -1755,6 +1794,10 @@ function convertBlock(node, depth = 0) {
|
|
|
1755
1794
|
}
|
|
1756
1795
|
case "thematicBreak":
|
|
1757
1796
|
return [{ type: "horizontalRule" }];
|
|
1797
|
+
case "code": {
|
|
1798
|
+
const codeNode = node;
|
|
1799
|
+
return [{ type: "codeBlock", content: codeNode.value, ...codeNode.lang ? { language: codeNode.lang } : {} }];
|
|
1800
|
+
}
|
|
1758
1801
|
case "jinjaIfBlockMdast": {
|
|
1759
1802
|
const jNode = node;
|
|
1760
1803
|
const branches = jNode.branches.map((b) => ({
|
|
@@ -1795,7 +1838,11 @@ function convertBlock(node, depth = 0) {
|
|
|
1795
1838
|
function convertListItem(node, depth = 0) {
|
|
1796
1839
|
if (depth > MAX_DEPTH2) throw new DepthError(depth);
|
|
1797
1840
|
const content = node.children.flatMap((child) => convertBlock(child, depth + 1));
|
|
1798
|
-
const base = {
|
|
1841
|
+
const base = {
|
|
1842
|
+
type: "listItem",
|
|
1843
|
+
spread: node.spread ?? false,
|
|
1844
|
+
content: content.length > 0 ? content : [{ type: "paragraph", content: [] }]
|
|
1845
|
+
};
|
|
1799
1846
|
if (typeof node.checked === "boolean") {
|
|
1800
1847
|
return { ...base, checked: node.checked };
|
|
1801
1848
|
}
|
|
@@ -1894,31 +1941,39 @@ function blockToMdast(node, depth = 0) {
|
|
|
1894
1941
|
return [{ type: "paragraph", children: node.content.flatMap((c) => inlineToMdast(c, depth + 1)) }];
|
|
1895
1942
|
case "heading":
|
|
1896
1943
|
return [{ type: "heading", depth: node.level, children: node.content.flatMap((c) => inlineToMdast(c, depth + 1)) }];
|
|
1897
|
-
case "bulletList":
|
|
1944
|
+
case "bulletList": {
|
|
1945
|
+
const items = node.content.map((li) => listItemToMdast(li, depth + 1));
|
|
1898
1946
|
return [
|
|
1899
1947
|
{
|
|
1900
1948
|
type: "list",
|
|
1901
1949
|
ordered: false,
|
|
1902
|
-
spread: false,
|
|
1903
|
-
children:
|
|
1950
|
+
spread: node.spread ?? false,
|
|
1951
|
+
children: items
|
|
1904
1952
|
}
|
|
1905
1953
|
];
|
|
1906
|
-
|
|
1954
|
+
}
|
|
1955
|
+
case "orderedList": {
|
|
1956
|
+
const items = node.content.map((li) => listItemToMdast(li, depth + 1));
|
|
1907
1957
|
return [
|
|
1908
1958
|
{
|
|
1909
1959
|
type: "list",
|
|
1910
1960
|
ordered: true,
|
|
1911
1961
|
start: node.start,
|
|
1912
|
-
spread: false,
|
|
1913
|
-
children:
|
|
1962
|
+
spread: node.spread ?? false,
|
|
1963
|
+
children: items
|
|
1914
1964
|
}
|
|
1915
1965
|
];
|
|
1966
|
+
}
|
|
1916
1967
|
case "listItem":
|
|
1917
1968
|
return listItemToMdast(node, depth).children.flatMap((child) => [child]);
|
|
1918
1969
|
case "blockquote":
|
|
1919
1970
|
return [{ type: "blockquote", children: node.content.flatMap((c) => blockToMdast(c, depth + 1)) }];
|
|
1920
1971
|
case "horizontalRule":
|
|
1921
1972
|
return [{ type: "thematicBreak" }];
|
|
1973
|
+
case "codeBlock": {
|
|
1974
|
+
const cb = node;
|
|
1975
|
+
return [{ type: "code", value: cb.content, ...cb.language ? { lang: cb.language } : {} }];
|
|
1976
|
+
}
|
|
1922
1977
|
case "jinjaIfBlock": {
|
|
1923
1978
|
const jNode = node;
|
|
1924
1979
|
const result = [];
|
|
@@ -1942,14 +1997,18 @@ function blockToMdast(node, depth = 0) {
|
|
|
1942
1997
|
}));
|
|
1943
1998
|
return [{ type: "table", children: rows }];
|
|
1944
1999
|
}
|
|
2000
|
+
case "noteBlock":
|
|
2001
|
+
return [];
|
|
1945
2002
|
}
|
|
1946
2003
|
}
|
|
1947
2004
|
function listItemToMdast(node, depth = 0) {
|
|
1948
2005
|
if (depth > MAX_DEPTH2) throw new DepthError(depth);
|
|
2006
|
+
const children = node.content.flatMap((child) => blockToMdast(child, depth + 1));
|
|
2007
|
+
const isSpread = node.spread ?? false;
|
|
1949
2008
|
const result = {
|
|
1950
2009
|
type: "listItem",
|
|
1951
|
-
spread:
|
|
1952
|
-
children
|
|
2010
|
+
spread: isSpread,
|
|
2011
|
+
children
|
|
1953
2012
|
};
|
|
1954
2013
|
if (typeof node.checked === "boolean") {
|
|
1955
2014
|
result.checked = node.checked;
|
|
@@ -1982,12 +2041,20 @@ function textHandler(node, parent, state, info) {
|
|
|
1982
2041
|
state.unsafe = originalUnsafe;
|
|
1983
2042
|
return result;
|
|
1984
2043
|
}
|
|
2044
|
+
function linkHandler(node, parent, state, info) {
|
|
2045
|
+
const childrenText = state.containerPhrasing(node, { ...info, before: "[", after: "]" });
|
|
2046
|
+
const url = node.url ?? "";
|
|
2047
|
+
const title = node.title;
|
|
2048
|
+
const titlePart = title ? ` "${title.replace(/"/g, '\\"')}"` : "";
|
|
2049
|
+
return `[${childrenText}](${url}${titlePart})`;
|
|
2050
|
+
}
|
|
1985
2051
|
function serializeToMarkdown(doc2) {
|
|
1986
2052
|
const mdastTree = toMdast(doc2);
|
|
1987
|
-
const
|
|
2053
|
+
const raw = toMarkdown(mdastTree, {
|
|
1988
2054
|
bullet: "-",
|
|
1989
2055
|
rule: "-",
|
|
1990
2056
|
listItemIndent: "one",
|
|
2057
|
+
incrementListMarker: true,
|
|
1991
2058
|
emphasis: "*",
|
|
1992
2059
|
strong: "*",
|
|
1993
2060
|
resourceLink: true,
|
|
@@ -1999,11 +2066,13 @@ function serializeToMarkdown(doc2) {
|
|
|
1999
2066
|
],
|
|
2000
2067
|
handlers: {
|
|
2001
2068
|
text: textHandler,
|
|
2069
|
+
link: linkHandler,
|
|
2002
2070
|
...resourceTagToMarkdown().handlers,
|
|
2003
2071
|
...jumpPointToMarkdown().handlers
|
|
2004
2072
|
},
|
|
2005
2073
|
extensions: [gfmNoAutolinkToMarkdown()]
|
|
2006
2074
|
});
|
|
2075
|
+
let result = raw.replace(/^(\s*)\\>/gm, "$1>").replace(/(\S) *>/g, (match, pre) => `${pre} >`).replace(/\\\[([^\]]*)\]/g, "\\[$1\\]").replace(/ /g, " ");
|
|
2007
2076
|
return result;
|
|
2008
2077
|
}
|
|
2009
2078
|
|
|
@@ -2087,20 +2156,23 @@ function convertInline2(node) {
|
|
|
2087
2156
|
}
|
|
2088
2157
|
function convertBlockToArray(node) {
|
|
2089
2158
|
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;
|
|
2159
|
+
return [convertJinjaIfBlock(node)];
|
|
2101
2160
|
}
|
|
2102
2161
|
return [convertBlock2(node)];
|
|
2103
2162
|
}
|
|
2163
|
+
function convertJinjaIfBlock(node) {
|
|
2164
|
+
return {
|
|
2165
|
+
type: "jinjaIfBlock",
|
|
2166
|
+
content: node.branches.map((branch) => ({
|
|
2167
|
+
type: "jinjaIfBranch",
|
|
2168
|
+
attrs: {
|
|
2169
|
+
branchType: branch.branchType,
|
|
2170
|
+
condition: branch.condition ?? ""
|
|
2171
|
+
},
|
|
2172
|
+
content: branch.content.length > 0 ? branch.content.flatMap(convertBlockToArray) : [{ type: "paragraph", content: [] }]
|
|
2173
|
+
}))
|
|
2174
|
+
};
|
|
2175
|
+
}
|
|
2104
2176
|
function convertBlock2(node) {
|
|
2105
2177
|
switch (node.type) {
|
|
2106
2178
|
case "paragraph":
|
|
@@ -2142,6 +2214,19 @@ function convertBlock2(node) {
|
|
|
2142
2214
|
};
|
|
2143
2215
|
case "horizontalRule":
|
|
2144
2216
|
return { type: "horizontalRule" };
|
|
2217
|
+
case "codeBlock": {
|
|
2218
|
+
const cb = node;
|
|
2219
|
+
return {
|
|
2220
|
+
type: "codeBlock",
|
|
2221
|
+
attrs: { language: cb.language ?? null },
|
|
2222
|
+
content: cb.content ? [{ type: "text", text: cb.content }] : void 0
|
|
2223
|
+
};
|
|
2224
|
+
}
|
|
2225
|
+
case "noteBlock":
|
|
2226
|
+
return {
|
|
2227
|
+
type: "noteBlock",
|
|
2228
|
+
content: node.content.flatMap(convertBlockToArray)
|
|
2229
|
+
};
|
|
2145
2230
|
case "table":
|
|
2146
2231
|
return {
|
|
2147
2232
|
type: "table",
|
|
@@ -2153,19 +2238,8 @@ function convertBlock2(node) {
|
|
|
2153
2238
|
}))
|
|
2154
2239
|
}))
|
|
2155
2240
|
};
|
|
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
|
-
}
|
|
2241
|
+
case "jinjaIfBlock":
|
|
2242
|
+
return convertJinjaIfBlock(node);
|
|
2169
2243
|
default:
|
|
2170
2244
|
return assertNever(node);
|
|
2171
2245
|
}
|
|
@@ -2197,16 +2271,30 @@ function pmDocToAST(pmDoc) {
|
|
|
2197
2271
|
return fromProseMirrorJSON(json);
|
|
2198
2272
|
}
|
|
2199
2273
|
function useEditorView(config) {
|
|
2200
|
-
const viewRef = useRef(null);
|
|
2201
2274
|
const viewInstanceRef = useRef(null);
|
|
2275
|
+
const containerRef = useRef(null);
|
|
2202
2276
|
const [, forceUpdate] = useState(0);
|
|
2203
2277
|
const configRef = useRef(config);
|
|
2204
2278
|
configRef.current = config;
|
|
2205
2279
|
useEffect(() => {
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2280
|
+
return () => {
|
|
2281
|
+
viewInstanceRef.current?.destroy();
|
|
2282
|
+
viewInstanceRef.current = null;
|
|
2283
|
+
};
|
|
2284
|
+
}, []);
|
|
2285
|
+
const viewRef = useCallback((container) => {
|
|
2286
|
+
if (container === containerRef.current) return;
|
|
2287
|
+
if (viewInstanceRef.current) {
|
|
2288
|
+
viewInstanceRef.current.destroy();
|
|
2289
|
+
viewInstanceRef.current = null;
|
|
2290
|
+
}
|
|
2291
|
+
containerRef.current = container;
|
|
2292
|
+
if (!container) {
|
|
2293
|
+
forceUpdate((n) => n + 1);
|
|
2294
|
+
return;
|
|
2295
|
+
}
|
|
2296
|
+
const { pmPlugins, nodeViews } = createPluginArray(configRef.current.plugins ?? []);
|
|
2297
|
+
const state = docToState(configRef.current.content, pmPlugins);
|
|
2210
2298
|
const view = new EditorView(container, {
|
|
2211
2299
|
state,
|
|
2212
2300
|
nodeViews,
|
|
@@ -2223,10 +2311,6 @@ function useEditorView(config) {
|
|
|
2223
2311
|
});
|
|
2224
2312
|
viewInstanceRef.current = view;
|
|
2225
2313
|
forceUpdate((n) => n + 1);
|
|
2226
|
-
return () => {
|
|
2227
|
-
view.destroy();
|
|
2228
|
-
viewInstanceRef.current = null;
|
|
2229
|
-
};
|
|
2230
2314
|
}, []);
|
|
2231
2315
|
const getAST = useCallback(() => {
|
|
2232
2316
|
const view = viewInstanceRef.current;
|
|
@@ -2244,6 +2328,7 @@ function useEditorView(config) {
|
|
|
2244
2328
|
const pmJSON = toProseMirrorJSON(doc2);
|
|
2245
2329
|
const pmDoc = PMNode.fromJSON(actionbookSchema, pmJSON);
|
|
2246
2330
|
const tr = view.state.tr.replaceWith(0, view.state.doc.content.size, pmDoc.content);
|
|
2331
|
+
tr.setMeta("addToHistory", false);
|
|
2247
2332
|
view.dispatch(tr);
|
|
2248
2333
|
}, []);
|
|
2249
2334
|
const focus = useCallback(() => {
|
|
@@ -2253,9 +2338,11 @@ function useEditorView(config) {
|
|
|
2253
2338
|
viewInstanceRef.current?.destroy();
|
|
2254
2339
|
viewInstanceRef.current = null;
|
|
2255
2340
|
}, []);
|
|
2341
|
+
const getView = useCallback(() => viewInstanceRef.current, []);
|
|
2256
2342
|
return {
|
|
2257
2343
|
viewRef,
|
|
2258
2344
|
view: viewInstanceRef.current,
|
|
2345
|
+
getView,
|
|
2259
2346
|
getAST,
|
|
2260
2347
|
getMarkdown,
|
|
2261
2348
|
setContent,
|
|
@@ -2264,20 +2351,16 @@ function useEditorView(config) {
|
|
|
2264
2351
|
};
|
|
2265
2352
|
}
|
|
2266
2353
|
|
|
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
2354
|
// src/ui/plugin/inputRulesPlugin.ts
|
|
2277
|
-
import { InputRule, wrappingInputRule } from "prosemirror-inputrules";
|
|
2355
|
+
import { InputRule, textblockTypeInputRule, wrappingInputRule } from "prosemirror-inputrules";
|
|
2356
|
+
import { TextSelection } from "prosemirror-state";
|
|
2357
|
+
var HEADING_RE = /^(#{1,6})\s$/;
|
|
2358
|
+
var BLOCKQUOTE_RE = /^\s*>\s$/;
|
|
2359
|
+
var CODE_BLOCK_RE = /^```([a-zA-Z0-9]*)$/;
|
|
2360
|
+
var HR_RE = /^([-*_])\1{2,}$/;
|
|
2278
2361
|
var BULLET_LIST_RE = /^\s*([-*])\s$/;
|
|
2279
2362
|
var ORDERED_LIST_RE = /^(\d+)\.\s$/;
|
|
2280
|
-
var JUMP_POINT_RE2 = /\^([A-Za-z_]
|
|
2363
|
+
var JUMP_POINT_RE2 = /\^([A-Za-z_]+)\^$/;
|
|
2281
2364
|
var BOLD_STAR_RE = /(?:^|[^*])\*\*([^*]+)\*\*$/;
|
|
2282
2365
|
var BOLD_UNDER_RE = /(?:^|[^_])__([^_]+)__$/;
|
|
2283
2366
|
var ITALIC_STAR_RE = /(?:^|[^*])\*([^*]+)\*$/;
|
|
@@ -2288,11 +2371,14 @@ function markInputRule(pattern, markType, markerLen) {
|
|
|
2288
2371
|
return new InputRule(pattern, (state, match, start, end) => {
|
|
2289
2372
|
const textContent2 = match[1];
|
|
2290
2373
|
const fullMatch = match[0];
|
|
2291
|
-
const
|
|
2374
|
+
const markedLength = markerLen * 2 + textContent2.length;
|
|
2375
|
+
const prefixLen = fullMatch.length - markedLength;
|
|
2376
|
+
const deleteFrom = start + prefixLen;
|
|
2292
2377
|
const tr = state.tr;
|
|
2293
|
-
tr.delete(
|
|
2378
|
+
tr.delete(deleteFrom, end);
|
|
2294
2379
|
const textNode = state.schema.text(textContent2, [markType.create()]);
|
|
2295
|
-
tr.insert(
|
|
2380
|
+
tr.insert(deleteFrom, textNode);
|
|
2381
|
+
tr.removeStoredMark(markType);
|
|
2296
2382
|
return tr;
|
|
2297
2383
|
});
|
|
2298
2384
|
}
|
|
@@ -2301,12 +2387,41 @@ function createInputRulesPlugin() {
|
|
|
2301
2387
|
name: "inputRules",
|
|
2302
2388
|
inputRules: () => {
|
|
2303
2389
|
const rules = [];
|
|
2304
|
-
rules.push(wrappingInputRule(BULLET_LIST_RE, actionbookSchema.nodes.bulletList));
|
|
2305
2390
|
rules.push(
|
|
2306
|
-
|
|
2307
|
-
|
|
2391
|
+
textblockTypeInputRule(HEADING_RE, actionbookSchema.nodes.heading, (match) => ({
|
|
2392
|
+
level: match[1].length
|
|
2308
2393
|
}))
|
|
2309
2394
|
);
|
|
2395
|
+
rules.push(wrappingInputRule(BLOCKQUOTE_RE, actionbookSchema.nodes.blockquote));
|
|
2396
|
+
rules.push(
|
|
2397
|
+
new InputRule(CODE_BLOCK_RE, (state, match, start, end) => {
|
|
2398
|
+
const language = match[1] || null;
|
|
2399
|
+
const $start = state.doc.resolve(start);
|
|
2400
|
+
const blockStart = $start.before($start.depth);
|
|
2401
|
+
const blockEnd = $start.after($start.depth);
|
|
2402
|
+
const tr = state.tr;
|
|
2403
|
+
tr.replaceWith(
|
|
2404
|
+
blockStart,
|
|
2405
|
+
blockEnd,
|
|
2406
|
+
actionbookSchema.nodes.codeBlock.create({ language })
|
|
2407
|
+
);
|
|
2408
|
+
return tr;
|
|
2409
|
+
})
|
|
2410
|
+
);
|
|
2411
|
+
rules.push(
|
|
2412
|
+
new InputRule(HR_RE, (state, _match, start, end) => {
|
|
2413
|
+
const { horizontalRule: hrType, paragraph: pType } = actionbookSchema.nodes;
|
|
2414
|
+
const $start = state.doc.resolve(start);
|
|
2415
|
+
const blockStart = $start.before($start.depth);
|
|
2416
|
+
const blockEnd = $start.after($start.depth);
|
|
2417
|
+
const tr = state.tr;
|
|
2418
|
+
tr.replaceWith(blockStart, blockEnd, [hrType.create(), pType.create()]);
|
|
2419
|
+
tr.setSelection(
|
|
2420
|
+
TextSelection.near(tr.doc.resolve(blockStart + hrType.createAndFill().nodeSize + 1))
|
|
2421
|
+
);
|
|
2422
|
+
return tr;
|
|
2423
|
+
})
|
|
2424
|
+
);
|
|
2310
2425
|
rules.push(
|
|
2311
2426
|
new InputRule(/^\s*[-*]\s\[([ xX])\]\s$/, (state, match, start, end) => {
|
|
2312
2427
|
const checked = match[1] !== " ";
|
|
@@ -2316,6 +2431,12 @@ function createInputRulesPlugin() {
|
|
|
2316
2431
|
return state.tr.delete(start, end).insert(start, list);
|
|
2317
2432
|
})
|
|
2318
2433
|
);
|
|
2434
|
+
rules.push(wrappingInputRule(BULLET_LIST_RE, actionbookSchema.nodes.bulletList));
|
|
2435
|
+
rules.push(
|
|
2436
|
+
wrappingInputRule(ORDERED_LIST_RE, actionbookSchema.nodes.orderedList, (match) => ({
|
|
2437
|
+
start: +match[1]
|
|
2438
|
+
}))
|
|
2439
|
+
);
|
|
2319
2440
|
const jumpPointType = actionbookSchema.nodes.jumpPoint;
|
|
2320
2441
|
rules.push(
|
|
2321
2442
|
new InputRule(JUMP_POINT_RE2, (state, match, start, end) => {
|
|
@@ -2342,24 +2463,85 @@ function createInputRulesPlugin() {
|
|
|
2342
2463
|
};
|
|
2343
2464
|
}
|
|
2344
2465
|
|
|
2466
|
+
// src/ui/plugin/historyPlugin.ts
|
|
2467
|
+
import { history, undo, redo } from "prosemirror-history";
|
|
2468
|
+
import { keymap as keymap2 } from "prosemirror-keymap";
|
|
2469
|
+
function createHistoryPlugin() {
|
|
2470
|
+
return {
|
|
2471
|
+
name: "history",
|
|
2472
|
+
plugins: () => [
|
|
2473
|
+
history(),
|
|
2474
|
+
keymap2({ "Mod-z": undo, "Mod-Shift-z": redo, "Mod-y": redo })
|
|
2475
|
+
]
|
|
2476
|
+
};
|
|
2477
|
+
}
|
|
2478
|
+
|
|
2345
2479
|
// src/ui/plugin/keymapPlugin.ts
|
|
2346
|
-
import { chainCommands, newlineInCode, createParagraphNear, liftEmptyBlock, splitBlock, toggleMark } from "prosemirror-commands";
|
|
2480
|
+
import { baseKeymap, chainCommands, newlineInCode, createParagraphNear, liftEmptyBlock, splitBlock, toggleMark, setBlockType, joinBackward } from "prosemirror-commands";
|
|
2481
|
+
import { keymap as keymap3 } from "prosemirror-keymap";
|
|
2347
2482
|
import { liftListItem, sinkListItem, splitListItem, wrapInList } from "prosemirror-schema-list";
|
|
2348
2483
|
var TAB_CHAR = " ";
|
|
2349
|
-
var { listItem, bulletList, orderedList, hardBreak } = actionbookSchema.nodes;
|
|
2484
|
+
var { listItem, bulletList, orderedList, hardBreak, heading, paragraph, horizontalRule, blockquote } = actionbookSchema.nodes;
|
|
2350
2485
|
var { bold: boldMark, italic: italicMark, underline: underlineMark, strikethrough: strikethroughMark, code: codeMark } = actionbookSchema.marks;
|
|
2351
2486
|
function cursorDirectlyInListItem(state) {
|
|
2352
2487
|
const { $from } = state.selection;
|
|
2353
2488
|
return $from.depth >= 2 && $from.node($from.depth - 1).type === listItem;
|
|
2354
2489
|
}
|
|
2355
|
-
var
|
|
2490
|
+
var backspaceAfterList = (state, dispatch) => {
|
|
2491
|
+
const { $from } = state.selection;
|
|
2492
|
+
if (!state.selection.empty) return false;
|
|
2493
|
+
if ($from.parentOffset !== 0) return false;
|
|
2494
|
+
if ($from.parent.type !== paragraph) return false;
|
|
2495
|
+
if ($from.parent.content.size !== 0) return false;
|
|
2496
|
+
const parentDepth = $from.depth - 1;
|
|
2497
|
+
if (parentDepth < 0) return false;
|
|
2498
|
+
const indexInParent = $from.index(parentDepth);
|
|
2499
|
+
if (indexInParent === 0) return false;
|
|
2500
|
+
const prevNode = $from.node(parentDepth).child(indexInParent - 1);
|
|
2501
|
+
const isList = prevNode.type === bulletList || prevNode.type === orderedList;
|
|
2502
|
+
if (!isList) return false;
|
|
2503
|
+
if (dispatch) {
|
|
2504
|
+
const from = $from.before($from.depth);
|
|
2505
|
+
const to = $from.after($from.depth);
|
|
2506
|
+
const tr = state.tr.delete(from, to);
|
|
2507
|
+
dispatch(tr.scrollIntoView());
|
|
2508
|
+
}
|
|
2509
|
+
return true;
|
|
2510
|
+
};
|
|
2511
|
+
var backspaceAfterLeafBlock = (state, dispatch) => {
|
|
2356
2512
|
const { $from } = state.selection;
|
|
2357
2513
|
if (!state.selection.empty) return false;
|
|
2358
2514
|
if ($from.parentOffset !== 0) return false;
|
|
2359
|
-
if (
|
|
2360
|
-
if ($from.
|
|
2361
|
-
|
|
2515
|
+
if ($from.parent.type !== paragraph) return false;
|
|
2516
|
+
if ($from.parent.content.size !== 0) return false;
|
|
2517
|
+
const parentDepth = $from.depth - 1;
|
|
2518
|
+
if (parentDepth < 0) return false;
|
|
2519
|
+
const indexInParent = $from.index(parentDepth);
|
|
2520
|
+
if (indexInParent === 0) return false;
|
|
2521
|
+
const prevNode = $from.node(parentDepth).child(indexInParent - 1);
|
|
2522
|
+
if (prevNode.type !== horizontalRule) return false;
|
|
2523
|
+
if (dispatch) {
|
|
2524
|
+
const hrPos = $from.posAtIndex(indexInParent - 1, parentDepth);
|
|
2525
|
+
dispatch(state.tr.delete(hrPos, hrPos + prevNode.nodeSize).scrollIntoView());
|
|
2526
|
+
}
|
|
2527
|
+
return true;
|
|
2362
2528
|
};
|
|
2529
|
+
var backspaceCommand = chainCommands(
|
|
2530
|
+
backspaceAfterList,
|
|
2531
|
+
backspaceAfterLeafBlock,
|
|
2532
|
+
(state, dispatch) => {
|
|
2533
|
+
const { $from } = state.selection;
|
|
2534
|
+
if (!state.selection.empty) return false;
|
|
2535
|
+
if ($from.parentOffset !== 0) return false;
|
|
2536
|
+
if ($from.parent.type === heading) {
|
|
2537
|
+
return setBlockType(paragraph)(state, dispatch);
|
|
2538
|
+
}
|
|
2539
|
+
if (!cursorDirectlyInListItem(state)) return false;
|
|
2540
|
+
if ($from.index($from.depth - 1) !== 0) return false;
|
|
2541
|
+
return liftListItem(listItem)(state, dispatch);
|
|
2542
|
+
},
|
|
2543
|
+
joinBackward
|
|
2544
|
+
);
|
|
2363
2545
|
var tabCommand = (state, dispatch) => {
|
|
2364
2546
|
const { $from } = state.selection;
|
|
2365
2547
|
if (cursorDirectlyInListItem(state) && $from.parentOffset === 0) {
|
|
@@ -2412,12 +2594,13 @@ function createKeymapPlugin() {
|
|
|
2412
2594
|
"Mod-e": toggleMark(codeMark),
|
|
2413
2595
|
"Mod-Shift-7": wrapInList(bulletList),
|
|
2414
2596
|
"Mod-Shift-8": wrapInList(orderedList)
|
|
2415
|
-
})
|
|
2597
|
+
}),
|
|
2598
|
+
plugins: () => [keymap3(baseKeymap)]
|
|
2416
2599
|
};
|
|
2417
2600
|
}
|
|
2418
2601
|
|
|
2419
2602
|
// src/ui/plugin/markdownClipboard.ts
|
|
2420
|
-
import { Fragment, Slice } from "prosemirror-model";
|
|
2603
|
+
import { DOMParser as ProseMirrorDOMParser, Fragment, Slice } from "prosemirror-model";
|
|
2421
2604
|
import { Plugin, PluginKey } from "prosemirror-state";
|
|
2422
2605
|
|
|
2423
2606
|
// src/ast/traverse.ts
|
|
@@ -2433,6 +2616,7 @@ function getChildren(node) {
|
|
|
2433
2616
|
case "doc":
|
|
2434
2617
|
case "blockquote":
|
|
2435
2618
|
case "listItem":
|
|
2619
|
+
case "noteBlock":
|
|
2436
2620
|
return node.content;
|
|
2437
2621
|
case "paragraph":
|
|
2438
2622
|
case "heading":
|
|
@@ -3904,6 +4088,23 @@ var gfmNoAutolinkFromMarkdown = () => [
|
|
|
3904
4088
|
gfmTaskListItemFromMarkdown()
|
|
3905
4089
|
];
|
|
3906
4090
|
var MAX_DEPTH5 = 128;
|
|
4091
|
+
var BRACKET_LINK_RE = /\[([^\]]+)\]\(([^)]*\s[^)]*)\)/g;
|
|
4092
|
+
function splitTextWithBracketLinks(value) {
|
|
4093
|
+
const results = [];
|
|
4094
|
+
let lastIndex = 0;
|
|
4095
|
+
for (const m of value.matchAll(BRACKET_LINK_RE)) {
|
|
4096
|
+
const idx = m.index;
|
|
4097
|
+
if (idx > lastIndex) results.push({ type: "text", value: value.slice(lastIndex, idx) });
|
|
4098
|
+
results.push({
|
|
4099
|
+
type: "link",
|
|
4100
|
+
url: m[2],
|
|
4101
|
+
children: [{ type: "text", value: m[1] }]
|
|
4102
|
+
});
|
|
4103
|
+
lastIndex = idx + m[0].length;
|
|
4104
|
+
}
|
|
4105
|
+
if (lastIndex < value.length) results.push({ type: "text", value: value.slice(lastIndex) });
|
|
4106
|
+
return results;
|
|
4107
|
+
}
|
|
3907
4108
|
function combinedTokensFromMarkdown(node, depth = 0) {
|
|
3908
4109
|
if (depth > MAX_DEPTH5) return;
|
|
3909
4110
|
if (!node.children) return;
|
|
@@ -3915,13 +4116,20 @@ function combinedTokensFromMarkdown(node, depth = 0) {
|
|
|
3915
4116
|
for (const child of node.children) {
|
|
3916
4117
|
const c = child;
|
|
3917
4118
|
if (c.type === "text") {
|
|
3918
|
-
const
|
|
3919
|
-
for (const
|
|
3920
|
-
if (
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
}
|
|
3924
|
-
|
|
4119
|
+
const afterLinks = splitTextWithBracketLinks(child.value);
|
|
4120
|
+
for (const linkPart of afterLinks) {
|
|
4121
|
+
if (linkPart.type !== "text") {
|
|
4122
|
+
newChildren.push(linkPart);
|
|
4123
|
+
continue;
|
|
4124
|
+
}
|
|
4125
|
+
const afterResourceTags = splitTextWithResourceTags(linkPart.value);
|
|
4126
|
+
for (const part of afterResourceTags) {
|
|
4127
|
+
if (part.type === "text") {
|
|
4128
|
+
const afterJumpPoints = splitTextWithJumpPoints(part.value);
|
|
4129
|
+
newChildren.push(...afterJumpPoints);
|
|
4130
|
+
} else {
|
|
4131
|
+
newChildren.push(part);
|
|
4132
|
+
}
|
|
3925
4133
|
}
|
|
3926
4134
|
}
|
|
3927
4135
|
} else {
|
|
@@ -4128,53 +4336,455 @@ function analyzeJinjaBlocks(doc2) {
|
|
|
4128
4336
|
});
|
|
4129
4337
|
}
|
|
4130
4338
|
|
|
4131
|
-
// src/
|
|
4132
|
-
var
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4339
|
+
// src/jinja/conditionHighlighter.ts
|
|
4340
|
+
var KEYWORDS = {
|
|
4341
|
+
and: "AND",
|
|
4342
|
+
or: "OR",
|
|
4343
|
+
not: "NOT",
|
|
4344
|
+
in: "IN",
|
|
4345
|
+
is: "IS",
|
|
4346
|
+
True: "BOOL",
|
|
4347
|
+
False: "BOOL",
|
|
4348
|
+
true: "BOOL",
|
|
4349
|
+
false: "BOOL",
|
|
4350
|
+
None: "NONE",
|
|
4351
|
+
null: "NONE"
|
|
4352
|
+
};
|
|
4353
|
+
var CATEGORY_BY_TYPE = {
|
|
4354
|
+
STRING: "value",
|
|
4355
|
+
NUMBER: "value",
|
|
4356
|
+
BOOL: "value",
|
|
4357
|
+
NONE: "value",
|
|
4358
|
+
IDENT: "variable",
|
|
4359
|
+
AND: "operator",
|
|
4360
|
+
OR: "operator",
|
|
4361
|
+
NOT: "operator",
|
|
4362
|
+
IN: "operator",
|
|
4363
|
+
IS: "operator",
|
|
4364
|
+
EQ: "operator",
|
|
4365
|
+
NEQ: "operator",
|
|
4366
|
+
LT: "operator",
|
|
4367
|
+
GT: "operator",
|
|
4368
|
+
LTE: "operator",
|
|
4369
|
+
GTE: "operator",
|
|
4370
|
+
LPAREN: "punctuation",
|
|
4371
|
+
RPAREN: "punctuation"
|
|
4372
|
+
};
|
|
4373
|
+
var NEGATIVE_NUMBER_PRECEDERS = /* @__PURE__ */ new Set([
|
|
4374
|
+
"AND",
|
|
4375
|
+
"OR",
|
|
4376
|
+
"NOT",
|
|
4377
|
+
"IN",
|
|
4378
|
+
"IS",
|
|
4379
|
+
"EQ",
|
|
4380
|
+
"NEQ",
|
|
4381
|
+
"LT",
|
|
4382
|
+
"GT",
|
|
4383
|
+
"LTE",
|
|
4384
|
+
"GTE",
|
|
4385
|
+
"LPAREN"
|
|
4386
|
+
]);
|
|
4387
|
+
function canStartNegativeNumber(tokens) {
|
|
4388
|
+
if (tokens.length === 0) {
|
|
4389
|
+
return true;
|
|
4152
4390
|
}
|
|
4391
|
+
const previous = tokens[tokens.length - 1];
|
|
4392
|
+
return NEGATIVE_NUMBER_PRECEDERS.has(previous.type);
|
|
4153
4393
|
}
|
|
4154
|
-
function
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
}
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4394
|
+
function finalizeTokens(input, rawTokens) {
|
|
4395
|
+
const highlighted = [];
|
|
4396
|
+
for (let i = 0; i < rawTokens.length; i++) {
|
|
4397
|
+
const token = rawTokens[i];
|
|
4398
|
+
const next = rawTokens[i + 1];
|
|
4399
|
+
if (token.type === "IS" && next?.type === "NOT") {
|
|
4400
|
+
highlighted.push({
|
|
4401
|
+
text: input.slice(token.start, next.end),
|
|
4402
|
+
start: token.start,
|
|
4403
|
+
end: next.end,
|
|
4404
|
+
category: "operator"
|
|
4405
|
+
});
|
|
4406
|
+
i++;
|
|
4407
|
+
continue;
|
|
4408
|
+
}
|
|
4409
|
+
highlighted.push({
|
|
4410
|
+
text: token.text,
|
|
4411
|
+
start: token.start,
|
|
4412
|
+
end: token.end,
|
|
4413
|
+
category: CATEGORY_BY_TYPE[token.type]
|
|
4414
|
+
});
|
|
4415
|
+
}
|
|
4416
|
+
return highlighted;
|
|
4417
|
+
}
|
|
4418
|
+
function tokenizeCondition(input) {
|
|
4419
|
+
const rawTokens = [];
|
|
4420
|
+
let i = 0;
|
|
4421
|
+
while (i < input.length) {
|
|
4422
|
+
const char = input[i];
|
|
4423
|
+
if (/\s/.test(char)) {
|
|
4424
|
+
i++;
|
|
4425
|
+
continue;
|
|
4426
|
+
}
|
|
4427
|
+
if (char === '"' || char === "'") {
|
|
4428
|
+
const start = i;
|
|
4429
|
+
const quote = char;
|
|
4430
|
+
i++;
|
|
4431
|
+
while (i < input.length) {
|
|
4432
|
+
if (input[i] === "\\" && i + 1 < input.length) {
|
|
4433
|
+
i += 2;
|
|
4434
|
+
continue;
|
|
4435
|
+
}
|
|
4436
|
+
if (input[i] === quote) {
|
|
4437
|
+
i++;
|
|
4438
|
+
rawTokens.push({
|
|
4439
|
+
type: "STRING",
|
|
4440
|
+
text: input.slice(start, i),
|
|
4441
|
+
start,
|
|
4442
|
+
end: i
|
|
4443
|
+
});
|
|
4444
|
+
break;
|
|
4445
|
+
}
|
|
4446
|
+
i++;
|
|
4447
|
+
}
|
|
4448
|
+
if (rawTokens[rawTokens.length - 1]?.start !== start) {
|
|
4449
|
+
return finalizeTokens(input, rawTokens);
|
|
4450
|
+
}
|
|
4451
|
+
continue;
|
|
4452
|
+
}
|
|
4453
|
+
if (/[0-9]/.test(char) || char === "-" && i + 1 < input.length && /[0-9]/.test(input[i + 1]) && canStartNegativeNumber(rawTokens)) {
|
|
4454
|
+
const start = i;
|
|
4455
|
+
if (input[i] === "-") {
|
|
4456
|
+
i++;
|
|
4457
|
+
}
|
|
4458
|
+
while (i < input.length && /[0-9]/.test(input[i])) {
|
|
4459
|
+
i++;
|
|
4460
|
+
}
|
|
4461
|
+
if (i < input.length && input[i] === ".") {
|
|
4462
|
+
i++;
|
|
4463
|
+
while (i < input.length && /[0-9]/.test(input[i])) {
|
|
4464
|
+
i++;
|
|
4465
|
+
}
|
|
4466
|
+
}
|
|
4467
|
+
rawTokens.push({
|
|
4468
|
+
type: "NUMBER",
|
|
4469
|
+
text: input.slice(start, i),
|
|
4470
|
+
start,
|
|
4471
|
+
end: i
|
|
4472
|
+
});
|
|
4473
|
+
continue;
|
|
4474
|
+
}
|
|
4475
|
+
if (/[a-zA-Z_]/.test(char)) {
|
|
4476
|
+
const start = i;
|
|
4477
|
+
i++;
|
|
4478
|
+
while (i < input.length && /[a-zA-Z0-9_.]/.test(input[i])) {
|
|
4479
|
+
i++;
|
|
4480
|
+
}
|
|
4481
|
+
const text2 = input.slice(start, i);
|
|
4482
|
+
rawTokens.push({
|
|
4483
|
+
type: KEYWORDS[text2] ?? "IDENT",
|
|
4484
|
+
text: text2,
|
|
4485
|
+
start,
|
|
4486
|
+
end: i
|
|
4487
|
+
});
|
|
4488
|
+
continue;
|
|
4489
|
+
}
|
|
4490
|
+
if (i + 1 < input.length) {
|
|
4491
|
+
const twoChar = input.slice(i, i + 2);
|
|
4492
|
+
if (twoChar === "==") {
|
|
4493
|
+
rawTokens.push({ type: "EQ", text: twoChar, start: i, end: i + 2 });
|
|
4494
|
+
i += 2;
|
|
4495
|
+
continue;
|
|
4496
|
+
}
|
|
4497
|
+
if (twoChar === "!=") {
|
|
4498
|
+
rawTokens.push({ type: "NEQ", text: twoChar, start: i, end: i + 2 });
|
|
4499
|
+
i += 2;
|
|
4500
|
+
continue;
|
|
4501
|
+
}
|
|
4502
|
+
if (twoChar === "<=") {
|
|
4503
|
+
rawTokens.push({ type: "LTE", text: twoChar, start: i, end: i + 2 });
|
|
4504
|
+
i += 2;
|
|
4505
|
+
continue;
|
|
4506
|
+
}
|
|
4507
|
+
if (twoChar === ">=") {
|
|
4508
|
+
rawTokens.push({ type: "GTE", text: twoChar, start: i, end: i + 2 });
|
|
4509
|
+
i += 2;
|
|
4510
|
+
continue;
|
|
4511
|
+
}
|
|
4512
|
+
}
|
|
4513
|
+
if (char === "<") {
|
|
4514
|
+
rawTokens.push({ type: "LT", text: char, start: i, end: i + 1 });
|
|
4515
|
+
i++;
|
|
4516
|
+
continue;
|
|
4517
|
+
}
|
|
4518
|
+
if (char === ">") {
|
|
4519
|
+
rawTokens.push({ type: "GT", text: char, start: i, end: i + 1 });
|
|
4520
|
+
i++;
|
|
4521
|
+
continue;
|
|
4522
|
+
}
|
|
4523
|
+
if (char === "(") {
|
|
4524
|
+
rawTokens.push({ type: "LPAREN", text: char, start: i, end: i + 1 });
|
|
4525
|
+
i++;
|
|
4526
|
+
continue;
|
|
4527
|
+
}
|
|
4528
|
+
if (char === ")") {
|
|
4529
|
+
rawTokens.push({ type: "RPAREN", text: char, start: i, end: i + 1 });
|
|
4530
|
+
i++;
|
|
4531
|
+
continue;
|
|
4532
|
+
}
|
|
4533
|
+
return finalizeTokens(input, rawTokens);
|
|
4534
|
+
}
|
|
4535
|
+
return finalizeTokens(input, rawTokens);
|
|
4536
|
+
}
|
|
4537
|
+
|
|
4538
|
+
// src/tree/documentTree.ts
|
|
4539
|
+
var MAX_DEPTH6 = 128;
|
|
4540
|
+
function extractInlineItems(content, blockIndex) {
|
|
4541
|
+
const items = [];
|
|
4542
|
+
for (const node of content) {
|
|
4543
|
+
if (node.type === "jumpPoint") {
|
|
4544
|
+
items.push({
|
|
4545
|
+
type: "jumpPoint",
|
|
4546
|
+
label: node.id,
|
|
4547
|
+
blockIndex,
|
|
4548
|
+
children: []
|
|
4549
|
+
});
|
|
4550
|
+
} else if (node.type === "resourceTag") {
|
|
4551
|
+
const isEndAction = node.tagType === "handoff";
|
|
4552
|
+
items.push({
|
|
4553
|
+
type: isEndAction ? "endAction" : "resourceTag",
|
|
4554
|
+
label: isEndAction ? `End ${node.text}` : node.text,
|
|
4555
|
+
blockIndex,
|
|
4556
|
+
children: [],
|
|
4557
|
+
meta: { tagType: node.tagType, resourceId: node.resourceId }
|
|
4558
|
+
});
|
|
4559
|
+
}
|
|
4560
|
+
}
|
|
4561
|
+
return items;
|
|
4562
|
+
}
|
|
4563
|
+
function extractBlockItems(blocks, startIndex, depth) {
|
|
4564
|
+
if (depth > MAX_DEPTH6) return [];
|
|
4565
|
+
const items = [];
|
|
4566
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
4567
|
+
const block = blocks[i];
|
|
4568
|
+
const blockIndex = startIndex + i;
|
|
4569
|
+
switch (block.type) {
|
|
4570
|
+
case "heading": {
|
|
4571
|
+
const label = textContent(block) || `Heading ${block.level}`;
|
|
4572
|
+
const inlineItems = extractInlineItems(block.content, blockIndex);
|
|
4573
|
+
items.push({
|
|
4574
|
+
type: "heading",
|
|
4575
|
+
label,
|
|
4576
|
+
blockIndex,
|
|
4577
|
+
children: inlineItems,
|
|
4578
|
+
meta: { level: block.level }
|
|
4579
|
+
});
|
|
4580
|
+
break;
|
|
4581
|
+
}
|
|
4582
|
+
case "paragraph": {
|
|
4583
|
+
const inlineItems = extractInlineItems(block.content, blockIndex);
|
|
4584
|
+
items.push(...inlineItems);
|
|
4585
|
+
break;
|
|
4586
|
+
}
|
|
4587
|
+
case "jinjaIfBlock": {
|
|
4588
|
+
const branches = block.branches.map((branch) => {
|
|
4589
|
+
const branchLabel = branch.branchType === "else" ? "ELSE" : `${branch.branchType.toUpperCase()} ${branch.condition || ""}`.trim();
|
|
4590
|
+
const branchChildren = extractBlockItems(branch.content, blockIndex, depth + 1);
|
|
4591
|
+
return {
|
|
4592
|
+
type: "jinjaBranch",
|
|
4593
|
+
label: branchLabel,
|
|
4594
|
+
blockIndex,
|
|
4595
|
+
children: branchChildren
|
|
4596
|
+
};
|
|
4597
|
+
});
|
|
4598
|
+
items.push({
|
|
4599
|
+
type: "jinjaIf",
|
|
4600
|
+
label: "Jinja if",
|
|
4601
|
+
blockIndex,
|
|
4602
|
+
children: branches
|
|
4603
|
+
});
|
|
4604
|
+
break;
|
|
4605
|
+
}
|
|
4606
|
+
case "noteBlock": {
|
|
4607
|
+
const noteContent = textContent(block);
|
|
4608
|
+
items.push({
|
|
4609
|
+
type: "noteBlock",
|
|
4610
|
+
label: noteContent ? `Note: ${noteContent.slice(0, 30)}` : "Note",
|
|
4611
|
+
blockIndex,
|
|
4612
|
+
children: []
|
|
4613
|
+
});
|
|
4614
|
+
break;
|
|
4615
|
+
}
|
|
4616
|
+
case "bulletList":
|
|
4617
|
+
case "orderedList": {
|
|
4618
|
+
for (const li of block.content) {
|
|
4619
|
+
const childItems = extractBlockItems(li.content, blockIndex, depth + 1);
|
|
4620
|
+
items.push(...childItems);
|
|
4621
|
+
}
|
|
4622
|
+
break;
|
|
4623
|
+
}
|
|
4624
|
+
case "blockquote": {
|
|
4625
|
+
const childItems = extractBlockItems(block.content, blockIndex, depth + 1);
|
|
4626
|
+
items.push(...childItems);
|
|
4627
|
+
break;
|
|
4628
|
+
}
|
|
4629
|
+
default:
|
|
4630
|
+
break;
|
|
4631
|
+
}
|
|
4632
|
+
}
|
|
4633
|
+
return items;
|
|
4634
|
+
}
|
|
4635
|
+
function buildDocumentTree(doc2) {
|
|
4636
|
+
const items = extractBlockItems(doc2.content, 0, 0);
|
|
4637
|
+
try {
|
|
4638
|
+
const structures = analyzeJinjaBlocks(doc2);
|
|
4639
|
+
if (structures.length > 0) {
|
|
4640
|
+
const hasStructuredJinja = items.some((n) => n.type === "jinjaIf");
|
|
4641
|
+
if (!hasStructuredJinja) {
|
|
4642
|
+
for (const s of structures) {
|
|
4643
|
+
const branches = s.branches.map((b) => ({
|
|
4644
|
+
type: "jinjaBranch",
|
|
4645
|
+
label: b.type === "else" ? "ELSE" : `${b.type.toUpperCase()} ${b.condition || ""}`.trim(),
|
|
4646
|
+
blockIndex: b.tagBlockIndex,
|
|
4647
|
+
children: []
|
|
4648
|
+
}));
|
|
4649
|
+
const jinjaNode = {
|
|
4650
|
+
type: "jinjaIf",
|
|
4651
|
+
label: "Jinja if",
|
|
4652
|
+
blockIndex: s.ifTagBlockIndex,
|
|
4653
|
+
children: branches
|
|
4654
|
+
};
|
|
4655
|
+
let inserted = false;
|
|
4656
|
+
for (let i = 0; i < items.length; i++) {
|
|
4657
|
+
if (items[i].blockIndex > s.ifTagBlockIndex) {
|
|
4658
|
+
items.splice(i, 0, jinjaNode);
|
|
4659
|
+
inserted = true;
|
|
4660
|
+
break;
|
|
4661
|
+
}
|
|
4662
|
+
}
|
|
4663
|
+
if (!inserted) items.push(jinjaNode);
|
|
4664
|
+
}
|
|
4665
|
+
}
|
|
4666
|
+
}
|
|
4667
|
+
} catch {
|
|
4668
|
+
}
|
|
4669
|
+
return items;
|
|
4670
|
+
}
|
|
4671
|
+
|
|
4672
|
+
// src/ui/plugin/markdownClipboard.ts
|
|
4673
|
+
var key = new PluginKey("markdownClipboard");
|
|
4674
|
+
var MAX_PASTE_LIST_DEPTH = 3;
|
|
4675
|
+
var MAX_FLATTEN_DEPTH = 128;
|
|
4676
|
+
function flattenDeepLists(node, listDepth = 0, _recurseDepth = 0) {
|
|
4677
|
+
if (_recurseDepth > MAX_FLATTEN_DEPTH) return node;
|
|
4678
|
+
const isList = node.type.name === "bulletList" || node.type.name === "orderedList";
|
|
4679
|
+
const currentDepth = isList ? listDepth + 1 : listDepth;
|
|
4680
|
+
if (isList && currentDepth >= MAX_PASTE_LIST_DEPTH) {
|
|
4681
|
+
const flatItems = [];
|
|
4682
|
+
node.forEach((li) => {
|
|
4683
|
+
const nonListBlocks = [];
|
|
4684
|
+
li.forEach((block) => {
|
|
4685
|
+
if (block.type.name !== "bulletList" && block.type.name !== "orderedList") {
|
|
4686
|
+
nonListBlocks.push(block);
|
|
4687
|
+
}
|
|
4688
|
+
});
|
|
4689
|
+
if (nonListBlocks.length > 0) {
|
|
4690
|
+
flatItems.push(li.type.create(li.attrs, nonListBlocks));
|
|
4691
|
+
}
|
|
4692
|
+
});
|
|
4693
|
+
if (flatItems.length === 0) return node;
|
|
4694
|
+
return node.copy(Fragment.fromArray(flatItems));
|
|
4695
|
+
}
|
|
4696
|
+
const children = [];
|
|
4697
|
+
let changed = false;
|
|
4698
|
+
node.forEach((child) => {
|
|
4699
|
+
const flattened = flattenDeepLists(child, currentDepth, _recurseDepth + 1);
|
|
4700
|
+
if (flattened !== child) changed = true;
|
|
4701
|
+
children.push(flattened);
|
|
4702
|
+
});
|
|
4703
|
+
if (!changed) return node;
|
|
4704
|
+
return node.copy(Fragment.fromArray(children));
|
|
4705
|
+
}
|
|
4706
|
+
function htmlToSlice(html) {
|
|
4707
|
+
if (typeof document === "undefined") return null;
|
|
4708
|
+
try {
|
|
4709
|
+
const domParser = new DOMParser();
|
|
4710
|
+
const parsed = domParser.parseFromString(html, "text/html");
|
|
4711
|
+
const body = parsed.body;
|
|
4712
|
+
if (!body || !body.childNodes.length) return null;
|
|
4713
|
+
const pmParser = ProseMirrorDOMParser.fromSchema(actionbookSchema);
|
|
4714
|
+
const doc2 = pmParser.parse(body);
|
|
4715
|
+
const flattened = flattenDeepLists(doc2);
|
|
4716
|
+
const content = flattened.content;
|
|
4717
|
+
let hasContent = false;
|
|
4718
|
+
content.forEach((node) => {
|
|
4719
|
+
if (node.type.name !== "paragraph" || node.content.size > 0) {
|
|
4720
|
+
hasContent = true;
|
|
4721
|
+
}
|
|
4722
|
+
});
|
|
4723
|
+
if (!hasContent) return null;
|
|
4724
|
+
const openDepth = content.childCount === 1 && content.firstChild?.type.name === "paragraph" ? 1 : 0;
|
|
4725
|
+
return new Slice(content, openDepth, openDepth);
|
|
4726
|
+
} catch {
|
|
4727
|
+
return null;
|
|
4728
|
+
}
|
|
4729
|
+
}
|
|
4730
|
+
function textToSlice(text2, view) {
|
|
4731
|
+
try {
|
|
4732
|
+
const existingIds = /* @__PURE__ */ new Set();
|
|
4733
|
+
view.state.doc.descendants((node) => {
|
|
4734
|
+
if (node.type.name === "jumpPoint") existingIds.add(node.attrs.id);
|
|
4735
|
+
});
|
|
4736
|
+
const deduped = text2.replace(/\^([A-Za-z_][A-Za-z0-9_]*)\^/gm, (match, id) => {
|
|
4737
|
+
if (existingIds.has(id)) return id;
|
|
4738
|
+
existingIds.add(id);
|
|
4739
|
+
return match;
|
|
4740
|
+
});
|
|
4741
|
+
const astNodes = parseFragment(deduped);
|
|
4742
|
+
const pmJSONNodes = astNodesToJSONContent(astNodes);
|
|
4743
|
+
const pmNodes = pmJSONNodes.map((json) => actionbookSchema.nodeFromJSON(json));
|
|
4744
|
+
const fragment = Fragment.fromArray(pmNodes);
|
|
4745
|
+
const openDepth = pmJSONNodes.length === 1 && pmJSONNodes[0].type === "paragraph" ? 1 : 0;
|
|
4746
|
+
return new Slice(fragment, openDepth, openDepth);
|
|
4747
|
+
} catch {
|
|
4748
|
+
return null;
|
|
4749
|
+
}
|
|
4750
|
+
}
|
|
4751
|
+
function createPlugin() {
|
|
4752
|
+
return new Plugin({
|
|
4753
|
+
key,
|
|
4754
|
+
props: {
|
|
4755
|
+
handlePaste(view, event) {
|
|
4756
|
+
const html = event.clipboardData?.getData("text/html");
|
|
4757
|
+
const text2 = event.clipboardData?.getData("text/plain");
|
|
4758
|
+
if (html) {
|
|
4759
|
+
const htmlSlice = htmlToSlice(html);
|
|
4760
|
+
if (htmlSlice) {
|
|
4761
|
+
view.dispatch(view.state.tr.replaceSelection(htmlSlice));
|
|
4762
|
+
return true;
|
|
4763
|
+
}
|
|
4764
|
+
}
|
|
4765
|
+
if (!text2) return false;
|
|
4766
|
+
const slice = textToSlice(text2, view);
|
|
4767
|
+
if (!slice) return false;
|
|
4768
|
+
view.dispatch(view.state.tr.replaceSelection(slice));
|
|
4769
|
+
return true;
|
|
4770
|
+
},
|
|
4771
|
+
clipboardTextParser(text2, _$context, _plain, view) {
|
|
4772
|
+
if (!text2) return Slice.empty;
|
|
4773
|
+
const slice = textToSlice(text2, view);
|
|
4774
|
+
if (!slice) {
|
|
4775
|
+
const textNode = actionbookSchema.text(text2);
|
|
4776
|
+
return new Slice(Fragment.from(textNode), 0, 0);
|
|
4172
4777
|
}
|
|
4173
4778
|
return slice;
|
|
4174
4779
|
},
|
|
4175
|
-
//
|
|
4176
|
-
|
|
4177
|
-
|
|
4780
|
+
// Transform pasted HTML: keep structure but flatten deep lists
|
|
4781
|
+
// to prevent Chrome contentEditable hanging
|
|
4782
|
+
transformPasted(slice) {
|
|
4783
|
+
const nodes = [];
|
|
4784
|
+
slice.content.forEach((node) => {
|
|
4785
|
+
nodes.push(flattenDeepLists(node));
|
|
4786
|
+
});
|
|
4787
|
+
return new Slice(Fragment.fromArray(nodes), slice.openStart, slice.openEnd);
|
|
4178
4788
|
},
|
|
4179
4789
|
clipboardTextSerializer(slice) {
|
|
4180
4790
|
try {
|
|
@@ -4197,7 +4807,7 @@ function createMarkdownClipboardPlugin() {
|
|
|
4197
4807
|
}
|
|
4198
4808
|
|
|
4199
4809
|
// src/ui/plugin/jumpPointPlugin.ts
|
|
4200
|
-
import { Plugin as Plugin2, PluginKey as PluginKey2, TextSelection } from "prosemirror-state";
|
|
4810
|
+
import { Plugin as Plugin2, PluginKey as PluginKey2, TextSelection as TextSelection2 } from "prosemirror-state";
|
|
4201
4811
|
import { Decoration, DecorationSet } from "prosemirror-view";
|
|
4202
4812
|
var adjacentKey = new PluginKey2("jumpPointAdjacent");
|
|
4203
4813
|
var JUMP_POINT_ADJACENT_SPEC = { jumpPointAdjacent: true };
|
|
@@ -4268,8 +4878,15 @@ function createJumpPointEditPlugin() {
|
|
|
4268
4878
|
}
|
|
4269
4879
|
});
|
|
4270
4880
|
}
|
|
4271
|
-
function
|
|
4881
|
+
function jumpPointAtOrBefore(state) {
|
|
4272
4882
|
const { selection } = state;
|
|
4883
|
+
if ("node" in selection) {
|
|
4884
|
+
const node = selection.node;
|
|
4885
|
+
if (node?.type?.name === "jumpPoint") {
|
|
4886
|
+
return { id: node.attrs.id, nodeStart: selection.from, nodeEnd: selection.to };
|
|
4887
|
+
}
|
|
4888
|
+
return null;
|
|
4889
|
+
}
|
|
4273
4890
|
if (!selection.empty) return null;
|
|
4274
4891
|
const { $from } = selection;
|
|
4275
4892
|
const nodeBefore = $from.nodeBefore;
|
|
@@ -4279,23 +4896,23 @@ function jumpPointBefore(state) {
|
|
|
4279
4896
|
return { id: nodeBefore.attrs.id, nodeStart, nodeEnd };
|
|
4280
4897
|
}
|
|
4281
4898
|
function explodeOnBackspace(state) {
|
|
4282
|
-
const info =
|
|
4899
|
+
const info = jumpPointAtOrBefore(state);
|
|
4283
4900
|
if (!info) return null;
|
|
4284
4901
|
const { id, nodeStart, nodeEnd } = info;
|
|
4285
4902
|
const rawText = `^${id}`;
|
|
4286
4903
|
const tr = state.tr.replaceWith(nodeStart, nodeEnd, state.schema.text(rawText));
|
|
4287
4904
|
const cursorPos = Math.min(nodeStart + rawText.length, tr.doc.content.size);
|
|
4288
|
-
tr.setSelection(
|
|
4905
|
+
tr.setSelection(TextSelection2.near(tr.doc.resolve(cursorPos)));
|
|
4289
4906
|
return tr;
|
|
4290
4907
|
}
|
|
4291
4908
|
function explodeOnArrowLeft(state) {
|
|
4292
|
-
const info =
|
|
4909
|
+
const info = jumpPointAtOrBefore(state);
|
|
4293
4910
|
if (!info) return null;
|
|
4294
4911
|
const { id, nodeStart, nodeEnd } = info;
|
|
4295
4912
|
const rawText = `^${id}^`;
|
|
4296
4913
|
const tr = state.tr.replaceWith(nodeStart, nodeEnd, state.schema.text(rawText));
|
|
4297
4914
|
const cursorPos = Math.min(nodeStart + 1 + id.length, tr.doc.content.size);
|
|
4298
|
-
tr.setSelection(
|
|
4915
|
+
tr.setSelection(TextSelection2.near(tr.doc.resolve(cursorPos)));
|
|
4299
4916
|
tr.setMeta(jumpPointEditKey, { from: nodeStart, to: nodeStart + rawText.length });
|
|
4300
4917
|
return tr;
|
|
4301
4918
|
}
|
|
@@ -4342,6 +4959,7 @@ function createJumpPointAdjacentPlugin() {
|
|
|
4342
4959
|
}
|
|
4343
4960
|
|
|
4344
4961
|
// src/ui/plugin/jumpPointNodeViewPlugin.tsx
|
|
4962
|
+
import { useCallback as useCallback2, useState as useState2 } from "react";
|
|
4345
4963
|
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
4346
4964
|
var JUMP_POINT_STYLE = {
|
|
4347
4965
|
display: "inline-flex",
|
|
@@ -4349,31 +4967,118 @@ var JUMP_POINT_STYLE = {
|
|
|
4349
4967
|
backgroundColor: "#FFF2B6",
|
|
4350
4968
|
border: "1px solid #FFC233",
|
|
4351
4969
|
color: "#AA5D04",
|
|
4352
|
-
borderRadius: "
|
|
4353
|
-
padding: "
|
|
4354
|
-
fontSize: "
|
|
4355
|
-
lineHeight:
|
|
4970
|
+
borderRadius: "2px",
|
|
4971
|
+
padding: "2px",
|
|
4972
|
+
fontSize: "12px",
|
|
4973
|
+
lineHeight: "16px",
|
|
4356
4974
|
userSelect: "none",
|
|
4357
4975
|
cursor: "default",
|
|
4358
|
-
boxSizing: "border-box"
|
|
4976
|
+
boxSizing: "border-box",
|
|
4977
|
+
height: "20px",
|
|
4978
|
+
overflow: "hidden"
|
|
4359
4979
|
};
|
|
4360
4980
|
var JUMP_POINT_ADJACENT_STYLE = {
|
|
4361
4981
|
...JUMP_POINT_STYLE,
|
|
4362
4982
|
backgroundColor: "#FFE680",
|
|
4363
4983
|
borderColor: "#FF9500"
|
|
4364
4984
|
};
|
|
4365
|
-
|
|
4366
|
-
|
|
4985
|
+
var JUMP_POINT_DUPLICATE_STYLE = {
|
|
4986
|
+
...JUMP_POINT_STYLE,
|
|
4987
|
+
backgroundColor: "#FFD9DD",
|
|
4988
|
+
borderColor: "#D9352C",
|
|
4989
|
+
color: "#9D091E"
|
|
4990
|
+
};
|
|
4991
|
+
var LABEL_STYLE = {
|
|
4992
|
+
padding: "0 4px",
|
|
4993
|
+
whiteSpace: "nowrap"
|
|
4994
|
+
};
|
|
4995
|
+
var CLOSE_BTN_STYLE = {
|
|
4996
|
+
display: "inline-flex",
|
|
4997
|
+
alignItems: "center",
|
|
4998
|
+
justifyContent: "center",
|
|
4999
|
+
width: "16px",
|
|
5000
|
+
height: "16px",
|
|
5001
|
+
padding: 0,
|
|
5002
|
+
border: "none",
|
|
5003
|
+
background: "transparent",
|
|
5004
|
+
cursor: "pointer",
|
|
5005
|
+
borderRadius: "1px",
|
|
5006
|
+
flexShrink: 0,
|
|
5007
|
+
color: "inherit",
|
|
5008
|
+
fontSize: "10px",
|
|
5009
|
+
lineHeight: 1
|
|
5010
|
+
};
|
|
5011
|
+
var TOOLTIP_STYLE = {
|
|
5012
|
+
position: "absolute",
|
|
5013
|
+
bottom: "calc(100% + 8px)",
|
|
5014
|
+
left: "50%",
|
|
5015
|
+
transform: "translateX(-50%)",
|
|
5016
|
+
backgroundColor: "#fff",
|
|
5017
|
+
border: "1px solid #CCC",
|
|
5018
|
+
borderRadius: "4px",
|
|
5019
|
+
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)",
|
|
5020
|
+
padding: "16px 20px",
|
|
5021
|
+
fontSize: "14px",
|
|
5022
|
+
lineHeight: "20px",
|
|
5023
|
+
color: "#0D0D0D",
|
|
5024
|
+
whiteSpace: "nowrap",
|
|
5025
|
+
zIndex: 100,
|
|
5026
|
+
pointerEvents: "none"
|
|
5027
|
+
};
|
|
5028
|
+
function JumpPointNodeViewComponent({ node, view, getPos, decorations }) {
|
|
5029
|
+
const id = node.attrs.id;
|
|
4367
5030
|
const isAdjacent = decorations?.some((d) => d.spec?.jumpPointAdjacent === true) ?? false;
|
|
5031
|
+
const isDuplicate = decorations?.some((d) => d.spec?.jumpPointDuplicate === true) ?? false;
|
|
5032
|
+
const [showTooltip, setShowTooltip] = useState2(false);
|
|
5033
|
+
const handleDelete2 = useCallback2(() => {
|
|
5034
|
+
const pos = getPos();
|
|
5035
|
+
if (pos == null) return;
|
|
5036
|
+
const tr = view.state.tr.delete(pos, pos + node.nodeSize);
|
|
5037
|
+
view.dispatch(tr);
|
|
5038
|
+
view.focus();
|
|
5039
|
+
}, [view, getPos, node.nodeSize]);
|
|
5040
|
+
if (isDuplicate) {
|
|
5041
|
+
return /* @__PURE__ */ jsxs3(
|
|
5042
|
+
"span",
|
|
5043
|
+
{
|
|
5044
|
+
style: { ...JUMP_POINT_DUPLICATE_STYLE, position: "relative" },
|
|
5045
|
+
id: `jp-${id}`,
|
|
5046
|
+
onMouseEnter: () => setShowTooltip(true),
|
|
5047
|
+
onMouseLeave: () => setShowTooltip(false),
|
|
5048
|
+
children: [
|
|
5049
|
+
/* @__PURE__ */ jsx4(IconAnchor, { size: 12, fill: "#9D091E", style: { paddingLeft: "2px", flexShrink: 0 } }),
|
|
5050
|
+
/* @__PURE__ */ jsx4("span", { style: LABEL_STYLE, children: id }),
|
|
5051
|
+
/* @__PURE__ */ jsx4(
|
|
5052
|
+
"button",
|
|
5053
|
+
{
|
|
5054
|
+
style: CLOSE_BTN_STYLE,
|
|
5055
|
+
onMouseDown: (e) => {
|
|
5056
|
+
e.preventDefault();
|
|
5057
|
+
e.stopPropagation();
|
|
5058
|
+
handleDelete2();
|
|
5059
|
+
},
|
|
5060
|
+
title: "Remove anchor",
|
|
5061
|
+
children: "\u2715"
|
|
5062
|
+
}
|
|
5063
|
+
),
|
|
5064
|
+
showTooltip && /* @__PURE__ */ jsxs3("span", { style: TOOLTIP_STYLE, children: [
|
|
5065
|
+
"\u201C",
|
|
5066
|
+
id,
|
|
5067
|
+
"\u201D is already used as an anchor"
|
|
5068
|
+
] })
|
|
5069
|
+
]
|
|
5070
|
+
}
|
|
5071
|
+
);
|
|
5072
|
+
}
|
|
4368
5073
|
if (isAdjacent) {
|
|
4369
5074
|
return /* @__PURE__ */ jsxs3("span", { style: JUMP_POINT_ADJACENT_STYLE, id: `jp-${id}`, children: [
|
|
4370
|
-
/* @__PURE__ */ jsx4(IconAnchor, { size: 12, fill: "#AA5D04", style: {
|
|
4371
|
-
`^${id}^`
|
|
5075
|
+
/* @__PURE__ */ jsx4(IconAnchor, { size: 12, fill: "#AA5D04", style: { paddingLeft: "2px", flexShrink: 0 } }),
|
|
5076
|
+
/* @__PURE__ */ jsx4("span", { style: LABEL_STYLE, children: `^${id}^` })
|
|
4372
5077
|
] });
|
|
4373
5078
|
}
|
|
4374
5079
|
return /* @__PURE__ */ jsxs3("span", { style: JUMP_POINT_STYLE, id: `jp-${id}`, children: [
|
|
4375
|
-
/* @__PURE__ */ jsx4(IconAnchor, { size: 12, fill: "#AA5D04", style: {
|
|
4376
|
-
id
|
|
5080
|
+
/* @__PURE__ */ jsx4(IconAnchor, { size: 12, fill: "#AA5D04", style: { paddingLeft: "2px", flexShrink: 0 } }),
|
|
5081
|
+
/* @__PURE__ */ jsx4("span", { style: LABEL_STYLE, children: id })
|
|
4377
5082
|
] });
|
|
4378
5083
|
}
|
|
4379
5084
|
function createJumpPointNodeViewPlugin() {
|
|
@@ -4388,108 +5093,100 @@ function createJumpPointNodeViewPlugin() {
|
|
|
4388
5093
|
// src/ui/plugin/jumpPointValidationPlugin.ts
|
|
4389
5094
|
import { Plugin as Plugin3, PluginKey as PluginKey3 } from "prosemirror-state";
|
|
4390
5095
|
import { Decoration as Decoration2, DecorationSet as DecorationSet2 } from "prosemirror-view";
|
|
4391
|
-
var
|
|
4392
|
-
function
|
|
4393
|
-
const
|
|
4394
|
-
|
|
4395
|
-
doc2.descendants((node, pos) => {
|
|
5096
|
+
var pluginKey = new PluginKey3("jumpPointValidation");
|
|
5097
|
+
function collectJumpPointIds(state) {
|
|
5098
|
+
const ids = /* @__PURE__ */ new Set();
|
|
5099
|
+
state.doc.descendants((node) => {
|
|
4396
5100
|
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
|
-
}
|
|
5101
|
+
ids.add(node.attrs.id);
|
|
4410
5102
|
}
|
|
4411
5103
|
});
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
5104
|
+
return ids;
|
|
5105
|
+
}
|
|
5106
|
+
function findDuplicatePositions(state) {
|
|
5107
|
+
const idCount = /* @__PURE__ */ new Map();
|
|
5108
|
+
const nodes = [];
|
|
5109
|
+
state.doc.descendants((node, pos) => {
|
|
5110
|
+
if (node.type.name === "jumpPoint") {
|
|
5111
|
+
const id = node.attrs.id;
|
|
5112
|
+
idCount.set(id, (idCount.get(id) ?? 0) + 1);
|
|
5113
|
+
nodes.push({ id, pos, size: node.nodeSize });
|
|
4420
5114
|
}
|
|
4421
|
-
}
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
4426
|
-
|
|
5115
|
+
});
|
|
5116
|
+
return nodes.filter((n) => (idCount.get(n.id) ?? 0) > 1);
|
|
5117
|
+
}
|
|
5118
|
+
function findBrokenAnchorRefs(state, existingIds) {
|
|
5119
|
+
const broken = [];
|
|
5120
|
+
const linkMarkType = state.schema.marks.link;
|
|
5121
|
+
if (!linkMarkType) return broken;
|
|
5122
|
+
state.doc.descendants((node, pos) => {
|
|
5123
|
+
if (!node.isText) return;
|
|
5124
|
+
const linkMark2 = node.marks.find((m) => m.type === linkMarkType);
|
|
5125
|
+
if (!linkMark2) return;
|
|
5126
|
+
const href = linkMark2.attrs.href;
|
|
5127
|
+
if (!href || !href.startsWith("#")) return;
|
|
5128
|
+
const refId = href.slice(1);
|
|
5129
|
+
if (refId && !existingIds.has(refId)) {
|
|
5130
|
+
broken.push({ from: pos, to: pos + node.nodeSize, refId });
|
|
4427
5131
|
}
|
|
4428
|
-
}
|
|
4429
|
-
return
|
|
5132
|
+
});
|
|
5133
|
+
return broken;
|
|
5134
|
+
}
|
|
5135
|
+
function hasDuplicateJumpPoints(state) {
|
|
5136
|
+
return findDuplicatePositions(state).length > 0;
|
|
5137
|
+
}
|
|
5138
|
+
function hasBrokenAnchorRefs(state) {
|
|
5139
|
+
const ids = collectJumpPointIds(state);
|
|
5140
|
+
return findBrokenAnchorRefs(state, ids).length > 0;
|
|
4430
5141
|
}
|
|
4431
5142
|
function createJumpPointValidationPlugin() {
|
|
4432
5143
|
return {
|
|
4433
5144
|
name: "jumpPointValidation",
|
|
4434
5145
|
plugins: () => [
|
|
4435
5146
|
new Plugin3({
|
|
4436
|
-
key:
|
|
5147
|
+
key: pluginKey,
|
|
4437
5148
|
state: {
|
|
4438
5149
|
init(_, state) {
|
|
4439
|
-
return
|
|
5150
|
+
return buildDecorations2(state);
|
|
4440
5151
|
},
|
|
4441
|
-
apply(tr,
|
|
4442
|
-
if (
|
|
4443
|
-
|
|
5152
|
+
apply(tr, oldSet, _oldState, newState) {
|
|
5153
|
+
if (tr.docChanged) {
|
|
5154
|
+
return buildDecorations2(newState);
|
|
5155
|
+
}
|
|
5156
|
+
return oldSet.map(tr.mapping, tr.doc);
|
|
4444
5157
|
}
|
|
4445
5158
|
},
|
|
4446
5159
|
props: {
|
|
4447
5160
|
decorations(state) {
|
|
4448
|
-
return
|
|
5161
|
+
return pluginKey.getState(state) ?? DecorationSet2.empty;
|
|
4449
5162
|
}
|
|
4450
5163
|
}
|
|
4451
5164
|
})
|
|
4452
5165
|
]
|
|
4453
5166
|
};
|
|
4454
5167
|
}
|
|
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;
|
|
5168
|
+
function buildDecorations2(state) {
|
|
5169
|
+
const decos = [];
|
|
5170
|
+
const duplicates = findDuplicatePositions(state);
|
|
5171
|
+
for (const { pos, size } of duplicates) {
|
|
5172
|
+
decos.push(
|
|
5173
|
+
Decoration2.node(pos, pos + size, { class: "jump-point-duplicate" }, { jumpPointDuplicate: true })
|
|
5174
|
+
);
|
|
5175
|
+
}
|
|
5176
|
+
const existingIds = collectJumpPointIds(state);
|
|
5177
|
+
const brokenRefs = findBrokenAnchorRefs(state, existingIds);
|
|
5178
|
+
for (const { from, to, refId } of brokenRefs) {
|
|
5179
|
+
decos.push(
|
|
5180
|
+
Decoration2.inline(from, to, {
|
|
5181
|
+
class: "broken-anchor-ref",
|
|
5182
|
+
"data-broken-ref": refId,
|
|
5183
|
+
title: `Anchor "${refId}" no longer exists`,
|
|
5184
|
+
style: "color: #D9352C; text-decoration-color: #D9352C;"
|
|
5185
|
+
})
|
|
5186
|
+
);
|
|
5187
|
+
}
|
|
5188
|
+
if (decos.length === 0) return DecorationSet2.empty;
|
|
5189
|
+
return DecorationSet2.create(state.doc, decos);
|
|
4493
5190
|
}
|
|
4494
5191
|
|
|
4495
5192
|
// src/ui/plugin/inlineToolTagNodeViewPlugin.tsx
|
|
@@ -4510,9 +5207,12 @@ var RESOURCE_TAG_ICONS2 = {
|
|
|
4510
5207
|
time_diff: IconTimeDiff
|
|
4511
5208
|
};
|
|
4512
5209
|
var DEFAULT_ICON = IconTool;
|
|
5210
|
+
var RESOURCE_ID_OVERRIDES = {
|
|
5211
|
+
"close-happy-tiger": { color: "#0D0D0D", icon: IconStop }
|
|
5212
|
+
};
|
|
4513
5213
|
var OUTER_STYLE = {
|
|
4514
5214
|
display: "inline-flex",
|
|
4515
|
-
padding: "
|
|
5215
|
+
padding: "2px",
|
|
4516
5216
|
border: "1px solid #CCCCCC",
|
|
4517
5217
|
borderRadius: "2px",
|
|
4518
5218
|
alignItems: "center",
|
|
@@ -4532,16 +5232,19 @@ var ICON_BLOCK_BASE = {
|
|
|
4532
5232
|
};
|
|
4533
5233
|
var LABEL_BASE = {
|
|
4534
5234
|
padding: "0 4px",
|
|
4535
|
-
fontSize: "
|
|
4536
|
-
lineHeight:
|
|
5235
|
+
fontSize: "12px",
|
|
5236
|
+
lineHeight: "16px",
|
|
4537
5237
|
userSelect: "none"
|
|
4538
5238
|
};
|
|
4539
|
-
function InlineToolTagNodeViewComponent({ node }) {
|
|
5239
|
+
function InlineToolTagNodeViewComponent({ node, selected }) {
|
|
4540
5240
|
const type = node.attrs.type;
|
|
4541
5241
|
const text2 = node.attrs.text;
|
|
4542
|
-
const
|
|
4543
|
-
const
|
|
4544
|
-
|
|
5242
|
+
const resourceId = node.attrs.resourceId;
|
|
5243
|
+
const override = RESOURCE_ID_OVERRIDES[resourceId];
|
|
5244
|
+
const color = override?.color ?? RESOURCE_TAG_COLORS2[type] ?? DEFAULT_COLOR;
|
|
5245
|
+
const Icon = override?.icon ?? RESOURCE_TAG_ICONS2[type] ?? DEFAULT_ICON;
|
|
5246
|
+
const style = selected ? { ...OUTER_STYLE, boxShadow: `inset 0 0 0 1px ${color}` } : OUTER_STYLE;
|
|
5247
|
+
return /* @__PURE__ */ jsxs4("span", { style, "data-type": type, "data-resource-id": node.attrs.resourceId, children: [
|
|
4545
5248
|
/* @__PURE__ */ jsx5("span", { style: { ...ICON_BLOCK_BASE, backgroundColor: color }, children: /* @__PURE__ */ jsx5(Icon, { size: 9, fill: "white" }) }),
|
|
4546
5249
|
/* @__PURE__ */ jsx5("span", { style: { ...LABEL_BASE, color }, children: text2 })
|
|
4547
5250
|
] });
|
|
@@ -4585,283 +5288,94 @@ function addInlineChipDecorations(doc2, decorations) {
|
|
|
4585
5288
|
})
|
|
4586
5289
|
);
|
|
4587
5290
|
}
|
|
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;
|
|
5291
|
+
});
|
|
5292
|
+
}
|
|
5293
|
+
function addStructureBorderDecorations(doc2, blocks, decorations) {
|
|
5294
|
+
const json = doc2.toJSON();
|
|
5295
|
+
let ast;
|
|
5296
|
+
try {
|
|
5297
|
+
ast = fromProseMirrorJSON(json);
|
|
5298
|
+
} catch {
|
|
5299
|
+
return;
|
|
5300
|
+
}
|
|
5301
|
+
const structures = analyzeJinjaBlocks(ast);
|
|
5302
|
+
for (const structure of structures) {
|
|
5303
|
+
const blockBranchType = /* @__PURE__ */ new Map();
|
|
5304
|
+
for (const branch of structure.branches) {
|
|
5305
|
+
blockBranchType.set(branch.tagBlockIndex, branch.type);
|
|
5306
|
+
for (let i = branch.blockStartIndex; i < branch.blockEndIndex; i++) {
|
|
5307
|
+
if (!blockBranchType.has(i)) {
|
|
5308
|
+
blockBranchType.set(i, branch.type);
|
|
5309
|
+
}
|
|
4837
5310
|
}
|
|
4838
5311
|
}
|
|
4839
|
-
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
continue;
|
|
4843
|
-
}
|
|
4844
|
-
if (char === ">") {
|
|
4845
|
-
rawTokens.push({ type: "GT", text: char, start: i, end: i + 1 });
|
|
4846
|
-
i++;
|
|
4847
|
-
continue;
|
|
4848
|
-
}
|
|
4849
|
-
if (char === "(") {
|
|
4850
|
-
rawTokens.push({ type: "LPAREN", text: char, start: i, end: i + 1 });
|
|
4851
|
-
i++;
|
|
4852
|
-
continue;
|
|
5312
|
+
const lastBranch = structure.branches[structure.branches.length - 1];
|
|
5313
|
+
if (lastBranch && !blockBranchType.has(structure.endifTagBlockIndex)) {
|
|
5314
|
+
blockBranchType.set(structure.endifTagBlockIndex, lastBranch.type);
|
|
4853
5315
|
}
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
5316
|
+
const first = structure.ifTagBlockIndex;
|
|
5317
|
+
const last = structure.endifTagBlockIndex;
|
|
5318
|
+
for (let i = first; i <= last; i++) {
|
|
5319
|
+
const block = blocks[i];
|
|
5320
|
+
if (!block) continue;
|
|
5321
|
+
const branchType = blockBranchType.get(i) || "if";
|
|
5322
|
+
const prevType = i > first ? blockBranchType.get(i - 1) : void 0;
|
|
5323
|
+
const nextType = i < last ? blockBranchType.get(i + 1) : void 0;
|
|
5324
|
+
const classes = ["jinja-bar", `jinja-bar-${branchType}`];
|
|
5325
|
+
if (i === first || prevType !== branchType) classes.push("jinja-bar-first");
|
|
5326
|
+
if (i === last || nextType !== branchType) classes.push("jinja-bar-last");
|
|
5327
|
+
decorations.push(Decoration3.node(block.from, block.to, { class: classes.join(" ") }));
|
|
4858
5328
|
}
|
|
4859
|
-
return finalizeTokens(input, rawTokens);
|
|
4860
5329
|
}
|
|
4861
|
-
|
|
5330
|
+
}
|
|
5331
|
+
function hasJinjaTags(doc2) {
|
|
5332
|
+
let found = false;
|
|
5333
|
+
doc2.descendants((node) => {
|
|
5334
|
+
if (found) return false;
|
|
5335
|
+
if (node.isText && node.text.includes("{%")) {
|
|
5336
|
+
found = true;
|
|
5337
|
+
return false;
|
|
5338
|
+
}
|
|
5339
|
+
});
|
|
5340
|
+
return found;
|
|
5341
|
+
}
|
|
5342
|
+
function buildDecorations3(doc2) {
|
|
5343
|
+
if (!hasJinjaTags(doc2)) return DecorationSet3.empty;
|
|
5344
|
+
const blocks = getBlockPositions(doc2);
|
|
5345
|
+
const decorations = [];
|
|
5346
|
+
addInlineChipDecorations(doc2, decorations);
|
|
5347
|
+
addStructureBorderDecorations(doc2, blocks, decorations);
|
|
5348
|
+
if (decorations.length === 0) return DecorationSet3.empty;
|
|
5349
|
+
return DecorationSet3.create(doc2, decorations);
|
|
5350
|
+
}
|
|
5351
|
+
function createJinjaDecorationPlugin() {
|
|
5352
|
+
return {
|
|
5353
|
+
name: "jinjaDecoration",
|
|
5354
|
+
plugins: () => [
|
|
5355
|
+
new Plugin4({
|
|
5356
|
+
key: jinjaPluginKey,
|
|
5357
|
+
state: {
|
|
5358
|
+
init(_, state) {
|
|
5359
|
+
return buildDecorations3(state.doc);
|
|
5360
|
+
},
|
|
5361
|
+
apply(tr, oldDecos) {
|
|
5362
|
+
if (!tr.docChanged) return oldDecos;
|
|
5363
|
+
return buildDecorations3(tr.doc);
|
|
5364
|
+
}
|
|
5365
|
+
},
|
|
5366
|
+
props: {
|
|
5367
|
+
decorations(state) {
|
|
5368
|
+
return jinjaPluginKey.getState(state);
|
|
5369
|
+
}
|
|
5370
|
+
}
|
|
5371
|
+
})
|
|
5372
|
+
]
|
|
5373
|
+
};
|
|
4862
5374
|
}
|
|
4863
5375
|
|
|
4864
5376
|
// src/ui/plugin/jinjaIfBlockPlugin.tsx
|
|
5377
|
+
import { useEffect as useEffect2, useRef as useRef2, useState as useState3 } from "react";
|
|
5378
|
+
import { createRoot as createRoot2 } from "react-dom/client";
|
|
4865
5379
|
import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
4866
5380
|
var PLACEHOLDER_TEXT = "Describe what AI agent should do when this condition is met";
|
|
4867
5381
|
var CONDITION_PLACEHOLDER = "Write a condition in natural language";
|
|
@@ -5312,8 +5826,8 @@ function ConditionDisplay({
|
|
|
5312
5826
|
editable = true,
|
|
5313
5827
|
onConditionChange
|
|
5314
5828
|
}) {
|
|
5315
|
-
const [isEditing, setIsEditing] =
|
|
5316
|
-
const [draftValue, setDraftValue] =
|
|
5829
|
+
const [isEditing, setIsEditing] = useState3(false);
|
|
5830
|
+
const [draftValue, setDraftValue] = useState3(condition);
|
|
5317
5831
|
const inputRef = useRef2(null);
|
|
5318
5832
|
useEffect2(() => {
|
|
5319
5833
|
if (!isEditing) {
|
|
@@ -5419,7 +5933,7 @@ function JinjaBranchHeader({
|
|
|
5419
5933
|
isLastBranch,
|
|
5420
5934
|
hasElseBranch
|
|
5421
5935
|
}) {
|
|
5422
|
-
const [menuSource, setMenuSource] =
|
|
5936
|
+
const [menuSource, setMenuSource] = useState3(null);
|
|
5423
5937
|
const kebabRef = useRef2(null);
|
|
5424
5938
|
const footerRef = useRef2(null);
|
|
5425
5939
|
useEffect2(() => {
|
|
@@ -5699,7 +6213,7 @@ function createJinjaIfBlockPlugin() {
|
|
|
5699
6213
|
|
|
5700
6214
|
// src/ui/plugin/linkPlugin.ts
|
|
5701
6215
|
import { InputRule as InputRule2, inputRules as inputRules2 } from "prosemirror-inputrules";
|
|
5702
|
-
import { Plugin as Plugin5, PluginKey as PluginKey5, TextSelection as
|
|
6216
|
+
import { Plugin as Plugin5, PluginKey as PluginKey5, TextSelection as TextSelection3 } from "prosemirror-state";
|
|
5703
6217
|
var LINK_INPUT_RE = /\[([^\]]*)\]\(([^)\s]*?)(?:\s+"([^"]*)")?\)$/;
|
|
5704
6218
|
var LINK_FULL_RE = /^\[([^\]]*)\]\(([^)\s]*?)(?:\s+"([^"]*)")?\)$/;
|
|
5705
6219
|
var linkEditKey = new PluginKey5("linkEdit");
|
|
@@ -5745,7 +6259,7 @@ function explodeLinkToRaw(state) {
|
|
|
5745
6259
|
const tr = state.tr;
|
|
5746
6260
|
tr.replaceWith(from, to, schema.text(rawText));
|
|
5747
6261
|
const newPos = Math.min(from + rawCursorOffset, tr.doc.content.size);
|
|
5748
|
-
tr.setSelection(
|
|
6262
|
+
tr.setSelection(TextSelection3.near(tr.doc.resolve(newPos)));
|
|
5749
6263
|
tr.setMeta(linkEditKey, { from, to: from + rawText.length });
|
|
5750
6264
|
return tr;
|
|
5751
6265
|
}
|
|
@@ -5891,11 +6405,11 @@ var STYLES = (
|
|
|
5891
6405
|
--ab-dh-color-idle: transparent;
|
|
5892
6406
|
--ab-dh-color-hover: #c4c4c4;
|
|
5893
6407
|
--ab-dh-color-visible: #8b8b8b;
|
|
5894
|
-
--ab-dh-color-accent:
|
|
5895
|
-
--ab-dh-bg-hover: rgba(
|
|
5896
|
-
--ab-dh-bg-active: rgba(
|
|
6408
|
+
--ab-dh-color-accent: rgba(1,156,110,0.8);
|
|
6409
|
+
--ab-dh-bg-hover: rgba(13,13,13,0.04);
|
|
6410
|
+
--ab-dh-bg-active: rgba(13,13,13,0.04);
|
|
5897
6411
|
--ab-dh-dragging-opacity: 0.4;
|
|
5898
|
-
--ab-dh-handle-size:
|
|
6412
|
+
--ab-dh-handle-size: 24px;
|
|
5899
6413
|
--ab-dh-handle-radius: 4px;
|
|
5900
6414
|
--ab-dh-transition-duration: 0.15s;
|
|
5901
6415
|
|
|
@@ -5912,15 +6426,19 @@ var STYLES = (
|
|
|
5912
6426
|
align-items: center;
|
|
5913
6427
|
justify-content: center;
|
|
5914
6428
|
cursor: grab;
|
|
5915
|
-
color:
|
|
6429
|
+
color: transparent;
|
|
5916
6430
|
border-radius: var(--ab-dh-handle-radius);
|
|
5917
|
-
transition: color var(--ab-dh-transition-duration), background var(--ab-dh-transition-duration);
|
|
6431
|
+
transition: color var(--ab-dh-transition-duration), background var(--ab-dh-transition-duration), opacity var(--ab-dh-transition-duration);
|
|
5918
6432
|
user-select: none;
|
|
5919
6433
|
pointer-events: auto;
|
|
5920
6434
|
touch-action: none;
|
|
6435
|
+
opacity: 0;
|
|
6436
|
+
pointer-events: none;
|
|
5921
6437
|
}
|
|
5922
|
-
.ab-drag-handle
|
|
5923
|
-
|
|
6438
|
+
.ab-drag-handle.ab-dh-active {
|
|
6439
|
+
opacity: 1;
|
|
6440
|
+
pointer-events: auto;
|
|
6441
|
+
color: var(--ab-dh-color-visible);
|
|
5924
6442
|
}
|
|
5925
6443
|
.ab-drag-handle:hover {
|
|
5926
6444
|
color: var(--ab-dh-color-visible) !important;
|
|
@@ -5934,18 +6452,20 @@ var STYLES = (
|
|
|
5934
6452
|
.ab-drop-indicator {
|
|
5935
6453
|
position: absolute;
|
|
5936
6454
|
left: 0; right: 0;
|
|
5937
|
-
height:
|
|
5938
|
-
background:
|
|
5939
|
-
border
|
|
6455
|
+
height: 4px;
|
|
6456
|
+
background: rgba(1,156,110,0.4);
|
|
6457
|
+
border: 1px solid rgba(1,156,110,0.6);
|
|
6458
|
+
border-radius: 12px;
|
|
5940
6459
|
pointer-events: none;
|
|
5941
6460
|
z-index: 20;
|
|
6461
|
+
box-sizing: border-box;
|
|
5942
6462
|
transition: top 60ms ease-out;
|
|
5943
6463
|
}
|
|
5944
6464
|
.ab-block-dragging {
|
|
5945
6465
|
opacity: var(--ab-dh-dragging-opacity, 0.4);
|
|
5946
6466
|
}
|
|
5947
6467
|
@keyframes ab-block-flash {
|
|
5948
|
-
from { background: rgba(
|
|
6468
|
+
from { background: rgba(1,156,110,0.08); }
|
|
5949
6469
|
to { background: transparent; }
|
|
5950
6470
|
}
|
|
5951
6471
|
.ab-block-just-moved {
|
|
@@ -6101,23 +6621,25 @@ var DragHandleController = class {
|
|
|
6101
6621
|
this.liveRegion.setAttribute("aria-live", "assertive");
|
|
6102
6622
|
this.liveRegion.setAttribute("aria-atomic", "true");
|
|
6103
6623
|
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 };
|
|
6624
|
+
this.hoverBound = { enter: () => {
|
|
6625
|
+
}, leave: () => {
|
|
6626
|
+
} };
|
|
6113
6627
|
this.scrollContainer = this.findScrollContainer(view.dom);
|
|
6114
6628
|
this.scrollContainer.addEventListener("scroll", this.onScroll, { passive: true });
|
|
6115
6629
|
this.resizeObserver = new ResizeObserver(() => this.scheduleUpdate());
|
|
6116
6630
|
this.resizeObserver.observe(view.dom);
|
|
6631
|
+
if (!view.editable) {
|
|
6632
|
+
this.layer.style.display = "none";
|
|
6633
|
+
}
|
|
6117
6634
|
this.rebuildHandles();
|
|
6118
6635
|
}
|
|
6119
6636
|
update(view, prevState) {
|
|
6120
6637
|
this.view = view;
|
|
6638
|
+
if (!view.editable) {
|
|
6639
|
+
this.layer.style.display = "none";
|
|
6640
|
+
return;
|
|
6641
|
+
}
|
|
6642
|
+
this.layer.style.display = "";
|
|
6121
6643
|
if (this.drag) {
|
|
6122
6644
|
this.pendingUpdate = true;
|
|
6123
6645
|
return;
|
|
@@ -6125,6 +6647,21 @@ var DragHandleController = class {
|
|
|
6125
6647
|
if (!view.state.doc.eq(prevState.doc)) {
|
|
6126
6648
|
this.scheduleUpdate();
|
|
6127
6649
|
}
|
|
6650
|
+
if (!view.state.selection.eq(prevState.selection) || !view.state.doc.eq(prevState.doc)) {
|
|
6651
|
+
this.updateActiveHandle();
|
|
6652
|
+
}
|
|
6653
|
+
}
|
|
6654
|
+
/** Show only the handle for the block containing the cursor. */
|
|
6655
|
+
updateActiveHandle() {
|
|
6656
|
+
const { $from } = this.view.state.selection;
|
|
6657
|
+
const cursorBlockOffset = $from.start(1) - 1;
|
|
6658
|
+
for (const h of this.handles) {
|
|
6659
|
+
if (h.block.offset === cursorBlockOffset) {
|
|
6660
|
+
h.el.classList.add("ab-dh-active");
|
|
6661
|
+
} else {
|
|
6662
|
+
h.el.classList.remove("ab-dh-active");
|
|
6663
|
+
}
|
|
6664
|
+
}
|
|
6128
6665
|
}
|
|
6129
6666
|
destroy() {
|
|
6130
6667
|
this.cancelDrag();
|
|
@@ -6216,6 +6753,7 @@ var DragHandleController = class {
|
|
|
6216
6753
|
el.setAttribute("role", "button");
|
|
6217
6754
|
el.setAttribute("aria-roledescription", "drag handle");
|
|
6218
6755
|
el.setAttribute("aria-label", `\uBE14\uB85D ${idx + 1} \uC774\uB3D9`);
|
|
6756
|
+
el.setAttribute("title", "Drag to move");
|
|
6219
6757
|
el.setAttribute("tabindex", "-1");
|
|
6220
6758
|
el.innerHTML = GRIP_SVG;
|
|
6221
6759
|
el.style.left = `${handleLeft}px`;
|
|
@@ -6226,6 +6764,7 @@ var DragHandleController = class {
|
|
|
6226
6764
|
}
|
|
6227
6765
|
this.handles = newHandles;
|
|
6228
6766
|
this.prevBlocks = newBlocks;
|
|
6767
|
+
this.updateActiveHandle();
|
|
6229
6768
|
}
|
|
6230
6769
|
bindHandleEvents(el, index) {
|
|
6231
6770
|
let currentIndex = index;
|
|
@@ -6296,7 +6835,8 @@ var DragHandleController = class {
|
|
|
6296
6835
|
pointerId: e.pointerId,
|
|
6297
6836
|
startX: e.clientX,
|
|
6298
6837
|
startY: e.clientY,
|
|
6299
|
-
activated: false
|
|
6838
|
+
activated: false,
|
|
6839
|
+
ghost: null
|
|
6300
6840
|
};
|
|
6301
6841
|
this.addGlobalDragListeners(e.pointerId);
|
|
6302
6842
|
}
|
|
@@ -6305,6 +6845,22 @@ var DragHandleController = class {
|
|
|
6305
6845
|
this.drag.activated = true;
|
|
6306
6846
|
this.drag.handle.classList.add("dragging");
|
|
6307
6847
|
this.drag.blockDom.classList.add("ab-block-dragging");
|
|
6848
|
+
const blockRect = this.drag.blockDom.getBoundingClientRect();
|
|
6849
|
+
const ghost = this.drag.blockDom.cloneNode(true);
|
|
6850
|
+
ghost.className = "ab-drag-ghost";
|
|
6851
|
+
ghost.style.cssText = `
|
|
6852
|
+
position: fixed;
|
|
6853
|
+
top: ${blockRect.top}px;
|
|
6854
|
+
left: ${blockRect.left}px;
|
|
6855
|
+
width: ${blockRect.width}px;
|
|
6856
|
+
opacity: 0.4;
|
|
6857
|
+
pointer-events: none;
|
|
6858
|
+
z-index: 9999;
|
|
6859
|
+
transition: none;
|
|
6860
|
+
`;
|
|
6861
|
+
document.body.appendChild(ghost);
|
|
6862
|
+
this.drag.ghost = ghost;
|
|
6863
|
+
this.drag._ghostOffsetY = this.drag.startY - blockRect.top;
|
|
6308
6864
|
const parent = this.view.dom.parentNode;
|
|
6309
6865
|
this.dropIndicator = document.createElement("div");
|
|
6310
6866
|
this.dropIndicator.className = "ab-drop-indicator";
|
|
@@ -6344,6 +6900,10 @@ var DragHandleController = class {
|
|
|
6344
6900
|
this.activateDrag();
|
|
6345
6901
|
}
|
|
6346
6902
|
this.drag.pointerY = e.clientY;
|
|
6903
|
+
if (this.drag.ghost) {
|
|
6904
|
+
const offsetY = this.drag._ghostOffsetY ?? 0;
|
|
6905
|
+
this.drag.ghost.style.top = `${e.clientY - offsetY}px`;
|
|
6906
|
+
}
|
|
6347
6907
|
this.updateDropTarget();
|
|
6348
6908
|
}
|
|
6349
6909
|
updateDropTarget() {
|
|
@@ -6415,6 +6975,10 @@ var DragHandleController = class {
|
|
|
6415
6975
|
this.cleaningUp = true;
|
|
6416
6976
|
this.drag.handle.classList.remove("dragging");
|
|
6417
6977
|
this.drag.blockDom.classList.remove("ab-block-dragging");
|
|
6978
|
+
if (this.drag.ghost) {
|
|
6979
|
+
this.drag.ghost.remove();
|
|
6980
|
+
this.drag.ghost = null;
|
|
6981
|
+
}
|
|
6418
6982
|
try {
|
|
6419
6983
|
this.drag.handle.releasePointerCapture(this.drag.pointerId);
|
|
6420
6984
|
} catch {
|
|
@@ -6620,6 +7184,55 @@ function createTodoNodeViewPlugin() {
|
|
|
6620
7184
|
};
|
|
6621
7185
|
}
|
|
6622
7186
|
|
|
7187
|
+
// src/ui/plugin/noteBlockPlugin.tsx
|
|
7188
|
+
var NoteBlockView = class {
|
|
7189
|
+
dom;
|
|
7190
|
+
contentDOM;
|
|
7191
|
+
constructor(_node, _view, _getPos) {
|
|
7192
|
+
this.dom = document.createElement("div");
|
|
7193
|
+
this.dom.setAttribute("data-note-block", "");
|
|
7194
|
+
this.dom.className = "ab-note-block";
|
|
7195
|
+
this.dom.style.cssText = `
|
|
7196
|
+
position: relative;
|
|
7197
|
+
margin: 8px 0;
|
|
7198
|
+
padding: 12px 16px 12px 16px;
|
|
7199
|
+
background: rgba(0, 0, 0, 0.015);
|
|
7200
|
+
border-top: 1px solid rgba(0, 0, 0, 0.08);
|
|
7201
|
+
color: #999;
|
|
7202
|
+
font-style: italic;
|
|
7203
|
+
`;
|
|
7204
|
+
const label = document.createElement("span");
|
|
7205
|
+
label.contentEditable = "false";
|
|
7206
|
+
label.textContent = "Note";
|
|
7207
|
+
label.style.cssText = `
|
|
7208
|
+
display: inline-block;
|
|
7209
|
+
font-size: 11px;
|
|
7210
|
+
font-weight: 600;
|
|
7211
|
+
font-style: normal;
|
|
7212
|
+
color: #aaa;
|
|
7213
|
+
background: rgba(0, 0, 0, 0.03);
|
|
7214
|
+
border: 1px solid rgba(0, 0, 0, 0.1);
|
|
7215
|
+
border-radius: 3px;
|
|
7216
|
+
padding: 1px 6px;
|
|
7217
|
+
margin-bottom: 6px;
|
|
7218
|
+
user-select: none;
|
|
7219
|
+
line-height: 1.4;
|
|
7220
|
+
`;
|
|
7221
|
+
this.dom.appendChild(label);
|
|
7222
|
+
this.contentDOM = document.createElement("div");
|
|
7223
|
+
this.contentDOM.className = "ab-note-block-content";
|
|
7224
|
+
this.dom.appendChild(this.contentDOM);
|
|
7225
|
+
}
|
|
7226
|
+
};
|
|
7227
|
+
function createNoteBlockPlugin() {
|
|
7228
|
+
return {
|
|
7229
|
+
name: "noteBlockNodeView",
|
|
7230
|
+
nodeViews: () => ({
|
|
7231
|
+
noteBlock: (node, view, getPos) => new NoteBlockView(node, view, getPos)
|
|
7232
|
+
})
|
|
7233
|
+
};
|
|
7234
|
+
}
|
|
7235
|
+
|
|
6623
7236
|
// src/ui/plugin/slashCommandPlugin.ts
|
|
6624
7237
|
import { Plugin as Plugin7, PluginKey as PluginKey7 } from "prosemirror-state";
|
|
6625
7238
|
var slashCommandKey = new PluginKey7("slashCommand");
|
|
@@ -6689,17 +7302,37 @@ function createSlashCommandPlugin() {
|
|
|
6689
7302
|
}
|
|
6690
7303
|
|
|
6691
7304
|
// src/ui/components/SlashCommandMenu.tsx
|
|
6692
|
-
import { useEffect as useEffect3, useRef as useRef3, useState as
|
|
7305
|
+
import React4, { useEffect as useEffect3, useLayoutEffect, useRef as useRef3, useState as useState4 } from "react";
|
|
6693
7306
|
import { createPortal } from "react-dom";
|
|
6694
|
-
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
7307
|
+
import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
6695
7308
|
function filterItems(items, query) {
|
|
6696
7309
|
if (!query) return items;
|
|
6697
|
-
const
|
|
6698
|
-
|
|
6699
|
-
|
|
7310
|
+
const colonIdx = query.indexOf(":");
|
|
7311
|
+
const searchPart = colonIdx >= 0 ? query.slice(colonIdx + 1).trim() : query;
|
|
7312
|
+
if (!searchPart) return items;
|
|
7313
|
+
const words = searchPart.toLowerCase().split(/\s+/);
|
|
7314
|
+
const filtered = items.filter(
|
|
7315
|
+
({ title, description }) => {
|
|
7316
|
+
const hay = (title + " " + (description ?? "")).toLowerCase();
|
|
7317
|
+
return words.every((w) => hay.includes(w));
|
|
7318
|
+
}
|
|
6700
7319
|
);
|
|
7320
|
+
return filtered.length > 0 ? filtered : items;
|
|
7321
|
+
}
|
|
7322
|
+
var SCROLLBAR_STYLE_ID = "ab-slash-menu-scrollbar";
|
|
7323
|
+
function injectScrollbarStyle() {
|
|
7324
|
+
if (document.getElementById(SCROLLBAR_STYLE_ID)) return;
|
|
7325
|
+
const style = document.createElement("style");
|
|
7326
|
+
style.id = SCROLLBAR_STYLE_ID;
|
|
7327
|
+
style.textContent = `
|
|
7328
|
+
.ab-slash-menu::-webkit-scrollbar { width: 6px; }
|
|
7329
|
+
.ab-slash-menu::-webkit-scrollbar-track { background: transparent; }
|
|
7330
|
+
.ab-slash-menu::-webkit-scrollbar-thumb { background: #c4c4c4; border-radius: 3px; }
|
|
7331
|
+
.ab-slash-menu::-webkit-scrollbar-thumb:hover { background: #999; }
|
|
7332
|
+
`;
|
|
7333
|
+
document.head.appendChild(style);
|
|
6701
7334
|
}
|
|
6702
|
-
var POPUP_SHADOW = "0
|
|
7335
|
+
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
7336
|
var BTN_RESET = {
|
|
6704
7337
|
border: "none",
|
|
6705
7338
|
padding: 0,
|
|
@@ -6712,11 +7345,14 @@ var BTN_RESET = {
|
|
|
6712
7345
|
width: "100%"
|
|
6713
7346
|
};
|
|
6714
7347
|
var VPORT_MARGIN = 8;
|
|
6715
|
-
var MENU_WIDTH =
|
|
6716
|
-
var MAX_MENU_H =
|
|
7348
|
+
var MENU_WIDTH = 440;
|
|
7349
|
+
var MAX_MENU_H = 400;
|
|
6717
7350
|
function SlashCommandMenu({ view, editorState, items }) {
|
|
6718
|
-
const [selectedIndex, setSelectedIndex] =
|
|
7351
|
+
const [selectedIndex, setSelectedIndex] = useState4(0);
|
|
6719
7352
|
const listRef = useRef3(null);
|
|
7353
|
+
useLayoutEffect(() => {
|
|
7354
|
+
injectScrollbarStyle();
|
|
7355
|
+
}, []);
|
|
6720
7356
|
const pluginState = editorState ? slashCommandKey.getState(editorState) : void 0;
|
|
6721
7357
|
const active = pluginState?.active ?? false;
|
|
6722
7358
|
const range = pluginState?.range ?? null;
|
|
@@ -6728,7 +7364,7 @@ function SlashCommandMenu({ view, editorState, items }) {
|
|
|
6728
7364
|
useEffect3(() => {
|
|
6729
7365
|
const list = listRef.current;
|
|
6730
7366
|
if (!list) return;
|
|
6731
|
-
const item = list.
|
|
7367
|
+
const item = list.querySelector(`[data-slash-index="${selectedIndex}"]`);
|
|
6732
7368
|
item?.scrollIntoView({ block: "nearest" });
|
|
6733
7369
|
}, [selectedIndex]);
|
|
6734
7370
|
useEffect3(() => {
|
|
@@ -6770,6 +7406,7 @@ function SlashCommandMenu({ view, editorState, items }) {
|
|
|
6770
7406
|
/* @__PURE__ */ jsx7(
|
|
6771
7407
|
"div",
|
|
6772
7408
|
{
|
|
7409
|
+
className: "ab-slash-menu",
|
|
6773
7410
|
style: {
|
|
6774
7411
|
position: "fixed",
|
|
6775
7412
|
top,
|
|
@@ -6777,10 +7414,12 @@ function SlashCommandMenu({ view, editorState, items }) {
|
|
|
6777
7414
|
width: MENU_WIDTH,
|
|
6778
7415
|
maxHeight: MAX_MENU_H,
|
|
6779
7416
|
overflowY: "auto",
|
|
7417
|
+
scrollbarWidth: "thin",
|
|
7418
|
+
scrollbarColor: "#c4c4c4 transparent",
|
|
6780
7419
|
background: "#fff",
|
|
6781
|
-
borderRadius:
|
|
7420
|
+
borderRadius: 4,
|
|
6782
7421
|
boxShadow: POPUP_SHADOW,
|
|
6783
|
-
padding:
|
|
7422
|
+
padding: "8px 0",
|
|
6784
7423
|
zIndex: 1100,
|
|
6785
7424
|
animation: "ab-float-in 0.12s ease"
|
|
6786
7425
|
},
|
|
@@ -6794,100 +7433,103 @@ function SlashCommandMenu({ view, editorState, items }) {
|
|
|
6794
7433
|
},
|
|
6795
7434
|
children: "No results"
|
|
6796
7435
|
}
|
|
6797
|
-
) : filtered.map((item, i) =>
|
|
6798
|
-
|
|
6799
|
-
|
|
6800
|
-
|
|
6801
|
-
|
|
6802
|
-
|
|
6803
|
-
|
|
6804
|
-
|
|
6805
|
-
|
|
6806
|
-
|
|
6807
|
-
|
|
7436
|
+
) : filtered.map((item, i) => {
|
|
7437
|
+
const prevGroup = i > 0 ? filtered[i - 1].group : void 0;
|
|
7438
|
+
const showGroupHeader = item.group && item.group !== prevGroup;
|
|
7439
|
+
return /* @__PURE__ */ jsxs6(React4.Fragment, { children: [
|
|
7440
|
+
showGroupHeader && /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
7441
|
+
i > 0 && /* @__PURE__ */ jsx7("div", { style: { height: 1, background: "rgba(0,0,0,0.06)", margin: "4px 10px" } }),
|
|
7442
|
+
/* @__PURE__ */ jsx7(
|
|
7443
|
+
"div",
|
|
7444
|
+
{
|
|
7445
|
+
style: {
|
|
7446
|
+
padding: "8px 16px 4px",
|
|
7447
|
+
fontSize: 13,
|
|
7448
|
+
fontWeight: 400,
|
|
7449
|
+
color: "#5e5e5e"
|
|
7450
|
+
},
|
|
7451
|
+
children: item.group
|
|
7452
|
+
}
|
|
7453
|
+
)
|
|
7454
|
+
] }),
|
|
7455
|
+
/* @__PURE__ */ jsx7(
|
|
7456
|
+
SlashMenuItem,
|
|
7457
|
+
{
|
|
7458
|
+
item,
|
|
7459
|
+
index: i,
|
|
7460
|
+
selected: i === selectedIndex,
|
|
7461
|
+
onMouseEnter: () => setSelectedIndex(i),
|
|
7462
|
+
onMouseDown: (e) => {
|
|
7463
|
+
e.preventDefault();
|
|
7464
|
+
if (range) {
|
|
7465
|
+
item.command({ view, range });
|
|
7466
|
+
view.focus();
|
|
7467
|
+
}
|
|
7468
|
+
}
|
|
6808
7469
|
}
|
|
6809
|
-
|
|
6810
|
-
},
|
|
6811
|
-
|
|
6812
|
-
)) })
|
|
7470
|
+
)
|
|
7471
|
+
] }, item.id ?? item.title);
|
|
7472
|
+
}) })
|
|
6813
7473
|
}
|
|
6814
7474
|
),
|
|
6815
7475
|
document.body
|
|
6816
7476
|
);
|
|
6817
7477
|
}
|
|
6818
|
-
function SlashMenuItem({ item, selected, onMouseEnter, onMouseDown }) {
|
|
7478
|
+
function SlashMenuItem({ item, index, selected, onMouseEnter, onMouseDown }) {
|
|
6819
7479
|
return /* @__PURE__ */ jsxs6(
|
|
6820
7480
|
"button",
|
|
6821
7481
|
{
|
|
7482
|
+
"data-slash-index": index,
|
|
6822
7483
|
style: {
|
|
6823
7484
|
...BTN_RESET,
|
|
6824
7485
|
display: "flex",
|
|
6825
7486
|
alignItems: "center",
|
|
6826
|
-
gap:
|
|
6827
|
-
padding: "
|
|
6828
|
-
|
|
6829
|
-
background: selected ? "rgba(99,102,241,0.07)" : "transparent",
|
|
7487
|
+
gap: 12,
|
|
7488
|
+
padding: "6px 16px",
|
|
7489
|
+
background: selected ? "rgba(13,13,13,0.04)" : "transparent",
|
|
6830
7490
|
transition: "background 0.08s"
|
|
6831
7491
|
},
|
|
6832
7492
|
onMouseEnter,
|
|
6833
7493
|
onMouseDown,
|
|
6834
7494
|
children: [
|
|
6835
|
-
item.icon !== void 0 && /* @__PURE__ */ jsx7(
|
|
7495
|
+
item.icon !== void 0 && /* @__PURE__ */ jsx7("span", { style: { flexShrink: 0, display: "flex", alignItems: "center" }, children: item.icon }),
|
|
7496
|
+
/* @__PURE__ */ jsx7(
|
|
6836
7497
|
"span",
|
|
6837
7498
|
{
|
|
6838
7499
|
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"
|
|
7500
|
+
fontSize: 14,
|
|
7501
|
+
fontWeight: 400,
|
|
7502
|
+
color: "#0d0d0d",
|
|
7503
|
+
whiteSpace: "nowrap",
|
|
7504
|
+
overflow: "hidden",
|
|
7505
|
+
textOverflow: "ellipsis",
|
|
7506
|
+
minWidth: 0
|
|
6851
7507
|
},
|
|
6852
|
-
children: item.
|
|
7508
|
+
children: item.title
|
|
6853
7509
|
}
|
|
6854
7510
|
),
|
|
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
|
-
] })
|
|
7511
|
+
/* @__PURE__ */ jsx7("span", { style: { flex: 1 } }),
|
|
7512
|
+
(item.description || item.shortcut) && /* @__PURE__ */ jsx7(
|
|
7513
|
+
"span",
|
|
7514
|
+
{
|
|
7515
|
+
style: {
|
|
7516
|
+
fontSize: 12,
|
|
7517
|
+
color: "#5e5e5e",
|
|
7518
|
+
whiteSpace: "nowrap",
|
|
7519
|
+
flexShrink: 0,
|
|
7520
|
+
textAlign: "right",
|
|
7521
|
+
fontFamily: item.shortcut ? "monospace" : "inherit"
|
|
7522
|
+
},
|
|
7523
|
+
children: item.shortcut ?? item.description
|
|
7524
|
+
}
|
|
7525
|
+
)
|
|
6884
7526
|
]
|
|
6885
7527
|
}
|
|
6886
7528
|
);
|
|
6887
7529
|
}
|
|
6888
7530
|
|
|
6889
7531
|
// src/ui/components/JinjaTreeView.tsx
|
|
6890
|
-
import { useState as
|
|
7532
|
+
import { useState as useState5 } from "react";
|
|
6891
7533
|
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
6892
7534
|
var BRANCH_COLORS = {
|
|
6893
7535
|
if: "#6366f1",
|
|
@@ -6932,7 +7574,7 @@ function BranchNode({
|
|
|
6932
7574
|
] });
|
|
6933
7575
|
}
|
|
6934
7576
|
function StructureNode({ structure, doc: doc2 }) {
|
|
6935
|
-
const [expanded, setExpanded] =
|
|
7577
|
+
const [expanded, setExpanded] = useState5(true);
|
|
6936
7578
|
const firstBranch = structure.branches[0];
|
|
6937
7579
|
const label = firstBranch?.condition ? `if ${firstBranch.condition}` : "if";
|
|
6938
7580
|
return /* @__PURE__ */ jsxs7("div", { className: "jinja-tree-structure", children: [
|
|
@@ -6965,13 +7607,179 @@ function JinjaTreeView({ doc: doc2, className }) {
|
|
|
6965
7607
|
return /* @__PURE__ */ jsx8("div", { className: `jinja-tree ${className || ""}`, children: structures.map((structure) => /* @__PURE__ */ jsx8(StructureNode, { structure, doc: doc2 }, structure.id)) });
|
|
6966
7608
|
}
|
|
6967
7609
|
|
|
7610
|
+
// src/ui/components/DocumentTreeView.tsx
|
|
7611
|
+
import { useState as useState6 } from "react";
|
|
7612
|
+
import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
7613
|
+
var ICONS = {
|
|
7614
|
+
heading: "H",
|
|
7615
|
+
jumpPoint: "\u2299",
|
|
7616
|
+
jinjaIf: "\u2325",
|
|
7617
|
+
jinjaBranch: "\u2387",
|
|
7618
|
+
resourceTag: "\u229B",
|
|
7619
|
+
noteBlock: "\u270D",
|
|
7620
|
+
endAction: "\u2192"
|
|
7621
|
+
};
|
|
7622
|
+
var COLORS = {
|
|
7623
|
+
heading: "#333",
|
|
7624
|
+
jumpPoint: "#d97706",
|
|
7625
|
+
jinjaIf: "#6366f1",
|
|
7626
|
+
jinjaBranch: "#8b5cf6",
|
|
7627
|
+
resourceTag: "#059669",
|
|
7628
|
+
noteBlock: "#999",
|
|
7629
|
+
endAction: "#059669"
|
|
7630
|
+
};
|
|
7631
|
+
function TreeNodeItem({
|
|
7632
|
+
node,
|
|
7633
|
+
onNavigate,
|
|
7634
|
+
depth,
|
|
7635
|
+
selectedPath,
|
|
7636
|
+
onSelect,
|
|
7637
|
+
path
|
|
7638
|
+
}) {
|
|
7639
|
+
const [collapsed, setCollapsed] = useState6(false);
|
|
7640
|
+
const hasChildren = node.children.length > 0;
|
|
7641
|
+
const icon = ICONS[node.type] || "\u2022";
|
|
7642
|
+
const color = COLORS[node.type] || "#666";
|
|
7643
|
+
const isSelected = selectedPath === path;
|
|
7644
|
+
const headingLevel = node.meta?.level;
|
|
7645
|
+
const headingLabel = headingLevel ? `H${headingLevel}` : icon;
|
|
7646
|
+
return /* @__PURE__ */ jsxs8("div", { style: { paddingLeft: depth > 0 ? 16 : 0 }, children: [
|
|
7647
|
+
/* @__PURE__ */ jsxs8(
|
|
7648
|
+
"div",
|
|
7649
|
+
{
|
|
7650
|
+
className: "doc-tree-node",
|
|
7651
|
+
style: {
|
|
7652
|
+
display: "flex",
|
|
7653
|
+
alignItems: "center",
|
|
7654
|
+
gap: 6,
|
|
7655
|
+
padding: "3px 6px",
|
|
7656
|
+
borderRadius: 4,
|
|
7657
|
+
cursor: onNavigate ? "pointer" : "default",
|
|
7658
|
+
fontSize: 13,
|
|
7659
|
+
lineHeight: "1.5",
|
|
7660
|
+
background: isSelected ? "rgba(99, 102, 241, 0.1)" : "transparent",
|
|
7661
|
+
transition: "background 0.12s ease"
|
|
7662
|
+
},
|
|
7663
|
+
onClick: (e) => {
|
|
7664
|
+
e.stopPropagation();
|
|
7665
|
+
if (hasChildren) setCollapsed(!collapsed);
|
|
7666
|
+
onSelect(path);
|
|
7667
|
+
onNavigate?.(node.blockIndex);
|
|
7668
|
+
},
|
|
7669
|
+
onMouseEnter: (e) => {
|
|
7670
|
+
if (!isSelected) e.currentTarget.style.background = "#f3f4f6";
|
|
7671
|
+
},
|
|
7672
|
+
onMouseLeave: (e) => {
|
|
7673
|
+
if (!isSelected) e.currentTarget.style.background = "transparent";
|
|
7674
|
+
},
|
|
7675
|
+
children: [
|
|
7676
|
+
hasChildren && /* @__PURE__ */ jsx9(
|
|
7677
|
+
"span",
|
|
7678
|
+
{
|
|
7679
|
+
style: {
|
|
7680
|
+
width: 14,
|
|
7681
|
+
textAlign: "center",
|
|
7682
|
+
fontSize: 10,
|
|
7683
|
+
color: "#999",
|
|
7684
|
+
flexShrink: 0,
|
|
7685
|
+
userSelect: "none"
|
|
7686
|
+
},
|
|
7687
|
+
children: collapsed ? "\u25B8" : "\u25BE"
|
|
7688
|
+
}
|
|
7689
|
+
),
|
|
7690
|
+
!hasChildren && /* @__PURE__ */ jsx9("span", { style: { width: 14, flexShrink: 0 } }),
|
|
7691
|
+
/* @__PURE__ */ jsx9(
|
|
7692
|
+
"span",
|
|
7693
|
+
{
|
|
7694
|
+
style: {
|
|
7695
|
+
display: "inline-flex",
|
|
7696
|
+
alignItems: "center",
|
|
7697
|
+
justifyContent: "center",
|
|
7698
|
+
width: 22,
|
|
7699
|
+
height: 18,
|
|
7700
|
+
borderRadius: 3,
|
|
7701
|
+
fontSize: 10,
|
|
7702
|
+
fontWeight: 700,
|
|
7703
|
+
color: isSelected ? "#6366f1" : color,
|
|
7704
|
+
background: isSelected ? "rgba(99, 102, 241, 0.15)" : `${color}11`,
|
|
7705
|
+
border: `1px solid ${isSelected ? "rgba(99, 102, 241, 0.3)" : `${color}33`}`,
|
|
7706
|
+
flexShrink: 0
|
|
7707
|
+
},
|
|
7708
|
+
children: node.type === "heading" ? headingLabel : icon
|
|
7709
|
+
}
|
|
7710
|
+
),
|
|
7711
|
+
/* @__PURE__ */ jsx9(
|
|
7712
|
+
"span",
|
|
7713
|
+
{
|
|
7714
|
+
style: {
|
|
7715
|
+
overflow: "hidden",
|
|
7716
|
+
textOverflow: "ellipsis",
|
|
7717
|
+
whiteSpace: "nowrap",
|
|
7718
|
+
color: isSelected ? "#6366f1" : node.type === "noteBlock" ? "#999" : node.type === "endAction" ? "#059669" : "#333",
|
|
7719
|
+
fontStyle: node.type === "noteBlock" ? "italic" : "normal",
|
|
7720
|
+
fontWeight: isSelected ? 600 : node.type === "heading" && headingLevel && headingLevel <= 2 ? 600 : 400
|
|
7721
|
+
},
|
|
7722
|
+
children: node.label
|
|
7723
|
+
}
|
|
7724
|
+
),
|
|
7725
|
+
node.meta?.tagType != null && /* @__PURE__ */ jsx9(
|
|
7726
|
+
"span",
|
|
7727
|
+
{
|
|
7728
|
+
style: {
|
|
7729
|
+
fontSize: 10,
|
|
7730
|
+
padding: "1px 5px",
|
|
7731
|
+
borderRadius: 999,
|
|
7732
|
+
background: node.type === "endAction" ? "rgba(5, 150, 105, 0.1)" : "rgba(0, 0, 0, 0.04)",
|
|
7733
|
+
color: node.type === "endAction" ? "#059669" : "#999",
|
|
7734
|
+
fontWeight: 500
|
|
7735
|
+
},
|
|
7736
|
+
children: String(node.meta.tagType)
|
|
7737
|
+
}
|
|
7738
|
+
)
|
|
7739
|
+
]
|
|
7740
|
+
}
|
|
7741
|
+
),
|
|
7742
|
+
hasChildren && !collapsed && /* @__PURE__ */ jsx9("div", { children: node.children.map((child, i) => /* @__PURE__ */ jsx9(
|
|
7743
|
+
TreeNodeItem,
|
|
7744
|
+
{
|
|
7745
|
+
node: child,
|
|
7746
|
+
onNavigate,
|
|
7747
|
+
depth: depth + 1,
|
|
7748
|
+
selectedPath,
|
|
7749
|
+
onSelect,
|
|
7750
|
+
path: `${path}/${i}`
|
|
7751
|
+
},
|
|
7752
|
+
`${child.type}-${child.blockIndex}-${i}`
|
|
7753
|
+
)) })
|
|
7754
|
+
] });
|
|
7755
|
+
}
|
|
7756
|
+
function DocumentTreeView({ doc: doc2, className, onNavigate }) {
|
|
7757
|
+
const tree = buildDocumentTree(doc2);
|
|
7758
|
+
const [selectedPath, setSelectedPath] = useState6(null);
|
|
7759
|
+
if (tree.length === 0) {
|
|
7760
|
+
return /* @__PURE__ */ jsx9("div", { className, style: { color: "#999", fontSize: 13, padding: 16 }, children: "No document structure to display." });
|
|
7761
|
+
}
|
|
7762
|
+
return /* @__PURE__ */ jsx9("div", { className, style: { padding: "8px 0", fontFamily: "Inter, sans-serif" }, children: tree.map((node, i) => /* @__PURE__ */ jsx9(
|
|
7763
|
+
TreeNodeItem,
|
|
7764
|
+
{
|
|
7765
|
+
node,
|
|
7766
|
+
onNavigate,
|
|
7767
|
+
depth: 0,
|
|
7768
|
+
selectedPath,
|
|
7769
|
+
onSelect: setSelectedPath,
|
|
7770
|
+
path: `${i}`
|
|
7771
|
+
},
|
|
7772
|
+
`${node.type}-${node.blockIndex}-${i}`
|
|
7773
|
+
)) });
|
|
7774
|
+
}
|
|
7775
|
+
|
|
6968
7776
|
// src/ui/components/FloatingMenu.tsx
|
|
6969
|
-
import { useCallback as
|
|
7777
|
+
import { useCallback as useCallback3, useEffect as useEffect4, useRef as useRef4, useState as useState7 } from "react";
|
|
6970
7778
|
import { createPortal as createPortal2 } from "react-dom";
|
|
6971
|
-
import { setBlockType, toggleMark as toggleMark2, wrapIn } from "prosemirror-commands";
|
|
7779
|
+
import { setBlockType as setBlockType2, toggleMark as toggleMark2, wrapIn } from "prosemirror-commands";
|
|
6972
7780
|
import { wrapInList as wrapInList2 } from "prosemirror-schema-list";
|
|
6973
|
-
import { Fragment as
|
|
6974
|
-
var { paragraph:
|
|
7781
|
+
import { Fragment as Fragment4, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
7782
|
+
var { paragraph: paragraph3, heading: heading3, bulletList: bulletList3, orderedList: orderedList3, blockquote: blockquote3 } = actionbookSchema.nodes;
|
|
6975
7783
|
var {
|
|
6976
7784
|
bold: bold2,
|
|
6977
7785
|
italic: italic2,
|
|
@@ -6993,7 +7801,7 @@ function hasMark(state, type) {
|
|
|
6993
7801
|
function activeHeadingLevel(state) {
|
|
6994
7802
|
const { $from } = state.selection;
|
|
6995
7803
|
const node = $from.parent;
|
|
6996
|
-
if (node.type ===
|
|
7804
|
+
if (node.type === heading3) return node.attrs.level;
|
|
6997
7805
|
return null;
|
|
6998
7806
|
}
|
|
6999
7807
|
function activeListType(state) {
|
|
@@ -7027,7 +7835,7 @@ function currentBlockLabel(state) {
|
|
|
7027
7835
|
if (lt === "ordered") return "1. List";
|
|
7028
7836
|
const { $from } = state.selection;
|
|
7029
7837
|
for (let d = $from.depth; d > 0; d--) {
|
|
7030
|
-
if ($from.node(d).type ===
|
|
7838
|
+
if ($from.node(d).type === blockquote3) return "Quote";
|
|
7031
7839
|
}
|
|
7032
7840
|
return "Text";
|
|
7033
7841
|
}
|
|
@@ -7036,7 +7844,7 @@ function emptyBlockCursorPos(state) {
|
|
|
7036
7844
|
if (!selection.empty) return null;
|
|
7037
7845
|
const { $from } = selection;
|
|
7038
7846
|
const parent = $from.parent;
|
|
7039
|
-
if ((parent.type ===
|
|
7847
|
+
if ((parent.type === paragraph3 || parent.type === heading3) && parent.content.size === 0) {
|
|
7040
7848
|
return selection.from;
|
|
7041
7849
|
}
|
|
7042
7850
|
return null;
|
|
@@ -7058,8 +7866,8 @@ var BTN_RESET2 = {
|
|
|
7058
7866
|
lineHeight: 1
|
|
7059
7867
|
};
|
|
7060
7868
|
function TBtn({ children, active, title, onMouseDown, style }) {
|
|
7061
|
-
const [hover, setHover] =
|
|
7062
|
-
return /* @__PURE__ */
|
|
7869
|
+
const [hover, setHover] = useState7(false);
|
|
7870
|
+
return /* @__PURE__ */ jsx10(
|
|
7063
7871
|
"button",
|
|
7064
7872
|
{
|
|
7065
7873
|
...{ [FLOAT_ATTR]: "" },
|
|
@@ -7090,12 +7898,12 @@ function TBtn({ children, active, title, onMouseDown, style }) {
|
|
|
7090
7898
|
);
|
|
7091
7899
|
}
|
|
7092
7900
|
function Divider() {
|
|
7093
|
-
return /* @__PURE__ */
|
|
7901
|
+
return /* @__PURE__ */ jsx10("div", { style: { width: 1, height: 18, background: "rgba(0,0,0,0.07)", margin: "0 2px", flexShrink: 0 } });
|
|
7094
7902
|
}
|
|
7095
7903
|
function BlockTypeDropdown({ view, state, label }) {
|
|
7096
|
-
const [open, setOpen] =
|
|
7904
|
+
const [open, setOpen] = useState7(false);
|
|
7097
7905
|
const btnRef = useRef4(null);
|
|
7098
|
-
const [hover, setHover] =
|
|
7906
|
+
const [hover, setHover] = useState7(false);
|
|
7099
7907
|
useEffect4(() => {
|
|
7100
7908
|
if (!open) return;
|
|
7101
7909
|
const onDown = (e) => {
|
|
@@ -7110,19 +7918,19 @@ function BlockTypeDropdown({ view, state, label }) {
|
|
|
7110
7918
|
const listType = activeListType(state);
|
|
7111
7919
|
const items = [
|
|
7112
7920
|
{ label: "Text", shortLabel: "\xB6", active: !headingLevel && !listType, run: () => {
|
|
7113
|
-
|
|
7921
|
+
setBlockType2(paragraph3)(view.state, view.dispatch);
|
|
7114
7922
|
view.focus();
|
|
7115
7923
|
} },
|
|
7116
7924
|
{ label: "Heading 1", shortLabel: "H1", active: headingLevel === 1, run: () => {
|
|
7117
|
-
|
|
7925
|
+
setBlockType2(heading3, { level: 1 })(view.state, view.dispatch);
|
|
7118
7926
|
view.focus();
|
|
7119
7927
|
} },
|
|
7120
7928
|
{ label: "Heading 2", shortLabel: "H2", active: headingLevel === 2, run: () => {
|
|
7121
|
-
|
|
7929
|
+
setBlockType2(heading3, { level: 2 })(view.state, view.dispatch);
|
|
7122
7930
|
view.focus();
|
|
7123
7931
|
} },
|
|
7124
7932
|
{ label: "Heading 3", shortLabel: "H3", active: headingLevel === 3, run: () => {
|
|
7125
|
-
|
|
7933
|
+
setBlockType2(heading3, { level: 3 })(view.state, view.dispatch);
|
|
7126
7934
|
view.focus();
|
|
7127
7935
|
} },
|
|
7128
7936
|
{ label: "Bullet List", shortLabel: "\u2022", active: listType === "bullet", run: () => {
|
|
@@ -7144,13 +7952,17 @@ function BlockTypeDropdown({ view, state, label }) {
|
|
|
7144
7952
|
view.focus();
|
|
7145
7953
|
} },
|
|
7146
7954
|
{ label: "Quote", shortLabel: ">", active: false, run: () => {
|
|
7147
|
-
|
|
7955
|
+
const { $from } = view.state.selection;
|
|
7956
|
+
for (let d = $from.depth; d > 0; d--) {
|
|
7957
|
+
if ($from.node(d).type.name === "listItem") return;
|
|
7958
|
+
}
|
|
7959
|
+
wrapIn(blockquote3)(view.state, view.dispatch);
|
|
7148
7960
|
view.focus();
|
|
7149
7961
|
} }
|
|
7150
7962
|
];
|
|
7151
7963
|
const btnRect = btnRef.current?.getBoundingClientRect();
|
|
7152
|
-
return /* @__PURE__ */
|
|
7153
|
-
/* @__PURE__ */
|
|
7964
|
+
return /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
7965
|
+
/* @__PURE__ */ jsxs9(
|
|
7154
7966
|
"button",
|
|
7155
7967
|
{
|
|
7156
7968
|
ref: btnRef,
|
|
@@ -7178,12 +7990,12 @@ function BlockTypeDropdown({ view, state, label }) {
|
|
|
7178
7990
|
},
|
|
7179
7991
|
children: [
|
|
7180
7992
|
label,
|
|
7181
|
-
/* @__PURE__ */
|
|
7993
|
+
/* @__PURE__ */ jsx10("span", { style: { fontSize: 8, opacity: 0.6 }, children: "\u25BE" })
|
|
7182
7994
|
]
|
|
7183
7995
|
}
|
|
7184
7996
|
),
|
|
7185
7997
|
open && btnRect && createPortal2(
|
|
7186
|
-
/* @__PURE__ */
|
|
7998
|
+
/* @__PURE__ */ jsx10(
|
|
7187
7999
|
"div",
|
|
7188
8000
|
{
|
|
7189
8001
|
...{ [FLOAT_ATTR]: "" },
|
|
@@ -7199,7 +8011,7 @@ function BlockTypeDropdown({ view, state, label }) {
|
|
|
7199
8011
|
minWidth: 168,
|
|
7200
8012
|
animation: "ab-float-in 0.12s ease"
|
|
7201
8013
|
},
|
|
7202
|
-
children: items.map((item) => /* @__PURE__ */
|
|
8014
|
+
children: items.map((item) => /* @__PURE__ */ jsx10(DropdownItem, { item, onRun: () => setOpen(false) }, item.label))
|
|
7203
8015
|
}
|
|
7204
8016
|
),
|
|
7205
8017
|
document.body
|
|
@@ -7207,8 +8019,8 @@ function BlockTypeDropdown({ view, state, label }) {
|
|
|
7207
8019
|
] });
|
|
7208
8020
|
}
|
|
7209
8021
|
function DropdownItem({ item, onRun }) {
|
|
7210
|
-
const [hover, setHover] =
|
|
7211
|
-
return /* @__PURE__ */
|
|
8022
|
+
const [hover, setHover] = useState7(false);
|
|
8023
|
+
return /* @__PURE__ */ jsxs9(
|
|
7212
8024
|
"button",
|
|
7213
8025
|
{
|
|
7214
8026
|
...{ [FLOAT_ATTR]: "" },
|
|
@@ -7235,15 +8047,15 @@ function DropdownItem({ item, onRun }) {
|
|
|
7235
8047
|
transition: "background 0.1s"
|
|
7236
8048
|
},
|
|
7237
8049
|
children: [
|
|
7238
|
-
/* @__PURE__ */
|
|
8050
|
+
/* @__PURE__ */ jsx10("span", { style: { width: 24, flexShrink: 0, textAlign: "center", fontWeight: 700, fontSize: 12, fontFamily: "monospace", color: "#6366f1" }, children: item.shortLabel }),
|
|
7239
8051
|
item.label
|
|
7240
8052
|
]
|
|
7241
8053
|
}
|
|
7242
8054
|
);
|
|
7243
8055
|
}
|
|
7244
8056
|
function SelectionToolbar({ view, state, selectionRect }) {
|
|
7245
|
-
const [linkMode, setLinkMode] =
|
|
7246
|
-
const [linkHref, setLinkHref] =
|
|
8057
|
+
const [linkMode, setLinkMode] = useState7(false);
|
|
8058
|
+
const [linkHref, setLinkHref] = useState7("");
|
|
7247
8059
|
const inputRef = useRef4(null);
|
|
7248
8060
|
const isBold = hasMark(state, bold2);
|
|
7249
8061
|
const isItalic = hasMark(state, italic2);
|
|
@@ -7259,7 +8071,7 @@ function SelectionToolbar({ view, state, selectionRect }) {
|
|
|
7259
8071
|
if (top < VPORT_MARGIN2) top = selectionRect.bottom + TOOLBAR_GAP;
|
|
7260
8072
|
left = Math.max(VPORT_MARGIN2, Math.min(left, window.innerWidth - toolbarW - VPORT_MARGIN2));
|
|
7261
8073
|
top = Math.max(VPORT_MARGIN2, Math.min(top, window.innerHeight - toolbarH - VPORT_MARGIN2));
|
|
7262
|
-
const run =
|
|
8074
|
+
const run = useCallback3(
|
|
7263
8075
|
(cmd) => {
|
|
7264
8076
|
cmd(view.state, view.dispatch);
|
|
7265
8077
|
view.focus();
|
|
@@ -7296,10 +8108,10 @@ function SelectionToolbar({ view, state, selectionRect }) {
|
|
|
7296
8108
|
view.dispatch(view.state.tr.removeMark(from, to, linkMark));
|
|
7297
8109
|
view.focus();
|
|
7298
8110
|
};
|
|
7299
|
-
return /* @__PURE__ */
|
|
8111
|
+
return /* @__PURE__ */ jsx10(
|
|
7300
8112
|
"div",
|
|
7301
8113
|
{
|
|
7302
|
-
...{ [FLOAT_ATTR]: "" },
|
|
8114
|
+
...{ [FLOAT_ATTR]: "selection-toolbar" },
|
|
7303
8115
|
style: {
|
|
7304
8116
|
position: "fixed",
|
|
7305
8117
|
left,
|
|
@@ -7319,9 +8131,9 @@ function SelectionToolbar({ view, state, selectionRect }) {
|
|
|
7319
8131
|
},
|
|
7320
8132
|
children: linkMode ? (
|
|
7321
8133
|
/* ── Link input mode ── */
|
|
7322
|
-
/* @__PURE__ */
|
|
7323
|
-
/* @__PURE__ */
|
|
7324
|
-
/* @__PURE__ */
|
|
8134
|
+
/* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
8135
|
+
/* @__PURE__ */ jsx10("span", { style: { fontSize: 13, color: "#9ca3af", paddingLeft: 4, flexShrink: 0 }, children: "\u2197" }),
|
|
8136
|
+
/* @__PURE__ */ jsx10(
|
|
7325
8137
|
"input",
|
|
7326
8138
|
{
|
|
7327
8139
|
ref: inputRef,
|
|
@@ -7352,7 +8164,7 @@ function SelectionToolbar({ view, state, selectionRect }) {
|
|
|
7352
8164
|
}
|
|
7353
8165
|
}
|
|
7354
8166
|
),
|
|
7355
|
-
/* @__PURE__ */
|
|
8167
|
+
/* @__PURE__ */ jsx10(
|
|
7356
8168
|
TBtn,
|
|
7357
8169
|
{
|
|
7358
8170
|
title: "Apply (Enter)",
|
|
@@ -7364,7 +8176,7 @@ function SelectionToolbar({ view, state, selectionRect }) {
|
|
|
7364
8176
|
children: "\u21B5"
|
|
7365
8177
|
}
|
|
7366
8178
|
),
|
|
7367
|
-
/* @__PURE__ */
|
|
8179
|
+
/* @__PURE__ */ jsx10(
|
|
7368
8180
|
TBtn,
|
|
7369
8181
|
{
|
|
7370
8182
|
title: "Cancel (Esc)",
|
|
@@ -7380,8 +8192,8 @@ function SelectionToolbar({ view, state, selectionRect }) {
|
|
|
7380
8192
|
] })
|
|
7381
8193
|
) : (
|
|
7382
8194
|
/* ── Normal toolbar mode ── */
|
|
7383
|
-
/* @__PURE__ */
|
|
7384
|
-
/* @__PURE__ */
|
|
8195
|
+
/* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
8196
|
+
/* @__PURE__ */ jsx10(
|
|
7385
8197
|
TBtn,
|
|
7386
8198
|
{
|
|
7387
8199
|
active: isBold,
|
|
@@ -7391,7 +8203,7 @@ function SelectionToolbar({ view, state, selectionRect }) {
|
|
|
7391
8203
|
children: "B"
|
|
7392
8204
|
}
|
|
7393
8205
|
),
|
|
7394
|
-
/* @__PURE__ */
|
|
8206
|
+
/* @__PURE__ */ jsx10(
|
|
7395
8207
|
TBtn,
|
|
7396
8208
|
{
|
|
7397
8209
|
active: isItalic,
|
|
@@ -7401,7 +8213,7 @@ function SelectionToolbar({ view, state, selectionRect }) {
|
|
|
7401
8213
|
children: "I"
|
|
7402
8214
|
}
|
|
7403
8215
|
),
|
|
7404
|
-
/* @__PURE__ */
|
|
8216
|
+
/* @__PURE__ */ jsx10(
|
|
7405
8217
|
TBtn,
|
|
7406
8218
|
{
|
|
7407
8219
|
active: isUnderline,
|
|
@@ -7411,7 +8223,7 @@ function SelectionToolbar({ view, state, selectionRect }) {
|
|
|
7411
8223
|
children: "U"
|
|
7412
8224
|
}
|
|
7413
8225
|
),
|
|
7414
|
-
/* @__PURE__ */
|
|
8226
|
+
/* @__PURE__ */ jsx10(
|
|
7415
8227
|
TBtn,
|
|
7416
8228
|
{
|
|
7417
8229
|
active: isStrike,
|
|
@@ -7421,7 +8233,7 @@ function SelectionToolbar({ view, state, selectionRect }) {
|
|
|
7421
8233
|
children: "S"
|
|
7422
8234
|
}
|
|
7423
8235
|
),
|
|
7424
|
-
/* @__PURE__ */
|
|
8236
|
+
/* @__PURE__ */ jsx10(
|
|
7425
8237
|
TBtn,
|
|
7426
8238
|
{
|
|
7427
8239
|
active: isCode,
|
|
@@ -7431,7 +8243,7 @@ function SelectionToolbar({ view, state, selectionRect }) {
|
|
|
7431
8243
|
children: "`\xB7`"
|
|
7432
8244
|
}
|
|
7433
8245
|
),
|
|
7434
|
-
/* @__PURE__ */
|
|
8246
|
+
/* @__PURE__ */ jsx10(
|
|
7435
8247
|
TBtn,
|
|
7436
8248
|
{
|
|
7437
8249
|
active: isLink,
|
|
@@ -7441,8 +8253,8 @@ function SelectionToolbar({ view, state, selectionRect }) {
|
|
|
7441
8253
|
children: "\u2197"
|
|
7442
8254
|
}
|
|
7443
8255
|
),
|
|
7444
|
-
/* @__PURE__ */
|
|
7445
|
-
/* @__PURE__ */
|
|
8256
|
+
/* @__PURE__ */ jsx10(Divider, {}),
|
|
8257
|
+
/* @__PURE__ */ jsx10(BlockTypeDropdown, { view, state, label: blockLabel })
|
|
7446
8258
|
] })
|
|
7447
8259
|
)
|
|
7448
8260
|
}
|
|
@@ -7453,7 +8265,7 @@ var BLOCK_ITEMS = [
|
|
|
7453
8265
|
shortLabel: "\xB6",
|
|
7454
8266
|
label: "Text",
|
|
7455
8267
|
run: (v) => {
|
|
7456
|
-
|
|
8268
|
+
setBlockType2(paragraph3)(v.state, v.dispatch);
|
|
7457
8269
|
v.focus();
|
|
7458
8270
|
}
|
|
7459
8271
|
},
|
|
@@ -7461,7 +8273,7 @@ var BLOCK_ITEMS = [
|
|
|
7461
8273
|
shortLabel: "H1",
|
|
7462
8274
|
label: "Heading 1",
|
|
7463
8275
|
run: (v) => {
|
|
7464
|
-
|
|
8276
|
+
setBlockType2(heading3, { level: 1 })(v.state, v.dispatch);
|
|
7465
8277
|
v.focus();
|
|
7466
8278
|
}
|
|
7467
8279
|
},
|
|
@@ -7469,7 +8281,7 @@ var BLOCK_ITEMS = [
|
|
|
7469
8281
|
shortLabel: "H2",
|
|
7470
8282
|
label: "Heading 2",
|
|
7471
8283
|
run: (v) => {
|
|
7472
|
-
|
|
8284
|
+
setBlockType2(heading3, { level: 2 })(v.state, v.dispatch);
|
|
7473
8285
|
v.focus();
|
|
7474
8286
|
}
|
|
7475
8287
|
},
|
|
@@ -7477,7 +8289,7 @@ var BLOCK_ITEMS = [
|
|
|
7477
8289
|
shortLabel: "H3",
|
|
7478
8290
|
label: "Heading 3",
|
|
7479
8291
|
run: (v) => {
|
|
7480
|
-
|
|
8292
|
+
setBlockType2(heading3, { level: 3 })(v.state, v.dispatch);
|
|
7481
8293
|
v.focus();
|
|
7482
8294
|
}
|
|
7483
8295
|
},
|
|
@@ -7512,7 +8324,7 @@ var BLOCK_ITEMS = [
|
|
|
7512
8324
|
shortLabel: "\u275D",
|
|
7513
8325
|
label: "Quote",
|
|
7514
8326
|
run: (v) => {
|
|
7515
|
-
wrapIn(
|
|
8327
|
+
wrapIn(blockquote3)(v.state, v.dispatch);
|
|
7516
8328
|
v.focus();
|
|
7517
8329
|
}
|
|
7518
8330
|
},
|
|
@@ -7532,7 +8344,7 @@ var BLOCK_ITEMS = [
|
|
|
7532
8344
|
}
|
|
7533
8345
|
];
|
|
7534
8346
|
function EmptyParaHandle({ view, cursorPos }) {
|
|
7535
|
-
const [menuOpen, setMenuOpen] =
|
|
8347
|
+
const [menuOpen, setMenuOpen] = useState7(false);
|
|
7536
8348
|
const coords = view.coordsAtPos(cursorPos);
|
|
7537
8349
|
const lineH = Math.max(coords.bottom - coords.top, 18);
|
|
7538
8350
|
const btnSize = 22;
|
|
@@ -7550,8 +8362,8 @@ function EmptyParaHandle({ view, cursorPos }) {
|
|
|
7550
8362
|
document.addEventListener("mousedown", onDown, true);
|
|
7551
8363
|
return () => document.removeEventListener("mousedown", onDown, true);
|
|
7552
8364
|
}, [menuOpen]);
|
|
7553
|
-
return /* @__PURE__ */
|
|
7554
|
-
/* @__PURE__ */
|
|
8365
|
+
return /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
8366
|
+
/* @__PURE__ */ jsx10(
|
|
7555
8367
|
"button",
|
|
7556
8368
|
{
|
|
7557
8369
|
...{ [FLOAT_ATTR]: "" },
|
|
@@ -7583,7 +8395,7 @@ function EmptyParaHandle({ view, cursorPos }) {
|
|
|
7583
8395
|
children: "+"
|
|
7584
8396
|
}
|
|
7585
8397
|
),
|
|
7586
|
-
menuOpen && /* @__PURE__ */
|
|
8398
|
+
menuOpen && /* @__PURE__ */ jsx10(
|
|
7587
8399
|
"div",
|
|
7588
8400
|
{
|
|
7589
8401
|
...{ [FLOAT_ATTR]: "" },
|
|
@@ -7599,7 +8411,7 @@ function EmptyParaHandle({ view, cursorPos }) {
|
|
|
7599
8411
|
minWidth: 168,
|
|
7600
8412
|
animation: "ab-float-in 0.12s ease"
|
|
7601
8413
|
},
|
|
7602
|
-
children: BLOCK_ITEMS.map((item) => /* @__PURE__ */
|
|
8414
|
+
children: BLOCK_ITEMS.map((item) => /* @__PURE__ */ jsx10(
|
|
7603
8415
|
BlockMenuItem,
|
|
7604
8416
|
{
|
|
7605
8417
|
item,
|
|
@@ -7617,8 +8429,8 @@ function BlockMenuItem({
|
|
|
7617
8429
|
view,
|
|
7618
8430
|
onRun
|
|
7619
8431
|
}) {
|
|
7620
|
-
const [hover, setHover] =
|
|
7621
|
-
return /* @__PURE__ */
|
|
8432
|
+
const [hover, setHover] = useState7(false);
|
|
8433
|
+
return /* @__PURE__ */ jsxs9(
|
|
7622
8434
|
"button",
|
|
7623
8435
|
{
|
|
7624
8436
|
...{ [FLOAT_ATTR]: "" },
|
|
@@ -7644,7 +8456,7 @@ function BlockMenuItem({
|
|
|
7644
8456
|
transition: "background 0.1s"
|
|
7645
8457
|
},
|
|
7646
8458
|
children: [
|
|
7647
|
-
/* @__PURE__ */
|
|
8459
|
+
/* @__PURE__ */ jsx10(
|
|
7648
8460
|
"span",
|
|
7649
8461
|
{
|
|
7650
8462
|
style: {
|
|
@@ -7665,10 +8477,10 @@ function BlockMenuItem({
|
|
|
7665
8477
|
);
|
|
7666
8478
|
}
|
|
7667
8479
|
function FloatingMenu({ view, editorState }) {
|
|
7668
|
-
const [showEmptyHandle, setShowEmptyHandle] =
|
|
8480
|
+
const [showEmptyHandle, setShowEmptyHandle] = useState7(false);
|
|
7669
8481
|
const dwellTimerRef = useRef4(null);
|
|
7670
8482
|
const lastEmptyPosRef = useRef4(null);
|
|
7671
|
-
const [, setScrollTick] =
|
|
8483
|
+
const [, setScrollTick] = useState7(0);
|
|
7672
8484
|
useEffect4(() => {
|
|
7673
8485
|
const editorDom = view?.dom;
|
|
7674
8486
|
if (!editorDom) return;
|
|
@@ -7708,8 +8520,8 @@ function FloatingMenu({ view, editorState }) {
|
|
|
7708
8520
|
}
|
|
7709
8521
|
const selectionRect = hasSelection ? getSelectionDOMRect() : null;
|
|
7710
8522
|
return createPortal2(
|
|
7711
|
-
/* @__PURE__ */
|
|
7712
|
-
hasSelection && selectionRect && /* @__PURE__ */
|
|
8523
|
+
/* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
8524
|
+
hasSelection && selectionRect && /* @__PURE__ */ jsx10(
|
|
7713
8525
|
SelectionToolbar,
|
|
7714
8526
|
{
|
|
7715
8527
|
view,
|
|
@@ -7717,7 +8529,7 @@ function FloatingMenu({ view, editorState }) {
|
|
|
7717
8529
|
selectionRect
|
|
7718
8530
|
}
|
|
7719
8531
|
),
|
|
7720
|
-
!hasSelection && showEmptyHandle && emptyPos !== null && /* @__PURE__ */
|
|
8532
|
+
!hasSelection && showEmptyHandle && emptyPos !== null && /* @__PURE__ */ jsx10(EmptyParaHandle, { view, cursorPos: emptyPos })
|
|
7721
8533
|
] }),
|
|
7722
8534
|
document.body
|
|
7723
8535
|
);
|
|
@@ -7886,6 +8698,7 @@ function createInlineSuggestPlugin(provider, endpoint, options) {
|
|
|
7886
8698
|
}
|
|
7887
8699
|
export {
|
|
7888
8700
|
ActionbookRenderer,
|
|
8701
|
+
DocumentTreeView,
|
|
7889
8702
|
EditorShell,
|
|
7890
8703
|
FloatingMenu,
|
|
7891
8704
|
JUMP_POINT_ADJACENT_SPEC,
|
|
@@ -7908,6 +8721,7 @@ export {
|
|
|
7908
8721
|
createKeymapPlugin,
|
|
7909
8722
|
createLinkPlugin,
|
|
7910
8723
|
createMarkdownClipboardPlugin,
|
|
8724
|
+
createNoteBlockPlugin,
|
|
7911
8725
|
createPluginArray,
|
|
7912
8726
|
createReactNodeView,
|
|
7913
8727
|
createSlashCommandPlugin,
|