Skip to content

feat(jats/inline-formula): Support emphasis elements and Inline formulas - #3726

Merged
ceberam merged 8 commits into
docling-project:mainfrom
taru-garg-2000:feat/jats-inline-formula-emphasis
Jul 22, 2026
Merged

feat(jats/inline-formula): Support emphasis elements and Inline formulas#3726
ceberam merged 8 commits into
docling-project:mainfrom
taru-garg-2000:feat/jats-inline-formula-emphasis

Conversation

@taru-garg-2000

@taru-garg-2000 taru-garg-2000 commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

#3696 landed inline tex-math rendering for JATS as the first step. This continues that work by handling the styling that can sit alongside the formula inside an <inline-formula>.

When we walk an <inline-formula>, we now break it into ordered inline pieces instead of one flat string: the tex-math becomes the formula, and emphasis around it (italic, bold, underline, strike, sub, sup) is kept as styled text. MathML <mml:math> or other alternatives are skipped — as MathML isn't parsed yet, so we rely on the tex-math sibling instead. The pieces go into an inline group so everything still reads as one continuous line.

A couple of examples:

<p>We use <inline-formula><italic>x</italic> <tex-math>$$a^2$$</tex-math></inline-formula> here.</p>

The x stays italic right next to the a^2 formula.

<p>Index <inline-formula>x<sub>i</sub> <tex-math>$$x_i$$</tex-math></inline-formula> shown.</p>

One thing I noticed with things like Superscript or Subscript, there is a space in between the element which carry that super/sub-script and the actual element in the sub/super-script. To explain, when parsing something like

<p><inline-formula>x<sup>2</sup></inline-formula></p>

We would expect to be rendered as x2 but it actually renders as x 2 (notice the space), it seems this is because how the elements are serialized, but I haven't looked into it that much.

@github-actions

Copy link
Copy Markdown
Contributor

DCO Check Passed

Thanks @taru-garg-2000, all your commits are properly signed off. 🎉

@mergify

mergify Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Merge Protections

🟢 All 2 merge protections satisfied — ready to merge.

Show 2 satisfied protections

🟢 Enforce conventional commit

Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/

  • title ~= ^(fix|feat|docs|style|refactor|perf|test|build|ci|chore|revert)(?:\(.+\))?(!)?:

🟢 Require two reviewer for test updates

When test data is updated, we require two reviewers

  • #approved-reviews-by >= 2

@PeterStaar-IBM
PeterStaar-IBM requested a review from ceberam July 1, 2026 03:47
@codecov

codecov Bot commented Jul 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.74468% with 4 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
docling/backend/xml/jats_backend.py 95.74% 4 Missing ⚠️

📢 Thoughts on this report? Let us know!

@ceberam

ceberam commented Jul 2, 2026

Copy link
Copy Markdown
Member

One thing I noticed with things like Superscript or Subscript, there is a space in between the element which carry that super/sub-script and the actual element in the sub/super-script.

This is correct and it affects all parsers. Just accept it as the normal behavior for now. There is another PR in docling-core that will fix it.

@ceberam ceberam left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @taru-garg-2000 for your PR. Please, see my comments below.
I was also wondering if you could extend the styling of text beyond the inline formulas, since it is still missing. I guess it would be pretty simple to reuse the static methods you created to add the formatting of text.

Comment thread docling/backend/xml/jats_backend.py Outdated
Comment thread docling/backend/xml/jats_backend.py Outdated
Comment thread docling/backend/xml/jats_backend.py Outdated
Comment thread docling/backend/xml/jats_backend.py Outdated
Comment thread tests/test_backend_jats.py Outdated
Comment thread docling/backend/xml/jats_backend.py Outdated
Comment thread tests/test_backend_jats.py
@taru-garg-2000

Copy link
Copy Markdown
Contributor Author

Hi @ceberam , Thanks a lot for the review! Happy to extend it for generalised implementation on formatting tags, I was wondering though if it would be better to keep it as a separate PR ?

@ceberam

ceberam commented Jul 2, 2026

Copy link
Copy Markdown
Member

Hi @ceberam , Thanks a lot for the review! Happy to extend it for generalised implementation on formatting tags, I was wondering though if it would be better to keep it as a separate PR ?

Let's do it in this PR since it will help us better design the formatting in a reusable manner.

@taru-garg-2000 taru-garg-2000 changed the title feat(jats/inline-formula): Support emphasis elements for Inline formulas WIP: feat(jats/inline-formula): Support emphasis elements for Inline formulas Jul 2, 2026
@taru-garg-2000
taru-garg-2000 marked this pull request as draft July 2, 2026 18:26
@taru-garg-2000 taru-garg-2000 changed the title WIP: feat(jats/inline-formula): Support emphasis elements for Inline formulas feat(jats/inline-formula): Support emphasis elements for Inline formulas Jul 2, 2026
@taru-garg-2000
taru-garg-2000 marked this pull request as ready for review July 8, 2026 16:04
@taru-garg-2000

taru-garg-2000 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

Hi @ceberam, There's some polishing still left I feel, however was looking to get an early review if the approach looks good ?

For tex-math items I tested on a bunch of real JATS files, and they seems to have this whole blob around them

