# Pandoc Admin & Developer Guide

This guide is for the people who build, deploy, embed, and extend pandoc rather than simply run it: packagers, integrators who call pandoc from a service, developers writing readers/writers/filters, and operators who run `pandoc-server` or the WebAssembly build. It documents pandoc's architecture, build system, configuration surface, security posture, and extension points.

For day-to-day command-line usage, see the companion **User Guide**. This document assumes you are comfortable with the command line, a Haskell toolchain, and document-conversion concepts.

> [!NOTE]
> The pandoc library is at version **3.10** (GPL-2.0-or-later). The repository is a multi-package Haskell project: the core library plus three companion packages (`pandoc-cli`, `pandoc-server`, `pandoc-lua-engine`) and two vendored libraries (`citeproc`, `xml-light`).

---

## 1. Executive Summary

Pandoc is a Haskell library and command-line tool that converts documents between dozens of markup and word-processing formats. Its defining architectural idea is a **single intermediate representation** — the *Pandoc abstract syntax tree* (AST) — that decouples input parsing from output rendering. Every input format has a *reader* that produces the AST; every output format has a *writer* that consumes it. As a result, supporting N input and M output formats requires N + M components, not N × M converters.

| Attribute | Value |
|-----------|-------|
| Language | Haskell |
| Library version | 3.10 |
| License | GPL-2.0-or-later |
| Build system | Cabal (`cabal-version: 2.4`), also Stack |
| Tested compilers | GHC 9.6.7, 9.8.4, 9.10.3, 9.12.2 |
| Packages in repo | `pandoc`, `pandoc-cli`, `pandoc-server`, `pandoc-lua-engine` (+ vendored `citeproc`, `xml-light`) |
| Core library modules | ~200 under `Text.Pandoc.*` |
| Runtime model | Pure conversion pipeline; no daemon required (optional HTTP server) |
| Scripting | Embedded Lua engine for filters and custom readers/writers |

> [!IMPORTANT]
> Pandoc itself does not generate PDFs. PDF output is delegated to an external engine (LaTeX, ConTeXt, groff, typst, or an HTML-to-PDF tool). Any deployment that needs PDF must provision that engine separately.

---

## 2. Architecture

### 2.1 The conversion pipeline

```text
   ┌──────────┐   ┌──────────┐   ┌─────────────────┐   ┌──────────┐   ┌──────────┐
   │  INPUT   │→ │  READER  │→ │   Pandoc AST    │→ │  WRITER  │→ │  OUTPUT  │
   │ (bytes/  │   │ (parse)  │   │  Blocks +       │   │ (render) │   │ (bytes/  │
   │  text)   │   │          │   │  Inlines + Meta │   │          │   │  text)   │
   └──────────┘   └──────────┘   └────────┬────────┘   └──────────┘   └──────────┘
                                          │
                            ┌─────────────┴─────────────┐
                            │  TRANSFORMS / FILTERS      │
                            │  • Lua filters             │
                            │  • JSON filters (exec)     │
                            │  • citeproc (citations)    │
                            │  • built-in transforms     │
                            └────────────────────────────┘
```

The AST (`Pandoc Meta [Block]`) is a list of block-level elements (paragraphs, headings, lists, tables, code blocks) containing inline elements (text runs, emphasis, links, math), plus a metadata map. Readers, writers, and filters all speak this one type. The pipeline is a pure function from input bytes to output bytes, wrapped in pandoc's `PandocMonad` for controlled IO (file reads, HTTP fetches, logging).

> [!NOTE]
> Filters, Lua filters, and citation processing are applied in the exact order they appear on the command line. The order is significant when transforms depend on one another's output.

### 2.2 Package layout

The repository is split into cooperating packages (declared in `cabal.project`):

| Package | Directory | Role |
|---------|-----------|------|
| `pandoc` (library) | `src/` | The core library: readers, writers, the AST, the App driver, templates, highlighting glue |
| `pandoc-cli` | `pandoc-cli/` | The `pandoc` executable; wires the library to a command line; can also run as server or REPL |
| `pandoc-server` | `pandoc-server/` | An HTTP conversion service built on Servant/WAI (version 0.1.3) |
| `pandoc-lua-engine` | `pandoc-lua-engine/` | The Lua scripting engine for filters and custom readers/writers |
| `citeproc` | `citeproc/` | Vendored Citation Style Language (CSL) processor |
| `xml-light` | `xml-light/` | Vendored lightweight XML parser used by XML-based readers/writers |

