diff --git a/adev/shared-docs/pipeline/api-gen/rendering/test/cli.spec.mts b/adev/shared-docs/pipeline/api-gen/rendering/test/cli.spec.mts index b020e9eacc6..94b9d845fbf 100644 --- a/adev/shared-docs/pipeline/api-gen/rendering/test/cli.spec.mts +++ b/adev/shared-docs/pipeline/api-gen/rendering/test/cli.spec.mts @@ -43,4 +43,17 @@ describe('CLI docs to html', () => { expect(cliTocs[0].textContent).toContain('ng component [name] [options]'); expect(cliTocs[1].textContent).toContain('ng c [name] [options]'); }); + + it('should rewrite absolute angular.dev hrefs in option descriptions to root-relative', async () => { + const renderableJson = await getRenderable(entryJson, '', 'angular/cli'); + const localFragment = JSDOM.fragment(renderEntry(renderableJson)); + const hrefs = Array.from(localFragment.querySelectorAll('a')).map((a) => + a.getAttribute('href'), + ); + // Absolute angular.dev URLs are rewritten to root-relative. + expect(hrefs).toContain('/cli-test-rewrite'); + expect(hrefs).not.toContain('https://angular.dev/cli-test-rewrite'); + // Subdomains are intentionally left as external. + expect(hrefs).toContain('https://next.angular.dev/cli-test-preview'); + }); }); diff --git a/adev/shared-docs/pipeline/api-gen/rendering/test/fake-cli-entries.json b/adev/shared-docs/pipeline/api-gen/rendering/test/fake-cli-entries.json index f35c6e34a5c..404d61b8a0e 100644 --- a/adev/shared-docs/pipeline/api-gen/rendering/test/fake-cli-entries.json +++ b/adev/shared-docs/pipeline/api-gen/rendering/test/fake-cli-entries.json @@ -2,9 +2,7 @@ "name": "generate", "command": "ng generate ", "shortDescription": "Generates and/or modifies files based on a schematic.", - "aliases": [ - "g" - ], + "aliases": ["g"], "deprecated": false, "options": [ { @@ -16,9 +14,7 @@ { "name": "dry-run", "type": "boolean", - "aliases": [ - "d" - ], + "aliases": ["d"], "default": false, "description": "Run through and reports activity without writing out results." }, @@ -44,6 +40,12 @@ "type": "string", "description": "The [collection:schematic] to run.", "positional": 0 + }, + { + "name": "test-angular-dev-href-rewrite", + "type": "boolean", + "default": false, + "description": "See [angular.dev test](https://angular.dev/cli-test-rewrite) and [preview test](https://next.angular.dev/cli-test-preview)." } ], "subcommands": [ @@ -75,17 +77,13 @@ { "name": "inline-style", "type": "boolean", - "aliases": [ - "s" - ], + "aliases": ["s"], "description": "Include styles inline in the root component.ts file. Only CSS styles can be included inline. Default is false, meaning that an external styles file is created and referenced in the root component.ts file." }, { "name": "inline-template", "type": "boolean", - "aliases": [ - "t" - ], + "aliases": ["t"], "description": "Include template inline in the root component.ts file. Default is false, meaning that an external template file is created and referenced in the root component.ts file. " }, { @@ -103,9 +101,7 @@ { "name": "prefix", "type": "string", - "aliases": [ - "p" - ], + "aliases": ["p"], "default": "app", "description": "A prefix to apply to generated selectors." }, @@ -135,9 +131,7 @@ { "name": "skip-tests", "type": "boolean", - "aliases": [ - "S" - ], + "aliases": ["S"], "default": false, "description": "Do not create \"spec.ts\" test files for the application." }, @@ -163,29 +157,17 @@ "name": "style", "type": "string", "default": "css", - "enum": [ - "css", - "scss", - "sass", - "less" - ], + "enum": ["css", "scss", "sass", "less"], "description": "The file extension or preprocessor to use for style files." }, { "name": "view-encapsulation", "type": "string", - "enum": [ - "Emulated", - "None", - "ShadowDom", - "ExperimentalIsolatedShadowDom" - ], + "enum": ["Emulated", "None", "ShadowDom", "ExperimentalIsolatedShadowDom"], "description": "The view encapsulation strategy to use in the new application." } ], - "aliases": [ - "app" - ], + "aliases": ["app"], "deprecated": false }, { @@ -216,9 +198,7 @@ "description": "Adds a developer-defined type to the filename, in the format \"name.type.ts\"." } ], - "aliases": [ - "cl" - ], + "aliases": ["cl"], "deprecated": false }, { @@ -229,22 +209,15 @@ { "name": "change-detection", "type": "string", - "aliases": [ - "c" - ], + "aliases": ["c"], "default": "Default", - "enum": [ - "Default", - "OnPush" - ], + "enum": ["Default", "OnPush"], "description": "The change detection strategy to use in the new component." }, { "name": "display-block", "type": "boolean", - "aliases": [ - "b" - ], + "aliases": ["b"], "default": false, "description": "Specifies if the style will contain `:host { display: block; }`." }, @@ -269,27 +242,21 @@ { "name": "inline-style", "type": "boolean", - "aliases": [ - "s" - ], + "aliases": ["s"], "default": false, "description": "Include styles inline in the component.ts file. Only CSS styles can be included inline. By default, an external styles file is created and referenced in the component.ts file." }, { "name": "inline-template", "type": "boolean", - "aliases": [ - "t" - ], + "aliases": ["t"], "default": false, "description": "Include template inline in the component.ts file. By default, an external template file is created and referenced in the component.ts file." }, { "name": "module", "type": "string", - "aliases": [ - "m" - ], + "aliases": ["m"], "description": "The declaring NgModule." }, { @@ -301,9 +268,7 @@ { "name": "prefix", "type": "string", - "aliases": [ - "p" - ], + "aliases": ["p"], "description": "The prefix to apply to the generated component selector." }, { @@ -344,13 +309,7 @@ "name": "style", "type": "string", "default": "css", - "enum": [ - "css", - "scss", - "sass", - "less", - "none" - ], + "enum": ["css", "scss", "sass", "less", "none"], "description": "The file extension or preprocessor to use for style files, or 'none' to skip generating the style file." }, { @@ -362,21 +321,12 @@ { "name": "view-encapsulation", "type": "string", - "aliases": [ - "v" - ], - "enum": [ - "Emulated", - "None", - "ShadowDom", - "ExperimentalIsolatedShadowDom" - ], + "aliases": ["v"], + "enum": ["Emulated", "None", "ShadowDom", "ExperimentalIsolatedShadowDom"], "description": "The view encapsulation strategy to use in the new component." } ], - "aliases": [ - "c" - ], + "aliases": ["c"], "deprecated": false }, { @@ -392,10 +342,7 @@ { "name": "type", "type": "string", - "enum": [ - "karma", - "browserslist" - ], + "enum": ["karma", "browserslist"], "description": "Specifies which type of configuration file to create.", "positional": 0 } @@ -423,9 +370,7 @@ { "name": "module", "type": "string", - "aliases": [ - "m" - ], + "aliases": ["m"], "description": "The declaring NgModule." }, { @@ -437,9 +382,7 @@ { "name": "prefix", "type": "string", - "aliases": [ - "p" - ], + "aliases": ["p"], "description": "A prefix to apply to generated selectors." }, { @@ -471,9 +414,7 @@ "description": "Whether the generated directive is standalone." } ], - "aliases": [ - "d" - ], + "aliases": ["d"], "deprecated": false }, { @@ -498,9 +439,7 @@ "description": "Adds a developer-defined type to the filename, in the format \"name.type.ts\"." } ], - "aliases": [ - "e" - ], + "aliases": ["e"], "deprecated": false }, { @@ -537,9 +476,7 @@ { "name": "implements", "type": "array", - "aliases": [ - "guardType" - ], + "aliases": ["guardType"], "description": "Specifies which type of guard to create." }, { @@ -560,9 +497,7 @@ "description": "Do not create \"spec.ts\" test files for the new guard." } ], - "aliases": [ - "g" - ], + "aliases": ["g"], "deprecated": false }, { @@ -631,9 +566,7 @@ "positional": 1 } ], - "aliases": [ - "i" - ], + "aliases": ["i"], "deprecated": false }, { @@ -656,9 +589,7 @@ { "name": "prefix", "type": "string", - "aliases": [ - "p" - ], + "aliases": ["p"], "default": "lib", "description": "A prefix to apply to generated selectors." }, @@ -692,9 +623,7 @@ "description": "Creates a library based upon the standalone API, without NgModules." } ], - "aliases": [ - "lib" - ], + "aliases": ["lib"], "deprecated": false }, { @@ -711,9 +640,7 @@ { "name": "module", "type": "string", - "aliases": [ - "m" - ], + "aliases": ["m"], "description": "The declaring NgModule." }, { @@ -742,16 +669,11 @@ "name": "routing-scope", "type": "string", "default": "Child", - "enum": [ - "Child", - "Root" - ], + "enum": ["Child", "Root"], "description": "The scope for the new routing module." } ], - "aliases": [ - "m" - ], + "aliases": ["m"], "deprecated": false }, { @@ -774,9 +696,7 @@ { "name": "module", "type": "string", - "aliases": [ - "m" - ], + "aliases": ["m"], "description": "The declaring NgModule." }, { @@ -809,9 +729,7 @@ "description": "Whether the generated pipe is standalone." } ], - "aliases": [ - "p" - ], + "aliases": ["p"], "deprecated": false }, { @@ -849,9 +767,7 @@ "description": "Do not create \"spec.ts\" test files for the new resolver." } ], - "aliases": [ - "r" - ], + "aliases": ["r"], "deprecated": false }, { @@ -883,9 +799,7 @@ "description": "Do not create \"spec.ts\" test files for the new service." } ], - "aliases": [ - "s" - ], + "aliases": ["s"], "deprecated": false }, { diff --git a/adev/shared-docs/pipeline/api-gen/rendering/transforms/cli-transforms.mts b/adev/shared-docs/pipeline/api-gen/rendering/transforms/cli-transforms.mts index 27482929638..a480628797b 100644 --- a/adev/shared-docs/pipeline/api-gen/rendering/transforms/cli-transforms.mts +++ b/adev/shared-docs/pipeline/api-gen/rendering/transforms/cli-transforms.mts @@ -53,11 +53,14 @@ export function getCliCardsRenderable(command: CliCommand): CliCardRenderable[] return cards; } +// Rewrite absolute angular.dev hrefs to root-relative so links stay in-site. +const angularDevHrefRegex = /(href=["'])https?:\/\/angular\.dev\//g; + function getRenderableOptions(items: CliOption[]): CliOptionRenderable[] { return items.map((option) => ({ ...option, deprecated: option.deprecated ? {version: undefined} : undefined, - description: marked.parse(option.description) as string, + description: (marked.parse(option.description) as string).replace(angularDevHrefRegex, '$1/'), })); }