pdf-single-to-two-column
Reconstruct one-column PDF files as searchable two-column PDFs, with Docling Markdown (referenced picture assets) followed by Pandoc and XeLaTeX as the default PDF-only workflow. Use for permanent lay
Files7
View on GitHubSKILL.mdskills/pdf-single-to-two-column/SKILL.md
GitHubPDF Single To Two Column
Goal and boundary
Create a new, searchable two-column PDF. Do not call reader Reflow, zoom, booklet printing, 2-up, or page slicing a reconstruction. Never overwrite the source. Work in a new run directory, keep the intermediate Markdown and picture assets, append _2col to the PDF name, and write manifest.json.
The default PDF-only backend is:
Docling PDF parse (OCR off, table-structure off, picture images on)
-> referenced Markdown + assets/
-> Pandoc Markdown-to-LaTeX
-> XeLaTeX classoption=twocolumn
-> pdftotext/layout + pdftoppm visual QA
This is a reconstruction, not a guarantee of the source's original pagination. Figures are preserved as extracted images when Docling can identify them, but figure order, captions, formulas, title/author blocks, and page breaks remain review items.
Backend policy
- If an authoritative DOCX, LaTeX, or publishing source exists and must remain paper-grade, change its column setting at the source and export again.
- For PDF-only input, use
scripts/docling_latex_backend.pyas the default and pin the tested Docling environment. Do not silently switch to Word,pdf2docx, or a text-only conversion after a Docling failure. - Use Word COM only for an actual editable DOCX. Headless Word PDF import is an explicit diagnostic experiment, not a default backend.
- Treat
pdftotext -> Pandoc -> Wordas a lossy diagnostic baseline. It is not acceptable for a paper batch because it can scramble reading order, formulas, author blocks, and figures. - Scanned PDFs need an explicit OCR contract. The default Docling pipeline sets
do_ocr=False; do not claim scanned-PDF support without recording OCR language, engine, confidence, and manual-review pages.
Prerequisites and version contract
The validated pilot used:
- Python 3.11.15 in an isolated environment;
- Docling 2.114.0;
- Pandoc 1.19.2.1;
- XeLaTeX from TeX Live 2025;
- Poppler
pdfinfo,pdftotext, andpdftoppm.
Check the environment before conversion:
$skill = "C:\Users\Administrator\.codex\skills\pdf-single-to-two-column"
$py = "D:\path\to\.venvs\docling-two-column\Scripts\python.exe"
& $py "$skill\scripts\docling_latex_backend.py" doctor
If the doctor reports a missing dependency, install it in an isolated environment and record the actual versions. Do not silently upgrade Docling for a production batch; rerun the pilot after any version change.
Standard workflow
1. Freeze a pilot
- Record the absolute source path, SHA-256, page count, page size, text extractability, and whether the source is born-digital or scanned.
- Copy 3-5 representative pages into a separate pilot input: title/author, dense body, formula/table, figure/caption, and footnote pages. Do not modify the original.
- Use the same pilot input for every backend comparison.
2. Run Docling reconstruction
Run one file into a fresh directory. The script writes Markdown, assets/, pandoc.log, a layout text dump, rendered PNGs, the PDF, and manifest.json.
$skill = "C:\Users\Administrator\.codex\skills\pdf-single-to-two-column"
$py = "D:\path\to\.venvs\docling-two-column\Scripts\python.exe"
$input = "D:\papers\pilot\sample-pages.pdf"
$run = "D:\papers\runs\sample-docling-2col"
& $py "$skill\scripts\docling_latex_backend.py" convert `
--input $input `
--output-dir $run `
--render-pages 1,2,3 `
--cjk-font "Microsoft YaHei"
if ($LASTEXITCODE -ne 0) { throw "Docling reconstruction failed; inspect $run\manifest.json and pandoc.log" }
Keep --render-pages targeted to representative pages. Use --no-render only for a deliberate text-only diagnostic run. Use --overwrite only when the run directory is disposable and the replacement is explicit.
3. Apply the quality gate
Do not batch until all of these are true for the pilot:
manifest.jsonisstatus: ok, records input/output hashes, actual versions, the Pandoc command, rendered pages, andreview_gate: pending_manual_visual_review.pdfinfoconfirms a non-empty PDF, expected page size, and a plausible page count.pdftotext -layoutshows title, authors, abstract, section order, and page numbers in left-column top-to-bottom then right-column order.- Rendered PNGs show no clipped text, overlap, black blocks, missing images, font substitution, incoherent blank regions, or cross-column mixing.
- Figures and captions are in a defensible order; formulas, tables, footnotes, and symbols are readable; text remains selectable.
- Compare the reconstructed pilot against the source page by page. A PDF being openable, searchable, or two columns wide is not sufficient.
Record a human decision beside the manifest as pilot_passed, pilot_rejected, or needs_review. Keep rejected outputs for diagnosis; do not feed them into the batch.
4. Batch only after approval
Use a new output directory and one manifest per input. Stop on the first failure or unexpected version. Example:
$skill = "C:\Users\Administrator\.codex\skills\pdf-single-to-two-column"
$py = "D:\path\to\.venvs\docling-two-column\Scripts\python.exe"
$inputDir = "D:\papers\incoming"
$outputRoot = "D:\papers\runs\two-column"
Get-ChildItem $inputDir -Filter *.pdf | Sort-Object Name | ForEach-Object {
$run = Join-Path $outputRoot $_.BaseName
& $py "$skill\scripts\docling_latex_backend.py" convert `
--input $_.FullName `
--output-dir $run `
--render-pages 1
if ($LASTEXITCODE -ne 0) { throw "Batch stopped at $($_.FullName)" }
}
Review a sample of full-batch manifests and rendered pages again. Do not overwrite or replace the source directory.
Failure handling
- If Docling cannot parse the PDF, preserve its manifest/log and report the exact version and error. Do not silently fall back to text-only Pandoc.
- If
assets/is empty for a document that visibly contains figures, mark the pilot as failed and inspect Docling's picture extraction before batching. - If title/author blocks, formulas, figure order, captions, or reading order are damaged, mark
pilot_rejectedorneeds_review; do not describe the output as publication-ready. - If Pandoc/XeLaTeX fails, inspect
pandoc.log, the selected CJK font, and the Markdown/image paths. Keep the Markdown as the debugging artifact. - If page count changes substantially or a right column is blank, treat it as a layout decision requiring review, not automatic success.
- If input is a BabelDOC-generated PDF, Docling may still parse it, but do not use it as evidence that the BabelDOC IL backend can process its own output. Keep backend experiments separate.
- For Word/MCP questions, consult
references/backends.md. An Office MCP connection does not imply a PDF reconstruction tool.
Bundled resources
scripts/docling_latex_backend.py: deterministic single-file Docling -> Markdown/assets -> Pandoc/XeLaTeX conversion, manifest, text dump, and rendering.scripts/doctor.py: environment inventory; reportsdocling-markdown-xelatexas the recommended backend when ready.references/backends.md: tested backend comparison and evidence limits.