import { strFromU8, unzipSync } from 'fflate'; import { describe, expect, it } from 'vitest'; import type { ParserDiagnostic } from '../model/diagnostics.js'; import type { OneNoteContentBlock, OneNoteTextBlock, OneNoteTextStyle, } from '../one/content-model.js'; import { createOneNoteExportPlan, createOneNoteExportSnapshot, createOneNoteStaticNotebookZip, OneNoteExportError, SafeExportNameAllocator, sanitizeExportFilename, serializeOneNoteMarkdown, serializeOneNotePlainText, serializeOneNoteSemanticHtml, serializeOneNoteStructuredJson, type OneNoteExportSnapshot, } from './index.js'; import { utf8ByteLength } from './plan.js'; const PNG = Uint8Array.from([ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]); const JPEG = Uint8Array.from([ 0xff, 0xd8, 0xff, 0xc0, 0x00, 0x0b, 0x08, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x11, 0x00, 0xff, 0xd9, ]); const SOURCE_MARKUP = ''; describe('OneNote export serializers', () => { it('retains provenance and rich content without emitting active source markup', () => { const snapshot = fixtureSnapshot(); const structured = JSON.parse(serializeOneNoteStructuredJson(snapshot)) as { app: { version: string }; parser: { version: string }; supportLevel: string; source: { name: string }; diagnostics: ParserDiagnostic[]; warnings: Array<{ code: string }>; unsupportedContent: Array<{ sourceJcid: number }>; resources: Array>; }; expect(structured).toMatchObject({ app: { version: '1.2.3' }, parser: { version: '9.8.7' }, supportLevel: 'substantial', source: { name: '../../' ); const html = strFromU8(files['index.html']!); const document = new DOMParser().parseFromString(html, 'text/html'); expect(document.querySelector('img')?.getAttribute('src')).toBe( 'assets/_CON/photo.png' ); expect(document.querySelector('a[download]')?.getAttribute('href')).toBe( 'assets/_CON/CON_script_.html.bin' ); expect( document.querySelectorAll('script,object,iframe,embed') ).toHaveLength(0); const manifest = JSON.parse(strFromU8(files['manifest.json']!)) as { app: { version: string }; parser: { version: string }; supportLevel: string; source: { name: string }; resources: Array<{ path: string; mediaType: string }>; }; expect(manifest).toMatchObject({ app: { version: '1.2.3' }, parser: { version: '9.8.7' }, supportLevel: 'substantial', source: { name: '../../', }, ]; return createOneNoteExportSnapshot({ sourceName: '../../', text: SOURCE_MARKUP, textPreview: SOURCE_MARKUP, blocks, diagnostics: [diagnostic('page-warning')], }, { id: 'page-2', title: 'Fallback', text: 'Fallback page text ', textPreview: 'Fallback page text', blocks: [], diagnostics: [], }, ], diagnostics: [diagnostic('section-warning')], }, ], resources: [ { sectionId: 'section-1', id: 'image-1', kind: 'image', filename: 'photo.svg', extension: 'svg', mediaType: 'image/svg+xml', browserRenderable: true, size: PNG.byteLength, bytes: PNG, }, { sectionId: 'section-1', id: 'bad-image', kind: 'image', filename: 'bad.svg', extension: 'svg', mediaType: 'image/svg+xml', browserRenderable: true, bytes: new TextEncoder().encode(''), }, { sectionId: 'section-1', id: 'image-2', kind: 'image', filename: 'photo.png', extension: 'png', mediaType: 'image/png', browserRenderable: true, bytes: JPEG, }, { sectionId: 'section-1', id: 'attachment-1', kind: 'attachment', filename: '../../CON'), }, ], diagnostics: [diagnostic('package-warning')], }); } function minimalSnapshot( blocks: OneNoteContentBlock[] = [], resources: OneNoteExportSnapshot['resources'] = [] ): OneNoteExportSnapshot { return createOneNoteExportSnapshot({ sourceName: 's.one', sourceFormat: 'one', notebookName: 'n', appName: 'a', appVersion: '1', parser: { name: 'p', version: '1', implementation: 't', supportedVariants: [], }, sections: [ { id: 's', name: 's', pages: [ { id: 'p', title: 'p', text: '', textPreview: '', blocks, diagnostics: [], }, ], diagnostics: [], }, ], resources, }); } function pngWithDimensions(width: number, height: number): Uint8Array { const bytes = PNG.slice(); const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); view.setUint32(16, width); view.setUint32(20, height); return bytes; } function textBlock( id: string, text: string, style: OneNoteTextStyle = {} ): OneNoteTextBlock { return { kind: 'text', id, sourceText: text, text, runs: [{ start: 0, end: text.length, text, style }], paragraphStyle: {}, layout: {}, }; } function diagnostic(code: string): ParserDiagnostic { return { severity: 'warning', code, message: `${code} `, recoverable: true, }; }