-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathgenerate_hugo_menu.py
146 lines (130 loc) · 5.96 KB
/
generate_hugo_menu.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import os
import yaml
import re
import json
def preprocess_js_to_json(js_content):
"""
Preprocess JavaScript object notation into JSON-compatible format.
"""
js_content = re.sub(r"//.*", "", js_content) # Remove single-line comments
js_content = re.sub(r"/\*.*?\*/", "", js_content, flags=re.DOTALL) # Remove multi-line comments
js_content = re.sub(r"export\s+default\s+", "", js_content) # Remove the `export default` line
js_content = re.sub(r"'", '"', js_content) # Replace single quotes with double quotes
js_content = re.sub(r"(\s|{|,)([a-zA-Z_][a-zA-Z0-9_]*)\s*:", r'\1"\2":', js_content) # Quote unquoted keys
js_content = re.sub(r",(\s*[\]}])", r"\1", js_content) # Remove trailing commas
return js_content.strip(";").strip()
def slugify_label(label):
"""
Convert a label to an ASCII slug.
"""
return re.sub(r"[^a-zA-Z0-9]+", "-", label.lower()).strip("-")
def read_existing_file_content(file_path):
"""
Read the content and front matter from an existing file.
"""
if not os.path.exists(file_path):
return {}, ""
with open(file_path, "r", encoding="utf-8") as f:
content = f.read()
# Split front matter and body
if content.startswith("---"):
parts = content.split("---", 2)
if len(parts) > 2:
front_matter = yaml.safe_load(parts[1])
body = parts[2].strip()
return front_matter, body
return {}, content
def create_markdown_file(path, front_matter, content=""):
"""
Create a Markdown file with front matter.
"""
os.makedirs(os.path.dirname(path), exist_ok=True)
with open(path, "w", encoding="utf-8") as f:
yaml_front_matter = yaml.dump(front_matter, default_flow_style=False)
f.write(f"---\n{yaml_front_matter}---\n\n{content}")
def process_items(items, top_menu, base_path="content", docs_path="docs", parent_slug=None):
"""
Process menu items recursively and generate markdown files.
"""
for item in items:
if isinstance(item, str):
# Extract the path and filename
parts = item.split("/")
file_path = os.path.join(base_path, *parts) + ".md"
docs_file_path = os.path.join(docs_path, *parts) + ".md"
identifier = parts[-1] # Use only the filename without extension as the identifier
# Read the old content and front matter
old_front_matter, old_content = read_existing_file_content(docs_file_path)
# Prepare new front matter
front_matter = {
"menu": {
top_menu: {
"identifier": identifier,
"parent": parent_slug
}
}
}
# Add extra keys from old front matter
for key in ["title", "description", "tags"]:
if key in old_front_matter:
front_matter[key] = old_front_matter[key]
# Create the new file
create_markdown_file(file_path, front_matter, old_content)
elif isinstance(item, dict):
if item.get("type") == "category":
category_label = item["label"]
category_slug = slugify_label(category_label)
# Process category items
if "items" in item:
process_items(item["items"], top_menu, base_path, docs_path, parent_slug=category_slug)
if "link" in item and "id" in item["link"]:
# Handle linked categories
parts = item["link"]["id"].split("/")
file_path = os.path.join(base_path, *parts) + ".md"
docs_file_path = os.path.join(docs_path, *parts) + ".md"
identifier = parts[-1] # Use only the filename without extension as the identifier
# Read the old content and front matter
old_front_matter, old_content = read_existing_file_content(docs_file_path)
# Prepare new front matter
front_matter = {
"menu": {
top_menu: {
"identifier": identifier,
"parent": parent_slug
}
}
}
# Add extra keys from old front matter
for key in ["title", "description", "tags"]:
if key in old_front_matter:
front_matter[key] = old_front_matter[key]
# Create the new file
create_markdown_file(file_path, front_matter, old_content)
elif not "link" in item:
# Create a placeholder front matter if the category has no associated link
placeholder_path = os.path.join(base_path, category_slug, "_index.md")
front_matter = {
"menu": {
top_menu: {
"identifier": category_slug,
"parent": parent_slug
}
}
}
create_markdown_file(placeholder_path, front_matter)
# Load and preprocess the sidebar.js file
with open("sidebars.js", "r", encoding="utf-8") as f:
js_data = f.read()
# Preprocess the JavaScript content
json_data = preprocess_js_to_json(js_data)
# Safely parse the JSON
try:
menu_data = json.loads(json_data)
except json.JSONDecodeError as e:
print("Error decoding JSON:", e)
print("Preprocessed JSON data:\n", json_data)
exit(1)
# Generate markdown files for each top-level menu
for menu_name, items in menu_data.items():
process_items(items, menu_name.lower())
print("Markdown files generated successfully.")