Skip to content

Commit 8f64db6

Browse files
committed
docs: simplify convert_docs.py to uni-directional conversion
The bi-directional support was initially implemented to migrate existing *.md files from MkDocs admonitions to GitHub-flavored markdown. With the migration complete, the reverse transformation is no longer needed. A uni-directional flow (GitHub -> MkDocs) is cleaner and sufficient for the build pipeline. It also adds a README.md file to explain what the scripts do.
1 parent a3a96fc commit 8f64db6

File tree

4 files changed

+80
-94
lines changed

4 files changed

+80
-94
lines changed

.github/workflows/docs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ jobs:
8383
done
8484
8585
- name: Convert Admonitions in Documentation
86-
run: python docs/scripts/convert_docs.py --mode github-to-mkdocs
86+
run: python docs/scripts/convert_docs.py
8787

8888
- name: Build Documentation (PR Check)
8989
if: github.event_name == 'pull_request'

docs/scripts/README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Documentation Transformation Scripts
2+
3+
This directory contains utility scripts to prepare our documentation for the **MkDocs** build process.
4+
5+
## Purpose
6+
7+
To ensure a great reading experience both on GitHub and the hosted site, we use **GitHub-flavored Markdown** as our primary source of truth. This script transforms GitHub's native syntax into **MkDocs-compatible syntax** (specifically for the `pymdown-extensions`) during the build pipeline.
8+
9+
## Supported Conversions (Uni-directional)
10+
11+
The script performs a uni-directional transformation: **GitHub Markdown → MkDocs Syntax**.
12+
13+
### Alert/Admonition Conversion
14+
15+
- GitHub uses a blockquote-based syntax for alerts.
16+
- MkDocs requires the `!!!` or `???` syntax to render colored callout boxes.
17+
18+
## Running the Conversion
19+
20+
The conversion is run as part of the build pipeline. No additional steps are required. If you need to run the conversion manually, you can run the `convert_docs.py` script in the repository root.
21+
22+
```bash
23+
python docs/scripts/convert_docs.py
24+
```
25+
26+
### Example
27+
28+
- **Source (GitHub-flavored Markdown):**
29+
```markdown
30+
> ⚠️ **Attention**
31+
>
32+
> This is an alert.
33+
```
34+
35+
- **Target (MkDocs Syntax):**
36+
```markdown
37+
!!! warning "Attention"
38+
This is an alert.
39+
```

docs/scripts/convert_docs.py

Lines changed: 7 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -88,57 +88,24 @@ def alert_replacer(match):
8888
content = re.sub(GITHUB_ALERT_PATTERN, alert_replacer, content, flags=re.MULTILINE)
8989
return content
9090

91-
def to_github(content):
92-
"""Converts MkDocs style to GitHub style."""
93-
94-
def mkdocs_replacer(match):
95-
adm_type, title, body = match.groups()
96-
# Safely retrieve the emoji, default to 'note' (📝) for unknown/unmapped types
97-
emoji = MAPPING.get(adm_type, {"emoji": "📝"})["emoji"]
98-
99-
# Strip trailing whitespace from captured body to prevent hanging '>'
100-
clean_body = body.rstrip()
101-
raw_lines = clean_body.split('\n')
102-
content_lines = [re.sub(r'^\s{4}', '', line).rstrip() for line in raw_lines]
103-
104-
# Header line logic
105-
github_lines = [f"> {emoji} **{title}**"] if title.strip() else [f"> {emoji}"]
106-
github_lines.append(">") # Spacer line
107-
108-
for line in content_lines:
109-
github_lines.append(f"> {line}" if line else ">")
110-
111-
return "\n".join(github_lines) + "\n"
112-
113-
return re.sub(MKDOCS_PATTERN, mkdocs_replacer, content)
114-
115-
def process_file(path, mode):
116-
mode_map = {
117-
"github-to-mkdocs": to_mkdocs,
118-
"mkdocs-to-github": to_github
119-
}
120-
if mode not in mode_map:
121-
raise ValueError(f"Unsupported mode: {mode}. Choose from {list(mode_map.keys())}.")
122-
target_func = mode_map[mode]
123-
91+
def process_file(path):
12492
with open(path, 'r', encoding='utf-8') as f:
12593
content = f.read()
126-
new_content = target_func(content)
94+
new_content = to_mkdocs(content)
12795
if new_content != content:
12896
with open(path, 'w', encoding='utf-8') as f:
12997
f.write(new_content)
130-
print(f"[{mode.upper()}] Converted: {path}")
98+
print(f"[CONVERTED] {path}")
13199

132-
def run_conversion(mode):
100+
def run_conversion():
133101
for root, dirs, files in os.walk('docs'):
134102
if any(x in root for x in ['scripts', 'assets', '__pycache__']):
135103
continue
136104
for file in files:
137105
if file.endswith('.md'):
138-
process_file(os.path.join(root, file), mode)
106+
process_file(os.path.join(root, file))
139107

140108
if __name__ == "__main__":
141-
parser = argparse.ArgumentParser(description="Bidirectional Markdown Admonition Converter")
142-
parser.add_argument("--mode", choices=["github-to-mkdocs", "mkdocs-to-github"], required=True, help="Target format")
109+
parser = argparse.ArgumentParser(description="GitHub to MkDocs Markdown Admonition Converter")
143110
args = parser.parse_args()
144-
run_conversion(args.mode)
111+
run_conversion()

docs/scripts/test_convert_docs.py

Lines changed: 33 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,39 @@
11
import pytest
2-
from convert_docs import to_mkdocs, to_github
2+
from convert_docs import to_mkdocs
33

