Remark Obsidian Md

Remark plugin to support Obsidian.md syntax (wiki links, callouts, highlights)

remark-obsidian-md

NPM Version License

remark plugin to support Obsidian.md syntax (wiki links, callouts, highlights).

Contents

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-md

Features

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 to My File but 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 with width="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 callouts option.
  • Rendering: By default, renders as HTML div blocks with data-callout attributes. You can opt-in to render as a MDX component <Callout> instead (see Options).

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

OptionTypeDefaultDescription
rootstring"./public"Directory path where your Obsidian vault/markdown files are located.
urlPrefixstringundefinedA string to prepend to all generated URLs (e.g., "/docs").
enableWikiLinksbooleantrueEnable parsing of [[Wiki Links]].
enableEmbedsbooleantrueEnable parsing of ![[Embeds]].
enableCalloutsbooleantrueEnable parsing of > [!type] blocks.
enableHighlightsbooleantrueEnable parsing of ==highlight==.
enableFrontmatterbooleantrueEnable custom frontmatter (YAML) component.
useMdxCalloutbooleanfalseIf true, renders a <Callout> component instead of HTML divs. Useful for MDX.
calloutCollapseIconstring-Custom SVG for the Callout collapse icon.
slugify(text: string) => string-Custom function to convert file names to URLs.
calloutsRecord<string, string>-Map of callout types to SVG icon strings. Use this to add custom icons.
customPropsobject-Inject custom HTML attributes/classes into generated nodes (wikiLinks, callouts, highlights, etc).
contentMapMap<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.

How to Install

  1. Download the template file from GitHub
  2. Move it anywhere in your vault
  3. Open it in Obsidian — done!

Stats

Stars

1

Forks

0

License

MIT

Last updated 1mo ago

Tags

admonitionadmonitionsalertalertscalloutcalloutsfumadocsfumadocs-mdxhastmarkdownobsidianremarkremark-pluginunifiedwiki-linkswikilinkwikilinks