Plugin API
The plugin system provides factory functions for creating plugins. This is the complete API reference.
OrgPressPlugin Interface
All plugins conform to the OrgPressPlugin interface:
interface OrgPressPlugin {
/** Unique plugin name */
name: string;
/**
* Plugin priority (higher = runs first)
* Default: 0
* Built-in plugins use 10
* User plugins typically use 50-100
*/
priority?: number;
/**
* Setup function called during plugin initialization
* Use this for complex plugins that need full PluginContext access
*/
setup?: (ctx: PluginContext) => void | Promise<void>;
// Internal markers (set by factory functions)
_type?: PluginType;
_config?: unknown;
}
type PluginType =
| "drawer" // CreateDrawer
| "block" // CreateBlock
| "element" // CreateElement
| "transformer" // CreateTransformer
| "rehype" // CreateRehypePlugin
| "uniorg" // CreateUniorgPlugin
| "command" // CreateCommand
| "vite" // CreateVitePlugin
| "middleware" // CreateMiddlewarePlugin
| "generic"; // CreatePlugin
Factory Functions
CreateBlock
Create plugins for handling code blocks by language.
function CreateBlock(
language: string | string[],
options: BlockOptions
): OrgPressPlugin;
interface BlockOptions {
/** Transform function for the code block */
transform: (code: string, ctx: BlockContext) => TransformResult | Promise<TransformResult>;
/** Optional React wrapper component */
wrapper?: unknown;
/** Optional client-side script */
clientScript?: string;
/** Default file extension for generated modules */
defaultExtension?: string;
/** Plugin priority (higher = runs first) */
priority?: number;
}
interface BlockContext {
blockId: string; // Unique ID (e.g., "block-0")
language: string; // Block language
params: Record<string, string>; // Parsed parameters
orgFilePath: string; // Relative path to org file
blockIndex: number; // 0-based index
base: string; // Base URL path
}
interface TransformResult {
code?: string; // Transformed code
html?: string; // HTML output
script?: string; // Additional script
css?: string; // Additional CSS
}
Example:
import { CreateBlock } from "org-press";
const myBlock = CreateBlock(["mylang", "ml"], {
transform: (code, ctx) => ({
html: `<pre id="${ctx.blockId}">${code}</pre>`,
css: `#${ctx.blockId} { background: #f5f5f5; }`,
}),
priority: 50,
});
CreateDrawer
Create plugins for handling org-mode drawers.
function CreateDrawer(
name: string | string[],
transform: DrawerTransformFn
): OrgPressPlugin;
type DrawerTransformFn = (
drawer: DrawerNode,
ctx: TransformContext
) => string | null | Promise<string | null>;
interface DrawerNode {
name: string; // Drawer name (e.g., "NOTE")
children: unknown[]; // Raw AST children
html: string; // Pre-rendered HTML content
}
interface TransformContext {
orgFilePath: string; // Relative path to org file
base: string; // Base URL path
config: OrgPressConfig;
}
Example:
import { CreateDrawer } from "org-press";
// Single drawer
const noteDrawer = CreateDrawer("NOTE", (drawer) =>
`<aside class="note">${drawer.html}</aside>`
);
// Multiple drawers
const callouts = CreateDrawer(
["NOTE", "TIP", "WARNING"],
(drawer) => `<aside class="callout-${drawer.name.toLowerCase()}">${drawer.html}</aside>`
);
// Remove drawer from output
const hideProps = CreateDrawer("PROPERTIES", () => null);
CreateTransformer
Create pipeline stages for the :use parameter.
function CreateTransformer(
name: string,
options: TransformerOptions
): OrgPressPlugin;
interface TransformerOptions {
/** Build-time transform (Node.js environment) */
onBuild?: (input: TransformerInput, ctx: BuildContext) => TransformerOutput;
/** Server-side execution (Node.js environment) */
onServer?: (code: string, ctx: ServerContext) => Promise<unknown>;
/**
* Client-side code (browser environment)
* - Function: Dynamic import for code splitting
* - String: Inline script
*/
client?: (() => Promise<ClientModule>) | string;
}
interface TransformerInput {
code: string; // Original source code
language: string; // Block language
params: Record<string, string>; // Block parameters
html?: string; // HTML from previous transformer
result?: unknown; // Result from onServer
clientData?: unknown; // Data for client
}
interface TransformerOutput {
html?: string; // HTML output
result?: unknown; // Pass to next transformer
clientData?: unknown; // Data for client hydration
script?: string; // Additional script
css?: string; // Additional styles
}
interface BuildContext {
id: string; // Unique block ID
code: string; // Original source code
orgFilePath: string; // Relative path to org file
blockIndex: number; // Block index
params: Record<string, string>;
}
interface ServerContext extends BuildContext {
execute: (code: string) => Promise<unknown>; // Code execution
contentHelpers?: ContentHelpers;
}
interface ClientModule {
onMount?: (element: HTMLElement, ctx: ClientContext) => void | (() => void);
onUnmount?: (element: HTMLElement) => void;
onUpdate?: (element: HTMLElement, ctx: ClientContext) => void;
}
interface ClientContext {
blockId: string;
data?: unknown; // From clientData
params: Record<string, string>;
}
Example:
import { CreateTransformer } from "org-press";
// Simple HTML wrapper
const wrapper = CreateTransformer("wrapper", {
onBuild: (input, ctx) => ({
html: `<div class="wrapped">${input.html}</div>`,
}),
});
// With server execution
const serverData = CreateTransformer("serverData", {
onServer: async (code, ctx) => {
const fs = await import("fs/promises");
return JSON.parse(await fs.readFile(code.trim(), "utf-8"));
},
onBuild: (input, ctx) => ({
html: `<pre>${JSON.stringify(input.result)}</pre>`,
}),
});
// With client interactivity
const interactive = CreateTransformer("interactive", {
onBuild: (input, ctx) => ({
html: `<button id="${ctx.id}">Click</button>`,
clientData: { count: 0 },
}),
client: `
export function onMount(el, ctx) {
let count = ctx.data.count;
el.onclick = () => el.textContent = ++count;
}
`,
});
CreateCommand
Create CLI commands for the orgp tool.
function CreateCommand(
name: string,
options: CommandOptions
): OrgPressPlugin;
interface CommandOptions {
/** Command description for help text */
description: string;
/** Command argument definitions */
args?: ArgDefinition[];
/** Execute the command (return exit code) */
execute: (args: ParsedArgs, ctx: CommandContext) => Promise<number>;
}
interface ArgDefinition {
name: string;
type: "string" | "boolean" | "number";
description?: string;
required?: boolean;
default?: string | boolean | number;
alias?: string; // Short flag (e.g., "v" for --verbose)
}
interface ParsedArgs {
[key: string]: string | boolean | number | string[] | undefined;
_: string[]; // Positional arguments
}
interface CommandContext {
config: OrgPressConfig;
projectRoot: string;
contentDir: string;
}
Example:
import { CreateCommand } from "org-press";
const lintCommand = CreateCommand("lint", {
description: "Lint org files for issues",
args: [
{ name: "fix", type: "boolean", alias: "f", description: "Auto-fix" },
{ name: "pattern", type: "string", default: "**/*.org" },
],
execute: async (args, ctx) => {
const fix = args.fix as boolean;
console.log(`Linting in ${ctx.contentDir}`);
// ... lint logic
return 0; // Exit code
},
});
// Usage: orgp lint --fix -pattern "docs/**/*.org"
CreateVitePlugin
Register Vite plugins from org-press plugins.
function CreateVitePlugin(
name: string,
config: VitePluginConfig
): OrgPressPlugin;
interface VitePluginConfig extends Omit<VitePlugin, "name"> {
/** When to run: 'pre' | 'post' | undefined */
enforce?: "pre" | "post";
/** When to apply: 'build' | 'serve' | undefined (both) */
apply?: "build" | "serve";
// ... all other Vite plugin hooks
}
Example:
import { CreateVitePlugin } from "org-press";
// Add virtual module support
const virtualModule = CreateVitePlugin("virtual-config", {
resolveId(id) {
if (id === "virtual:my-config") {
return "\0virtual:my-config";
}
},
load(id) {
if (id === "\0virtual:my-config") {
return `export default ${JSON.stringify({ key: "value" })}`;
}
},
});
// Add custom transform
const customTransform = CreateVitePlugin("my-transform", {
enforce: "pre",
apply: "build",
transform(code, id) {
if (id.endsWith(".special")) {
return transformCode(code);
}
},
});
CreateMiddlewarePlugin
Register dev server middleware for custom API routes.
function CreateMiddlewarePlugin(
path: string,
optionsOrHandler: MiddlewareOptions | MiddlewareHandler
): OrgPressPlugin;
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS";
interface MiddlewareOptions {
/** HTTP methods to handle. Default: all methods */
methods?: HttpMethod[];
/** Handler function */
handler: MiddlewareHandler;
}
type MiddlewareHandler = (
req: IncomingMessage,
res: ServerResponse,
next: () => void
) => void | Promise<void>;
Example:
import { CreateMiddlewarePlugin } from "org-press";
// Simple handler (shorthand)
const pingApi = CreateMiddlewarePlugin("/api/ping", (req, res) => {
res.end("pong");
});
// With method filtering
const dataApi = CreateMiddlewarePlugin("/api/data", {
methods: ["GET", "POST"],
handler: async (req, res, next) => {
if (req.method === "GET") {
res.setHeader("Content-Type", "application/json");
res.end(JSON.stringify({ items: [] }));
} else {
// Handle POST
let body = "";
req.on("data", (chunk) => (body += chunk));
req.on("end", () => {
res.setHeader("Content-Type", "application/json");
res.end(JSON.stringify({ received: JSON.parse(body) }));
});
}
},
});
CreatePlugin
Full control escape hatch for complex plugins.
function CreatePlugin(
name: string,
setup: PluginSetupFunction
): OrgPressPlugin;
type PluginSetupFunction = (ctx: PluginContext) => void | Promise<void>;
Example:
import { CreatePlugin } from "org-press";
const complexPlugin = CreatePlugin("my-plugin", (ctx) => {
// Multiple drawer types
ctx.onDrawer(["NOTE", "TIP"], (drawer) =>
`<aside>${drawer.html}</aside>`
);
// Code block handling
ctx.onBlock("mylang", (block, blockCtx) => ({
html: `<div>${block.value}</div>`,
}));
// CLI command
ctx.addCommand("mycommand", {
description: "Do something",
execute: async () => 0,
});
// Pipeline hooks
ctx.hook("build:start", () => console.log("Building..."));
});
CreateRehypePlugin
Wrap rehype plugins for use in org-press.
function CreateRehypePlugin(
plugin: RehypePlugin,
options?: unknown
): OrgPressPlugin;
Example:
import { CreateRehypePlugin } from "org-press";
import rehypeHighlight from "rehype-highlight";
const highlightPlugin = CreateRehypePlugin(rehypeHighlight, {
languages: { javascript: js, typescript: ts },
});
CreateUniorgPlugin
Wrap uniorg plugins for use in org-press.
function CreateUniorgPlugin(
plugin: UniorgPlugin,
options?: unknown
): OrgPressPlugin;
PluginContext API
The PluginContext is available in CreatePlugin setup functions:
interface PluginContext {
// === Element Handlers ===
/** Register handler for any AST element type */
onElement(type: string, handler: ElementHandler): void;
/** Register drawer handler */
onDrawer(name: string | string[], handler: DrawerHandler): void;
/** Register code block handler */
onBlock(language: string | string[], handler: BlockHandler): void;
// === Pipeline Hooks ===
/** Hook into pipeline stages */
hook(stage: PipelineStage, handler: StageHandler): void;
// === Unified Ecosystem ===
/** Add rehype plugin to render pipeline */
useRehype(plugin: RehypePlugin, options?: unknown): void;
/** Add uniorg plugin to parse pipeline */
useUniorg(plugin: UniorgPlugin, options?: unknown): void;
// === Extensions ===
/** Add CLI command */
addCommand(name: string, options: CommandOptions): void;
/** Add transformer for :use parameter */
addTransformer(name: string, options: TransformerOptions): void;
// === Vite Integration ===
/** Register a Vite plugin */
addVitePlugin(plugin: VitePlugin): void;
/** Register dev server middleware */
addMiddleware(path: string, options: MiddlewareOptions): void;
// === Shared State ===
/** Provide value for other plugins */
provide<T>(key: string, value: T): void;
/** Inject value from another plugin */
inject<T>(key: string): T | undefined;
// === Utilities ===
config: OrgPressConfig;
projectRoot: string;
logger: Logger;
}
Pipeline Stages
Available stages for ctx.hook():
type PipelineStage =
| "parse:before" // Before uniorg parsing
| "parse:after" // After uniorg, before transforms
| "transform:before" // Before element transforms
| "transform:after" // After element transforms
| "render:before" // Before rehype processing
| "render:after" // After HTML generation
| "build:start" // Build started
| "build:end"; // Build finished
interface StagePayload {
stage: PipelineStage;
source?: string; // parse:before
ast?: OrgData; // parse:after, transform:*
html?: string; // render:after
metadata?: Record<string, unknown>; // All stages after parse
}
Plugin Presets
Pre-configured plugin arrays for common setups:
import {
defaultPlugins, // Standard content plugins
minimalPlugins, // Empty array
cliPlugins, // CLI command plugins
allPlugins, // defaultPlugins + cliPlugins
} from "org-press";
defaultPlugins
| Plugin | Description |
|---|---|
domPlugin | DOM rendering for :use dom |
javascriptPlugin | JavaScript/JS handling |
typescriptPlugin | TypeScript/TS handling |
cssPlugin | CSS handling |
serverPlugin | Server-side execution |
cliPlugins
| Plugin | Description |
|---|---|
fmtPlugin | orgp fmt command |
lintPlugin | orgp lint command |
typeCheckPlugin | orgp type-check command |
Usage
// Standard setup
export default {
plugins: [...defaultPlugins],
};
// Add custom plugins
export default {
plugins: [
...defaultPlugins,
CreateDrawer("NOTE", (d) => `<aside>${d.html}</aside>`),
myCustomPlugin,
],
};
// Minimal - full control
export default {
plugins: [
CreateBlock("javascript", { transform: (code) => ({ code }) }),
// Only what you need
],
};
Type Exports
All types are exported from org-press:
import type {
// Core
OrgPressPlugin,
PluginType,
PluginContext,
// Pipeline
PipelineStage,
StagePayload,
StageHandler,
// Nodes
DrawerNode,
CodeBlockNode,
// Transform
TransformContext,
BlockTransformContext,
TransformResult,
// Transformer
TransformerOptions,
TransformerInput,
TransformerOutput,
BuildContext,
ServerContext,
ClientModule,
ClientContext,
// Handlers
ElementHandler,
DrawerHandler,
BlockHandler,
// Command
CommandOptions,
CommandContext,
ArgDefinition,
ParsedArgs,
// Vite/Middleware
VitePluginConfig,
MiddlewareOptions,
MiddlewareHandler,
HttpMethod,
// Ecosystem
RehypePlugin,
UniorgPlugin,
// Utilities
Logger,
OrgPressConfig,
} from "org-press";
See Also
- Creating Plugins - Tutorial with examples
- Modes API - Understanding
:usepipeline - CLI Plugins - CLI command details