Skip to content

fix(viewer): keep unbalanced markdown emphasis literal in PDF reports - #1176

Open
apetcu wants to merge 2 commits into
usestrix:mainfrom
apetcu:fix/1171-pdf-malformed-markup
Open

fix(viewer): keep unbalanced markdown emphasis literal in PDF reports#1176
apetcu wants to merge 2 commits into
usestrix:mainfrom
apetcu:fix/1171-pdf-malformed-markup

Conversation

@apetcu

@apetcu apetcu commented Aug 26, 2026

Copy link
Copy Markdown

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/env sanitization. The <b><i></b></i> seen in the issue is what _inline_md produced from ****** (literal <b> tags in finding text were already escaped and are fine); ReportLab rejects the crossed tags, so POST /api/report/send failed for the whole report.

Fixes #1171

Root cause

_inline_md applied 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 the Paragraph and, 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.
  • Tests: parametrized crossed-markup cases for _inline_md, _markdown_flowables with unbalanced emphasis, an end-to-end generate_report_pdf with a masked secret in the summary, and the _para fallback. The new tests fail on main with 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 — clean

Prepared with AI assistance (Claude Code); reviewed and tested locally by @apetcu.

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-apps

greptile-apps Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR prevents malformed Markdown emphasis from producing crossed ReportLab tags and adds a plain-text fallback for rejected paragraph markup.

  • Adds explicit bold-italic parsing and restricts emphasis spans to avoid delimiter interleaving.
  • Routes Markdown prose, bullets, and headings through a paragraph-construction fallback.
  • Adds regression coverage for masked secrets, unbalanced emphasis, fallback rendering, and end-to-end PDF generation.

Confidence Score: 4/5

The 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

Filename Overview
strix/interface/viewer/report_pdf.py Prevents crossed emphasis tags and adds paragraph fallback handling, but the narrowed patterns regress balanced nested Markdown emphasis.
tests/test_report_pdf.py Adds strong crash-regression coverage, though it does not assert that previously supported balanced nested emphasis remains formatted.
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

Comment thread strix/interface/viewer/report_pdf.py Outdated
Comment on lines +424 to +427
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)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 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.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

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.
@bearsyankees

Copy link
Copy Markdown
Collaborator

Thanks for the pr @apetcu -- triaging :)

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.

[BUG]PDF report generation fails when finding contains malformed HTML-like text

2 participants