:sig
function component_resolve(name : string) string

:params
name : a component path, optionally followed by `:HANDLER`

:returns
The absolute source path the name resolves to, or an empty string when nothing matches.

:content
`component_resolve()` answers "which file would `component()` actually load for this name?". It renders nothing and runs no handler.

This is the tool for debugging resolution. Because a relative name is tried against several directories in turn, the same string can mean different files depending on which unit is calling it, and the failure that follows is usually reported against the wrong place. Printing the resolved path shows you which candidate won.

## The order it searches

`.capy` is appended when the name has no suffix. A `:HANDLER` suffix does not affect the returned path.

A name starting with `/` is tried as a real filesystem path first, then as a path under the site root.

A relative name is tried against, in order:

1. the directory of the entry unit handling the request
2. the directory of the unit calling `component_resolve()`, when that differs
3. the site root

The first candidate that exists is returned. A candidate that resolves outside the site root is rejected, and the result is an empty string.

An empty return means that no component source file matches the name.

## Check whether a component exists

`if component_resolve(...)` is a compile error. A string has no `bool` constructor.

Use this test:

    if length(component_resolve(name)) > 0 { ... }

:example capy render
print(component_resolve("/doc/examples/card"), "\n")

:example capy render show which directory a relative name reached
var resolved := component_resolve("card")
if length(resolved) > 0 { print(resolved, "\n") } else { print("unresolved\n") }

:example capy render the handler suffix does not change the path
print(component_resolve("/doc/examples/card.capy:CARD"), "\n")

:see-group
components
