digpdf 0.1.0__py3-none-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- digpdf/LICENSE +19 -0
- digpdf/README.md +178 -0
- digpdf/THIRD-PARTY-NOTICES.txt +15853 -0
- digpdf/__init__.py +76 -0
- digpdf/__main__.py +3 -0
- digpdf/bin/digpdf.exe +0 -0
- digpdf/bin/pdfium.dll +0 -0
- digpdf-0.1.0.dist-info/METADATA +187 -0
- digpdf-0.1.0.dist-info/RECORD +11 -0
- digpdf-0.1.0.dist-info/WHEEL +4 -0
- digpdf-0.1.0.dist-info/entry_points.txt +2 -0
digpdf/LICENSE
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
digpdf
|
|
2
|
+
Copyright (c) 2026 Jakob Mørup Wang. All rights reserved.
|
|
3
|
+
|
|
4
|
+
Permission is granted, free of charge, to any person obtaining a copy of the digpdf program in compiled form and of
|
|
5
|
+
the files distributed with it, among them its Python package (together the "Software"), to use it for any purpose,
|
|
6
|
+
including commercial use, and to redistribute unmodified copies of it, provided this licence and
|
|
7
|
+
THIRD-PARTY-NOTICES.txt are included with every copy.
|
|
8
|
+
|
|
9
|
+
The source code of the digpdf program is not published and is not part of this licence. You may not modify the
|
|
10
|
+
Software, or decompile, disassemble or reverse engineer the program, except where the law allows it regardless of
|
|
11
|
+
this limitation.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
14
|
+
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
15
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
16
|
+
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
17
|
+
|
|
18
|
+
The Software includes third-party software under its own licences, listed in THIRD-PARTY-NOTICES.txt; those licences
|
|
19
|
+
govern those parts.
|
digpdf/README.md
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# digpdf
|
|
2
|
+
|
|
3
|
+
digpdf converts a PDF to HTML for LLM agents and ingestion pipelines. It can also render a page, or a part of a
|
|
4
|
+
page, to PNG, so an agent can look at what the text does not carry.
|
|
5
|
+
|
|
6
|
+
It reads the text layer of the PDF with [PDFium](https://pdfium.googlesource.com/pdfium/), the PDF engine in Chrome.
|
|
7
|
+
It runs no machine learning model and no OCR, and it needs no GPU. The same file gives the same HTML on every run.
|
|
8
|
+
Measured over 2,650 PDFs on a three-core server, the median page took 0.1 second.
|
|
9
|
+
|
|
10
|
+
digpdf works out reading order and tables from where the text stands on the page, the order it is stored in the
|
|
11
|
+
file, and drawn lines and fills. It gets some pages wrong. Try it on your own documents.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
pip install digpdf
|
|
16
|
+
|
|
17
|
+
This needs Python 3.8 or newer. It installs the `digpdf` command and the Python package. `uv tool install digpdf` and
|
|
18
|
+
`pipx install digpdf` work as well.
|
|
19
|
+
|
|
20
|
+
Without Python, download the archive for Linux, macOS or Windows from the
|
|
21
|
+
[releases page](https://github.com/digpdf/digpdf/releases). Unpack it and run `./digpdf` in its folder, or
|
|
22
|
+
`.\digpdf.exe` on Windows. Keep the PDFium library next to the program.
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
Convert a PDF to HTML.
|
|
27
|
+
|
|
28
|
+
digpdf report.pdf > report.html
|
|
29
|
+
|
|
30
|
+
Render page 3 to PNG. Pages count from 1.
|
|
31
|
+
|
|
32
|
+
digpdf report.pdf 3 > page-3.png
|
|
33
|
+
|
|
34
|
+
Render a part of page 3. The four numbers are a `data-bbox` copied from the HTML.
|
|
35
|
+
|
|
36
|
+
digpdf report.pdf 3 120,40,880,300 > crop.png
|
|
37
|
+
|
|
38
|
+
In Python, `html()` returns a string and `image()` returns PNG bytes.
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
import digpdf
|
|
42
|
+
|
|
43
|
+
html = digpdf.html("report.pdf")
|
|
44
|
+
png = digpdf.image("report.pdf", 3)
|
|
45
|
+
crop = digpdf.image("report.pdf", 3, "120,40,880,300")
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
There are no options. The PNG has two pixels per PDF point, up to 2,000 pixels on the long side.
|
|
49
|
+
|
|
50
|
+
If a file cannot be read, nothing is written to stdout, one line on stderr says why, and the exit code is 1. In
|
|
51
|
+
Python, `digpdf.Unreadable` is raised.
|
|
52
|
+
|
|
53
|
+
The HTML looks like this. It is part of a page with a title, a table and a paragraph.
|
|
54
|
+
|
|
55
|
+
```html
|
|
56
|
+
<div data-page="1">
|
|
57
|
+
<div data-bbox="122,51,268,63" class="s1">Staff in numbers</div>
|
|
58
|
+
<div data-bbox="121,134,717,210" class="s1"><table>
|
|
59
|
+
<tr><td>Satisfaction</td><td>2021</td><td>2022</td></tr>
|
|
60
|
+
<tr><td>Very satisfied</td><td>41</td><td>44</td></tr>
|
|
61
|
+
<tr><td>Satisfied</td><td>38</td><td>37</td></tr>
|
|
62
|
+
<tr><td>Not satisfied</td><td>21</td><td>19</td></tr>
|
|
63
|
+
</table></div>
|
|
64
|
+
<div data-bbox="121,467,527,481" class="s1">A paragraph after the tables, to end the page.</div>
|
|
65
|
+
</div>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Design goals
|
|
69
|
+
|
|
70
|
+
A PDF page has two dimensions and text has one, so every conversion loses something. The goal is to lose as little
|
|
71
|
+
as possible of what an agent or a search index needs. Reading order has the highest priority, then tables, then the
|
|
72
|
+
breaks between blocks.
|
|
73
|
+
|
|
74
|
+
The rendered page is the reference. Where the HTML and the page disagree, the HTML is wrong.
|
|
75
|
+
|
|
76
|
+
A reading error that looks plausible is hard to catch later. The aim is therefore to show where digpdf could not
|
|
77
|
+
read something, instead of writing a best guess. Such a place is marked in the HTML, and the agent can ask for its
|
|
78
|
+
image.
|
|
79
|
+
|
|
80
|
+
Where it is unclear whether two things belong together, the aim is to keep them apart. A table cell that was split
|
|
81
|
+
in two can usually be put together again by the reader. Two cells that were merged are much harder to take apart.
|
|
82
|
+
|
|
83
|
+
digpdf does not label content. There are no heading or caption elements. A title is a block like any other, and its
|
|
84
|
+
class shows that it is large and bold.
|
|
85
|
+
|
|
86
|
+
## Why HTML and not Markdown
|
|
87
|
+
|
|
88
|
+
HTML takes more tokens than Markdown, but it can hold things that plain Markdown cannot.
|
|
89
|
+
|
|
90
|
+
- Table cells that span several columns or rows, and line breaks inside a cell.
|
|
91
|
+
- The page and the box of every block, which an agent needs to ask for the image of a block.
|
|
92
|
+
- The marks on places that need vision and on hidden text.
|
|
93
|
+
- The font, size and colour of the text.
|
|
94
|
+
|
|
95
|
+
If you need Markdown, run the HTML through an HTML to Markdown converter. Most converters drop the boxes and the
|
|
96
|
+
marks.
|
|
97
|
+
|
|
98
|
+
## How it differs from other parsers
|
|
99
|
+
|
|
100
|
+
If your PDFs are scans without a text layer, use a parser with OCR. digpdf only shows where the images are.
|
|
101
|
+
|
|
102
|
+
Some parsers run layout or vision models and label headings, captions and figures. digpdf runs no model and adds
|
|
103
|
+
no labels. It reads the text that is in the file and gives you the image for the rest.
|
|
104
|
+
|
|
105
|
+
Other tools that read the text layer also give coordinates and render pages. What digpdf adds is having it all in
|
|
106
|
+
one document. Every block has its box, places that need vision are marked, hidden text is separated from visible
|
|
107
|
+
text, and the image command takes the boxes as they are written.
|
|
108
|
+
|
|
109
|
+
## The HTML in detail
|
|
110
|
+
|
|
111
|
+
Every page is a `<div data-page="n">` with the blocks of the page inside it in reading order. A block is a
|
|
112
|
+
paragraph, a table, a list, a code block, a figure or a single line such as a title.
|
|
113
|
+
|
|
114
|
+
A block is a `<div>` with a `data-bbox`, the box around it. The box is four whole numbers, `x0,y0,x1,y1`, on a grid
|
|
115
|
+
from 0 to 1000 across the width and the height of the page as it is displayed, with 0,0 in the top left corner.
|
|
116
|
+
|
|
117
|
+
The class of a text block is the font, size and colour that most of its text has. The classes are defined in one
|
|
118
|
+
`<style>` at the top of the document. A paragraph keeps the line breaks it has in the PDF.
|
|
119
|
+
|
|
120
|
+
Where digpdf recognises these, it writes them with HTML's own elements.
|
|
121
|
+
|
|
122
|
+
| In the PDF | In the HTML |
|
|
123
|
+
|---|---|
|
|
124
|
+
| Table | `<table>`, with `colspan` and `rowspan` for merged cells |
|
|
125
|
+
| List | `<ul>` or `<ol>` |
|
|
126
|
+
| Text on a monospace grid | `<pre>` |
|
|
127
|
+
| Bold, italic, underline, strike-through | `<b>`, `<i>`, `<u>`, `<s>` |
|
|
128
|
+
| Link | `<a href>` |
|
|
129
|
+
|
|
130
|
+
A link to `javascript:`, `vbscript:` or `data:` has its target in `data-href` and no `href`, so nothing runs if the
|
|
131
|
+
HTML is opened in a browser.
|
|
132
|
+
|
|
133
|
+
An image is an `<img data-bbox>` at its place in the reading order. It has no `src`. It says where on the page an
|
|
134
|
+
image is, and the image command gives you the pixels. A scanned page without a text layer has images and no text.
|
|
135
|
+
|
|
136
|
+
A place that has to be read from the image has the attribute `data-visual`. digpdf sets it on a figure, a formula, a
|
|
137
|
+
chart, text with a broken encoding, and a page it failed to read. The attribute is on a `<div>`, on a `<span>`
|
|
138
|
+
inside a paragraph, or on a `<tbody>` inside a table. The words of the text layer are still inside the element, but
|
|
139
|
+
they do not say what the page shows. Give the element's `data-bbox` and the page number to the image command, and
|
|
140
|
+
read the PNG with a vision model or OCR. Content without the mark can still be read wrong.
|
|
141
|
+
|
|
142
|
+
Text that is in the file but cannot be seen on the page is not written as text. It is an empty element with the
|
|
143
|
+
`hidden` attribute and the text in `data-text`. `data-hidden` says how it is hidden (`offpage`, `clipped`,
|
|
144
|
+
`covered`, `invisible`, `samecolour`, `tiny`). An OCR layer over a scanned page is read as ordinary text.
|
|
145
|
+
|
|
146
|
+
There are no `<sup>` and `<sub>` elements. Text that is raised or lowered in the PDF is set apart from the word with
|
|
147
|
+
a space, so 10 to the power of 20 is written `10 20` and not `1020`.
|
|
148
|
+
|
|
149
|
+
## Limitations
|
|
150
|
+
|
|
151
|
+
- No OCR. A scanned page comes out as images, and reading them is up to you.
|
|
152
|
+
- A PDF that needs a password to open cannot be read.
|
|
153
|
+
- digpdf does not repair a damaged file itself. PDFium may repair one while opening it. digpdf then reads what
|
|
154
|
+
PDFium recovered, which may be incomplete, and a line on stderr says that the file is damaged. If PDFium cannot
|
|
155
|
+
open the file, it cannot be read.
|
|
156
|
+
- If a single page fails, the other pages are still written. The failed page is one `data-visual` block, and a line
|
|
157
|
+
on stderr says so.
|
|
158
|
+
- digpdf sets no limit on the time or the memory a file may take. For files you do not trust, set a timeout and a
|
|
159
|
+
memory limit yourself, for example on a container.
|
|
160
|
+
|
|
161
|
+
## Platform notes
|
|
162
|
+
|
|
163
|
+
- On Windows, the built-in Windows PowerShell 5.1 changes what a program writes when it is redirected with `>`. The
|
|
164
|
+
characters of the HTML are changed and the PNG is ruined. The same goes for PowerShell before 7.4 on any system.
|
|
165
|
+
Use `cmd`, PowerShell 7.4 or newer, or the Python package.
|
|
166
|
+
- The standalone archives are not signed. On Windows, running the program from a downloaded archive may show
|
|
167
|
+
"Windows protected your PC" (choose More info, then Run anyway). On macOS the program may be blocked until the
|
|
168
|
+
quarantine mark is removed with `xattr -dr com.apple.quarantine FOLDER`. Installing with pip, uv or pipx avoids
|
|
169
|
+
both.
|
|
170
|
+
|
|
171
|
+
## Problems
|
|
172
|
+
|
|
173
|
+
Report a file that reads wrong, or a system digpdf does not run on, at https://github.com/digpdf/digpdf/issues
|
|
174
|
+
|
|
175
|
+
## Licence
|
|
176
|
+
|
|
177
|
+
digpdf is free to use, also commercially. It is not open source. See LICENSE. It includes PDFium and other
|
|
178
|
+
third-party software under their own licences, listed in THIRD-PARTY-NOTICES.txt.
|