feat: render rich OneNote pages and resources

This commit is contained in:
2026-07-22 19:18:42 +02:00
parent 141be03f5e
commit 1750a6b5c3
12 changed files with 1252 additions and 64 deletions

View File

@@ -1,28 +1,35 @@
import type { OneNotePageDto } from '../onenote/model/dto.js';
import type { OneNoteResource } from '../onenote/one/content-model.js';
import {
failureFromUnknown,
openPackageForWorker,
openSectionForWorker,
resourcePayload,
workerPageKey,
workerResourceKey,
} from './parser-adapter.js';
import type { WorkerRequest, WorkerResponse } from './worker-protocol.js';
interface ModuleWorkerScope {
onmessage: ((event: MessageEvent<WorkerRequest>) => void) | null;
postMessage(response: WorkerResponse): void;
postMessage(response: WorkerResponse, transfer?: Transferable[]): void;
}
interface ParserSession {
pages: Map<string, OneNotePageDto>;
resources: Map<string, OneNoteResource>;
}
const workerScope = globalThis as unknown as ModuleWorkerScope;
const sessions = new Map<string, ParserSession>();
let sessionSequence = 0;
function createSession(pages: Map<string, OneNotePageDto>): string {
function createSession(
pages: Map<string, OneNotePageDto>,
resources: Map<string, OneNoteResource>
): string {
const id = `session-${++sessionSequence}`;
sessions.set(id, { pages });
sessions.set(id, { pages, resources });
return id;
}
@@ -34,7 +41,7 @@ async function handleRequest(data: WorkerRequest): Promise<void> {
new Uint8Array(data.bytes),
data.fileName
);
const sessionId = createSession(parsed.pages);
const sessionId = createSession(parsed.pages, parsed.resources);
workerScope.postMessage({
type: 'section',
requestId: data.requestId,
@@ -56,7 +63,7 @@ async function handleRequest(data: WorkerRequest): Promise<void> {
new Uint8Array(data.bytes),
data.fileName
);
const sessionId = createSession(parsed.pages);
const sessionId = createSession(parsed.pages, parsed.resources);
workerScope.postMessage({
type: 'package',
requestId: data.requestId,
@@ -108,6 +115,47 @@ async function handleRequest(data: WorkerRequest): Promise<void> {
});
return;
}
case 'get-resource': {
const session = sessions.get(data.sessionId);
if (!session) {
workerScope.postMessage({
type: 'failure',
requestId: data.requestId,
error: {
code: 'session-not-available',
message: 'The parser session is no longer available.',
recoverable: false,
},
});
return;
}
const resource = session.resources.get(
workerResourceKey(data.resourceId, data.sectionId)
);
const payload = resource ? resourcePayload(resource) : undefined;
if (!payload) {
workerScope.postMessage({
type: 'failure',
requestId: data.requestId,
error: {
code: 'resource-not-available',
message: 'The selected embedded resource is not available.',
recoverable: true,
},
});
return;
}
workerScope.postMessage(
{
type: 'resource',
requestId: data.requestId,
sessionId: data.sessionId,
resource: payload,
},
[payload.bytes]
);
return;
}
case 'dispose':
sessions.delete(data.sessionId);
workerScope.postMessage({