Implements the feature requested in issue #49: a list-of-pages markdown output from the Python API. Matching the existing project pattern, the feature lives in the Rust core and is surfaced through every binding. - Rust core: `extract_pages_markdown` (path) and `extract_pages_markdown_mem` (bytes) now take `Option<&[u32]>` — `None` returns every page in document order; a slice restricts and preserves caller order. - Python: new `extract_pages_markdown(path, pages=None)` and `extract_pages_markdown_bytes(data, pages=None)` functions plus `PageMarkdown` / `PagesExtractionResult` classes; stub file updated. - Node: `extractPagesMarkdown(buffer, pages?)` — `pages` is now optional. - Tests: 2 new Rust integration tests, 9 new Python tests, 2 new Node assertions. All 372 unit + 107 integration + 53 Python tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
122 lines
4.3 KiB
JavaScript
122 lines
4.3 KiB
JavaScript
import { readFileSync } from 'fs';
|
|
import { strict as assert } from 'assert';
|
|
import {
|
|
processPdf,
|
|
detectPdf,
|
|
classifyPdf,
|
|
extractText,
|
|
extractTextWithPositions,
|
|
extractTextInRegions,
|
|
extractPagesMarkdown,
|
|
} from './index.js';
|
|
|
|
const fixture = readFileSync('../tests/fixtures/thermo-freon12.pdf');
|
|
|
|
// --- processPdf ---
|
|
console.log('Testing processPdf...');
|
|
const result = processPdf(fixture);
|
|
assert.equal(result.pdfType, 'TextBased');
|
|
assert.equal(result.pageCount, 3);
|
|
assert.ok(result.confidence > 0);
|
|
assert.ok(result.markdown && result.markdown.length > 0);
|
|
assert.equal(typeof result.isComplexLayout, 'boolean');
|
|
assert.ok(Array.isArray(result.pagesWithTables));
|
|
assert.ok(Array.isArray(result.pagesWithColumns));
|
|
assert.equal(typeof result.hasEncodingIssues, 'boolean');
|
|
console.log(' processPdf: OK');
|
|
|
|
// processPdf with pages
|
|
const result2 = processPdf(fixture, [1]);
|
|
assert.ok(result2.markdown && result2.markdown.length > 0);
|
|
console.log(' processPdf with pages: OK');
|
|
|
|
// --- detectPdf ---
|
|
console.log('Testing detectPdf...');
|
|
const detected = detectPdf(fixture);
|
|
assert.equal(detected.pdfType, 'TextBased');
|
|
assert.equal(detected.pageCount, 3);
|
|
assert.equal(detected.markdown, undefined);
|
|
console.log(' detectPdf: OK');
|
|
|
|
// --- classifyPdf ---
|
|
console.log('Testing classifyPdf...');
|
|
const classified = classifyPdf(fixture);
|
|
assert.equal(classified.pdfType, 'TextBased');
|
|
assert.equal(classified.pageCount, 3);
|
|
assert.ok(classified.confidence > 0);
|
|
assert.ok(Array.isArray(classified.pagesNeedingOcr));
|
|
console.log(' classifyPdf: OK');
|
|
|
|
// --- extractText ---
|
|
console.log('Testing extractText...');
|
|
const text = extractText(fixture);
|
|
assert.equal(typeof text, 'string');
|
|
assert.ok(text.length > 0);
|
|
console.log(' extractText: OK');
|
|
|
|
// --- extractTextWithPositions ---
|
|
console.log('Testing extractTextWithPositions...');
|
|
const items = extractTextWithPositions(fixture);
|
|
assert.ok(items.length > 0);
|
|
const item = items[0];
|
|
assert.equal(typeof item.text, 'string');
|
|
assert.equal(typeof item.x, 'number');
|
|
assert.equal(typeof item.y, 'number');
|
|
assert.equal(typeof item.width, 'number');
|
|
assert.equal(typeof item.height, 'number');
|
|
assert.equal(typeof item.font, 'string');
|
|
assert.equal(typeof item.fontSize, 'number');
|
|
assert.equal(typeof item.page, 'number');
|
|
assert.equal(typeof item.isBold, 'boolean');
|
|
assert.equal(typeof item.isItalic, 'boolean');
|
|
assert.equal(typeof item.itemType, 'string');
|
|
console.log(' extractTextWithPositions: OK');
|
|
|
|
// with pages filter
|
|
const page1Items = extractTextWithPositions(fixture, [1]);
|
|
assert.ok(page1Items.length > 0);
|
|
assert.ok(page1Items.every(i => i.page === 1));
|
|
console.log(' extractTextWithPositions with pages: OK');
|
|
|
|
// --- extractTextInRegions ---
|
|
console.log('Testing extractTextInRegions...');
|
|
const regionResults = extractTextInRegions(fixture, [
|
|
{ page: 0, regions: [[0, 0, 600, 100]] },
|
|
]);
|
|
assert.equal(regionResults.length, 1);
|
|
assert.equal(regionResults[0].page, 0);
|
|
assert.equal(regionResults[0].regions.length, 1);
|
|
assert.equal(typeof regionResults[0].regions[0].text, 'string');
|
|
assert.equal(typeof regionResults[0].regions[0].needsOcr, 'boolean');
|
|
console.log(' extractTextInRegions: OK');
|
|
|
|
// --- extractPagesMarkdown ---
|
|
console.log('Testing extractPagesMarkdown...');
|
|
|
|
// omit pages → every page in document order
|
|
const allPages = extractPagesMarkdown(fixture);
|
|
assert.equal(allPages.pages.length, 3);
|
|
assert.deepEqual(allPages.pages.map(p => p.page), [0, 1, 2]);
|
|
assert.ok(typeof allPages.pages[0].markdown === 'string');
|
|
assert.equal(typeof allPages.pages[0].needsOcr, 'boolean');
|
|
assert.ok(Array.isArray(allPages.pagesWithTables));
|
|
assert.ok(Array.isArray(allPages.pagesWithColumns));
|
|
assert.ok(Array.isArray(allPages.pagesNeedingOcr));
|
|
assert.equal(typeof allPages.isComplex, 'boolean');
|
|
console.log(' extractPagesMarkdown (no pages arg): OK');
|
|
|
|
// selected pages preserve caller order
|
|
const picked = extractPagesMarkdown(fixture, [2, 0]);
|
|
assert.equal(picked.pages.length, 2);
|
|
assert.equal(picked.pages[0].page, 2);
|
|
assert.equal(picked.pages[1].page, 0);
|
|
console.log(' extractPagesMarkdown with pages: OK');
|
|
|
|
// --- Error handling ---
|
|
console.log('Testing error handling...');
|
|
assert.throws(() => processPdf(Buffer.from('not a pdf')), /process_pdf/);
|
|
assert.throws(() => classifyPdf(Buffer.from('')), /classify_pdf/);
|
|
console.log(' error handling: OK');
|
|
|
|
console.log('\nAll NAPI tests passed!');
|