From 812a996b2fd06ae3a9496fc8abcf64e68f3c8603 Mon Sep 17 00:00:00 2001 From: Gustavo Madeira Santana Date: Sat, 28 Feb 2026 19:20:07 -0500 Subject: [PATCH] adding config layer --- extensions/diffs/README.md | 29 +++++ extensions/diffs/index.test.ts | 80 +++++++++++++ extensions/diffs/index.ts | 8 +- extensions/diffs/openclaw.plugin.json | 72 +++++++++++- extensions/diffs/src/config.test.ts | 32 ++++++ extensions/diffs/src/config.ts | 147 ++++++++++++++++++++++++ extensions/diffs/src/prompt-guidance.ts | 3 +- extensions/diffs/src/render.test.ts | 11 +- extensions/diffs/src/render.ts | 26 +++-- extensions/diffs/src/tool.test.ts | 65 +++++++++++ extensions/diffs/src/tool.ts | 27 +++-- extensions/diffs/src/types.ts | 17 ++- extensions/diffs/src/viewer-client.ts | 1 + 13 files changed, 487 insertions(+), 31 deletions(-) create mode 100644 extensions/diffs/src/config.test.ts create mode 100644 extensions/diffs/src/config.ts diff --git a/extensions/diffs/README.md b/extensions/diffs/README.md index fe0e01c0480..d889d2f815f 100644 --- a/extensions/diffs/README.md +++ b/extensions/diffs/README.md @@ -54,6 +54,35 @@ Useful options: - `ttlSeconds`: artifact lifetime - `baseUrl`: override the gateway base URL used in the returned viewer link +## Plugin Defaults + +Set plugin-wide defaults in `~/.openclaw/openclaw.json`: + +```json5 +{ + plugins: { + entries: { + diffs: { + enabled: true, + config: { + defaults: { + fontFamily: "Fira Code", + fontSize: 15, + layout: "unified", + wordWrap: true, + background: true, + theme: "dark", + mode: "both", + }, + }, + }, + }, + }, +} +``` + +Explicit tool parameters still win over these defaults. + ## Example Agent Prompts Open in canvas: diff --git a/extensions/diffs/index.test.ts b/extensions/diffs/index.test.ts index 69b4dc312e0..bf6c3d668a8 100644 --- a/extensions/diffs/index.test.ts +++ b/extensions/diffs/index.test.ts @@ -1,4 +1,6 @@ +import type { IncomingMessage } from "node:http"; import { describe, expect, it, vi } from "vitest"; +import { createMockServerResponse } from "../../src/test-utils/mock-http-response.js"; import plugin from "./index.js"; describe("diffs plugin registration", () => { @@ -40,4 +42,82 @@ describe("diffs plugin registration", () => { expect(on).toHaveBeenCalledTimes(1); expect(on.mock.calls[0]?.[0]).toBe("before_prompt_build"); }); + + it("applies plugin-config defaults through registered tool and viewer handler", async () => { + let registeredTool: + | { execute?: (toolCallId: string, params: Record) => Promise } + | undefined; + let registeredHttpHandler: + | (( + req: IncomingMessage, + res: ReturnType, + ) => Promise) + | undefined; + + plugin.register?.({ + id: "diffs", + name: "Diffs", + description: "Diffs", + source: "test", + config: { + gateway: { + port: 18789, + bind: "loopback", + }, + }, + pluginConfig: { + defaults: { + theme: "light", + background: false, + layout: "split", + }, + }, + runtime: {} as never, + logger: { + info() {}, + warn() {}, + error() {}, + }, + registerTool(tool) { + registeredTool = typeof tool === "function" ? undefined : tool; + }, + registerHook() {}, + registerHttpHandler(handler) { + registeredHttpHandler = handler as typeof registeredHttpHandler; + }, + registerHttpRoute() {}, + registerChannel() {}, + registerGatewayMethod() {}, + registerCli() {}, + registerService() {}, + registerProvider() {}, + registerCommand() {}, + resolvePath(input: string) { + return input; + }, + on() {}, + }); + + const result = await registeredTool?.execute?.("tool-1", { + before: "one\n", + after: "two\n", + }); + const viewerPath = String( + (result as { details?: Record } | undefined)?.details?.viewerPath, + ); + const res = createMockServerResponse(); + const handled = await registeredHttpHandler?.( + { + method: "GET", + url: viewerPath, + } as IncomingMessage, + res, + ); + + expect(handled).toBe(true); + expect(res.statusCode).toBe(200); + expect(String(res.body)).toContain('body data-theme="light"'); + expect(String(res.body)).toContain('"backgroundEnabled":false'); + expect(String(res.body)).toContain('"diffStyle":"split"'); + }); }); diff --git a/extensions/diffs/index.ts b/extensions/diffs/index.ts index e1d02d9e595..0cfd2eaf7f7 100644 --- a/extensions/diffs/index.ts +++ b/extensions/diffs/index.ts @@ -1,6 +1,7 @@ import path from "node:path"; import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; -import { emptyPluginConfigSchema, resolvePreferredOpenClawTmpDir } from "openclaw/plugin-sdk"; +import { resolvePreferredOpenClawTmpDir } from "openclaw/plugin-sdk"; +import { diffsPluginConfigSchema, resolveDiffsPluginDefaults } from "./src/config.js"; import { createDiffsHttpHandler } from "./src/http.js"; import { DIFFS_AGENT_GUIDANCE } from "./src/prompt-guidance.js"; import { DiffArtifactStore } from "./src/store.js"; @@ -10,14 +11,15 @@ const plugin = { id: "diffs", name: "Diffs", description: "Read-only diff viewer and PNG renderer for agents.", - configSchema: emptyPluginConfigSchema(), + configSchema: diffsPluginConfigSchema, register(api: OpenClawPluginApi) { + const defaults = resolveDiffsPluginDefaults(api.pluginConfig); const store = new DiffArtifactStore({ rootDir: path.join(resolvePreferredOpenClawTmpDir(), "openclaw-diffs"), logger: api.logger, }); - api.registerTool(createDiffsTool({ api, store })); + api.registerTool(createDiffsTool({ api, store, defaults })); api.registerHttpHandler(createDiffsHttpHandler({ store, logger: api.logger })); api.on("before_prompt_build", async () => ({ prependContext: DIFFS_AGENT_GUIDANCE, diff --git a/extensions/diffs/openclaw.plugin.json b/extensions/diffs/openclaw.plugin.json index c34453410b6..de92fb83f2c 100644 --- a/extensions/diffs/openclaw.plugin.json +++ b/extensions/diffs/openclaw.plugin.json @@ -2,9 +2,79 @@ "id": "diffs", "name": "Diffs", "description": "Read-only diff viewer and image renderer for agents.", + "uiHints": { + "defaults.fontFamily": { + "label": "Default Font", + "help": "Preferred font family name for diff content and headers." + }, + "defaults.fontSize": { + "label": "Default Font Size", + "help": "Base diff font size in pixels." + }, + "defaults.layout": { + "label": "Default Layout", + "help": "Initial diff layout shown in the viewer." + }, + "defaults.wordWrap": { + "label": "Default Word Wrap", + "help": "Wrap long lines by default." + }, + "defaults.background": { + "label": "Default Background Highlights", + "help": "Show added/removed background highlights by default." + }, + "defaults.theme": { + "label": "Default Theme", + "help": "Initial viewer theme." + }, + "defaults.mode": { + "label": "Default Output Mode", + "help": "Tool default when mode is omitted. Use view for canvas/gateway viewer, image for PNG, or both." + } + }, "configSchema": { "type": "object", "additionalProperties": false, - "properties": {} + "properties": { + "defaults": { + "type": "object", + "additionalProperties": false, + "properties": { + "fontFamily": { + "type": "string", + "default": "Fira Code" + }, + "fontSize": { + "type": "number", + "minimum": 10, + "maximum": 24, + "default": 15 + }, + "layout": { + "type": "string", + "enum": ["unified", "split"], + "default": "unified" + }, + "wordWrap": { + "type": "boolean", + "default": true + }, + "background": { + "type": "boolean", + "default": true + }, + "theme": { + "type": "string", + "enum": ["light", "dark"], + "default": "dark" + }, + "mode": { + "type": "string", + "enum": ["view", "image", "both"], + "default": "both" + } + } + } + } } } diff --git a/extensions/diffs/src/config.test.ts b/extensions/diffs/src/config.test.ts new file mode 100644 index 00000000000..9f068119c37 --- /dev/null +++ b/extensions/diffs/src/config.test.ts @@ -0,0 +1,32 @@ +import { describe, expect, it } from "vitest"; +import { DEFAULT_DIFFS_TOOL_DEFAULTS, resolveDiffsPluginDefaults } from "./config.js"; + +describe("resolveDiffsPluginDefaults", () => { + it("returns built-in defaults when config is missing", () => { + expect(resolveDiffsPluginDefaults(undefined)).toEqual(DEFAULT_DIFFS_TOOL_DEFAULTS); + }); + + it("applies configured defaults from plugin config", () => { + expect( + resolveDiffsPluginDefaults({ + defaults: { + fontFamily: "JetBrains Mono", + fontSize: 17, + layout: "split", + wordWrap: false, + background: false, + theme: "light", + mode: "view", + }, + }), + ).toEqual({ + fontFamily: "JetBrains Mono", + fontSize: 17, + layout: "split", + wordWrap: false, + background: false, + theme: "light", + mode: "view", + }); + }); +}); diff --git a/extensions/diffs/src/config.ts b/extensions/diffs/src/config.ts new file mode 100644 index 00000000000..bc67a8f23db --- /dev/null +++ b/extensions/diffs/src/config.ts @@ -0,0 +1,147 @@ +import type { OpenClawPluginConfigSchema } from "openclaw/plugin-sdk"; +import { + DIFF_LAYOUTS, + DIFF_MODES, + DIFF_THEMES, + type DiffLayout, + type DiffMode, + type DiffPresentationDefaults, + type DiffTheme, + type DiffToolDefaults, +} from "./types.js"; + +type DiffsPluginConfig = { + defaults?: { + fontFamily?: string; + fontSize?: number; + layout?: DiffLayout; + wordWrap?: boolean; + background?: boolean; + theme?: DiffTheme; + mode?: DiffMode; + }; +}; + +export const DEFAULT_DIFFS_TOOL_DEFAULTS: DiffToolDefaults = { + fontFamily: "Fira Code", + fontSize: 15, + layout: "unified", + wordWrap: true, + background: true, + theme: "dark", + mode: "both", +}; + +const DIFFS_PLUGIN_CONFIG_JSON_SCHEMA = { + type: "object", + additionalProperties: false, + properties: { + defaults: { + type: "object", + additionalProperties: false, + properties: { + fontFamily: { type: "string", default: DEFAULT_DIFFS_TOOL_DEFAULTS.fontFamily }, + fontSize: { + type: "number", + minimum: 10, + maximum: 24, + default: DEFAULT_DIFFS_TOOL_DEFAULTS.fontSize, + }, + layout: { + type: "string", + enum: [...DIFF_LAYOUTS], + default: DEFAULT_DIFFS_TOOL_DEFAULTS.layout, + }, + wordWrap: { type: "boolean", default: DEFAULT_DIFFS_TOOL_DEFAULTS.wordWrap }, + background: { type: "boolean", default: DEFAULT_DIFFS_TOOL_DEFAULTS.background }, + theme: { + type: "string", + enum: [...DIFF_THEMES], + default: DEFAULT_DIFFS_TOOL_DEFAULTS.theme, + }, + mode: { + type: "string", + enum: [...DIFF_MODES], + default: DEFAULT_DIFFS_TOOL_DEFAULTS.mode, + }, + }, + }, + }, +} as const; + +export const diffsPluginConfigSchema: OpenClawPluginConfigSchema = { + safeParse(value: unknown) { + if (value === undefined) { + return { success: true, data: undefined }; + } + try { + return { success: true, data: resolveDiffsPluginDefaults(value) }; + } catch (error) { + return { + success: false, + error: { + issues: [{ path: [], message: error instanceof Error ? error.message : String(error) }], + }, + }; + } + }, + jsonSchema: DIFFS_PLUGIN_CONFIG_JSON_SCHEMA, +}; + +export function resolveDiffsPluginDefaults(config: unknown): DiffToolDefaults { + if (!config || typeof config !== "object" || Array.isArray(config)) { + return { ...DEFAULT_DIFFS_TOOL_DEFAULTS }; + } + + const defaults = (config as DiffsPluginConfig).defaults; + if (!defaults || typeof defaults !== "object" || Array.isArray(defaults)) { + return { ...DEFAULT_DIFFS_TOOL_DEFAULTS }; + } + + return { + fontFamily: normalizeFontFamily(defaults.fontFamily), + fontSize: normalizeFontSize(defaults.fontSize), + layout: normalizeLayout(defaults.layout), + wordWrap: defaults.wordWrap !== false, + background: defaults.background !== false, + theme: normalizeTheme(defaults.theme), + mode: normalizeMode(defaults.mode), + }; +} + +export function toPresentationDefaults(defaults: DiffToolDefaults): DiffPresentationDefaults { + const { fontFamily, fontSize, layout, wordWrap, background, theme } = defaults; + return { + fontFamily, + fontSize, + layout, + wordWrap, + background, + theme, + }; +} + +function normalizeFontFamily(fontFamily?: string): string { + const normalized = fontFamily?.trim(); + return normalized || DEFAULT_DIFFS_TOOL_DEFAULTS.fontFamily; +} + +function normalizeFontSize(fontSize?: number): number { + if (fontSize === undefined || !Number.isFinite(fontSize)) { + return DEFAULT_DIFFS_TOOL_DEFAULTS.fontSize; + } + const rounded = Math.floor(fontSize); + return Math.min(Math.max(rounded, 10), 24); +} + +function normalizeLayout(layout?: DiffLayout): DiffLayout { + return layout && DIFF_LAYOUTS.includes(layout) ? layout : DEFAULT_DIFFS_TOOL_DEFAULTS.layout; +} + +function normalizeTheme(theme?: DiffTheme): DiffTheme { + return theme && DIFF_THEMES.includes(theme) ? theme : DEFAULT_DIFFS_TOOL_DEFAULTS.theme; +} + +function normalizeMode(mode?: DiffMode): DiffMode { + return mode && DIFF_MODES.includes(mode) ? mode : DEFAULT_DIFFS_TOOL_DEFAULTS.mode; +} diff --git a/extensions/diffs/src/prompt-guidance.ts b/extensions/diffs/src/prompt-guidance.ts index 63d549e2f79..43d6656e43c 100644 --- a/extensions/diffs/src/prompt-guidance.ts +++ b/extensions/diffs/src/prompt-guidance.ts @@ -5,5 +5,6 @@ export const DIFFS_AGENT_GUIDANCE = [ "Use `mode=image` when you need a rendered PNG. The tool result includes `details.imagePath` for the generated file.", "When you need to deliver the PNG to a user or channel, do not rely on the raw tool-result image renderer. Instead, call the `message` tool and pass `details.imagePath` through `path` or `filePath`.", "Use `mode=both` when you want both the gateway viewer URL and the PNG artifact.", - "Good defaults: `theme=dark` for canvas rendering, `layout=unified` for most diffs, and include `path` for before/after text when you know the file name.", + "If the user has configured diffs plugin defaults, prefer omitting `mode`, `theme`, `layout`, and related presentation options unless you need to override them for this specific diff.", + "Include `path` for before/after text when you know the file name.", ].join("\n"); diff --git a/extensions/diffs/src/render.test.ts b/extensions/diffs/src/render.test.ts index 84d10cb3b95..95dcccd2f56 100644 --- a/extensions/diffs/src/render.test.ts +++ b/extensions/diffs/src/render.test.ts @@ -1,4 +1,5 @@ import { describe, expect, it } from "vitest"; +import { DEFAULT_DIFFS_TOOL_DEFAULTS } from "./config.js"; import { renderDiffDocument } from "./render.js"; describe("renderDiffDocument", () => { @@ -11,9 +12,8 @@ describe("renderDiffDocument", () => { path: "src/example.ts", }, { - layout: "unified", + presentation: DEFAULT_DIFFS_TOOL_DEFAULTS, expandUnchanged: false, - theme: "light", }, ); @@ -48,9 +48,12 @@ describe("renderDiffDocument", () => { title: "Workspace patch", }, { - layout: "split", + presentation: { + ...DEFAULT_DIFFS_TOOL_DEFAULTS, + layout: "split", + theme: "dark", + }, expandUnchanged: true, - theme: "dark", }, ); diff --git a/extensions/diffs/src/render.ts b/extensions/diffs/src/render.ts index 1ef40948348..cb682e93feb 100644 --- a/extensions/diffs/src/render.ts +++ b/extensions/diffs/src/render.ts @@ -12,6 +12,10 @@ import { VIEWER_LOADER_PATH } from "./viewer-assets.js"; const DEFAULT_FILE_NAME = "diff.txt"; +function escapeCssString(value: string): string { + return value.replaceAll("\\", "\\\\").replaceAll('"', '\\"'); +} + function escapeHtml(value: string): string { return value .replaceAll("&", "&") @@ -46,21 +50,25 @@ function resolveBeforeAfterFileName(input: Extract @@ -341,7 +349,7 @@ export async function renderDiffDocument( html: buildHtmlDocument({ title, bodyHtml: rendered.bodyHtml, - theme: options.theme, + theme: options.presentation.theme, }), title, fileCount: rendered.fileCount, diff --git a/extensions/diffs/src/tool.test.ts b/extensions/diffs/src/tool.test.ts index bba9a01ce07..b90debd5c53 100644 --- a/extensions/diffs/src/tool.test.ts +++ b/extensions/diffs/src/tool.test.ts @@ -3,6 +3,7 @@ import os from "node:os"; import path from "node:path"; import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import { DEFAULT_DIFFS_TOOL_DEFAULTS } from "./config.js"; import { DiffArtifactStore } from "./store.js"; import { createDiffsTool } from "./tool.js"; @@ -23,6 +24,7 @@ describe("diffs tool", () => { const tool = createDiffsTool({ api: createApi(), store, + defaults: DEFAULT_DIFFS_TOOL_DEFAULTS, }); const result = await tool.execute?.("tool-1", { @@ -49,6 +51,7 @@ describe("diffs tool", () => { const tool = createDiffsTool({ api: createApi(), store, + defaults: DEFAULT_DIFFS_TOOL_DEFAULTS, screenshotter, }); @@ -69,6 +72,7 @@ describe("diffs tool", () => { const tool = createDiffsTool({ api: createApi(), store, + defaults: DEFAULT_DIFFS_TOOL_DEFAULTS, screenshotter: { screenshotHtml: vi.fn(async () => { throw new Error("browser missing"); @@ -91,6 +95,7 @@ describe("diffs tool", () => { const tool = createDiffsTool({ api: createApi(), store, + defaults: DEFAULT_DIFFS_TOOL_DEFAULTS, }); await expect( @@ -102,6 +107,66 @@ describe("diffs tool", () => { }), ).rejects.toThrow("Invalid baseUrl"); }); + + it("uses configured defaults when tool params omit them", async () => { + const tool = createDiffsTool({ + api: createApi(), + store, + defaults: { + ...DEFAULT_DIFFS_TOOL_DEFAULTS, + mode: "view", + theme: "light", + layout: "split", + wordWrap: false, + background: false, + fontFamily: "JetBrains Mono", + fontSize: 17, + }, + }); + + const result = await tool.execute?.("tool-5", { + before: "one\n", + after: "two\n", + path: "README.md", + }); + + expect(readTextContent(result, 0)).toContain("Diff viewer ready."); + expect((result?.details as Record).mode).toBe("view"); + + const viewerPath = String((result?.details as Record).viewerPath); + const [id] = viewerPath.split("/").filter(Boolean).slice(-2); + const html = await store.readHtml(id); + expect(html).toContain('body data-theme="light"'); + expect(html).toContain("--diffs-font-size: 17px;"); + expect(html).toContain('--diffs-font-family: "JetBrains Mono"'); + }); + + it("prefers explicit tool params over configured defaults", async () => { + const tool = createDiffsTool({ + api: createApi(), + store, + defaults: { + ...DEFAULT_DIFFS_TOOL_DEFAULTS, + mode: "view", + theme: "light", + layout: "split", + }, + }); + + const result = await tool.execute?.("tool-6", { + before: "one\n", + after: "two\n", + mode: "both", + theme: "dark", + layout: "unified", + }); + + expect((result?.details as Record).mode).toBe("both"); + const viewerPath = String((result?.details as Record).viewerPath); + const [id] = viewerPath.split("/").filter(Boolean).slice(-2); + const html = await store.readHtml(id); + expect(html).toContain('body data-theme="dark"'); + }); }); function createApi(): OpenClawPluginApi { diff --git a/extensions/diffs/src/tool.ts b/extensions/diffs/src/tool.ts index 97e07057a5c..012250beaa0 100644 --- a/extensions/diffs/src/tool.ts +++ b/extensions/diffs/src/tool.ts @@ -4,6 +4,7 @@ import type { AnyAgentTool, OpenClawPluginApi } from "openclaw/plugin-sdk"; import { PlaywrightDiffScreenshotter, type DiffScreenshotter } from "./browser.js"; import { renderDiffDocument } from "./render.js"; import type { DiffArtifactStore } from "./store.js"; +import type { DiffToolDefaults } from "./types.js"; import { DIFF_LAYOUTS, DIFF_MODES, @@ -63,6 +64,7 @@ type DiffsToolParams = Static; export function createDiffsTool(params: { api: OpenClawPluginApi; store: DiffArtifactStore; + defaults: DiffToolDefaults; screenshotter?: DiffScreenshotter; }): AnyAgentTool { return { @@ -74,16 +76,19 @@ export function createDiffsTool(params: { execute: async (_toolCallId, rawParams) => { const toolParams = rawParams as DiffsToolParams; const input = normalizeDiffInput(toolParams); - const mode = normalizeMode(toolParams.mode); - const theme = normalizeTheme(toolParams.theme); - const layout = normalizeLayout(toolParams.layout); + const mode = normalizeMode(toolParams.mode, params.defaults.mode); + const theme = normalizeTheme(toolParams.theme, params.defaults.theme); + const layout = normalizeLayout(toolParams.layout, params.defaults.layout); const expandUnchanged = toolParams.expandUnchanged === true; const ttlMs = normalizeTtlMs(toolParams.ttlSeconds); const rendered = await renderDiffDocument(input, { - layout, + presentation: { + ...params.defaults, + layout, + theme, + }, expandUnchanged, - theme, }); const artifact = await params.store.createArtifact({ @@ -218,16 +223,16 @@ function normalizeBaseUrl(baseUrl?: string): string | undefined { } } -function normalizeMode(mode?: DiffMode): DiffMode { - return mode && DIFF_MODES.includes(mode) ? mode : "both"; +function normalizeMode(mode: DiffMode | undefined, fallback: DiffMode): DiffMode { + return mode && DIFF_MODES.includes(mode) ? mode : fallback; } -function normalizeTheme(theme?: DiffTheme): DiffTheme { - return theme && DIFF_THEMES.includes(theme) ? theme : "dark"; +function normalizeTheme(theme: DiffTheme | undefined, fallback: DiffTheme): DiffTheme { + return theme && DIFF_THEMES.includes(theme) ? theme : fallback; } -function normalizeLayout(layout?: DiffLayout): DiffLayout { - return layout && DIFF_LAYOUTS.includes(layout) ? layout : "unified"; +function normalizeLayout(layout: DiffLayout | undefined, fallback: DiffLayout): DiffLayout { + return layout && DIFF_LAYOUTS.includes(layout) ? layout : fallback; } function normalizeTtlMs(ttlSeconds?: number): number | undefined { diff --git a/extensions/diffs/src/types.ts b/extensions/diffs/src/types.ts index 76452834b08..cc0183c9335 100644 --- a/extensions/diffs/src/types.ts +++ b/extensions/diffs/src/types.ts @@ -8,6 +8,19 @@ export type DiffLayout = (typeof DIFF_LAYOUTS)[number]; export type DiffMode = (typeof DIFF_MODES)[number]; export type DiffTheme = (typeof DIFF_THEMES)[number]; +export type DiffPresentationDefaults = { + fontFamily: string; + fontSize: number; + layout: DiffLayout; + wordWrap: boolean; + background: boolean; + theme: DiffTheme; +}; + +export type DiffToolDefaults = DiffPresentationDefaults & { + mode: DiffMode; +}; + export type BeforeAfterDiffInput = { kind: "before_after"; before: string; @@ -26,9 +39,8 @@ export type PatchDiffInput = { export type DiffInput = BeforeAfterDiffInput | PatchDiffInput; export type DiffRenderOptions = { - layout: DiffLayout; + presentation: DiffPresentationDefaults; expandUnchanged: boolean; - theme: DiffTheme; }; export type DiffViewerOptions = { @@ -39,6 +51,7 @@ export type DiffViewerOptions = { diffStyle: DiffLayout; expandUnchanged: boolean; themeType: DiffTheme; + backgroundEnabled: boolean; overflow: "scroll" | "wrap"; unsafeCSS: string; }; diff --git a/extensions/diffs/src/viewer-client.ts b/extensions/diffs/src/viewer-client.ts index e18d174b532..07131d84144 100644 --- a/extensions/diffs/src/viewer-client.ts +++ b/extensions/diffs/src/viewer-client.ts @@ -281,6 +281,7 @@ async function hydrateViewer(): Promise { if (firstPayload) { viewerState.theme = firstPayload.options.themeType; viewerState.layout = firstPayload.options.diffStyle; + viewerState.backgroundEnabled = firstPayload.options.backgroundEnabled; viewerState.wrapEnabled = firstPayload.options.overflow === "wrap"; }