sphinx-oceanid 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sphinx_oceanid-0.1.0/LICENSE +28 -0
- sphinx_oceanid-0.1.0/PKG-INFO +180 -0
- sphinx_oceanid-0.1.0/README.md +154 -0
- sphinx_oceanid-0.1.0/pyproject.toml +91 -0
- sphinx_oceanid-0.1.0/src/sphinx_oceanid/__init__.py +42 -0
- sphinx_oceanid-0.1.0/src/sphinx_oceanid/_static/oceanid-fullscreen.js +127 -0
- sphinx_oceanid-0.1.0/src/sphinx_oceanid/_static/oceanid-observer.js +97 -0
- sphinx_oceanid-0.1.0/src/sphinx_oceanid/_static/oceanid-renderer.js +107 -0
- sphinx_oceanid-0.1.0/src/sphinx_oceanid/_static/oceanid-theme.js +156 -0
- sphinx_oceanid-0.1.0/src/sphinx_oceanid/_static/oceanid-zoom.js +196 -0
- sphinx_oceanid-0.1.0/src/sphinx_oceanid/_static/oceanid.css +151 -0
- sphinx_oceanid-0.1.0/src/sphinx_oceanid/assets.py +105 -0
- sphinx_oceanid-0.1.0/src/sphinx_oceanid/autoclassdiag.py +109 -0
- sphinx_oceanid-0.1.0/src/sphinx_oceanid/config.py +110 -0
- sphinx_oceanid-0.1.0/src/sphinx_oceanid/diagram_types.py +55 -0
- sphinx_oceanid-0.1.0/src/sphinx_oceanid/directives.py +192 -0
- sphinx_oceanid-0.1.0/src/sphinx_oceanid/exceptions.py +9 -0
- sphinx_oceanid-0.1.0/src/sphinx_oceanid/nodes.py +19 -0
- sphinx_oceanid-0.1.0/src/sphinx_oceanid/py.typed +0 -0
- sphinx_oceanid-0.1.0/src/sphinx_oceanid/visitors.py +116 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026, driller
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sphinx-oceanid
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: High-quality Mermaid diagrams in Sphinx, powered by beautiful-mermaid
|
|
5
|
+
Keywords: sphinx,mermaid,diagrams,documentation,beautiful-mermaid
|
|
6
|
+
Author: driller
|
|
7
|
+
Author-email: driller <eleshis@gmail.com>
|
|
8
|
+
License-Expression: BSD-3-Clause
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Framework :: Sphinx :: Extension
|
|
12
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
15
|
+
Classifier: Topic :: Documentation
|
|
16
|
+
Requires-Dist: sphinx>=7.4
|
|
17
|
+
Requires-Dist: sphinx-autobuild>=2024.0 ; extra == 'preview'
|
|
18
|
+
Requires-Python: >=3.13
|
|
19
|
+
Project-URL: Homepage, https://github.com/drillan/sphinx-oceanid
|
|
20
|
+
Project-URL: Documentation, https://drillan.github.io/sphinx-oceanid/
|
|
21
|
+
Project-URL: Repository, https://github.com/drillan/sphinx-oceanid
|
|
22
|
+
Project-URL: Bug Tracker, https://github.com/drillan/sphinx-oceanid/issues
|
|
23
|
+
Project-URL: Changelog, https://github.com/drillan/sphinx-oceanid/blob/main/CHANGELOG.md
|
|
24
|
+
Provides-Extra: preview
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
# sphinx-oceanid
|
|
28
|
+
|
|
29
|
+
[](https://pypi.org/project/sphinx-oceanid/)
|
|
30
|
+
[](https://pypi.org/project/sphinx-oceanid/)
|
|
31
|
+
[](https://drillan.github.io/sphinx-oceanid/)
|
|
32
|
+
[](README.ja.md)
|
|
33
|
+
|
|
34
|
+
High-quality Mermaid diagrams in Sphinx, powered by [beautiful-mermaid](https://github.com/niccolozy/beautiful-mermaid).
|
|
35
|
+
|
|
36
|
+
## Features
|
|
37
|
+
|
|
38
|
+
- **beautiful-mermaid rendering** — Uses ELK.js-based layout engine for high-quality SVG output
|
|
39
|
+
- **CSS variable theming** — Automatic dark/light theme detection with instant switching (no re-render)
|
|
40
|
+
- **Zero-config** — Works out of the box with CDN-hosted beautiful-mermaid
|
|
41
|
+
- **sphinx-revealjs support** — Lazy rendering for hidden slides via IntersectionObserver ([example](https://drillan.github.io/sphinx-oceanid/slides/))
|
|
42
|
+
- **Pan & zoom** — Native Pointer Events + SVG transform (no d3.js dependency)
|
|
43
|
+
- **Fullscreen modal** — View diagrams in a viewport-sized overlay
|
|
44
|
+
- **External file support** — Reference `.mmd` files instead of inline code
|
|
45
|
+
- **Auto class diagrams** — Generate class hierarchy diagrams from Python code
|
|
46
|
+
|
|
47
|
+
## Supported Diagram Types
|
|
48
|
+
|
|
49
|
+
| Type | Alias |
|
|
50
|
+
|------|-------|
|
|
51
|
+
| `flowchart` | `graph` |
|
|
52
|
+
| `sequenceDiagram` | |
|
|
53
|
+
| `classDiagram` | |
|
|
54
|
+
| `stateDiagram` | `stateDiagram-v2` |
|
|
55
|
+
| `erDiagram` | |
|
|
56
|
+
| `xychart-beta` | |
|
|
57
|
+
|
|
58
|
+
Unsupported diagram types produce explicit warnings (or errors), never silent degradation.
|
|
59
|
+
|
|
60
|
+
## Installation
|
|
61
|
+
|
|
62
|
+
sphinx-oceanid requires Python 3.13+.
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pip install sphinx-oceanid
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
From source:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
pip install git+https://github.com/drillan/sphinx-oceanid.git
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Or clone and install locally:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
git clone https://github.com/drillan/sphinx-oceanid.git
|
|
78
|
+
cd sphinx-oceanid
|
|
79
|
+
pip install .
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Quick Start
|
|
83
|
+
|
|
84
|
+
Add the extension to your `conf.py`:
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
extensions = ["sphinx_oceanid"]
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Then use the `mermaid` directive in your reStructuredText files:
|
|
91
|
+
|
|
92
|
+
```rst
|
|
93
|
+
.. mermaid::
|
|
94
|
+
|
|
95
|
+
flowchart LR
|
|
96
|
+
A[Start] --> B[Process] --> C[End]
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Or in Markdown (MyST) files:
|
|
100
|
+
|
|
101
|
+
````markdown
|
|
102
|
+
```{mermaid}
|
|
103
|
+
sequenceDiagram
|
|
104
|
+
Alice->>Bob: Hello
|
|
105
|
+
Bob-->>Alice: Hi!
|
|
106
|
+
```
|
|
107
|
+
````
|
|
108
|
+
|
|
109
|
+
## Configuration
|
|
110
|
+
|
|
111
|
+
All configuration options use the `oceanid_` prefix in `conf.py`:
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
# conf.py
|
|
115
|
+
extensions = ["sphinx_oceanid"]
|
|
116
|
+
|
|
117
|
+
# Theme (default: "auto" — detects dark/light from Sphinx theme)
|
|
118
|
+
oceanid_theme = "auto"
|
|
119
|
+
oceanid_theme_dark = "zinc-dark"
|
|
120
|
+
oceanid_theme_light = "zinc-light"
|
|
121
|
+
|
|
122
|
+
# Enable zoom on all diagrams (default: False)
|
|
123
|
+
oceanid_zoom = True
|
|
124
|
+
|
|
125
|
+
# Enable fullscreen modal (default: False)
|
|
126
|
+
oceanid_fullscreen = True
|
|
127
|
+
|
|
128
|
+
# Action for unsupported diagram types: "warning" or "error" (default: "warning")
|
|
129
|
+
oceanid_unsupported_action = "warning"
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Directive Options
|
|
133
|
+
|
|
134
|
+
```rst
|
|
135
|
+
.. mermaid::
|
|
136
|
+
:name: my-diagram
|
|
137
|
+
:alt: Description for accessibility
|
|
138
|
+
:align: center
|
|
139
|
+
:caption: Diagram caption (rendered as <figcaption>)
|
|
140
|
+
:title: Mermaid native title (rendered inside the diagram)
|
|
141
|
+
:zoom:
|
|
142
|
+
:config: {"theme": "forest"}
|
|
143
|
+
|
|
144
|
+
flowchart LR
|
|
145
|
+
A --> B --> C
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Auto Class Diagrams
|
|
149
|
+
|
|
150
|
+
Generate class hierarchy diagrams from Python code:
|
|
151
|
+
|
|
152
|
+
```rst
|
|
153
|
+
.. autoclasstree:: mypackage.MyClass
|
|
154
|
+
:full:
|
|
155
|
+
:namespace: mypackage
|
|
156
|
+
:caption: Class hierarchy
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Local Preview
|
|
160
|
+
|
|
161
|
+
Mermaid diagrams require HTTP serving — opening built HTML via `file://` will not render diagrams due to browser CORS restrictions.
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
# Quick static server (no extra dependencies)
|
|
165
|
+
make -C docs serve
|
|
166
|
+
|
|
167
|
+
# Live reload (requires sphinx-autobuild)
|
|
168
|
+
pip install sphinx-oceanid[preview]
|
|
169
|
+
make -C docs livehtml
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
See [docs/install.md](docs/install.md) for Makefile setup instructions.
|
|
173
|
+
|
|
174
|
+
## Documentation
|
|
175
|
+
|
|
176
|
+
Full documentation is available at **[drillan.github.io/sphinx-oceanid](https://drillan.github.io/sphinx-oceanid/)** or in the [docs/](docs/) directory.
|
|
177
|
+
|
|
178
|
+
## License
|
|
179
|
+
|
|
180
|
+
BSD-3-Clause. See [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# sphinx-oceanid
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/sphinx-oceanid/)
|
|
4
|
+
[](https://pypi.org/project/sphinx-oceanid/)
|
|
5
|
+
[](https://drillan.github.io/sphinx-oceanid/)
|
|
6
|
+
[](README.ja.md)
|
|
7
|
+
|
|
8
|
+
High-quality Mermaid diagrams in Sphinx, powered by [beautiful-mermaid](https://github.com/niccolozy/beautiful-mermaid).
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- **beautiful-mermaid rendering** — Uses ELK.js-based layout engine for high-quality SVG output
|
|
13
|
+
- **CSS variable theming** — Automatic dark/light theme detection with instant switching (no re-render)
|
|
14
|
+
- **Zero-config** — Works out of the box with CDN-hosted beautiful-mermaid
|
|
15
|
+
- **sphinx-revealjs support** — Lazy rendering for hidden slides via IntersectionObserver ([example](https://drillan.github.io/sphinx-oceanid/slides/))
|
|
16
|
+
- **Pan & zoom** — Native Pointer Events + SVG transform (no d3.js dependency)
|
|
17
|
+
- **Fullscreen modal** — View diagrams in a viewport-sized overlay
|
|
18
|
+
- **External file support** — Reference `.mmd` files instead of inline code
|
|
19
|
+
- **Auto class diagrams** — Generate class hierarchy diagrams from Python code
|
|
20
|
+
|
|
21
|
+
## Supported Diagram Types
|
|
22
|
+
|
|
23
|
+
| Type | Alias |
|
|
24
|
+
|------|-------|
|
|
25
|
+
| `flowchart` | `graph` |
|
|
26
|
+
| `sequenceDiagram` | |
|
|
27
|
+
| `classDiagram` | |
|
|
28
|
+
| `stateDiagram` | `stateDiagram-v2` |
|
|
29
|
+
| `erDiagram` | |
|
|
30
|
+
| `xychart-beta` | |
|
|
31
|
+
|
|
32
|
+
Unsupported diagram types produce explicit warnings (or errors), never silent degradation.
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
sphinx-oceanid requires Python 3.13+.
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install sphinx-oceanid
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
From source:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pip install git+https://github.com/drillan/sphinx-oceanid.git
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Or clone and install locally:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
git clone https://github.com/drillan/sphinx-oceanid.git
|
|
52
|
+
cd sphinx-oceanid
|
|
53
|
+
pip install .
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Quick Start
|
|
57
|
+
|
|
58
|
+
Add the extension to your `conf.py`:
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
extensions = ["sphinx_oceanid"]
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Then use the `mermaid` directive in your reStructuredText files:
|
|
65
|
+
|
|
66
|
+
```rst
|
|
67
|
+
.. mermaid::
|
|
68
|
+
|
|
69
|
+
flowchart LR
|
|
70
|
+
A[Start] --> B[Process] --> C[End]
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Or in Markdown (MyST) files:
|
|
74
|
+
|
|
75
|
+
````markdown
|
|
76
|
+
```{mermaid}
|
|
77
|
+
sequenceDiagram
|
|
78
|
+
Alice->>Bob: Hello
|
|
79
|
+
Bob-->>Alice: Hi!
|
|
80
|
+
```
|
|
81
|
+
````
|
|
82
|
+
|
|
83
|
+
## Configuration
|
|
84
|
+
|
|
85
|
+
All configuration options use the `oceanid_` prefix in `conf.py`:
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
# conf.py
|
|
89
|
+
extensions = ["sphinx_oceanid"]
|
|
90
|
+
|
|
91
|
+
# Theme (default: "auto" — detects dark/light from Sphinx theme)
|
|
92
|
+
oceanid_theme = "auto"
|
|
93
|
+
oceanid_theme_dark = "zinc-dark"
|
|
94
|
+
oceanid_theme_light = "zinc-light"
|
|
95
|
+
|
|
96
|
+
# Enable zoom on all diagrams (default: False)
|
|
97
|
+
oceanid_zoom = True
|
|
98
|
+
|
|
99
|
+
# Enable fullscreen modal (default: False)
|
|
100
|
+
oceanid_fullscreen = True
|
|
101
|
+
|
|
102
|
+
# Action for unsupported diagram types: "warning" or "error" (default: "warning")
|
|
103
|
+
oceanid_unsupported_action = "warning"
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Directive Options
|
|
107
|
+
|
|
108
|
+
```rst
|
|
109
|
+
.. mermaid::
|
|
110
|
+
:name: my-diagram
|
|
111
|
+
:alt: Description for accessibility
|
|
112
|
+
:align: center
|
|
113
|
+
:caption: Diagram caption (rendered as <figcaption>)
|
|
114
|
+
:title: Mermaid native title (rendered inside the diagram)
|
|
115
|
+
:zoom:
|
|
116
|
+
:config: {"theme": "forest"}
|
|
117
|
+
|
|
118
|
+
flowchart LR
|
|
119
|
+
A --> B --> C
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Auto Class Diagrams
|
|
123
|
+
|
|
124
|
+
Generate class hierarchy diagrams from Python code:
|
|
125
|
+
|
|
126
|
+
```rst
|
|
127
|
+
.. autoclasstree:: mypackage.MyClass
|
|
128
|
+
:full:
|
|
129
|
+
:namespace: mypackage
|
|
130
|
+
:caption: Class hierarchy
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Local Preview
|
|
134
|
+
|
|
135
|
+
Mermaid diagrams require HTTP serving — opening built HTML via `file://` will not render diagrams due to browser CORS restrictions.
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
# Quick static server (no extra dependencies)
|
|
139
|
+
make -C docs serve
|
|
140
|
+
|
|
141
|
+
# Live reload (requires sphinx-autobuild)
|
|
142
|
+
pip install sphinx-oceanid[preview]
|
|
143
|
+
make -C docs livehtml
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
See [docs/install.md](docs/install.md) for Makefile setup instructions.
|
|
147
|
+
|
|
148
|
+
## Documentation
|
|
149
|
+
|
|
150
|
+
Full documentation is available at **[drillan.github.io/sphinx-oceanid](https://drillan.github.io/sphinx-oceanid/)** or in the [docs/](docs/) directory.
|
|
151
|
+
|
|
152
|
+
## License
|
|
153
|
+
|
|
154
|
+
BSD-3-Clause. See [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "sphinx-oceanid"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "High-quality Mermaid diagrams in Sphinx, powered by beautiful-mermaid"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "BSD-3-Clause"
|
|
7
|
+
license-files = ["LICENSE"]
|
|
8
|
+
requires-python = ">=3.13"
|
|
9
|
+
keywords = ["sphinx", "mermaid", "diagrams", "documentation", "beautiful-mermaid"]
|
|
10
|
+
classifiers = [
|
|
11
|
+
"Development Status :: 3 - Alpha",
|
|
12
|
+
"Framework :: Sphinx :: Extension",
|
|
13
|
+
"License :: OSI Approved :: BSD License",
|
|
14
|
+
"Programming Language :: Python :: 3.13",
|
|
15
|
+
"Programming Language :: Python :: 3.14",
|
|
16
|
+
"Topic :: Documentation",
|
|
17
|
+
]
|
|
18
|
+
authors = [
|
|
19
|
+
{ name = "driller", email = "eleshis@gmail.com" },
|
|
20
|
+
]
|
|
21
|
+
dependencies = [
|
|
22
|
+
"sphinx>=7.4",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[project.urls]
|
|
26
|
+
Homepage = "https://github.com/drillan/sphinx-oceanid"
|
|
27
|
+
Documentation = "https://drillan.github.io/sphinx-oceanid/"
|
|
28
|
+
Repository = "https://github.com/drillan/sphinx-oceanid"
|
|
29
|
+
"Bug Tracker" = "https://github.com/drillan/sphinx-oceanid/issues"
|
|
30
|
+
Changelog = "https://github.com/drillan/sphinx-oceanid/blob/main/CHANGELOG.md"
|
|
31
|
+
|
|
32
|
+
[build-system]
|
|
33
|
+
requires = ["uv_build>=0.10.0,<0.11.0"]
|
|
34
|
+
build-backend = "uv_build"
|
|
35
|
+
|
|
36
|
+
[project.optional-dependencies]
|
|
37
|
+
preview = ["sphinx-autobuild>=2024.0"]
|
|
38
|
+
|
|
39
|
+
[dependency-groups]
|
|
40
|
+
test = [
|
|
41
|
+
"pytest",
|
|
42
|
+
"myst-parser",
|
|
43
|
+
"sphinx-revealjs",
|
|
44
|
+
]
|
|
45
|
+
dev = [
|
|
46
|
+
"ruff",
|
|
47
|
+
"mypy",
|
|
48
|
+
"types-docutils",
|
|
49
|
+
{ include-group = "test" },
|
|
50
|
+
]
|
|
51
|
+
docs = [
|
|
52
|
+
"myst-parser>=5.0.0",
|
|
53
|
+
"shibuya>=2026.1.9",
|
|
54
|
+
"sphinx>=9.1.0",
|
|
55
|
+
"sphinx-autobuild>=2024.0",
|
|
56
|
+
"sphinx-design>=0.6",
|
|
57
|
+
"sphinx-revealjs>=3.0",
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
[tool.pytest.ini_options]
|
|
61
|
+
testpaths = ["tests"]
|
|
62
|
+
|
|
63
|
+
[tool.ruff]
|
|
64
|
+
line-length = 120
|
|
65
|
+
target-version = "py313"
|
|
66
|
+
|
|
67
|
+
[tool.ruff.lint]
|
|
68
|
+
extend-select = [
|
|
69
|
+
"I", # isort
|
|
70
|
+
"UP", # pyupgrade
|
|
71
|
+
"B", # flake8-bugbear
|
|
72
|
+
"SIM", # flake8-simplify
|
|
73
|
+
"TCH", # flake8-type-checking
|
|
74
|
+
"RUF", # Ruff-specific
|
|
75
|
+
"PIE", # flake8-pie
|
|
76
|
+
"PT", # flake8-pytest-style
|
|
77
|
+
"RSE", # flake8-raise
|
|
78
|
+
"C4", # flake8-comprehensions
|
|
79
|
+
"FURB", # refurb
|
|
80
|
+
"PERF", # perflint
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
[tool.ruff.lint.isort]
|
|
84
|
+
known-first-party = ["sphinx_oceanid"]
|
|
85
|
+
|
|
86
|
+
[tool.mypy]
|
|
87
|
+
python_version = "3.13"
|
|
88
|
+
strict = true
|
|
89
|
+
warn_unreachable = true
|
|
90
|
+
enable_error_code = ["ignore-without-code", "redundant-cast", "truthy-bool"]
|
|
91
|
+
exclude = ["tests/roots/", "examples/"]
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""sphinx-oceanid: High-quality Mermaid diagrams in Sphinx."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from sphinx.application import Sphinx
|
|
10
|
+
|
|
11
|
+
from importlib.metadata import version
|
|
12
|
+
|
|
13
|
+
__version__ = version("sphinx-oceanid")
|
|
14
|
+
|
|
15
|
+
_STATIC_DIR = str(Path(__file__).parent / "_static")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def setup(app: Sphinx) -> dict[str, bool | str]:
|
|
19
|
+
"""Sphinx extension entry point.
|
|
20
|
+
|
|
21
|
+
Registers nodes, directives, config values, and event handlers.
|
|
22
|
+
"""
|
|
23
|
+
from .assets import install_assets
|
|
24
|
+
from .config import register_config_values, validate_config
|
|
25
|
+
from .directives import Mermaid, MermaidClassDiagram
|
|
26
|
+
from .nodes import mermaid_node
|
|
27
|
+
from .visitors import html_depart_mermaid, html_visit_mermaid
|
|
28
|
+
|
|
29
|
+
register_config_values(app)
|
|
30
|
+
app.add_node(mermaid_node, html=(html_visit_mermaid, html_depart_mermaid))
|
|
31
|
+
app.add_directive("mermaid", Mermaid)
|
|
32
|
+
app.add_directive("autoclasstree", MermaidClassDiagram)
|
|
33
|
+
app.connect("config-inited", validate_config)
|
|
34
|
+
app.connect("html-page-context", install_assets)
|
|
35
|
+
app.connect("builder-inited", _register_static_path)
|
|
36
|
+
|
|
37
|
+
return {"version": __version__, "parallel_read_safe": True}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _register_static_path(app: Sphinx) -> None:
|
|
41
|
+
"""Register the extension's _static directory for file copying."""
|
|
42
|
+
app.config.html_static_path.append(_STATIC_DIR)
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* sphinx-oceanid: Fullscreen modal for Mermaid diagrams (FR-018).
|
|
3
|
+
*
|
|
4
|
+
* Creates a modal overlay, injects fullscreen buttons on rendered diagrams,
|
|
5
|
+
* and watches for newly rendered diagrams via MutationObserver.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Create the fullscreen modal DOM element and append to document body.
|
|
10
|
+
*
|
|
11
|
+
* @param {object} config - Oceanid config with fullscreenButton and fullscreenButtonOpacity
|
|
12
|
+
* @returns {{modal: HTMLElement, container: HTMLElement, close: Function}}
|
|
13
|
+
*/
|
|
14
|
+
const createModal = (config) => {
|
|
15
|
+
const modal = document.createElement("div");
|
|
16
|
+
modal.className = "oceanid-fullscreen-modal";
|
|
17
|
+
|
|
18
|
+
const closeBtn = document.createElement("button");
|
|
19
|
+
closeBtn.className = "oceanid-fullscreen-close";
|
|
20
|
+
closeBtn.textContent = "\u00d7";
|
|
21
|
+
closeBtn.setAttribute("aria-label", "Close fullscreen");
|
|
22
|
+
|
|
23
|
+
const container = document.createElement("div");
|
|
24
|
+
container.className = "oceanid-container-fullscreen";
|
|
25
|
+
|
|
26
|
+
modal.appendChild(closeBtn);
|
|
27
|
+
modal.appendChild(container);
|
|
28
|
+
document.body.appendChild(modal);
|
|
29
|
+
|
|
30
|
+
const close = () => {
|
|
31
|
+
modal.classList.remove("active");
|
|
32
|
+
container.innerHTML = "";
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
closeBtn.addEventListener("click", close);
|
|
36
|
+
|
|
37
|
+
modal.addEventListener("click", (e) => {
|
|
38
|
+
if (e.target === modal) {
|
|
39
|
+
close();
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
document.addEventListener("keydown", (e) => {
|
|
44
|
+
if (e.key === "Escape" && modal.classList.contains("active")) {
|
|
45
|
+
close();
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
return { modal, container, close };
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Inject a fullscreen button on a rendered diagram element.
|
|
54
|
+
*
|
|
55
|
+
* @param {Element} el - .oceanid-diagram element with data-oceanid-rendered="true"
|
|
56
|
+
* @param {object} config - Oceanid config
|
|
57
|
+
* @param {{modal: HTMLElement, container: HTMLElement}} modalCtx - Modal context
|
|
58
|
+
*/
|
|
59
|
+
const addFullscreenButton = (el, config, modalCtx) => {
|
|
60
|
+
if (el.querySelector(".oceanid-fullscreen-btn")) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const wrapper = el.querySelector(".oceanid-svg-container");
|
|
65
|
+
if (!wrapper) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
el.style.position = el.style.position || "relative";
|
|
70
|
+
|
|
71
|
+
const btn = document.createElement("button");
|
|
72
|
+
btn.className = "oceanid-fullscreen-btn";
|
|
73
|
+
btn.textContent = config.fullscreenButton;
|
|
74
|
+
btn.setAttribute("aria-label", "Open fullscreen");
|
|
75
|
+
btn.style.opacity = String(config.fullscreenButtonOpacity / 100);
|
|
76
|
+
|
|
77
|
+
btn.addEventListener("click", () => {
|
|
78
|
+
const svg = wrapper.querySelector("svg");
|
|
79
|
+
if (!svg) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
modalCtx.container.innerHTML = "";
|
|
83
|
+
const clone = svg.cloneNode(true);
|
|
84
|
+
clone.style.width = "100%";
|
|
85
|
+
clone.style.height = "auto";
|
|
86
|
+
clone.style.maxHeight = "90vh";
|
|
87
|
+
modalCtx.container.appendChild(clone);
|
|
88
|
+
modalCtx.modal.classList.add("active");
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
el.appendChild(btn);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Set up fullscreen modal functionality.
|
|
96
|
+
*
|
|
97
|
+
* - Creates modal DOM and appends to body
|
|
98
|
+
* - Adds fullscreen button to already-rendered diagrams
|
|
99
|
+
* - Uses MutationObserver to add button to diagrams rendered later (lazy)
|
|
100
|
+
*
|
|
101
|
+
* @param {object} config - Oceanid config
|
|
102
|
+
*/
|
|
103
|
+
export const setupFullscreen = (config) => {
|
|
104
|
+
const modalCtx = createModal(config);
|
|
105
|
+
|
|
106
|
+
document
|
|
107
|
+
.querySelectorAll('.oceanid-diagram[data-oceanid-rendered="true"]')
|
|
108
|
+
.forEach((el) => {
|
|
109
|
+
addFullscreenButton(el, config, modalCtx);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const observer = new MutationObserver((mutations) => {
|
|
113
|
+
mutations.forEach((mutation) => {
|
|
114
|
+
if (
|
|
115
|
+
mutation.type === "attributes" &&
|
|
116
|
+
mutation.attributeName === "data-oceanid-rendered" &&
|
|
117
|
+
mutation.target.getAttribute("data-oceanid-rendered") === "true"
|
|
118
|
+
) {
|
|
119
|
+
addFullscreenButton(mutation.target, config, modalCtx);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
document.querySelectorAll(".oceanid-diagram").forEach((el) => {
|
|
125
|
+
observer.observe(el, { attributes: true });
|
|
126
|
+
});
|
|
127
|
+
};
|