feat: decode OneNote ink strokes

This commit is contained in:
2026-07-22 19:16:08 +02:00
parent 30b0357530
commit 141be03f5e
5 changed files with 424 additions and 15 deletions

View File

@@ -44,6 +44,24 @@ describe('OneNote rich-content model', () => {
expect(model.pages[0]!.text).toContain('TEST\tD');
expect(blocks.some((block) => block.kind === 'table')).toBe(true);
expect(blocks.some((block) => block.kind === 'image')).toBe(true);
const ink = blocks.filter((block) => block.kind === 'ink');
expect(ink).toHaveLength(11);
expect(
ink
.flatMap((block) => block.strokes)
.reduce((total, stroke) => total + stroke.points.length, 0)
).toBe(1316);
expect(ink[0]!.strokes[0]!.points.slice(0, 3)).toEqual([
{ x: 3360, y: 5848 },
{ x: 3360, y: 5854 },
{ x: 3360, y: 5860 },
]);
expect(ink[0]!.boundingBox).toEqual({
x: 2152,
y: 5848,
width: 1208,
height: 3992,
});
const testing = textBlock(blocks, 'Testing!');
expect(testing.runs.map((run) => run.text)).toEqual(['Testing', '!']);
@@ -86,6 +104,7 @@ describe('OneNote rich-content model', () => {
const diagnosticCodes = model.diagnostics.map(({ code }) => code);
expect(diagnosticCodes).not.toContain('CONTENT_PARSE_FAILED');
expect(diagnosticCodes).not.toContain('INVALID_TABLE_VECTOR');
expect(diagnosticCodes).not.toContain('INK_STROKE_PARSE_FAILED');
});
it('associates only allow-listed hyperlink marker targets', () => {
@@ -101,6 +120,24 @@ describe('OneNote rich-content model', () => {
unsafe.runs.find((run) => run.text === 'Example')?.href
).toBeUndefined();
});
it('bounds aggregate ink point expansion', () => {
const model = parseOneNoteSectionContent(fixture, {
limits: { maxInkPoints: 100 },
});
expect(model.diagnostics).toContainEqual(
expect.objectContaining({
code: 'INK_STROKE_PARSE_FAILED',
message: expect.stringContaining('Ink point count exceeds 100'),
})
);
const blocks = model.pages.flatMap((page) => collectBlocks(page.blocks));
const parsedPoints = blocks
.filter((block) => block.kind === 'ink')
.flatMap((block) => block.strokes)
.reduce((total, stroke) => total + stroke.points.length, 0);
expect(parsedPoints).toBeLessThanOrEqual(100);
});
});
function parseSyntheticLink(href: string): OneNoteTextBlock {