This separation lets downstream users depend on only what they need — for example, a service that converts in-process can depend on the `pandoc` library and `pandoc-lua-engine` without pulling in the CLI or the HTTP server.

### 2.3 The CLI driver

The command-line entry point lives in `Text.Pandoc.App` (`src/Text/Pandoc/App.hs`). Its public surface includes:

| Symbol | Purpose |
|--------|---------|
| `convertWithOpts :: Opt -> PandocIO ()` | Run a full conversion from a parsed options record |
| `Opt(..)` | The complete set of conversion options (every CLI flag has a field) |
| `options` | The option parser specification (GetOpt descriptors) |
| `parseOptions` / `parseOptionsFromArgs` | Parse argv into an `Opt` |
| `applyFilters` | Apply the configured filter chain to the AST |
| `defaultOpts` | The default option record |
| `versionInfo` | The `--version` banner contents |

The actual flag parsing and the `Opt` record are factored into the `Text.Pandoc.App.Opt` and `Text.Pandoc.App.CommandLineOptions` submodules under `src/Text/Pandoc/App/`.

---

## 3. Repository Structure

```text
pandoc/
├── src/Text/Pandoc/          Core library (~200 modules)
│   ├── App.hs                CLI driver: convertWithOpts, options
│   ├── App/                  Option record + command-line parsing
│   ├── Readers/              One module per input format (Markdown, LaTeX,
│   │                         Docx, ODT, HTML, Org, RST, Typst, …)
│   ├── Writers/              One module per output format (HTML, LaTeX,
│   │                         Docx, Powerpoint, Markdown, JATS, …)
│   ├── Parsing/              Shared parser combinators
│   ├── Citeproc/             Bridge to the citeproc library
│   ├── Class/                PandocMonad: controlled IO abstraction
│   └── Data/                 Bundled data-file access
├── pandoc-cli/               The pandoc executable
│   ├── src/                  Main entry, dispatch to server/lua/repl
│   └── (build variants: server, no-server, lua, no-lua, wasm)
├── pandoc-server/            HTTP server (Servant/WAI)
├── pandoc-lua-engine/        Lua filter & scripting engine
├── citeproc/                 Vendored CSL processor + localizations
├── xml-light/                Vendored XML parser
├── data/                     Templates, translations, reference docs
│   ├── templates/            Default templates per output format
│   ├── translations/         UI-string localizations (107 locales)
│   ├── reference.docx/.odt/.pptx   Style reference documents
│   └── *.lua, abbreviations, init.lua
├── man/                      Man-page sources
├── wasm/                     WebAssembly build (JS glue, examples, patches)
├── test/                     Test suite (command tests, golden files)
├── benchmark/                Performance benchmarks
├── linux/ macos/ windows/    Platform packaging scripts
├── pandoc.cabal              Library + test + benchmark definitions
├── cabal.project             Multi-package + wasm build configuration
├── stack.yaml                Stack build configuration
└── MANUAL.txt                The authoritative user manual (source of MANUAL.html)
```

### 3.1 The `data/` directory

Everything in `data/` ships with pandoc and is discoverable at runtime through the user data directory or (when compiled with `embed_data_files`) baked into the binary:

- **`templates/`** — the default standalone template for each output format. Inspect any with `pandoc -D FORMAT`.
- **`translations/`** — localized UI strings (e.g. "Figure", "Table of Contents") for 107 locales, selected via the `lang` variable.
- **`reference.docx` / `reference.odt` / `reference.pptx`** — the style templates for Office output. Extract with `pandoc --print-default-data-file reference.docx`.
- **`init.lua`** — the Lua init script run when the scripting engine starts.

---

## 4. System Requirements

### 4.1 Runtime

The released binaries are **statically linked** and have no dynamic dependencies or external data-file requirements. The only optional runtime dependencies are the external tools pandoc shells out to:

| Capability | External requirement |
|------------|----------------------|
| PDF via LaTeX | A TeX distribution: TeX Live, MiKTeX, BasicTeX, or TinyTeX |
| PDF via HTML | `weasyprint`, `prince`, `wkhtmltopdf`, or `pagedjs-cli` |
| PDF via ConTeXt / ms / typst | `context`, `groff`/`pdfroff`, or `typst` |
| SVG in formats without SVG support | `rsvg-convert` (from librsvg) |
| JSON filters | The interpreter for the filter's language (e.g. Python) |

> [!WARNING]
> The statically-linked binaries (and Conda Forge builds) **cannot load Lua filters that depend on C-based Lua modules**. Deployments needing those must use a dynamically-linked build compiled from source.

