const test = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); const vm = require('node:vm'); const zlib = require('node:zlib'); const runtime = {window: {}, Blob, Response, DecompressionStream, TextDecoder, Uint8Array}; vm.createContext(runtime); vm.runInContext(fs.readFileSync(path.join(__dirname, 'docview.js'), 'utf8'), runtime); function pdfWithStream(content, compressed = false) { const stream = compressed ? zlib.deflateSync(Buffer.from(content, 'latin1')) : Buffer.from(content, 'latin1'); const filter = compressed ? ' /Filter /FlateDecode' : ''; const prefix = `%PDF-1.4\n1 0 obj\n<< /Length ${stream.length}${filter} >>\nstream\n`; return Buffer.concat([Buffer.from(prefix, 'latin1'), stream, Buffer.from('\nendstream\nendobj\n%%EOF', 'latin1')]); } test('PDF text extraction handles literal strings and escaped parentheses', async () => { const pdf = pdfWithStream('BT /F1 12 Tf 72 700 Td (Hello \\(PDF\\)) Tj ET'); assert.equal(await runtime.window.DocView.pdf(pdf), 'Hello (PDF)'); }); test('PDF text extraction inflates streams and keeps TJ word spacing', async () => { const pdf = pdfWithStream('BT /F1 12 Tf [(lightweight) -250 ( parser)] TJ ET', true); assert.equal(await runtime.window.DocView.pdf(pdf), 'lightweight parser'); }); test('PDF text extraction reports scanned or non-text PDFs without OCR', async () => { const pdf = pdfWithStream('q 0 0 100 100 re f Q'); await assert.rejects(runtime.window.DocView.pdf(pdf), /без OCR/); });