feat(artifact): artifact markdown 表格复用 CopyButton

- ArtifactFilePreview 中 Streamdown 的 table 组件覆盖为 MarkdownTable
- artifact 区表格复制/下载行为与聊天区一致
This commit is contained in:
mt 2026-06-11 09:50:22 +08:00
parent 407618baf0
commit f3c160f103

View File

@ -14,6 +14,7 @@ import {
useState, useState,
type CSSProperties, type CSSProperties,
type ComponentProps, type ComponentProps,
type ComponentPropsWithoutRef,
type HTMLAttributes, type HTMLAttributes,
} from "react"; } from "react";
import { toast } from "sonner"; import { toast } from "sonner";
@ -40,6 +41,7 @@ import { CodeEditor } from "@/components/workspace/code-editor";
import { useArtifactContent } from "@/core/artifacts/hooks"; import { useArtifactContent } from "@/core/artifacts/hooks";
import { resolveArtifactURL, urlOfArtifact } from "@/core/artifacts/utils"; import { resolveArtifactURL, urlOfArtifact } from "@/core/artifacts/utils";
import { useI18n } from "@/core/i18n/hooks"; import { useI18n } from "@/core/i18n/hooks";
import { MarkdownTable } from "@/components/workspace/messages/markdown-content";
import { streamdownPlugins } from "@/core/streamdown"; import { streamdownPlugins } from "@/core/streamdown";
import { checkCodeFile, getFileName } from "@/core/utils/files"; import { checkCodeFile, getFileName } from "@/core/utils/files";
import { useMarkdownDownload } from "@/core/utils/markdown-download"; import { useMarkdownDownload } from "@/core/utils/markdown-download";
@ -909,11 +911,26 @@ export function ArtifactFilePreview({
threadId: string; threadId: string;
filepath?: string; filepath?: string;
}) { }) {
const { t } = useI18n();
const zoomScale = zoom / 100; const zoomScale = zoom / 100;
const normalizedContent = useMemo(() => { const normalizedContent = useMemo(() => {
return rewriteArtifactImagePaths(content ?? "", threadId, filepath); return rewriteArtifactImagePaths(content ?? "", threadId, filepath);
}, [content, threadId, filepath]); }, [content, threadId, filepath]);
const streamdownComponents = useMemo(
() => ({
a: CitationLink,
table: (props: ComponentPropsWithoutRef<"table">) => (
<MarkdownTable
copyLabel={t.clipboard.copyToClipboard}
downloadLabel={t.common.download}
{...props}
/>
),
}),
[t.clipboard.copyToClipboard, t.common.download],
);
if (language === "markdown") { if (language === "markdown") {
return ( return (
<div <div
@ -923,7 +940,7 @@ export function ArtifactFilePreview({
<Streamdown <Streamdown
className="w-full" className="w-full"
{...streamdownPlugins} {...streamdownPlugins}
components={{ a: CitationLink }} components={streamdownComponents}
> >
{normalizedContent} {normalizedContent}
</Streamdown> </Streamdown>