docling-project / docling-project/docling-core

`HierarchicalChunker` records `''` in `meta.headings` for a heading whose text is in an `InlineGroup`, and emits that heading's text as a body chunk

Open
#769 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
HTML
Stars
282
Forks
214
Avg merge
2d 15h
Merged PRs (30d)
21

Description

The Markdown backend represents a heading of any level with more than one inline run as a `SectionHeaderItem` with `text=""` and one `InlineGroup` child holding the runs. A `#` heading gives a `TitleItem` of the same shape. `## [0.68.0] - 2026-07-24` is one such heading. A heading that is a single link or a single emphasis span keeps its text on the item. Measured on docling 2.124.0.

`MarkdownDocSerializer` handles the shape. `export_to_markdown()` renders `## [Release](https://example.com/releases) notes`. `HierarchicalChunker` does not:

- It stores the heading item in `heading_by_level` and builds `meta.headings` from `item.text`. The heading contributes `''`. A `TitleItem` of this shape gives `['']`.
- The loop `continue`s on a heading without marking its children visited. The `InlineGroup` then arrives as an item of its own and is serialized as content. The result is a chunk whose text is the heading.

`HybridChunker` starts from these chunks and inherits both, and adds a re-serialization defect of its own, #770. Every chunk under such a heading carries an empty string where its heading should be, and the heading text lands in the body of the first chunk. The same document shape appears in #740 for the LaTeX serializer, fixed by #743 in 2.95.0, and in #750 for the DocLang serializer.

Reproduced on docling-core 2.96.0. The loop is unchanged on `main`, in `hierarchical_chunker.py`, `HierarchicalChunker.chunk`.

## Reproduction

```python
from docling_core.types.doc.document import DoclingDocument
from docling_core.types.doc.labels import DocItemLabel
from docling_core.transforms.chunker.hierarchical_chunker import HierarchicalChunker

doc = DoclingDocument(name="t")
doc.add_title(text="Sample")
heading = doc.add_heading(text="", level=1)
group = doc.add_inline_group(parent=heading)
doc.add_text(label=DocItemLabel.TEXT, text="Release", parent=group, hyperlink="https://example.com/releases")
doc.add_text(label=DocItemLabel.TEXT, text="notes", parent=group)
para = doc.add_inline_group()
doc.add_text(label=DocItemLabel.TEXT, text="Install with", parent=para)
doc.add_code(text="pip install x", parent=para)
doc.add_text(label=DocItemLabel.TEXT, text="first.", parent=para)

print(doc.export_to_markdown())
for c in HierarchicalChunker().chunk(doc):
print(c.meta.headings, repr(c.text))
```

Output on 2.96.0:

```
# Sample

## [Release](https://example.com/releases) notes

Install with `pip install x` first.

['Sample', ''] '[Release](https://example.com/releases) notes'
['Sample', ''] 'Install with `pip install x` first.'
```

A real changelog converted with docling 2.124.0 and chunked gives `headings=['Changelog', '', 'Added']` on every chunk, plus one extra chunk per release heading whose text is the heading itself.

## Expected

```
['Sample', 'Release notes'] 'Install with `pip install x` first.'
```

`meta.headings` should carry the heading's plain text, as it does for a heading whose text sits on the item. How formatting and hyperlinks inside a heading render is the serializer's concern and does not belong in the metadata. No chunk should have the heading's runs as its content.

Contributor guide

Open the contributing guide

Research direction

Start with hierarchical_chunker.py and the HierarchicalChunker.chunk method, then run the reproduction from the issue against the current implementation. Check how heading_by_level, item.text, and InlineGroup traversal affect meta.headings and chunk content; done means formatted heading runs are absent from body chunks and metadata contains their plain text, matching the expected output.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
data
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
84/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.