refactor(frontend): consolidate citation logic, slim exports and impl
- SafeCitationContent: add loadingOnly and renderBody props.
- loadingOnly: show only loading indicator or null (e.g. write_file step).
- renderBody(parsed): custom body renderer (e.g. artifact preview).
- message-group write_file: use SafeCitationContent(content, isLoading,
rehypePlugins, loadingOnly) instead of local useParsedCitations +
shouldShowCitationLoading + CitationsLoadingIndicator. Pass rehypePlugins
into ToolCall.
- artifact-file-detail markdown preview: use SafeCitationContent with
renderBody((p) => <ArtifactFilePreview ... cleanContent={p.cleanContent}
citationMap={p.citationMap} />). Remove local shouldShowCitationLoading
and CitationsLoadingIndicator branch.
- core/citations: inline buildCitationMap into use-parsed-citations, remove
from utils; stop exporting hasCitationsBlock (internal to shouldShowCitationLoading).
- inline-citation: make InlineCitationCard, InlineCitationCardBody,
InlineCitationSource file-private (no longer exported).
Co-authored-by: Cursor <cursoragent@cursor.com>
---
refactor(前端): 收拢引用逻辑、精简导出与实现
- SafeCitationContent 新增 loadingOnly、renderBody。
- loadingOnly:仅显示加载或 null(如 write_file 步骤)。
- renderBody(parsed):自定义正文渲染(如 artifact 预览)。
- message-group write_file:改用 SafeCitationContent(loadingOnly),去掉
本地 useParsedCitations + shouldShowCitationLoading + CitationsLoadingIndicator,
并向 ToolCall 传入 rehypePlugins。
- artifact-file-detail 的 markdown 预览:改用 SafeCitationContent +
renderBody 渲染 ArtifactFilePreview,去掉本地加载判断与
CitationsLoadingIndicator 分支。
- core/citations:buildCitationMap 内联到 use-parsed-citations 并从 utils
删除;hasCitationsBlock 不再导出(仅 shouldShowCitationLoading 内部使用)。
- inline-citation:InlineCitationCard/Body/Source 改为文件内私有,不再导出。
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import type { ImgHTMLAttributes } from "react";
|
||||
import type { ReactNode } from "react";
|
||||
import { useMemo } from "react";
|
||||
|
||||
import {
|
||||
@@ -14,6 +15,7 @@ import {
|
||||
import {
|
||||
shouldShowCitationLoading,
|
||||
useParsedCitations,
|
||||
type UseParsedCitationsResult,
|
||||
} from "@/core/citations";
|
||||
import { streamdownPlugins } from "@/core/streamdown";
|
||||
import { cn } from "@/lib/utils";
|
||||
@@ -25,7 +27,11 @@ export type SafeCitationContentProps = {
|
||||
className?: string;
|
||||
remarkPlugins?: MessageResponseProps["remarkPlugins"];
|
||||
isHuman?: boolean;
|
||||
img?: (props: ImgHTMLAttributes<HTMLImageElement> & { threadId?: string; maxWidth?: string }) => React.ReactNode;
|
||||
img?: (props: ImgHTMLAttributes<HTMLImageElement> & { threadId?: string; maxWidth?: string }) => ReactNode;
|
||||
/** When true, only show loading indicator or null (e.g. write_file step). */
|
||||
loadingOnly?: boolean;
|
||||
/** When set, use instead of default MessageResponse (e.g. artifact preview). */
|
||||
renderBody?: (parsed: UseParsedCitationsResult) => ReactNode;
|
||||
};
|
||||
|
||||
/** Single place for citation-aware body: shows loading until citations complete (no half-finished refs), else body. */
|
||||
@@ -37,20 +43,12 @@ export function SafeCitationContent({
|
||||
remarkPlugins = streamdownPlugins.remarkPlugins,
|
||||
isHuman = false,
|
||||
img,
|
||||
loadingOnly = false,
|
||||
renderBody,
|
||||
}: SafeCitationContentProps) {
|
||||
const { citations, cleanContent, citationMap } = useParsedCitations(content);
|
||||
const parsed = useParsedCitations(content);
|
||||
const { citations, cleanContent, citationMap } = parsed;
|
||||
const showLoading = shouldShowCitationLoading(content, cleanContent, isLoading);
|
||||
|
||||
if (showLoading) {
|
||||
return (
|
||||
<CitationsLoadingIndicator
|
||||
citations={citations}
|
||||
className={cn("my-2", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
if (!cleanContent) return null;
|
||||
|
||||
const components = useMemo(
|
||||
() =>
|
||||
createCitationMarkdownComponents({
|
||||
@@ -61,6 +59,19 @@ export function SafeCitationContent({
|
||||
}),
|
||||
[citationMap, isHuman, img],
|
||||
);
|
||||
|
||||
if (showLoading) {
|
||||
return (
|
||||
<CitationsLoadingIndicator
|
||||
citations={citations}
|
||||
className={cn("my-2", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
if (loadingOnly) return null;
|
||||
if (renderBody) return renderBody(parsed);
|
||||
if (!cleanContent) return null;
|
||||
|
||||
return (
|
||||
<MessageResponse
|
||||
className={className}
|
||||
|
||||
Reference in New Issue
Block a user