Repository navigation
fix(render): draw decorated blanks and replace XML-forbidden chars - #605
Merged
Merged
Conversation
Two defects made to_svg lose a form field or write a file no parser opens (vyncint#586): - A run of blanks was trimmed to nothing and skipped, decoration and all, so an underlined or struck-through empty field vanished from the SVG while the HTML drew it. A decorated run now keeps its blanks. - escape_xml passed through every character other than & < > ", so a C0 control in the window title or U+FFFF in a cell went into the SVG as itself and made it ill-formed. Characters outside the XML 1.0 Char production now become U+FFFD, one for one, in the SVG and the HTML alike, since they share the function. The tests check the decorated runs, both replacements, and that each document holds only XML Chars and nests its tags. Signed-off-by: anyingiit <49945850+anyingiit@users.noreply.github.com>
vyncint
approved these changes
Oct 23, 2026
vyncint
left a comment
Owner
There was a problem hiding this comment.
Thanks — both fixes are right. Verified beyond the tests: the decorated runs render correctly (I rasterised an underlined empty field and a struck-through "ab " with Inkscape; both lines draw where a terminal draws them, thanks to the existing xml:space="preserve"), and the SVG passes a real XML parser. The dependency-free well-formedness helper is fine. Its new PTY test was clean across a 15-shard stress run.
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 & why
Fixes both defects in #586:
to_svgtrimmed each run's trailing blanks and skipped a run left empty, decoration and all, so an underlined empty form field (printf 'Name: \033[4m \033[0m|') vanished from the SVG whileto_htmldrew it. A run with underline or strikethrough now keeps its blanks, so the line is drawn under them as a terminal draws it. That includes the trailing blanks of a decorated run that has text: an underlined "ab " is now underlined across all five cells, as into_html, where before the line stopped after "ab". Undecorated runs are trimmed as before. Concealed text still draws nothing in the SVG;to_htmldraws the underline of a concealed underlined run, and I left that existing difference alone.escape_xmlnow writes every character outside the XML 1.0Charproduction (C0 controls other than tab, LF and CR, plus U+FFFE and U+FFFF) as U+FFFD, one for one so a cell stays one column. A window title holding\x01or a cell holding U+FFFF no longer makes an SVG no parser opens.to_htmlshares the function, so it gets the same treatment.Tests in
crates/termlens/tests/export.rs: a decorated-blanks screen, U+FFFF in a cell (both built withScreen::parse, no PTY), and\x01in an OSC 0 title through theemitfixture (ignored on Windows with the usual #149 reason, like the other fixture-driven export tests). Each checks the output with a smallassert_well_formed_xmlhelper: every character is an XMLCharand the tags nest. That is not a full parse (entities and attribute syntax aren't checked); I also parsed the test SVGs withxmllintby hand and they are well-formed. I kept it dependency-free rather than adding an XML parser as a dev-dependency. If you'd prefer a real parse (as asked in #376), I'm happy to switch it toroxmltreeorquick-xml.Closes #586
Motivation / disclosure: I had some spare AI-assistant quota (Claude Code) and am using it to try to help projects with open good-first-issues. The change was prepared with Claude Code and verified as listed below; per CONTRIBUTING §6 the commit carries no AI attribution and I'm the author of record under the DCO. If it doesn't fit, isn't up to your bar, or you'd simply rather not take it, please feel free to close it, no hard feelings at all.
Checklist
render.rsreverted and pass with itcargo fmt --allandcargo clippy --workspace --all-targets --all-featuresare clean;cargo test --workspace --all-featurespassescheck-dco.sh main..HEAD: OK)check-no-ai-attribution.sh main..HEAD: OK)CHANGELOG.mdupdated under[Unreleased]→Fixedcargo insta review, not blind-accepted (none in this PR: no existing snapshot had a decorated blank run or a forbidden character)