Metadata-Version: 2.4
Name: mkdocs-typer2
Version: 0.4.0
Summary: Typer CLI docs for MkDocs (optional) and Zensical via Python-Markdown
License-File: LICENSE
Requires-Python: >=3.10
Requires-Dist: markdown<4,>=3.3.6
Requires-Dist: pydantic>=2.9.2
Requires-Dist: typer>=0.12.5
Provides-Extra: mkdocs
Requires-Dist: mkdocs<2,>=1.6.1; extra == 'mkdocs'
Provides-Extra: termynal
Requires-Dist: ansi2html>=1.8; extra == 'termynal'
Requires-Dist: termynal<1,>=0.12; extra == 'termynal'
Provides-Extra: zensical
Requires-Dist: zensical<1,>=0.0.30; extra == 'zensical'
Description-Content-Type: text/markdown

# mkdocs-typer2

[![PyTest](https://img.shields.io/badge/Pytest-0A9EDC?style=for-the-badge&logo=pytest&logoColor=white)](https://docs.pytest.org/)
[![Ruff](https://img.shields.io/badge/Ruff-FFC107?style=for-the-badge&logo=python&logoColor=black)](https://docs.astral.sh/ruff/)
[![MkDocs](https://img.shields.io/badge/MkDocs-000000?style=for-the-badge&logo=markdown&logoColor=white)](https://www.mkdocs.org/)
[![Typer](https://img.shields.io/badge/Typer-FF4B4B?style=for-the-badge&logo=python&logoColor=white)](https://typer.tiangolo.com/)
[![UV](https://img.shields.io/badge/UV-2C2C2C?style=for-the-badge&logo=python&logoColor=white)](https://github.com/astral-sh/uv)
[![Python](https://img.shields.io/badge/Python-3.10%20|%203.11%20|%203.12|%203.13%20|%203.14-3776AB?style=for-the-badge&logo=python&logoColor=white)](https://www.python.org/)
[![PyPI](https://img.shields.io/pypi/v/mkdocs-typer2?style=for-the-badge)](https://pypi.org/project/mkdocs-typer2/)
[![License](https://img.shields.io/badge/License-Apache_2.0-D22128?style=for-the-badge&logo=apache&logoColor=white)](https://opensource.org/licenses/Apache-2.0)
[![Downloads](https://img.shields.io/pepy/dt/mkdocs-typer2?style=for-the-badge)](https://pepy.tech/project/mkdocs-typer2)
[![Codecov](https://img.shields.io/codecov/c/github/syn54x/mkdocs-typer2?style=for-the-badge&logo=codecov&logoColor=white)](https://codecov.io/gh/syn54x/mkdocs-typer2)
[![Issues](https://img.shields.io/github/issues/syn54x/mkdocs-typer2?style=for-the-badge&logo=github&logoColor=white)](https://github.com/syn54x/mkdocs-typer2/issues)

A Python-Markdown extension (and optional MkDocs plugin) that automatically generates documentation for your Typer CLI applications. The same extension works with [Zensical](https://zensical.org/) using `markdown_extensions` only.

You might be wondering why there are two plugins for Typer. The [`mkdocs-typer`](https://github.com/bruce-szalwinski/mkdocs-typer) plugin is great, but it hasn't been updated in over a year, and there have been a number of changes to Typer since then. One important change is that Typer now has its own documentation generation system via the `typer <module> utils docs` command. This plugin simply leverages that system to generate the documentation for your Typer CLIs.

I created this plugin because the original plugin was no longer working for me, and I wanted to have a simple plugin that would work with the latest version of Typer. If the original `mkdocs-typer` plugin still works for you, there probably isn't a reason to switch. However, if you are looking for a plugin that will work with the latest version of Typer, this plugin is for you!

- [Read The Docs](https://syn54x.github.io/mkdocs-typer2/)
- [Check out a demo](https://syn54x.github.io/mkdocs-typer2/cli)

## Features

- Integrates with MkDocs (optional extra) and the Material theme, or with Zensical via Markdown extensions
- Automatically generates CLI documentation from your Typer commands
- Supports all Typer command features including arguments, options, and help text
- Easy to configure and use
- `pretty` feature for formatting arguments & options as tables
- `engine` option to select legacy markdown parsing or native Click walking
- `termynal` output mode that renders `--help` as an animated, colored terminal
- Global plugin configuration or per-documentation block configuration

## How It Works

The plugin can either parse Typer's generated markdown (legacy) or walk the Click command tree directly (native). Both approaches are rendered as Markdown and integrated into your MkDocs site.

The plugin works by:

1. Registering a Markdown extension that processes special directive blocks
2. Resolving the command tree (legacy: `typer <module> utils docs`, native: Click walk)
3. Formatting arguments and options as lists or tables based on `pretty`
4. Integrating the resulting HTML into the generated site

## Installation

The base package installs the Typer CLI helper, the **Python-Markdown** extension (`mkdocs_typer2.markdown:makeExtension`), and runtime dependencies only. Add MkDocs and/or Zensical when you need them.

**Markdown extension only** (for example with Zensical, or if you register the extension yourself):

```bash
pip install mkdocs-typer2
```

**With MkDocs** (enables the `mkdocs-typer2` plugin entry point):

```bash
pip install "mkdocs-typer2[mkdocs]"
```

**With Zensical** (installs the `zensical` CLI into the same environment; you still configure `markdown_extensions` as shown below):

```bash
pip install "mkdocs-typer2[zensical]"
```

**Both**:

```bash
pip install "mkdocs-typer2[mkdocs,zensical]"
```

Using uv:

```bash
uv add "mkdocs-typer2[mkdocs]"   # or [zensical] / [mkdocs,zensical]
```

### Requirements

- Python 3.10 or higher
- **Always:** Typer 0.12.5 or higher, Pydantic 2.9.2 or higher, Python-Markdown 3.3.6 or higher (declared as `markdown` on PyPI)
- **Optional:** MkDocs 1.6.1 or higher (install extra `[mkdocs]`)
- **Optional:** Zensical 0.0.30 or higher (install extra `[zensical]`)

## Configuration

### MkDocs

Add the plugin to your `mkdocs.yml` file:

```yaml
plugins:
  - mkdocs-typer2
```

### Pretty Mode

The plugin offers a `pretty` option that can be set in your `mkdocs.yml` file to enable table-based formatting for options and arguments:

```yaml
plugins:
  - mkdocs-typer2:
      pretty: true
```

**Options when `:pretty: false`:**


**Options**:
* `--name`: The name of the project  [required]

**Options when `:pretty: true`:**

| Name | Description | Required | Default |
| --- | --- | --- | --- |
| `--name` | The name of the project | Yes | - |


### Engine Selection

Use `engine` to select how the command tree is built:

```yaml
plugins:
  - mkdocs-typer2:
      engine: native  # or legacy
```

### Zensical

Zensical uses the same Python-Markdown stack as MkDocs for compatibility, so you enable this project **as a Markdown extension** only. Zensical does not run arbitrary MkDocs Python plugins, so do not list `mkdocs-typer2` under `plugins`.

Install with `pip install "mkdocs-typer2[zensical]"` (or include `zensical` in your environment another way), then register the extension and options that match what you would pass to the MkDocs plugin.

**`mkdocs.yml`** (Zensical reads this format):

```yaml
markdown_extensions:
  - tables
  - mkdocs_typer2.markdown:makeExtension:
      pretty: false
      engine: native
```

The `tables` extension is included here because the extension renders inner CLI markdown with `markdown.markdown(..., extensions=["tables"])`.

**`zensical.toml`** (quoted table key because the factory path contains a colon):

```toml
[project.markdown_extensions.tables]

[project.markdown_extensions."mkdocs_typer2.markdown:makeExtension"]
pretty = false
engine = "native"
```

If you share one project between MkDocs and Zensical, keep `mkdocs-typer2` out of `plugins` for the Zensical-focused config (or use separate config files) so the Markdown extension is not applied twice.

#### Termynal assets under Zensical

The `:termynal:` output mode only emits termynal's `data-termynal` markup; the CSS/JS that styles and animates it is shipped separately. Under MkDocs the `termynal` plugin injects them, but **Zensical does not run that plugin**, so the blocks render as unstyled text unless you add the assets yourself.

The simplest way is to point `extra_css` / `extra_javascript` at termynal's assets on a CDN. Pin the version to the `termynal` you installed (`pip show termynal`) so the assets match the markup this extension emits:

**`mkdocs.yml`:**

```yaml
extra_css:
  - https://cdn.jsdelivr.net/gh/termynal/termynal.py@0.14.0/termynal/assets/termynal.css
extra_javascript:
  - https://cdn.jsdelivr.net/gh/termynal/termynal.py@0.14.0/termynal/assets/termynal.js
```

**`zensical.toml`:**

```toml
[project]
extra_css = ["https://cdn.jsdelivr.net/gh/termynal/termynal.py@0.14.0/termynal/assets/termynal.css"]
extra_javascript = ["https://cdn.jsdelivr.net/gh/termynal/termynal.py@0.14.0/termynal/assets/termynal.js"]
```

To self-host instead, copy `termynal.css` / `termynal.js` from the installed `termynal` package's `assets/` directory into your docs tree and reference them by relative path.

Do **not** inline the CSS/JS into page content (Zensical folds raw `<style>` text into the page title/heading). Use `extra_css` / `extra_javascript` so the assets load in the page head/footer as intended.

## Usage

### Basic Usage

In your Markdown files, use the `::: mkdocs-typer2` directive to generate documentation for your Typer CLI:

```markdown
::: mkdocs-typer2
    :module: my_module
    :name: mycli
```

### Required Parameters

- `:module:` - The module containing your Typer CLI application. This is the *installed* module, not the directory path. For example, if your app is located in `src/my_module/cli.py`, your `:module:` should typically be `my_module.cli`.

### Optional Parameters

- `:name:` - The name of the CLI. If left blank, your CLI will simply be named `CLI` in your documentation.
- `:pretty:` - Set to `true` to enable pretty formatting for this specific documentation block, overriding the global setting.
- `:engine:` - `legacy` parses Typer markdown (deprecated). `native` walks Click and renders lists or tables based on `pretty`.
- `:termynal:` - Set to `true` to render the CLI's `--help` as an animated, colored [termynal](https://github.com/termynal/termynal.py) terminal instead of Markdown tables. By default only the root command's `--help` is rendered (see `:subcommands:` to include nested commands). Overrides the global `termynal` setting.
- `:command:` - Render a specific subcommand instead of the root. A space-separated path selects nested commands (e.g. `:command: export` renders `<cli> export --help`; `:command: subapp sub-command` goes one level deeper). `:subcommands:` recursion then applies relative to the selected command. Block-level only.
- `:subcommands:` - Recursion depth for termynal output. `0` (default) renders only the selected command's `--help`; `1` adds a block per direct subcommand, `2` adds their subcommands, and so on; `-1` renders every level. Hidden commands are skipped at every level.
- `:width:` - Terminal width (in columns) used when capturing `--help` for termynal output. Defaults to `80`.
- `:scheme:` - Color palette for termynal output. One of `ansi2html`, `dracula`, `mint-terminal`, `osx`, `osx-basic`, `osx-solid-colors`, `solarized`, `xterm`. Invalid values fall back to `xterm` (the default).
- `:dark_bg:` - Set to `false` to use the scheme's light-background variant. Defaults to `true`.
- `:buttons:` - Window chrome style for termynal output. One of `macos` (default) or `windows`. Invalid values fall back to `macos`.
- `:prompt:` - Prompt symbol shown before the `--help` command. Defaults to `$`.
- `:type_delay:` / `:line_delay:` / `:start_delay:` - Termynal animation timings in milliseconds (per character, per line, before start). Left unset, termynal's own defaults apply.

### Termynal Output Mode

Termynal mode introspects the Typer/Click app in-process and emits a faithful,
colored terminal of what `<cmd> --help` prints. Typer apps (which render help
through rich) come out colored; plain Click apps render their monochrome help.
Nothing is executed as a subprocess. By default only the root command is shown;
set `:subcommands:` (or `termynal_subcommands`) to a depth to stack its
subcommands' `--help` below it (`-1` for the full tree).

How it works: the app module is imported and each command's `--help` is rendered
in-process (forcing rich's terminal output so color is preserved). Hidden
commands are skipped, matching what `--help` itself shows. The ANSI output is
converted to inline HTML with [`ansi2html`](https://github.com/pycontribs/ansi2html)
and wrapped in termynal's `data-ty` markup, which `termynal.js` animates. It does
not import termynal's Python renderer — it emits the markup directly, and
`tests/test_termynal_contract.py` guards that markup against drift.

Enable it globally via the MkDocs plugin:

```yaml
plugins:
  - mkdocs-typer2:
      termynal: true
      termynal_subcommands: 0
      termynal_width: 80
      termynal_scheme: xterm
      termynal_dark_bg: true
      termynal_buttons: macos
      termynal_prompt: "$"
      # termynal_type_delay / termynal_line_delay / termynal_start_delay (ms)
      # may also be set; unset, termynal's own animation defaults apply.
```

Every block-level option above has a global `termynal_`-prefixed equivalent
(e.g. `:buttons:` ↔ `termynal_buttons`); the block-level value wins. The
`:command:` selector is block-level only.

or per block:

```markdown
::: mkdocs-typer2
    :module: my_module.cli
    :name: mycli
    :termynal: true
    :width: 100
```

To document one subcommand per block — with your own headings and prose around
each — select it with `:command:`:

```markdown
## Export

::: mkdocs-typer2
    :module: my_module.cli
    :name: mycli
    :termynal: true
    :command: export
```

**Requirements / caveats:**

- Termynal mode needs the optional `termynal` extra:
  `pip install "mkdocs-typer2[termynal]"`. Using `:termynal:` without it raises a
  clear install hint. ANSI-to-HTML conversion is done with `ansi2html`; the rest
  of mkdocs-typer2 has no termynal dependency.
- The rendered blocks rely on termynal's CSS/JS being present on the page, and
  how you provide it differs by builder:
  - **MkDocs:** enable the
    [`termynal` MkDocs plugin](https://github.com/termynal/termynal.py)
    (`plugins: [termynal]`); it injects `termynal.css` / `termynal.js`
    automatically.
  - **Zensical:** the termynal plugin does not run, so add the assets yourself
    via `extra_css` / `extra_javascript` — see
    [Termynal assets under Zensical](#termynal-assets-under-zensical).

  Without the CSS/JS the blocks render as unstyled text.

## Advanced Usage

### Per-Block Pretty Configuration

You can override the global pretty setting for individual documentation blocks:

```markdown
::: mkdocs-typer2
    :module: my_module.cli
    :name: mycli
    :pretty: true
    :engine: native
```

### Multiple CLI Documentation

You can document multiple CLIs in the same MkDocs site by using multiple directive blocks:

```markdown
# Main CLI

::: mkdocs-typer2
    :module: my_module.cli
    :name: mycli

# Admin CLI

::: mkdocs-typer2
    :module: my_module.admin
    :name: admin-cli
```

## Example

This repository is a good example of how to use the plugin. We have a simple CLI located in `src/mkdocs_typer2/cli/cli.py`.

The CLI's documentation is automatically generated using the block level directive in `docs/cli.md`:

```markdown
::: mkdocs-typer2
    :module: mkdocs_typer2.cli.cli
    :name: mkdocs-typer2
    :engine: legacy
```

And the pretty versions in `docs/cli-pretty-legacy.md` and `docs/cli-pretty-native.md`:

```markdown
::: mkdocs-typer2
    :module: mkdocs_typer2.cli.cli
    :name: mkdocs-typer2
    :pretty: true
    :engine: legacy
```

```markdown
:::: mkdocs-typer2
    :module: mkdocs_typer2.cli.cli
    :name: mkdocs-typer2
    :pretty: true
    :engine: native
```

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

When working in this repository, sync dependencies (including optional extras used in CI) with:

```bash
uv sync --all-extras --group dev
```

## License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
