mdxlite

A minimal MDX runtime for constrained environments, e.g. Cloudflare Workers.

@mdx-js/mdx usage during runtime requires use of eval (evaluate and evaluateSync) in order to transform and run mdx, unfortunately not all environments allow for use of eval - like Cloudflare Workers.

mdxlite works similar to @mdx-js/mdx, in that you can take a string of markdown with JSX and transform it, yet does so without using eval or new Function()!

Getting Started:

bun add mdxlite

Usage:

import { transformMarkdown } from "mdxlite";

let markdown = `
  # Hello, world!
`;

let jsxElements = await transformMarkdown({ markdown });

Types:

The package exports a transformMarkdown function that takes an Options object.

Here are the generated types for the library:

import type { Element, Parents } from "hast";
import type { ComponentType } from "react";
import type { JSX } from "react/jsx-runtime";
import type { Options as RemarkRehypeOptions } from "remark-rehype";
import type { PluggableList } from "unified";

export type UrlTransform = (
  url: string,
  key: string,
  node: Readonly<Element>
) => string | null | undefined;

export type AllowElement = (
  element: Readonly<Element>,
  index: number,
  parent: Readonly<Parents> | undefined
) => boolean | null | undefined;

export type ExtraProps = { node?: Element };

export type Components = {
  [Key in keyof JSX.IntrinsicElements | string]:
    Key extends keyof JSX.IntrinsicElements
      ? ComponentType<JSX.IntrinsicElements[Key] & ExtraProps> | keyof JSX.IntrinsicElements
      : ComponentType<any> | keyof JSX.IntrinsicElements
};

export type ModuleValue = any;

export type ModuleLike =
  | ModuleValue
  | (() => ModuleValue)
  | (() => Promise<ModuleValue>)
  | Promise<ModuleValue>;

export type Options = {
  markdown?: string | null | undefined;
  // A mapping of components to use for the markdown
  // If you want to have these elements replace html / raw JSX within the markdown
  // you'll want to use the `rehype-raw` plugin as well
  components?: Components | null | undefined;
  // A mapping of import sources to modules
  imports?: Record<string, ModuleLike>;

  
  allowElement?: AllowElement | null | undefined;
  allowedElements?: ReadonlyArray<string> | null | undefined;
  disallowedElements?: ReadonlyArray<string> | null | undefined;
  rehypePlugins?: PluggableList | null | undefined;
  remarkPlugins?: PluggableList | null | undefined;
  remarkRehypeOptions?: Readonly<RemarkRehypeOptions> | null | undefined;
  skipHtml?: boolean | null | undefined;
  unwrapDisallowed?: boolean | null | undefined;
  urlTransform?: UrlTransform | null | undefined;
};

export declare function transformMarkdown(
  options: Options
): Promise<ReactNode>;

Credits:

This package was heavily inspired by, and uses most of the same code as the react-markdown package, and generally wouldn't be possible without many packages in the unifiedjs ecosystem.