44
# --- 1. A2UI Specific Header Cases ---
55
ADMONITION_CASES = [
6-
('!!! info "Coming soon..."', "Coming soon..."),
7-
('!!! warning "Status: Early Stage Public Preview"', "Status: Early Stage Public Preview"),
8-
('!!! success "Stable Release"', "Stable Release"),
9-
('!!! note "Version Compatibility"', "Version Compatibility"),
10-
('!!! warning "Attention"', "Attention"),
11-
('!!! tip "It\'s Just JSON"', "It's Just JSON"),
6+
('!!! info "Coming soon..."', "Coming soon...", "ℹ️"),
7+
('!!! warning "Status: Early Stage Public Preview"', "Status: Early Stage Public Preview", "⚠️"),
8+
('!!! success "Stable Release"', "Stable Release", "✅"),
9+
('!!! note "Version Compatibility"', "Version Compatibility", "📝"),
10+
('!!! warning "Attention"', "Attention", "⚠️"),
11+
('!!! tip "It\'s Just JSON"', "It's Just JSON", "💡"),
1212
]
1313

14-
@pytest.mark.parametrize("header, expected_title", ADMONITION_CASES)
15-
def test_standard_a2ui_round_trip(header, expected_title):
16-
"""Verifies that all standard A2UI headers survive a round-trip conversion."""
14+
@pytest.mark.parametrize("expected_header, title, emoji", ADMONITION_CASES)
15+
def test_standard_a2ui_conversion(expected_header, title, emoji):
16+
"""Verifies that GitHub style converts to expected A2UI headers."""
1717
body = " Line 1\n Line 2"
18-
original = f"{header}\n{body}\n"
18+
github_input = f"> {emoji} **{title}**\n>\n> Line 1\n> Line 2\n"
1919

20-
# MkDocs -> GitHub
21-
github = to_github(original)
22-
assert f"**{expected_title}**" in github
20+
expected = f"{expected_header}\n{body}\n"
2321

2422
# GitHub -> MkDocs
25-
back = to_mkdocs(github)
26-
assert back.strip() == original.strip()
23+
result = to_mkdocs(github_input)
24+
assert result.strip() == expected.strip()
2725

2826

2927
# --- 2. Empty Title Edge Case ---
3028
def test_empty_title_case():
3129
"""
32-
Verifies !!! tip "" converts to '> 💡' exactly.
33-
- No trailing spaces
34-
- No bold markers (****)
30+
Verifies '> 💡' converts to !!! tip "".
3531
"""
36-
original = '!!! tip ""\n Content.\n'
37-
github = to_github(original)
32+
github_input = "> 💡\n>\n> Content.\n"
33+
expected = '!!! tip ""\n Content.\n'
3834

39-
lines = github.splitlines()
40-
assert lines[0] == "> 💡" # Strictly no space or bold markers
41-
assert lines[1] == ">" # Spacer line
42-
43-
back = to_mkdocs(github)
44-
assert back == original
35+
result = to_mkdocs(github_input)
36+
assert result == expected
4537

4638

4739
# --- 3. Spacing & Internal Paragraph Preservation ---
@@ -73,49 +65,37 @@ def test_paragraph_spacing_and_trailing_lines():
7365
assert result == expected
7466

7567

76-
# --- 4. Unmapped/Unknown Type Fallback ---
77-
def test_unknown_type_fallback():
78-
"""
79-
Verifies that an unknown admonition type defaults to the 'note' emoji (📝).
80-
"""
81-
original = '!!! mystery "Secret"\n Content.\n'
82-
github = to_github(original)
83-
84-
assert "> 📝 **Secret**" in github
85-
86-
# Note: Round trip will convert it back to '!!! note'
87-
# because the source type 'mystery' wasn't in the map.
88-
back = to_mkdocs(github)
89-
assert '!!! note "Secret"' in back
90-
91-
92-
# --- 5. Multiple Blocks & Isolation ---
68+
# --- 4. Multiple Blocks & Isolation ---
9369
def test_multiple_blocks_in_one_file():
9470
"""Ensures multiple blocks are processed without bleeding into each other."""
95-
original = (
71+
github_input = (
72+
'> ✅ **Block 1**\n'
73+
'> Content 1\n'
74+
'\n'
75+
'> ℹ️ **Block 2**\n'
76+
'> Content 2\n'
77+
)
78+
79+
expected = (
9680
'!!! success "Block 1"\n'
9781
' Content 1\n'
9882
'\n'
9983
'!!! info "Block 2"\n'
10084
' Content 2\n'
10185
)
102-
github = to_github(original)
103-
assert "> ✅ **Block 1**" in github
104-
assert "> ℹ️ **Block 2**" in github
10586

106-
back = to_mkdocs(github)
107-
assert back == original
87+
result = to_mkdocs(github_input)
88+
assert result == expected
10889

10990

110-
# --- 6. False Positive Prevention ---
91+
# --- 5. False Positive Prevention ---
11192
def test_regular_blockquote_ignored():
11293
"""Ensures regular quotes are not touched."""
11394
source = "> This is just a quote, not an admonition."
11495
assert to_mkdocs(source) == source
115-
assert to_github(source) == source
11696

11797

118-
# --- 7. GitHub Official Alert Syntax Support ---
98+
# --- 6. GitHub Official Alert Syntax Support ---
11999
def test_github_alert_to_mkdocs():
120100
"""Verifies official [!TYPE] syntax conversion."""
121101
source = "> [!WARNING]\n> **Security Notice**\n> Do not share keys."

0 commit comments

Comments
 (0)