refactor(file-preview): one rendersAsPage() for the terminal and the preview

What counts as an HTML page lived in three places: HTML_VIEW_EXTENSIONS
on the server, a /\.html?$/ regex in the terminal link provider and a
HTML_PAGE_EXTS set in panels-ui.js. The two frontend copies are now one
rendersAsPage() next to previewsInFileViewer() in constants.js, used by
the link provider (and through it every grid tile and the split's Pane
B, which share registerFilePathLinkProvider) and by openFilePreview()
and its toolbar. A new test pins it equal to the server's list.

toggleFilePreviewPage() now returns the preview load, so a caller (and
the coming frontend test) can await the flip.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Codeman maintainer committed 2026-10-13 17:14:53 +02:00
1 parent 7b4832b3e4
commit 8f62faf130
4 files changed
+67 -6

No files matched your search

+41
View File
@@ -0,0 +1,41 @@
/**
* @fileoverview File Viewer: an `.html` file renders as a sandboxed page.
*
* The server half (`/html-view/<cap>/...`, html-view-routes.ts) is pinned by
* test/routes/html-view-routes.test.ts. This file pins the frontend half:
*
* 1. `rendersAsPage()` (constants.js) and the server's HTML_VIEW_EXTENSIONS
* name the same extensions, so the terminal, the preview and the route
* agree on what a page is.
*
* Loaded via `vm` with a jsdom document injected, like
* file-preview-markdown.test.ts: constants.js + panels-ui.js only.
*/
import { readFileSync } from 'node:fs';
import { resolve } from 'node:path';
import vm from 'node:vm';
import { describe, expect, it } from 'vitest';
import { HTML_VIEW_EXTENSIONS } from '../src/web/routes/html-view-routes.js';
const PUBLIC = resolve(import.meta.dirname, '../src/web/public');
const constantsJs = readFileSync(resolve(PUBLIC, 'constants.js'), 'utf8');
describe('rendersAsPage', () => {
it('names exactly the extensions the html-view route renders', () => {
const context = vm.createContext({});
vm.runInContext(`${constantsJs}\nglobalThis.__page = { rendersAsPage, HTML_PAGE_EXTENSIONS };`, context, {
filename: 'constants.js',
});
const { rendersAsPage, HTML_PAGE_EXTENSIONS } = (
context as { __page: { rendersAsPage: (p: string) => boolean; HTML_PAGE_EXTENSIONS: Set<string> } }
).__page;
expect([...HTML_PAGE_EXTENSIONS].sort()).toEqual([...HTML_VIEW_EXTENSIONS].sort());
expect(rendersAsPage('/tmp/out/report.html')).toBe(true);
expect(rendersAsPage('docs/INDEX.HTM')).toBe(true);
expect(rendersAsPage('notes.md')).toBe(false);
expect(rendersAsPage('page.html.txt')).toBe(false);
expect(rendersAsPage(undefined as unknown as string)).toBe(false);
});
});