### 4.2 Build toolchain

| Tool | Minimum |
|------|---------|
| GHC | 9.6.7 (tested up to 9.12.2) |
| Cabal | 2.0+ (`cabal-version: 2.4` in the project) |
| Stack | 1.7.0+ (alternative to Cabal) |

---

## 5. Building From Source

Build the executable, not the bare library, by targeting `pandoc-cli`.

### 5.1 Stack

```bash
git clone https://github.com/jgm/pandoc
cd pandoc
stack setup            # downloads the right GHC if needed
stack install pandoc-cli
```

`stack install` places the `pandoc` binary in `~/.local/bin`; add it to your `PATH`.

### 5.2 Cabal

```bash
cabal update
cabal install pandoc-cli      # released version from Hackage
```

To build the local (development) tree instead, run the command from inside the source directory — cabal uses the `cabal.project` packages.

### 5.3 Custom build (for packagers)

```bash
cabal update
cabal build --only-dependencies
cabal configure --flags=FLAGSPEC --enable-tests
cabal build
cabal test
cabal install pandoc-cli
```

### 5.4 Build flags

Flags are toggled with `+flag` / `-flag` in `cabal configure --flags=...`, in `cabal.project`'s `package` stanzas, or with `--flag pandoc:embed_data_files` under Stack.

**`pandoc` library flags:**

| Flag | Default | Effect |
|------|---------|--------|
| `embed_data_files` | off | Bake all `data/` files into the binary, producing a relocatable, self-contained executable |
| `http` | on | Include HTTP support for fetching remote inputs/resources |

**`pandoc-cli` flags:**

| Flag | Default | Effect |
|------|---------|--------|
| `lua` | on | Compile in Lua filter and custom-writer support (links `pandoc-lua-engine`) |
| `server` | on | Compile in HTTP server mode (active when the binary is named/symlinked `pandoc-server`) |
| `repl` | on | Compile in the Lua REPL |
| `nightly` | off | Stamp the build with nightly version metadata |

> [!TIP]
> For a fully relocatable binary, build with `embed_data_files`: `cabal build -fembed_data_files` or `stack build --flag pandoc:embed_data_files`. This is also the recommended build for running under `--sandbox`, since data-file lookups then succeed without filesystem access.

### 5.5 Running tests and benchmarks

```bash
cabal test                                   # full suite
cabal test --test-options='-p markdown'      # only tests matching "markdown"
cabal test --test-options='-j4 --hide-successes'
```

```bash
cabal configure --enable-benchmarks && cabal build
cabal bench
cabal bench --benchmark-options='markdown -s 20'
```

The test driver is `test/test-pandoc.hs`. Format conversions are largely tested via **command tests** (`test/command/`) — each file pairs an invocation with its expected output — and **golden files** under format-specific subdirectories (`test/docx/`, `test/odt/`, `test/pptx/`, etc.).

---

## 6. Embedding the Library

To convert documents in-process from Haskell, depend on the `pandoc` library and use the high-level API from the top-level `Text.Pandoc` module. A conversion runs inside `PandocMonad` (typically `runIO`):

```haskell
import Text.Pandoc

main :: IO ()
main = do
  result <- runIO $ do
    doc <- readMarkdown def "# Hello *world*"
    writeHtml5String def doc
  html <- handleError result
  putStrLn (show html)
```

Key library entry points:

| Module | Provides |
|--------|----------|
| `Text.Pandoc` | Re-exports readers, writers, options, and the monad |
| `Text.Pandoc.Readers.*` | `readMarkdown`, `readLaTeX`, `readDocx`, … |
| `Text.Pandoc.Writers.*` | `writeHtml5String`, `writeLaTeX`, `writeDocx`, … |
| `Text.Pandoc.Class` | `PandocMonad`, `runIO`, `runPure` (sandboxed, no IO) |
| `Text.Pandoc.App` | `convertWithOpts` for a full CLI-equivalent run |
| `Text.Pandoc.JSON` | `toJSONFilter` for building JSON filters in Haskell |

> [!NOTE]
> `runPure` runs a conversion with no IO at all — useful for safely converting untrusted input or for testing. `runIO` permits controlled IO (file reads, HTTP, logging) mediated by `PandocMonad`.

---

## 7. Deploying `pandoc-server`

The `pandoc-server` package (version 0.1.3) exposes pandoc conversion over HTTP using the Servant framework on WAI. The same functionality is built into the `pandoc` binary when compiled with the `server` flag and is activated by invoking the binary as `pandoc-server`.

