moble
February 25, 2025, 8:34pm
1
The Documenter docs show how it’s possible to explicitly name a header with something like
# [Header](@id my_custom_header_name)
which can then be linked to in the documentation with something like
[Custom Header](@ref my_custom_header_name)
I’d like to be able to do the same for an arbitrary point on the page — not just a header. Is this possible?
I’ve tried just using the same syntax outside of a header, but it errors with “invalid local link/image: file does not exist in [the file where I placed it]”.
I can add it as raw HTML like this:
```@raw html
<a id="L_operators_Euler_angles"></a>
```
It’s ugly, but it works — in the sense that I can manually enter that id in the URL and it jumps to the right spot. The problem is that then I don’t know how to actually link to it because
inline raw HTML is not allowed, so any link to it has to be in its own paragraph, and
Documenter doesn’t recognize the raw anchor, so I can’t just use @ref with it.
Is there anything I can do that doesn’t involve just writing my docs in HTML?
moble
July 6, 2026, 2:52am
2
This has been discussed in Documenter#745 and Julia#2584 . People seem to agree that it’s a good idea, but nobody has done anything about it.
I just did something about it.
master ← kahliburke:kb/inline-id-anchors
drafted 09:34AM - 07 Jul 26 UTC
Closes #745.
## What this does
Generalizes the `@id` mechanism — currently lim… ited to top-level headers — so `[content](@id name)` can attach a named, cross-referenceable anchor to **arbitrary inline content** (text, images). For example, the original use case in this issue: a thumbnail image that jumps to a full-size figure.
```markdown
An inline text anchor: [some phrase](@id my-anchor).
A clickable thumbnail that is itself an anchor target:
[](@id figure-1)
... elsewhere, on any page ...
Jump to [the phrase](@ref my-anchor) or [Figure 1](@ref figure-1).
```
This follows the direction suggested here by @ettersi (reuse `@id` for consistency with header labels) and @mortenpi (the at-id lookup is currently restricted to headings; generalizing it).
## Behavior
- Resolves through the existing `@ref` pipeline, including forward and cross-page references.
- Shares a single id namespace with header `@id` labels, so a duplicate id (header/header, header/inline, or inline/inline) is caught by the existing uniqueness check.
- Ids are slugified exactly as header `@id`s are, so `[x](@id My Anchor)` yields a valid `My-Anchor` id.
- Written to the `objects.inv` inventory as `std:label` entries, so other projects can reach them via `DocumenterInterLinks` `@extref` — addressing the inventory requests from @moble and @goerz.
- Rendered as `<span id="...">` in HTML and `\hypertarget` in LaTeX (matching the `\hyperlinkref` emitted for a resolved `@ref`). A `<span>` (rather than `<a id>`) keeps the anchored content visually unchanged and avoids nesting an `<a>` inside content that may itself be a link or image.
## Implementation
- New `AnchoredInline` inline element (`documents.jl`).
- `collect_named_anchors!` (`expander_pipeline.jl`) walks each page during template expansion — before the cross-reference stage — and rewrites non-header `@id` links, registering them in the same `AnchorMap` as headers.
- `@contents` population skips non-heading anchors that now share that map.
- HTML and LaTeX writer methods for `AnchoredInline`.
## Tests & docs
- Integration tests in `test/crossreferences.jl` covering HTML output, inventory entries, cross-page references, nesting in admonitions/lists, header-slug collisions, id slugification, empty-content anchors, and duplicate-id failure.
- An inline anchor added to the `examples/` build, with an `objects.inv` assertion via `DocInventories` in `test/examples/tests.jl` (exercises the real HTML + LaTeX integration path).
- A new "Anchors on arbitrary content" section in `man/syntax.md`, plus a CHANGELOG entry.
- Full test suite passes locally.
## Notes for reviewers
- **Naming:** the anchors are stored in `doc.internal.headers` (reusing the header machinery, per the discussion above), which makes that field name a bit of a misnomer now. Happy to rename it to `doc.internal.anchors` throughout if you'd prefer.
- **Scope:** this handles inline `@id` links in page Markdown. Anchors inside docstrings / `@example` output (which live in off-tree ASTs) and block-level anchoring (e.g. labeling a table or equation, as @odow / @moble mentioned) are out of scope here and would be natural follow-ups.
## Demo
*(screenshots of a small demo site — inline text anchor, a thumbnail-gallery that jumps to full-size figures across pages, and the decoded `objects.inv` — to be added.)*