Skip to content

Commit 9d82ca4

Browse files
committed
maybe done
1 parent 2a0656a commit 9d82ca4

5 files changed

Lines changed: 62 additions & 32 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ TAGS ?= dev
77
docs:
88
@echo "==> Deploying MkDocs documentation locally via mike (Tags: $(TAGS))..."
99
doxygen Doxyfile
10-
uv run python scripts/gen_concept_docs.py --config docs/concept_groups.json --xml documentation/xml --out docs/cpp-gl
10+
uv run python scripts/gen_concept_docs.py --config docs/concepts_cfg.json --xml documentation/xml --out docs/cpp-gl
1111
uv run mike deploy $(TAGS)
1212
@echo "==> Documentation deployed to local gh-pages branch."
1313

docs/concept_groups.json

Lines changed: 0 additions & 16 deletions
This file was deleted.

docs/concepts_cfg.json

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"index": {
3+
"title": "Concepts API Reference",
4+
"anchor": "concepts-api-reference",
5+
"description": "This page serves as the central index for all C++20 concepts used across the library to enforce type safety and template constraints."
6+
},
7+
"groups": {
8+
"GL": {
9+
"prefix": "gl::",
10+
"filename": "gl_traits.md",
11+
"anchor": "gl-traits-concepts-documentation",
12+
"title": "GL Traits & Concepts",
13+
"description": "This page documents the C++20 concepts and type traits used to constrain templates across the GL library."
14+
},
15+
"HGL": {
16+
"prefix": "hgl::",
17+
"filename": "hgl_traits.md",
18+
"anchor": "hgl-traits-concepts-documentation",
19+
"title": "HGL Traits & Concepts",
20+
"description": "This page documents the C++20 concepts and type traits used to constrain templates across the HGL library."
21+
}
22+
}
23+
}

mkdocs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ nav:
2222
- Namespaces: cpp-gl/namespaces.md
2323
- Classes & Structs: cpp-gl/annotated.md
2424
- Class Hierarchy: cpp-gl/hierarchy.md
25-
- Concepts: cpp-gl/concepts.md
25+
- Traits & Concepts: cpp-gl/concepts.md
2626
- Files: cpp-gl/files.md
2727
- Todo List: cpp-gl/todo.md
2828
# - Bug List: cpp-gl/bug.md

scripts/gen_concept_docs.py

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
from pathlib import Path
66
from dataclasses import dataclass
77

8+
89
@dataclass
910
class TParamDescriptor:
1011
name: str
1112
desc: str
1213

14+
1315
@dataclass
1416
class ConceptDescriptor:
1517
name: str
@@ -19,11 +21,21 @@ class ConceptDescriptor:
1921
params: list[TParamDescriptor]
2022
definition: str
2123

24+
2225
class ConceptParser:
23-
def __init__(self, xml_dir: Path, out_dir: Path, groups: dict):
26+
def __init__(self, xml_dir: Path, out_dir: Path, config: dict):
2427
self.xml_dir = xml_dir
2528
self.out_dir = out_dir
26-
self.groups = groups
29+
30+
# Extract the index configuration
31+
self.index_config = config.get("index")
32+
if not self.index_config:
33+
raise ValueError(
34+
"Configuration must include an 'index' block with title, anchor, and description."
35+
)
36+
37+
self.groups = config.get("groups", {})
38+
2739
self.concept_links = {} # Registry mapping refid -> file#anchor
2840
self.categorized_concepts = {key: [] for key in self.groups.keys()}
2941

@@ -72,7 +84,7 @@ def _xml_to_md(self, elem: ET.Element) -> str:
7284
# SMART LINK MERGE:
7385
# Prevents wrapping a Markdown link in backticks, which breaks the link.
7486
# Instead, it places backticks INSIDE the brackets.
75-
match = re.fullmatch(r'\[(`?)(.*?)\1\]\((.*?)\)', inner.strip())
87+
match = re.fullmatch(r"\[(`?)(.*?)\1\]\((.*?)\)", inner.strip())
7688
if match:
7789
res += f"[`{match.group(2)}`]({match.group(3)})"
7890
elif "](" in inner:
@@ -144,10 +156,14 @@ def _parse_concept_xml(self, xml_path: Path) -> ConceptDescriptor | None:
144156

