@@ -94,14 +94,61 @@ await File.WriteAllTextAsync(
9494
9595 var wwwRoot = Path . Combine ( outputDirectory , "wwwroot" ) ;
9696 await File . WriteAllTextAsync ( Path . Combine ( wwwRoot , ".nojekyll" ) , string . Empty , cancellationToken ) ;
97- File . Copy (
98- Path . Combine ( wwwRoot , "index.html" ) ,
99- Path . Combine ( wwwRoot , "404.html" ) ,
100- true ) ;
97+ await WriteNotFoundAsync ( wwwRoot , cancellationToken ) ;
98+ CopyCustomDomain ( wwwRoot ) ;
10199 Console . WriteLine ( $ "Web application: { wwwRoot } ") ;
102100 return 0 ;
103101 }
104102
103+ /// <summary>
104+ /// The application has a single route, so an unknown path is always a wrong URL.
105+ /// Serving a copy of index.html there does not work: its base href is relative,
106+ /// so the framework files would be requested under the unknown path and 404,
107+ /// leaving the page stuck on the loading screen. Redirect to the site root
108+ /// instead, which differs between a project page and a custom domain.
109+ /// </summary>
110+ private static async Task WriteNotFoundAsync (
111+ string wwwRoot ,
112+ CancellationToken cancellationToken ) =>
113+ await File . WriteAllTextAsync (
114+ Path . Combine ( wwwRoot , "404.html" ) ,
115+ """
116+ <!DOCTYPE html>
117+ <html lang="en">
118+ <head>
119+ <meta charset="utf-8"/>
120+ <title>.NET Matrix</title>
121+ <script>
122+ var root = location.hostname.endsWith('.github.io')
123+ ? '/' + location.pathname.split('/')[1] + '/'
124+ : '/';
125+ if (location.pathname !== root) {
126+ location.replace(root);
127+ }
128+ </script>
129+ </head>
130+ <body></body>
131+ </html>
132+
133+ """ ,
134+ cancellationToken ) ;
135+
136+ /// <summary>
137+ /// An Actions based deployment publishes exactly the artifact, so the custom
138+ /// domain has to travel with it or GitHub Pages drops it on the next deploy.
139+ /// </summary>
140+ private void CopyCustomDomain ( string wwwRoot )
141+ {
142+ var source = Path . Combine ( buildPaths . SolutionDirectory , "CNAME" ) ;
143+ if ( ! File . Exists ( source ) )
144+ {
145+ return ;
146+ }
147+
148+ File . Copy ( source , Path . Combine ( wwwRoot , "CNAME" ) , true ) ;
149+ Console . WriteLine ( $ "Custom domain: { File . ReadAllText ( source ) . Trim ( ) } ") ;
150+ }
151+
105152 /// <summary>
106153 /// Releases are baked into the catalog from the local clone, so the published
107154 /// application needs no GitHub API call to list them. The unauthenticated API
0 commit comments