diff --git a/src/parse_bench/inference/pipelines/parse.py b/src/parse_bench/inference/pipelines/parse.py index 1599bc8..19c70a2 100644 --- a/src/parse_bench/inference/pipelines/parse.py +++ b/src/parse_bench/inference/pipelines/parse.py @@ -526,6 +526,15 @@ def register_parse_pipelines(register_fn) -> None: # type: ignore[no-untyped-de ) ) + register_fn( + PipelineSpec( + pipeline_name="pymupdf4llm_html_tables", + provider_name="pymupdf4llm", + product_type=ProductType.PARSE, + config={"table_output": "html"}, + ) + ) + register_fn( PipelineSpec( pipeline_name="markitdown", diff --git a/src/parse_bench/inference/providers/parse/pymupdf4llm.py b/src/parse_bench/inference/providers/parse/pymupdf4llm.py index 70cd85b..a24710c 100644 --- a/src/parse_bench/inference/providers/parse/pymupdf4llm.py +++ b/src/parse_bench/inference/providers/parse/pymupdf4llm.py @@ -89,6 +89,19 @@ def _markdown_options(self, pymupdf: Any) -> dict[str, Any]: raise ProviderConfigError("PyMuPDF4LLM 'ocr_language' must be a non-empty string") options["ocr_language"] = ocr_language + table_output = self.base_config.get("table_output") + if table_output is not None: + if not isinstance(table_output, str): + raise ProviderConfigError("PyMuPDF4LLM 'table_output' must be a string") + normalized_table_output = table_output.strip().lower() + if normalized_table_output not in ("markdown", "html"): + raise ProviderConfigError("PyMuPDF4LLM 'table_output' must be 'markdown' or 'html'") + # Opt-in HTML table rendering. pymupdf4llm builds that ship the native + # HTML table engine emit structured markup for table_output="html"; + # builds without it ignore the extra keyword, so the default markdown + # pipelines above are unaffected. + options["table_output"] = normalized_table_output + raw_backend = self.base_config.get("ocr_backend") if raw_backend is None: return options diff --git a/tests/parse_bench/inference/providers/parse/test_pymupdf4llm.py b/tests/parse_bench/inference/providers/parse/test_pymupdf4llm.py index 2973c91..6d176b2 100644 --- a/tests/parse_bench/inference/providers/parse/test_pymupdf4llm.py +++ b/tests/parse_bench/inference/providers/parse/test_pymupdf4llm.py @@ -1,5 +1,8 @@ """Tests for PyMuPDF4LLM layout normalization helpers.""" +import pytest + +from parse_bench.inference.providers.base import ProviderConfigError from parse_bench.inference.providers.parse.pymupdf4llm import ( _PYMUPDF_CLASS_TO_CANONICAL, PyMuPDF4LLMProvider, @@ -29,3 +32,21 @@ def test_build_layout_page_maps_all_pymupdf_classes() -> None: assert page is not None assert [item.layout_segments[0].label for item in page.items] == list(_PYMUPDF_CLASS_TO_CANONICAL.values()) + + +def test_markdown_options_threads_table_output() -> None: + provider = PyMuPDF4LLMProvider("pymupdf4llm", {"table_output": "html"}) + options = provider._markdown_options(None) + assert options["table_output"] == "html" + + +def test_markdown_options_omits_table_output_by_default() -> None: + provider = PyMuPDF4LLMProvider("pymupdf4llm", {}) + options = provider._markdown_options(None) + assert "table_output" not in options + + +def test_markdown_options_rejects_unknown_table_output() -> None: + provider = PyMuPDF4LLMProvider("pymupdf4llm", {"table_output": "xml"}) + with pytest.raises(ProviderConfigError): + provider._markdown_options(None)