Find the undrawable glyphs by parsing the source, not by listing them - #48
Merged
Conversation
…ting them
The last round of this fixed the catalogs and left the icons, because icons are
not translated copy — they are bare literals in the source. `ui.small_button("✕")`
is invisible to a scan of `en.txt`, so the Genealogy card kept shipping a box on
every kit-remove, MDKA-edit and MDKA-remove button.
Reading the sources instead found twenty-odd more that no screenshot had reached
yet: every clear-filter `✕`, the Y-STR agreement `✓`/`✗`, the sortable-table sort
arrows `▲`/`▼`, the unread dots on threads and DMs, the match-strength meter, the
STR group banner `▸`, and `→` in a dozen status lines. Each replacement was
probed against the actual fonts rather than chosen by eye — `✕`(U+2715) sits one
codepoint from `✖`(U+2716) and only the latter has a glyph, which is precisely
how this recurs:
✕ -> ✖ ✎ -> ✏ ✓ -> ✔ ✗ -> ✖
● -> ⚫ ○ -> ⚪ ▲▼ -> ⏶⏷ ▸ -> ▶ → -> ›
Two of them were in `navigator-app`, not here: a consensus warning and the import
summary's reference notes, both built there and drawn by egui via `sources.rs`
and `events.rs`.
`every_source_string_literal_is_renderable` is the part meant to outlast this.
Parsing rather than grepping is what makes it safe — comments are full of `→` and
`◆` naming the very bug they describe, and the AST has literals and no comments.
Two things had to be right for it to see anything: doc comments arrive as
`#[doc = "…"]` attributes, and syn hands macro bodies over as an unparsed
`TokenStream`, which would have hidden nearly every label in the app, since they
are built by `format!`. Verified by injecting a bad glyph into a `format!` and
watching it fail.
It is scoped to this crate, and the doc comment says why that gap is deliberate:
`navigator-app` also feeds the CLI and the HTML exporter, where `→` and `✓` are
correct, so which of its strings reach a window is a dataflow question rather
than a syntactic one.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What was wrong
The boxes on the Genealogy card were
✕(kit-remove, MDKA-remove) and✎(MDKA-edit). The last round of this fixed the locale catalogs and stopped there — but icons are not translated copy, they are bare literals in the source, andui.small_button("✕")is invisible to a scan ofen.txt.Reading the sources instead found ~20 more that no screenshot had reached yet: every clear-filter
✕, the Y-STR agreement✓/✗, the sortable-table sort arrows▲/▼, the unread dots on threads and DMs, the match-strength meter, the STR group banner▸, and→in a dozen status lines.Every replacement was probed against the actual fonts rather than chosen by eye —
✕(U+2715) sits one codepoint from✖(U+2716) and only the latter has a glyph, which is precisely how this recurs:✕✎✓✗✖✏✔✖●○⚫⚪▲▼▸→⏶⏷▶›Two of them were in
navigator-app, not the UI crate: a consensus warning and the import summary's reference notes, both built there and drawn by egui viasources.rsandevents.rs.The part meant to outlast it
every_source_string_literal_is_renderableparses this crate's own sources withsynand checks every string literal against egui's own fonts, so a new icon is covered the moment it is typed rather than when someone remembers to extend a list.Parsing rather than grepping is what makes that safe — comments are full of
→and◆naming the very bug they describe, and the AST has literals and no comments. Two things had to be right for it to see anything:#[doc = "…"]attributes, andTokenStream, which would have hidden nearly every label in the app, since they are built byformat!.The first version had that second hole and passed vacuously. It is only trustworthy because a bad glyph was injected into a
format!and the test was watched failing with both codepoints named, before being reverted.Scope, deliberately
The gate covers
navigator-uionly, and the doc comment says why rather than papering over it:navigator-appalso feeds the CLI and the HTML exporter, where→and✓are correct, so which of its strings reach a window is a dataflow question rather than a syntactic one.cli.rsand#[cfg(test)]modules are excluded here for the same reason — a terminal renders in the user's own font.Verification
cargo fmt --allclean ·cargo clippy --all-targets -- -D warningsclean ·cargo test --workspaceall green (0 failed).Worth a glance in the running app
⏶/⏷are heavier than the▲/▼they replace, and⚫/⚪are chunkier than●/○in the match-strength meter. They were the only drawable options in that shape family.🤖 Generated with Claude Code