@@ -215,6 +215,90 @@ def escape_html(text):
215215with open ('./timestamps.json' , 'w' ) as f :
216216 json .dump (timestamps , f , indent = 2 , sort_keys = True )
217217
218+ # Legacy path redirects
219+ # These handle old URLs that were previously served by Apache RewriteRule redirects.
220+ # For local targets, we use symlinks. For cross-origin targets (css-houdini.org),
221+ # we create HTML files with meta refresh.
222+
223+ LEGACY_REDIRECTS = {
224+ # Old name -> new name (local redirects via symlink)
225+ "css-anchor-1" : "css-anchor-position-1" ,
226+ "css3-grid-align" : "css-grid-1" ,
227+ "css3-text-layout" : "css-writing-modes-3" ,
228+ "css3-2d-transforms" : "css-transforms" ,
229+ "css3-3d-transforms" : "css-transforms" ,
230+ "mediaqueries3" : "mediaqueries-3" ,
231+ "mediaqueries4" : "mediaqueries-4" ,
232+ "css-namespaces-1" : "css-namespaces" ,
233+ "css-snappoints-1" : "css-scroll-snap-1" ,
234+ "css-snappoints" : "css-scroll-snap" ,
235+ "css-snap-size-1" : "css-rhythm-1" ,
236+ "css-snap-size" : "css-rhythm" ,
237+ "css-step-sizing" : "css-rhythm" ,
238+ "css-containment" : "css-contain" ,
239+ "css-logical-props" : "css-logical" ,
240+ "css-device-adapt-1" : "css-viewport-1" ,
241+ "css-device-adapt" : "css-viewport" ,
242+ "css-overscroll-behavior-1" : "css-overscroll-1" ,
243+ "css-overscroll-behavior" : "css-overscroll" ,
244+ "css-shared-element-transitions-1" : "css-view-transitions-1" ,
245+ "css-shared-element-transitions" : "css-view-transitions" ,
246+ "css-timing-1" : "css-easing-1" ,
247+ "css-timing" : "css-easing" ,
248+ "css-scoping-2" : "css-cascade-6" ,
249+ }
250+
251+ # Cross-origin redirects need HTML meta refresh files
252+ CROSS_ORIGIN_REDIRECTS = {
253+ "cssom-values-1" : "https://drafts.css-houdini.org/css-typed-om-1/" ,
254+ "cssom-values" : "https://drafts.css-houdini.org/css-typed-om/" ,
255+ }
256+
257+ REDIRECT_HTML_TEMPLATE = """<!doctype html>
258+ <html lang="en">
259+ <head>
260+ <meta charset="utf-8">
261+ <title>Redirecting…</title>
262+ <meta http-equiv="refresh" content="0; url={url}">
263+ <link rel="canonical" href="{url}">
264+ </head>
265+ <body>
266+ <p>This page has moved to <a href="{url}">{url}</a>.</p>
267+ </body>
268+ </html>
269+ """
270+
271+ for old_path , new_path in LEGACY_REDIRECTS .items ():
272+ if os .path .exists (new_path ) and not os .path .exists (old_path ):
273+ try :
274+ os .symlink (new_path , old_path )
275+ except OSError :
276+ pass
277+
278+ for old_path , url in CROSS_ORIGIN_REDIRECTS .items ():
279+ if not os .path .exists (old_path ):
280+ os .makedirs (old_path , exist_ok = True )
281+ index_file = os .path .join (old_path , "index.html" )
282+ if not os .path .exists (index_file ):
283+ with open (index_file , "w" , encoding = "utf-8" ) as f :
284+ f .write (REDIRECT_HTML_TEMPLATE .format (url = url ))
285+
286+ # css2 subpage redirects: old CSS 2.1 chapter URLs redirect to the spec root
287+ CSS2_SUBPAGES = [
288+ "about.html" , "aural.html" , "box.html" , "cascade.html" , "changes.html" ,
289+ "colors.html" , "conform.html" , "cover.html" , "fonts.html" , "generate.html" ,
290+ "grammar.html" , "indexlist.html" , "intro.html" , "leftblank.html" , "media.html" ,
291+ "page.html" , "propidx.html" , "refs.html" , "sample.html" , "selector.html" ,
292+ "syndata.html" , "tables.html" , "text.html" , "ui.html" , "visudet.html" ,
293+ "visufx.html" , "visuren.html" , "zindex.html" ,
294+ ]
295+
296+ for subpage in CSS2_SUBPAGES :
297+ subpage_path = os .path .join ("css2" , subpage )
298+ if not os .path .exists (subpage_path ):
299+ with open (subpage_path , "w" , encoding = "utf-8" ) as f :
300+ f .write (REDIRECT_HTML_TEMPLATE .format (url = "./" ))
301+
218302# Build the index page
219303
220304# Flatten all specs into a single list with full metadata
0 commit comments