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
tramais 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.nexisis a command-line tool for link and backlink analysis. It ships no library target.mdbook-wikilinkis 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-spliceedits YAML in place and supplies the frontmatter value type, andslug-collatesupplies the case- and accent-insensitive path order that breaks ties.frontmatter-losslesssplits 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
Quick start
use ;
let vault = vec!;
let index = build;
let note = "See [[Plan]] and ![[diagram.png]]. Not a link: `[[Plan]]`.";
for link in body_links
assert_eq!;
assert_eq!;
Options for a stricter reader
The defaults above are the long-standing behaviour. A tool that renders or publishes notes can ask for more:
body_links_spanned_with(body, &ScanOptions { .. })picks the code rules (CodeRules::SkillExportfor skill renderers), skips links inside HTML comments, and reads[[#Heading]]as a link to the note it is in.- Each parsed link carries its
heading, itsblock(#^id) and an embed'ssize(|300or|300x200). LinkIndex::resolve_strictrefuses a name several files answer to, returningResolveError::Ambiguouswith every candidate, whereresolve_frompicks one.LinkIndex::candidateslists them.relative_link(from, to, fragment),encode_uri_component,encode_uri_fragmentandescape_labelwrite a resolved link back out as a relative markdown link.
use CodeRules;
use ;
let options = ScanOptions ;
let links = body_links_spanned_with;
assert_eq!;
assert_eq!;
let index = build;
assert!;
assert_eq!;
The public items are documented on docs.rs.
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 withrust-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.
Design decisions
Short notes on settled design choices are in decisions/.
TypeScript twin
@osdlc/markdown-link
is the TypeScript twin of the crate's parsing half: the code lexer, the link
scanner (with ScanOptions), display text and typed references. It does
not resolve or write links yet: LinkIndex, relative_link and the URI
encoders are Rust only. It
sits beside the crate, in
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
repository, in packages/rust/markdown-link.
License
Licensed under either of Apache License, Version 2.0 or MIT License, at your option.