import { WorkerPoolContextProvider, useWorkerPool } from "@pierre/diffs/react";import DiffsWorker from "@pierre/diffs/worker/worker.js?worker";import * as Schema from "effect/Schema";import { useEffect, useMemo, type ReactNode } from "react";import { useTheme } from "../hooks/useTheme";import { resolveDiffThemeName, type DiffThemeName } from "../lib/diffRendering"; export class DiffWorkerError extends Schema.TaggedErrorClass<DiffWorkerError>()("DiffWorkerError", { operation: Schema.Literals(["create-worker", "get-render-options", "set-render-options"]), themeName: Schema.Literals(["pierre-light", "pierre-dark"]), cause: Schema.Defect(),}) { override get message(): string { return `Diff worker operation ${this.operation} failed for theme ${this.themeName}.`; }} function DiffWorkerThemeSync({ themeName }: { themeName: DiffThemeName }) { const workerPool = useWorkerPool(); useEffect(() => { if (!workerPool) { return; } let operation: DiffWorkerError["operation"] = "get-render-options"; void (async () => { try { const current = workerPool.getDiffRenderOptions(); if (current.theme === themeName) { return; } operation = "set-render-options"; await workerPool.setRenderOptions({ ...current, theme: themeName, }); } catch (cause) { console.error(new DiffWorkerError({ operation, themeName, cause })); } })(); }, [themeName, workerPool]); return null;} export function DiffWorkerPoolProvider({ children }: { children?: ReactNode }) { const { resolvedTheme } = useTheme(); const diffThemeName = resolveDiffThemeName(resolvedTheme); const workerPoolSize = useMemo(() => { const cores = typeof navigator === "undefined" ? 4 : Math.max(1, navigator.hardwareConcurrency || 4); return Math.max(2, Math.min(6, Math.floor(cores / 2))); }, []); return ( <WorkerPoolContextProvider poolOptions={{ workerFactory: () => { try { return new DiffsWorker(); } catch (cause) { throw new DiffWorkerError({ operation: "create-worker", themeName: diffThemeName, cause, }); } }, poolSize: workerPoolSize, totalASTLRUCacheSize: 240, }} highlighterOptions={{ theme: diffThemeName, tokenizeMaxLineLength: 1_000, useTokenTransformer: true, }} > <DiffWorkerThemeSync themeName={diffThemeName} /> {children} </WorkerPoolContextProvider> );}
import { WorkerPoolContextProvider, useWorkerPool } from "@pierre/diffs/react";
import DiffsWorker from "@pierre/diffs/worker/worker.js?worker";
import * as Schema from "effect/Schema";
import { useEffect, useMemo, type ReactNode } from "react";
import { useTheme } from "../hooks/useTheme";
import { resolveDiffThemeName, type DiffThemeName } from "../lib/diffRendering";
export class DiffWorkerError extends Schema.TaggedErrorClass<DiffWorkerError>()("DiffWorkerError", {
operation: Schema.Literals(["create-worker", "get-render-options", "set-render-options"]),
themeName: Schema.Literals(["pierre-light", "pierre-dark"]),
cause: Schema.Defect(),
}) {
override get message(): string {
return `Diff worker operation ${this.operation} failed for theme ${this.themeName}.`;
}
}
function DiffWorkerThemeSync({ themeName }: { themeName: DiffThemeName }) {
const workerPool = useWorkerPool();
useEffect(() => {
if (!workerPool) {
return;
}
let operation: DiffWorkerError["operation"] = "get-render-options";
void (async () => {
try {
const current = workerPool.getDiffRenderOptions();
if (current.theme === themeName) {
return;
}
operation = "set-render-options";
await workerPool.setRenderOptions({
...current,
theme: themeName,
});
} catch (cause) {
console.error(new DiffWorkerError({ operation, themeName, cause }));
}
})();
}, [themeName, workerPool]);
return null;
}
export function DiffWorkerPoolProvider({ children }: { children?: ReactNode }) {
const { resolvedTheme } = useTheme();
const diffThemeName = resolveDiffThemeName(resolvedTheme);
const workerPoolSize = useMemo(() => {
const cores =
typeof navigator === "undefined" ? 4 : Math.max(1, navigator.hardwareConcurrency || 4);
return Math.max(2, Math.min(6, Math.floor(cores / 2)));
}, []);
return (
<WorkerPoolContextProvider
poolOptions={{
workerFactory: () => {
try {
return new DiffsWorker();
} catch (cause) {
throw new DiffWorkerError({
operation: "create-worker",
themeName: diffThemeName,
cause,
});
}
},
poolSize: workerPoolSize,
totalASTLRUCacheSize: 240,
}}
highlighterOptions={{
theme: diffThemeName,
tokenizeMaxLineLength: 1_000,
useTokenTransformer: true,
}}
>
<DiffWorkerThemeSync themeName={diffThemeName} />
{children}
</WorkerPoolContextProvider>
);
}