| Crates.io | liaison |
| lib.rs | liaison |
| version | 0.2.0 |
| created_at | 2025-11-12 20:54:55.957657+00 |
| updated_at | 2026-01-17 18:21:20.512847+00 |
| description | Content transclusion tool that materializes references into source files |
| homepage | https://github.com/dnorman/liaison |
| repository | https://github.com/dnorman/liaison |
| max_upload_size | |
| id | 1929963 |
| size | 274,388 |
A content transclusion tool that materializes references into source files in place, perfect for documentation that embeds code snippets.
Works with HTML, Markdown, Rust, TypeScript, Python, and any text format.
cargo install liaison
Or from source:
git clone https://github.com/dnorman/liaison
cd liaison
cargo install --path .
1. Mark content in your source files:
// src/lib.rs
pub fn example() {
// liaison id=demo-code
let x = 42;
println!("Hello: {}", x);
// liaison end
}
2. Reference it in documentation:
<!-- README.md -->
Here's how to use it:
<!-- liaison transclude="src/lib.rs#demo-code" -->
<!-- liaison end -->
3. Run liaison:
liaison README.md
4. Your documentation now contains the actual code:
<!-- README.md -->
Here's how to use it:
<!-- liaison transclude="src/lib.rs#demo-code" -->
let x = 42;
println!("Hello: {}", x);
<!-- liaison end -->
# Process specific files
liaison index.html README.md
# Check what would change (dry run)
liaison --check README.md
# Clear all transcluded content (for testing)
liaison --reset README.md
# Continue processing even if some transclusions fail
liaison --ignore-errors README.md
# Process files matching patterns (.liaison.toml)
liaison
Create .liaison.toml in your repository root:
[glob]
include = ["docs/**/*.{md,html}", "README.md"]
exclude = ["target/**", "node_modules/**"]
Default: Empty include list (process nothing unless files specified via CLI).
For code files (.rs, .ts, .py, .js, etc.) and Markdown:
Define reusable blocks:
// liaison id=my-function
fn my_function() -> i32 {
42
}
// liaison end
Reference them:
<!-- liaison transclude="src/lib.rs#my-function" -->
<!-- liaison end -->
Comment styles auto-detected:
//#<!-- -->HTML supports two transclusion styles:
Element transclusion (using attributes):
<!-- source.html -->
<section id="intro">
<h1>Welcome</h1>
<p>Getting started guide</p>
</section>
<!-- target.html -->
<div transclude="source.html#intro"></div>
After running liaison:
<div transclude="source.html#intro">
<h1>Welcome</h1>
<p>Getting started guide</p>
</div>
Comment transclusion (same syntax as Markdown):
<!-- works in HTML files too -->
<!-- liaison transclude="components/header.html#banner" -->
<!-- liaison end -->
Self-closing tags are automatically expanded:
<!-- before -->
<header transclude="header.html#nav" />
<!-- after -->
<header transclude="header.html#nav">
<nav>...</nav>
</header>
Content is automatically dedented based on the marker's indentation:
fn main() {
// liaison id=indented
let x = 5;
if x > 0 {
println!("positive");
}
// liaison end
}
Extracts as:
let x = 5;
if x > 0 {
println!("positive");
}
Transcluded content can itself contain transclusions, which are automatically expanded:
<!-- index.html transcludes header.html -->
<header transclude="header.html#banner"></header>
<!-- header.html contains a nested transclude -->
<div id="banner">
<h1>My Site</h1>
<!-- liaison transclude="tagline.md#slogan" -->
<!-- liaison end -->
</div>
All levels are expanded in a single pass.
HTML hosts automatically indent transcluded content to match the target element:
<div transclude="content.html#section">
<!-- content is indented to match -->
</div>
Prevents infinite loops from circular references.
All changes succeed or none are applied—no partial updates on errors.
Fetch content from HTTP(S) URLs:
<!-- liaison transclude="https://example.com/api/snippet.rs#demo" -->
<!-- liaison end -->
Code from plaintext files is automatically HTML-escaped when transcluded into HTML:
<pre><code transclude="src/lib.rs#generic-function"></code></pre>
Rust code with <T> generics becomes <T> in HTML.
Paths are resolved relative to the Git repository root of the file being processed:
# Works from any directory
cd ~/projects/tool && liaison ~/projects/docs/index.html
File-relative paths (since v0.1.0): Paths are first tried relative to the current file's directory, then fall back to repo-relative:
<!-- docs/index.html -->
<div transclude="header.html#banner"></div>
<!-- Looks in docs/header.html first -->
Cross-repository: All files in a single command must be from the same repository.
.. in paths is rejectedliaison [OPTIONS] [PATH]...
Arguments:
[PATH]... Files to process (overrides glob config)
Options:
--check Check if changes would be made (dry run)
--reset Clear all transcluded content to empty
--ignore-errors Continue processing even if some transclusions fail
-h, --help Print help
-V, --version Print version
See the demo/ directory and tests/fixtures/ for working examples.
Transclusion—a term coined by Ted Nelson in 1963—is the inclusion of one document inside another by reference. Instead of copying content, you point to it. The source stays authoritative; the reference stays current.
Most formats don't support this natively. Liaison fixes that.
Phase 1 (you are here)
CLI transclusion between HTML and plaintext files. Define blocks with id, reference them with transclude, run the command. Useful, harmless, nothing to see here.
Phase 2
Web content. Fetch from remote URLs with caching and authentication. Full CSS selector support for extracting content from any webpage. Now we can point at anything on the internet.
Phase 3
More formats. XML (XPath), JSON (JSONPath), CSV (cell ranges), spreadsheets, maybe even Word docs. If it can be parsed, it can be transcluded.
Phase 4
A daemon. Watches your files and folders for changes. Re-materializes references automatically. Support for transcluding entire files into directories. Keeps everything synchronized. While you sleep.
Phase 5
Graph database overlay. The transclusion graph becomes its own persistent layer—point to things that live only in the graph, or pull external content into the graph by pointing at it. Track the live version, the archived version, or both. The graph remembers everything you've ever referenced.
Phase 6
At this point, files are just... views. The graph is the source of truth. Liaison is the filesystem muahahaha.
Dual-licensed under MIT or Apache 2.0 (your choice).