fix(viewer): keep unbalanced markdown emphasis literal in PDF reports - #1176
fix(viewer): keep unbalanced markdown emphasis literal in PDF reports#1176apetcu wants to merge 2 commits into
Conversation
A run of asterisks in a finding (e.g. a masked secret '******') was turned into <b><i></b></i> by the emphasis regexes in _inline_md, and reportlab rejected the crossed tags, failing the whole /api/report/send request. Emphasis content can no longer contain its own delimiter or a tag, so the bold/italic passes cannot interleave, and _para() falls back to the plain text if reportlab still rejects the markup. Fixes usestrix#1171
Greptile SummaryThe PR prevents malformed Markdown emphasis from producing crossed ReportLab tags and adds a plain-text fallback for rejected paragraph markup.
Confidence Score: 4/5The balanced nested-emphasis regression should be fixed before merging because valid narrative Markdown can now render visibly incorrect text in PDF reports. The delimiter-excluding expressions prevent outer emphasis from matching balanced nested spans, leaving raw Markdown markers in reachable report narratives that previously rendered with nested formatting. Files Needing Attention: strix/interface/viewer/report_pdf.py, tests/test_report_pdf.py Important Files Changed
Prompt To Fix All With AI### Issue 1
strix/interface/viewer/report_pdf.py:424-427
**Nested emphasis renders literally**
When a report narrative contains balanced nested Markdown such as `**bold with *italic* inside**`, the new delimiter-excluding patterns cannot match the outer span, causing raw emphasis delimiters and incomplete formatting to appear in the generated PDF.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Reviews (1): Last reviewed commit: "fix(viewer): keep unbalanced markdown em..." | Re-trigger Greptile |
| seg = re.sub(r"\*\*\*([^*<>\n]+?)\*\*\*", r"<b><i>\1</i></b>", seg) | ||
| seg = re.sub(r"\*\*([^*<>\n]+?)\*\*", r"<b>\1</b>", seg) | ||
| seg = re.sub(r"__([^_<>\n]+?)__", r"<b>\1</b>", seg) | ||
| seg = re.sub(r"\*([^*<>\n]+?)\*", r"<i>\1</i>", seg) |
There was a problem hiding this comment.
Nested emphasis renders literally
When a report narrative contains balanced nested Markdown such as **bold with *italic* inside**, the new delimiter-excluding patterns cannot match the outer span, causing raw emphasis delimiters and incomplete formatting to appear in the generated PDF.
Knowledge Base Used: Findings, usage, and reporting
Prompt To Fix With AI
This is a comment left during a code review.
Path: strix/interface/viewer/report_pdf.py
Line: 424-427
Comment:
**Nested emphasis renders literally**
When a report narrative contains balanced nested Markdown such as `**bold with *italic* inside**`, the new delimiter-excluding patterns cannot match the outer span, causing raw emphasis delimiters and incomplete formatting to appear in the generated PDF.
**Knowledge Base Used:** [Findings, usage, and reporting](https://app.greptile.com/strix-org-3/-/custom-context/knowledge-base/usestrix/strix/-/docs/findings-and-reporting.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.There was a problem hiding this comment.
Good catch — balanced nesting had regressed. Addressed in bc1b0b7: bold spans now only require a non-delimiter at each end (so a masked ****** still stays literal) and italic content may contain complete <b>..</b> spans, so **bold with *italic* inside** and *outer **bold** inner* render correctly again; covered by test_inline_md_keeps_balanced_nested_emphasis.
Restricting emphasis content to non-delimiters made `**bold with *italic* inside**` render its outer delimiters literally. Bold spans now only require a non-delimiter at each end (so `******` still stays literal) and italic content may contain complete <b>..</b> spans, which keeps nesting working while still ruling out crossed tags.
|
Thanks for the pr @apetcu -- triaging :) |
Summary
Generating the PDF report crashed with
ValueError: Parse error: saw </b> instead of expected </i>whenever a finding contained a run of asterisks — typically a masked secret such as'******'from Spring Boot's/actuator/envsanitization. The<b><i></b></i>seen in the issue is what_inline_mdproduced from******(literal<b>tags in finding text were already escaped and are fine); ReportLab rejects the crossed tags, soPOST /api/report/sendfailed for the whole report.Fixes #1171
Root cause
_inline_mdapplied the**…**,__…__and*…*substitutions with.+?content, so one pass could open a tag inside another pass's span and the passes interleaved into crossed markup. Any unbalanced emphasis (***x***,**a *b** c*) triggered the same crash.Changes
_inline_md: emphasis content may no longer contain its own delimiter or a tag ([^*<>\n]/[^_<>\n]), so the passes cannot cross;***x***is handled explicitly as bold-italic; a bare run of asterisks stays literal._para: builds theParagraphand, if ReportLab still rejects the markup, retries with our<b>/<i>/<font>tags stripped so the text renders instead of failing the whole report. Used for prose, bullets and headings in_markdown_flowables._inline_md,_markdown_flowableswith unbalanced emphasis, an end-to-endgenerate_report_pdfwith a masked secret in the summary, and the_parafallback. The new tests fail onmainwith the traceback from the issue.Verification
uv run pytest tests/test_report_pdf.py tests/test_fenced_code.py— 25 passed (8 new)uv run ruff format --check,uv run ruff check,uv run mypy strix/interface/viewer/report_pdf.py— cleanPrepared with AI assistance (Claude Code); reviewed and tested locally by @apetcu.