\documentclass[12pt]{minimal} \usepackage{wasysym} \usepackage[substack]{amsmath} \usepackage{amsfonts} \usepackage{amssymb} \usepackage{amsbsy} \usepackage[mathscr]{eucal} \usepackage{mathrsfs} \DeclareFontFamily{T1}{linotext}{} \DeclareFontShape{T1}{linotext}{m}{n} { <-> linotext }{} \DeclareSymbolFont{linotext}{T1}{linotext}{m}{n} \DeclareSymbolFontAlphabet{\mathLINOTEXT}{linotext} \begin{document} $$ \frac{dA(t)}{dt}={\gamma}_{i,j,B} \left( { \,\substack{ ^{3} \\ {\sum} \\ _{i=1} }\, }I_{i,F,B}(t)+I_{i,M,B}(t) \right) -{\mu}_{A}A(t)-{\delta}A(t), $$ \end{document}

Which kind of corrupts the render of actual formula

\frac{dA(t)}{dt}={\gamma}_{i,j,B} \left( { \,\substack{ ^{3} \\ {\sum} \\ _{i=1} }\, }I_{i,F,B}(t)+I_{i,M,B}(t) \right) -{\mu}_{A}A(t)-{\delta}A(t)

Although it is latex, we don't really render it correctly when the conversion to markdown happens.

@taru-garg-2000
taru-garg-2000 requested a review from ceberam July 14, 2026 16:04
@taru-garg-2000

taru-garg-2000 commented Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

Polished up the remaining bit, so for the current implementation we check if the text in a tex-math element is surrounded with $$ or $ if so extract the text within them, else just fallback to the text available in the element (this will not work if there is a lot of latex other than the formula like above), happy to find more samples on real documents and test it out against those.

@taru-garg-2000 taru-garg-2000 changed the title feat(jats/inline-formula): Support emphasis elements for Inline formulas feat(jats/inline-formula): Support emphasis elements and Inline formulas Jul 14, 2026
@ceberam

ceberam commented Jul 20, 2026

Copy link
Copy Markdown
Member

@taru-garg-2000 I have added the commit 9d55328 , which replaces my previous JATS example with another one having text-math tags in both <inline-formula> and <disp-formula>.
Hope that helps and let me know if you need any support.

@taru-garg-2000

taru-garg-2000 commented Jul 20, 2026

Copy link
Copy Markdown
Contributor Author

Thanks a lot! I already see some very great results, it seems to be working well actually, previous renderer didn't support inline formulas.

image

Github renderer does a very good job.

and some that can be improved, will fix the ones which didn't go through. Some of the inline ones failing, will go through them, I checked this on a Markdown renderer which supports both LaTex and Markdown.

@ceberam

ceberam commented Jul 20, 2026

Copy link
Copy Markdown
Member

Great! Could you please rebase to main and resolve the conflicts? I will then do a second review.

taru-garg-2000 and others added 7 commits July 21, 2026 19:47
Signed-off-by: Taru Garg <taru.garg@hashicorp.com>
Signed-off-by: Taru Garg <taru.garg@hashicorp.com>
Signed-off-by: Taru Garg <taru.garg@hashicorp.com>
Generalize the inline walker to accumulate styled InlineSegments so bold, italic, underline, strike, sub, and sup formatting is preserved for all paragraph text, not only inside inline formulas. Regenerate JATS groundtruth to include the recovered body emphasis.

Signed-off-by: Taru Garg <taru.garg@hashicorp.com>
Condense the multi-line docstring/comments added for the inline emphasis walker, and remove the markdown-rendering test that duplicated the italic-inside-formula structural case.

Signed-off-by: Taru Garg <taru.garg@hashicorp.com>
Add a PMC article to test the parsing of formulas in JATS documents.
Add third-party attribution notice for JATS test data.

Signed-off-by: Cesar Berrospi Ramis <ceb@zurich.ibm.com>
Signed-off-by: Cesar Berrospi Ramis <ceb@zurich.ibm.com>
@taru-garg-2000
taru-garg-2000 force-pushed the feat/jats-inline-formula-emphasis branch from 9d55328 to 53b0a45 Compare July 21, 2026 14:24

@ceberam ceberam left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @taru-garg-2000 for addressing the previous comments. I went through a detailed review. I can confirm that inline JATS formulas are now emitted as ordered inline pieces, with surrounding emphasis preserved as formatted text and tex-math kept as formula content. The targeted behavior is covered by meaningful tests, and I don't see significant security or performance concerns from these changes.

Must fix

  • InlineSegment is a plain @dataclass, but its fields are annotated with Pydantic-style Field(...). That pattern should be reserved for actual Pydantic models. For a normal dataclass, plain type annotations are the right fit here. For documentation, use dataclass.field instead of pydantic's Field function.

Notes

Signed-off-by: Taru Garg <taru.garg@hashicorp.com>
@taru-garg-2000

Copy link
Copy Markdown
Contributor Author

Hi @ceberam, Thanks a lot for the feedback, since the dataclass itself is quite simple, I felt the best approach would be to have the documentation as a docstring, and annotations as simple type annotations. I tried using the dataclasses.field but that introduced doc only in version 3.14, and the we don't really need a default_factory or a complex default for any of these.

Let me know in case we lean towards another approach.

@ceberam ceberam left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

@taru-garg-2000

Copy link
Copy Markdown
Contributor Author

Hi @ceberam, Not really sure why the test is failing but it seems like a timeout than something to do with change, wondering if you can re-trigger this?

@ceberam
ceberam merged commit df4fdc9 into docling-project:main Jul 22, 2026
41 of 44 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants