diff --git a/adev/shared-docs/pipeline/api-gen/rendering/symbol-context.ts b/adev/shared-docs/pipeline/api-gen/rendering/symbol-context.ts index d363f7641a8..83a1ce1b548 100644 --- a/adev/shared-docs/pipeline/api-gen/rendering/symbol-context.ts +++ b/adev/shared-docs/pipeline/api-gen/rendering/symbol-context.ts @@ -38,8 +38,6 @@ export function getCurrentSymbol(): string | undefined { return currentSymbol; } -export function logUnknownSymbol(link: string, symbol: string): void { - console.warn( - `WARNING: {@link ${link}} is invalid, ${symbol} or ${currentSymbol}.${symbol} is unknown in this context`, - ); +export function unknownSymbolMessage(link: string, symbol: string): string { + return `WARNING: {@link ${link}} is invalid, ${symbol} or ${currentSymbol}.${symbol} is unknown in this context`; } diff --git a/adev/shared-docs/pipeline/api-gen/rendering/test/marked.spec.ts b/adev/shared-docs/pipeline/api-gen/rendering/test/marked.spec.ts index ffe03191815..85011204105 100644 --- a/adev/shared-docs/pipeline/api-gen/rendering/test/marked.spec.ts +++ b/adev/shared-docs/pipeline/api-gen/rendering/test/marked.spec.ts @@ -34,6 +34,13 @@ describe('markdown to html', () => { const symbols = new Map([ ['AfterRenderPhase', 'core'], ['afterRender', 'core'], + ['EmbeddedViewRef', 'core'], + ['ChangeDetectionStrategy', 'core'], + ['ChangeDetectorRef', 'core'], + ['withNoHttpTransferCache', 'platform-browser'], + ['withHttpTransferCacheOptions', 'platform-browser'], + ['withI18nSupport', 'platform-browser'], + ['withEventReplay', 'platform-browser'], ]); setSymbols(symbols); for (const entry of entryJson.entries) { diff --git a/adev/shared-docs/pipeline/api-gen/rendering/test/renderable.spec.ts b/adev/shared-docs/pipeline/api-gen/rendering/test/renderable.spec.ts index 1400bc2bacd..9efb7ed8381 100644 --- a/adev/shared-docs/pipeline/api-gen/rendering/test/renderable.spec.ts +++ b/adev/shared-docs/pipeline/api-gen/rendering/test/renderable.spec.ts @@ -12,6 +12,7 @@ import {getRenderable} from '../processing'; import {DocEntryRenderable} from '../entities/renderables'; import {initHighlighter} from '../shiki/shiki'; import {configureMarkedGlobally} from '../marked/configuration'; +import {setSymbols} from '../symbol-context'; // Note: The tests will probably break if the schema of the api extraction changes. // All entries in the fake-entries are extracted from Angular's api. @@ -28,6 +29,19 @@ describe('renderable', () => { encoding: 'utf-8', }); const entryJson = JSON.parse(entryContent) as any; + const symbols = new Map([ + ['AfterRenderPhase', 'core'], + ['afterRender', 'core'], + ['EmbeddedViewRef', 'core'], + ['ChangeDetectionStrategy', 'core'], + ['ChangeDetectorRef', 'core'], + ['withNoHttpTransferCache', 'platform-browser'], + ['withHttpTransferCacheOptions', 'platform-browser'], + ['withI18nSupport', 'platform-browser'], + ['withEventReplay', 'platform-browser'], + ]); + setSymbols(symbols); + for (const entry of entryJson.entries) { const renderableJson = getRenderable(entry, '@angular/fakeentry') as DocEntryRenderable; entries.set(entry['name'], renderableJson); diff --git a/adev/shared-docs/pipeline/api-gen/rendering/test/transforms/jsdoc-transforms.spec.ts b/adev/shared-docs/pipeline/api-gen/rendering/test/transforms/jsdoc-transforms.spec.ts index 912fcec27a5..6f8a07ec64d 100644 --- a/adev/shared-docs/pipeline/api-gen/rendering/test/transforms/jsdoc-transforms.spec.ts +++ b/adev/shared-docs/pipeline/api-gen/rendering/test/transforms/jsdoc-transforms.spec.ts @@ -70,10 +70,6 @@ describe('jsdoc transforms', () => { name: 'see', comment: '{@link /cli/build ng build}', }, - { - name: 'see', - comment: '{@link cli/build ng build}', - }, { name: 'see', comment: '{@link /ecosystem/rxjs-interop/output-interop Output Interop}', @@ -135,16 +131,24 @@ describe('jsdoc transforms', () => { url: '/cli/build', }); - // TODO: in the future when all links are valid we would throw an error instead when not starting with a slash - // Links should be absolute within adev (to support both next & stable site) expect(entry.additionalLinks[11]).toEqual({ - label: 'ng build', - url: 'cli/build', - }); - - expect(entry.additionalLinks[12]).toEqual({ label: 'Output Interop', url: '/ecosystem/rxjs-interop/output-interop', }); }); + + it('should throw on invalid relatie @link', () => { + const entryFn = () => + addHtmlAdditionalLinks({ + jsdocTags: [ + { + name: 'see', + comment: '{@link cli/build ng build}', + }, + ], + moduleName: 'test', + }); + + expect(entryFn).toThrowError(/Forbidden relative link: cli\/build ng build/); + }); }); diff --git a/adev/shared-docs/pipeline/api-gen/rendering/transforms/jsdoc-transforms.ts b/adev/shared-docs/pipeline/api-gen/rendering/transforms/jsdoc-transforms.ts index 529e0df952e..69e089692bf 100644 --- a/adev/shared-docs/pipeline/api-gen/rendering/transforms/jsdoc-transforms.ts +++ b/adev/shared-docs/pipeline/api-gen/rendering/transforms/jsdoc-transforms.ts @@ -31,7 +31,7 @@ import { import {getLinkToModule} from './url-transforms'; import {addApiLinksToHtml} from './code-transforms'; -import {getCurrentSymbol, getModuleName, logUnknownSymbol} from '../symbol-context'; +import {getCurrentSymbol, getModuleName, unknownSymbolMessage} from '../symbol-context'; export const JS_DOC_REMARKS_TAG = 'remarks'; export const JS_DOC_USAGE_NOTES_TAG = 'usageNotes'; @@ -186,6 +186,12 @@ function parseAtLink(link: string): {label: string; url: string} { if (rawSymbol.startsWith('#')) { rawSymbol = rawSymbol.substring(1); } else if (rawSymbol.includes('/')) { + if (!rawSymbol.startsWith('/') && !rawSymbol.startsWith('http')) { + throw Error( + `Forbidden relative link: ${link}. Links should be absolute and start with a slash`, + ); + } + return { url: rawSymbol, label: description ?? rawSymbol.split('/').pop()!, @@ -204,11 +210,9 @@ function parseAtLink(link: string): {label: string; url: string} { moduleName = getModuleName(`${currentSymbol}.${symbol}`); if (!moduleName || !currentSymbol) { - // TODO: remove the links that generate this error - // TODO: throw an error when there are no more warning generated - logUnknownSymbol(link, symbol); - return {label, url: '#'}; + throw unknownSymbolMessage(link, symbol); } + subSymbol = symbol; symbol = currentSymbol; }