dishui 0.0.64 → 0.0.65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Badge/index.js +12 -9
- package/dist/components/Badge/index.js.map +1 -1
- package/dist/components/Button/index.js +43 -40
- package/dist/components/Button/index.js.map +1 -1
- package/dist/components/Card/index.d.ts +11 -0
- package/dist/components/Card/index.js +62 -37
- package/dist/components/Card/index.js.map +1 -1
- package/dist/components/Chart/Chart.js.map +1 -1
- package/dist/components/Checkbox/index.js +32 -30
- package/dist/components/Checkbox/index.js.map +1 -1
- package/dist/components/Demo/index.js.map +1 -1
- package/dist/components/EmptyState/index.d.ts +4 -1
- package/dist/components/EmptyState/index.js +3 -3
- package/dist/components/EmptyState/index.js.map +1 -1
- package/dist/components/FileUploader/DropZone.js.map +1 -1
- package/dist/components/FileUploader/FileItem.js.map +1 -1
- package/dist/components/FileUploader/FileUploader.js.map +1 -1
- package/dist/components/FileUploader/UploadQueue.js.map +1 -1
- package/dist/components/Input/index.js +30 -30
- package/dist/components/Input/index.js.map +1 -1
- package/dist/components/Label/index.js +41 -40
- package/dist/components/Label/index.js.map +1 -1
- package/dist/components/List/index.js +47 -32
- package/dist/components/List/index.js.map +1 -1
- package/dist/components/Markdown/Markdown.js +61 -57
- package/dist/components/Markdown/Markdown.js.map +1 -1
- package/dist/components/Markdown/markdownComponents.js +49 -49
- package/dist/components/Markdown/markdownComponents.js.map +1 -1
- package/dist/components/Modal/index.d.ts +7 -3
- package/dist/components/Modal/index.js +77 -65
- package/dist/components/Modal/index.js.map +1 -1
- package/dist/components/Page/index.d.ts +58 -0
- package/dist/components/Page/index.js +74 -0
- package/dist/components/Page/index.js.map +1 -0
- package/dist/components/PageHeader/index.js.map +1 -1
- package/dist/components/Select/index.js +0 -3
- package/dist/components/Select/index.js.map +1 -1
- package/dist/components/SidebarToggleButton/index.js.map +1 -1
- package/dist/components/StatCard/index.d.ts +3 -1
- package/dist/components/StatCard/index.js +39 -11
- package/dist/components/StatCard/index.js.map +1 -1
- package/dist/components/Table/index.js +103 -85
- package/dist/components/Table/index.js.map +1 -1
- package/dist/components/Tabs/index.d.ts +19 -5
- package/dist/components/Tabs/index.js +32 -13
- package/dist/components/Tabs/index.js.map +1 -1
- package/dist/components/Tree/Tree.js.map +1 -1
- package/dist/components/pro/ArticleContextMenu/index.js.map +1 -1
- package/dist/components/pro/ArticleControl/ArticleControl2.js.map +1 -1
- package/dist/components/pro/CodeEditor/editors/CodeEditor.js +141 -134
- package/dist/components/pro/CodeEditor/editors/CodeEditor.js.map +1 -1
- package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js +81 -78
- package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js.map +1 -1
- package/dist/components/pro/CodeEditor/panels/FootnotePanel.js.map +1 -1
- package/dist/components/pro/CodeEditor/panels/HistoryPanel.js.map +1 -1
- package/dist/components/pro/CodeEditor/panels/OutlinePanel.js.map +1 -1
- package/dist/components/pro/CodeEditor/panels/TableOfContentsPanel.js.map +1 -1
- package/dist/components/pro/CodeEditor/panels/VariablePanel.js.map +1 -1
- package/dist/components/pro/CodeEditor/themes.js +59 -59
- package/dist/components/pro/CodeEditor/themes.js.map +1 -1
- package/dist/components/pro/DataTable/DataTable.js +49 -48
- package/dist/components/pro/DataTable/DataTable.js.map +1 -1
- package/dist/components/pro/DataTable/Filters.js +42 -42
- package/dist/components/pro/DataTable/Filters.js.map +1 -1
- package/dist/components/pro/DataTable/PivotPanel.js.map +1 -1
- package/dist/components/pro/DataTable/PivotView.js +35 -32
- package/dist/components/pro/DataTable/PivotView.js.map +1 -1
- package/dist/components/pro/DataTable/components/BulkActions.js.map +1 -1
- package/dist/components/pro/DataTable/components/ColumnSelector.js.map +1 -1
- package/dist/components/pro/DataTable/components/FilterBar.js.map +1 -1
- package/dist/components/pro/DataTable/components/TableBody.js.map +1 -1
- package/dist/components/pro/DataTable/components/TableHeader.js.map +1 -1
- package/dist/components/pro/DataTable/components/TablePagination.js.map +1 -1
- package/dist/components/pro/DataTable/components/TableToolbar.js.map +1 -1
- package/dist/components/pro/DataTable/pivotExtension.js.map +1 -1
- package/dist/components/pro/DataTable/rowDetailExtension.js.map +1 -1
- package/dist/components/pro/DataTable/tanstack-table.js +37 -37
- package/dist/components/pro/DataTable/tanstack-table.js.map +1 -1
- package/dist/components/pro/FileExplorer/Breadcrumb.js +53 -53
- package/dist/components/pro/FileExplorer/Breadcrumb.js.map +1 -1
- package/dist/components/pro/FileExplorer/CreateDialog.js.map +1 -1
- package/dist/components/pro/FileExplorer/FileExplorer.js.map +1 -1
- package/dist/components/pro/FileExplorer/FileIcon.js +22 -22
- package/dist/components/pro/FileExplorer/FileIcon.js.map +1 -1
- package/dist/components/pro/FileExplorer/GridView.js.map +1 -1
- package/dist/components/pro/FileExplorer/ListView.js.map +1 -1
- package/dist/components/pro/FileExplorer/Toolbar.js.map +1 -1
- package/dist/components/pro/Flow/Flow.js +496 -494
- package/dist/components/pro/Flow/Flow.js.map +1 -1
- package/dist/components/pro/Flow/FlowCanvas.js +916 -917
- package/dist/components/pro/Flow/FlowCanvas.js.map +1 -1
- package/dist/components/pro/Flow/context/FlowUIContext.js.map +1 -1
- package/dist/components/pro/Flow/edges/EdgeRenderer.js +59 -59
- package/dist/components/pro/Flow/edges/EdgeRenderer.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useClipboard.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useDeleteSelection.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useEdgeMutations.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useLayoutActions.js +9 -11
- package/dist/components/pro/Flow/hooks/useLayoutActions.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useLineMutations.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useMindMap.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useNodeMutations.js.map +1 -1
- package/dist/components/pro/Flow/lines/FreehandTool.js +9 -9
- package/dist/components/pro/Flow/lines/FreehandTool.js.map +1 -1
- package/dist/components/pro/Flow/lines/LineRenderer.js +5 -5
- package/dist/components/pro/Flow/lines/LineRenderer.js.map +1 -1
- package/dist/components/pro/Flow/nodes/DataNodeView.js +113 -93
- package/dist/components/pro/Flow/nodes/DataNodeView.js.map +1 -1
- package/dist/components/pro/Flow/nodes/MediaContent.js.map +1 -1
- package/dist/components/pro/Flow/nodes/MediaOverlay.js.map +1 -1
- package/dist/components/pro/Flow/nodes/Model3DView.js +1 -1
- package/dist/components/pro/Flow/nodes/Model3DView.js.map +1 -1
- package/dist/components/pro/Flow/nodes/NodeRenderer.js +118 -118
- package/dist/components/pro/Flow/nodes/NodeRenderer.js.map +1 -1
- package/dist/components/pro/Flow/nodes/dataUtils.js.map +1 -1
- package/dist/components/pro/Flow/nodes/shapes.js +1 -3
- package/dist/components/pro/Flow/nodes/shapes.js.map +1 -1
- package/dist/components/pro/Flow/panels/AIPanel.js.map +1 -1
- package/dist/components/pro/Flow/panels/Breadcrumb.js.map +1 -1
- package/dist/components/pro/Flow/panels/ContextMenu.js.map +1 -1
- package/dist/components/pro/Flow/panels/DataInspectorSection.js.map +1 -1
- package/dist/components/pro/Flow/panels/ExpandableTextarea.js.map +1 -1
- package/dist/components/pro/Flow/panels/FlowPanelGroup.js.map +1 -1
- package/dist/components/pro/Flow/panels/FlowToolbar.js +97 -97
- package/dist/components/pro/Flow/panels/FlowToolbar.js.map +1 -1
- package/dist/components/pro/Flow/panels/InspectorPanel.js +57 -57
- package/dist/components/pro/Flow/panels/InspectorPanel.js.map +1 -1
- package/dist/components/pro/Flow/panels/OutlinePanel.js +26 -22
- package/dist/components/pro/Flow/panels/OutlinePanel.js.map +1 -1
- package/dist/components/pro/Flow/panels/PresentationMode.js +18 -16
- package/dist/components/pro/Flow/panels/PresentationMode.js.map +1 -1
- package/dist/components/pro/Flow/panels/ProjectTitle.js.map +1 -1
- package/dist/components/pro/Flow/panels/ShapePalette.js +109 -104
- package/dist/components/pro/Flow/panels/ShapePalette.js.map +1 -1
- package/dist/components/pro/Flow/panels/toolbarIcons.js.map +1 -1
- package/dist/components/pro/RichTextEditor/AIRewrite.js.map +1 -1
- package/dist/components/pro/RichTextEditor/BlockHandle.js.map +1 -1
- package/dist/components/pro/RichTextEditor/BubbleToolbar.js.map +1 -1
- package/dist/components/pro/RichTextEditor/CommentDialog.js.map +1 -1
- package/dist/components/pro/RichTextEditor/CommentPanel.js.map +1 -1
- package/dist/components/pro/RichTextEditor/CommentPopover.js.map +1 -1
- package/dist/components/pro/RichTextEditor/ContextMenu.js.map +1 -1
- package/dist/components/pro/RichTextEditor/RichTextEditor.js.map +1 -1
- package/dist/components/pro/RichTextEditor/SlashMenu.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/FloatingDialogMenu.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/MarkdownTemplates.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/SelectDropdown.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/TableOpsMenu.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/CodeBlockView.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/FloatingDialog.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/MarkdownBlock.js.map +1 -1
- package/dist/contexts/AppContext.js.map +1 -1
- package/dist/dishui.css +1 -1
- package/dist/hooks/useTableColumns.js +7 -8
- package/dist/hooks/useTableColumns.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +227 -221
- package/dist/layouts/MainLayout.js +22 -22
- package/dist/layouts/MainLayout.js.map +1 -1
- package/dist/layouts/Navbar.js.map +1 -1
- package/dist/layouts/Sidebar.js +94 -73
- package/dist/layouts/Sidebar.js.map +1 -1
- package/dist/layouts/headbar/Headbar.js.map +1 -1
- package/dist/layouts/headbar/HeadbarLangSwitcher.js.map +1 -1
- package/dist/layouts/headbar/HeadbarSearch.js.map +1 -1
- package/dist/layouts/headbar/HeadbarThemeSwitcher.js +11 -11
- package/dist/layouts/headbar/HeadbarThemeSwitcher.js.map +1 -1
- package/dist/layouts/headbar/HeadbarTitle.js.map +1 -1
- package/dist/utils/i18n.js +10 -10
- package/dist/utils/i18n.js.map +1 -1
- package/dist/utils/menu.js.map +1 -1
- package/dist/utils/routerBuilder.js +17 -15
- package/dist/utils/routerBuilder.js.map +1 -1
- package/dist/utils/themes.js.map +1 -1
- package/package.json +7 -7
|
@@ -1,56 +1,56 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
import E from "./CodeEditor.js";
|
|
2
|
+
import M from "../panels/TableOfContentsPanel.js";
|
|
3
|
+
import S from "../panels/FootnotePanel.js";
|
|
4
4
|
import { extractFootnotes as J, extractMarkdownSections as R, markdownExtensions as D } from "./markdownExtensions.js";
|
|
5
5
|
import { useCallback as N, useEffect as W, useRef as v, useState as u } from "react";
|
|
6
6
|
import { jsx as p, jsxs as w } from "react/jsx-runtime";
|
|
7
|
-
var I = (
|
|
8
|
-
const b =
|
|
9
|
-
`).filter((
|
|
10
|
-
if (b.length < 2) return
|
|
11
|
-
const
|
|
12
|
-
return
|
|
13
|
-
|
|
14
|
-
|
|
7
|
+
var I = (a) => {
|
|
8
|
+
const b = a.split(`
|
|
9
|
+
`).filter((e) => e.trim());
|
|
10
|
+
if (b.length < 2) return a;
|
|
11
|
+
const d = b.map((e) => e.split("|").map((i) => i.trim()).filter((i, n, c) => n > 0 && n < c.length - 1)), s = [];
|
|
12
|
+
return d.forEach((e) => {
|
|
13
|
+
e.forEach((i, n) => {
|
|
14
|
+
s[n] = Math.max(s[n] || 0, i.length);
|
|
15
15
|
});
|
|
16
|
-
}),
|
|
17
|
-
if (
|
|
18
|
-
const l =
|
|
16
|
+
}), d.map((e, i) => "| " + e.map((n, c) => {
|
|
17
|
+
if (i === 1 && n.match(/^:?-+:?$/)) {
|
|
18
|
+
const l = n.startsWith(":"), m = n.endsWith(":"), k = s[c];
|
|
19
19
|
return l && m ? ":" + "-".repeat(k - 2) + ":" : l ? ":" + "-".repeat(k - 1) : m ? "-".repeat(k - 1) + ":" : "-".repeat(k);
|
|
20
20
|
}
|
|
21
|
-
return
|
|
21
|
+
return n.padEnd(s[c], " ");
|
|
22
22
|
}).join(" | ") + " |").join(`
|
|
23
23
|
`);
|
|
24
|
-
}, q = (
|
|
25
|
-
const
|
|
26
|
-
if (!
|
|
27
|
-
let
|
|
28
|
-
for (;
|
|
29
|
-
|
|
30
|
-
let
|
|
31
|
-
|
|
32
|
-
const
|
|
33
|
-
for (;
|
|
34
|
-
|
|
35
|
-
const c =
|
|
24
|
+
}, q = (a, b) => {
|
|
25
|
+
const d = a.state.doc.lineAt(b);
|
|
26
|
+
if (!d.text.includes("|")) return null;
|
|
27
|
+
let s = d.number, e = d.number - 1;
|
|
28
|
+
for (; e >= 1 && a.state.doc.line(e).text.includes("|"); )
|
|
29
|
+
s = e, e--;
|
|
30
|
+
let i = d.number;
|
|
31
|
+
e = d.number + 1;
|
|
32
|
+
const n = a.state.doc.lines;
|
|
33
|
+
for (; e <= n && a.state.doc.line(e).text.includes("|"); )
|
|
34
|
+
i = e, e++;
|
|
35
|
+
const c = a.state.doc.line(s), l = a.state.doc.line(i);
|
|
36
36
|
return {
|
|
37
37
|
start: c.from,
|
|
38
38
|
end: l.to,
|
|
39
|
-
text:
|
|
39
|
+
text: a.state.doc.sliceString(c.from, l.to)
|
|
40
40
|
};
|
|
41
|
-
}, H = ({ value:
|
|
41
|
+
}, H = ({ value: a = "", onChange: b, showTableOfContents: d = !0, showFootnotes: s = !0, onSectionsChange: e, onFootnotesChange: i, tableOfContentsPosition: n = "right", customExtensions: c = [], customContextMenu: l = [], ...m }) => {
|
|
42
42
|
const [k, x] = u([]), [h, L] = u([]), [j, A] = u(1);
|
|
43
43
|
v(null), W(() => {
|
|
44
|
-
const t = R(
|
|
45
|
-
x(t), L(
|
|
44
|
+
const t = R(a), r = J(a);
|
|
45
|
+
x(t), L(r), e && e(t), i && i(r);
|
|
46
46
|
}, [
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
a,
|
|
48
|
+
e,
|
|
49
|
+
i
|
|
50
50
|
]);
|
|
51
51
|
const f = N((t) => {
|
|
52
|
-
const
|
|
53
|
-
|
|
52
|
+
const r = document.querySelector(`.cm-line:nth-child(${t})`);
|
|
53
|
+
r && r.scrollIntoView({
|
|
54
54
|
behavior: "smooth",
|
|
55
55
|
block: "center"
|
|
56
56
|
});
|
|
@@ -58,13 +58,13 @@ var I = (o) => {
|
|
|
58
58
|
{
|
|
59
59
|
label: "格式化表格",
|
|
60
60
|
action: (t) => {
|
|
61
|
-
const
|
|
62
|
-
if (
|
|
63
|
-
const
|
|
61
|
+
const r = t.state.selection.main, o = q(t, r.from);
|
|
62
|
+
if (o) {
|
|
63
|
+
const $ = I(o.text);
|
|
64
64
|
t.dispatch({ changes: {
|
|
65
|
-
from:
|
|
66
|
-
to:
|
|
67
|
-
insert:
|
|
65
|
+
from: o.start,
|
|
66
|
+
to: o.end,
|
|
67
|
+
insert: $
|
|
68
68
|
} });
|
|
69
69
|
} else alert("请将光标放在表格中");
|
|
70
70
|
}
|
|
@@ -78,10 +78,10 @@ var I = (o) => {
|
|
|
78
78
|
{
|
|
79
79
|
label: "剪切",
|
|
80
80
|
action: (t) => {
|
|
81
|
-
const
|
|
82
|
-
navigator.clipboard.writeText(
|
|
83
|
-
from:
|
|
84
|
-
to:
|
|
81
|
+
const r = t.state.selection.main, o = t.state.sliceDoc(r.from, r.to);
|
|
82
|
+
navigator.clipboard.writeText(o), t.dispatch({ changes: {
|
|
83
|
+
from: r.from,
|
|
84
|
+
to: r.to,
|
|
85
85
|
insert: ""
|
|
86
86
|
} });
|
|
87
87
|
}
|
|
@@ -89,18 +89,18 @@ var I = (o) => {
|
|
|
89
89
|
{
|
|
90
90
|
label: "复制",
|
|
91
91
|
action: (t) => {
|
|
92
|
-
const
|
|
93
|
-
navigator.clipboard.writeText(
|
|
92
|
+
const r = t.state.selection.main, o = t.state.sliceDoc(r.from, r.to);
|
|
93
|
+
navigator.clipboard.writeText(o);
|
|
94
94
|
}
|
|
95
95
|
},
|
|
96
96
|
{
|
|
97
97
|
label: "粘贴",
|
|
98
98
|
action: async (t) => {
|
|
99
|
-
const
|
|
99
|
+
const r = await navigator.clipboard.readText(), o = t.state.selection.main;
|
|
100
100
|
t.dispatch({ changes: {
|
|
101
|
-
from:
|
|
102
|
-
to:
|
|
103
|
-
insert:
|
|
101
|
+
from: o.from,
|
|
102
|
+
to: o.to,
|
|
103
|
+
insert: r
|
|
104
104
|
} });
|
|
105
105
|
}
|
|
106
106
|
},
|
|
@@ -120,48 +120,51 @@ var I = (o) => {
|
|
|
120
120
|
}
|
|
121
121
|
},
|
|
122
122
|
...l
|
|
123
|
-
],
|
|
124
|
-
|
|
123
|
+
], T = [...D(), ...c], g = () => {
|
|
124
|
+
const t = [
|
|
125
125
|
"dark",
|
|
126
126
|
"retro",
|
|
127
127
|
"cyberpunk",
|
|
128
128
|
"matrix"
|
|
129
|
-
].includes(m.theme || "light") ? "markdown-sidebar-dark" : "markdown-sidebar-light"
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
129
|
+
].includes(m.theme || "light") ? "markdown-sidebar-dark" : "markdown-sidebar-light";
|
|
130
|
+
return /* @__PURE__ */ w("div", {
|
|
131
|
+
className: `markdown-sidebar space-y-4 ${t}`,
|
|
132
|
+
style: { width: "320px" },
|
|
133
|
+
children: [d && /* @__PURE__ */ p(M, {
|
|
134
|
+
sections: k,
|
|
135
|
+
onSectionClick: f,
|
|
136
|
+
currentLine: j,
|
|
137
|
+
theme: m.theme
|
|
138
|
+
}), s && h.length > 0 && /* @__PURE__ */ p(S, {
|
|
139
|
+
footnotes: h,
|
|
140
|
+
onFootnoteClick: f,
|
|
141
|
+
onJumpToDefinition: (r, o) => {
|
|
142
|
+
console.log(`Jumping to definition of footnote ${r} at line ${o}`), f(o);
|
|
143
|
+
},
|
|
144
|
+
onJumpToReference: (r, o) => {
|
|
145
|
+
console.log(`Jumping to reference of footnote ${r} at line ${o}`), f(o);
|
|
146
|
+
},
|
|
147
|
+
theme: m.theme
|
|
148
|
+
})]
|
|
149
|
+
});
|
|
150
|
+
};
|
|
148
151
|
return /* @__PURE__ */ w("div", {
|
|
149
152
|
className: "markdown-editor-wrapper flex gap-4",
|
|
150
153
|
children: [
|
|
151
|
-
|
|
154
|
+
n === "left" && (d || s) && g(),
|
|
152
155
|
/* @__PURE__ */ p("div", {
|
|
153
156
|
className: "markdown-editor-main flex-1",
|
|
154
|
-
children: /* @__PURE__ */ p(
|
|
157
|
+
children: /* @__PURE__ */ p(E, {
|
|
155
158
|
...m,
|
|
156
|
-
value:
|
|
159
|
+
value: a,
|
|
157
160
|
onChange: b,
|
|
158
161
|
language: "markdown",
|
|
159
162
|
autocompletion: !1,
|
|
160
|
-
extensions:
|
|
163
|
+
extensions: T,
|
|
161
164
|
contextMenu: y
|
|
162
165
|
})
|
|
163
166
|
}),
|
|
164
|
-
|
|
167
|
+
n === "right" && (d || s) && g(),
|
|
165
168
|
/* @__PURE__ */ p("style", { children: `
|
|
166
169
|
.markdown-sidebar-light {
|
|
167
170
|
color: #000000;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MarkdownEditor.js","names":[],"sources":["../../../../../src/components/pro/CodeEditor/editors/MarkdownEditor.tsx"],"sourcesContent":["import React, { useState, useEffect, useCallback, useRef } from 'react';\nimport CodeEditor, { CodeEditorProps, ContextMenuItem } from './CodeEditor';\nimport TableOfContentsPanel from '../panels/TableOfContentsPanel';\nimport FootnotePanel from '../panels/FootnotePanel';\nimport {\n markdownExtensions,\n extractMarkdownSections,\n extractFootnotes,\n MarkdownSection,\n FootnoteInfo,\n} from './markdownExtensions';\nimport { EditorView } from '@codemirror/view';\n\nexport interface MarkdownEditorProps extends Omit<CodeEditorProps, 'language' | 'extensions' | 'autocompletion' | 'contextMenu'> {\n showTableOfContents?: boolean;\n showFootnotes?: boolean;\n onSectionsChange?: (sections: MarkdownSection[]) => void;\n onFootnotesChange?: (footnotes: FootnoteInfo[]) => void;\n tableOfContentsPosition?: 'left' | 'right';\n customExtensions?: CodeEditorProps['extensions'];\n customContextMenu?: ContextMenuItem[];\n}\n\n// 表格格式化函数\nconst formatMarkdownTable = (tableText: string): string => {\n const lines = tableText.split('\\n').filter(line => line.trim());\n if (lines.length < 2) return tableText;\n\n // 解析表格\n const rows = lines.map(line => {\n return line.split('|')\n .map(cell => cell.trim())\n .filter((_, i, arr) => i > 0 && i < arr.length - 1); // 移除首尾空元素\n });\n\n // 计算每列的最大宽度\n const colWidths: number[] = [];\n rows.forEach(row => {\n row.forEach((cell, i) => {\n colWidths[i] = Math.max(colWidths[i] || 0, cell.length);\n });\n });\n\n // 格式化每一行\n const formattedRows = rows.map((row, rowIndex) => {\n const cells = row.map((cell, colIndex) => {\n // 对于分隔行,保持对齐标记\n if (rowIndex === 1 && cell.match(/^:?-+:?$/)) {\n const hasLeft = cell.startsWith(':');\n const hasRight = cell.endsWith(':');\n const width = colWidths[colIndex];\n\n if (hasLeft && hasRight) {\n return ':' + '-'.repeat(width - 2) + ':';\n } else if (hasLeft) {\n return ':' + '-'.repeat(width - 1);\n } else if (hasRight) {\n return '-'.repeat(width - 1) + ':';\n } else {\n return '-'.repeat(width);\n }\n }\n\n return cell.padEnd(colWidths[colIndex], ' ');\n });\n\n return '| ' + cells.join(' | ') + ' |';\n });\n\n return formattedRows.join('\\n');\n};\n\n// 检测是否在表格中\nconst isInTable = (view: EditorView, pos: number): { start: number; end: number; text: string } | null => {\n const line = view.state.doc.lineAt(pos);\n const lineText = line.text;\n\n if (!lineText.includes('|')) return null;\n\n // 向上查找表格开始\n let startLine = line.number;\n let currentLine = line.number - 1;\n while (currentLine >= 1) {\n const l = view.state.doc.line(currentLine);\n if (!l.text.includes('|')) break;\n startLine = currentLine;\n currentLine--;\n }\n\n // 向下查找表格结束\n let endLine = line.number;\n currentLine = line.number + 1;\n const totalLines = view.state.doc.lines;\n while (currentLine <= totalLines) {\n const l = view.state.doc.line(currentLine);\n if (!l.text.includes('|')) break;\n endLine = currentLine;\n currentLine++;\n }\n\n const startLineObj = view.state.doc.line(startLine);\n const endLineObj = view.state.doc.line(endLine);\n\n return {\n start: startLineObj.from,\n end: endLineObj.to,\n text: view.state.doc.sliceString(startLineObj.from, endLineObj.to),\n };\n};\n\nconst MarkdownEditor: React.FC<MarkdownEditorProps> = ({\n value = '',\n onChange,\n showTableOfContents = true,\n showFootnotes = true,\n onSectionsChange,\n onFootnotesChange,\n tableOfContentsPosition = 'right',\n customExtensions = [],\n customContextMenu = [],\n ...codeEditorProps\n}) => {\n const [sections, setSections] = useState<MarkdownSection[]>([]);\n const [footnotes, setFootnotes] = useState<FootnoteInfo[]>([]);\n const [currentLine, setCurrentLine] = useState(1);\n const editorViewRef = useRef<EditorView | null>(null);\n\n // 提取章节和脚注\n useEffect(() => {\n const newSections = extractMarkdownSections(value);\n const newFootnotes = extractFootnotes(value);\n\n setSections(newSections);\n setFootnotes(newFootnotes);\n\n if (onSectionsChange) {\n onSectionsChange(newSections);\n }\n\n if (onFootnotesChange) {\n onFootnotesChange(newFootnotes);\n }\n }, [value, onSectionsChange, onFootnotesChange]);\n\n // 跳转到指定行\n const jumpToLine = useCallback((line: number) => {\n const lineElement = document.querySelector(`.cm-line:nth-child(${line})`);\n if (lineElement) {\n lineElement.scrollIntoView({ behavior: 'smooth', block: 'center' });\n }\n }, []);\n\n // Markdown 专属上下文菜单\n const markdownContextMenu: ContextMenuItem[] = [\n {\n label: '格式化表格',\n action: (view) => {\n const selection = view.state.selection.main;\n const tableInfo = isInTable(view, selection.from);\n\n if (tableInfo) {\n const formatted = formatMarkdownTable(tableInfo.text);\n view.dispatch({\n changes: {\n from: tableInfo.start,\n to: tableInfo.end,\n insert: formatted,\n },\n });\n } else {\n alert('请将光标放在表格中');\n }\n },\n },\n { label: '', action: () => { }, separator: true },\n {\n label: '剪切',\n action: (view) => {\n const selection = view.state.selection.main;\n const text = view.state.sliceDoc(selection.from, selection.to);\n navigator.clipboard.writeText(text);\n view.dispatch({\n changes: { from: selection.from, to: selection.to, insert: '' },\n });\n },\n },\n {\n label: '复制',\n action: (view) => {\n const selection = view.state.selection.main;\n const text = view.state.sliceDoc(selection.from, selection.to);\n navigator.clipboard.writeText(text);\n },\n },\n {\n label: '粘贴',\n action: async (view) => {\n const text = await navigator.clipboard.readText();\n const selection = view.state.selection.main;\n view.dispatch({\n changes: { from: selection.from, to: selection.to, insert: text },\n });\n },\n },\n { label: '', action: () => { }, separator: true },\n {\n label: '全选',\n action: (view) => {\n view.dispatch({\n selection: { anchor: 0, head: view.state.doc.length },\n });\n },\n },\n ...customContextMenu,\n ];\n\n // 合并扩展\n const allExtensions = [...markdownExtensions(), ...customExtensions];\n\n // 侧边栏内容\n const renderSidebar = () => {\n // 根据主题决定侧边栏的样式类\n const darkThemes = ['dark', 'retro', 'cyberpunk', 'matrix'];\n const sidebarThemeClass =\n darkThemes.includes(codeEditorProps.theme || 'light')\n ? 'markdown-sidebar-dark'\n : 'markdown-sidebar-light';\n\n return (\n <div className={`markdown-sidebar space-y-4 ${sidebarThemeClass}`} style={{ width: '320px' }}>\n {showTableOfContents && (\n <TableOfContentsPanel\n sections={sections}\n onSectionClick={jumpToLine}\n currentLine={currentLine}\n theme={codeEditorProps.theme}\n />\n )}\n {showFootnotes && footnotes.length > 0 && (\n <FootnotePanel\n footnotes={footnotes}\n onFootnoteClick={jumpToLine}\n onJumpToDefinition={(id, line) => {\n console.log(`Jumping to definition of footnote ${id} at line ${line}`);\n jumpToLine(line);\n }}\n onJumpToReference={(id, line) => {\n console.log(`Jumping to reference of footnote ${id} at line ${line}`);\n jumpToLine(line);\n }}\n theme={codeEditorProps.theme}\n />\n )}\n </div>\n );\n };\n\n return (\n <div className=\"markdown-editor-wrapper flex gap-4\">\n {/* 左侧边栏 */}\n {tableOfContentsPosition === 'left' && (showTableOfContents || showFootnotes) && renderSidebar()}\n\n {/* 编辑器 */}\n <div className=\"markdown-editor-main flex-1\">\n <CodeEditor\n {...codeEditorProps}\n value={value}\n onChange={onChange}\n language=\"markdown\"\n autocompletion={false}\n extensions={allExtensions}\n contextMenu={markdownContextMenu}\n />\n </div>\n\n {/* 右侧边栏 */}\n {tableOfContentsPosition === 'right' && (showTableOfContents || showFootnotes) && renderSidebar()}\n\n {/* 侧边栏主题样式 */}\n <style>{`\n .markdown-sidebar-light {\n color: #000000;\n }\n .markdown-sidebar-dark {\n color: #d4d4d4;\n }\n .markdown-sidebar-dark .card,\n .markdown-sidebar-dark .toc-panel,\n .markdown-sidebar-dark .footnote-panel,\n .markdown-sidebar-dark .outline-panel,\n .markdown-sidebar-dark .variable-panel {\n background-color: #1e1e1e !important;\n border-color: #3e3e42 !important;\n color: #d4d4d4 !important;\n }\n .markdown-sidebar-dark .border-base-300 {\n border-color: #3e3e42 !important;\n }\n .markdown-sidebar-dark input,\n .markdown-sidebar-dark .input {\n background-color: #2d2d2d !important;\n border-color: #3e3e42 !important;\n color: #d4d4d4 !important;\n }\n .markdown-sidebar-dark button,\n .markdown-sidebar-dark .btn {\n color: #d4d4d4 !important;\n }\n .markdown-sidebar-dark .hover\\\\:bg-base-200:hover,\n .markdown-sidebar-dark .toc-item:hover,\n .markdown-sidebar-dark .outline-item:hover,\n .markdown-sidebar-dark .variable-item:hover,\n .markdown-sidebar-dark .footnote-item:hover {\n background-color: #2d2d2d !important;\n }\n .markdown-sidebar-dark .bg-primary\\\\/20 {\n background-color: rgba(96, 165, 250, 0.2) !important;\n }\n .markdown-sidebar-dark .bg-base-200 {\n background-color: #2d2d2d !important;\n }\n .markdown-sidebar-dark .bg-warning\\\\/10 {\n background-color: rgba(251, 191, 36, 0.1) !important;\n }\n .markdown-sidebar-dark .border-warning\\\\/30 {\n border-color: rgba(251, 191, 36, 0.3) !important;\n }\n .markdown-sidebar-dark .text-warning {\n color: #fbbf24 !important;\n }\n `}</style>\n </div>\n );\n};\n\nexport default MarkdownEditor;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MarkdownEditor.js","names":[],"sources":["../../../../../src/components/pro/CodeEditor/editors/MarkdownEditor.tsx"],"sourcesContent":["import React, { useState, useEffect, useCallback, useRef } from 'react';\nimport CodeEditor, { CodeEditorProps, ContextMenuItem } from './CodeEditor';\nimport TableOfContentsPanel from '../panels/TableOfContentsPanel';\nimport FootnotePanel from '../panels/FootnotePanel';\nimport {\n markdownExtensions,\n extractMarkdownSections,\n extractFootnotes,\n MarkdownSection,\n FootnoteInfo,\n} from './markdownExtensions';\nimport { EditorView } from '@codemirror/view';\n\nexport interface MarkdownEditorProps extends Omit<CodeEditorProps, 'language' | 'extensions' | 'autocompletion' | 'contextMenu'> {\n showTableOfContents?: boolean;\n showFootnotes?: boolean;\n onSectionsChange?: (sections: MarkdownSection[]) => void;\n onFootnotesChange?: (footnotes: FootnoteInfo[]) => void;\n tableOfContentsPosition?: 'left' | 'right';\n customExtensions?: CodeEditorProps['extensions'];\n customContextMenu?: ContextMenuItem[];\n}\n\n// 表格格式化函数\nconst formatMarkdownTable = (tableText: string): string => {\n const lines = tableText.split('\\n').filter(line => line.trim());\n if (lines.length < 2) return tableText;\n\n // 解析表格\n const rows = lines.map(line => {\n return line.split('|')\n .map(cell => cell.trim())\n .filter((_, i, arr) => i > 0 && i < arr.length - 1); // 移除首尾空元素\n });\n\n // 计算每列的最大宽度\n const colWidths: number[] = [];\n rows.forEach(row => {\n row.forEach((cell, i) => {\n colWidths[i] = Math.max(colWidths[i] || 0, cell.length);\n });\n });\n\n // 格式化每一行\n const formattedRows = rows.map((row, rowIndex) => {\n const cells = row.map((cell, colIndex) => {\n // 对于分隔行,保持对齐标记\n if (rowIndex === 1 && cell.match(/^:?-+:?$/)) {\n const hasLeft = cell.startsWith(':');\n const hasRight = cell.endsWith(':');\n const width = colWidths[colIndex];\n\n if (hasLeft && hasRight) {\n return ':' + '-'.repeat(width - 2) + ':';\n } else if (hasLeft) {\n return ':' + '-'.repeat(width - 1);\n } else if (hasRight) {\n return '-'.repeat(width - 1) + ':';\n } else {\n return '-'.repeat(width);\n }\n }\n\n return cell.padEnd(colWidths[colIndex], ' ');\n });\n\n return '| ' + cells.join(' | ') + ' |';\n });\n\n return formattedRows.join('\\n');\n};\n\n// 检测是否在表格中\nconst isInTable = (view: EditorView, pos: number): { start: number; end: number; text: string } | null => {\n const line = view.state.doc.lineAt(pos);\n const lineText = line.text;\n\n if (!lineText.includes('|')) return null;\n\n // 向上查找表格开始\n let startLine = line.number;\n let currentLine = line.number - 1;\n while (currentLine >= 1) {\n const l = view.state.doc.line(currentLine);\n if (!l.text.includes('|')) break;\n startLine = currentLine;\n currentLine--;\n }\n\n // 向下查找表格结束\n let endLine = line.number;\n currentLine = line.number + 1;\n const totalLines = view.state.doc.lines;\n while (currentLine <= totalLines) {\n const l = view.state.doc.line(currentLine);\n if (!l.text.includes('|')) break;\n endLine = currentLine;\n currentLine++;\n }\n\n const startLineObj = view.state.doc.line(startLine);\n const endLineObj = view.state.doc.line(endLine);\n\n return {\n start: startLineObj.from,\n end: endLineObj.to,\n text: view.state.doc.sliceString(startLineObj.from, endLineObj.to),\n };\n};\n\nconst MarkdownEditor: React.FC<MarkdownEditorProps> = ({\n value = '',\n onChange,\n showTableOfContents = true,\n showFootnotes = true,\n onSectionsChange,\n onFootnotesChange,\n tableOfContentsPosition = 'right',\n customExtensions = [],\n customContextMenu = [],\n ...codeEditorProps\n}) => {\n const [sections, setSections] = useState<MarkdownSection[]>([]);\n const [footnotes, setFootnotes] = useState<FootnoteInfo[]>([]);\n const [currentLine, setCurrentLine] = useState(1);\n const editorViewRef = useRef<EditorView | null>(null);\n\n // 提取章节和脚注\n useEffect(() => {\n const newSections = extractMarkdownSections(value);\n const newFootnotes = extractFootnotes(value);\n\n setSections(newSections);\n setFootnotes(newFootnotes);\n\n if (onSectionsChange) {\n onSectionsChange(newSections);\n }\n\n if (onFootnotesChange) {\n onFootnotesChange(newFootnotes);\n }\n }, [value, onSectionsChange, onFootnotesChange]);\n\n // 跳转到指定行\n const jumpToLine = useCallback((line: number) => {\n const lineElement = document.querySelector(`.cm-line:nth-child(${line})`);\n if (lineElement) {\n lineElement.scrollIntoView({ behavior: 'smooth', block: 'center' });\n }\n }, []);\n\n // Markdown 专属上下文菜单\n const markdownContextMenu: ContextMenuItem[] = [\n {\n label: '格式化表格',\n action: (view) => {\n const selection = view.state.selection.main;\n const tableInfo = isInTable(view, selection.from);\n\n if (tableInfo) {\n const formatted = formatMarkdownTable(tableInfo.text);\n view.dispatch({\n changes: {\n from: tableInfo.start,\n to: tableInfo.end,\n insert: formatted,\n },\n });\n } else {\n alert('请将光标放在表格中');\n }\n },\n },\n { label: '', action: () => { }, separator: true },\n {\n label: '剪切',\n action: (view) => {\n const selection = view.state.selection.main;\n const text = view.state.sliceDoc(selection.from, selection.to);\n navigator.clipboard.writeText(text);\n view.dispatch({\n changes: { from: selection.from, to: selection.to, insert: '' },\n });\n },\n },\n {\n label: '复制',\n action: (view) => {\n const selection = view.state.selection.main;\n const text = view.state.sliceDoc(selection.from, selection.to);\n navigator.clipboard.writeText(text);\n },\n },\n {\n label: '粘贴',\n action: async (view) => {\n const text = await navigator.clipboard.readText();\n const selection = view.state.selection.main;\n view.dispatch({\n changes: { from: selection.from, to: selection.to, insert: text },\n });\n },\n },\n { label: '', action: () => { }, separator: true },\n {\n label: '全选',\n action: (view) => {\n view.dispatch({\n selection: { anchor: 0, head: view.state.doc.length },\n });\n },\n },\n ...customContextMenu,\n ];\n\n // 合并扩展\n const allExtensions = [...markdownExtensions(), ...customExtensions];\n\n // 侧边栏内容\n const renderSidebar = () => {\n // 根据主题决定侧边栏的样式类\n const darkThemes = ['dark', 'retro', 'cyberpunk', 'matrix'];\n const sidebarThemeClass =\n darkThemes.includes(codeEditorProps.theme || 'light')\n ? 'markdown-sidebar-dark'\n : 'markdown-sidebar-light';\n\n return (\n <div className={`markdown-sidebar space-y-4 ${sidebarThemeClass}`} style={{ width: '320px' }}>\n {showTableOfContents && (\n <TableOfContentsPanel\n sections={sections}\n onSectionClick={jumpToLine}\n currentLine={currentLine}\n theme={codeEditorProps.theme}\n />\n )}\n {showFootnotes && footnotes.length > 0 && (\n <FootnotePanel\n footnotes={footnotes}\n onFootnoteClick={jumpToLine}\n onJumpToDefinition={(id, line) => {\n console.log(`Jumping to definition of footnote ${id} at line ${line}`);\n jumpToLine(line);\n }}\n onJumpToReference={(id, line) => {\n console.log(`Jumping to reference of footnote ${id} at line ${line}`);\n jumpToLine(line);\n }}\n theme={codeEditorProps.theme}\n />\n )}\n </div>\n );\n };\n\n return (\n <div className=\"markdown-editor-wrapper flex gap-4\">\n {/* 左侧边栏 */}\n {tableOfContentsPosition === 'left' && (showTableOfContents || showFootnotes) && renderSidebar()}\n\n {/* 编辑器 */}\n <div className=\"markdown-editor-main flex-1\">\n <CodeEditor\n {...codeEditorProps}\n value={value}\n onChange={onChange}\n language=\"markdown\"\n autocompletion={false}\n extensions={allExtensions}\n contextMenu={markdownContextMenu}\n />\n </div>\n\n {/* 右侧边栏 */}\n {tableOfContentsPosition === 'right' && (showTableOfContents || showFootnotes) && renderSidebar()}\n\n {/* 侧边栏主题样式 */}\n <style>{`\n .markdown-sidebar-light {\n color: #000000;\n }\n .markdown-sidebar-dark {\n color: #d4d4d4;\n }\n .markdown-sidebar-dark .card,\n .markdown-sidebar-dark .toc-panel,\n .markdown-sidebar-dark .footnote-panel,\n .markdown-sidebar-dark .outline-panel,\n .markdown-sidebar-dark .variable-panel {\n background-color: #1e1e1e !important;\n border-color: #3e3e42 !important;\n color: #d4d4d4 !important;\n }\n .markdown-sidebar-dark .border-base-300 {\n border-color: #3e3e42 !important;\n }\n .markdown-sidebar-dark input,\n .markdown-sidebar-dark .input {\n background-color: #2d2d2d !important;\n border-color: #3e3e42 !important;\n color: #d4d4d4 !important;\n }\n .markdown-sidebar-dark button,\n .markdown-sidebar-dark .btn {\n color: #d4d4d4 !important;\n }\n .markdown-sidebar-dark .hover\\\\:bg-base-200:hover,\n .markdown-sidebar-dark .toc-item:hover,\n .markdown-sidebar-dark .outline-item:hover,\n .markdown-sidebar-dark .variable-item:hover,\n .markdown-sidebar-dark .footnote-item:hover {\n background-color: #2d2d2d !important;\n }\n .markdown-sidebar-dark .bg-primary\\\\/20 {\n background-color: rgba(96, 165, 250, 0.2) !important;\n }\n .markdown-sidebar-dark .bg-base-200 {\n background-color: #2d2d2d !important;\n }\n .markdown-sidebar-dark .bg-warning\\\\/10 {\n background-color: rgba(251, 191, 36, 0.1) !important;\n }\n .markdown-sidebar-dark .border-warning\\\\/30 {\n border-color: rgba(251, 191, 36, 0.3) !important;\n }\n .markdown-sidebar-dark .text-warning {\n color: #fbbf24 !important;\n }\n `}</style>\n </div>\n );\n};\n\nexport default MarkdownEditor;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FootnotePanel.js","names":[],"sources":["../../../../../src/components/pro/CodeEditor/panels/FootnotePanel.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { FootnoteInfo } from '../editors/markdownExtensions';\nimport { EditorTheme } from '../types';\n\nexport interface FootnotePanelProps {\n footnotes: FootnoteInfo[];\n onFootnoteClick: (line: number) => void;\n onJumpToDefinition?: (id: string, line: number) => void;\n onJumpToReference?: (id: string, line: number) => void;\n className?: string;\n theme?: EditorTheme;\n}\n\nconst FootnotePanel: React.FC<FootnotePanelProps> = ({\n footnotes,\n onFootnoteClick,\n onJumpToDefinition,\n onJumpToReference,\n className = '',\n theme = 'light',\n}) => {\n const [filter, setFilter] = useState('');\n\n // 过滤脚注\n const filteredFootnotes = footnotes.filter((footnote) =>\n footnote.id.toLowerCase().includes(filter.toLowerCase())\n );\n\n // 分类脚注\n const defined = filteredFootnotes.filter((f) => f.definitionLine);\n const undefined = filteredFootnotes.filter((f) => !f.definitionLine);\n\n return (\n <div className={`footnote-panel bg-base-100 border border-base-300 rounded-lg p-2 ${className}`}>\n {/* 标题 */}\n <div className=\"footnote-header flex items-center gap-2 px-2 py-1 mb-2 border-b border-base-300\">\n <svg className=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z\"\n />\n </svg>\n <span className=\"font-semibold\">脚注</span>\n <span className=\"text-xs opacity-60 ml-auto\">({footnotes.length})</span>\n </div>\n\n {/* 搜索框 */}\n <input\n type=\"text\"\n placeholder=\"搜索脚注...\"\n value={filter}\n onChange={(e) => setFilter(e.target.value)}\n className=\"input input-sm input-bordered w-full mb-2\"\n />\n\n {/* 脚注列表 */}\n <div className=\"footnote-content max-h-96 overflow-y-auto\">\n {filteredFootnotes.length === 0 ? (\n <div className=\"text-center text-sm opacity-60 py-4\">\n {filter ? '未找到匹配的脚注' : '暂无脚注'}\n </div>\n ) : (\n <div className=\"space-y-3\">\n {/* 已定义的脚注 */}\n {defined.length > 0 && (\n <div>\n <div className=\"text-xs font-semibold opacity-70 mb-1 px-2\">已定义</div>\n {defined.map((footnote) => (\n <div\n key={footnote.id}\n className=\"footnote-item bg-base-200 rounded p-2 mb-1 hover:bg-base-300 cursor-pointer transition-colors\"\n >\n <div className=\"flex items-center justify-between mb-1\">\n <span className=\"font-mono text-sm font-semibold text-primary\">\n [^{footnote.id}]\n </span>\n <div className=\"flex gap-1\">\n {footnote.definitionLine && (\n <button\n className=\"btn btn-xs btn-ghost tooltip tooltip-left\"\n data-tip=\"跳转到定义\"\n onClick={() => {\n onFootnoteClick(footnote.definitionLine!);\n if (onJumpToDefinition) {\n onJumpToDefinition(footnote.id, footnote.definitionLine!);\n }\n }}\n title=\"跳转到定义\"\n >\n <svg className=\"w-3 h-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\"\n />\n </svg>\n </button>\n )}\n </div>\n </div>\n <div className=\"text-xs opacity-70 mb-2\">\n {footnote.definitionLine && `定义: 第 ${footnote.definitionLine} 行`}\n {footnote.referenceLines && footnote.referenceLines.length > 0 && (\n <div className=\"mt-1\">\n 引用 ({footnote.referenceLines.length}): \n {footnote.referenceLines.map((refLine, idx) => (\n <button\n key={idx}\n className=\"btn btn-xs btn-ghost ml-1 text-info\"\n onClick={() => {\n onFootnoteClick(refLine);\n if (onJumpToReference) {\n onJumpToReference(footnote.id, refLine);\n }\n }}\n title={`跳转到第 ${refLine} 行`}\n >\n L{refLine}\n </button>\n ))}\n </div>\n )}\n </div>\n </div>\n ))}\n </div>\n )}\n\n {/* 未定义的脚注 */}\n {undefined.length > 0 && (\n <div>\n <div className=\"text-xs font-semibold opacity-70 mb-1 px-2 text-warning\">\n 未定义\n </div>\n {undefined.map((footnote) => (\n <div\n key={footnote.id}\n className=\"footnote-item bg-warning/10 border border-warning/30 rounded p-2 mb-1 hover:bg-warning/20 cursor-pointer transition-colors\"\n >\n <div className=\"flex items-center justify-between mb-1\">\n <span className=\"font-mono text-sm font-semibold text-warning\">\n [^{footnote.id}]\n </span>\n <button\n className=\"btn btn-xs btn-ghost\"\n onClick={() => onFootnoteClick(footnote.line)}\n title=\"跳转到引用\"\n >\n <svg className=\"w-3 h-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M13 7l5 5m0 0l-5 5m5-5H6\"\n />\n </svg>\n </button>\n </div>\n <div className=\"text-xs opacity-70\">\n 引用: 第 {footnote.line} 行 | ⚠️ 缺少定义\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport default FootnotePanel;\n\n"],"mappings":";;AAaA,IAAM,IAAA,CAA+C,EACnD,WAAA,GACA,iBAAA,GACA,oBAAA,GACA,mBAAA,GACA,WAAA,IAAY,IACZ,OAAA,IAAQ,QAAA,MACJ;AACJ,QAAM,CAAC,GAAQ,CAAA,IAAa,EAAS,EAAE,GAGjC,IAAoB,EAAU,OAAA,CAAQ,MAC1C,EAAS,GAAG,YAAY,EAAE,SAAS,EAAO,YAAY,CAAC,CACzD,GAGM,IAAU,EAAkB,OAAA,CAAQ,MAAM,EAAE,cAAc,GAC1D,IAAY,EAAkB,OAAA,CAAQ,MAAM,CAAC,EAAE,cAAc;AAEnE,SACE,gBAAA,EAAC,OAAD;AAAA,IAAK,WAAW,oEAAoE,CAAA;AAAA,cAApF;AAAA,MAEE,gBAAA,EAAC,OAAD;AAAA,QAAK,WAAU;AAAA,kBAAf;AAAA,UACE,gBAAA,EAAC,OAAD;AAAA,YAAK,WAAU;AAAA,YAAU,MAAK;AAAA,YAAO,SAAQ;AAAA,YAAY,QAAO;AAAA,sBAC9D,gBAAA,EAAC,QAAD;AAAA,cACE,eAAc;AAAA,cACd,gBAAe;AAAA,cACf,aAAa;AAAA,cACb,GAAE;AAAA,YACH,CAAA;AAAA,UACE,CAAA;AAAA,UACL,gBAAA,EAAC,QAAD;AAAA,YAAM,WAAU;AAAA,sBAAgB;AAAA,UAAQ,CAAA;AAAA,UACxC,gBAAA,EAAC,QAAD;AAAA,YAAM,WAAU;AAAA,sBAAhB;AAAA,cAA6C;AAAA,cAAE,EAAU;AAAA,cAAO;AAAA,YAAO;AAAA;QACpE;AAAA;MAGL,gBAAA,EAAC,SAAD;AAAA,QACE,MAAK;AAAA,QACL,aAAY;AAAA,QACZ,OAAO;AAAA,QACP,UAAA,CAAW,MAAM,EAAU,EAAE,OAAO,KAAK;AAAA,QACzC,WAAU;AAAA,MACX,CAAA;AAAA,MAGD,gBAAA,EAAC,OAAD;AAAA,QAAK,WAAU;AAAA,kBACZ,EAAkB,WAAW,IAC5B,gBAAA,EAAC,OAAD;AAAA,UAAK,WAAU;AAAA,oBACZ,IAAS,aAAa;AAAA,QACpB,CAAA,IAEL,gBAAA,EAAC,OAAD;AAAA,UAAK,WAAU;AAAA,oBAAf,CAEG,EAAQ,SAAS,KAChB,gBAAA,EAAC,OAAD,EAAA,UAAA,CACE,gBAAA,EAAC,OAAD;AAAA,YAAK,WAAU;AAAA,sBAA6C;AAAA,UAAQ,CAAA,GACnE,EAAQ,IAAA,CAAK,MACZ,gBAAA,EAAC,OAAD;AAAA,YAEE,WAAU;AAAA,sBAFZ,CAIE,gBAAA,EAAC,OAAD;AAAA,cAAK,WAAU;AAAA,wBAAf,CACE,gBAAA,EAAC,QAAD;AAAA,gBAAM,WAAU;AAAA,0BAAhB;AAAA,kBAA+D;AAAA,kBAC1D,EAAS;AAAA,kBAAG;AAAA,gBACX;AAAA,kBACN,gBAAA,EAAC,OAAD;AAAA,gBAAK,WAAU;AAAA,0BACZ,EAAS,kBACR,gBAAA,EAAC,UAAD;AAAA,kBACE,WAAU;AAAA,kBACV,YAAS;AAAA,kBACT,SAAA,MAAe;AACb,oBAAA,EAAgB,EAAS,cAAe,GACpC,KACF,EAAmB,EAAS,IAAI,EAAS,cAAe;AAAA,kBAE5D;AAAA,kBACA,OAAM;AAAA,4BAEN,gBAAA,EAAC,OAAD;AAAA,oBAAK,WAAU;AAAA,oBAAU,MAAK;AAAA,oBAAO,SAAQ;AAAA,oBAAY,QAAO;AAAA,8BAC9D,gBAAA,EAAC,QAAD;AAAA,sBACE,eAAc;AAAA,sBACd,gBAAe;AAAA,sBACf,aAAa;AAAA,sBACb,GAAE;AAAA,oBACH,CAAA;AAAA,kBACE,CAAA;AAAA,gBACC,CAAA;AAAA,cAEP,CAAA,CACF;AAAA,gBACL,gBAAA,EAAC,OAAD;AAAA,cAAK,WAAU;AAAA,wBAAf,CACG,EAAS,kBAAkB,SAAS,EAAS,cAAA,MAC7C,EAAS,kBAAkB,EAAS,eAAe,SAAS,KAC3D,gBAAA,EAAC,OAAD;AAAA,gBAAK,WAAU;AAAA,0BAAf;AAAA,kBAAsB;AAAA,kBACf,EAAS,eAAe;AAAA,kBAAO;AAAA,kBACnC,EAAS,eAAe,IAAA,CAAK,GAAS,MACrC,gBAAA,EAAC,UAAD;AAAA,oBAEE,WAAU;AAAA,oBACV,SAAA,MAAe;AACb,sBAAA,EAAgB,CAAO,GACnB,KACF,EAAkB,EAAS,IAAI,CAAO;AAAA,oBAE1C;AAAA,oBACA,OAAO,QAAQ,CAAA;AAAA,8BATjB,CAUC,KACG,CACI;AAAA,qBAXD,CAWC,CACT;AAAA,gBACE;AAAA,gBAEJ;AAAA,cACF;AAAA,aAvDE,EAAS,EAuDX,CACN,CACE,EAAA,CAAA,GAIN,EAAU,SAAS,KAClB,gBAAA,EAAC,OAAD,EAAA,UAAA,CACE,gBAAA,EAAC,OAAD;AAAA,YAAK,WAAU;AAAA,sBAA0D;AAAA,UAEpE,CAAA,GACJ,EAAU,IAAA,CAAK,MACd,gBAAA,EAAC,OAAD;AAAA,YAEE,WAAU;AAAA,sBAFZ,CAIE,gBAAA,EAAC,OAAD;AAAA,cAAK,WAAU;AAAA,wBAAf,CACE,gBAAA,EAAC,QAAD;AAAA,gBAAM,WAAU;AAAA,0BAAhB;AAAA,kBAA+D;AAAA,kBAC1D,EAAS;AAAA,kBAAG;AAAA,gBACX;AAAA,kBACN,gBAAA,EAAC,UAAD;AAAA,gBACE,WAAU;AAAA,gBACV,SAAA,MAAe,EAAgB,EAAS,IAAI;AAAA,gBAC5C,OAAM;AAAA,0BAEN,gBAAA,EAAC,OAAD;AAAA,kBAAK,WAAU;AAAA,kBAAU,MAAK;AAAA,kBAAO,SAAQ;AAAA,kBAAY,QAAO;AAAA,4BAC9D,gBAAA,EAAC,QAAD;AAAA,oBACE,eAAc;AAAA,oBACd,gBAAe;AAAA,oBACf,aAAa;AAAA,oBACb,GAAE;AAAA,kBACH,CAAA;AAAA,gBACE,CAAA;AAAA,cACC,CAAA,CACL;AAAA,gBACL,gBAAA,EAAC,OAAD;AAAA,cAAK,WAAU;AAAA,wBAAf;AAAA,gBAAoC;AAAA,gBAC3B,EAAS;AAAA,gBAAK;AAAA,cAClB;AAAA,cACF;AAAA,aAzBE,EAAS,EAyBX,CACN,CACE,EAAA,CAAA,CAEJ;AAAA;MAEJ,CAAA;AAAA,IACF;AAAA;AAET"}
|
|
1
|
+
{"version":3,"file":"FootnotePanel.js","names":[],"sources":["../../../../../src/components/pro/CodeEditor/panels/FootnotePanel.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { FootnoteInfo } from '../editors/markdownExtensions';\nimport { EditorTheme } from '../types';\n\nexport interface FootnotePanelProps {\n footnotes: FootnoteInfo[];\n onFootnoteClick: (line: number) => void;\n onJumpToDefinition?: (id: string, line: number) => void;\n onJumpToReference?: (id: string, line: number) => void;\n className?: string;\n theme?: EditorTheme;\n}\n\nconst FootnotePanel: React.FC<FootnotePanelProps> = ({\n footnotes,\n onFootnoteClick,\n onJumpToDefinition,\n onJumpToReference,\n className = '',\n theme = 'light',\n}) => {\n const [filter, setFilter] = useState('');\n\n // 过滤脚注\n const filteredFootnotes = footnotes.filter((footnote) =>\n footnote.id.toLowerCase().includes(filter.toLowerCase())\n );\n\n // 分类脚注\n const defined = filteredFootnotes.filter((f) => f.definitionLine);\n const undefined = filteredFootnotes.filter((f) => !f.definitionLine);\n\n return (\n <div className={`footnote-panel bg-base-100 border border-base-300 rounded-lg p-2 ${className}`}>\n {/* 标题 */}\n <div className=\"footnote-header flex items-center gap-2 px-2 py-1 mb-2 border-b border-base-300\">\n <svg className=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z\"\n />\n </svg>\n <span className=\"font-semibold\">脚注</span>\n <span className=\"text-xs opacity-60 ml-auto\">({footnotes.length})</span>\n </div>\n\n {/* 搜索框 */}\n <input\n type=\"text\"\n placeholder=\"搜索脚注...\"\n value={filter}\n onChange={(e) => setFilter(e.target.value)}\n className=\"input input-sm input-bordered w-full mb-2\"\n />\n\n {/* 脚注列表 */}\n <div className=\"footnote-content max-h-96 overflow-y-auto\">\n {filteredFootnotes.length === 0 ? (\n <div className=\"text-center text-sm opacity-60 py-4\">\n {filter ? '未找到匹配的脚注' : '暂无脚注'}\n </div>\n ) : (\n <div className=\"space-y-3\">\n {/* 已定义的脚注 */}\n {defined.length > 0 && (\n <div>\n <div className=\"text-xs font-semibold opacity-70 mb-1 px-2\">已定义</div>\n {defined.map((footnote) => (\n <div\n key={footnote.id}\n className=\"footnote-item bg-base-200 rounded p-2 mb-1 hover:bg-base-300 cursor-pointer transition-colors\"\n >\n <div className=\"flex items-center justify-between mb-1\">\n <span className=\"font-mono text-sm font-semibold text-primary\">\n [^{footnote.id}]\n </span>\n <div className=\"flex gap-1\">\n {footnote.definitionLine && (\n <button\n className=\"btn btn-xs btn-ghost tooltip tooltip-left\"\n data-tip=\"跳转到定义\"\n onClick={() => {\n onFootnoteClick(footnote.definitionLine!);\n if (onJumpToDefinition) {\n onJumpToDefinition(footnote.id, footnote.definitionLine!);\n }\n }}\n title=\"跳转到定义\"\n >\n <svg className=\"w-3 h-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\"\n />\n </svg>\n </button>\n )}\n </div>\n </div>\n <div className=\"text-xs opacity-70 mb-2\">\n {footnote.definitionLine && `定义: 第 ${footnote.definitionLine} 行`}\n {footnote.referenceLines && footnote.referenceLines.length > 0 && (\n <div className=\"mt-1\">\n 引用 ({footnote.referenceLines.length}): \n {footnote.referenceLines.map((refLine, idx) => (\n <button\n key={idx}\n className=\"btn btn-xs btn-ghost ml-1 text-info\"\n onClick={() => {\n onFootnoteClick(refLine);\n if (onJumpToReference) {\n onJumpToReference(footnote.id, refLine);\n }\n }}\n title={`跳转到第 ${refLine} 行`}\n >\n L{refLine}\n </button>\n ))}\n </div>\n )}\n </div>\n </div>\n ))}\n </div>\n )}\n\n {/* 未定义的脚注 */}\n {undefined.length > 0 && (\n <div>\n <div className=\"text-xs font-semibold opacity-70 mb-1 px-2 text-warning\">\n 未定义\n </div>\n {undefined.map((footnote) => (\n <div\n key={footnote.id}\n className=\"footnote-item bg-warning/10 border border-warning/30 rounded p-2 mb-1 hover:bg-warning/20 cursor-pointer transition-colors\"\n >\n <div className=\"flex items-center justify-between mb-1\">\n <span className=\"font-mono text-sm font-semibold text-warning\">\n [^{footnote.id}]\n </span>\n <button\n className=\"btn btn-xs btn-ghost\"\n onClick={() => onFootnoteClick(footnote.line)}\n title=\"跳转到引用\"\n >\n <svg className=\"w-3 h-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M13 7l5 5m0 0l-5 5m5-5H6\"\n />\n </svg>\n </button>\n </div>\n <div className=\"text-xs opacity-70\">\n 引用: 第 {footnote.line} 行 | ⚠️ 缺少定义\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport default FootnotePanel;\n\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HistoryPanel.js","names":[],"sources":["../../../../../src/components/pro/CodeEditor/panels/HistoryPanel.tsx"],"sourcesContent":["import React, { useState } from 'react';\n\nexport interface HistoryEntry {\n id: string;\n timestamp: Date;\n content: string;\n description?: string;\n}\n\nexport interface HistoryPanelProps {\n history: HistoryEntry[];\n currentIndex: number;\n onRestore: (index: number) => void;\n onClear?: () => void;\n className?: string;\n height?: string;\n maxHeight?: string;\n}\n\nconst HistoryPanel: React.FC<HistoryPanelProps> = ({\n history,\n currentIndex,\n onRestore,\n onClear,\n className = '',\n height,\n maxHeight = '600px',\n}) => {\n const [expandedEntry, setExpandedEntry] = useState<string | null>(null);\n\n const formatTimestamp = (date: Date) => {\n const now = new Date();\n const diff = now.getTime() - date.getTime();\n const seconds = Math.floor(diff / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n\n if (days > 0) {\n return `${days}d ago`;\n } else if (hours > 0) {\n return `${hours}h ago`;\n } else if (minutes > 0) {\n return `${minutes}m ago`;\n } else {\n return `${seconds}s ago`;\n }\n };\n\n const formatTime = (date: Date) => {\n return date.toLocaleTimeString('en-US', {\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n });\n };\n\n const toggleExpand = (id: string) => {\n setExpandedEntry(expandedEntry === id ? null : id);\n };\n\n const getContentPreview = (content: string, maxLength: number = 50) => {\n const firstLine = content.split('\\n')[0];\n if (firstLine.length > maxLength) {\n return firstLine.substring(0, maxLength) + '...';\n }\n return firstLine;\n };\n\n return (\n <div className={`history-panel bg-base-100 border border-base-300 rounded-lg p-2 ${className}`}>\n <div className=\"history-header mb-2\">\n <div className=\"flex items-center gap-2 px-2 py-1 mb-3 border-b border-base-300\">\n <svg className=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n <span className=\"font-semibold\">History</span>\n <span className=\"text-xs opacity-60 ml-auto\">({history.length})</span>\n </div>\n\n {/* Actions */}\n <div className=\"flex gap-2 mb-2\">\n <button\n className=\"btn btn-xs btn-ghost flex-1\"\n onClick={onClear}\n disabled={history.length === 0}\n title=\"Clear history\"\n >\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\"\n />\n </svg>\n Clear\n </button>\n </div>\n </div>\n\n <div\n className=\"history-content overflow-y-auto\"\n style={{\n height: height,\n maxHeight: !height ? maxHeight : undefined\n }}\n >\n {history.length === 0 ? (\n <div className=\"text-center text-sm opacity-60 py-4\">\n No history yet\n </div>\n ) : (\n <div className=\"space-y-1\">\n {[...history].reverse().map((entry, reverseIndex) => {\n const index = history.length - 1 - reverseIndex;\n const isExpanded = expandedEntry === entry.id;\n const isCurrent = index === currentIndex;\n const lineCount = entry.content.split('\\n').length;\n const versionNumber = index + 1;\n\n return (\n <div\n key={entry.id}\n className={`history-item border rounded p-2 cursor-pointer transition-colors ${isCurrent\n ? 'border-primary bg-primary/10'\n : 'border-base-300 hover:bg-base-200'\n }`}\n >\n <div\n className=\"flex items-start gap-2\"\n onClick={() => toggleExpand(entry.id)}\n >\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2 mb-1\">\n <span className=\"font-mono text-xs font-bold\">\n #{versionNumber}\n </span>\n {isCurrent && (\n <span className=\"badge badge-primary badge-xs\">Current</span>\n )}\n <span className=\"text-xs opacity-60 ml-auto\">\n {formatTimestamp(entry.timestamp)}\n </span>\n </div>\n\n {entry.description && (\n <div className=\"text-sm mb-1\">{entry.description}</div>\n )}\n\n <div className=\"text-xs font-mono opacity-70 truncate\">\n {getContentPreview(entry.content)}\n </div>\n\n <div className=\"text-xs opacity-50 mt-1\">\n {formatTime(entry.timestamp)} • {lineCount} lines\n </div>\n </div>\n\n <button\n className={`btn btn-xs btn-ghost transition-transform ${isExpanded ? 'rotate-180' : ''\n }`}\n >\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 9l-7 7-7-7\"\n />\n </svg>\n </button>\n </div>\n\n {isExpanded && (\n <div className=\"mt-2 pt-2 border-t border-base-300\">\n <div className=\"bg-base-200 rounded p-2 mb-2 max-h-32 overflow-y-auto\">\n <pre className=\"text-xs font-mono whitespace-pre-wrap break-words\">\n {entry.content}\n </pre>\n </div>\n\n <button\n className=\"btn btn-xs btn-primary w-full\"\n onClick={(e) => {\n e.stopPropagation();\n onRestore(index);\n }}\n disabled={isCurrent}\n >\n <svg\n className=\"w-4 h-4 mr-1\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\"\n />\n </svg>\n Restore this version\n </button>\n </div>\n )}\n </div>\n );\n })}\n </div>\n )}\n </div>\n\n <style>{`\n .history-panel .history-item {\n transition: all 0.2s ease;\n }\n\n .history-panel .history-item:hover {\n transform: translateX(2px);\n }\n `}</style>\n </div>\n );\n};\n\nexport default HistoryPanel;\n\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"HistoryPanel.js","names":[],"sources":["../../../../../src/components/pro/CodeEditor/panels/HistoryPanel.tsx"],"sourcesContent":["import React, { useState } from 'react';\n\nexport interface HistoryEntry {\n id: string;\n timestamp: Date;\n content: string;\n description?: string;\n}\n\nexport interface HistoryPanelProps {\n history: HistoryEntry[];\n currentIndex: number;\n onRestore: (index: number) => void;\n onClear?: () => void;\n className?: string;\n height?: string;\n maxHeight?: string;\n}\n\nconst HistoryPanel: React.FC<HistoryPanelProps> = ({\n history,\n currentIndex,\n onRestore,\n onClear,\n className = '',\n height,\n maxHeight = '600px',\n}) => {\n const [expandedEntry, setExpandedEntry] = useState<string | null>(null);\n\n const formatTimestamp = (date: Date) => {\n const now = new Date();\n const diff = now.getTime() - date.getTime();\n const seconds = Math.floor(diff / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n\n if (days > 0) {\n return `${days}d ago`;\n } else if (hours > 0) {\n return `${hours}h ago`;\n } else if (minutes > 0) {\n return `${minutes}m ago`;\n } else {\n return `${seconds}s ago`;\n }\n };\n\n const formatTime = (date: Date) => {\n return date.toLocaleTimeString('en-US', {\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n });\n };\n\n const toggleExpand = (id: string) => {\n setExpandedEntry(expandedEntry === id ? null : id);\n };\n\n const getContentPreview = (content: string, maxLength: number = 50) => {\n const firstLine = content.split('\\n')[0];\n if (firstLine.length > maxLength) {\n return firstLine.substring(0, maxLength) + '...';\n }\n return firstLine;\n };\n\n return (\n <div className={`history-panel bg-base-100 border border-base-300 rounded-lg p-2 ${className}`}>\n <div className=\"history-header mb-2\">\n <div className=\"flex items-center gap-2 px-2 py-1 mb-3 border-b border-base-300\">\n <svg className=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n <span className=\"font-semibold\">History</span>\n <span className=\"text-xs opacity-60 ml-auto\">({history.length})</span>\n </div>\n\n {/* Actions */}\n <div className=\"flex gap-2 mb-2\">\n <button\n className=\"btn btn-xs btn-ghost flex-1\"\n onClick={onClear}\n disabled={history.length === 0}\n title=\"Clear history\"\n >\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\"\n />\n </svg>\n Clear\n </button>\n </div>\n </div>\n\n <div\n className=\"history-content overflow-y-auto\"\n style={{\n height: height,\n maxHeight: !height ? maxHeight : undefined\n }}\n >\n {history.length === 0 ? (\n <div className=\"text-center text-sm opacity-60 py-4\">\n No history yet\n </div>\n ) : (\n <div className=\"space-y-1\">\n {[...history].reverse().map((entry, reverseIndex) => {\n const index = history.length - 1 - reverseIndex;\n const isExpanded = expandedEntry === entry.id;\n const isCurrent = index === currentIndex;\n const lineCount = entry.content.split('\\n').length;\n const versionNumber = index + 1;\n\n return (\n <div\n key={entry.id}\n className={`history-item border rounded p-2 cursor-pointer transition-colors ${isCurrent\n ? 'border-primary bg-primary/10'\n : 'border-base-300 hover:bg-base-200'\n }`}\n >\n <div\n className=\"flex items-start gap-2\"\n onClick={() => toggleExpand(entry.id)}\n >\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2 mb-1\">\n <span className=\"font-mono text-xs font-bold\">\n #{versionNumber}\n </span>\n {isCurrent && (\n <span className=\"badge badge-primary badge-xs\">Current</span>\n )}\n <span className=\"text-xs opacity-60 ml-auto\">\n {formatTimestamp(entry.timestamp)}\n </span>\n </div>\n\n {entry.description && (\n <div className=\"text-sm mb-1\">{entry.description}</div>\n )}\n\n <div className=\"text-xs font-mono opacity-70 truncate\">\n {getContentPreview(entry.content)}\n </div>\n\n <div className=\"text-xs opacity-50 mt-1\">\n {formatTime(entry.timestamp)} • {lineCount} lines\n </div>\n </div>\n\n <button\n className={`btn btn-xs btn-ghost transition-transform ${isExpanded ? 'rotate-180' : ''\n }`}\n >\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 9l-7 7-7-7\"\n />\n </svg>\n </button>\n </div>\n\n {isExpanded && (\n <div className=\"mt-2 pt-2 border-t border-base-300\">\n <div className=\"bg-base-200 rounded p-2 mb-2 max-h-32 overflow-y-auto\">\n <pre className=\"text-xs font-mono whitespace-pre-wrap break-words\">\n {entry.content}\n </pre>\n </div>\n\n <button\n className=\"btn btn-xs btn-primary w-full\"\n onClick={(e) => {\n e.stopPropagation();\n onRestore(index);\n }}\n disabled={isCurrent}\n >\n <svg\n className=\"w-4 h-4 mr-1\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\"\n />\n </svg>\n Restore this version\n </button>\n </div>\n )}\n </div>\n );\n })}\n </div>\n )}\n </div>\n\n <style>{`\n .history-panel .history-item {\n transition: all 0.2s ease;\n }\n\n .history-panel .history-item:hover {\n transform: translateX(2px);\n }\n `}</style>\n </div>\n );\n};\n\nexport default HistoryPanel;\n\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OutlinePanel.js","names":[],"sources":["../../../../../src/components/pro/CodeEditor/panels/OutlinePanel.tsx"],"sourcesContent":["import React from 'react';\nimport { OutlineItem } from '../types';\n\nexport interface OutlinePanelProps {\n outline: OutlineItem[];\n onItemClick: (line: number) => void;\n className?: string;\n}\n\nconst OutlinePanel: React.FC<OutlinePanelProps> = ({ outline, onItemClick, className = '' }) => {\n const getIcon = (type: OutlineItem['type']) => {\n switch (type) {\n case 'function':\n return (\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4\" />\n </svg>\n );\n case 'class':\n return (\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10\" />\n </svg>\n );\n case 'method':\n return (\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z\" />\n </svg>\n );\n case 'variable':\n return (\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z\" />\n </svg>\n );\n case 'interface':\n return (\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M4 5a1 1 0 011-1h4a1 1 0 011 1v7a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM14 5a1 1 0 011-1h4a1 1 0 011 1v7a1 1 0 01-1 1h-4a1 1 0 01-1-1V5z\" />\n </svg>\n );\n case 'type':\n return (\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>\n );\n default:\n return null;\n }\n };\n\n const renderOutlineItem = (item: OutlineItem, depth: number = 0) => {\n return (\n <div key={`${item.name}-${item.line}`}>\n <div\n className=\"outline-item flex items-center gap-2 px-2 py-1 hover:bg-base-200 cursor-pointer rounded\"\n style={{ paddingLeft: `${depth * 16 + 8}px` }}\n onClick={() => onItemClick(item.line)}\n >\n <span className=\"text-primary\">{getIcon(item.type)}</span>\n <span className=\"text-sm truncate flex-1\">{item.name}</span>\n <span className=\"text-xs opacity-60\">{item.line}</span>\n </div>\n {item.children && item.children.length > 0 && (\n <div className=\"outline-children\">\n {item.children.map((child) => renderOutlineItem(child, depth + 1))}\n </div>\n )}\n </div>\n );\n };\n\n return (\n <div className={`outline-panel bg-base-100 border border-base-300 rounded-lg p-2 ${className}`}>\n <div className=\"outline-header flex items-center gap-2 px-2 py-1 mb-2 border-b border-base-300\">\n <svg className=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M4 6h16M4 12h16M4 18h7\" />\n </svg>\n <span className=\"font-semibold\">大纲</span>\n </div>\n <div className=\"outline-content max-h-96 overflow-y-auto\">\n {outline.length === 0 ? (\n <div className=\"text-center text-sm opacity-60 py-4\">暂无大纲</div>\n ) : (\n outline.map((item) => renderOutlineItem(item))\n )}\n </div>\n </div>\n );\n};\n\nexport default OutlinePanel;\n\n"],"mappings":";;AASA,IAAM,IAAA,CAA6C,EAAE,SAAA,GAAS,aAAA,GAAa,WAAA,IAAY,GAAA,MAAS;AAC9F,QAAM,IAAA,CAAW,MAA8B;AAC7C,YAAQ,GAAR;AAAA,MACE,KAAK;AACH,eACE,gBAAA,EAAC,OAAD;AAAA,UAAK,WAAU;AAAA,UAAU,MAAK;AAAA,UAAO,SAAQ;AAAA,UAAY,QAAO;AAAA,
|
|
1
|
+
{"version":3,"file":"OutlinePanel.js","names":[],"sources":["../../../../../src/components/pro/CodeEditor/panels/OutlinePanel.tsx"],"sourcesContent":["import React from 'react';\nimport { OutlineItem } from '../types';\n\nexport interface OutlinePanelProps {\n outline: OutlineItem[];\n onItemClick: (line: number) => void;\n className?: string;\n}\n\nconst OutlinePanel: React.FC<OutlinePanelProps> = ({ outline, onItemClick, className = '' }) => {\n const getIcon = (type: OutlineItem['type']) => {\n switch (type) {\n case 'function':\n return (\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4\" />\n </svg>\n );\n case 'class':\n return (\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10\" />\n </svg>\n );\n case 'method':\n return (\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z\" />\n </svg>\n );\n case 'variable':\n return (\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z\" />\n </svg>\n );\n case 'interface':\n return (\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M4 5a1 1 0 011-1h4a1 1 0 011 1v7a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM14 5a1 1 0 011-1h4a1 1 0 011 1v7a1 1 0 01-1 1h-4a1 1 0 01-1-1V5z\" />\n </svg>\n );\n case 'type':\n return (\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>\n );\n default:\n return null;\n }\n };\n\n const renderOutlineItem = (item: OutlineItem, depth: number = 0) => {\n return (\n <div key={`${item.name}-${item.line}`}>\n <div\n className=\"outline-item flex items-center gap-2 px-2 py-1 hover:bg-base-200 cursor-pointer rounded\"\n style={{ paddingLeft: `${depth * 16 + 8}px` }}\n onClick={() => onItemClick(item.line)}\n >\n <span className=\"text-primary\">{getIcon(item.type)}</span>\n <span className=\"text-sm truncate flex-1\">{item.name}</span>\n <span className=\"text-xs opacity-60\">{item.line}</span>\n </div>\n {item.children && item.children.length > 0 && (\n <div className=\"outline-children\">\n {item.children.map((child) => renderOutlineItem(child, depth + 1))}\n </div>\n )}\n </div>\n );\n };\n\n return (\n <div className={`outline-panel bg-base-100 border border-base-300 rounded-lg p-2 ${className}`}>\n <div className=\"outline-header flex items-center gap-2 px-2 py-1 mb-2 border-b border-base-300\">\n <svg className=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M4 6h16M4 12h16M4 18h7\" />\n </svg>\n <span className=\"font-semibold\">大纲</span>\n </div>\n <div className=\"outline-content max-h-96 overflow-y-auto\">\n {outline.length === 0 ? (\n <div className=\"text-center text-sm opacity-60 py-4\">暂无大纲</div>\n ) : (\n outline.map((item) => renderOutlineItem(item))\n )}\n </div>\n </div>\n );\n};\n\nexport default OutlinePanel;\n\n"],"mappings":";;AASA,IAAM,IAAA,CAA6C,EAAE,SAAA,GAAS,aAAA,GAAa,WAAA,IAAY,GAAA,MAAS;AAC9F,QAAM,IAAA,CAAW,MAA8B;AAC7C,YAAQ,GAAR;AAAA,MACE,KAAK;AACH,eACE,gBAAA,EAAC,OAAD;AAAA,UAAK,WAAU;AAAA,UAAU,MAAK;AAAA,UAAO,SAAQ;AAAA,UAAY,QAAO;AAAA,UAC9D,UAAA,gBAAA,EAAC,QAAD;AAAA,YAAM,eAAc;AAAA,YAAQ,gBAAe;AAAA,YAAQ,aAAa;AAAA,YAAG,GAAE;AAAA,UAAyC,CAAA;AAAA,QAC3G,CAAA;AAAA,MAET,KAAK;AACH,eACE,gBAAA,EAAC,OAAD;AAAA,UAAK,WAAU;AAAA,UAAU,MAAK;AAAA,UAAO,SAAQ;AAAA,UAAY,QAAO;AAAA,UAC9D,UAAA,gBAAA,EAAC,QAAD;AAAA,YAAM,eAAc;AAAA,YAAQ,gBAAe;AAAA,YAAQ,aAAa;AAAA,YAAG,GAAE;AAAA,UAA0J,CAAA;AAAA,QAC5N,CAAA;AAAA,MAET,KAAK;AACH,eACE,gBAAA,EAAC,OAAD;AAAA,UAAK,WAAU;AAAA,UAAU,MAAK;AAAA,UAAO,SAAQ;AAAA,UAAY,QAAO;AAAA,UAC9D,UAAA,gBAAA,EAAC,QAAD;AAAA,YAAM,eAAc;AAAA,YAAQ,gBAAe;AAAA,YAAQ,aAAa;AAAA,YAAG,GAAE;AAAA,UAAwF,CAAA;AAAA,QAC1J,CAAA;AAAA,MAET,KAAK;AACH,eACE,gBAAA,EAAC,OAAD;AAAA,UAAK,WAAU;AAAA,UAAU,MAAK;AAAA,UAAO,SAAQ;AAAA,UAAY,QAAO;AAAA,UAC9D,UAAA,gBAAA,EAAC,QAAD;AAAA,YAAM,eAAc;AAAA,YAAQ,gBAAe;AAAA,YAAQ,aAAa;AAAA,YAAG,GAAE;AAAA,UAAgI,CAAA;AAAA,QAClM,CAAA;AAAA,MAET,KAAK;AACH,eACE,gBAAA,EAAC,OAAD;AAAA,UAAK,WAAU;AAAA,UAAU,MAAK;AAAA,UAAO,SAAQ;AAAA,UAAY,QAAO;AAAA,UAC9D,UAAA,gBAAA,EAAC,QAAD;AAAA,YAAM,eAAc;AAAA,YAAQ,gBAAe;AAAA,YAAQ,aAAa;AAAA,YAAG,GAAE;AAAA,UAAoI,CAAA;AAAA,QACtM,CAAA;AAAA,MAET,KAAK;AACH,eACE,gBAAA,EAAC,OAAD;AAAA,UAAK,WAAU;AAAA,UAAU,MAAK;AAAA,UAAO,SAAQ;AAAA,UAAY,QAAO;AAAA,UAC9D,UAAA,gBAAA,EAAC,QAAD;AAAA,YAAM,eAAc;AAAA,YAAQ,gBAAe;AAAA,YAAQ,aAAa;AAAA,YAAG,GAAE;AAAA,UAAwH,CAAA;AAAA,QAC1L,CAAA;AAAA,MAET;AACE,eAAO;AAAA,IACX;AAAA,EACF,GAEM,IAAA,CAAqB,GAAmB,IAAgB,MAE1D,gBAAA,EAAC,OAAD,EAAA,UAAA,CACE,gBAAA,EAAC,OAAD;AAAA,IACE,WAAU;AAAA,IACV,OAAO,EAAE,aAAa,GAAG,IAAQ,KAAK,CAAA,KAAM;AAAA,IAC5C,SAAA,MAAe,EAAY,EAAK,IAAI;AAAA,IAHtC,UAAA;AAAA,MAKE,gBAAA,EAAC,QAAD;AAAA,QAAM,WAAU;AAAA,QAAgB,UAAA,EAAQ,EAAK,IAAI;AAAA,MAAQ,CAAA;AAAA,MACzD,gBAAA,EAAC,QAAD;AAAA,QAAM,WAAU;AAAA,QAA2B,UAAA,EAAK;AAAA,MAAW,CAAA;AAAA,MAC3D,gBAAA,EAAC,QAAD;AAAA,QAAM,WAAU;AAAA,QAAsB,UAAA,EAAK;AAAA,MAAW,CAAA;AAAA,IACnD;AAAA,EACJ,CAAA,GAAA,EAAK,YAAY,EAAK,SAAS,SAAS,KACvC,gBAAA,EAAC,OAAD;AAAA,IAAK,WAAU;AAAA,IACZ,UAAA,EAAK,SAAS,IAAA,CAAK,MAAU,EAAkB,GAAO,IAAQ,CAAC,CAAC;AAAA,EAC9D,CAAA,CAEJ,EAAA,GAfK,GAAG,EAAK,IAAA,IAAQ,EAAK,IAAA,EAe1B;AAIT,SACE,gBAAA,EAAC,OAAD;AAAA,IAAK,WAAW,mEAAmE,CAAA;AAAA,IAAnF,UAAA,CACE,gBAAA,EAAC,OAAD;AAAA,MAAK,WAAU;AAAA,MAAf,UAAA,CACE,gBAAA,EAAC,OAAD;AAAA,QAAK,WAAU;AAAA,QAAU,MAAK;AAAA,QAAO,SAAQ;AAAA,QAAY,QAAO;AAAA,QAC9D,UAAA,gBAAA,EAAC,QAAD;AAAA,UAAM,eAAc;AAAA,UAAQ,gBAAe;AAAA,UAAQ,aAAa;AAAA,UAAG,GAAE;AAAA,QAA0B,CAAA;AAAA,MAC5F,CAAA,GACL,gBAAA,EAAC,QAAD;AAAA,QAAM,WAAU;AAAA,QAAgB,UAAA;AAAA,MAAQ,CAAA,CACrC;AAAA,IACL,CAAA,GAAA,gBAAA,EAAC,OAAD;AAAA,MAAK,WAAU;AAAA,MACZ,UAAA,EAAQ,WAAW,IAClB,gBAAA,EAAC,OAAD;AAAA,QAAK,WAAU;AAAA,QAAsC,UAAA;AAAA,MAAS,CAAA,IAE9D,EAAQ,IAAA,CAAK,MAAS,EAAkB,CAAI,CAAC;AAAA,IAE5C,CAAA,CACF;AAAA;AAET"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableOfContentsPanel.js","names":[],"sources":["../../../../../src/components/pro/CodeEditor/panels/TableOfContentsPanel.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { MarkdownSection } from '../editors/markdownExtensions';\nimport { EditorTheme } from '../types';\n\nexport interface TableOfContentsPanelProps {\n sections: MarkdownSection[];\n onSectionClick: (line: number) => void;\n currentLine?: number;\n className?: string;\n theme?: EditorTheme;\n}\n\nconst TableOfContentsPanel: React.FC<TableOfContentsPanelProps> = ({\n sections,\n onSectionClick,\n currentLine = 1,\n className = '',\n theme = 'light',\n}) => {\n const [filter, setFilter] = useState('');\n const [expandedSections, setExpandedSections] = useState<Set<string>>(new Set());\n\n // 过滤章节\n const filteredSections = sections.filter((section) =>\n section.title.toLowerCase().includes(filter.toLowerCase())\n );\n\n // 构建层级结构\n const buildHierarchy = (sections: MarkdownSection[]) => {\n const root: Array<MarkdownSection & { children?: MarkdownSection[] }> = [];\n const stack: Array<MarkdownSection & { children?: MarkdownSection[] }> = [];\n\n for (const section of sections) {\n const node = { ...section, children: [] };\n\n // 找到合适的父节点\n while (stack.length > 0 && stack[stack.length - 1].level >= section.level) {\n stack.pop();\n }\n\n if (stack.length === 0) {\n root.push(node);\n } else {\n const parent = stack[stack.length - 1];\n if (!parent.children) parent.children = [];\n parent.children.push(node);\n }\n\n stack.push(node);\n }\n\n return root;\n };\n\n const hierarchy = buildHierarchy(filteredSections);\n\n // 切换展开/折叠\n const toggleExpand = (id: string) => {\n const newExpanded = new Set(expandedSections);\n if (newExpanded.has(id)) {\n newExpanded.delete(id);\n } else {\n newExpanded.add(id);\n }\n setExpandedSections(newExpanded);\n };\n\n // 获取章节图标\n const getSectionIcon = (level: number) => {\n const icons = [\n // H1\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z\" />\n </svg>,\n // H2\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z\" />\n </svg>,\n // H3\n <svg className=\"w-3 h-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>,\n // H4\n <svg className=\"w-3 h-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>,\n // H5\n <svg className=\"w-2 h-2\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>,\n // H6\n <svg className=\"w-2 h-2\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>,\n ];\n return icons[level - 1] || icons[0];\n };\n\n // 渲染章节项\n const renderSection = (\n section: MarkdownSection & { children?: MarkdownSection[] },\n depth: number = 0\n ) => {\n const hasChildren = section.children && section.children.length > 0;\n const isExpanded = expandedSections.has(section.id);\n const isActive = currentLine >= section.line && \n (sections.find(s => s.line > section.line && s.level <= section.level)?.line || Infinity) > currentLine;\n\n const levelColors = [\n 'text-primary',\n 'text-secondary',\n 'text-accent',\n 'text-info',\n 'text-success',\n 'text-warning',\n ];\n const colorClass = levelColors[(section.level - 1) % levelColors.length];\n\n return (\n <div key={section.id}>\n <div\n className={`toc-item flex items-center gap-2 px-2 py-1.5 rounded cursor-pointer transition-colors ${\n isActive ? 'bg-primary/20 font-semibold' : 'hover:bg-base-200'\n }`}\n style={{ paddingLeft: `${depth * 12 + 8}px` }}\n onClick={() => onSectionClick(section.line)}\n >\n {hasChildren && (\n <button\n className=\"btn btn-xs btn-ghost btn-circle\"\n onClick={(e) => {\n e.stopPropagation();\n toggleExpand(section.id);\n }}\n >\n {isExpanded ? (\n <svg className=\"w-3 h-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M19 9l-7 7-7-7\" />\n </svg>\n ) : (\n <svg className=\"w-3 h-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\n </svg>\n )}\n </button>\n )}\n {!hasChildren && <span className=\"w-6\"></span>}\n <span className={colorClass}>{getSectionIcon(section.level)}</span>\n <span className=\"text-sm truncate flex-1\" title={section.title}>\n {section.title}\n </span>\n <span className=\"text-xs opacity-60\">{section.line}</span>\n </div>\n\n {hasChildren && (isExpanded || !hasChildren) && (\n <div className=\"toc-children\">\n {section.children!.map((child) => renderSection(child, depth + 1))}\n </div>\n )}\n </div>\n );\n };\n\n return (\n <div className={`toc-panel bg-base-100 border border-base-300 rounded-lg p-2 ${className}`}>\n {/* 标题 */}\n <div className=\"toc-header flex items-center gap-2 px-2 py-1 mb-2 border-b border-base-300\">\n <svg className=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 6h16M4 10h16M4 14h16M4 18h16\"\n />\n </svg>\n <span className=\"font-semibold\">目录</span>\n <span className=\"text-xs opacity-60 ml-auto\">({sections.length})</span>\n </div>\n\n {/* 搜索框 */}\n <input\n type=\"text\"\n placeholder=\"搜索章节...\"\n value={filter}\n onChange={(e) => setFilter(e.target.value)}\n className=\"input input-sm input-bordered w-full mb-2\"\n />\n\n {/* 操作按钮 */}\n <div className=\"flex gap-1 mb-2\">\n <button\n className=\"btn btn-xs btn-ghost\"\n onClick={() => {\n const allIds = new Set(sections.map((s) => s.id));\n setExpandedSections(allIds);\n }}\n >\n 全部展开\n </button>\n <button\n className=\"btn btn-xs btn-ghost\"\n onClick={() => setExpandedSections(new Set())}\n >\n 全部折叠\n </button>\n </div>\n\n {/* 章节列表 */}\n <div className=\"toc-content max-h-[600px] overflow-y-auto\">\n {filteredSections.length === 0 ? (\n <div className=\"text-center text-sm opacity-60 py-4\">\n {filter ? '未找到匹配的章节' : '暂无章节'}\n </div>\n ) : (\n hierarchy.map((section) => renderSection(section))\n )}\n </div>\n\n <style>{`\n .toc-item {\n user-select: none;\n }\n .toc-children {\n margin-top: 2px;\n }\n .toc-panel {\n position: relative;\n z-index: 1;\n }\n .toc-item button {\n z-index: 2;\n }\n `}</style>\n </div>\n );\n};\n\nexport default TableOfContentsPanel;\n\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TableOfContentsPanel.js","names":[],"sources":["../../../../../src/components/pro/CodeEditor/panels/TableOfContentsPanel.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { MarkdownSection } from '../editors/markdownExtensions';\nimport { EditorTheme } from '../types';\n\nexport interface TableOfContentsPanelProps {\n sections: MarkdownSection[];\n onSectionClick: (line: number) => void;\n currentLine?: number;\n className?: string;\n theme?: EditorTheme;\n}\n\nconst TableOfContentsPanel: React.FC<TableOfContentsPanelProps> = ({\n sections,\n onSectionClick,\n currentLine = 1,\n className = '',\n theme = 'light',\n}) => {\n const [filter, setFilter] = useState('');\n const [expandedSections, setExpandedSections] = useState<Set<string>>(new Set());\n\n // 过滤章节\n const filteredSections = sections.filter((section) =>\n section.title.toLowerCase().includes(filter.toLowerCase())\n );\n\n // 构建层级结构\n const buildHierarchy = (sections: MarkdownSection[]) => {\n const root: Array<MarkdownSection & { children?: MarkdownSection[] }> = [];\n const stack: Array<MarkdownSection & { children?: MarkdownSection[] }> = [];\n\n for (const section of sections) {\n const node = { ...section, children: [] };\n\n // 找到合适的父节点\n while (stack.length > 0 && stack[stack.length - 1].level >= section.level) {\n stack.pop();\n }\n\n if (stack.length === 0) {\n root.push(node);\n } else {\n const parent = stack[stack.length - 1];\n if (!parent.children) parent.children = [];\n parent.children.push(node);\n }\n\n stack.push(node);\n }\n\n return root;\n };\n\n const hierarchy = buildHierarchy(filteredSections);\n\n // 切换展开/折叠\n const toggleExpand = (id: string) => {\n const newExpanded = new Set(expandedSections);\n if (newExpanded.has(id)) {\n newExpanded.delete(id);\n } else {\n newExpanded.add(id);\n }\n setExpandedSections(newExpanded);\n };\n\n // 获取章节图标\n const getSectionIcon = (level: number) => {\n const icons = [\n // H1\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z\" />\n </svg>,\n // H2\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z\" />\n </svg>,\n // H3\n <svg className=\"w-3 h-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>,\n // H4\n <svg className=\"w-3 h-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>,\n // H5\n <svg className=\"w-2 h-2\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>,\n // H6\n <svg className=\"w-2 h-2\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>,\n ];\n return icons[level - 1] || icons[0];\n };\n\n // 渲染章节项\n const renderSection = (\n section: MarkdownSection & { children?: MarkdownSection[] },\n depth: number = 0\n ) => {\n const hasChildren = section.children && section.children.length > 0;\n const isExpanded = expandedSections.has(section.id);\n const isActive = currentLine >= section.line && \n (sections.find(s => s.line > section.line && s.level <= section.level)?.line || Infinity) > currentLine;\n\n const levelColors = [\n 'text-primary',\n 'text-secondary',\n 'text-accent',\n 'text-info',\n 'text-success',\n 'text-warning',\n ];\n const colorClass = levelColors[(section.level - 1) % levelColors.length];\n\n return (\n <div key={section.id}>\n <div\n className={`toc-item flex items-center gap-2 px-2 py-1.5 rounded cursor-pointer transition-colors ${\n isActive ? 'bg-primary/20 font-semibold' : 'hover:bg-base-200'\n }`}\n style={{ paddingLeft: `${depth * 12 + 8}px` }}\n onClick={() => onSectionClick(section.line)}\n >\n {hasChildren && (\n <button\n className=\"btn btn-xs btn-ghost btn-circle\"\n onClick={(e) => {\n e.stopPropagation();\n toggleExpand(section.id);\n }}\n >\n {isExpanded ? (\n <svg className=\"w-3 h-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M19 9l-7 7-7-7\" />\n </svg>\n ) : (\n <svg className=\"w-3 h-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\n </svg>\n )}\n </button>\n )}\n {!hasChildren && <span className=\"w-6\"></span>}\n <span className={colorClass}>{getSectionIcon(section.level)}</span>\n <span className=\"text-sm truncate flex-1\" title={section.title}>\n {section.title}\n </span>\n <span className=\"text-xs opacity-60\">{section.line}</span>\n </div>\n\n {hasChildren && (isExpanded || !hasChildren) && (\n <div className=\"toc-children\">\n {section.children!.map((child) => renderSection(child, depth + 1))}\n </div>\n )}\n </div>\n );\n };\n\n return (\n <div className={`toc-panel bg-base-100 border border-base-300 rounded-lg p-2 ${className}`}>\n {/* 标题 */}\n <div className=\"toc-header flex items-center gap-2 px-2 py-1 mb-2 border-b border-base-300\">\n <svg className=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 6h16M4 10h16M4 14h16M4 18h16\"\n />\n </svg>\n <span className=\"font-semibold\">目录</span>\n <span className=\"text-xs opacity-60 ml-auto\">({sections.length})</span>\n </div>\n\n {/* 搜索框 */}\n <input\n type=\"text\"\n placeholder=\"搜索章节...\"\n value={filter}\n onChange={(e) => setFilter(e.target.value)}\n className=\"input input-sm input-bordered w-full mb-2\"\n />\n\n {/* 操作按钮 */}\n <div className=\"flex gap-1 mb-2\">\n <button\n className=\"btn btn-xs btn-ghost\"\n onClick={() => {\n const allIds = new Set(sections.map((s) => s.id));\n setExpandedSections(allIds);\n }}\n >\n 全部展开\n </button>\n <button\n className=\"btn btn-xs btn-ghost\"\n onClick={() => setExpandedSections(new Set())}\n >\n 全部折叠\n </button>\n </div>\n\n {/* 章节列表 */}\n <div className=\"toc-content max-h-[600px] overflow-y-auto\">\n {filteredSections.length === 0 ? (\n <div className=\"text-center text-sm opacity-60 py-4\">\n {filter ? '未找到匹配的章节' : '暂无章节'}\n </div>\n ) : (\n hierarchy.map((section) => renderSection(section))\n )}\n </div>\n\n <style>{`\n .toc-item {\n user-select: none;\n }\n .toc-children {\n margin-top: 2px;\n }\n .toc-panel {\n position: relative;\n z-index: 1;\n }\n .toc-item button {\n z-index: 2;\n }\n `}</style>\n </div>\n );\n};\n\nexport default TableOfContentsPanel;\n\n"],"mappings":"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"}
|