markdown-link 0.5.4

Parse and resolve Markdown and wiki-style links in notes: every `[[link]]`, `![[embed]]`, and relative Markdown link in a note body or its frontmatter, with code spans excluded, plus a LinkIndex that resolves a target against a set of file paths.
Documentation
# markdown-link

Parse and resolve Markdown and wiki-style links in notes, in Rust.

Notes link to each other in several forms. `[[Note]]`, `[[Note#Heading|alias]]`,
`![[image.png]]`, relative Markdown links and frontmatter values all point at
files by a name or a partial path. Resolving a name to the right file needs
clear rules. Getting those rules wrong gives broken link graphs and broken
renames.

markdown-link does two jobs:

- Find every link in a note: `[[wikilink]]`, `![[embed]]`, relative Markdown
  links, and links in frontmatter values. Code spans and code blocks are
  skipped.
- Resolve a link target against a set of file paths. Any path suffix reaches
  a file, and when several files match, the one in the linking note's folder
  wins, then the shorter path.

The resolver follows documented link-resolution conventions. A fixture vault
and a shared case file, which other language ports can run, check the
behaviour.

## Who it is for

Programs that read or change a folder of notes: link graph builders, search
indexers, static site generators, linters, and tools that rewrite links when
a file is renamed.

## When not to use it

- You only need to render wikilinks to HTML as part of an mdBook build. Use
  `mdbook-wikilink`.
- You need a full Markdown parser or an editor model. markdown-link only finds
  and resolves links. Pair it with a Markdown parser if you need more.
- You need note-app features beyond links, such as tags, properties queries,
  canvas or plugins.

## How it compares

- [`trama`]https://crates.io/crates/trama is a library. It extracts
  wikilinks and builds a file index that resolves a link by file stem,
  ignoring case. It has no path-suffix matching, no tie-break by the linking
  note's folder, and no frontmatter links.
- [`nexis`]https://crates.io/crates/nexis is a command-line tool for link
  and backlink analysis. It ships no library target.
- [`mdbook-wikilink`]https://crates.io/crates/mdbook-wikilink is an mdBook
  preprocessor. It turns wikilinks into HTML links for a book. It does not
  expose a link index or a scanner.
- The same author publishes related libraries, and markdown-link uses two of
  them: [`yaml-splice`]https://crates.io/crates/yaml-splice edits YAML in
  place and supplies the frontmatter value type, and
  [`slug-collate`]https://crates.io/crates/slug-collate supplies the
  case- and accent-insensitive path order that breaks ties.
  `frontmatter-lossless` splits a note into frontmatter and body; it is only
  used by markdown-link's own tests.

markdown-link combines the link scanner, the path-suffix resolution rules and
a fixture-vault test suite in one library.

## Install

```sh
cargo add markdown-link
```

## Quick start

```rust
use markdown_link::{LinkIndex, LinkKind, body_links};

let vault = vec![
    "Projects/Plan.md".to_string(),
    "Daily/2026-10-18.md".to_string(),
    "Assets/diagram.png".to_string(),
];
let index = LinkIndex::build(&vault);

let note = "See [[Plan]] and ![[diagram.png]]. Not a link: `[[Plan]]`.";
for link in body_links(note) {
    let found = index.resolve_from(&link.target, "Daily/2026-10-18.md");
    println!("{:?} {} -> {:?}", link.kind, link.target, found);
}

assert_eq!(index.resolve("Plan"), Some("Projects/Plan.md"));
assert_eq!(body_links(note)[1].kind, LinkKind::Embed);
```

The public items are documented on [docs.rs](https://docs.rs/markdown-link).

## Supported versions

- Rust: 1.89 or newer. This is the only place the number is stated in
  prose. The source of truth is the workspace's `rust-version`, which the
  crate inherits with `rust-version.workspace = true`.

## Platforms

Any platform with `std`. The crate has no platform-specific code and no
`unsafe` code.

## Stability

This is a 0.x crate. Breaking changes are possible between minor versions and
are listed in the [changelog](CHANGELOG.md).

## Design decisions

Short notes on settled design choices are in [decisions/](decisions/).

## TypeScript twin

[`@osdlc/markdown-link`](https://www.npmjs.com/package/@osdlc/markdown-link)
is the TypeScript twin of the crate's parsing half: the code lexer, the link
scanner, display text and typed references. It does not resolve links yet. It
sits beside the crate, in
[`packages/ts/markdown-link`](https://github.com/osdlc/osdlc/tree/main/packages/ts/markdown-link).
Its tests read this crate's `tests/fixtures/conformance.json`, so the two
agree on every case in it. Its offsets count UTF-16 code units, where the
crate's count bytes.

## Source

The crate lives in the [osdlc/osdlc](https://github.com/osdlc/osdlc)
repository, in `packages/rust/markdown-link`.

## License

Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or
[MIT License](LICENSE-MIT), at your option.