mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-19 09:38:39 +00:00
refactor(diffs): dedupe functions
This commit is contained in:
@@ -150,6 +150,16 @@ function buildImageRenderOptions(options: DiffRenderOptions): DiffRenderOptions
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildRenderVariants(options: DiffRenderOptions): {
|
||||||
|
viewerOptions: DiffViewerOptions;
|
||||||
|
imageOptions: DiffViewerOptions;
|
||||||
|
} {
|
||||||
|
return {
|
||||||
|
viewerOptions: buildDiffOptions(options),
|
||||||
|
imageOptions: buildDiffOptions(buildImageRenderOptions(options)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeSupportedLanguage(value?: string): SupportedLanguages | undefined {
|
function normalizeSupportedLanguage(value?: string): SupportedLanguages | undefined {
|
||||||
const normalized = value?.trim();
|
const normalized = value?.trim();
|
||||||
return normalized ? (normalized as SupportedLanguages) : undefined;
|
return normalized ? (normalized as SupportedLanguages) : undefined;
|
||||||
@@ -298,6 +308,35 @@ function buildHtmlDocument(params: {
|
|||||||
</html>`;
|
</html>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RenderedSection = {
|
||||||
|
viewer: string;
|
||||||
|
image: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
function buildRenderedSection(params: {
|
||||||
|
viewerPrerenderedHtml: string;
|
||||||
|
imagePrerenderedHtml: string;
|
||||||
|
payload: Omit<DiffViewerPayload, "prerenderedHTML">;
|
||||||
|
}): RenderedSection {
|
||||||
|
return {
|
||||||
|
viewer: renderDiffCard({
|
||||||
|
prerenderedHTML: params.viewerPrerenderedHtml,
|
||||||
|
...params.payload,
|
||||||
|
}),
|
||||||
|
image: renderStaticDiffCard(params.imagePrerenderedHtml),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildRenderedBodies(sections: ReadonlyArray<RenderedSection>): {
|
||||||
|
viewerBodyHtml: string;
|
||||||
|
imageBodyHtml: string;
|
||||||
|
} {
|
||||||
|
return {
|
||||||
|
viewerBodyHtml: sections.map((section) => section.viewer).join("\n"),
|
||||||
|
imageBodyHtml: sections.map((section) => section.image).join("\n"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
async function renderBeforeAfterDiff(
|
async function renderBeforeAfterDiff(
|
||||||
input: Extract<DiffInput, { kind: "before_after" }>,
|
input: Extract<DiffInput, { kind: "before_after" }>,
|
||||||
options: DiffRenderOptions,
|
options: DiffRenderOptions,
|
||||||
@@ -314,33 +353,35 @@ async function renderBeforeAfterDiff(
|
|||||||
contents: input.after,
|
contents: input.after,
|
||||||
...(lang ? { lang } : {}),
|
...(lang ? { lang } : {}),
|
||||||
};
|
};
|
||||||
const viewerPayloadOptions = buildDiffOptions(options);
|
const { viewerOptions, imageOptions } = buildRenderVariants(options);
|
||||||
const imagePayloadOptions = buildDiffOptions(buildImageRenderOptions(options));
|
|
||||||
const [viewerResult, imageResult] = await Promise.all([
|
const [viewerResult, imageResult] = await Promise.all([
|
||||||
preloadMultiFileDiff({
|
preloadMultiFileDiff({
|
||||||
oldFile,
|
oldFile,
|
||||||
newFile,
|
newFile,
|
||||||
options: viewerPayloadOptions,
|
options: viewerOptions,
|
||||||
}),
|
}),
|
||||||
preloadMultiFileDiff({
|
preloadMultiFileDiff({
|
||||||
oldFile,
|
oldFile,
|
||||||
newFile,
|
newFile,
|
||||||
options: imagePayloadOptions,
|
options: imageOptions,
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
|
const section = buildRenderedSection({
|
||||||
return {
|
viewerPrerenderedHtml: viewerResult.prerenderedHTML,
|
||||||
viewerBodyHtml: renderDiffCard({
|
imagePrerenderedHtml: imageResult.prerenderedHTML,
|
||||||
prerenderedHTML: viewerResult.prerenderedHTML,
|
payload: {
|
||||||
oldFile: viewerResult.oldFile,
|
oldFile: viewerResult.oldFile,
|
||||||
newFile: viewerResult.newFile,
|
newFile: viewerResult.newFile,
|
||||||
options: viewerPayloadOptions,
|
options: viewerOptions,
|
||||||
langs: buildPayloadLanguages({
|
langs: buildPayloadLanguages({
|
||||||
oldFile: viewerResult.oldFile,
|
oldFile: viewerResult.oldFile,
|
||||||
newFile: viewerResult.newFile,
|
newFile: viewerResult.newFile,
|
||||||
}),
|
}),
|
||||||
}),
|
},
|
||||||
imageBodyHtml: renderStaticDiffCard(imageResult.prerenderedHTML),
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
...buildRenderedBodies([section]),
|
||||||
fileCount: 1,
|
fileCount: 1,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -365,36 +406,34 @@ async function renderPatchDiff(
|
|||||||
throw new Error(`Patch input is too large to render (max ${MAX_PATCH_TOTAL_LINES} lines).`);
|
throw new Error(`Patch input is too large to render (max ${MAX_PATCH_TOTAL_LINES} lines).`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const viewerPayloadOptions = buildDiffOptions(options);
|
const { viewerOptions, imageOptions } = buildRenderVariants(options);
|
||||||
const imagePayloadOptions = buildDiffOptions(buildImageRenderOptions(options));
|
|
||||||
const sections = await Promise.all(
|
const sections = await Promise.all(
|
||||||
files.map(async (fileDiff) => {
|
files.map(async (fileDiff) => {
|
||||||
const [viewerResult, imageResult] = await Promise.all([
|
const [viewerResult, imageResult] = await Promise.all([
|
||||||
preloadFileDiff({
|
preloadFileDiff({
|
||||||
fileDiff,
|
fileDiff,
|
||||||
options: viewerPayloadOptions,
|
options: viewerOptions,
|
||||||
}),
|
}),
|
||||||
preloadFileDiff({
|
preloadFileDiff({
|
||||||
fileDiff,
|
fileDiff,
|
||||||
options: imagePayloadOptions,
|
options: imageOptions,
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return {
|
return buildRenderedSection({
|
||||||
viewer: renderDiffCard({
|
viewerPrerenderedHtml: viewerResult.prerenderedHTML,
|
||||||
prerenderedHTML: viewerResult.prerenderedHTML,
|
imagePrerenderedHtml: imageResult.prerenderedHTML,
|
||||||
|
payload: {
|
||||||
fileDiff: viewerResult.fileDiff,
|
fileDiff: viewerResult.fileDiff,
|
||||||
options: viewerPayloadOptions,
|
options: viewerOptions,
|
||||||
langs: buildPayloadLanguages({ fileDiff: viewerResult.fileDiff }),
|
langs: buildPayloadLanguages({ fileDiff: viewerResult.fileDiff }),
|
||||||
}),
|
},
|
||||||
image: renderStaticDiffCard(imageResult.prerenderedHTML),
|
});
|
||||||
};
|
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
viewerBodyHtml: sections.map((section) => section.viewer).join("\n"),
|
...buildRenderedBodies(sections),
|
||||||
imageBodyHtml: sections.map((section) => section.image).join("\n"),
|
|
||||||
fileCount: files.length,
|
fileCount: files.length,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -187,9 +187,10 @@ export function createDiffsTool(params: {
|
|||||||
content: [
|
content: [
|
||||||
{
|
{
|
||||||
type: "text",
|
type: "text",
|
||||||
text:
|
text: buildFileArtifactMessage({
|
||||||
`Diff ${image.format.toUpperCase()} generated at: ${artifactFile.path}\n` +
|
format: image.format,
|
||||||
"Use the `message` tool with `path` or `filePath` to send this file.",
|
filePath: artifactFile.path,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
details: buildArtifactDetails({
|
details: buildArtifactDetails({
|
||||||
@@ -257,10 +258,11 @@ export function createDiffsTool(params: {
|
|||||||
content: [
|
content: [
|
||||||
{
|
{
|
||||||
type: "text",
|
type: "text",
|
||||||
text:
|
text: buildFileArtifactMessage({
|
||||||
`Diff viewer: ${viewerUrl}\n` +
|
format: image.format,
|
||||||
`Diff ${image.format.toUpperCase()} generated at: ${artifactFile.path}\n` +
|
filePath: artifactFile.path,
|
||||||
"Use the `message` tool with `path` or `filePath` to send this file.",
|
viewerUrl,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
details: buildArtifactDetails({
|
details: buildArtifactDetails({
|
||||||
@@ -330,6 +332,17 @@ function buildArtifactDetails(params: {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildFileArtifactMessage(params: {
|
||||||
|
format: DiffOutputFormat;
|
||||||
|
filePath: string;
|
||||||
|
viewerUrl?: string;
|
||||||
|
}): string {
|
||||||
|
const lines = params.viewerUrl ? [`Diff viewer: ${params.viewerUrl}`] : [];
|
||||||
|
lines.push(`Diff ${params.format.toUpperCase()} generated at: ${params.filePath}`);
|
||||||
|
lines.push("Use the `message` tool with `path` or `filePath` to send this file.");
|
||||||
|
return lines.join("\n");
|
||||||
|
}
|
||||||
|
|
||||||
async function renderDiffArtifactFile(params: {
|
async function renderDiffArtifactFile(params: {
|
||||||
screenshotter: DiffScreenshotter;
|
screenshotter: DiffScreenshotter;
|
||||||
store: DiffArtifactStore;
|
store: DiffArtifactStore;
|
||||||
|
|||||||
@@ -106,39 +106,9 @@ function createToolbarButton(params: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function applyToolbarButtonStyles(button: HTMLButtonElement, active: boolean): void {
|
function applyToolbarButtonStyles(button: HTMLButtonElement, active: boolean): void {
|
||||||
button.style.display = "inline-flex";
|
|
||||||
button.style.alignItems = "center";
|
|
||||||
button.style.justifyContent = "center";
|
|
||||||
button.style.width = "24px";
|
|
||||||
button.style.height = "24px";
|
|
||||||
button.style.padding = "0";
|
|
||||||
button.style.margin = "0";
|
|
||||||
button.style.border = "0";
|
|
||||||
button.style.borderRadius = "0";
|
|
||||||
button.style.background = "transparent";
|
|
||||||
button.style.boxShadow = "none";
|
|
||||||
button.style.lineHeight = "0";
|
|
||||||
button.style.cursor = "pointer";
|
|
||||||
button.style.overflow = "visible";
|
|
||||||
button.style.flex = "0 0 auto";
|
|
||||||
button.style.opacity = active ? "0.92" : "0.6";
|
|
||||||
button.style.color =
|
button.style.color =
|
||||||
viewerState.theme === "dark" ? "rgba(226, 232, 240, 0.74)" : "rgba(15, 23, 42, 0.52)";
|
viewerState.theme === "dark" ? "rgba(226, 232, 240, 0.74)" : "rgba(15, 23, 42, 0.52)";
|
||||||
|
button.dataset.active = String(active);
|
||||||
const svg = button.querySelector<SVGElement>("svg");
|
|
||||||
if (!svg) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
svg.style.display = "block";
|
|
||||||
svg.style.width = "16px";
|
|
||||||
svg.style.height = "16px";
|
|
||||||
svg.style.minWidth = "16px";
|
|
||||||
svg.style.minHeight = "16px";
|
|
||||||
svg.style.overflow = "visible";
|
|
||||||
svg.style.flex = "0 0 auto";
|
|
||||||
svg.style.color = "inherit";
|
|
||||||
svg.style.fill = "currentColor";
|
|
||||||
svg.style.pointerEvents = "none";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function splitIcon(): string {
|
function splitIcon(): string {
|
||||||
@@ -193,11 +163,6 @@ function themeIcon(theme: DiffTheme): string {
|
|||||||
function createToolbar(): HTMLElement {
|
function createToolbar(): HTMLElement {
|
||||||
const toolbar = document.createElement("div");
|
const toolbar = document.createElement("div");
|
||||||
toolbar.className = "oc-diff-toolbar";
|
toolbar.className = "oc-diff-toolbar";
|
||||||
toolbar.style.display = "inline-flex";
|
|
||||||
toolbar.style.alignItems = "center";
|
|
||||||
toolbar.style.gap = "6px";
|
|
||||||
toolbar.style.marginInlineStart = "6px";
|
|
||||||
toolbar.style.flex = "0 0 auto";
|
|
||||||
|
|
||||||
toolbar.append(
|
toolbar.append(
|
||||||
createToolbarButton({
|
createToolbarButton({
|
||||||
|
|||||||
Reference in New Issue
Block a user