Markdown Export Configuration#
Docling's markdown export pipeline converts a parsed DoclingDocument to a Markdown string. The main entry points are DoclingDocument.export_to_markdown() and DoclingDocument.save_as_markdown(). Both delegate to MarkdownDocSerializer, which orchestrates format-specific sub-serializers for text, tables, pictures, lists, and code blocks.
All configuration is captured in MarkdownParams, a Pydantic model that extends CommonParams. MarkdownParams is constructed from the keyword arguments of export_to_markdown() and threaded through the serializer hierarchy.
MarkdownParams Reference#
MarkdownParams defines all tunable fields for the serializer. Key fields:
| Parameter | Default | Description |
|---|---|---|
layers | {ContentLayer.BODY} | Content layers to include |
image_mode | ImageRefMode.PLACEHOLDER | Image rendering: PLACEHOLDER, EMBEDDED (base64), or REFERENCED (file path) |
image_placeholder | "<!-- image -->" | String emitted when image_mode=PLACEHOLDER |
page_break_placeholder | None | If set, replaces internal page-break markers with this string (e.g. "<!-- page break -->") |
pages (from CommonParams) | None | Set of page numbers to include; None = all pages |
escape_underscores | True | Escape _ outside of URLs |
escape_html | True | HTML-escape text content |
compact_tables | False | Omit column padding in tables (better for large tables / downstream parsing) |
format_code_blocks | True | Wrap code items in fenced code blocks |
enable_chart_tables | True | Render tabular chart data as Markdown tables |
wrap_width | None | Wrap text at this column width |
indent | 4 | Spaces per list-nesting level |
mark_meta | False | Prefix meta section output with field names |
The pages field comes from the parent CommonParams class and gates serialization: any item whose provenance page number is not in the set is added to the excluded-refs list by get_excluded_refs().
Page Breaks#
When page_break_placeholder is set to any non-None string, requires_page_break() returns True. During document iteration, the base DocSerializer.get_parts() calls _iterate_items() with add_page_breaks=True, which inserts _PageBreakNode objects at page transitions . These produce internal tokens matching the pattern #_#_DOCLING_DOC_PAGE_BREAK_{prev}_{next}_#_#.
In MarkdownDocSerializer.serialize_doc(), after concatenating all parts, every internal token is replaced with the caller-supplied page_break_placeholder string (or "" if the field is set but empty). Setting page_break_placeholder=None (the default) suppresses the entire mechanism — no tokens are generated and no replacements are made.
Summary of values:
page_break_placeholder value | Behaviour |
|---|---|
None (default) | No page-break markers inserted |
"" | Markers silently removed (useful for clean text) |
"<!-- page break -->" | HTML comment inserted between pages |
| Any other string | That string inserted between pages |
Page Filtering#
Single-page export is exposed via the page_no parameter on export_to_markdown() and save_as_markdown(). Internally, page_no is converted to a one-element set and passed as MarkdownParams.pages .
For multi-page subsets, construct a MarkdownDocSerializer directly and pass pages={1, 3, 5} inside MarkdownParams.
Element-level filtering (first/last item index) is handled by start_idx / stop_idx in CommonParams, which correspond to the from_element / to_element arguments of export_to_markdown() .
Usage in docling-serve and docling-jobkit#
In docling-serve, markdown export is configured through ConvertDocumentsOptions. The markdown-specific field is:
| Field | Default | Description |
|---|---|---|
md_page_break_placeholder | "" | Inserted between pages in markdown output |
The empty-string default means no break is shown unless the caller sets a non-empty value. Downstream, the value is coerced with or None before being forwarded to export_to_markdown(), which aligns with the None-means-disabled semantics of MarkdownParams.page_break_placeholder.
docling-serve does not call export_to_markdown() directly. Conversion tasks are delegated to workers via the orchestrator (Ray / RQ / Local). The actual export is performed by docling-jobkit:
results.py→_export_document_as_content()callsexport_to_markdown(image_mode=…, page_break_placeholder=md_page_break_placeholder or None)for in-memory results.export.py→_materialize_document_exports()callssave_as_markdown(…, page_break_placeholder=md_page_break_placeholder or None)when writing files.
The page_range field in ConvertDocumentsOptions controls which pages are processed during conversion (a pipeline-level filter), not which pages appear in the markdown output. To filter at serialization time, use page_no / MarkdownParams.pages.
Key Source References#
| File | Purpose |
|---|---|
docling_core/transforms/serializer/markdown.py | MarkdownParams, MarkdownDocSerializer, all element serializers |
docling_core/transforms/serializer/common.py | CommonParams (incl. pages), DocSerializer, _get_page_breaks(), page-break iteration |
docling_core/types/doc/document.py | export_to_markdown() and save_as_markdown() method signatures |
docling/datamodel/service/options.py | ConvertDocumentsOptions.md_page_break_placeholder for docling-serve |
docling_jobkit/convert/export.py | File-based markdown export in docling-jobkit |