### 7.1 Server options

From `Text.Pandoc.Server` (`pandoc-server/src/Text/Pandoc/Server.hs`):

| Option | Flag | Default | Meaning |
|--------|------|---------|---------|
| Port | `-p` / `--port` | `3030` | TCP port to listen on |
| Timeout | `-t` / `--timeout` | `2` | Per-request timeout in seconds |

```bash
# Run the server (binary built/symlinked as pandoc-server)
pandoc-server --port 3030 --timeout 5
```

The server defines a Servant `API` and a WAI `app`. Requests carry a JSON `Params` body describing the conversion (input text or base64 `Blob`, source/target formats, options); the response is the converted document.

### 7.2 Operational characteristics

- **Stateless.** Each request is an independent pure conversion. Scale horizontally behind a load balancer; no shared state or database.
- **CORS.** The server installs WAI CORS middleware, so browser clients can call it cross-origin.
- **Short default timeout.** The 2-second default protects against pathological inputs; raise it deliberately for large documents.

> [!CAUTION]
> A conversion server accepts arbitrary documents from clients. Treat every request as untrusted input. The server performs conversions in a constrained manner, but you remain responsible for resource limits (request size, concurrency, timeout) and for not enabling filters or PDF engines that reach the network or filesystem on a public endpoint. See section 9.

---

## 8. WebAssembly Build

Pandoc compiles to WebAssembly (`wasm32`) for in-browser conversion, powering the online demo. The wasm configuration lives in `cabal.project` (guarded by `if arch(wasm32)`) and the `wasm/` directory.

Notable wasm build choices:

- Tests are disabled (`tests: False`).
- The CLI is built with `+lua -repl -server` and the library with `+embed_data_files -http` — no HTTP, no server, but Lua filters and embedded data are retained.
- Several dependencies are pulled from patched Git forks (`wasm/patches/*.patch`) to work under the WASI/wasm32 toolchain (conduit-extra, streaming-commons, xml-conduit, splitmix, hslua, and a custom Lua build with stubbed `tmpnam`/`tmpfile`/`system`).
- `wasm/index.js` provides the JavaScript glue; `wasm/examples/` contains ready-made conversion demos (e.g. markdown-to-revealjs, docx-with-equations-to-latex).

> [!NOTE]
> The wasm build is a specialized target. Most integrators want the native library or `pandoc-server` instead; reach for wasm only when conversion must run client-side in a browser sandbox.

---

## 9. Security Analysis

Pandoc's threat model centers on **processing untrusted documents**. The relevant controls:

### 9.1 Sandbox mode

`--sandbox` (or `sandbox: true` in a defaults file; `runPure` in the library) limits the IO that readers and writers may perform to the files named on the command line. This blocks attacks such as exfiltrating local files through `include` directives in the source document.

```bash
pandoc --sandbox untrusted.md -o out.html
```

> [!CAUTION]
> `--sandbox` does **not** constrain:
> - **Filters** — JSON and Lua filters run with full process privileges. Do not enable user-supplied filters on untrusted input.
> - **PDF engines** — the external engine runs unsandboxed. Generating PDFs from user-controlled HTML can enable server-side request forgery (SSRF) through the engine's resource fetching. If you must do this, isolate the engine (no network, restricted filesystem) at the OS/container level.

### 9.2 Network access

Pandoc fetches remote inputs and resources over HTTP when given URLs or when `--embed-resources` downloads assets. On a server or for untrusted input, consider building with `-http` (disabling HTTP support) or running in `--sandbox`, and restrict egress at the network layer. `--no-check-certificate` disables TLS verification — never enable it for untrusted or production fetches.

### 9.3 Data-file lookups under sandbox

Some readers/writers (notably `docx`) need bundled data files. Under `--sandbox`, filesystem lookups fail. Compile with `embed_data_files` so the data is baked into the binary and the sandbox still works.

### 9.4 Reporting

Security issues are reported privately per `SECURITY.md` in the repository, not through public issues.

### 9.5 Failure modes as signals

Pandoc fails closed with a specific nonzero exit code (see section 12). In automation, treat any nonzero exit as a failed conversion and inspect the code — for example, code 47 (PDF program not found) versus 64 (parse error) call for very different responses.

---

## 10. Configuration Surface

Pandoc has no central config file; configuration is layered from three sources, later sources overriding earlier ones:

1. **The user data directory** — bundled and user-overridable resources.
2. **Defaults files** — reusable YAML/JSON option sets (`-d`/`--defaults`).
3. **Command-line options and document metadata** — highest precedence.

### 10.1 The user data directory

Resources placed here override pandoc's built-in defaults. Default locations:

| Platform | Default user data directory |
|----------|------------------------------|
| *nix / macOS | `$XDG_DATA_HOME/pandoc` (i.e. `$HOME/.local/share/pandoc`), falling back to `$HOME/.pandoc` |
| Windows | `%APPDATA%\pandoc` |

Override per run with `--data-dir`. Confirm the active directory with `pandoc --version`. Recognized subdirectories and files include `templates/`, `defaults/`, `filters/`, `metadata/`, `csl/`, and override copies of `reference.docx`, `reference.odt`, `epub.css`, and `abbreviations`.

> [!NOTE]
> Pandoc does **not** create the user data directory for you. Create it yourself before dropping in overrides.

### 10.2 Defaults files

A defaults file maps almost every command-line option to a YAML key. Store frequently used option sets and invoke them by name:

```yaml
# ~/.local/share/pandoc/defaults/report.yaml
from: markdown
to: pdf
pdf-engine: xelatex
standalone: true
number-sections: true
toc: true
toc-depth: 2
variables:
  geometry: margin=1in
  fontsize: 11pt
verbosity: INFO
```

```bash
pandoc input.md -dreport -o report.pdf
```

