mkdocs-techdocs-frontmatter 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,171 @@
1
+ import html
2
+ import json
3
+ from typing import Any
4
+
5
+ import yaml
6
+ from markdown.extensions import Extension
7
+ from markdown.preprocessors import Preprocessor
8
+
9
+
10
+ def _stringify(value: Any) -> str:
11
+ if value is None:
12
+ return ""
13
+ if isinstance(value, bool):
14
+ return "Yes" if value else "No"
15
+ if isinstance(value, (list, tuple)):
16
+ return ", ".join(_stringify(entry) for entry in value if _stringify(entry))
17
+ if isinstance(value, dict):
18
+ return json.dumps(value, default=str, ensure_ascii=False)
19
+ return str(value)
20
+
21
+
22
+ def _default_label(key: str) -> str:
23
+ return key.replace("_", " ").replace("-", " ").title()
24
+
25
+
26
+ def _as_bool(value: Any, default: bool) -> bool:
27
+ if isinstance(value, bool):
28
+ return value
29
+
30
+ if isinstance(value, str):
31
+ normalized = value.strip().lower()
32
+ if normalized in ("true", "yes", "1", "on"):
33
+ return True
34
+ if normalized in ("false", "no", "0", "off"):
35
+ return False
36
+
37
+ return default
38
+
39
+
40
+ def _render_key(options: dict[str, Any]) -> str:
41
+ return options.get("render_key") or "techdocs_frontmatter_render"
42
+
43
+
44
+ def _should_render(metadata: dict[str, Any], options: dict[str, Any]) -> bool:
45
+ default_render = _as_bool(options.get("render"), True)
46
+ render_key = _render_key(options)
47
+
48
+ if render_key in metadata:
49
+ return _as_bool(metadata[render_key], default_render)
50
+
51
+ return default_render
52
+
53
+
54
+ def _select_items(metadata: dict[str, Any], options: dict[str, Any]) -> list[tuple[str, str, str]]:
55
+ include = options.get("include") or metadata.keys()
56
+ exclude = set(options.get("exclude") or [])
57
+ labels = options.get("labels") or {}
58
+ if options.get("exclude_render_key", True):
59
+ exclude.add(_render_key(options))
60
+ items = []
61
+
62
+ for key in include:
63
+ if key in exclude or key not in metadata:
64
+ continue
65
+
66
+ value = _stringify(metadata[key])
67
+ if not value:
68
+ continue
69
+
70
+ items.append((key, labels.get(key) or _default_label(key), value))
71
+
72
+ return items
73
+
74
+
75
+ def _render_metadata(metadata: dict[str, Any], options: dict[str, Any]) -> list[str]:
76
+ items = _select_items(metadata, options)
77
+ if not items:
78
+ return []
79
+
80
+ title = options.get("title") or "Article metadata"
81
+ render = _should_render(metadata, options)
82
+ payload = json.dumps(
83
+ {key: value for key, _label, value in items},
84
+ ensure_ascii=False,
85
+ )
86
+ if not render:
87
+ lines = [
88
+ '<div hidden data-techdocs-frontmatter data-techdocs-frontmatter-render="false">',
89
+ f' <code hidden data-techdocs-frontmatter-json>{html.escape(payload)}</code>',
90
+ f' <span>{html.escape(title)}</span>',
91
+ ]
92
+
93
+ for _key, label, value in items:
94
+ lines.append(f' <span>{html.escape(label)}: {html.escape(value)}</span>')
95
+
96
+ lines.extend(['</div>', ''])
97
+ return lines
98
+
99
+ lines = [
100
+ f'<aside class="techdocs-frontmatter" data-techdocs-frontmatter aria-label="{html.escape(title)}">',
101
+ f' <code hidden data-techdocs-frontmatter-json>{html.escape(payload)}</code>',
102
+ f' <p class="techdocs-frontmatter__heading">{html.escape(title)}</p>',
103
+ ' <dl class="techdocs-frontmatter__list">',
104
+ ]
105
+
106
+ for key, label, value in items:
107
+ lines.extend(
108
+ [
109
+ f' <div class="techdocs-frontmatter__row" data-techdocs-frontmatter-key="{html.escape(key)}">',
110
+ f' <dt>{html.escape(label)}</dt>',
111
+ f' <dd>{html.escape(value)}</dd>',
112
+ ' </div>',
113
+ ],
114
+ )
115
+
116
+ lines.extend([' </dl>', '</aside>', ''])
117
+ return lines
118
+
119
+
120
+ class FrontmatterMetadataPreprocessor(Preprocessor):
121
+ def __init__(self, options: dict[str, Any]) -> None:
122
+ super().__init__()
123
+ self.options = options
124
+
125
+ def run(self, lines: list[str]) -> list[str]:
126
+ if not lines or lines[0].strip() != '---':
127
+ return lines
128
+
129
+ end_index = next(
130
+ (
131
+ index
132
+ for index, line in enumerate(lines[1:], start=1)
133
+ if line.strip() in ('---', '...')
134
+ ),
135
+ None,
136
+ )
137
+ if end_index is None:
138
+ return lines
139
+
140
+ metadata = yaml.safe_load('\n'.join(lines[1:end_index])) or {}
141
+ if not isinstance(metadata, dict):
142
+ return lines
143
+
144
+ metadata_lines = _render_metadata(metadata, self.options)
145
+ if not metadata_lines:
146
+ return lines
147
+
148
+ return lines[: end_index + 1] + metadata_lines + lines[end_index + 1 :]
149
+
150
+
151
+ class FrontmatterMetadataExtension(Extension):
152
+ config = {
153
+ 'title': ['Article metadata', 'Title shown above rendered frontmatter metadata.'],
154
+ 'render': [True, 'Whether to visibly render the metadata block in generated documentation.'],
155
+ 'render_key': ['techdocs_frontmatter_render', 'Frontmatter key that can override whether metadata is rendered for one page.'],
156
+ 'exclude_render_key': [True, 'Whether to omit the render control key from emitted/indexed frontmatter metadata.'],
157
+ 'include': [None, 'Only render these frontmatter keys, in this order.'],
158
+ 'exclude': [None, 'Hide these frontmatter keys.'],
159
+ 'labels': [{}, 'User-facing labels for frontmatter keys.'],
160
+ }
161
+
162
+ def extendMarkdown(self, md):
163
+ md.preprocessors.register(
164
+ FrontmatterMetadataPreprocessor(self.getConfigs()),
165
+ 'frontmatter_metadata',
166
+ 100,
167
+ )
168
+
169
+
170
+ def makeExtension(**kwargs):
171
+ return FrontmatterMetadataExtension(**kwargs)
@@ -0,0 +1,28 @@
1
+ from typing import Any
2
+
3
+ from mkdocs.config import config_options
4
+ from mkdocs.plugins import BasePlugin
5
+
6
+ from mkdocs_techdocs_frontmatter import _render_metadata
7
+
8
+
9
+ class TechDocsFrontmatterPlugin(BasePlugin):
10
+ config_scheme = (
11
+ ('title', config_options.Type(str, default='Article metadata')),
12
+ ('render', config_options.Type(bool, default=True)),
13
+ ('render_key', config_options.Type(str, default='techdocs_frontmatter_render')),
14
+ ('exclude_render_key', config_options.Type(bool, default=True)),
15
+ ('include', config_options.Type(list, default=[])),
16
+ ('exclude', config_options.Type(list, default=[])),
17
+ ('labels', config_options.Type(dict, default={})),
18
+ )
19
+
20
+ def on_page_markdown(self, markdown: str, page: Any, config: Any, files: Any) -> str:
21
+ metadata = getattr(page, 'meta', None) or {}
22
+ metadata_lines = _render_metadata(metadata, self.config)
23
+
24
+ if not metadata_lines:
25
+ return markdown
26
+
27
+ rendered = '\n'.join(metadata_lines)
28
+ return f"{rendered}\n{markdown}"
@@ -0,0 +1,62 @@
1
+ Metadata-Version: 2.4
2
+ Name: mkdocs-techdocs-frontmatter
3
+ Version: 0.1.0
4
+ Summary: Python-Markdown extension that renders TechDocs page frontmatter as searchable metadata.
5
+ Author: Gijs Reijn
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/Gijsreyn/backstage-plugin-techdocs-addon-frontmatter
8
+ Project-URL: Repository, https://github.com/Gijsreyn/backstage-plugin-techdocs-addon-frontmatter
9
+ Project-URL: Issues, https://github.com/Gijsreyn/backstage-plugin-techdocs-addon-frontmatter/issues
10
+ Keywords: mkdocs,mkdocs-plugin,techdocs,backstage,frontmatter
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3 :: Only
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Classifier: Topic :: Documentation
19
+ Classifier: Topic :: Software Development :: Documentation
20
+ Requires-Python: >=3.14
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: Markdown>=3.4
24
+ Requires-Dist: mkdocs>=1.6
25
+ Requires-Dist: PyYAML>=6.0
26
+ Dynamic: license-file
27
+
28
+ # mkdocs-techdocs-frontmatter
29
+
30
+ A [MkDocs](https://www.mkdocs.org/) plugin that emits YAML frontmatter from
31
+ Markdown pages as visible, indexable metadata during TechDocs generation.
32
+
33
+ Companion to the
34
+ [`backstage-plugin-techdocs-addon-frontmatter`](https://github.com/Gijsreyn/backstage-plugin-techdocs-addon-frontmatter)
35
+ Backstage TechDocs addon. See the repository README for full usage,
36
+ configuration, and integration with Backstage search.
37
+
38
+ ## Install
39
+
40
+ ```sh
41
+ pip install mkdocs-techdocs-frontmatter
42
+ ```
43
+
44
+ ## Enable
45
+
46
+ ```yaml
47
+ # mkdocs.yml
48
+ plugins:
49
+ - techdocs-core
50
+ - techdocs-frontmatter:
51
+ title: Article metadata
52
+ render: true
53
+ include: [type, author, last_review_date]
54
+ labels:
55
+ type: Type
56
+ author: Author
57
+ last_review_date: Last reviewed
58
+ ```
59
+
60
+ ## License
61
+
62
+ MIT
@@ -0,0 +1,8 @@
1
+ mkdocs_techdocs_frontmatter/__init__.py,sha256=PPSv-uUDRk726oW3PzboAyayv_1C71t9dscghkMGtg8,5768
2
+ mkdocs_techdocs_frontmatter/plugin.py,sha256=oLdEp9YQR5bSlowOQ3cfl3qn3SHIfLv5vhS5zeaQ7B8,1093
3
+ mkdocs_techdocs_frontmatter-0.1.0.dist-info/licenses/LICENSE,sha256=THGwJ7J29LE4sRhrjozYO_6a_Tsi8c0UlyA2R7ZD4Io,1088
4
+ mkdocs_techdocs_frontmatter-0.1.0.dist-info/METADATA,sha256=bGQ9YdxvGiREMhRmGCyDq1YXGO8AApAvt1IjCqeoFYU,2051
5
+ mkdocs_techdocs_frontmatter-0.1.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
6
+ mkdocs_techdocs_frontmatter-0.1.0.dist-info/entry_points.txt,sha256=N-F9CTzD3WL-Gmp_MQJI9j_9VENZRHvSjR1xQiBTQmI,101
7
+ mkdocs_techdocs_frontmatter-0.1.0.dist-info/top_level.txt,sha256=NzSwGVDW2uJ_kpm9phehbW4gwGtR3zHK2XYKC7SPDFU,28
8
+ mkdocs_techdocs_frontmatter-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (83.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [mkdocs.plugins]
2
+ techdocs-frontmatter = mkdocs_techdocs_frontmatter.plugin:TechDocsFrontmatterPlugin
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Gijs Reijn
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ mkdocs_techdocs_frontmatter