Working demo · the exact test you asked for
Your brief asked for a test run on two sample files, one PDF and one web page, showing the formatting carried over. That is exactly what is below — real inputs, real outputs, both downloadable.
Operations Report — sample source document
Regional Sales Q1
-----------------
[table 1]
--------------------------------------------------------------------
Region Branch Units Revenue
--------------------------------------------------------------------
North Delhi 1,240 892,400
Chandigarh 860 611,200
Lucknow 705 498,350
North subtotal 2,805 2,001,950
West Mumbai 2,110 1,580,500
Pune 1,180 845,600
Ahmedabad 930 662,100
West subtotal 4,220 3,088,200
South Bengaluru 1,750 1,298,000
Chennai 1,105 812,350
South subtotal 2,855 2,110,350
GRAND TOTAL 9,880 7,200,500
--------------------------------------------------------------------
✓ heading underlined and on its own line · table columns still line up in a plain text editor · reading order preserved
Unicode ======== - Afrikaans - አማርኛ - العربية - অসমীয়া - Български - 閩東語 / Mìng-dĕ̤ng-ngṳ̄ - ᏣᎳᎩ - کوردی [table] -------------------------------------------------------------------- Alias(es) Universal Coded Character Set (UCS) ISO/IEC 10646 Languages 172 scripts ( list ) Standard Unicode Standard Encoding formats UTF-8 UTF-16 GB18030 UTF-32 BOCU SCSU UTF-7 --------------------------------------------------------------------
✓ 1,040 lines · 14 tables rendered as aligned columns · UTF-8 throughout · right-to-left runs (Arabic, Kurdish) preserved
First version mis-read a merged region cell as a heading and tore it out of its table. Table regions are now excluded from heading detection, then re-rendered as aligned columns.
Blocks are sorted by vertical position, so tables appear where they belong rather than being dumped at the end of the page.
Output is NFC-normalised UTF-8 with zero-width characters stripped. RTL runs are kept in logical order, which is what a text editor expects.
python extract.py <file-or-url> out.txt — commented source, no build step.
The honest limit. This handles digital PDFs and web pages. Screenshots are a different problem — an image has no text layer, so it needs OCR, and OCR accuracy depends entirely on image quality. Your brief mentions screenshots, so that is worth settling before we start: I would add Tesseract for that path and be explicit that OCR output needs review, rather than quietly implying it is as reliable as the other two.