fix(docs-infra): ignore external links when mapping navigation items to routes

When navigation items contain external URLs (e.g. https:// links for documentation or third-party resources), mapNavigationItemsToRoutes previously registered them as Angular Router route definitions. In recent versions of @angular/build, the static prerender worker asserts that discovered routes do not return empty content during SSG prerendering, causing production builds and CI adev-deploy to fail on these routes.

This change filters out external links in mapNavigationItemsToRoutes so only valid internal application paths are registered as Angular routes.
This commit is contained in:
Matthew Beck
2026-09-02 18:20:50 -07:00
parent 69c87301aa
commit 502fa130aa
3 changed files with 76 additions and 2 deletions
+18 -1
View File
@@ -1,4 +1,4 @@
load("//adev/shared-docs:defaults.bzl", "ts_project")
load("//adev/shared-docs:defaults.bzl", "ts_project", "zoneless_web_test_suite")
package(default_visibility = ["//visibility:private"])
@@ -21,3 +21,20 @@ ts_project(
"//adev/shared-docs/providers",
],
)
ts_project(
name = "test_lib",
testonly = True,
srcs = glob(
["*.spec.ts"],
),
deps = [
":utils",
"//adev/shared-docs/interfaces",
],
)
zoneless_web_test_suite(
name = "test",
deps = [":test_lib"],
)
@@ -0,0 +1,54 @@
/*!
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import {NavigationItem} from '../interfaces/index';
import {isExternalLink, mapNavigationItemsToRoutes} from './navigation.utils';
describe('navigation.utils', () => {
describe('isExternalLink', () => {
it('should return true for http and https links', () => {
expect(isExternalLink('http://example.com')).toBeTrue();
expect(isExternalLink('https://example.com')).toBeTrue();
expect(isExternalLink('https://github.com/angular/angularfire#readme')).toBeTrue();
});
it('should return false for internal relative or absolute paths', () => {
expect(isExternalLink('guide/signals')).toBeFalse();
expect(isExternalLink('/guide/signals')).toBeFalse();
expect(isExternalLink('overview')).toBeFalse();
});
});
describe('mapNavigationItemsToRoutes', () => {
it('should map internal navigation items to routes and ignore external links', () => {
const items: NavigationItem[] = [
{
label: 'Overview',
path: 'overview',
},
{
label: 'AngularFire',
path: 'https://github.com/angular/angularfire#readme',
},
{
label: 'Google Maps',
path: 'https://github.com/angular/components/tree/main/src/google-maps#readme',
},
{
label: 'Guide',
path: 'guide/components',
},
];
const routes = mapNavigationItemsToRoutes(items, {});
expect(routes.length).toBe(2);
expect(routes.map((r) => r.path)).toEqual(['overview', 'guide/components']);
});
});
});
+4 -1
View File
@@ -96,7 +96,10 @@ export const mapNavigationItemsToRoutes = (
additionalRouteProperties: Partial<Route>,
): Route[] =>
navigationItems
.filter((route): route is NavigationItem & {path: string} => Boolean(route.path))
.filter(
(route): route is NavigationItem & {path: string} =>
Boolean(route.path) && !isExternalLink(route.path!),
)
.map((navigationItem) => {
const route = {
path: navigationItem.path,