Repository navigation
fix(jats): keep the target of an ext-link in a mixed citation - #4813
Conversation
A <mixed-citation> was flattened to plain text with _get_text, so an <ext-link> inside it lost its xlink:href. The target survived only when the link text repeated the URL. Walk the citation with _walk_linear, the inline walker of body paragraphs, so the link becomes a hyperlink on its own run, as docling-project#4029 does in the body. A citation with one run stays a single list item. A citation with more runs becomes an empty list item with an inline group, as footnotes and HTML list items do. Element citations are unchanged. Regenerate the JATS ground truth. Only the six references that contain an ext-link change: two in pntd.0008301, three in pone.0234687 and one in ptag100. The text of every other reference is unchanged. Resolves docling-project#4793 Signed-off-by: Yashvardhan Thanvi <[email protected]>
|
✅ DCO Check Passed Thanks @Thanatos9404, all your commits are properly signed off. 🎉 |
Merge Protections🟢 All 2 merge protections satisfied — ready to merge. Show 2 satisfied protections🟢 Enforce conventional commitMake sure that we follow https://www.conventionalcommits.org/en/v1.0.0/
🟢 Require two reviewer for test updatesWhen test data is updated, we require two reviewers
|
AI triage (advisory)Checked commit The PR changes the JATS backend so that a CI safety: needs maintainer care before you approve CI.
2 related pull request(s) in the same code
Reference data changes
Assessment: expected. Mixed citations that contain links or styling now become several inline runs. This explains the extra text items in the The |
There was a problem hiding this comment.
AI first review (advisory): no blocker found
This review covers the full diff at 75f5de284e. It read the code and did not run it.
I found no merge-deciding defect. I traced _add_mixed_citation through _walk_linear, _strip_segments, and _emit_inline. A one-run citation stays a list item with its formatting and hyperlink. A multi-run citation becomes an empty list item with an inline group, as _add_footnote_group does. The regression tests cover the lost link target, the differing link text, the single-run case, and styling. I could not read the changed reference data, so the human reviewer must check the three groundtruth diffs. The new *et al* . spacing the PR describes is the visible effect to look for there.
A maintainer makes the merge decision. This review never approves the pull request.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
ceberam
left a comment
There was a problem hiding this comment.
Thanks @Thanatos9404 for this contribution!
Just to keep the repo tidy, please do not create another test module for testing the references. Add the new tests in tests/test_backend_jats.py.
|
@ceberam Happy to move them, but |
Move the four mixed-citation tests from tests/test_backend_jats_references.py into tests/test_backend_jats.py and remove the separate module, as asked in review. They now build the reference list with convert_jats_body and reuse the _list_items, _inline_group_items and _formatting_tuple helpers, like the element-citation tests. This takes tests/test_backend_jats.py to 1593 lines, past the 1500-line limit of the max-lines hook, so add it to the [warn] list of .github/max-lines-ignore. Signed-off-by: Yashvardhan Thanvi <[email protected]>
|
Thanks @ceberam, moved the tests into |
A
<mixed-citation>in the reference list is flattened to plain text with_get_text, so an<ext-link>inside it loses itsxlink:href. The target survives only when the link text repeats the URL. This is the citation case that #4029 left out of scope.Issue resolved by this Pull Request:
Resolves #4793
Root cause
In
_walk_linear, themixed-citationbranch didtext = JatsDocumentBackend._get_text(child).strip()and added that string as a list item._get_textonly collects text, so every link target (and any styling) inside the citation was dropped.Change
mixed-citationbranch now calls a new_add_mixed_citation. It walks the citation with_walk_linear, the inline walker that body paragraphs use, so each<ext-link>becomes a run with its hyperlink, the same way feat(jats): preserve external hyperlinks #4029 handles links in the body._add_footnote_groupuses for footnotes and the HTML backend uses for list items with links.<italic>,<bold>,<sub>,<sup>) and inline formulas in a mixed citation are kept too. No mixed citation in the existing fixtures has styling, so this changes no reference data. Real articles often style part of a citation, for example<italic>et al</italic>.. Such a citation now exports as*et al* ., the same as a styled body paragraph, until docling-core#693 lands. Inline formulas, which were dropped before, are now kept.<element-citation>is not changed. It is rebuilt from its fields, and its text keeps the trailing space thattest_jats_element_citation_empty_name_parts_are_omittedexpects. Links inside an element citation (for example in<comment>) are still not converted; none of the fixtures has one, and that would be a separate change to_parse_element_citation. Like body paragraphs,_walk_linearreads only<ext-link>, so a<uri xlink:href>in a citation also still loses its target.Behavior on the input from the issue:
main):- BRAVO-CITATION. A work. 2020. https://example.org/c2-citation, and no text item has the hyperlinkhttps://example.org/c2-citation.- BRAVO-CITATION. A work. 2020. [https://example.org/c2-citation](https://example.org/c2-citation). The list item holds an inline group with the runsBRAVO-CITATION. A work. 2020.andhttps://example.org/c2-citation, and the second run has the hyperlink. The body link is unchanged.Reference data
Only the six references that contain an
<ext-link>change. I compared the old and new.jsonitem by item (text, label, hyperlink, formatting, content layer): the other 178 mixed citations in the fixtures are identical.pntd.0008301: 2 references (CGIAR-CSI SRTM and USGS NASA). In the first one, the link texthttp://Srtm.Csi.Cgiar.Org/differs from its target, which was lost before.pone.0234687: 3 references (FAO, IPCC and GREET).ptag100: 1 reference, with aSearch inSPIRElink inside<comment>. Its targethttps://inspirehep.net/literature?q=find%20EPRINT%202408.15986v3was lost before.elife-56337andpmc2231364: no change (they have no mixed citations).In the
.mdfiles the URL becomes a Markdown link. In the.itxtand.jsonfiles each changed reference is an empty list item with an inline group, and the items after it are renumbered. Two references show the existing inline group spacing of the serializer,ttps:// [www.ipcc.ch/...](...)and[hep-th] [ [Search inSPIRE](...) ].Body paragraphs with links already export the same way, for example( [https://www.inration.educagri.fr/fr/forum.php](...) )inpone.0234687.nxml.md. The spacing is the serializer topic tracked in docling-core#693.Checklist:
Review evidence:
New tests in
tests/test_backend_jats_references.py.tests/test_backend_jats.pyhas 1494 lines and themax-lineshook allows 1500, so the tests are in a new module that reusesget_converter, astests/test_backend_pptx_charts.pydoes.test_jats_mixed_citation_keeps_external_link_target: the input from the issue; checks the runs and the Markdown.test_jats_mixed_citation_keeps_link_target_that_differs_from_its_text: the link text isdoi:10.5555/surveyand the target ishttps://doi.org/10.5555/survey.test_jats_mixed_citation_with_one_run_stays_a_single_list_item: a plain citation keeps its old shape (no inline group), and a citation that is only a link keeps the link on the list item.test_jats_mixed_citation_keeps_inline_styling: italic and bold runs in a citation.All four fail on
main(ffce191) and pass with this change.Commands and results (Windows 11, Python 3.10.20, docling-core 2.100.0, environment from
uv sync --frozen --group dev --all-packages --no-group docs --no-group examples --extra format-xml-jats):uv run pytest tests/test_backend_jats_references.pywith the backend ofmainuv run pytest tests/test_backend_jats_references.py tests/test_backend_jats.pyuv run pytest tests/test_backend_jats.py tests/test_backend_jats_references.py tests/test_input_doc.py tests/test_backend_optional_dependencies.py tests/test_data_gen_flag.pyDOCLING_GEN_TEST_DATA=1 uv run pytest tests/test_backend_jats.py -k e2euv run prek run --files <changed files>(whatmake validateruns)uv run ty check docling/backend/xml/jats_backend.pymainNot run: the full test suite and the ML suites. On Windows, the hooks that call
python3ran through apython3alias of the project interpreter.