Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,38 @@ Path("output.md").write_bytes(md.encode())
| **Plain text** | `to_text(path)` | Search indexing, simple NLP tasks |
| **LlamaIndex docs** | `LlamaMarkdownReader().load_data(path)` | Direct LlamaIndex integration |

### HTML table output

By default, tables are rendered as GitHub-compatible Markdown. To emit
reconstructed HTML `<table>` elements instead, use `table_output="html"`:

```python
import pymupdf4llm

md = pymupdf4llm.to_markdown("document.pdf", table_output="html")
```

In layout mode this keeps the layout pipeline for reading order, body text, and
OCR handling, and swaps only table rendering to the HTML table engine. The
standalone table API is also available:

```python
from pymupdf4llm.helpers.table_html import to_html

html = to_html("document.pdf", page_index=0)
```

### Layout edge threshold

Layout mode accepts `edge_threshold`, passed through to `page.get_layout()`
to adjust the layout model's grouping confidence:

```python
md = pymupdf4llm.to_markdown("document.pdf", edge_threshold=0.75)
```

The default remains the library default unless this option is provided.

### Extraction capabilities

| Feature | Description |
Expand Down Expand Up @@ -532,4 +564,3 @@ If you find this useful, please consider giving it a star — it helps others di
[![Star on GitHub](https://img.shields.io/github/stars/pymupdf/pymupdf4llm.svg?style=for-the-badge&label=Star&logo=github)](https://github.com/pymupdf/pymupdf4llm/)



45 changes: 45 additions & 0 deletions src/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ def _layout_to_markdown(
show_progress=False,
use_ocr=True,
write_images=False,
render_html_tables=None,
edge_threshold=None,
# unsupported options for pymupdf layout:
**kwargs,
):
Expand All @@ -101,6 +103,8 @@ def _layout_to_markdown(
force_ocr=force_ocr,
ocr_language=ocr_language,
ocr_function=ocr_function,
render_html_tables=render_html_tables,
edge_threshold=edge_threshold,
)
return parsed_doc.to_markdown(
header=header,
Expand Down Expand Up @@ -129,6 +133,8 @@ def _layout_to_json(
force_ocr=False,
ocr_language="eng",
ocr_function=None,
render_html_tables=None,
edge_threshold=None,
# unsupported options for pymupdf layout:
**kwargs,
):
Expand All @@ -146,6 +152,8 @@ def _layout_to_json(
force_ocr=force_ocr,
ocr_language=ocr_language,
ocr_function=ocr_function,
render_html_tables=render_html_tables,
edge_threshold=edge_threshold,
)
return parsed_doc.to_json()

Expand All @@ -168,6 +176,7 @@ def _layout_to_text(
table_max_width=100,
table_min_col_width=10,
page_chunks=False,
edge_threshold=None,
# unsupported options for pymupdf layout:
**kwargs,
):
Expand All @@ -183,6 +192,7 @@ def _layout_to_text(
force_ocr=force_ocr,
ocr_language=ocr_language,
ocr_function=ocr_function,
edge_threshold=edge_threshold,
)
return parsed_doc.to_text(
header=header,
Expand All @@ -197,13 +207,48 @@ def _layout_to_text(


def to_markdown(*args, **kwargs):
# `render_html_tables` is an internal flag this wrapper injects for
# table_output="html"; it is not a public kwarg. Drop any user-supplied value
# so it cannot silently enable/disable HTML tables via **kwargs.
kwargs.pop("render_html_tables", None)
if kwargs.get("table_output") == "html":
# Render tables as HTML via table_html.
kwargs = dict(kwargs)
kwargs.pop("table_output", None)
if _use_layout:
# Preferred path: render HTML tables on the layout path, reusing the
# GNN layout. Keeps the layout path's text, reading order, and OCR --
# only the table rendering is swapped.
return _layout_to_markdown(*args, render_html_tables=True, **kwargs)
# No layout engine available: fall back to the rag path, which has its own
# table_output="html" wiring. OCR is not available on this path.
legacy_kwargs = dict(kwargs)
for name in (
"footer",
"header",
"ocr_dpi",
"ocr_function",
"ocr_language",
"use_ocr",
"force_ocr",
):
legacy_kwargs.pop(name, None)
return pymupdf4llm.helpers.pymupdf_rag.to_markdown(
*args, table_output="html", **legacy_kwargs
)
if _use_layout:
return _layout_to_markdown(*args, **kwargs)
else:
return pymupdf4llm.helpers.pymupdf_rag.to_markdown(*args, **kwargs)


def to_json(*args, **kwargs):
# See to_markdown: `render_html_tables` is internal, not a public kwarg.
kwargs.pop("render_html_tables", None)
if kwargs.get("table_output") == "html":
kwargs = dict(kwargs)
kwargs.pop("table_output", None)
kwargs["render_html_tables"] = True
if _use_layout:
return _layout_to_json(*args, **kwargs)
else:
Expand Down
Loading
Loading