ddonche/goblin-lang
0.46.24
1
0
reference builtin
[[pathfind]]

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 from ends 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

Note
This makes 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"

Note
In "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:

  1. resolve the destination page or asset
  2. get its final emitted path
  3. call pathfind(current_file, destination_file)
  4. 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)

  1. Lexical means pathfind works on the path strings themselves. It does not inspect the real filesystem.