Skip to content

fix(report): render em dash & non-ASCII names correctly in PDF reports#97

Merged
fabio-gos-sonarsource merged 3 commits into
mainfrom
fix/pdf-utf8-mojibake
Jul 8, 2026
Merged

fix(report): render em dash & non-ASCII names correctly in PDF reports#97
fabio-gos-sonarsource merged 3 commits into
mainfrom
fix/pdf-utf8-mojibake

Conversation

@fabio-gos-sonarsource

@fabio-gos-sonarsource fabio-gos-sonarsource commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Problem

The global PDF report showed mojibake in the Skipped Repositories empty-state line:

None â€" all targeted repositories were analyzed.

gofpdf's core fonts render text as Windows-1252, so the UTF-8 em dash (, E2 80 94) was emitted as raw bytes and decoded as â€". The same class of bug affected any accented repository/organization name in both PDF reports.

Fix

Install gofpdf's UTF-8 translator (pdf.UnicodeTranslatorFromDescriptor("")) and route user-facing text through it:

GlobalReport.pdf (globalreport.go)

  • the em-dash "None — …" line,
  • the Skipped Repositories table cells (repository / branch / reason),
  • the organization subtitle in the header.

repository_summary.pdf (repository_summary.go)

  • the repository and branch name cells in each row.

Translation happens before the column-fit / truncation width logic so those stay accurate on single-byte-encoded text.

Tests

  • TestRenderSkippedReposSection_NoMojibake — renders the skipped section (empty state + accented café/naïve + em dash) with compression disabled and asserts no raw multi-byte UTF-8 sequence (E2 80 94, C3 A9, C3 AF) survives into the PDF content stream.
  • TestCreateRepositoryPDFRow_NoMojibake — same guard for a repository summary row with accented repo/branch names.

All builds (./..., -tags webui, -tags resultsall) and the full test suite pass.

🤖 Generated with Claude Code

gofpdf's core fonts render text as Windows-1252, so the UTF-8 em dash in the
"Skipped Repositories" empty-state line ("None — all targeted repositories
were analyzed.") appeared as the mojibake "None â€"…" in GlobalReport.pdf.

Install a UTF-8 translator (pdf.UnicodeTranslatorFromDescriptor) and route the
em-dash line, the skipped-repo table cells (repo/branch/reason), and the
organization subtitle through it, so those — plus any accented repository or
organization name — render correctly. Add a regression test asserting no raw
multi-byte UTF-8 sequence survives into the PDF content stream.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread pkg/utils/globalreport.go
Apply the same gofpdf Windows-1252 translator to repository_summary.pdf so
accented repository and branch names render correctly instead of as mojibake.
Translation is applied before truncation so the byte-based length limit matches
the rendered single-byte characters. Add a regression test asserting no raw
multi-byte UTF-8 sequence survives into the content stream.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@fabio-gos-sonarsource fabio-gos-sonarsource changed the title fix(report): render em dash & non-ASCII names correctly in global PDF fix(report): render em dash & non-ASCII names correctly in PDF reports Jul 8, 2026
Address Gitar review on #97: the "Largest Repo" stat card in renderGlobalPDF
drew ginfo.LargestRepository (a user-controlled repo name) without the UTF-8
translator, so an accented name still mojibaked in the summary card.

Route the ginfo card values through tr() before valOrNA. Translating first also
fixes valOrNA's byte-based truncation (s[:15]) splitting a multi-byte rune, since
the string is single-byte Windows-1252 by then. Add an end-to-end regression test
that renders the global PDF with an accented largest-repo name and asserts no raw
UTF-8 survives into the decompressed content stream.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@sonarqubecloud

sonarqubecloud Bot commented Jul 8, 2026

Copy link
Copy Markdown

@fabio-gos-sonarsource
fabio-gos-sonarsource merged commit f0bd591 into main Jul 8, 2026
4 checks passed
@gitar-bot

gitar-bot Bot commented Jul 8, 2026

Copy link
Copy Markdown
Code Review ✅ Approved 1 resolved / 1 findings

Integrates gofpdf's UTF-8 translator into both global and repository PDF reports, resolving the mojibake rendering for em dashes and non-ASCII names. The previously identified issue with the Largest Repo stat card was also addressed as part of this fix.

✅ 1 resolved
Bug: Largest Repo stat card still mojibakes non-ASCII repo names

📄 pkg/utils/globalreport.go:542-550 📄 pkg/utils/globalreport.go:552-555 📄 pkg/utils/globalreport.go:570 📄 pkg/utils/globalreport.go:511
The fix routes the organization subtitle and Skipped Repositories cells through the new tr UTF-8 translator, but the stat cards in the same renderGlobalPDF are left untranslated. ginfo.LargestRepository (a repository name — user-controlled, may contain accents like café) and the other ginfo values are passed to valOrNA(...) and then drawn via pdf.CellFormat at line 570 without tr(). This reproduces exactly the mojibake bug this PR is meant to fix: an accented largest-repo name will render as garbled Windows-1252 bytes in the summary card.

Additionally, valOrNA truncates by bytes (s[:15]) at line 547, which can split a multibyte UTF-8 sequence; wrapping that raw byte-sliced string in tr() afterward could then feed the translator an invalid partial sequence. Prefer translating first (or truncating on runes) before measuring/slicing.

Suggested fix: wrap the card value(s) in tr() before drawing, consistent with the organization subtitle at line 511. Also consider rune-based truncation in valOrNA.

Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Auto-apply Compact
gitar auto-apply:on         
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@fabio-gos-sonarsource
fabio-gos-sonarsource deleted the fix/pdf-utf8-mojibake branch July 8, 2026 14:31
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.

1 participant