mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-21 14:11:26 +00:00
Diffs: preserve base paths for viewer assets
This commit is contained in:
@@ -281,6 +281,8 @@ Viewer assets:
|
||||
- `/plugins/diffs/assets/viewer.js`
|
||||
- `/plugins/diffs/assets/viewer-runtime.js`
|
||||
|
||||
The viewer document resolves those assets relative to the viewer URL, so an optional `baseUrl` path prefix is preserved for both asset requests too.
|
||||
|
||||
URL construction behavior:
|
||||
|
||||
- If `baseUrl` is provided, it is used after strict validation.
|
||||
|
||||
@@ -11,6 +11,7 @@ const SHARED_BROWSER_KEY = "__default__";
|
||||
const IMAGE_SIZE_LIMIT_ERROR = "Diff frame did not render within image size limits.";
|
||||
const PDF_REFERENCE_PAGE_HEIGHT_PX = 1_056;
|
||||
const MAX_PDF_PAGES = 50;
|
||||
const LOCAL_VIEWER_BASE_HREF = "http://127.0.0.1/plugins/diffs/view/local/local";
|
||||
|
||||
export type DiffScreenshotter = {
|
||||
screenshotHtml(params: {
|
||||
@@ -274,7 +275,7 @@ function injectBaseHref(html: string): string {
|
||||
if (html.includes("<base ")) {
|
||||
return html;
|
||||
}
|
||||
return html.replace("<head>", '<head><base href="http://127.0.0.1/" />');
|
||||
return html.replace("<head>", `<head><base href="${LOCAL_VIEWER_BASE_HREF}" />`);
|
||||
}
|
||||
|
||||
async function resolveBrowserExecutablePath(config: OpenClawConfig): Promise<string | undefined> {
|
||||
|
||||
@@ -261,8 +261,8 @@ describe("renderDiffDocument", () => {
|
||||
expect(rendered.fileCount).toBe(1);
|
||||
expect(rendered.html).toContain("data-openclaw-diff-root");
|
||||
expect(rendered.html).toContain("src/example.ts");
|
||||
expect(rendered.html).toContain("/plugins/diffs/assets/viewer.js");
|
||||
expect(rendered.imageHtml).toContain("/plugins/diffs/assets/viewer.js");
|
||||
expect(rendered.html).toContain("../../assets/viewer.js");
|
||||
expect(rendered.imageHtml).toContain("../../assets/viewer.js");
|
||||
expect(rendered.imageHtml).toContain("max-width: 960px;");
|
||||
expect(rendered.imageHtml).toContain("--diffs-font-size: 16px;");
|
||||
expect(rendered.html).toContain("min-height: 100vh;");
|
||||
@@ -273,6 +273,27 @@ describe("renderDiffDocument", () => {
|
||||
expect(rendered.html).not.toContain("fonts.googleapis.com");
|
||||
});
|
||||
|
||||
it("resolves viewer assets under an optional base path", async () => {
|
||||
const rendered = await renderDiffDocument(
|
||||
{
|
||||
kind: "before_after",
|
||||
before: "const value = 1;\n",
|
||||
after: "const value = 2;\n",
|
||||
},
|
||||
{
|
||||
presentation: DEFAULT_DIFFS_TOOL_DEFAULTS,
|
||||
image: resolveDiffImageRenderOptions({ defaults: DEFAULT_DIFFS_TOOL_DEFAULTS }),
|
||||
expandUnchanged: false,
|
||||
},
|
||||
);
|
||||
|
||||
const loaderSrc = rendered.html.match(/<script type="module" src="([^"]+)"><\/script>/)?.[1];
|
||||
expect(loaderSrc).toBe("../../assets/viewer.js");
|
||||
expect(
|
||||
new URL(loaderSrc ?? "", "https://example.com/openclaw/plugins/diffs/view/id/token").pathname,
|
||||
).toBe("/openclaw/plugins/diffs/assets/viewer.js");
|
||||
});
|
||||
|
||||
it("renders multi-file patch input", async () => {
|
||||
const patch = [
|
||||
"diff --git a/a.ts b/a.ts",
|
||||
@@ -399,7 +420,7 @@ describe("viewer assets", () => {
|
||||
const loader = await getServedViewerAsset(VIEWER_LOADER_PATH);
|
||||
|
||||
expect(loader?.contentType).toBe("text/javascript; charset=utf-8");
|
||||
expect(String(loader?.body)).toContain(`${VIEWER_RUNTIME_PATH}?v=`);
|
||||
expect(String(loader?.body)).toContain(`./viewer-runtime.js?v=`);
|
||||
});
|
||||
|
||||
it("serves the runtime bundle body", async () => {
|
||||
|
||||
@@ -9,11 +9,11 @@ import type {
|
||||
DiffViewerPayload,
|
||||
RenderedDiffDocument,
|
||||
} from "./types.js";
|
||||
import { VIEWER_LOADER_PATH } from "./viewer-assets.js";
|
||||
|
||||
const DEFAULT_FILE_NAME = "diff.txt";
|
||||
const MAX_PATCH_FILE_COUNT = 128;
|
||||
const MAX_PATCH_TOTAL_LINES = 120_000;
|
||||
const VIEWER_LOADER_DOCUMENT_PATH = "../../assets/viewer.js";
|
||||
|
||||
function escapeCssString(value: string): string {
|
||||
return value.replaceAll("\\", "\\\\").replaceAll('"', '\\"');
|
||||
@@ -296,7 +296,7 @@ function buildHtmlDocument(params: {
|
||||
${params.bodyHtml}
|
||||
</div>
|
||||
</main>
|
||||
<script type="module" src="${VIEWER_LOADER_PATH}"></script>
|
||||
<script type="module" src="${VIEWER_LOADER_DOCUMENT_PATH}"></script>
|
||||
</body>
|
||||
</html>`;
|
||||
}
|
||||
|
||||
@@ -288,7 +288,7 @@ describe("createDiffsHttpHandler", () => {
|
||||
|
||||
expect(handled).toBe(true);
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(String(res.body)).toContain("/plugins/diffs/assets/viewer-runtime.js?v=");
|
||||
expect(String(res.body)).toContain("./viewer-runtime.js?v=");
|
||||
});
|
||||
|
||||
it("serves the shared viewer runtime asset", async () => {
|
||||
|
||||
@@ -57,7 +57,7 @@ describe("diffs tool", () => {
|
||||
const cleanupSpy = vi.spyOn(store, "scheduleCleanup");
|
||||
const screenshotter = createPngScreenshotter({
|
||||
assertHtml: (html) => {
|
||||
expect(html).toContain("/plugins/diffs/assets/viewer.js");
|
||||
expect(html).toContain("../../assets/viewer.js");
|
||||
},
|
||||
assertImage: (image) => {
|
||||
expect(image).toMatchObject({
|
||||
@@ -352,7 +352,7 @@ describe("diffs tool", () => {
|
||||
it("prefers explicit tool params over configured defaults", async () => {
|
||||
const screenshotter = createPngScreenshotter({
|
||||
assertHtml: (html) => {
|
||||
expect(html).toContain("/plugins/diffs/assets/viewer.js");
|
||||
expect(html).toContain("../../assets/viewer.js");
|
||||
},
|
||||
assertImage: (image) => {
|
||||
expect(image).toMatchObject({
|
||||
|
||||
@@ -5,6 +5,7 @@ import { fileURLToPath } from "node:url";
|
||||
export const VIEWER_ASSET_PREFIX = "/plugins/diffs/assets/";
|
||||
export const VIEWER_LOADER_PATH = `${VIEWER_ASSET_PREFIX}viewer.js`;
|
||||
export const VIEWER_RUNTIME_PATH = `${VIEWER_ASSET_PREFIX}viewer-runtime.js`;
|
||||
const VIEWER_RUNTIME_RELATIVE_IMPORT_PATH = "./viewer-runtime.js";
|
||||
|
||||
const VIEWER_RUNTIME_FILE_URL = new URL("../assets/viewer-runtime.js", import.meta.url);
|
||||
|
||||
@@ -56,7 +57,7 @@ async function loadViewerAssets(): Promise<RuntimeAssetCache> {
|
||||
runtimeAssetCache = {
|
||||
mtimeMs: runtimeStat.mtimeMs,
|
||||
runtimeBody,
|
||||
loaderBody: `import "${VIEWER_RUNTIME_PATH}?v=${hash}";\n`,
|
||||
loaderBody: `import "${VIEWER_RUNTIME_RELATIVE_IMPORT_PATH}?v=${hash}";\n`,
|
||||
};
|
||||
return runtimeAssetCache;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user