asyncapi-tag 1.0.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.
- asyncapi_tag-1.0.0/LICENSE +6 -0
- asyncapi_tag-1.0.0/PKG-INFO +206 -0
- asyncapi_tag-1.0.0/README.md +169 -0
- asyncapi_tag-1.0.0/pyproject.toml +58 -0
- asyncapi_tag-1.0.0/setup.cfg +4 -0
- asyncapi_tag-1.0.0/src/asyncapi_tag/__init__.py +28 -0
- asyncapi_tag-1.0.0/src/asyncapi_tag/assets.py +106 -0
- asyncapi_tag-1.0.0/src/asyncapi_tag/extension.py +276 -0
- asyncapi_tag-1.0.0/src/asyncapi_tag/mkdocs_plugin.py +109 -0
- asyncapi_tag-1.0.0/src/asyncapi_tag.egg-info/PKG-INFO +206 -0
- asyncapi_tag-1.0.0/src/asyncapi_tag.egg-info/SOURCES.txt +16 -0
- asyncapi_tag-1.0.0/src/asyncapi_tag.egg-info/dependency_links.txt +1 -0
- asyncapi_tag-1.0.0/src/asyncapi_tag.egg-info/entry_points.txt +5 -0
- asyncapi_tag-1.0.0/src/asyncapi_tag.egg-info/requires.txt +8 -0
- asyncapi_tag-1.0.0/src/asyncapi_tag.egg-info/top_level.txt +1 -0
- asyncapi_tag-1.0.0/tests/test_extension.py +198 -0
- asyncapi_tag-1.0.0/tests/test_legacy_shim.py +30 -0
- asyncapi_tag-1.0.0/tests/test_mkdocs_plugin.py +164 -0
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright [2024] [Weesho Lapara]
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: asyncapi-tag
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Render AsyncAPI documents in Markdown with an <asyncapi-tag> element. Python-Markdown extension with a MkDocs plugin.
|
|
5
|
+
Author-email: Weesho Lapara <support@weesholapara.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Weesho-Lapara/asyncapi-tag
|
|
8
|
+
Project-URL: Changelog, https://github.com/Weesho-Lapara/asyncapi-tag/blob/main/CHANGELOG.md
|
|
9
|
+
Project-URL: Issues, https://github.com/Weesho-Lapara/asyncapi-tag/issues
|
|
10
|
+
Keywords: asyncapi,markdown,mkdocs,documentation,event-driven,api
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: Environment :: Web Environment
|
|
13
|
+
Classifier: Framework :: MkDocs
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
24
|
+
Classifier: Topic :: Documentation
|
|
25
|
+
Classifier: Topic :: Software Development :: Documentation
|
|
26
|
+
Classifier: Topic :: Text Processing :: Markup :: Markdown
|
|
27
|
+
Requires-Python: >=3.9
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
License-File: LICENSE
|
|
30
|
+
Requires-Dist: Markdown>=3.4
|
|
31
|
+
Provides-Extra: mkdocs
|
|
32
|
+
Requires-Dist: mkdocs>=1.5; extra == "mkdocs"
|
|
33
|
+
Provides-Extra: test
|
|
34
|
+
Requires-Dist: mkdocs>=1.5; extra == "test"
|
|
35
|
+
Requires-Dist: pytest>=7; extra == "test"
|
|
36
|
+
Dynamic: license-file
|
|
37
|
+
|
|
38
|
+
# asyncapi-tag
|
|
39
|
+
|
|
40
|
+
Render [AsyncAPI](https://www.asyncapi.com/) documents inside Markdown pages with a single element:
|
|
41
|
+
|
|
42
|
+
```html
|
|
43
|
+
<asyncapi-tag src="asyncapi.yaml"></asyncapi-tag>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`asyncapi-tag` is a [Python-Markdown](https://python-markdown.github.io/) extension, so it works in
|
|
47
|
+
any tool built on Python-Markdown. It ships with a plugin for [MkDocs](https://www.mkdocs.org/)
|
|
48
|
+
that resolves document paths the same way MkDocs resolves links. Rendering in the browser is done
|
|
49
|
+
by the official [AsyncAPI React component](https://github.com/asyncapi/asyncapi-react), pinned to
|
|
50
|
+
an exact version and loaded with Subresource Integrity. JSON and YAML documents both work.
|
|
51
|
+
|
|
52
|
+
> Formerly published as `mkdocs-asyncapi-tag-plugin`. See [Migrating](#migrating-from-mkdocs-asyncapi-tag-plugin).
|
|
53
|
+
|
|
54
|
+
## MkDocs
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
pip install asyncapi-tag
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
```yaml
|
|
61
|
+
# mkdocs.yml
|
|
62
|
+
plugins:
|
|
63
|
+
- asyncapi-tag
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Put your AsyncAPI file anywhere under `docs/` and reference it from a page. Paths are relative to
|
|
67
|
+
the Markdown file, or relative to `docs/` when they start with `/`. Absolute `http(s)://` URLs are
|
|
68
|
+
passed through unchanged.
|
|
69
|
+
|
|
70
|
+
```markdown
|
|
71
|
+
<!-- docs/api/events.md -->
|
|
72
|
+
# Events API
|
|
73
|
+
|
|
74
|
+
<asyncapi-tag src="events.yaml" sidebar="false"></asyncapi-tag>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
A missing document or an invalid attribute is reported as a MkDocs warning, so `mkdocs build
|
|
78
|
+
--strict` fails instead of shipping a broken page.
|
|
79
|
+
|
|
80
|
+
### Plugin options
|
|
81
|
+
|
|
82
|
+
```yaml
|
|
83
|
+
plugins:
|
|
84
|
+
- asyncapi-tag:
|
|
85
|
+
load_assets: true # emit the viewer script and stylesheet (default: true)
|
|
86
|
+
viewer_js: https://unpkg.com/@asyncapi/react-component@3.2.1/browser/standalone/index.js
|
|
87
|
+
viewer_js_integrity: sha384-… # set to '' to omit the integrity attribute
|
|
88
|
+
viewer_css: https://unpkg.com/@asyncapi/react-component@3.2.1/styles/default.min.css
|
|
89
|
+
viewer_css_integrity: sha384-…
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
To self-host the viewer, copy the two files into `docs/` and point the options at them.
|
|
93
|
+
Relative paths are resolved per page like `src` is:
|
|
94
|
+
|
|
95
|
+
```yaml
|
|
96
|
+
plugins:
|
|
97
|
+
- asyncapi-tag:
|
|
98
|
+
viewer_js: assets/asyncapi/index.js
|
|
99
|
+
viewer_js_integrity: ''
|
|
100
|
+
viewer_css: assets/asyncapi/default.min.css
|
|
101
|
+
viewer_css_integrity: ''
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Or set `load_assets: false` and load the files yourself through `extra_javascript` and
|
|
105
|
+
`extra_css`. The page-side runner script is still needed in that case; copy it from
|
|
106
|
+
`asyncapi_tag.assets.RUNNER_JS`.
|
|
107
|
+
|
|
108
|
+
## Plain Python-Markdown
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
import markdown
|
|
112
|
+
|
|
113
|
+
html = markdown.markdown(text, extensions=["asyncapi_tag"])
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Extension options (pass them as `extension_configs={"asyncapi_tag": {...}}`):
|
|
117
|
+
|
|
118
|
+
| Option | Default | Description |
|
|
119
|
+
|---|---|---|
|
|
120
|
+
| `viewer_js`, `viewer_css` | pinned unpkg URLs | Where to load the viewer from |
|
|
121
|
+
| `viewer_js_integrity`, `viewer_css_integrity` | matching SRI hashes | Empty string omits the attribute |
|
|
122
|
+
| `load_assets` | `True` | Emit the loader with the first tag on a page |
|
|
123
|
+
| `url_resolver` | identity | Callable mapping `src` (and relative asset URLs) to what the browser fetches |
|
|
124
|
+
| `warn` | `logging` | Callable receiving warning messages |
|
|
125
|
+
|
|
126
|
+
## Attributes
|
|
127
|
+
|
|
128
|
+
Only `src` is required. Attribute names are case-insensitive. Boolean attributes accept
|
|
129
|
+
`true`/`false`, `1`/`0`, `yes`/`no`, `on`/`off`; a bare attribute means `true`.
|
|
130
|
+
|
|
131
|
+
| Attribute | Values | Default | Effect |
|
|
132
|
+
|---|---|---|---|
|
|
133
|
+
| `src` | path or URL | required | The AsyncAPI document (JSON or YAML) |
|
|
134
|
+
| `id` | string | `asyncapi-tag-N` | HTML id of the container element |
|
|
135
|
+
| `sidebar` | boolean | `true` | Show the navigation sidebar |
|
|
136
|
+
| `info` | boolean | `true` | Show the info section |
|
|
137
|
+
| `servers` | boolean | `true` | Show servers |
|
|
138
|
+
| `operations` | boolean | `true` | Show operations |
|
|
139
|
+
| `messages` | boolean | `true` | Show messages |
|
|
140
|
+
| `schemas` | boolean | `true` | Show schemas |
|
|
141
|
+
| `errors` | boolean | `true` | Show parser errors |
|
|
142
|
+
| `showMessageExamples` | boolean | viewer default | Show examples for standalone messages |
|
|
143
|
+
| `messageExamples` | boolean | `true` | Expand message examples |
|
|
144
|
+
| `showServers` | `byDefault`, `bySpecTags`, `byServersTags` | `byDefault` | How the sidebar groups servers |
|
|
145
|
+
| `showOperations` | `byDefault`, `bySpecTags`, `byOperationsTags` | `byDefault` | How the sidebar groups operations |
|
|
146
|
+
| `useChannelAddressAsIdentifier` | boolean | viewer default | AsyncAPI v3: label operations by channel address |
|
|
147
|
+
| `publishLabel`, `subscribeLabel` | string | `PUB`, `SUB` | Operation labels for AsyncAPI v2 |
|
|
148
|
+
| `sendLabel`, `receiveLabel`, `requestLabel`, `replyLabel` | string | `SEND`, `RECEIVE`, `REQUEST`, `REPLY` | Operation labels for AsyncAPI v3 |
|
|
149
|
+
| `parserOptions` | JSON object | viewer default | Passed to the AsyncAPI parser, e.g. `parserOptions='{"applyTraits": false}'` |
|
|
150
|
+
| `schemaID` | string | container id | The viewer's `schemaID` option |
|
|
151
|
+
|
|
152
|
+
These map onto the React component's
|
|
153
|
+
[configuration](https://github.com/asyncapi/asyncapi-react/blob/master/docs/configuration/config-modification.md).
|
|
154
|
+
Defaults for `sidebar` and `messageExamples` follow earlier releases of this plugin rather than the
|
|
155
|
+
viewer, so existing pages keep their look.
|
|
156
|
+
|
|
157
|
+
## How it works
|
|
158
|
+
|
|
159
|
+
Each tag becomes a `<div class="asyncapi-tag">` carrying the document URL and the viewer
|
|
160
|
+
configuration as HTML-escaped data attributes. The first tag on a page also emits the viewer's
|
|
161
|
+
stylesheet and script and a short runner script. The runner fetches each document as text, hands it
|
|
162
|
+
to `AsyncApiStandalone.render`, and prints a visible error inside the container if fetching or
|
|
163
|
+
rendering fails. No content from the Markdown source is interpolated into JavaScript.
|
|
164
|
+
|
|
165
|
+
Tags inside fenced or indented code blocks are left alone, so you can document the syntax.
|
|
166
|
+
|
|
167
|
+
Material for MkDocs users with `navigation.instant` enabled are covered: the runner re-scans the
|
|
168
|
+
page on Material's `document$` event.
|
|
169
|
+
|
|
170
|
+
## Migrating from mkdocs-asyncapi-tag-plugin
|
|
171
|
+
|
|
172
|
+
1. Replace `mkdocs-asyncapi-tag-plugin` with `asyncapi-tag` in your requirements. The plugin id in
|
|
173
|
+
`mkdocs.yml` is unchanged (`asyncapi-tag`).
|
|
174
|
+
2. Remove the `asyncapi_file` plugin option. MkDocs already copies every non-Markdown file under
|
|
175
|
+
`docs/` into the site; the option now only prints a deprecation warning.
|
|
176
|
+
3. Use a path relative to the page (or `/`-prefixed relative to `docs/`) in `src`. Earlier versions
|
|
177
|
+
emitted the build machine's filesystem path, so only `/`-prefixed paths ever worked; those still work.
|
|
178
|
+
4. String attributes such as `publishLabel="PUBLISH"` and `showServers="bySpecTags"` now take
|
|
179
|
+
effect. Earlier versions silently discarded them.
|
|
180
|
+
|
|
181
|
+
`mkdocs-asyncapi-tag-plugin` 1.0.0 is a deprecated shim that only depends on this package, so
|
|
182
|
+
upgrading it also works, but no further releases will be made under the old name.
|
|
183
|
+
|
|
184
|
+
## Updating the pinned viewer
|
|
185
|
+
|
|
186
|
+
```sh
|
|
187
|
+
python scripts/update_viewer.py # latest @asyncapi/react-component
|
|
188
|
+
python scripts/update_viewer.py 3.2.1 # specific version
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
The script rewrites the version, URLs and SRI hashes in `src/asyncapi_tag/assets.py`.
|
|
192
|
+
|
|
193
|
+
## Development
|
|
194
|
+
|
|
195
|
+
```sh
|
|
196
|
+
python -m venv .venv && source .venv/bin/activate
|
|
197
|
+
pip install -e ".[test]"
|
|
198
|
+
pytest
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
The JavaScript runner is syntax-checked with `node` when it is installed. See `AGENTS.md` for the
|
|
202
|
+
repository layout and release procedure.
|
|
203
|
+
|
|
204
|
+
## License
|
|
205
|
+
|
|
206
|
+
MIT
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# asyncapi-tag
|
|
2
|
+
|
|
3
|
+
Render [AsyncAPI](https://www.asyncapi.com/) documents inside Markdown pages with a single element:
|
|
4
|
+
|
|
5
|
+
```html
|
|
6
|
+
<asyncapi-tag src="asyncapi.yaml"></asyncapi-tag>
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
`asyncapi-tag` is a [Python-Markdown](https://python-markdown.github.io/) extension, so it works in
|
|
10
|
+
any tool built on Python-Markdown. It ships with a plugin for [MkDocs](https://www.mkdocs.org/)
|
|
11
|
+
that resolves document paths the same way MkDocs resolves links. Rendering in the browser is done
|
|
12
|
+
by the official [AsyncAPI React component](https://github.com/asyncapi/asyncapi-react), pinned to
|
|
13
|
+
an exact version and loaded with Subresource Integrity. JSON and YAML documents both work.
|
|
14
|
+
|
|
15
|
+
> Formerly published as `mkdocs-asyncapi-tag-plugin`. See [Migrating](#migrating-from-mkdocs-asyncapi-tag-plugin).
|
|
16
|
+
|
|
17
|
+
## MkDocs
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
pip install asyncapi-tag
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
```yaml
|
|
24
|
+
# mkdocs.yml
|
|
25
|
+
plugins:
|
|
26
|
+
- asyncapi-tag
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Put your AsyncAPI file anywhere under `docs/` and reference it from a page. Paths are relative to
|
|
30
|
+
the Markdown file, or relative to `docs/` when they start with `/`. Absolute `http(s)://` URLs are
|
|
31
|
+
passed through unchanged.
|
|
32
|
+
|
|
33
|
+
```markdown
|
|
34
|
+
<!-- docs/api/events.md -->
|
|
35
|
+
# Events API
|
|
36
|
+
|
|
37
|
+
<asyncapi-tag src="events.yaml" sidebar="false"></asyncapi-tag>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
A missing document or an invalid attribute is reported as a MkDocs warning, so `mkdocs build
|
|
41
|
+
--strict` fails instead of shipping a broken page.
|
|
42
|
+
|
|
43
|
+
### Plugin options
|
|
44
|
+
|
|
45
|
+
```yaml
|
|
46
|
+
plugins:
|
|
47
|
+
- asyncapi-tag:
|
|
48
|
+
load_assets: true # emit the viewer script and stylesheet (default: true)
|
|
49
|
+
viewer_js: https://unpkg.com/@asyncapi/react-component@3.2.1/browser/standalone/index.js
|
|
50
|
+
viewer_js_integrity: sha384-… # set to '' to omit the integrity attribute
|
|
51
|
+
viewer_css: https://unpkg.com/@asyncapi/react-component@3.2.1/styles/default.min.css
|
|
52
|
+
viewer_css_integrity: sha384-…
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
To self-host the viewer, copy the two files into `docs/` and point the options at them.
|
|
56
|
+
Relative paths are resolved per page like `src` is:
|
|
57
|
+
|
|
58
|
+
```yaml
|
|
59
|
+
plugins:
|
|
60
|
+
- asyncapi-tag:
|
|
61
|
+
viewer_js: assets/asyncapi/index.js
|
|
62
|
+
viewer_js_integrity: ''
|
|
63
|
+
viewer_css: assets/asyncapi/default.min.css
|
|
64
|
+
viewer_css_integrity: ''
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Or set `load_assets: false` and load the files yourself through `extra_javascript` and
|
|
68
|
+
`extra_css`. The page-side runner script is still needed in that case; copy it from
|
|
69
|
+
`asyncapi_tag.assets.RUNNER_JS`.
|
|
70
|
+
|
|
71
|
+
## Plain Python-Markdown
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
import markdown
|
|
75
|
+
|
|
76
|
+
html = markdown.markdown(text, extensions=["asyncapi_tag"])
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Extension options (pass them as `extension_configs={"asyncapi_tag": {...}}`):
|
|
80
|
+
|
|
81
|
+
| Option | Default | Description |
|
|
82
|
+
|---|---|---|
|
|
83
|
+
| `viewer_js`, `viewer_css` | pinned unpkg URLs | Where to load the viewer from |
|
|
84
|
+
| `viewer_js_integrity`, `viewer_css_integrity` | matching SRI hashes | Empty string omits the attribute |
|
|
85
|
+
| `load_assets` | `True` | Emit the loader with the first tag on a page |
|
|
86
|
+
| `url_resolver` | identity | Callable mapping `src` (and relative asset URLs) to what the browser fetches |
|
|
87
|
+
| `warn` | `logging` | Callable receiving warning messages |
|
|
88
|
+
|
|
89
|
+
## Attributes
|
|
90
|
+
|
|
91
|
+
Only `src` is required. Attribute names are case-insensitive. Boolean attributes accept
|
|
92
|
+
`true`/`false`, `1`/`0`, `yes`/`no`, `on`/`off`; a bare attribute means `true`.
|
|
93
|
+
|
|
94
|
+
| Attribute | Values | Default | Effect |
|
|
95
|
+
|---|---|---|---|
|
|
96
|
+
| `src` | path or URL | required | The AsyncAPI document (JSON or YAML) |
|
|
97
|
+
| `id` | string | `asyncapi-tag-N` | HTML id of the container element |
|
|
98
|
+
| `sidebar` | boolean | `true` | Show the navigation sidebar |
|
|
99
|
+
| `info` | boolean | `true` | Show the info section |
|
|
100
|
+
| `servers` | boolean | `true` | Show servers |
|
|
101
|
+
| `operations` | boolean | `true` | Show operations |
|
|
102
|
+
| `messages` | boolean | `true` | Show messages |
|
|
103
|
+
| `schemas` | boolean | `true` | Show schemas |
|
|
104
|
+
| `errors` | boolean | `true` | Show parser errors |
|
|
105
|
+
| `showMessageExamples` | boolean | viewer default | Show examples for standalone messages |
|
|
106
|
+
| `messageExamples` | boolean | `true` | Expand message examples |
|
|
107
|
+
| `showServers` | `byDefault`, `bySpecTags`, `byServersTags` | `byDefault` | How the sidebar groups servers |
|
|
108
|
+
| `showOperations` | `byDefault`, `bySpecTags`, `byOperationsTags` | `byDefault` | How the sidebar groups operations |
|
|
109
|
+
| `useChannelAddressAsIdentifier` | boolean | viewer default | AsyncAPI v3: label operations by channel address |
|
|
110
|
+
| `publishLabel`, `subscribeLabel` | string | `PUB`, `SUB` | Operation labels for AsyncAPI v2 |
|
|
111
|
+
| `sendLabel`, `receiveLabel`, `requestLabel`, `replyLabel` | string | `SEND`, `RECEIVE`, `REQUEST`, `REPLY` | Operation labels for AsyncAPI v3 |
|
|
112
|
+
| `parserOptions` | JSON object | viewer default | Passed to the AsyncAPI parser, e.g. `parserOptions='{"applyTraits": false}'` |
|
|
113
|
+
| `schemaID` | string | container id | The viewer's `schemaID` option |
|
|
114
|
+
|
|
115
|
+
These map onto the React component's
|
|
116
|
+
[configuration](https://github.com/asyncapi/asyncapi-react/blob/master/docs/configuration/config-modification.md).
|
|
117
|
+
Defaults for `sidebar` and `messageExamples` follow earlier releases of this plugin rather than the
|
|
118
|
+
viewer, so existing pages keep their look.
|
|
119
|
+
|
|
120
|
+
## How it works
|
|
121
|
+
|
|
122
|
+
Each tag becomes a `<div class="asyncapi-tag">` carrying the document URL and the viewer
|
|
123
|
+
configuration as HTML-escaped data attributes. The first tag on a page also emits the viewer's
|
|
124
|
+
stylesheet and script and a short runner script. The runner fetches each document as text, hands it
|
|
125
|
+
to `AsyncApiStandalone.render`, and prints a visible error inside the container if fetching or
|
|
126
|
+
rendering fails. No content from the Markdown source is interpolated into JavaScript.
|
|
127
|
+
|
|
128
|
+
Tags inside fenced or indented code blocks are left alone, so you can document the syntax.
|
|
129
|
+
|
|
130
|
+
Material for MkDocs users with `navigation.instant` enabled are covered: the runner re-scans the
|
|
131
|
+
page on Material's `document$` event.
|
|
132
|
+
|
|
133
|
+
## Migrating from mkdocs-asyncapi-tag-plugin
|
|
134
|
+
|
|
135
|
+
1. Replace `mkdocs-asyncapi-tag-plugin` with `asyncapi-tag` in your requirements. The plugin id in
|
|
136
|
+
`mkdocs.yml` is unchanged (`asyncapi-tag`).
|
|
137
|
+
2. Remove the `asyncapi_file` plugin option. MkDocs already copies every non-Markdown file under
|
|
138
|
+
`docs/` into the site; the option now only prints a deprecation warning.
|
|
139
|
+
3. Use a path relative to the page (or `/`-prefixed relative to `docs/`) in `src`. Earlier versions
|
|
140
|
+
emitted the build machine's filesystem path, so only `/`-prefixed paths ever worked; those still work.
|
|
141
|
+
4. String attributes such as `publishLabel="PUBLISH"` and `showServers="bySpecTags"` now take
|
|
142
|
+
effect. Earlier versions silently discarded them.
|
|
143
|
+
|
|
144
|
+
`mkdocs-asyncapi-tag-plugin` 1.0.0 is a deprecated shim that only depends on this package, so
|
|
145
|
+
upgrading it also works, but no further releases will be made under the old name.
|
|
146
|
+
|
|
147
|
+
## Updating the pinned viewer
|
|
148
|
+
|
|
149
|
+
```sh
|
|
150
|
+
python scripts/update_viewer.py # latest @asyncapi/react-component
|
|
151
|
+
python scripts/update_viewer.py 3.2.1 # specific version
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
The script rewrites the version, URLs and SRI hashes in `src/asyncapi_tag/assets.py`.
|
|
155
|
+
|
|
156
|
+
## Development
|
|
157
|
+
|
|
158
|
+
```sh
|
|
159
|
+
python -m venv .venv && source .venv/bin/activate
|
|
160
|
+
pip install -e ".[test]"
|
|
161
|
+
pytest
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
The JavaScript runner is syntax-checked with `node` when it is installed. See `AGENTS.md` for the
|
|
165
|
+
repository layout and release procedure.
|
|
166
|
+
|
|
167
|
+
## License
|
|
168
|
+
|
|
169
|
+
MIT
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "asyncapi-tag"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "Render AsyncAPI documents in Markdown with an <asyncapi-tag> element. Python-Markdown extension with a MkDocs plugin."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
license-files = ["LICENSE"]
|
|
12
|
+
requires-python = ">=3.9"
|
|
13
|
+
authors = [{ name = "Weesho Lapara", email = "support@weesholapara.com" }]
|
|
14
|
+
keywords = ["asyncapi", "markdown", "mkdocs", "documentation", "event-driven", "api"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 5 - Production/Stable",
|
|
17
|
+
"Environment :: Web Environment",
|
|
18
|
+
"Framework :: MkDocs",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"Operating System :: OS Independent",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
23
|
+
"Programming Language :: Python :: 3.9",
|
|
24
|
+
"Programming Language :: Python :: 3.10",
|
|
25
|
+
"Programming Language :: Python :: 3.11",
|
|
26
|
+
"Programming Language :: Python :: 3.12",
|
|
27
|
+
"Programming Language :: Python :: 3.13",
|
|
28
|
+
"Programming Language :: Python :: 3.14",
|
|
29
|
+
"Topic :: Documentation",
|
|
30
|
+
"Topic :: Software Development :: Documentation",
|
|
31
|
+
"Topic :: Text Processing :: Markup :: Markdown",
|
|
32
|
+
]
|
|
33
|
+
dependencies = ["Markdown>=3.4"]
|
|
34
|
+
|
|
35
|
+
[project.optional-dependencies]
|
|
36
|
+
mkdocs = ["mkdocs>=1.5"]
|
|
37
|
+
test = ["mkdocs>=1.5", "pytest>=7"]
|
|
38
|
+
|
|
39
|
+
[project.urls]
|
|
40
|
+
Homepage = "https://github.com/Weesho-Lapara/asyncapi-tag"
|
|
41
|
+
Changelog = "https://github.com/Weesho-Lapara/asyncapi-tag/blob/main/CHANGELOG.md"
|
|
42
|
+
Issues = "https://github.com/Weesho-Lapara/asyncapi-tag/issues"
|
|
43
|
+
|
|
44
|
+
[project.entry-points."markdown.extensions"]
|
|
45
|
+
asyncapi_tag = "asyncapi_tag.extension:AsyncAPITagExtension"
|
|
46
|
+
|
|
47
|
+
[project.entry-points."mkdocs.plugins"]
|
|
48
|
+
asyncapi-tag = "asyncapi_tag.mkdocs_plugin:AsyncAPIPlugin"
|
|
49
|
+
|
|
50
|
+
[tool.setuptools.dynamic]
|
|
51
|
+
version = { attr = "asyncapi_tag.__version__" }
|
|
52
|
+
|
|
53
|
+
[tool.setuptools.packages.find]
|
|
54
|
+
where = ["src"]
|
|
55
|
+
|
|
56
|
+
[tool.pytest.ini_options]
|
|
57
|
+
testpaths = ["tests"]
|
|
58
|
+
addopts = "-ra"
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""Render AsyncAPI documents in Markdown with an ``<asyncapi-tag>`` element.
|
|
2
|
+
|
|
3
|
+
The package is a `Python-Markdown <https://python-markdown.github.io/>`_
|
|
4
|
+
extension (:class:`asyncapi_tag.extension.AsyncAPITagExtension`) and a thin
|
|
5
|
+
MkDocs plugin around it (:class:`asyncapi_tag.mkdocs_plugin.AsyncAPIPlugin`).
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from asyncapi_tag.assets import (
|
|
9
|
+
VIEWER_CSS_INTEGRITY,
|
|
10
|
+
VIEWER_CSS_URL,
|
|
11
|
+
VIEWER_JS_INTEGRITY,
|
|
12
|
+
VIEWER_JS_URL,
|
|
13
|
+
VIEWER_VERSION,
|
|
14
|
+
)
|
|
15
|
+
from asyncapi_tag.extension import AsyncAPITagExtension, makeExtension
|
|
16
|
+
|
|
17
|
+
__version__ = "1.0.0"
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
"AsyncAPITagExtension",
|
|
21
|
+
"makeExtension",
|
|
22
|
+
"VIEWER_VERSION",
|
|
23
|
+
"VIEWER_JS_URL",
|
|
24
|
+
"VIEWER_JS_INTEGRITY",
|
|
25
|
+
"VIEWER_CSS_URL",
|
|
26
|
+
"VIEWER_CSS_INTEGRITY",
|
|
27
|
+
"__version__",
|
|
28
|
+
]
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"""Pinned viewer assets and the browser-side loader.
|
|
2
|
+
|
|
3
|
+
The viewer is the standalone bundle of ``@asyncapi/react-component``. The
|
|
4
|
+
version, URLs and Subresource Integrity hashes below are updated together
|
|
5
|
+
with ``scripts/update_viewer.py``; do not edit them by hand.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import html
|
|
11
|
+
|
|
12
|
+
# --- managed by scripts/update_viewer.py ------------------------------------
|
|
13
|
+
VIEWER_VERSION = "3.2.1"
|
|
14
|
+
VIEWER_JS_URL = "https://unpkg.com/@asyncapi/react-component@3.2.1/browser/standalone/index.js"
|
|
15
|
+
VIEWER_JS_INTEGRITY = "sha384-wy5bSOazlkSKMGH7XMW6+pK8ho8+rCPr7mTqKdAb/dvfwXAPWCFivgr3C7wJMFAh"
|
|
16
|
+
VIEWER_CSS_URL = "https://unpkg.com/@asyncapi/react-component@3.2.1/styles/default.min.css"
|
|
17
|
+
VIEWER_CSS_INTEGRITY = "sha384-oo9RoQcacP++XdMX6CjTucTvASEORHX3chFik0/V2kHcsHiVboGyWZztGeq/0bum"
|
|
18
|
+
# ---------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
CONTAINER_CLASS = "asyncapi-tag"
|
|
21
|
+
|
|
22
|
+
# Runs once per page. It finds every container the extension emitted, fetches
|
|
23
|
+
# the AsyncAPI document as text (JSON or YAML, the viewer parses both) and
|
|
24
|
+
# renders it. Nothing from the Markdown source is interpolated into this
|
|
25
|
+
# script: per-tag data travels in HTML data attributes, which are HTML-escaped.
|
|
26
|
+
RUNNER_JS = """\
|
|
27
|
+
(function () {
|
|
28
|
+
"use strict";
|
|
29
|
+
var SELECTOR = ".asyncapi-tag[data-asyncapi-src]";
|
|
30
|
+
function showError(el, message) {
|
|
31
|
+
el.textContent = "";
|
|
32
|
+
var p = document.createElement("p");
|
|
33
|
+
p.className = "asyncapi-tag-error";
|
|
34
|
+
p.textContent = "AsyncAPI viewer: " + message;
|
|
35
|
+
el.appendChild(p);
|
|
36
|
+
}
|
|
37
|
+
function render(el) {
|
|
38
|
+
if (el.getAttribute("data-asyncapi-state")) { return; }
|
|
39
|
+
el.setAttribute("data-asyncapi-state", "loading");
|
|
40
|
+
var src = el.getAttribute("data-asyncapi-src");
|
|
41
|
+
var config = {};
|
|
42
|
+
try {
|
|
43
|
+
config = JSON.parse(el.getAttribute("data-asyncapi-config") || "{}");
|
|
44
|
+
} catch (err) {
|
|
45
|
+
showError(el, "invalid configuration (" + err.message + ")");
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (!window.AsyncApiStandalone) {
|
|
49
|
+
showError(el, "the viewer script did not load; check the browser console and any Content Security Policy.");
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
fetch(src, { credentials: "same-origin" }).then(function (response) {
|
|
53
|
+
if (!response.ok) {
|
|
54
|
+
throw new Error("could not fetch " + src + " (HTTP " + response.status + ")");
|
|
55
|
+
}
|
|
56
|
+
return response.text();
|
|
57
|
+
}).then(function (text) {
|
|
58
|
+
return window.AsyncApiStandalone.render({ schema: text, config: config }, el);
|
|
59
|
+
}).then(function () {
|
|
60
|
+
el.setAttribute("data-asyncapi-state", "rendered");
|
|
61
|
+
}).catch(function (err) {
|
|
62
|
+
showError(el, err && err.message ? err.message : String(err));
|
|
63
|
+
if (window.console) { console.error("asyncapi-tag:", err); }
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
function renderAll() {
|
|
67
|
+
var nodes = document.querySelectorAll(SELECTOR);
|
|
68
|
+
for (var i = 0; i < nodes.length; i++) { render(nodes[i]); }
|
|
69
|
+
}
|
|
70
|
+
renderAll();
|
|
71
|
+
/* Material for MkDocs instant navigation swaps page content without a reload. */
|
|
72
|
+
if (window.document$ && typeof window.document$.subscribe === "function") {
|
|
73
|
+
window.document$.subscribe(renderAll);
|
|
74
|
+
}
|
|
75
|
+
})();
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _attr(name: str, value: str) -> str:
|
|
80
|
+
return f' {name}="{html.escape(value, quote=True)}"'
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def loader_html(
|
|
84
|
+
js_url: str,
|
|
85
|
+
css_url: str,
|
|
86
|
+
js_integrity: str = "",
|
|
87
|
+
css_integrity: str = "",
|
|
88
|
+
) -> str:
|
|
89
|
+
"""Return the HTML that loads the viewer and runs it on the page.
|
|
90
|
+
|
|
91
|
+
Integrity attributes are emitted only when a hash is given, so the loader
|
|
92
|
+
also works for self-hosted copies of the viewer.
|
|
93
|
+
"""
|
|
94
|
+
parts = []
|
|
95
|
+
if css_url:
|
|
96
|
+
attrs = _attr("rel", "stylesheet") + _attr("href", css_url)
|
|
97
|
+
if css_integrity:
|
|
98
|
+
attrs += _attr("integrity", css_integrity) + _attr("crossorigin", "anonymous")
|
|
99
|
+
parts.append(f"<link{attrs}>")
|
|
100
|
+
if js_url:
|
|
101
|
+
attrs = _attr("src", js_url)
|
|
102
|
+
if js_integrity:
|
|
103
|
+
attrs += _attr("integrity", js_integrity) + _attr("crossorigin", "anonymous")
|
|
104
|
+
parts.append(f"<script{attrs}></script>")
|
|
105
|
+
parts.append(f"<script>{RUNNER_JS}</script>")
|
|
106
|
+
return "\n".join(parts)
|