⚠️Early Alpha — Org-press is experimental. Perfect for hackers and tinkerers, not ready for production. Documentation may be incomplete or inaccurate.

Modes API

The Modes API provides a unified, composable system for block rendering in org-press.

Overview

The Modes API provides a clean, pipe-based syntax for controlling block rendering:

#+begin_src javascript :use dom | withSourceCode
console.log("Hello World");
#+end_src

Key Concepts

Mode Plugins

Mode plugins control the base rendering behavior. They are built-in plugins included in builtinPlugins by default:

ModeDescription
domExecute code and show results (default)
sourceOnlyShow source code only, no execution
silentExecute but don't show output
rawExecute and output raw result
serverExecute on server during SSR/build

These are implemented as plugins (domPlugin, sourceOnlyPlugin, silentPlugin, rawPlugin) with higher priority than language plugins, so they match first when you specify :use dom etc.

Wrappers

Wrappers transform the render output. They can be chained using the pipe syntax:

:use dom | withSourceCode | withContainer?class=my-class

Built-in Wrappers

WrapperDescription
withSourceCodeShow both source code and result
withContainerWrap output in a container div
withErrorBoundaryCatch and display errors gracefully
withConsoleCapture and display console output
withCollapseMake output collapsible

Format Wrappers

For server execution, format wrappers format the output:

FormatDescription
jsonFormat output as JSON
yamlFormat output as YAML
csvFormat output as CSV
htmlOutput raw HTML

Syntax

Basic Usage

#+begin_src javascript :use dom
// Execute and show result
"Hello World"
#+end_src

#+begin_src javascript :use sourceOnly
// Show code only
const x = 1;
#+end_src

#+begin_src javascript :use silent
// Execute but don't show
console.log("silent");
#+end_src

With Wrappers

#+begin_src javascript :use dom | withSourceCode
// Show both code and result
1 + 1
#+end_src

#+begin_src javascript :use dom | withSourceCode?position=before
// Source code shown before result
1 + 1
#+end_src

#+begin_src javascript :use dom | withConsole | withSourceCode
// Show console output, then code and result
console.log("Hello");
"World"
#+end_src

Server Execution

#+begin_src javascript :use server
// Runs at build time
const fs = require('fs');
return fs.readFileSync('package.json', 'utf8');
#+end_src

#+begin_src javascript :use server | json
// Format result as JSON
return { message: "Hello" };
#+end_src

Configuration

Default Mode

Set a default mode for all blocks in your config:

// .org-press/config.js
export default {
  defaultUse: "dom | withErrorBoundary"
};

Language Defaults

Set different defaults per language:

// .org-press/config.js
export default {
  languageDefaults: {
    javascript: "dom",
    typescript: "dom | withErrorBoundary",
    python: "sourceOnly"
  }
};

Custom Render Functions

Plugins can export a render function to customize rendering:

// In a code block or plugin
export const render = (result, ctx) => {
  return {
    html: `<div class="custom-render">${result}</div>`,
    css: `.custom-render { background: #f0f0f0; }`
  };
};

RenderFn Signature

type RenderFn = (result: unknown, ctx: BlockContext) => RenderResult;

interface BlockContext {
  language: string;
  code: string;
  blockIndex: number;
  blockName?: string;
  parameters: Record<string, string>;
}

interface RenderResult {
  html: string;
  css?: string;
  js?: string;
}

Creating Custom Wrappers

Wrappers follow the pattern: (config?) => (render) => RenderFn

import { registerWrapper } from 'org-press';

// Simple wrapper (no config)
const myWrapper = (render) => (result, ctx) => {
  const inner = render(result, ctx);
  return {
    html: `<div class="my-wrapper">${inner.html}</div>`,
    css: inner.css
  };
};

// Configurable wrapper
const myConfigurableWrapper = (config = {}) => (render) => (result, ctx) => {
  const inner = render(result, ctx);
  return {
    html: `<div class="${config.class || 'default'}">${inner.html}</div>`
  };
};

// Register wrappers
registerWrapper('myWrapper', myWrapper);
registerWrapper('myConfigurable', myConfigurableWrapper);

Usage:

#+begin_src javascript :use dom | myWrapper
"Hello"
#+end_src

#+begin_src javascript :use dom | myConfigurable?class=custom-class
"Hello"
#+end_src

Migration from Legacy System

If you're migrating from the old :exports system:

Old SyntaxNew Syntax
:exports code:use sourceOnly
:exports results:use dom
:exports both~:use domwithSourceCode~
:exports none:use silent