Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified .coverage
Binary file not shown.
2 changes: 1 addition & 1 deletion .python-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.12
3.13
18 changes: 17 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,23 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
## [unreleased]

## [0.1.4] - 2025-03-15

### Added
- Added support for Python 3.13
- Added per-block configuration for `pretty` option in documentation directives
- Added justfile for common development tasks
- Added docs/cli-pretty.md example for pretty-formatted CLI documentation
- Added docs/changelog.md that includes the project's CHANGELOG

### Changed
- Enhanced documentation with more detailed usage instructions and examples
- Updated navigation structure in mkdocs.yaml
- Improved TyperProcessor to support overriding global `pretty` setting at the block level

## [0.1.3] - 2025-03-09

### Fixed
- Fixed issue where docstrings weren't displayed in the generated documentation when `pretty` option was enabled
Expand Down
104 changes: 92 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
# mkdocs-typer2

[![PyPI version](https://badge.fury.io/py/mkdocs-typer2.svg)](https://badge.fury.io/py/mkdocs-typer2)
![Python 3.10 | 3.11 | 3.12](https://img.shields.io/badge/python-3.10%20|%203.11%20|%203.12-blue.svg)
![Python 3.10 | 3.11 | 3.12 | 3.13](https://img.shields.io/badge/python-3.10%20|%203.11%20|%203.12-blue.svg)
![Ruff](https://img.shields.io/badge/linted%20by-ruff-FFC107.svg)
[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![Downloads](https://static.pepy.tech/badge/mkdocs-typer2)](https://pepy.tech/project/mkdocs-typer2)
[![codecov](https://codecov.io/gh/syn54x/mkdocs-typer2/branch/main/graph/badge.svg)](https://codecov.io/gh/syn54x/mkdocs-typer2)
[![Issues](https://img.shields.io/github/issues/syn54x/mkdocs-typer2)](https://github.com/syn54x/mkdocs-typer2/issues)



A MkDocs plugin that automatically generates beautiful documentation for your Typer CLI applications.

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 it's 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.
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!
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)
Expand All @@ -25,6 +23,19 @@ I created this plugin because the original plugin was no longer working for me,
- 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 encapsulating arguments & options inside tables instead of lists
- Global plugin configuration or per-documentation block configuration

## How It Works

The plugin leverages Typer's built-in documentation generation via the `typer <module> utils docs` command to create Markdown documentation. It then processes this Markdown content and integrates it into your MkDocs site.

The plugin works by:

1. Registering a Markdown extension that processes special directive blocks
2. Running the Typer documentation command on your specified module
3. Optionally reformatting the output to use tables for arguments and options (the "pretty" mode)
4. Integrating the resulting HTML into your MkDocs site

## Installation

Expand All @@ -34,37 +45,89 @@ Install using pip:
pip install mkdocs-typer2
```

## Usage
### Requirements

- Python 3.10 or higher
- MkDocs 1.6.1 or higher
- Typer 0.12.5 or higher
- Pydantic 2.9.2 or higher

## Configuration

1. Add the plugin to your `mkdocs.yml` file:
### Basic Configuration

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

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

The plugin offers a `pretty` option that can be set in your `mkdocs.yml` file to enable pretty documentation. This will use markdown tables to format the CLI options and arguments instead of lists.
### Pretty Mode

The plugin offers a `pretty` option that can be set in your `mkdocs.yml` file to enable pretty documentation. This will use markdown tables to format the CLI options and arguments instead of lists:

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

2. In your Markdown files, use the `:::typer` directive to generate documentation for your Typer CLI
## 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
```

- The `:module:` option is required and specifies the module containing your Typer CLI application. This is the *installed* module, not the directory. I.e: If you app is located in `src/my_module/cli.py`, your `:module:` should typically be `my_module.cli`.
- The `:name:` option is optional and specifies the name of the CLI. If left blank, your CLI will simply be named `CLI` in your documentation.
### 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.

## 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
```

### 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.py`.
This repository is a good example of how to use the plugin. We have a simple CLI located in `src/mkdocs_typer2/cli.py`.

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

Expand All @@ -73,3 +136,20 @@ The CLI's documentation is automatically generated using the block level directi
:module: mkdocs_typer2.cli
:name: mkdocs-typer2
```

And the pretty version in `docs/cli-pretty.md`:

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

## Contributing

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

## License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
1 change: 1 addition & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--8<-- "CHANGELOG.md"
4 changes: 4 additions & 0 deletions docs/cli-pretty.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
::: mkdocs-typer2
:module: mkdocs_typer2.cli
:name: mkdocs-typer2
:pretty: true
15 changes: 15 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
@default:
just --list

sync:
uv sync
pre-commit install

rm:
rm -rf .venv

test *ARGS:
uv run pytest {{ARGS}}

serve:
uv run mkdocs serve
10 changes: 6 additions & 4 deletions mkdocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,14 @@ theme:
- toc.follow
watch:
- src/
- README.md
- CHANGELOG.md

nav:
- Home: index.md
- Example CLI: cli.md
- Changelog: changelog.md
- CLI (Old): cli.md
- CLI (Pretty): cli-pretty.md
- CHANGELOG: changelog.md

markdown_extensions:
- abbr
Expand All @@ -46,8 +49,7 @@ markdown_extensions:

plugins:
- search
- mkdocs-typer2:
pretty: true
- mkdocs-typer2
- mkdocstrings:
handlers:
python:
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "mkdocs-typer2"
version = "0.1.3"
version = "0.1.4"
description = "Mkdocs plugin for generating Typer CLI docs"
readme = "README.md"
requires-python = ">=3.10"
Expand Down
15 changes: 13 additions & 2 deletions src/mkdocs_typer2/markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,31 @@ def run(self, parent, blocks):
# Extract options from the block
module_match = re.search(r":module:\s*(\S+)", block)
name_match = re.search(r":name:\s*(\S+)", block)

pretty_match = re.search(r":pretty:\s*(\S+)", block)
if not module_match:
raise ValueError("Module is required")

module = module_match.group(1)
name = name_match.group(1) if name_match else ""

# Determine if pretty formatting should be used
# Block-level setting overrides global setting if present
use_pretty = self.pretty # Start with global setting
if pretty_match:
# Parse the block-level setting as a boolean
block_pretty_value = pretty_match.group(1).lower()
if block_pretty_value in ["true", "1", "yes"]:
use_pretty = True
elif block_pretty_value in ["false", "0", "no"]:
use_pretty = False

# Run typer command
cmd = f"typer {module} utils docs --name {name}"
# print(cmd)
result = subprocess.run(cmd.split(), capture_output=True, text=True)

if result.returncode == 0:
if self.pretty:
if use_pretty:
md_content = self.pretty_output(result.stdout)
else:
md_content = result.stdout
Expand Down
36 changes: 36 additions & 0 deletions tests/test_markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,39 @@ def test_typer_processor_run_missing_module():

with pytest.raises(ValueError, match="Module is required"):
processor.run(parent, blocks)


@pytest.mark.parametrize(
"global_pretty,block_pretty,should_use_pretty",
[
(True, None, True), # Global pretty enabled, no block level setting
(False, None, False), # Global pretty disabled, no block level setting
(False, True, True), # Global pretty disabled, block level enabled
(True, False, False), # Global pretty enabled, block level disabled
],
)
def test_typer_processor_pretty_option(global_pretty, block_pretty, should_use_pretty):
md = markdown.Markdown()
processor = TyperProcessor(md.parser, pretty=global_pretty)
parent = etree.Element("div")

# Build block with or without pretty option
block = ":::mkdocs-typer2\n :module: test_module"
if block_pretty is not None:
block += f"\n :pretty: {str(block_pretty).lower()}"

blocks = [block]

with patch("subprocess.run") as mock_run, patch.object(
processor, "pretty_output"
) as mock_pretty_output:
mock_run.return_value.returncode = 0
mock_run.return_value.stdout = "# Test Output"
mock_pretty_output.return_value = "# Pretty Test Output"

processor.run(parent, blocks)

if should_use_pretty:
mock_pretty_output.assert_called_once()
else:
mock_pretty_output.assert_not_called()