Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"react-dom": "^19.3.1"
},
"devDependencies": {
"@types/chrome": "^0.1.4",
"@types/chrome": "^0.3.6",
"@types/react": "^19.3.0",
"@types/react-dom": "^19.3.0",
"@vitejs/plugin-react": "latest",
Expand Down
2 changes: 2 additions & 0 deletions apps/extension/src/panel-presence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
* documents exist, so nothing has to be announced: a port from the panel would not survive
* the worker being stopped, and reconnecting it would keep waking the worker.
*/
// The literal, unlike chrome.runtime.ContextType.SIDE_PANEL, needs no runtime enum object.
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-assignment
const sidePanel = "SIDE_PANEL" as chrome.runtime.ContextType;

export async function panelShowsTab(tabId: number): Promise<boolean> {
Expand Down
6 changes: 3 additions & 3 deletions apps/extension/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@ function serviceWorker(alias: SdkAliases): Plugin {
rolldownOptions: {
input: resolve(import.meta.dirname, entry),
// Vite's preload helper mentions import.meta; with modulePreload off it is unused.
onwarn(warning, warn) {
if (warning.code !== "EMPTY_IMPORT_META") {
warn(warning);
onLog(level, log, handler) {
if (log.code !== "EMPTY_IMPORT_META") {
handler(level, log);
}
},
// Core's modules only declare things; let the small worker bundle take
Expand Down
6 changes: 3 additions & 3 deletions apps/reader/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,12 @@
"yaml": "^2.9.1"
},
"devDependencies": {
"@playwright/test": "1.61.1",
"@playwright/test": "1.64.1",
"@types/react": "^19.3.0",
"@types/react-dom": "^19.3.0",
"@vitejs/plugin-react": "latest",
"axe-core": "^4.13.0",
"fake-indexeddb": "6.2.4",
"axe-core": "^4.14.0",
"fake-indexeddb": "6.2.6",
"vite": "latest"
}
}
2 changes: 1 addition & 1 deletion apps/reader/src/highlight-colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ let parsedDevice: { readonly raw: string | null; readonly value: HighlightMeanin
export function deviceHighlightMeanings(): HighlightMeanings {
const raw = read(deviceMeaningsKey);
if (raw !== parsedDevice.raw) {
let value: unknown = {};
let value: unknown;
try {
value = raw ? JSON.parse(raw) : {};
} catch {
Expand Down
18 changes: 10 additions & 8 deletions apps/reader/src/lazy-feature.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { t as translate } from "@lingui/core/macro";
import { useLingui as useLocale } from "@lingui/react";
import { Trans } from "@lingui/react/macro";
import { Component, lazy, Suspense, useMemo, useState } from "react";
import { Component, lazy, Suspense, useState } from "react";

import type { ComponentType, JSX, ReactNode } from "react";

Expand All @@ -20,14 +20,16 @@ export function lazyFeature<Props extends object>(
};
function Feature(props: Props): JSX.Element {
useLocale();
const [attempt, retry] = useState(0);
const Surface = useMemo(() => {
// React.lazy remembers rejections; a retry needs a fresh lazy identity.
void attempt;
return lazy(load);
}, [attempt]);
// React.lazy remembers rejections; a retry needs a fresh lazy identity.
const [{ attempt, Surface }, setFeature] = useState(() => ({
attempt: 0,
Surface: lazy(load),
}));
const retry = (): void => {
setFeature((current) => ({ attempt: current.attempt + 1, Surface: lazy(load) }));
};
return (
<FeatureBoundary key={attempt} label={label} retry={() => retry((value) => value + 1)}>
<FeatureBoundary key={attempt} label={label} retry={retry}>
<Suspense fallback={<p role="status">{translate`Loading ${label}…`}</p>}>
<Surface {...props} />
</Suspense>
Expand Down
3 changes: 1 addition & 2 deletions apps/reader/src/library-index-queue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,11 @@ export async function runLibraryIndexQueue(options: LibraryIndexQueueOptions): P
throw new Error("Saved page exceeds the background extraction limit.");
}
text = extract(result.bytes);
} catch (reason) {
} catch {
signal.throwIfAborted();
skipped++;
attempted.add(key);
// File failures don't prevent the rest of the library from being indexed.
void reason;
}
if (text !== undefined) {
await idle(signal);
Expand Down
1 change: 1 addition & 0 deletions apps/reader/src/source-part-creation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ export async function confirmChapterPlans(
} catch (error) {
throw new Error(
`${String(index)} of ${String(plans.length)} chapters created. You can retry without creating duplicates. ${error instanceof Error ? error.message : translate({ message: "Could not create the chapter." })}`,
{ cause: error },
);
}
}
Expand Down
2 changes: 1 addition & 1 deletion apps/reader/src/use-mdbase-library-views.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export function useMdbaseLibraryViews(
t({ message: "Reader could not save this library view." }),
);
setProblem(message);
throw new Error(message);
throw new Error(message, { cause: reason });
} finally {
setSaving(false);
}
Expand Down
8 changes: 7 additions & 1 deletion apps/reader/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,13 @@ export default defineConfig(async ({ mode }): Promise<UserConfig> => {
"@codemirror/view",
],
},
...{ test: { setupFiles: [new URL("../../scripts/test-i18n.mjs", import.meta.url).pathname] } },
...{
test: {
setupFiles: [new URL("../../scripts/test-i18n.mjs", import.meta.url).pathname],
// happy-dom 21 leaves iframes without documents unless page loading is enabled.
environmentOptions: { happyDOM: { settings: { enableIframePageLoading: true } } },
},
},
// The SDK starts its own module Worker from a module-relative URL; keep it out of
// dev pre-bundling so that URL still names the SDK's files, and emit ES workers.
optimizeDeps: { exclude: ["@mdbase-dev/sdk"] },
Expand Down
30 changes: 15 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"format": "prettier --write .",
"format:check": "prettier --check .",
"lint": "pnpm lint:code && pnpm format:check && pnpm check:architecture",
"lint:code": "eslint . --max-warnings 0",
"lint:code": "node --max-old-space-size=8192 node_modules/eslint/bin/eslint.js . --max-warnings 0",
"test": "pnpm test:architecture && pnpm test:publisher && pnpm test:workspaces",
"test:workspaces": "pnpm -r --if-present test",
"test:architecture": "node --test scripts/lib/architecture-check.test.mjs",
Expand All @@ -41,31 +41,31 @@
"typecheck": "pnpm -r --if-present typecheck"
},
"devDependencies": {
"@babel/core": "7.29.0",
"@babel/core": "8.0.9",
"@callumalpass/mdbase": "0.3.0-rc.9",
"@eslint/js": "^9.39.2",
"@lingui/babel-plugin-lingui-macro": "6.9.0",
"@lingui/cli": "6.9.0",
"@eslint/js": "^10.0.1",
"@lingui/babel-plugin-lingui-macro": "6.10.1",
"@lingui/cli": "6.10.1",
"@lingui/core": "6.10.1",
"@lingui/format-po": "6.9.0",
"@lingui/message-utils": "6.9.0",
"@lingui/format-po": "6.10.1",
"@lingui/message-utils": "6.10.1",
"@lingui/react": "6.10.1",
"@lingui/vite-plugin": "6.9.0",
"@lingui/vite-plugin": "6.10.1",
"@mdbase-dev/connect-dev": "0.1.0-beta.125",
"@mdbase-dev/connect-protocol": "file:packages/connect/vendor/mdbase-dev-connect-protocol-0.1.0-beta.129-c280cd194ffd.tgz",
"@mdbase-dev/i18n": "0.1.0-beta.147",
"@mdbase-reader/i18n": "workspace:0.1.0-beta.0",
"@types/node": "^22.19.11",
"eslint": "^9.39.2",
"@types/node": "^26.6.5",
"eslint": "^10.13.0",
"eslint-import-resolver-typescript": "^4.4.5",
"eslint-plugin-import-x": "^4.17.1",
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-react-hooks": "^7.1.1",
"globals": "^16.5.0",
"prettier": "^3.9.0",
"typescript": "^5.9.3",
"typescript-eslint": "^8.66.0",
"vitest": "^4.1.10",
"globals": "^17.13.0",
"prettier": "^3.9.10",
"typescript": "^6.0.3",
"typescript-eslint": "^8.72.1",
"vitest": "^5.0.5",
"yaml": "^2.9.1"
}
}
2 changes: 2 additions & 0 deletions packages/connect/src/reader-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ export async function refineReaderSettings(
const template = settings.stored[key];
const problem = template === undefined ? undefined : await nameTemplateProblem(template);
if (problem) {
// No enum is involved; typescript-eslint 8.72 misreads the literal-union key as one.
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-assignment
values[key] = readerSettingsDefinition.fields[key].default;
stored.delete(key);
warnings.push({ field: key, message: `${problem}. Reader's default is used meanwhile.` });
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/application/materialize-source.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ describe("materializeSource", () => {

it("uses a readable title fallback when CSL data is absent", () => {
const { citation, ...uncitedSource } = source;
void citation;
expect(citation).toBeDefined();
const result = materializeSource({ ...uncitedSource, body: "![[ann_01]]" }, [annotation], []);

expect(result.markdown).toContain("> — Crime and Punishment, p. 16");
Expand Down
2 changes: 1 addition & 1 deletion packages/reading-surface/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@
"@mdbase-reader/core": "workspace:*"
},
"devDependencies": {
"happy-dom": "^20.11.2"
"happy-dom": "^21.0.4"
}
}
2 changes: 1 addition & 1 deletion packages/renderer-epub/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@
},
"devDependencies": {
"@types/react": "^19.3.0",
"happy-dom": "^20.11.2"
"happy-dom": "^21.0.4"
}
}
4 changes: 2 additions & 2 deletions packages/renderer-html/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
},
"devDependencies": {
"@types/react": "^19.3.0",
"happy-dom": "^20.11.2",
"jsdom": "28.1.0"
"happy-dom": "^21.0.4",
"jsdom": "30.1.3"
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { transformPosition, transformSize } from "@embedpdf/models";
import { Rotation, transformPosition, transformSize } from "@embedpdf/models";
import { describe, expect, it } from "vitest";

import {
Expand Down Expand Up @@ -27,7 +27,7 @@ describe("touch selection geometry", () => {
expect(rangeFromEndpoints(fixed, fixed)).toEqual({ start: fixed, end: fixed });
});

it.each([0, 1, 2, 3])(
it.each([Rotation.Degree0, Rotation.Degree90, Rotation.Degree180, Rotation.Degree270])(
"round-trips client coordinates at rotation %i and different zoom levels",
(angle) => {
const rotation = angle;
Expand Down
2 changes: 2 additions & 0 deletions packages/renderer-pdf/src/pdf-touch-selection-handles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,8 @@ class TouchSelectionHandles {
}
const distance = rectDistance(point, rect);
if (!closest || distance < closest.distance) {
// Two quarter-turn counts summed mod 4 are a quarter-turn count.
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-assignment
closest = { page, rect, rotation: (object.rotation + doc.rotation) % 4, distance };
}
}
Expand Down
Loading