From db00b1a91de7fdb0b9961d263f56a6c761821842 Mon Sep 17 00:00:00 2001 From: Juan Pablo Garcia Ripa Date: Tue, 22 Nov 2022 23:23:55 +0100 Subject: [PATCH 1/4] add DocCodeSpanLink to allow links with backticks Signed-off-by: Juan Pablo Garcia Ripa --- .../src/commands/api-reports/api-extractor.ts | 101 ++++++++++++++++-- 1 file changed, 90 insertions(+), 11 deletions(-) diff --git a/packages/repo-tools/src/commands/api-reports/api-extractor.ts b/packages/repo-tools/src/commands/api-reports/api-extractor.ts index d434aae0a6..f74e97381c 100644 --- a/packages/repo-tools/src/commands/api-reports/api-extractor.ts +++ b/packages/repo-tools/src/commands/api-reports/api-extractor.ts @@ -39,9 +39,17 @@ import { DocNode, IDocNodeContainerParameters, TSDocTagSyntaxKind, + TSDocConfiguration, + DocPlainText, + DocLinkTag, } from '@microsoft/tsdoc'; import { TSDocConfigFile } from '@microsoft/tsdoc-config'; -import { ApiPackage, ApiModel, ApiItem } from '@microsoft/api-extractor-model'; +import { + ApiPackage, + ApiModel, + ApiItem, + ApiItemKind, +} from '@microsoft/api-extractor-model'; import { IMarkdownDocumenterOptions, MarkdownDocumenter, @@ -827,6 +835,16 @@ export async function buildDocs({ } } + // This class only propose is to have a different kind and be able to render links with backticks + class DocCodeSpanLink extends DocLinkTag { + static kind = 'DocCodeSpanLink'; + + /** @override */ + public get kind(): string { + return DocCodeSpanLink.kind; + } + } + // This is where we actually write the markdown and where we can hook // in the rendering of our own nodes. class CustomCustomMarkdownEmitter extends CustomMarkdownEmitter { @@ -845,7 +863,7 @@ export async function buildDocs({ /** @override */ protected writeNode( docNode: DocNode, - context: IMarkdownEmitterContext, + context: IMarkdownEmitterContext, docNodeSiblings: boolean, ): void { switch (docNode.kind) { @@ -861,6 +879,26 @@ export async function buildDocs({ context.writer.writeLine(); break; } + case DocCodeSpanLink.kind: { + const node = docNode as DocLinkTag; + + if (node.codeDestination) { + // TODO @sarabadu understand if we need `codeDestination` at all on this custom DocCodeSpanLink + super.writeLinkTagWithCodeDestination(node, context); + } else if (node.urlDestination) { + const linkText = + node.linkText !== undefined ? node.linkText : node.urlDestination; + const encodedLinkText = this.getEscapedText( + linkText.replace(/\s+/g, ' '), + ); + context.writer.write('['); + context.writer.write(`\`${encodedLinkText}\``); + context.writer.write(`](${node.urlDestination})`); + } else if (node.linkText) { + this.writePlainText(node.linkText, context); + } + break; + } default: super.writeNode(docNode, context, docNodeSiblings); } @@ -884,13 +922,22 @@ export async function buildDocs({ super(options); // It's a strict model, we gotta register the allowed usage of our new node - this._tsdocConfiguration.docNodeManager.registerDocNodes( - '@backstage/docs', - [{ docNodeKind: DocFrontMatter.kind, constructor: DocFrontMatter }], - ); - this._tsdocConfiguration.docNodeManager.registerAllowableChildren( - 'Paragraph', - [DocFrontMatter.kind], + ( + this._tsdocConfiguration as TSDocConfiguration + ).docNodeManager.registerDocNodes('@backstage/docs', [ + { docNodeKind: DocFrontMatter.kind, constructor: DocFrontMatter }, + ]); + ( + this._tsdocConfiguration as TSDocConfiguration + ).docNodeManager.registerDocNodes('@backstage/docs', [ + { docNodeKind: DocCodeSpanLink.kind, constructor: DocCodeSpanLink }, + ]); + ( + this._tsdocConfiguration as TSDocConfiguration + ).docNodeManager.registerAllowableChildren('Paragraph', [ + DocFrontMatter.kind, + DocCodeSpanLink.kind, + ]); ); this._markdownEmitter = new CustomCustomMarkdownEmitter(newModel); @@ -941,8 +988,40 @@ export async function buildDocs({ }), ); - // Now write the actual breadcrumbs - super._writeBreadcrumb(output, apiItem); + const configuration: TSDocConfiguration = this._tsdocConfiguration; + + output.appendNodeInParagraph( + new DocLinkTag({ + configuration, + tagName: '@link', + linkText: 'Home', + urlDestination: this._getLinkFilenameForApiItem(this._apiModel), + }), + ); + + for (const hierarchyItem of apiItem.getHierarchy()) { + switch (hierarchyItem.kind) { + case ApiItemKind.Model: + case ApiItemKind.EntryPoint: + // We don't show the model as part of the breadcrumb because it is the root-level container. + // We don't show the entry point because today API Extractor doesn't support multiple entry points; + // this may change in the future. + break; + default: + output.appendNodesInParagraph([ + new DocPlainText({ + configuration, + text: ' > ', + }), + new DocCodeSpanLink({ + configuration, + tagName: '@link', + linkText: hierarchyItem.displayName, + urlDestination: this._getLinkFilenameForApiItem(hierarchyItem), + }), + ]); + } + } // We wanna ignore the header that always gets written after the breadcrumb // This otherwise becomes more or less a duplicate of the title in the front matter From fcf5d4f4ba264c65fdb79e2e3bad4a4b4d40b7e0 Mon Sep 17 00:00:00 2001 From: Juan Pablo Garcia Ripa Date: Tue, 22 Nov 2022 23:26:23 +0100 Subject: [PATCH 2/4] add @config annotation to docs Signed-off-by: Juan Pablo Garcia Ripa --- .../src/commands/api-reports/api-extractor.ts | 28 +++++++++++++++++-- plugins/proxy-backend/api-report.md | 2 +- plugins/proxy-backend/src/service/router.ts | 19 ++++++++++++- 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/packages/repo-tools/src/commands/api-reports/api-extractor.ts b/packages/repo-tools/src/commands/api-reports/api-extractor.ts index f74e97381c..2b130f50e0 100644 --- a/packages/repo-tools/src/commands/api-reports/api-extractor.ts +++ b/packages/repo-tools/src/commands/api-reports/api-extractor.ts @@ -40,6 +40,8 @@ import { IDocNodeContainerParameters, TSDocTagSyntaxKind, TSDocConfiguration, + Standardization, + DocBlockTag, DocPlainText, DocLinkTag, } from '@microsoft/tsdoc'; @@ -342,7 +344,12 @@ export async function getTsDocConfig() { tagName: '@ignore', syntaxKind: TSDocTagSyntaxKind.ModifierTag, }); + tsdocConfigFile.addTagDefinition({ + tagName: '@config', + syntaxKind: TSDocTagSyntaxKind.BlockTag, + }); tsdocConfigFile.setSupportForTag('@ignore', true); + tsdocConfigFile.setSupportForTag('@config', true); return tsdocConfigFile; } @@ -879,9 +886,15 @@ export async function buildDocs({ context.writer.writeLine(); break; } + case 'BlockTag': { + const node = docNode as DocBlockTag; + if (node.tagName === '@config') { + context.writer.writeLine('## Related config '); + } + break; + } case DocCodeSpanLink.kind: { const node = docNode as DocLinkTag; - if (node.codeDestination) { // TODO @sarabadu understand if we need `codeDestination` at all on this custom DocCodeSpanLink super.writeLinkTagWithCodeDestination(node, context); @@ -938,8 +951,19 @@ export async function buildDocs({ DocFrontMatter.kind, DocCodeSpanLink.kind, ]); - ); + const def = { + tagName: '@config', + syntaxKind: TSDocTagSyntaxKind.BlockTag, + tagNameWithUpperCase: '@CONFIG', + standardization: Standardization.Extended, + allowMultiple: false, + }; + (this._tsdocConfiguration as TSDocConfiguration).addTagDefinition(def); + (this._tsdocConfiguration as TSDocConfiguration).setSupportForTag( + def, + true, + ); this._markdownEmitter = new CustomCustomMarkdownEmitter(newModel); } diff --git a/plugins/proxy-backend/api-report.md b/plugins/proxy-backend/api-report.md index b6497adbaf..581e7a904c 100644 --- a/plugins/proxy-backend/api-report.md +++ b/plugins/proxy-backend/api-report.md @@ -8,7 +8,7 @@ import express from 'express'; import { Logger } from 'winston'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; -// @public (undocumented) +// @public export function createRouter(options: RouterOptions): Promise; // @public (undocumented) diff --git a/plugins/proxy-backend/src/service/router.ts b/plugins/proxy-backend/src/service/router.ts index b7ee7014bc..224c2c6202 100644 --- a/plugins/proxy-backend/src/service/router.ts +++ b/plugins/proxy-backend/src/service/router.ts @@ -178,7 +178,24 @@ export function buildMiddleware( return createProxyMiddleware(filter, fullConfig); } -/** @public */ +/** + * Creates a new {@link https://expressjs.com/en/api.html#router | "express router"} that proxy each target configured under the `proxy` key of the config + * @example + * ```ts + * let router = await createRouter({logger, config, discovery}); + * ``` + * @config + * ```yaml + * proxy: + * simple-example: http://simple.example.com:8080 # Opt 1 Simple URL String + * '/larger-example/v1': # Opt 2 `http-proxy-middleware` compatible object + * target: http://larger.example.com:8080/svc.v1 + * headers: + * Authorization: Bearer ${EXAMPLE_AUTH_TOKEN} + *``` + * @see https://backstage.io/docs/plugins/proxying + * @public + */ export async function createRouter( options: RouterOptions, ): Promise { From 03843259b4941b727ffaf07886865617e8076ee6 Mon Sep 17 00:00:00 2001 From: Juan Pablo Garcia Ripa Date: Mon, 28 Nov 2022 20:58:51 +0100 Subject: [PATCH 3/4] add changeset and prettier Signed-off-by: Juan Pablo Garcia Ripa --- .changeset/slow-eggs-grab.md | 8 ++++++++ .changeset/warm-parents-notice.md | 5 +++++ .../repo-tools/src/commands/api-reports/api-extractor.ts | 2 +- 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 .changeset/slow-eggs-grab.md create mode 100644 .changeset/warm-parents-notice.md diff --git a/.changeset/slow-eggs-grab.md b/.changeset/slow-eggs-grab.md new file mode 100644 index 0000000000..e4c537687f --- /dev/null +++ b/.changeset/slow-eggs-grab.md @@ -0,0 +1,8 @@ +--- +'@backstage/repo-tools': minor +--- + +Api reference documentation improvements + +- breadcrumbs links semantics as code spans +- new `@config` annotation to describe related config keys diff --git a/.changeset/warm-parents-notice.md b/.changeset/warm-parents-notice.md new file mode 100644 index 0000000000..9ea14e2068 --- /dev/null +++ b/.changeset/warm-parents-notice.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-proxy-backend': patch +--- + +Add documentation to de api reference diff --git a/packages/repo-tools/src/commands/api-reports/api-extractor.ts b/packages/repo-tools/src/commands/api-reports/api-extractor.ts index 2b130f50e0..bae62ccc7e 100644 --- a/packages/repo-tools/src/commands/api-reports/api-extractor.ts +++ b/packages/repo-tools/src/commands/api-reports/api-extractor.ts @@ -1037,7 +1037,7 @@ export async function buildDocs({ configuration, text: ' > ', }), - new DocCodeSpanLink({ + new DocCodeSpanLink({ configuration, tagName: '@link', linkText: hierarchyItem.displayName, From e3747dab822fa89c108c1207091edd97feed35ec Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 29 Nov 2022 10:30:52 +0100 Subject: [PATCH 4/4] Update .changeset/warm-parents-notice.md Signed-off-by: Patrik Oldsberg --- .changeset/warm-parents-notice.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/warm-parents-notice.md b/.changeset/warm-parents-notice.md index 9ea14e2068..0084a968a1 100644 --- a/.changeset/warm-parents-notice.md +++ b/.changeset/warm-parents-notice.md @@ -2,4 +2,4 @@ '@backstage/plugin-proxy-backend': patch --- -Add documentation to de api reference +Documented the `createRouter` method.