mirror of
https://github.com/TriliumNext/Trilium.git
synced 2026-10-12 02:09:59 +00:00
The previous commit parsed every page twice with Defuddle, once as an
article and once as a whole, so that the Article / Whole page switch
was instant. Most clips never use the switch, so every popup and every
shortcut save paid for a parse whose result was thrown away.
`readable-page.js` now reads one way per call. A file injection takes
no arguments, so the script only registers
`globalThis.triliumReadPage(variant)`, and `extractPage(tabId, variant)`
calls it with a second `executeScript({ func, args })` in the same
isolated world. Two script files would have bundled Defuddle twice.
- The popup reads the article, and the whole page only when there is
no article. Switching to Whole page reads it then, showing "Reading
the page…" with Save disabled, and `PagePreview` keeps the result in
`laterReadings` so switching back and forth reads it once. A reading
is `undefined` until made and `null` when it shows nothing or fails,
which disables its button and falls back to the article.
- The shortcut and the context menu read the article, and the whole
page only when there is none: one parse on an article page, as
before the switch existed.
`readActivePage()` falls back with consecutive `if`s rather than
`article ?? await extractPage(...)`: written with `??`, v8 recorded a
negative count for the code after it, and the branch gate failed with
every case tested.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
76 lines
3.0 KiB
TypeScript
76 lines
3.0 KiB
TypeScript
import type { Window as HappyDOMWindow } from "happy-dom";
|
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
import { fakeBrowser } from "wxt/testing/fake-browser";
|
|
|
|
import { createLink, extractPage, getPageLocationOrigin, randomString } from "./utils";
|
|
|
|
describe("randomString", () => {
|
|
it("returns alphanumeric strings of the requested length", () => {
|
|
expect(randomString(0)).toBe("");
|
|
expect(randomString(20)).toMatch(/^[A-Za-z0-9]{20}$/);
|
|
expect(randomString(20)).not.toBe(randomString(20));
|
|
});
|
|
});
|
|
|
|
describe("getPageLocationOrigin", () => {
|
|
afterEach(() => setUrl("about:blank"));
|
|
|
|
it("returns the page's origin, and file:// for local files", () => {
|
|
setUrl("https://example.com:8080/dir/page.html?q=1#hash");
|
|
expect(getPageLocationOrigin()).toBe("https://example.com:8080");
|
|
|
|
setUrl("file:///home/user/page.html");
|
|
expect(getPageLocationOrigin()).toBe("file://");
|
|
});
|
|
});
|
|
|
|
describe("createLink", () => {
|
|
it("sends the click action to the extension", () => {
|
|
const sendMessage = vi.spyOn(fakeBrowser.runtime, "sendMessage")
|
|
.mockResolvedValue(undefined);
|
|
const action = { name: "openNoteInTrilium", noteId: "abc" };
|
|
|
|
const link = createLink(action, "Open");
|
|
expect(link.textContent).toBe("Open");
|
|
expect(link.style.color).toBe("lightskyblue");
|
|
expect(createLink(action, "Close", "tomato").style.color).toBe("tomato");
|
|
|
|
link.click();
|
|
expect(sendMessage).toHaveBeenCalledWith(null, action);
|
|
});
|
|
});
|
|
|
|
|
|
describe("extractPage", () => {
|
|
afterEach(() => {
|
|
Reflect.deleteProperty(fakeBrowser, "scripting");
|
|
Reflect.deleteProperty(globalThis, "triliumReadPage");
|
|
});
|
|
|
|
it("injects the readable-page script, then reads the page as asked", async () => {
|
|
const page = { title: "Article", content: "<p>Body</p>" };
|
|
const readPage = vi.fn((variant: string) => variant === "article" ? page : undefined);
|
|
const executeScript = vi.fn(async ({ func, args }: { func?: (variant: string) => unknown, args?: [ string ] }) => {
|
|
if (!func || !args) return [];
|
|
Object.assign(globalThis, { triliumReadPage: readPage });
|
|
return [ { result: func(...args) } ];
|
|
});
|
|
Object.assign(fakeBrowser, { scripting: { executeScript } });
|
|
|
|
expect(await extractPage(7, "article")).toBe(page);
|
|
expect(executeScript.mock.calls.map(([ injection ]) => injection)).toEqual([
|
|
{ target: { tabId: 7 }, files: [ "/readable-page.js" ] },
|
|
{ target: { tabId: 7 }, func: expect.any(Function), args: [ "article" ] }
|
|
]);
|
|
expect(await extractPage(7, "wholePage")).toBeUndefined();
|
|
expect(readPage.mock.calls).toEqual([ [ "article" ], [ "wholePage" ] ]);
|
|
|
|
executeScript.mockResolvedValue([]);
|
|
expect(await extractPage(7, "article")).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
function setUrl(url: string) {
|
|
(window as unknown as HappyDOMWindow).happyDOM.setURL(url);
|
|
}
|