Path fields support `${HOME}`, `${USERDATA}`, and `${.}` (the defaults file's own directory) interpolation. Repeatable options (`--css`, `--metadata-file`, `--include-in-header`, `--variable`, …) combine with, rather than replace, command-line values.

### 10.3 Templates and reference documents

- **Templates** drive standalone output. Print the default with `pandoc -D FORMAT`; override by placing a file in `templates/` or passing `--template`.
- **Reference documents** (`reference.docx`, `reference.odt`, `reference.pptx`) drive the styling of Office output. Extract the defaults with `--print-default-data-file`, edit the styles, and supply with `--reference-doc`.

---

## 11. Extending Pandoc

### 11.1 Filters

The lowest-friction extension point. A filter transforms the AST between reading and writing:

- **Lua filters** (`-L`/`--lua-filter`) run on the built-in engine; no external dependency. Each filter maps AST element names to transforming functions.
- **JSON filters** (`-F`/`--filter`) are external executables reading/writing the AST as JSON. Writable in any language; the target format is passed as `argv[1]`. In Haskell, `Text.Pandoc.JSON.toJSONFilter` builds one.

Filter lookup order: explicit path → `$DATADIR/filters` → `$PATH` (executables only).

### 11.2 Custom readers and writers

Beyond the built-in formats, pandoc can load a **custom reader or writer written in Lua** by passing the script path as the `-f`/`-t` format. This lets you support a new format without recompiling, by implementing the parse or render logic in Lua against pandoc's AST.

### 11.3 Adding a built-in format

To add a first-class format, add a module under `src/Text/Pandoc/Readers/` or `Writers/`, wire it into the format registry, and add tests (golden files under `test/` and/or command tests under `test/command/`). Each reader produces the AST; each writer consumes it — the modular design means no other component changes.

---

## 12. Exit Codes Reference

Pandoc returns `0` on success and a specific code on failure. Use these in automation to distinguish failure classes:

| Code | Constructor | Code | Constructor |
|------|-------------|------|-------------|
| 1 | PandocIOError | 47 | PandocPDFProgramNotFoundError |
| 3 | PandocFailOnWarningError | 61 | PandocHttpError |
| 4 | PandocAppError | 62 | PandocShouldNeverHappenError |
| 5 | PandocTemplateError | 63 | PandocSomeError |
| 6 | PandocOptionError | 64 | PandocParseError |
| 21 | PandocUnknownReaderError | 66 | PandocMakePDFError |
| 22 | PandocUnknownWriterError | 67 | PandocSyntaxMapError |
| 23 | PandocUnsupportedExtensionError | 83 | PandocFilterError |
| 24 | PandocCiteprocError | 84 | PandocLuaError |
| 25 | PandocBibliographyError | 89 | PandocNoScriptingEngine |
| 31 | PandocEpubSubdirectoryError | 91 | PandocMacroLoop |
| 43 | PandocPDFError | 92 | PandocUTF8DecodingError |
| 44 | PandocXMLError | 93 | PandocIpynbDecodingError |
| — | — | 99 | PandocResourceNotFound |

---

## 13. Operations Playbook

### 13.1 Verifying a deployment

```bash
pandoc --version                       # version, features, data dir
pandoc --list-input-formats | wc -l    # reader count sanity check
echo '# ok' | pandoc -t html           # smoke-test a conversion
```

### 13.2 Provisioning for PDF

Confirm the chosen engine is on `PATH` before enabling PDF jobs. For LaTeX, install missing packages with your TeX manager (e.g. `tlmgr install collection-fontsrecommended`). For HTML-based PDF, install WeasyPrint/Prince/wkhtmltopdf and select it with `--pdf-engine`.

### 13.3 CI integration

- Use `--fail-if-warnings` to make conversions fail loudly (exit code 3).
- Use `--log=FILE` to capture machine-readable JSON logs for build artifacts.
- Pin a pandoc version; behavior and default extensions evolve between releases.
- Official Docker images (`pandoc/core`, `pandoc/latex`) and GitHub Actions / GitLab CI examples exist for pipeline use.

### 13.4 Performance

Released binaries are compiled with `-threaded` and the RTS option `-A8m` (8 MB allocation area). For very large documents, the dominant cost is usually parsing and the external PDF engine, not pandoc's rendering. Benchmark with the in-repo `cabal bench` suite when evaluating regressions.

---

## 14. Code Quality & Conventions

- **Style.** The project enforces formatting with `stylish-haskell` (`.stylish-haskell.yaml`) and lint rules with HLint (`.hlint.yaml`); `.editorconfig` standardizes whitespace.
- **Dead-code detection.** `weeder.toml` configures Weeder to find unused exports.
- **Module discipline.** One reader/writer per format keeps the surface area predictable; shared logic lives in `Parsing/`, `Writers/Shared`, and `Readers/`-level helpers.
- **Controlled IO.** All IO flows through `PandocMonad`, enabling both real-IO (`runIO`) and pure (`runPure`) execution from the same code — central to sandboxing and testability.
- **Testing strategy.** Heavy use of golden tests and declarative command tests (`test/command/`) means most format behavior is pinned to expected output, making regressions easy to catch.

---

## 15. Potential Improvements

Drawn from the project's open issue tracker at the documented commit — these are active areas, useful context for contributors and integrators:

| Theme | Representative open issues |
|-------|---------------------------|
| Typst writer fidelity | `lang` attribute propagation on spans (#11673); EPUB→PDF via the typst engine (#11626) |
| Org mode reader | Use code (`~`) vs verbatim (`=`) markers (#11655) |
| New format support | Atlassian Document Format (ADF) reader/writer for Confluence Cloud (#9898) |
| Markdown lists | Mixing incremental and non-incremental list types (#11653) |
| HTML output | Lazy-loading images (`loading="lazy"`) (#6197) |
| Word/ODT styling | List paragraphs using "List Paragraph" vs "Normal" style (#10974) |

> [!TIP]
> The modular reader/writer architecture means most of these are localized changes — a single writer module plus tests — rather than cross-cutting work. The format registry and the golden-test layout are the two touch points a contributor must learn first.

---

## 16. Quick Reference

### Build

| Task | Command |
|------|---------|
| Build with Stack | `stack install pandoc-cli` |
| Build with Cabal | `cabal install pandoc-cli` |
| Relocatable binary | `cabal build -fembed_data_files` |
| Run tests | `cabal test` |
| Run a subset of tests | `cabal test --test-options='-p PATTERN'` |
| Run benchmarks | `cabal bench` |

### Server

| Task | Command |
|------|---------|
| Start server | `pandoc-server --port 3030 --timeout 5` |
| Default port / timeout | `3030` / `2s` |

### Configuration

| Item | Where |
|------|-------|
| User data dir (*nix) | `$HOME/.local/share/pandoc` |
| User data dir (Windows) | `%APPDATA%\pandoc` |
| Override data dir | `--data-dir=DIR` |
| Defaults files | `<data-dir>/defaults/*.yaml`, used via `-dNAME` |
| Inspect default template | `pandoc -D FORMAT` |
| Extract a data file | `pandoc --print-default-data-file=FILE` |

### Security

| Goal | Action |
|------|--------|
| Process untrusted input | `--sandbox` (+ `embed_data_files` build) |
| Disable HTTP support | build with `-http` |
| Make warnings fatal | `--fail-if-warnings` |
| Pure, no-IO conversion (library) | `runPure` |

---

_Generated June 2026 from jgm/pandoc at 9376458. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
