1
+ #!/usr/bin/env python3
2
+
3
+ import yaml
4
+ import json
5
+ import sys
6
+
7
+ def extract_links_from_nav (nav_data ):
8
+ """Recursively extract all link values from the navigation structure"""
9
+ links = []
10
+
11
+ if isinstance (nav_data , dict ):
12
+ if 'link' in nav_data :
13
+ link = nav_data ['link' ]
14
+ # Skip external URLs
15
+ if not link .startswith ('http' ):
16
+ links .append (link )
17
+
18
+ if 'children' in nav_data :
19
+ for child in nav_data ['children' ]:
20
+ links .extend (extract_links_from_nav (child ))
21
+
22
+ elif isinstance (nav_data , list ):
23
+ for item in nav_data :
24
+ links .extend (extract_links_from_nav (item ))
25
+
26
+ return links
27
+
28
+ def load_sidenav ():
29
+ """Load and parse the sidenav.yml file"""
30
+ with open ('sidenav.yml' , 'r' ) as f :
31
+ return yaml .safe_load (f )
32
+
33
+ def load_xref_mapping ():
34
+ """Load and parse the xref-mapping.json file"""
35
+ with open ('xref-mapping.json' , 'r' ) as f :
36
+ return json .load (f )
37
+
38
+ def fix_link_mappings (link ):
39
+ """Handle special cases where navigation link names don't match xref mapping keys"""
40
+ mapping_fixes = {
41
+ 'webhooks-reference' : 'outbound-webhooks-reference' ,
42
+ }
43
+ return mapping_fixes .get (link , link )
44
+
45
+ def generate_new_url (page_slug , xref_mapping ):
46
+ """Generate new URL from xref mapping (without domain prefix)"""
47
+ # Try to fix the link mapping first
48
+ fixed_slug = fix_link_mappings (page_slug )
49
+
50
+ if fixed_slug in xref_mapping :
51
+ mapping = xref_mapping [fixed_slug ]
52
+ component = mapping ['component' ]
53
+ module = mapping ['module' ]
54
+
55
+ # Handle ROOT module - it doesn't appear in the URL
56
+ if module == 'ROOT' :
57
+ return f"/{ component } /{ fixed_slug } .html"
58
+ else :
59
+ return f"/{ component } /{ module } /{ fixed_slug } .html"
60
+
61
+ return None
62
+
63
+ def process_server_links (link ):
64
+ """Handle server administration links which have special paths"""
65
+ if link .startswith ('server/' ):
66
+ # Extract version and path components
67
+ parts = link .split ('/' )
68
+ if len (parts ) >= 4 :
69
+ version = parts [1 ] # e.g., 'latest', 'v4.6', etc.
70
+ module = parts [2 ] # e.g., 'installation', 'operator', etc.
71
+ page = parts [3 ] # e.g., 'phase-1-prerequisites'
72
+
73
+ # Map version to component name
74
+ if version == 'latest' :
75
+ component = 'server-admin-latest'
76
+ else :
77
+ component = f'server-admin-{ version } '
78
+
79
+ return f"/{ component } /{ module } /{ page } .html"
80
+
81
+ return None
82
+
83
+ def handle_authentication_links (link ):
84
+ """Handle authentication links which have special paths"""
85
+ if link .startswith ('authentication/' ):
86
+ # Remove 'authentication/' prefix and map to permissions-authentication module
87
+ page_slug = link .replace ('authentication/' , '' )
88
+ return f"/guides/permissions-authentication/{ page_slug } .html"
89
+
90
+ return None
91
+
92
+ def handle_deploy_links (link ):
93
+ """Handle deploy links which have special paths"""
94
+ if link .startswith ('deploy/' ):
95
+ # Remove 'deploy/' prefix and map to deploy module
96
+ page_slug = link .replace ('deploy/' , '' )
97
+ return f"/guides/deploy/{ page_slug } .html"
98
+
99
+ return None
100
+
101
+ def handle_style_links (link ):
102
+ """Handle style links which have special paths"""
103
+ if link .startswith ('style/' ):
104
+ # Remove 'style/' prefix and map to docs-style module
105
+ page_slug = link .replace ('style/' , '' )
106
+ return f"/contributors/docs-style/{ page_slug } .html"
107
+
108
+ return None
109
+
110
+ def handle_templates_links (link ):
111
+ """Handle templates links which have special paths"""
112
+ if link .startswith ('templates/' ):
113
+ # Remove 'templates/' prefix and map to templates module
114
+ page_slug = link .replace ('templates/' , '' )
115
+ return f"/contributors/templates/{ page_slug } .html"
116
+
117
+ return None
118
+
119
+ def main ():
120
+ # Load data files
121
+ sidenav_data = load_sidenav ()
122
+ xref_mapping = load_xref_mapping ()
123
+
124
+ # Extract English navigation links
125
+ en_nav = sidenav_data .get ('en' , [])
126
+ links = extract_links_from_nav (en_nav )
127
+
128
+ # Remove duplicates and sort
129
+ unique_links = sorted (set (links ))
130
+
131
+ # Generate redirects
132
+ redirects = []
133
+ unmapped_links = []
134
+
135
+ for link in unique_links :
136
+ old_url = f"/{ link } /"
137
+ new_url = None
138
+
139
+ # Handle special cases first
140
+ if link .startswith ('server/' ):
141
+ new_url = process_server_links (link )
142
+ elif link .startswith ('authentication/' ):
143
+ new_url = handle_authentication_links (link )
144
+ elif link .startswith ('deploy/' ):
145
+ new_url = handle_deploy_links (link )
146
+ elif link .startswith ('style/' ):
147
+ new_url = handle_style_links (link )
148
+ elif link .startswith ('templates/' ):
149
+ new_url = handle_templates_links (link )
150
+ else :
151
+ # Try to find in xref mapping
152
+ new_url = generate_new_url (link , xref_mapping )
153
+
154
+ if new_url :
155
+ redirects .append ({
156
+ 'old' : old_url ,
157
+ 'new' : new_url
158
+ })
159
+ else :
160
+ unmapped_links .append (link )
161
+
162
+ # Print warnings to stderr
163
+ if unmapped_links :
164
+ print (f"Warning: Could not map { len (unmapped_links )} links:" , file = sys .stderr )
165
+ for link in unmapped_links :
166
+ print (f" - { link } " , file = sys .stderr )
167
+ print (file = sys .stderr )
168
+
169
+ # Generate YAML output
170
+ print ("# Generated redirects from Jekyll to Antora" )
171
+ print ("# Format: old (Jekyll) -> new (Antora)" )
172
+ print (f"# Total redirects: { len (redirects )} " )
173
+ print ()
174
+
175
+ for redirect in redirects :
176
+ print (f"- old: { redirect ['old' ]} " )
177
+ print (f" new: { redirect ['new' ]} " )
178
+ print ()
179
+
180
+ if __name__ == "__main__" :
181
+ main ()
0 commit comments