remark-obsidian-md
v1.1.0
Published
Remark plugin to support Obsidian.md syntax (wiki links, callouts, highlights)
Maintainers
Readme
remark-obsidian-md
remark plugin to support Obsidian.md syntax (wiki links, callouts, highlights).
Contents
- What is this?
- When should I use this?
- Installation
- Features
- Usage
- Options
- Examples
- Types
- Next Steps
- Credits
- License
What is this?
This is a remark plugin that transforms Obsidian-specific markdown syntax into standard compatible Markdown (MDAST) or HTML. It bridges the gap between your personal knowledge base and your web publisher.
It handles features unique to Obsidian, like Wiki Links ([[Note]]), Embeds (![[Note]]), Callouts (> [!info]), and Highlights (==text==), resolving them correctly against your file system so they work in static site generators like Next.js, Gatsby, or Astro.
When should I use this?
Use this plugin if:
- You use Obsidian.md to write content and want to publish it to the web (e.g., a Digital Garden or Blog).
- You want to preserve Obsidian's internal linking graph (
[[Link]]) without manually converting links to standard markdown ([Link](./path/to/file.md)). - You use Next.js, Fumadocs, or Contentlayer and want to support Obsidian callouts and highlights out of the box.
Installation
npm install remark-obsidian-md
# or
pnpm add remark-obsidian-md
# or
yarn add remark-obsidian-mdFeatures
Wiki Links
The plugin scans your root directory to resolve file paths automatically. You don't need to know the relative path; just the filename is enough.
- Standard:
[[My File]]→ becomes a link to/my-file(slugified). - Headings:
[[My File#Some Heading]]or[[#Some Heading]]→ links to the specific anchor in the page.
Aliasing
You can display custom text for a link using the pipe | separator.
[[My File|Click Here]]→ Renders a link pointing toMy Filebut displaying "Click Here".
Images & Resizing
Images support standard embedding and Obsidian's resizing syntax.
[[image.png]]→ Link to open just the image.![[image.png]]→ Renders the image in the page.[[image.png|300]]→ Renders the image withwidth="300".
Note Embedding
Using ![[My Note]] will embed the content of that note directly into the current page.
Callouts
Supports standard Obsidian callouts (e.g., > [!info] Title).
- Icons: automatically applies Lucide icons matching the default Obsidian callouts types (info, tip, warning, etc.).
- Customization: You can overwrite icons or add new types via the
calloutsoption. - Rendering: By default, renders as HTML
divblocks withdata-calloutattributes. You can opt-in to render as a MDX component<Callout>instead (seeOptions).
Collapsable
Supports the fold syntax:
> [!info]+(Open by default)> [!info]-(Collapsed by default)
Highlights
Text wrapped in double equals ==highlighted text== is transformed into an HTML <mark>highlighted text</mark> tag.
Frontmatter
Creates an component that mimics the way Obsidian.md displays frontmatter (YAML) properties.
Usage
Unified / Remark
Use it as a standard plugin in your unified processor. You can provide the root directory so the plugin know how to resolve file paths (defaults to ./public/).
import { unified } from "unified";
import remarkParse from "remark-parse";
import remarkObsidianMd from "remark-obsidian-md";
import remarkRehype from "remark-rehype";
import rehypeStringify from "rehype-stringify";
const file = await unified()
.use(remarkParse)
// Add the plugin here
.use(remarkObsidianMd, {
root: "./public/vault",
// Add another options here
})
.use(remarkRehype)
.use(rehypeStringify)
.process("[[My Note]]");
console.log(String(file));Next.js / Fumadocs
If you are using Fumadocs, add the plugin to your source configuration.
// source.config.ts
import { defineConfig, defineDocs } from "fumadocs-mdx/config";
import remarkObsidianMd, { type Options } from "remark-obsidian-md";
export const content = defineDocs({
dir: "./public/vault", // Your markdown content directory
});
export default defineConfig({
mdxOptions: {
remarkPlugins: [
[
remarkObsidianMd,
{
root: "./public/vault",
// Optional: Add a prefix if your docs live under /docs
urlPrefix: "/docs",
} satisfies Options,
],
],
},
});Options
| Option | Type | Default | Description |
| :-------------------- | :------------------------- | :----------- | :------------------------------------------------------------------------------------------------- |
| root | string | "./public" | Directory path where your Obsidian vault/markdown files are located. |
| urlPrefix | string | undefined | A string to prepend to all generated URLs (e.g., "/docs"). |
| enableWikiLinks | boolean | true | Enable parsing of [[Wiki Links]]. |
| enableEmbeds | boolean | true | Enable parsing of ![[Embeds]]. |
| enableCallouts | boolean | true | Enable parsing of > [!type] blocks. |
| enableHighlights | boolean | true | Enable parsing of ==highlight==. |
| enableFrontmatter | boolean | true | Enable custom frontmatter (YAML) component. |
| useMdxCallout | boolean | false | If true, renders a <Callout> component instead of HTML divs. Useful for MDX. |
| calloutCollapseIcon | string | - | Custom SVG for the Callout collapse icon. |
| slugify | (text: string) => string | - | Custom function to convert file names to URLs. |
| callouts | Record<string, string> | - | Map of callout types to SVG icon strings. Use this to add custom icons. |
| customProps | object | - | Inject custom HTML attributes/classes into generated nodes (wikiLinks, callouts, highlights, etc). |
| contentMap | Map<string, Metadata> | - | Advanced: Manually provide the map of files instead of scanning root. |
Examples
Custom Callout Icons
You can register your own callout types or overwrite existing ones by passing SVG strings.
use(remarkObsidianMd, {
callouts: {
"my-custom-type": "<svg>...</svg>", // Usage: `> [!my-custom-type] Title`
note: "<svg>...</svg>", // Overwrites the default 'note' icon
},
});Custom Styling
You can import the default CSS styles included in the package:
import "remark-obsidian-md/styles/callouts.css";
import "remark-obsidian-md/styles/callouts-colors.css";
import "remark-obsidian-md/styles/frontmatter.css";
// if that doesn't work, try to import directly from the node modules
import "../../node_modules/styles/callouts.css";
import "../../node_modules/styles/callouts-colors.css";
import "../../node_modules/styles/frontmatter.css";Or manually style the elements. The plugin produces the following HTML structure:
- Normal Callouts:
<div class="callout" data-callout="type">
<div class="callout-title">
<div class="callout-icon">
<svg><!-- ... --></svg>
</div>
Callout Title
</div>
<p>Callout content</p>
</div>- Collapsable Callouts:
<details class="callout" data-callout="type" open>
<summary class="callout-title">
<div class="callout-icon">
<svg><!-- ... --></svg>
</div>
Callout Title
<div class="callout-collapse-icon">
<svg><!-- ... --></svg>
</div>
</summary>
<p>Callout content</p>
</details>- Frontmatter:
<details class="frontmatter" open>
<summary class="frontmatter-title">
<div class="frontmatter-collapse-icon">
<svg><!-- ... --></svg>
</div>
Properties
</summary>
<ul class="frontmatter-properties">
<!-- String | Number | Date | Time -->
<li class="frontmatter-property">
<div class="frontmatter-icon">
<svg><!-- ... --></svg>
</div>
<div class="frontmatter-property-key">Key name</div>
<div class="frontmatter-property-value" data-type="string">Value</div>
</li>
<!-- Boolean -->
<li class="frontmatter-property">
<div class="frontmatter-icon">
<svg><!-- ... --></svg>
</div>
<div class="frontmatter-property-key">Key name</div>
<div class="frontmatter-property-value" data-type="boolean">
<input type="checkbox" disabled checked />
</div>
</li>
<!-- List -->
<li class="frontmatter-property">
<div class="frontmatter-icon">
<svg><!-- ... --></svg>
</div>
<div class="frontmatter-property-key">Key name</div>
<div class="frontmatter-property-value" data-type="list">
<ul>
<li>String value</li>
<li><a href="...">Links</a></li>
</ul>
</div>
</li>
</ul>
</details>Custom Callout Colors
If you want to customize the callouts colors, you can easily do so by adding the following CSS styles:
[data-callout="note"] {
--callout-color: 2, 122, 255; /* rgb */
}Types
This package is fully typed with TypeScript.
It exports the additional type Options.
The node types are supported in @types/mdast by default.
Credits
- Lucide: default callouts icons.
License
This project is licensed under the MIT License.
