From c31ded6f36b4d9787489c586685bdd7abe140bf3 Mon Sep 17 00:00:00 2001 From: Feiyang1 Date: Tue, 20 Apr 2021 16:23:04 -0700 Subject: [PATCH 1/4] generate link for namespaces correctly --- .../src/documenters/MarkdownDocumenterHelpers.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/repo-scripts/api-documenter/src/documenters/MarkdownDocumenterHelpers.ts b/repo-scripts/api-documenter/src/documenters/MarkdownDocumenterHelpers.ts index 30dec957eeb..908a4e072d0 100644 --- a/repo-scripts/api-documenter/src/documenters/MarkdownDocumenterHelpers.ts +++ b/repo-scripts/api-documenter/src/documenters/MarkdownDocumenterHelpers.ts @@ -96,9 +96,18 @@ export function getFilenameForApiItem(apiItem: ApiItem): string { multipleEntryPoints = true; } break; + case ApiItemKind.Namespace: + baseName += '.' + qualifiedName; + break; + // append the file name with the first letter of the ApiItemKind to avoid name collision. + // Sometimes we could have a class/interface and an entry point that have the same name. + // This happened in the admin SDK where the App interface and the app namespace write to the same file. case ApiItemKind.Class: + baseName += '.' + qualifiedName + '_c'; + break; case ApiItemKind.Interface: - baseName += '.' + qualifiedName; + baseName += '.' + qualifiedName + '_i'; + break; } } return baseName + '.md'; From 3b18da181294e43bea387142278850b8f6ea686e Mon Sep 17 00:00:00 2001 From: Feiyang1 Date: Wed, 21 Apr 2021 11:20:30 -0700 Subject: [PATCH 2/4] add addFileNameSuffix option --- .../api-documenter/src/cli/BaseAction.ts | 18 ++++- .../api-documenter/src/cli/MarkdownAction.ts | 5 +- .../src/documenters/MarkdownDocumenter.ts | 66 +++++++++++++++---- .../documenters/MarkdownDocumenterHelpers.ts | 32 ++++++--- 4 files changed, 95 insertions(+), 26 deletions(-) diff --git a/repo-scripts/api-documenter/src/cli/BaseAction.ts b/repo-scripts/api-documenter/src/cli/BaseAction.ts index 8dfbc40770e..f3cd12a3607 100644 --- a/repo-scripts/api-documenter/src/cli/BaseAction.ts +++ b/repo-scripts/api-documenter/src/cli/BaseAction.ts @@ -24,6 +24,7 @@ import colors from 'colors'; import { CommandLineAction, + CommandLineFlagParameter, CommandLineStringParameter } from '@rushstack/ts-command-line'; import { FileSystem } from '@rushstack/node-core-library'; @@ -39,11 +40,13 @@ export interface IBuildApiModelResult { apiModel: ApiModel; inputFolder: string; outputFolder: string; + addFileNameSuffix: boolean; } export abstract class BaseAction extends CommandLineAction { private _inputFolderParameter!: CommandLineStringParameter; private _outputFolderParameter!: CommandLineStringParameter; + private _fileNameSuffixParameter!: CommandLineFlagParameter; protected onDefineParameters(): void { // override @@ -65,6 +68,17 @@ export abstract class BaseAction extends CommandLineAction { ` ANY EXISTING CONTENTS WILL BE DELETED!` + ` If omitted, the default is "./${this.actionName}"` }); + + this._fileNameSuffixParameter = this.defineFlagParameter({ + parameterLongName: '--name-suffix', + parameterShortName: '-s', + description: + `Add suffix to interface and class names in the file path.` + + `For example, packageA.myinterface_i.md for MyInterface interface, ` + + `Add packageA.myclass_c.md for MyClass class.` + + `This is to avoid name conflict in case packageA also has, for example, a namespace with the same name in lowercase.` + + `This option is specifically designed for the Admin SDK where such case occurs.` + }); } protected buildApiModel(): IBuildApiModelResult { @@ -79,6 +93,8 @@ export abstract class BaseAction extends CommandLineAction { this._outputFolderParameter.value || `./${this.actionName}`; FileSystem.ensureFolder(outputFolder); + const addFileNameSuffix: boolean = this._fileNameSuffixParameter.value; + for (const filename of FileSystem.readFolder(inputFolder)) { if (filename.match(/\.api\.json$/i)) { console.log(`Reading ${filename}`); @@ -89,7 +105,7 @@ export abstract class BaseAction extends CommandLineAction { this._applyInheritDoc(apiModel, apiModel); - return { apiModel, inputFolder, outputFolder }; + return { apiModel, inputFolder, outputFolder, addFileNameSuffix }; } // TODO: This is a temporary workaround. The long term plan is for API Extractor's DocCommentEnhancer diff --git a/repo-scripts/api-documenter/src/cli/MarkdownAction.ts b/repo-scripts/api-documenter/src/cli/MarkdownAction.ts index 274e0ed48d8..e28e9ec6854 100644 --- a/repo-scripts/api-documenter/src/cli/MarkdownAction.ts +++ b/repo-scripts/api-documenter/src/cli/MarkdownAction.ts @@ -35,12 +35,13 @@ export class MarkdownAction extends BaseAction { protected async onExecute(): Promise { // override - const { apiModel, outputFolder } = this.buildApiModel(); + const { apiModel, outputFolder, addFileNameSuffix } = this.buildApiModel(); const markdownDocumenter: MarkdownDocumenter = new MarkdownDocumenter({ apiModel, documenterConfig: undefined, - outputFolder + outputFolder, + addFileNameSuffix }); markdownDocumenter.generateFiles(); } diff --git a/repo-scripts/api-documenter/src/documenters/MarkdownDocumenter.ts b/repo-scripts/api-documenter/src/documenters/MarkdownDocumenter.ts index 2f79de6e9ad..3163b88d536 100644 --- a/repo-scripts/api-documenter/src/documenters/MarkdownDocumenter.ts +++ b/repo-scripts/api-documenter/src/documenters/MarkdownDocumenter.ts @@ -91,6 +91,7 @@ export interface IMarkdownDocumenterOptions { apiModel: ApiModel; documenterConfig: DocumenterConfig | undefined; outputFolder: string; + addFileNameSuffix: boolean; } /** @@ -104,11 +105,13 @@ export class MarkdownDocumenter { private readonly _markdownEmitter: CustomMarkdownEmitter; private readonly _outputFolder: string; private readonly _pluginLoader: PluginLoader; + private readonly _addFileNameSuffix: boolean; public constructor(options: IMarkdownDocumenterOptions) { this._apiModel = options.apiModel; this._documenterConfig = options.documenterConfig; this._outputFolder = options.outputFolder; + this._addFileNameSuffix = options.addFileNameSuffix; this._tsdocConfiguration = CustomDocNodes.configuration; this._markdownEmitter = new CustomMarkdownEmitter(this._apiModel); @@ -123,7 +126,7 @@ export class MarkdownDocumenter { outputFolder: this._outputFolder, documenter: new MarkdownDocumenterAccessor({ getLinkForApiItem: (apiItem: ApiItem) => { - return getLinkForApiItem(apiItem); + return getLinkForApiItem(apiItem, this._addFileNameSuffix); } }) }); @@ -156,7 +159,7 @@ export class MarkdownDocumenter { // write to file const filename: string = path.join( this._outputFolder, - getFilenameForApiItem(apiItem) + getFilenameForApiItem(apiItem, this._addFileNameSuffix) ); const stringBuilder: StringBuilder = new StringBuilder(); @@ -172,7 +175,7 @@ export class MarkdownDocumenter { this._markdownEmitter.emit(stringBuilder, output, { contextApiItem: apiItem, onGetFilenameForApiItem: (apiItemForFilename: ApiItem) => { - return getLinkForApiItem(apiItemForFilename); + return getLinkForApiItem(apiItemForFilename, this._addFileNameSuffix); } }); @@ -393,7 +396,11 @@ export class MarkdownDocumenter { case ApiItemKind.Constructor: { constructorsTable.addRow( new DocTableRow({ configuration }, [ - createTitleCell(apiMember, configuration), + createTitleCell( + apiMember, + configuration, + this._addFileNameSuffix + ), createModifiersCell(apiMember, configuration), createDescriptionCell(apiMember, configuration) ]) @@ -407,7 +414,11 @@ export class MarkdownDocumenter { case ApiItemKind.Method: { methodsTable.addRow( new DocTableRow({ configuration }, [ - createTitleCell(apiMember, configuration), + createTitleCell( + apiMember, + configuration, + this._addFileNameSuffix + ), createModifiersCell(apiMember, configuration), createDescriptionCell(apiMember, configuration) ]) @@ -422,7 +433,11 @@ export class MarkdownDocumenter { if ((apiMember as ApiPropertyItem).isEventProperty) { eventsTable.addRow( new DocTableRow({ configuration }, [ - createTitleCell(apiMember, configuration), + createTitleCell( + apiMember, + configuration, + this._addFileNameSuffix + ), createModifiersCell(apiMember, configuration), this._createPropertyTypeCell(apiMember), createDescriptionCell(apiMember, configuration) @@ -435,7 +450,11 @@ export class MarkdownDocumenter { } else { propertiesTable.addRow( new DocTableRow({ configuration }, [ - createTitleCell(apiMember, configuration), + createTitleCell( + apiMember, + configuration, + this._addFileNameSuffix + ), createModifiersCell(apiMember, configuration), this._createPropertyTypeCell(apiMember), createDescriptionCell(apiMember, configuration) @@ -509,7 +528,11 @@ export class MarkdownDocumenter { case ApiItemKind.MethodSignature: { methodsTable.addRow( new DocTableRow({ configuration }, [ - createTitleCell(apiMember, configuration), + createTitleCell( + apiMember, + configuration, + this._addFileNameSuffix + ), createDescriptionCell(apiMember, configuration) ]) ); @@ -523,7 +546,11 @@ export class MarkdownDocumenter { if ((apiMember as ApiPropertyItem).isEventProperty) { eventsTable.addRow( new DocTableRow({ configuration }, [ - createTitleCell(apiMember, configuration), + createTitleCell( + apiMember, + configuration, + this._addFileNameSuffix + ), this._createPropertyTypeCell(apiMember), createDescriptionCell(apiMember, configuration) ]) @@ -534,7 +561,11 @@ export class MarkdownDocumenter { } else { propertiesTable.addRow( new DocTableRow({ configuration }, [ - createTitleCell(apiMember, configuration), + createTitleCell( + apiMember, + configuration, + this._addFileNameSuffix + ), this._createPropertyTypeCell(apiMember), createDescriptionCell(apiMember, configuration) ]) @@ -686,7 +717,10 @@ export class MarkdownDocumenter { configuration, tagName: '@link', linkText: unwrappedTokenText, - urlDestination: getLinkForApiItem(apiItemResult.resolvedApiItem) + urlDestination: getLinkForApiItem( + apiItemResult.resolvedApiItem, + this._addFileNameSuffix + ) }) ); continue; @@ -714,7 +748,7 @@ export class MarkdownDocumenter { for (const apiMember of apiModel.members) { const row: DocTableRow = new DocTableRow({ configuration }, [ - createTitleCell(apiMember, configuration), + createTitleCell(apiMember, configuration, this._addFileNameSuffix), createDescriptionCell(apiMember, configuration) ]); @@ -755,7 +789,11 @@ export class MarkdownDocumenter { for (const entryPoint of apiContainer.entryPoints) { const row: DocTableRow = new DocTableRow({ configuration }, [ - createEntryPointTitleCell(entryPoint, configuration), + createEntryPointTitleCell( + entryPoint, + configuration, + this._addFileNameSuffix + ), createDescriptionCell(entryPoint, configuration) ]); @@ -828,7 +866,7 @@ export class MarkdownDocumenter { for (const apiMember of apiMembers) { const row: DocTableRow = new DocTableRow({ configuration }, [ - createTitleCell(apiMember, configuration), + createTitleCell(apiMember, configuration, this._addFileNameSuffix), createDescriptionCell(apiMember, configuration) ]); diff --git a/repo-scripts/api-documenter/src/documenters/MarkdownDocumenterHelpers.ts b/repo-scripts/api-documenter/src/documenters/MarkdownDocumenterHelpers.ts index 908a4e072d0..93ba487c875 100644 --- a/repo-scripts/api-documenter/src/documenters/MarkdownDocumenterHelpers.ts +++ b/repo-scripts/api-documenter/src/documenters/MarkdownDocumenterHelpers.ts @@ -49,13 +49,19 @@ import { DocNoteBox } from '../nodes/DocNoteBox'; import { DocTableRow } from '../nodes/DocTableRow'; import { DocTableCell } from '../nodes/DocTableCell'; -export function getLinkForApiItem(apiItem: ApiItem) { - const fileName = getFilenameForApiItem(apiItem); +export function getLinkForApiItem( + apiItem: ApiItem, + addFileNameSuffix: boolean +) { + const fileName = getFilenameForApiItem(apiItem, addFileNameSuffix); const headingAnchor = getHeadingAnchorForApiItem(apiItem); return `./${fileName}#${headingAnchor}`; } -export function getFilenameForApiItem(apiItem: ApiItem): string { +export function getFilenameForApiItem( + apiItem: ApiItem, + addFileNameSuffix: boolean +): string { if (apiItem.kind === ApiItemKind.Model) { return 'index.md'; } @@ -103,10 +109,16 @@ export function getFilenameForApiItem(apiItem: ApiItem): string { // Sometimes we could have a class/interface and an entry point that have the same name. // This happened in the admin SDK where the App interface and the app namespace write to the same file. case ApiItemKind.Class: - baseName += '.' + qualifiedName + '_c'; + baseName += '.' + qualifiedName; + if (addFileNameSuffix) { + baseName += '_c'; + } break; case ApiItemKind.Interface: - baseName += '.' + qualifiedName + '_i'; + baseName += '.' + qualifiedName; + if (addFileNameSuffix) { + baseName += '_i'; + } break; } } @@ -233,7 +245,8 @@ export function createExampleSection( export function createTitleCell( apiItem: ApiItem, - configuration: TSDocConfiguration + configuration: TSDocConfiguration, + addFileNameSuffix: boolean ): DocTableCell { return new DocTableCell({ configuration }, [ new DocParagraph({ configuration }, [ @@ -241,7 +254,7 @@ export function createTitleCell( configuration, tagName: '@link', linkText: Utilities.getConciseSignature(apiItem), - urlDestination: getLinkForApiItem(apiItem) + urlDestination: getLinkForApiItem(apiItem, addFileNameSuffix) }) ]) ]); @@ -348,7 +361,8 @@ export function createThrowsSection( export function createEntryPointTitleCell( apiItem: ApiEntryPoint, - configuration: TSDocConfiguration + configuration: TSDocConfiguration, + addFileNameSuffix: boolean ): DocTableCell { return new DocTableCell({ configuration }, [ new DocParagraph({ configuration }, [ @@ -356,7 +370,7 @@ export function createEntryPointTitleCell( configuration, tagName: '@link', linkText: `/${apiItem.displayName}`, - urlDestination: getLinkForApiItem(apiItem) + urlDestination: getLinkForApiItem(apiItem, addFileNameSuffix) }) ]) ]); From 32968eccc186e16161c8bae38dca827b81bb9332 Mon Sep 17 00:00:00 2001 From: Feiyang1 Date: Wed, 21 Apr 2021 11:56:18 -0700 Subject: [PATCH 3/4] add suffix to namespace files --- repo-scripts/api-documenter/src/cli/BaseAction.ts | 2 +- .../src/documenters/MarkdownDocumenterHelpers.ts | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/repo-scripts/api-documenter/src/cli/BaseAction.ts b/repo-scripts/api-documenter/src/cli/BaseAction.ts index f3cd12a3607..0bed34178d3 100644 --- a/repo-scripts/api-documenter/src/cli/BaseAction.ts +++ b/repo-scripts/api-documenter/src/cli/BaseAction.ts @@ -76,7 +76,7 @@ export abstract class BaseAction extends CommandLineAction { `Add suffix to interface and class names in the file path.` + `For example, packageA.myinterface_i.md for MyInterface interface, ` + `Add packageA.myclass_c.md for MyClass class.` + - `This is to avoid name conflict in case packageA also has, for example, a namespace with the same name in lowercase.` + + `This is to avoid name conflict in case packageA also has, for example, an entry point with the same name in lowercase.` + `This option is specifically designed for the Admin SDK where such case occurs.` }); } diff --git a/repo-scripts/api-documenter/src/documenters/MarkdownDocumenterHelpers.ts b/repo-scripts/api-documenter/src/documenters/MarkdownDocumenterHelpers.ts index 93ba487c875..590393aa895 100644 --- a/repo-scripts/api-documenter/src/documenters/MarkdownDocumenterHelpers.ts +++ b/repo-scripts/api-documenter/src/documenters/MarkdownDocumenterHelpers.ts @@ -104,6 +104,9 @@ export function getFilenameForApiItem( break; case ApiItemKind.Namespace: baseName += '.' + qualifiedName; + if (addFileNameSuffix) { + baseName += '_n'; + } break; // append the file name with the first letter of the ApiItemKind to avoid name collision. // Sometimes we could have a class/interface and an entry point that have the same name. From 0a63b65ed02d4590c1af8bc9687f0adf550f012f Mon Sep 17 00:00:00 2001 From: Feiyang1 Date: Thu, 22 Apr 2021 15:10:37 -0700 Subject: [PATCH 4/4] prepare for publishing --- repo-scripts/api-documenter/package.json | 11 +++++++---- repo-scripts/api-documenter/src/start.ts | 2 ++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/repo-scripts/api-documenter/package.json b/repo-scripts/api-documenter/package.json index 8e702c69ef5..312d6fd8352 100644 --- a/repo-scripts/api-documenter/package.json +++ b/repo-scripts/api-documenter/package.json @@ -1,7 +1,6 @@ { "name": "@firebase/api-documenter", "version": "0.1.0", - "private": true, "description": "Read JSON files from api-extractor, generate documentation pages", "repository": { "directory": "repo-scripts/documenter", @@ -14,9 +13,12 @@ "test": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' nyc --reporter lcovonly -- mocha src/**/*.test.ts --config ../../config/mocharc.node.js" }, "bin": { - "api-documenter": "./bin/api-documenter" + "api-documenter-fire": "./dist/start.js" }, - "main": "lib/index.js", + "files": [ + "dist" + ], + "main": "dist/index.js", "typings": "dist/rollup.d.ts", "dependencies": { "api-extractor-model-me": "0.1.1", @@ -24,7 +26,8 @@ "@rushstack/node-core-library": "3.36.0", "@rushstack/ts-command-line": "4.7.8", "colors": "~1.2.1", - "resolve": "~1.17.0" + "resolve": "~1.17.0", + "tslib": "^2.1.0" }, "devDependencies": { "@types/resolve": "1.17.1", diff --git a/repo-scripts/api-documenter/src/start.ts b/repo-scripts/api-documenter/src/start.ts index 3ba945be7c7..55d50fb21f2 100644 --- a/repo-scripts/api-documenter/src/start.ts +++ b/repo-scripts/api-documenter/src/start.ts @@ -1,3 +1,5 @@ +#!/usr/bin/env node + /** * @license * Copyright 2020 Google LLC