145157
detailed_desc = root.find("detaileddescription")
146158
if detailed_desc is not None:
147-
for param_list in detailed_desc.findall('.//parameterlist[@kind="templateparam"]'):
159+
for param_list in detailed_desc.findall(
160+
'.//parameterlist[@kind="templateparam"]'
161+
):
148162
for item in param_list.findall("parameteritem"):
149163
p_name = self._xml_to_md(item.find(".//parametername")).strip()
150-
p_desc = self._xml_to_md(item.find(".//parameterdescription")).strip()
164+
p_desc = self._xml_to_md(
165+
item.find(".//parameterdescription")
166+
).strip()
151167
params.append(TParamDescriptor(name=p_name, desc=p_desc))
152168
param_list.clear()
153169

@@ -165,7 +181,9 @@ def _parse_concept_xml(self, xml_path: Path) -> ConceptDescriptor | None:
165181
tpl_nodes = root.findall(".//templateparamlist/param")
166182
tpl_strings = [self._get_text(p).strip() for p in tpl_nodes]
167183
template_decl += ", ".join(tpl_strings) + ">\n"
168-
definition = f"{template_decl}concept {name.split('::')[-1]} = {constraint};"
184+
definition = (
185+
f"{template_decl}concept {name.split('::')[-1]} = {constraint};"
186+
)
169187

170188
return ConceptDescriptor(
171189
name=name,
@@ -180,7 +198,9 @@ def process(self):
180198
"""Main execution flow: builds registry, parses data, and generates markdown."""
181199
index_xml = self.xml_dir / "index.xml"
182200
if not index_xml.exists():
183-
print(f"Error: Could not find Doxygen index at {index_xml}. Run Doxygen first.")
201+
print(
202+
f"Error: Could not find Doxygen index at {index_xml}. Run Doxygen first."
203+
)
184204
return
185205

186206
tree = ET.parse(index_xml)
@@ -246,8 +266,8 @@ def _generate_group_files(self):
246266

247267
def _generate_index_file(self):
248268
"""Generates the central API index mapping to all grouped concepts."""
249-
md = "# Concepts API Reference {: #concepts-api-reference }\n\n"
250-
md += "This page serves as the central index for all C++20 concepts used across the library to enforce type safety and template constraints.\n\n---\n\n"
269+
md = f"# {self.index_config['title']} {{: #{self.index_config['anchor']} }}\n\n"
270+
md += f"{self.index_config['description']}\n\n---\n\n"
251271

252272
for group_key, group_info in self.groups.items():
253273
md += f"## {group_key} Concepts\n\n"
@@ -266,11 +286,14 @@ def _generate_index_file(self):
266286
index_path.write_text(md, encoding="utf-8")
267287
print(f"Generated {index_path} (API Index)")
268288

289+
269290
if __name__ == "__main__":
270291
parser = argparse.ArgumentParser()
271-
parser.add_argument("--xml", default="xml", type=Path, help="Path to Doxygen XML output")
272-
parser.add_argument("--out", default="docs/cpp-gl", type=Path, help="Path to MkDocs output folder")
273-
parser.add_argument("--config", default="groups.json", type=Path, help="Path to the groups JSON configuration file")
292+
parser.add_argument("--xml", type=Path, help="Path to Doxygen XML output")
293+
parser.add_argument("--out", type=Path, help="Path to MkDocs output folder")
294+
parser.add_argument(
295+
"--config", type=Path, help="Path to the groups JSON configuration file"
296+
)
274297
args = parser.parse_args()
275298

276299
# Load configuration from JSON
@@ -279,7 +302,7 @@ def _generate_index_file(self):
279302
exit(1)
280303

281304
with open(args.config, "r", encoding="utf-8") as f:
282-
groups_config = json.load(f)
305+
config = json.load(f)
283306

284-
app = ConceptParser(args.xml, args.out, groups=groups_config)
307+
app = ConceptParser(args.xml, args.out, config=config)
285308
app.process()

0 commit comments

Comments
 (0)