Extract every ATX heading (# Title, ## Subtitle, …) and return
{ level, text, slug } triples in source order. slug is what
crossnote's HeadingIdGenerator produces — the value the click
resolver matches against — so this is what [[Note#slug]] should
link to and what completion providers should insert.
Skips lines inside fenced code blocks (… or ~~~ … ~~~) so
# foo inside a code sample doesn't become a phantom heading.
If a heading has a trailing {#explicit-id} block-attribute span
(the syntax crossnote's curly-bracket-attributes plugin
recognises), it's stripped before slugifying so the slug matches
the heading text rather than the literal {...} block.
Extract every ATX heading (
# Title,## Subtitle, …) and return{ level, text, slug }triples in source order.slugis what crossnote's HeadingIdGenerator produces — the value the click resolver matches against — so this is what[[Note#slug]]should link to and what completion providers should insert.Skips lines inside fenced code blocks (
…or ~~~ … ~~~) so# fooinside a code sample doesn't become a phantom heading.If a heading has a trailing
{#explicit-id}block-attribute span (the syntax crossnote's curly-bracket-attributes plugin recognises), it's stripped before slugifying so the slug matches the heading text rather than the literal{...}block.