feat: 代码片段功能与 Markdown 内嵌片段渲染、文档截图等

This commit is contained in:
2026-10-09 18:53:38 +08:00
parent 5598e1cbb7
commit da72843c70
64 changed files with 7047 additions and 248 deletions

View File

@@ -45,6 +45,7 @@ import { toast } from "@/lib/toast";
import MarkdownBodyClient from "@/components/MarkdownBodyClient";
import ImageInsertModal from "@/components/ImageInsertModal";
import TimelineEditor from "@/components/TimelineEditor";
import SnippetPickerModal from "@/components/SnippetPickerModal";
import { ENTRIES_TEMPLATE, ENTRIES_TEMPLATE_AUTO } from "@/lib/entryBlocks";
import EmojiPicker from "@/components/EmojiPicker";
import { resolveTimelineBlockForEdit, parseVideoInput } from "@/lib/directiveBlocks";
@@ -260,6 +261,7 @@ export default function MarkdownEditor({
const [activeWheel, setActiveWheel] = useState<"fg" | "bg" | null>(null);
const [colorHsv, setColorHsv] = useState<HSV>({ h: 0, s: 1, v: 1 });
const [videoInput, setVideoInput] = useState("");
const [snippetPickerOpen, setSnippetPickerOpen] = useState(false);
const [toolNarrow, setToolNarrow] = useState(false);
const [uploadError, setUploadError] = useState("");
const [modKey, setModKey] = useState("Ctrl");
@@ -1670,6 +1672,7 @@ export default function MarkdownEditor({
{!isComment && (
<button type="button" role="menuitem" className="j13-md-menu-item" onMouseDown={(e) => e.preventDefault()} onClick={() => openPopover("video")}>视频…</button>
)}
<button type="button" role="menuitem" className="j13-md-menu-item" onMouseDown={(e) => e.preventDefault()} onClick={() => { setPopover(null); setSnippetPickerOpen(true); }}>代码片段…</button>
{toolNarrow && (
<button type="button" role="menuitem" className="j13-md-menu-item" onMouseDown={(e) => e.preventDefault()} onClick={() => { setPopover(null); toggleFullscreen(); }}>{fullscreen ? "退出全屏" : "全屏写作"}</button>
)}
@@ -1712,6 +1715,13 @@ export default function MarkdownEditor({
{popover === "video" && videoPopover}
</div>
)}
{!isComment && !toolNarrow && (
<ToolBtn
label="代码片段"
icon={<Code2 size={15} />}
onClick={() => setSnippetPickerOpen(true)}
/>
)}
{allowHide && !toolNarrow ? (
<div className="j13-md-popover-anchor relative">
<ToolBtn
@@ -1897,6 +1907,12 @@ export default function MarkdownEditor({
onInsertUrl={insertImageUrl}
onPickMedia={(item) => insertAtCursor(`![图片](${item.url})`)}
/>
<SnippetPickerModal
open={snippetPickerOpen}
onClose={() => setSnippetPickerOpen(false)}
onPick={(id) => insertAtCursor(`[snippet id=${id}]`)}
/>
</div>
);
}