OMNI-CORE LogoOMNI-CORE
omni-mdxomni-3D (soon)Open SourceAbout
GitHubDocumentation
OMNI-CORE

Knowledge must flow freely to shape the future.

Ecosystem

  • omni-mdx
  • omni-3D

Resources

  • Documentation
  • Interactive Playground

Legal & Open Source

  • GitHub Organization
  • Notice

TOAQ GROUP © 2024 - 2026

Released under the MIT License.

Navigation

Getting Started

  • Introduction
    • Web & Next.js
    • Python Engine
    • Build from Source
  • Syntax Guide

Web Integration

  • Next.js Integration
  • Binary AST Transfer
  • Custom Components
  • Unified & Plugins Ecosystem Integration
    • Basic App Router
    • Advanced Rendering
    • Live Client Editor

Python

  • Introduction & Core Engine
    • Basic Parsing & Traversal
    • Advanced Analysis & RAG
    • Native Qt Rendering
    • HTML & Web Rendering
    • Basic Parsing
    • Advanced Analysis
    • HTML Rendering
    • Qt Rendering

Architecture & Core

    • Design Philosophy
    • The Rendering Pipeline
    • Lexing & Tokenization
    • AST Node Design
    • Math & JSX Handling
    • Protocol Specification
    • Zero-Copy Decoding
    • Memory Lifecycle
    • WASM Bindings (Browser)
    • Node.js Native Addons
    • Python Bindings (PyO3)
  • Security
    • Benchmarks
    • Fuzzing Results
Docs
Unified & Plugins Ecosystem Integration

Unified & Plugin Ecosystem Integration

Last Updated April 4, 2026

The @toaq-oss/omni-mdx parser is entirely written in Rust for maximum performance, but it doesn’t operate in an isolated bubble. We provide a seamless, zero-config bridge to the unified ecosystem, allowing you to use hundreds of existing community plugins.

Why Ecosystem Compatibility Matters

The MDX and Markdown communities have spent years building incredible tools to transform content: syntax highlighters (rehype-highlight), heading anchor generators (rehype-slug), table of contents builders, and more.

Reinventing these tools in Rust would take years and lock users into a proprietary ecosystem. Instead, Omni-MDX offers the best of both worlds:

  1. The speed of Rust: The heavy lifting of parsing raw text into an Abstract Syntax Tree (AST) is done natively.
  2. The flexibility of JavaScript: The resulting AST is mapped to the standard hast (HTML AST) format, allowing any existing rehype plugin to modify it before it reaches React.

The Architecture: Rehype vs Remark

In the traditional unified ecosystem, there are two main steps:

  1. Remark: Parses Markdown into an mdast (Markdown AST).
  2. Rehype: Transforms the mdast into a hast (HTML AST).

Omni-MDX skips the Remark phase entirely. Because our Rust core directly generates HTML-equivalent nodes (e.g., <h1>, <div>, <pre>) to ensure the fastest possible React rendering, our AST translates directly to HAST.

ℹ️ Information
Rule of thumb: Always use rehype-* plugins with Omni-MDX, not remark-* plugins.

Performance: The Hybrid Cost

While adding JavaScript plugins (rehype-highlight, etc.) introduces a small overhead due to the Rust-to-JS bridge, Omni-MDX remains significantly faster because the initial parsing (the heaviest task) is already completed natively. The JS engine only processes a pre-structured HAST tree instead of raw text.


Usage in Server Components (Async)

Injecting plugins into the Omni-MDX pipeline is as simple as passing an options object to parseMdx. Because many plugins perform asynchronous operations (like loading language grammars for syntax highlighting), this is the recommended approach.

Here is an example using rehype-highlight in a Next.js Server Component:

tsx
import { parseMdx, MDXServerRenderer } from "@toaq-oss/omni-mdx/server";
import rehypeHighlight from "rehype-highlight";
// Don't forget to import the CSS theme in your layout or page!
import "highlight.js/styles/github-dark.css";

export default async function BlogPost({ content }) {
  // 1. The Rust core parses the text at lightning speed.
  // 2. The unified bridge converts it to HAST.
  // 3. rehype-highlight injects  tags with color classes.
  const ast = await parseMdx(content, {
    rehypePlugins: [rehypeHighlight],
  });

  return ;
}

Usage in the Browser (Client-Side)

If you are building a live MDX editor, you can also use plugins directly in the browser via WebAssembly.

tsx
"use client";
import { useState, useEffect } from "react";
import { parseMdx, MDXClientRenderer } from "@toaq-oss/omni-mdx/client";
import rehypeSlug from "rehype-slug";

export function LiveEditor({ rawText }) {
  const [ast, setAst] = useState(null);

  useEffect(() => {
    // parseMdx compiles via WASM and applies the plugins directly in the browser
    parseMdx(rawText, {
      rehypePlugins: [rehypeSlug] // Automatically adds id="" to all headings
    }).then(setAst);
  }, [rawText]);

  if (!ast) return 
Loading engine...
; return ; }
⚠️ Warning
Warning for Client-Side Plugins: Ensure the plugins you provide to the client parser are browser-safe. Some rehype plugins rely on Node.js native APIs (fs, path) and will crash your bundler (Webpack/Turbopack) if imported into a "use client" file.

Synchronous Parsing

If you are in an environment where you cannot use await (e.g., a legacy synchronous data pipeline), you can use parseMdxSync.

tsx
import { parseMdxSync } from "@toaq-oss/omni-mdx/server";
import rehypeSlug from "rehype-slug";

const ast = parseMdxSync("# Hello", {
  rehypePlugins: [rehypeSlug]
});

Limitations of Sync:
The unified ecosystem is asynchronous by default. If you use parseMdxSync and provide a plugin that attempts to perform an asynchronous task (like reading a file or making a network request), the unified engine will throw an error: “Cannot call runSync on an async plugin”. Whenever possible, prefer the standard async parseMdx function.


Passing Options to Plugins

Omni-MDX accepts standard unified PluggableList types. This means you can pass configurations to your plugins using nested arrays, exactly as you would in standard MDX setups:

tsx
import rehypeAutolinkHeadings from "rehype-autolink-headings";
import rehypeSlug from "rehype-slug";

const ast = await parseMdx(content, {
  rehypePlugins: [
    rehypeSlug,
    [rehypeAutolinkHeadings, { behavior: 'wrap' }] // Plugin with options
  ]
});
Boosted by omni-mdx native node

On this page

  • Why Ecosystem Compatibility Matters
  • The Architecture: Rehype vs Remark
  • Performance: The Hybrid Cost
  • Usage in Server Components (Async)
  • Usage in the Browser (Client-Side)
  • Synchronous Parsing
  • Passing Options to Plugins
Edit this page on GitHub

Caught a typo or want to improve the docs? Submitting a PR is the best way to help!