Skip to content

fix(loader): resolve relative asset paths against the scenario, not the CWD - #200

Merged
LeadcodeDev merged 1 commit into
mainfrom
fix/asset-paths-relative-to-scenario
Aug 12, 2026
Merged

fix(loader): resolve relative asset paths against the scenario, not the CWD#200
LeadcodeDev merged 1 commit into
mainfrom
fix/asset-paths-relative-to-scenario

Conversation

@LeadcodeDev

Copy link
Copy Markdown
Owner

Closes #186.

What

cd /tmp/rmchk && rustmotion render -f rel.json -o a.png --frame 0    # ok
cd /        && rustmotion render -f /tmp/rmchk/rel.json -o b.png --frame 0
# Error: views[0].scenes[0].children[0].src: file not found 'assets/dot.png'

"src": "assets/dot.png" resolved against the process working directory. This is the single cause behind a family of "component X does not render" reports: a scenario authored beside its assets works, then the studio — which runs from the repository root — resolves nothing. The symptom varied by component (hard error for image/gif, a warning for video, silence for an audio track feeding a waveform), which made it look like several unrelated bugs.

include had always resolved relative to the including file. Two path-like fields in one document following two different rules is the trap.

How

One pass over the raw JSON, before deserialisation, so no component changes: by the time an image or an audio track is constructed, its src is already absolute. Applied in four places, all of which already hold both the JSON and its file path:

  • the JSON loader, the HTML loader, the CLI's validation pipeline;
  • and per included file — an include's assets belong to the file that names them, not to the parent that pulled it in, or moving an include would silently break every path inside it.

track is rewritten alongside src: the audio analysis is cached under the track's src and a waveform finds it by track, so rewriting one and not the other would make every lookup miss.

Deliberately conservative

A path is rewritten only when the file exists next to the scenario. Anything else is left exactly as written, which means:

  • a path that used to resolve against the working directory still does — no existing setup breaks;
  • a genuine typo still reaches the validator with the author's own spelling in the message, not a rewritten one they never typed.

Absolute paths, http(s):// and data: are untouched.

Tests

Six on the rewrite itself (absolute result, independence from the CWD, missing file left alone, absolute/remote left alone, src/track agreeing, unrelated keys untouched) and one through the loader asserting a scenario's audio[0].src comes back absolute and pointing at the real file — the end-to-end property the issue is about.

cargo test --workspace green, cargo fmt --check and cargo clippy --all-targets -- -D warnings clean. Verified by hand: the failing command above now renders from /, byte-identical to the run from the scenario's own directory.

…he CWD

"src": "assets/logo.png" resolved against the process working directory, so
the same file rendered from its own folder and failed from anywhere else — the
studio runs from the repository root, which is why a scenario authored beside
its assets showed nothing there.

`include` had always resolved relative to the including file. Two path-like
fields in one document following two different rules is the trap, and it is
the single cause behind a family of "component X does not render" reports:
a hard error for image and gif, a warning for video, silence for an audio
track feeding a waveform.

Rewrite on the raw JSON before deserialisation, so no component changes: by
the time an image or an audio track is constructed its src is already
absolute. Applied in the JSON loader, the HTML loader, the CLI's validation
pipeline, and per included file — an include's assets belong to the file that
names them, not to the parent that pulled it in.

Deliberately conservative: a path is rewritten only when the file exists next
to the scenario. Anything else is left exactly as written, so a path that used
to resolve against the working directory still does, and a genuine typo still
reaches the validator with the author's own spelling.

`track` is rewritten alongside `src`: the audio analysis is cached under the
track's src and a waveform finds it by track, so rewriting one and not the
other would make every lookup miss.
@LeadcodeDev LeadcodeDev self-assigned this Aug 12, 2026
@LeadcodeDev LeadcodeDev added the bug Something isn't working label Aug 12, 2026
@LeadcodeDev
LeadcodeDev merged commit d69e027 into main Aug 12, 2026
3 checks passed
@LeadcodeDev
LeadcodeDev deleted the fix/asset-paths-relative-to-scenario branch August 12, 2026 17:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Relative asset paths resolve against the process CWD, not the scenario file

1 participant