From c4f7251860dec7240e25a345fdda466f0ae3003f Mon Sep 17 00:00:00 2001 From: Local Dev Date: Tue, 22 Sep 2026 22:06:54 +0200 Subject: [PATCH] feat(pdf-editor): convert a PDF to Word, and say what that costs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A PDF does not contain paragraphs. It contains glyphs with coordinates, and there is no heading, no list, no table and no guaranteed reading order — only runs of characters that happen to sit near each other. Converting to Word means working out where the paragraphs were, from geometry. That inference is the whole feature, and it is sometimes wrong, so this is called a conversion and never an edit, and the dialog reports what it found before anything is written. Lines are grouped by baseline, runs joined with the spaces a PDF only implies by leaving a gap, and paragraphs ended where the next line sits unusually far below, is indented, or where the previous one stopped short of the measure. Headings come from size relative to the body — which is the most common size on the page, not the average, because a page of 11 pt under a 28 pt title averages to something that is neither. Bold and italic come from the font's name, the only place a PDF records them. What it refuses to fake is as important. A page set in columns is reported, not silently interleaved. A page with no text says so, and says why: it is an image of writing, and reading that needs character recognition this editor does not have. Tables become plain paragraphs rather than an invented grid, because a wrong table is harder to repair than no table. The .docx is written here rather than by a vendored builder: a Word file is a zip of five XML parts, and the subset that can honestly be produced — paragraphs of styled runs — is about two hundred lines. Vendoring a document library would have added another megabyte on top of the four pdf.js and pdf-lib already weigh, to generate markup we would still have to get right. Entries are stored rather than deflated, which keeps a compressor out of the add-on; the CRCs are the part that cannot be skipped, since Word calls the file corrupt rather than naming the part that upset it. Text replaced in place converts as replaced. Converting would otherwise hand back the words the user had just edited away. Checked by taking the output apart — every CRC verified, both XML parts run through a real parser — and then, because that is still marking my own homework, by opening the result in the Word editor extension, where mammoth reads it with none of my code involved. --- bundled-addons/pdf-editor/addon.json | 2 +- bundled-addons/pdf-editor/editor.html | 20 ++ bundled-addons/pdf-editor/editor.js | 137 ++++++++++++ bundled-addons/pdf-editor/lib/docx.js | 189 ++++++++++++++++ bundled-addons/pdf-editor/lib/reflow.js | 277 ++++++++++++++++++++++++ 5 files changed, 624 insertions(+), 1 deletion(-) create mode 100644 bundled-addons/pdf-editor/lib/docx.js create mode 100644 bundled-addons/pdf-editor/lib/reflow.js diff --git a/bundled-addons/pdf-editor/addon.json b/bundled-addons/pdf-editor/addon.json index f75a66b..66a3845 100644 --- a/bundled-addons/pdf-editor/addon.json +++ b/bundled-addons/pdf-editor/addon.json @@ -1,7 +1,7 @@ { "id": "pdf-editor", "name": "PDF Editor", - "version": "0.2.0", + "version": "0.3.0", "description": "Open a PDF in a full tab: read it, mark it up with highlight, underline, strike-through, pen, shapes, arrows, text and a drawn signature, then move, resize, restyle or delete anything you placed. Reorder, rotate or drop pages, fill in form fields, redact for real, and save a new copy. Marks are written into the saved file as real PDF content. The original is never touched.", "author": "Silent Mode", "icon": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTYgMmg4bDYgNnYxMmEyIDIgMCAwIDEtMiAySDZhMiAyIDAgMCAxLTItMlY0YTIgMiAwIDAgMSAyLTJ6IiBmaWxsPSIjZGMyNjI2Ii8+PHBhdGggZD0iTTE0IDJ2Nmg2eiIgZmlsbD0iIzk5MWIxYiIvPjx0ZXh0IHg9IjEyIiB5PSIxNyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1mYW1pbHk9InN5c3RlbS11aSwtYXBwbGUtc3lzdGVtLHNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iNS41IiBmb250LXdlaWdodD0iODAwIiBmaWxsPSIjZmZmIj5QREY8L3RleHQ+PC9zdmc+", diff --git a/bundled-addons/pdf-editor/editor.html b/bundled-addons/pdf-editor/editor.html index c0d5074..3ca06fc 100644 --- a/bundled-addons/pdf-editor/editor.html +++ b/bundled-addons/pdf-editor/editor.html @@ -18,6 +18,10 @@ No document + + + + +