Context
Found while verifying #365 (closed by #390) on main 0.7.1. Every icon renders nothing.
Cause
set_root_attribute in crates/rustmotion-core/src/engine/renderer/assets.rs keeps the closing quote of the previous value and appends another one. Iconify sources always carry width="1em", so the output is <svg … width="84"" height="84"" …>, which does not parse. The unit tests only check contains("width=\"84\""), so they miss the stray quote.
Repro
{"version":"1.0","video":{"width":320,"height":180,"fps":30,"background":"#FFFFFF"},"scenes":[{"duration":1,"children":[{"type":"icon","icon":"lucide:rocket","style":{"width":84,"height":84,"color":"#2563EB"}}]}]}
rustmotion still -f icon.json --time 0 → failed to parse icon 'lucide:rocket': SVG data parsing failed cause expected a whitespace not '"' at 1:52, blank image, exit code 0.
To do
Definition of done
- A test that fails on current
main is written first. For anything visual it is a render test (scenario → frame → pixel assertions); tests that build AnimatedProperties by hand are not enough — that is exactly how the regressions listed here slipped through.
- Each item is verified end to end: scenario JSON,
rustmotion validate, render, image inspected.
cargo fmt --all --check, cargo clippy --workspace --all-targets -- -D warnings, cargo test --workspace pass.
- Vocabulary changes update
crates/rustmotion/skills/SKILL.md, the relevant rules/ file and the exported schema. A field the validator accepts must have an effect, otherwise the validator rejects it or warns.
- No comments in Rust code (repository rule). Commits follow
<type>: <verb> <message>. No AI attribution in commits, PRs or issue comments.
Context
Found while verifying #365 (closed by #390) on
main0.7.1. Everyiconrenders nothing.Cause
set_root_attributeincrates/rustmotion-core/src/engine/renderer/assets.rskeeps the closing quote of the previous value and appends another one. Iconify sources always carrywidth="1em", so the output is<svg … width="84"" height="84"" …>, which does not parse. The unit tests only checkcontains("width=\"84\""), so they miss the stray quote.Repro
{"version":"1.0","video":{"width":320,"height":180,"fps":30,"background":"#FFFFFF"},"scenes":[{"duration":1,"children":[{"type":"icon","icon":"lucide:rocket","style":{"width":84,"height":84,"color":"#2563EB"}}]}]}rustmotion still -f icon.json --time 0→failed to parse icon 'lucide:rocket': SVG data parsing failed cause expected a whitespace not '"' at 1:52, blank image, exit code 0.To do
render --frameonly warns and exits 0 when an icon cannot be loaded, whilestill,renderandsheetexit 1: align it.{slug}-{color}-{w}x{h}.svgare neither reused nor migrated, so an icon present many times on disk fails offline: reuse or migrate them.validate --offline/rustmotion icons prefetchtogether with validate and still fetch Google Fonts over the network with no opt-in #320: a render that must work offline needs a way to preload its icons.Definition of done
mainis written first. For anything visual it is a render test (scenario → frame → pixel assertions); tests that buildAnimatedPropertiesby hand are not enough — that is exactly how the regressions listed here slipped through.rustmotion validate, render, image inspected.cargo fmt --all --check,cargo clippy --workspace --all-targets -- -D warnings,cargo test --workspacepass.crates/rustmotion/skills/SKILL.md, the relevantrules/file and the exported schema. A field the validator accepts must have an effect, otherwise the validator rejects it or warns.<type>: <verb> <message>. No AI attribution in commits, PRs or issue comments.