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
20 changes: 19 additions & 1 deletion CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,25 @@ $ uv add gp-sphinx --prerelease allow

<!-- To maintainers and contributors: Please add notes for the forthcoming version below -->

### What's new

#### Responsive Mermaid diagrams

Mermaid diagrams gain a `:responsive:` option with `fit` and
`preserve` policies. Use `fit` when a diagram should scale to the
content column, and `preserve` when a dense architecture map or matrix
should keep its readable width and scroll horizontally instead.
See {ref}`sphinx-gp-mermaid-how-to` for authoring guidance. (#64)

#### Code highlighting for trees, commands, and paths

`sphinx-gp-highlighting` gives docs a dedicated `tree` lexer for
directory layout snippets plus inline roles for commands, paths, and
directories. Projects can opt in to safe automatic highlighting for
shell prompts, allow-listed commands, and clear filesystem literals
while ordinary code names stay unchanged. See
{ref}`sphinx-gp-highlighting` for setup and examples. (#64)

## gp-sphinx 0.0.1a32 (2026-07-04)

### What's new
Expand Down Expand Up @@ -791,4 +810,3 @@ build cleanly. Section IDs are now namespaced per program so
(#16)

[Furo]: https://github.com/pradyunsg/furo

9 changes: 7 additions & 2 deletions docs/_ext/mermaid_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ def _figure_markup(light: str, dark: str, *, alt: str) -> str:
``body[data-theme]`` rules toggle the committed variants with no script.

>>> markup = _figure_markup("<svg/>", "<svg/>", alt="A flow")
>>> 'class="gp-sphinx-mermaid"' in markup
>>> 'class="gp-sphinx-mermaid gp-sphinx-mermaid--fit"' in markup
True
>>> 'data-mermaid-responsive="fit"' in markup
True
>>> markup.count("gp-sphinx-mermaid__variant--theme-")
2
Expand All @@ -68,7 +70,10 @@ def _figure_markup(light: str, dark: str, *, alt: str) -> str:
aria = f' aria-label="{html.escape(alt, quote=True)}"'
return "".join(
[
'<figure class="gp-sphinx-mermaid">',
(
'<figure class="gp-sphinx-mermaid gp-sphinx-mermaid--fit" '
'data-mermaid-responsive="fit">'
),
(
'<div class="gp-sphinx-mermaid__variant '
f'gp-sphinx-mermaid__variant--theme-light" role="img"{aria}>'
Expand Down
6 changes: 6 additions & 0 deletions docs/_ext/package_reference.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ class PackageDocsRecord:
"sphinx-ux-badges": "ux",
"sphinx-ux-autodoc-layout": "ux",
"sphinx-gp-mermaid": "ux",
"sphinx-gp-highlighting": "highlighting",
"sphinx-vite-builder": "build-seo",
"sphinx-gp-opengraph": "build-seo",
"sphinx-gp-sitemap": "build-seo",
Expand Down Expand Up @@ -945,6 +946,11 @@ def maturity_badge(maturity: str) -> str:
"Badge primitives, layout presenters, and other shared "
"rendering helpers consumed by the autodoc family.",
),
(
"highlighting",
"Highlighting",
"Pygments lexers and inline literal helpers for code-heavy docs.",
),
(
"build-seo",
"Build & SEO",
Expand Down
2 changes: 2 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
str(project_root / "packages" / "sphinx-autodoc-typehints-gp" / "src"),
)
sys.path.insert(0, str(project_root / "packages" / "sphinx-gp-mermaid" / "src"))
sys.path.insert(0, str(project_root / "packages" / "sphinx-gp-highlighting" / "src"))
sys.path.insert(0, str(cwd / "_ext")) # docs demo modules

import gp_sphinx # noqa: E402
Expand Down Expand Up @@ -102,6 +103,7 @@
"sphinx_autodoc_argparse.exemplar",
"sphinx_ux_autodoc_layout",
"sphinx_gp_mermaid",
"sphinx_gp_highlighting",
"mermaid_examples",
],
fastmcp_tool_modules=["fastmcp_demo_tools"],
Expand Down
4 changes: 4 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ GitHub <https://github.com/git-pull/gp-sphinx>
:caption: Theme & coordinator
```

```{cluster-toctree} highlighting
:caption: Highlighting
```

```{cluster-toctree} build-seo
:caption: Build & SEO
```
6 changes: 6 additions & 0 deletions docs/packages/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ The rendering pipeline every autodoc extension consumes, plus shared page primit
- [`sphinx-fonts`](sphinx-fonts/index.md) — IBM Plex font preloading
- [`sphinx-gp-mermaid`](sphinx-gp-mermaid/index.md) — build-time mermaid diagrams as dual-theme inline SVG

## Code highlighting

Pygments lexers and inline literal helpers for code-heavy documentation:

- [`sphinx-gp-highlighting`](sphinx-gp-highlighting/index.md) — directory-tree code blocks and inline command/path highlighting

## Autodoc extensions

Domain-specific [autodoc extensions](https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html) — each adds directives that generate documentation from a particular source-construct family (Python APIs, argparse parsers, pytest fixtures, etc.):
Expand Down
56 changes: 56 additions & 0 deletions docs/packages/sphinx-gp-highlighting/examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
(sphinx-gp-highlighting-examples)=

# Examples

## Directory trees

Use `tree` for static project layouts. It highlights connector glyphs,
directory names, filenames, and comments without pretending the snippet
is a shell transcript.

```tree
python_module
├── tmuxp_plugin_my_plugin_module
│ ├── __init__.py
│ └── plugin.py
└── pyproject.toml # Python project configuration file
```

The longer aliases render the same way:

```directory-tree
docs/
├── conf.py
├── index.md
└── packages/
```

```dir-tree
src/
└── package_name/
└── __init__.py
```

## Inline literals

Explicit roles let prose declare intent while keeping the familiar
inline-code shape:

Run {cmd}`tmuxp freeze my-session`, then edit
{path}`~/.config/tmuxp/config.yaml`.

Store plugin modules under {dir}`./plugins/`.

## Safe automatic highlighting

Safe automatic highlighting is opt-in and command allow-list based:

```python
gp_highlighting_inline_literals = "safe"
gp_highlighting_inline_commands = ["tmuxp", "agentgrep"]
```

With that configuration, ordinary backtick literals such as
`tmuxp freeze my-session`, `agentgrep search mermaid`, and
`~/.config/tmuxp/` can receive the same package-owned inline classes,
while names such as `module_name` stay unchanged.
52 changes: 52 additions & 0 deletions docs/packages/sphinx-gp-highlighting/how-to.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
(sphinx-gp-highlighting-how-to)=

# How to

## Highlight a directory tree

Use the `tree` lexer for static directory layouts. It highlights connector glyphs, directory names, filenames, and trailing comments without treating the snippet as a shell transcript:

````markdown
```tree
python_module
├── tmuxp_plugin_my_plugin_module
│ ├── __init__.py
│ └── plugin.py
└── pyproject.toml # Python project configuration file
```
````

The aliases `directory-tree` and `dir-tree` are equivalent.

## Mark up inline commands and paths

Use explicit roles when the prose knows what the literal is:

```markdown
Run {cmd}`tmuxp freeze my-session`, then edit {path}`~/.config/tmuxp/config.yaml`.
Store plugin modules under {dir}`./plugins/`.
```

The `{cmd}` role uses Sphinx's inline Pygments path with Bash highlighting. The `{path}` and `{dir}` roles keep ordinary inline-code styling and add package-owned classes for path-specific CSS.

## Enable safe automatic inline highlighting

Automatic highlighting of ordinary backtick literals is opt-in:

```python
gp_highlighting_inline_literals = "safe"
gp_highlighting_inline_commands = ["tmuxp", "agentgrep", "unihan-etl"]
```

Safe mode only catches shell prompts, configured command names with arguments, and clear filesystem paths or directories. Literals such as `module_name` and `PackageClass` stay unchanged.

## Use MyST inline language attributes

MyST's `attrs_inline` extension can still request a lexer directly:

```markdown
Inline Python code `value = 1`{l=python}
```

`sphinx-gp-highlighting` leaves literals that already carry a language alone, so explicit MyST language attributes and the package's safe auto-detection can coexist.

6 changes: 6 additions & 0 deletions docs/packages/sphinx-gp-highlighting/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
(sphinx-gp-highlighting)=

# sphinx-gp-highlighting

```{package-landing} sphinx-gp-highlighting
```
44 changes: 44 additions & 0 deletions docs/packages/sphinx-gp-highlighting/reference.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
(sphinx-gp-highlighting-reference)=

# Reference

[`sphinx_gp_highlighting/__init__.py`](https://github.com/git-pull/gp-sphinx/tree/main/packages/sphinx-gp-highlighting/src/sphinx_gp_highlighting/__init__.py).

## Registered surface

```{package-reference} sphinx-gp-highlighting
```

## Lexers

`sphinx-gp-highlighting` registers these Pygments aliases:

| Alias | Purpose |
| --- | --- |
| `tree` | Preferred directory-tree fence name |
| `directory-tree` | Explicit directory-tree alias |
| `dir-tree` | Short directory-tree alias |

## Config values

```{eval-rst}
.. autoconfigvalues:: sphinx_gp_highlighting
```

## Roles

```{eval-rst}
.. autoroles:: sphinx_gp_highlighting
```

## API

```{eval-rst}
.. autofunction:: sphinx_gp_highlighting.setup

.. autoclass:: sphinx_gp_highlighting.lexers.DirectoryTreeLexer

.. autofunction:: sphinx_gp_highlighting.inline.classify_inline_literal

.. autofunction:: sphinx_gp_highlighting.inline.build_highlighted_literal
```
32 changes: 30 additions & 2 deletions docs/packages/sphinx-gp-mermaid/how-to.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,44 @@ Write a diagram in a MyST fence — it renders to inline SVG at build time, so i
```markdown
:::{mermaid}
:caption: How a request flows.
:alt: browser request through the CDN to the origin
:name: request-flow
:responsive: fit

flowchart LR
browser --> cdn --> origin
:::
```

`:caption:`, `:alt:`, and `:name:` are the directive's options; `:name:` gives the figure a cross-reference target. When you build through {py:func}`~gp_sphinx.config.merge_sphinx_config` with the extension in `extra_extensions`, plain {rst:dir}`mermaid` fences route to the same directive automatically (it sets `myst_fence_as_directive = ["mermaid"]`).
`:caption:`, `:alt:`, `:name:`, `:class:`, and `:responsive:` are the directive's options; `:name:` gives the figure a cross-reference target. When you build through {py:func}`~gp_sphinx.config.merge_sphinx_config` with the extension in `extra_extensions`, plain {rst:dir}`mermaid` fences route to the same directive automatically (it sets `myst_fence_as_directive = ["mermaid"]`).

See {ref}`sphinx-gp-mermaid-reference` for the full option and config list.

## Choose the responsive policy

Every rendered diagram sits in a scrollable figure. The `:responsive:` option decides what the SVG itself does inside that figure:

- `fit` is the default. It keeps the SVG's build-time aspect ratio but lets the browser scale the diagram down to the content column.
- `preserve` keeps the SVG at its intrinsic Mermaid-rendered width. If the diagram is wider than the column, the figure scrolls horizontally.

Use `fit` for diagrams that remain readable when scaled: small flows, state diagrams, and short sequence diagrams. Use `preserve` for diagrams where scale-down would make labels unreadable, such as dense architecture maps or compatibility matrices.

```markdown
:::{mermaid}
:caption: Dense architecture map.
:alt: subsystem ownership and data flow
:name: architecture-map
:responsive: preserve

flowchart LR
api --> planner --> executor --> sinks
planner --> cache
executor --> audit
:::
```

`fit` and `preserve` do not rewrite the Mermaid graph. If a wide `flowchart LR` turns into a hard-to-read strip on phones, split it into smaller diagrams or use a top-to-bottom layout. Reach for `preserve` when the wide view is the useful artifact.

## Install the renderer

Rendering shells out to [`mmdc`](https://github.com/mermaid-js/mermaid-cli), so the docs toolchain needs Node. Install it as a dev dependency:
Expand All @@ -33,6 +61,6 @@ In a container, set `PUPPETEER_EXECUTABLE_PATH` to your Chrome (the generated pu

## How rendering behaves

Each diagram renders twice — a light and a dark SVG — and CSS on `body[data-theme]` shows the matching one, so the theme toggle works with no JavaScript and no layout shift. Rendered SVGs are cached by content hash under `<confdir>/_mermaid_cache`, which lives outside `_build` and survives `rm -rf docs/_build`, so a clean rebuild re-renders nothing unchanged.
Each diagram renders twice — a light and a dark SVG — and CSS on `body[data-theme]` shows the matching one, so the theme toggle works with no JavaScript and no layout shift. The HTML figure carries `gp-sphinx-mermaid--fit` or `gp-sphinx-mermaid--preserve`, plus `data-mermaid-responsive`, `data-mermaid-width`, and `data-mermaid-height` attributes for downstream styling or audits. Rendered SVGs are cached by content hash under `<confdir>/_mermaid_cache`, which lives outside `_build` and survives `rm -rf docs/_build`, so a clean rebuild re-renders nothing unchanged.

If `mmdc` is missing or fails, the build still succeeds: the diagram degrades to its escaped source text with a single warning, and non-HTML builders emit a `[diagram: <alt>]` stand-in.
1 change: 1 addition & 0 deletions docs/redirects.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ extensions/sphinx-gp-opengraph packages/sphinx-gp-opengraph
extensions/sphinx-gp-sitemap packages/sphinx-gp-sitemap
extensions/sphinx-gp-llms packages/sphinx-gp-llms
extensions/sphinx-gp-mermaid packages/sphinx-gp-mermaid
extensions/sphinx-gp-highlighting packages/sphinx-gp-highlighting
extensions/gp-sphinx packages/gp-sphinx
extensions/index packages/index
extensions/sphinx-autodoc-argparse packages/sphinx-autodoc-argparse
Expand Down
30 changes: 30 additions & 0 deletions packages/sphinx-gp-highlighting/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# sphinx-gp-highlighting

Reusable Sphinx highlighting helpers for git-pull documentation. The package
ships Pygments lexers for documentation-oriented blocks and Sphinx inline
literal helpers for commands, paths, and directories.

## Install

```console
$ pip install sphinx-gp-highlighting
```

## Usage

Enable the extension in `conf.py`:

```python
extensions = ["sphinx_gp_highlighting"]
```

Use the `tree` lexer for directory layouts:

````markdown
```tree
python_module
├── package
│ └── __init__.py
└── pyproject.toml
```
````
Loading