emdedd
v0.1.1
Published
Live-links TypeScript and C# source code into Markdown documentation
Maintainers
Readme
embed-sync
A zero-install script that live-links TypeScript and C# source code into Markdown documentation. Drop a one-line marker in your .md file, point it at a symbol, and embed-sync pulls in the current declaration — keeping docs and code in sync automatically.
How it works
You place HTML comment markers in your Markdown that reference a source file and a symbol name:
### Loan Position
<!-- ts-embed: ../src/models/loans.ts#ILoanPosition -->Running embed-sync resolves the symbol, extracts its full declaration (including JSDoc/XML doc comments), and injects it as a fenced code block:
### Loan Position
<!-- ts-embed: ../src/models/loans.ts#ILoanPosition -->
```ts
// @generated by embed-sync — do not edit
/**
* Represents a loan position in the securities lending system.
*/
export interface ILoanPosition {
loanId: string;
borrower: string;
lender: string;
quantity: number;
collateralValue: number;
status: "open" | "closed" | "pending";
}
On subsequent runs, the content between the markers is replaced with the latest version from source. The operation is **idempotent** — running it twice produces the same output.
## Usage
```bash
chmod +x embed-sync.ts
./embed-sync.ts "docs/**/*.md,specs/*.md"The input is a comma-delimited list of glob patterns that resolve the Markdown files to scan.
Requires Deno (v2+). No npm install, no package.json, no build step — dependencies are auto-resolved on first run and cached.
Marker syntax
<!-- ts-embed: <relative-path-to-file>#<SymbolName> -->
<!-- cs-embed: <relative-path-to-file>#<SymbolName> -->- Paths are resolved relative to the Markdown file, not the working directory.
- The closing marker (
<!-- /ts-embed -->or<!-- /cs-embed -->) is inserted automatically on first run. - Existing content between markers is fully replaced on each run.
Supported symbols
TypeScript (via the TypeScript Compiler API):
| Declaration | Example |
|---|---|
| Interface | #ILoanPosition |
| Class | #TradeProcessor |
| Function | #calculateAccrual |
| Type alias | #ReconciliationResult |
| Enum | #LoanStatus |
| Const / variable | #DEFAULT_TIMEOUT |
| Namespaced | #MyNamespace.InnerType |
C# (via pattern matching):
| Declaration | Example |
|---|---|
| Class | #TradeProcessor |
| Interface | #ILoanService |
| Record | #Loan |
| Struct | #Position |
| Enum | #LoanStatus |
| Delegate | #TradeHandler |
| Method | #CalculateAccrual |
Both extractors preserve leading doc comments (JSDoc for TS, /// XML docs for C#).
Error reporting
When a file or symbol can't be resolved, the script prints a structured error with the absolute path and line number — compatible with IDE click-through:
❌ Symbol 'DoesNotExist' not found in /repo/src/loans.ts
Source: ../src/loans.ts#DoesNotExist
Location: /repo/docs/api-reference.md:54
❌ File not found: /repo/src/nonexistent.ts
Source: ../src/nonexistent.ts#Foo
Location: /repo/docs/api-reference.md:50The script exits with code 1 if any errors occurred, code 0 on success.
CI integration
# GitHub Actions example
- name: Verify docs are in sync
run: |
./embed-sync.ts "docs/**/*.md"
git diff --exit-code -- docs/This fails the build if source code changed but the Markdown wasn't regenerated.
