Pathfind
In Goblin, pathfind computes the correct path between two locations.
It is a pure path operation—no filesystem access, no project lookup—just normalized path math.
Pathfind
What you write
pathfind(from, to) pathfind(from, to, "relative") pathfind(from, to, "href")
pathfind(from, to) pathfind(from, to, "relative") pathfind(from, to, "href")
What it does
It returns a string representing how to reach to from from.
By default, it produces a relative path.
Relative Mode (default)
What you write
pathfind("docs/page.html", "assets/logo.png")
pathfind("docs/page.html", "assets/logo.png")
What it does
Returns the relative path from the directory containing from to to:
"../assets/logo.png"
"../assets/logo.png"
How from is interpreted
This part matters.
- If
fromends with/, it is treated as a directory - Otherwise, it is treated as a file, and its parent directory is used
pathfind("docs/page.html", "assets/logo.png") /// base: docs pathfind("docs/", "assets/logo.png") /// base: docs
pathfind("docs/page.html", "assets/logo.png") /// base: docs pathfind("docs/", "assets/logo.png") /// base: docs
pathfind ideal for generated HTML, where the current page is usually a file and the destination is another emitted file or asset.Same Directory
pathfind("docs/page.html", "docs/other.html")
pathfind("docs/page.html", "docs/other.html")
"other.html"
"other.html"
Different Branches
pathfind("a/b/c/page.html", "a/b/d/other.html")
pathfind("a/b/c/page.html", "a/b/d/other.html")
"../d/other.html"
"../d/other.html"
Href Mode
What you write
pathfind("docs/page.html", "assets/logo.png", "href")
pathfind("docs/page.html", "assets/logo.png", "href")
What it does
Returns a normalized root-style path based on to:
"/assets/logo.png"
"/assets/logo.png"
"href" mode, from is accepted for consistency, but the result is derived from to.Normalization
pathfind always normalizes path input before calculating the result.
That means it:
- converts
\into/ - removes empty segments
- removes
.segments - resolves
..lexically where possible1
Example:
pathfind("a/b/./page.html", "a/c/../d/logo.png")
pathfind("a/b/./page.html", "a/c/../d/logo.png")
This behaves as though the inputs were:
"a/b/page.html" "a/d/logo.png"
"a/b/page.html" "a/d/logo.png"
What Pathfind Is For
pathfind is especially useful when Goblin already knows both sides of a link.
For example:
- the current emitted file
- the destination emitted file
- an asset path in the final build
- a route resolved from
routes.json
That makes it a strong fit for static site generation, wiki-link conversion, and asset rewriting.
Strategy
A common pattern is:
- resolve the destination page or asset
- get its final emitted path
- call
pathfind(current_file, destination_file) - place the result into generated HTML
What Pathfind Does Not Do
pathfind does not:
- resolve wiki links by itself
- inspect your project structure
- read
routes.json - check whether files exist
- know what a portal is
- understand canonical URLs automatically
It only performs the path math.
That is why it works best as the last-mile link calculator after some other part of the build has already resolved the destination.
Invalid Modes
The third argument must be either "relative" or "href".
pathfind("a", "b", "weird")
pathfind("a", "b", "weird")
error: R0330: invalid-path-mode: invalid pathfind mode: weird = help: Mode must be "relative" or "href".
error: R0330: invalid-path-mode: invalid pathfind mode: weird = help: Mode must be "relative" or "href".
Why This Exists
Computing final links in generated output is annoying.
You often know:
- where the current file will be emitted
- where the destination file will be emitted
But you still need the correct relative path between them.
pathfind exists so you do not have to hand-write ../.. path math or guess how many levels deep something is.
That makes builds safer, cleaner, and easier to reason about.
Related Builtins
dirname(path)basename(path)path_join(a, b)path_normalize(path)path_relative_to(path, base)
-
Lexical means
pathfindworks on the path strings themselves. It does not inspect the real filesystem. ↩