Tutorial Image URL Resolution
Date: 2026-04-18 Status: Approved
Problem
Tutorial markdown contains relative image paths (). Glamour renders these as non-actionable text: Image: alt → /27.png. Users cannot view the images.
Solution
Resolve relative image paths to full GitHub raw content URLs during parsing, so glamour renders the full URL inline — copyable in any terminal, and auto-linked in OSC8-capable terminals:
Image: Run Java → https://raw.githubusercontent.com/sap-tutorials/Tutorials/main/tutorials/java-hana-setup/27.pngDesign
New function in internal/tutorials/parser.go
go
const rawBaseURL = "https://raw.githubusercontent.com"
func ResolveImageURLs(content, repo, branch, slug string) string- Regex matches
wherepathdoes not start withhttp://orhttps:// - Replaces path with
{rawBaseURL}/sap-tutorials/{repo}/{branch}/tutorials/{slug}/{path} - Strips leading
/from the relative path before joining - Leaves absolute URLs untouched
- Paths containing
../are left unchanged (GitHub raw CDN does not resolve traversals)
Integration
Called inside Parse() on each step's content after normalizeOptionBlocks(). Parse() gains a branch parameter (current signature: Parse(md, slug, repo string)).
Both V1 and V2 parsers benefit. Both static and TUI render paths benefit. Content is resolved at parse time and cached with full URLs on first tutorial show.
Call-site changes
cmd/tutorials.go— passbranchtoParse()(already available in scope)internal/tutorials/parser_test.go— update existing test calls with newbranchargument
Handled image path formats
| Source | Resolved |
|---|---|
 |  |
 | Same (leading / stripped) |
 | ...tutorials/{slug}/images/foo.png |
 | Unchanged (traversal not resolved) |
 | Unchanged |
Scope
- ~15 lines added to
parser.goforResolveImageURLs+rawBaseURLconstant - One-line signature change to
Parse()andParseFrontmatterOnly(addsbranch) - One-line change in
cmd/tutorials.goto passbranch - Test updates in
parser_test.go(mechanical — addbrancharg to 5 call sites) - No new files, no new dependencies
Alternatives Considered
- Pre-process at each render site — Two call sites to maintain, easy to miss one.
- Custom glamour image renderer — Overkill for URL rewriting; glamour's extension API is limited.