From 89e4ffb29b37100984b1767760851eb33d3ce01b Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Thu, 22 Sep 2022 12:11:39 -0700 Subject: [PATCH 1/6] First pass --- .changeset/popular-beans-wonder.md | 5 ++ .../api-documenter/src/cli/MarkdownAction.ts | 16 ++++- .../src/documenters/MarkdownDocumenter.ts | 61 ++++++++++++++++--- scripts/docgen/docgen.ts | 3 +- 4 files changed, 73 insertions(+), 12 deletions(-) create mode 100644 .changeset/popular-beans-wonder.md diff --git a/.changeset/popular-beans-wonder.md b/.changeset/popular-beans-wonder.md new file mode 100644 index 00000000000..65c9d801b78 --- /dev/null +++ b/.changeset/popular-beans-wonder.md @@ -0,0 +1,5 @@ +--- +'@firebase/api-documenter': minor +--- + +Add an option to sort functions by first param. (--sort-functions) diff --git a/repo-scripts/api-documenter/src/cli/MarkdownAction.ts b/repo-scripts/api-documenter/src/cli/MarkdownAction.ts index b5d4156c8c9..f70db55cf12 100644 --- a/repo-scripts/api-documenter/src/cli/MarkdownAction.ts +++ b/repo-scripts/api-documenter/src/cli/MarkdownAction.ts @@ -21,8 +21,10 @@ import { ApiDocumenterCommandLine } from './ApiDocumenterCommandLine'; import { BaseAction } from './BaseAction'; import { MarkdownDocumenter } from '../documenters/MarkdownDocumenter'; +import { CommandLineFlagParameter } from '@rushstack/ts-command-line'; export class MarkdownAction extends BaseAction { + private _shouldSortFunctions!: CommandLineFlagParameter; public constructor(parser: ApiDocumenterCommandLine) { super({ actionName: 'markdown', @@ -33,10 +35,21 @@ export class MarkdownAction extends BaseAction { }); } + protected onDefineParameters(): void { + super.onDefineParameters(); + + this._shouldSortFunctions = this.defineFlagParameter({ + parameterLongName: '--sort-functions', + description: + `Sorts functions tables and listings by first parameter.` + }); + } + protected async onExecute(): Promise { // override const { apiModel, outputFolder, addFileNameSuffix, projectName } = this.buildApiModel(); + const shouldSortFunctions: boolean = this._shouldSortFunctions.value; if (!projectName) { throw new Error('No project name provided. Use --project.'); @@ -47,7 +60,8 @@ export class MarkdownAction extends BaseAction { documenterConfig: undefined, outputFolder, addFileNameSuffix, - projectName + projectName, + shouldSortFunctions }); markdownDocumenter.generateFiles(); } diff --git a/repo-scripts/api-documenter/src/documenters/MarkdownDocumenter.ts b/repo-scripts/api-documenter/src/documenters/MarkdownDocumenter.ts index f8215d0a19a..e7e26827149 100644 --- a/repo-scripts/api-documenter/src/documenters/MarkdownDocumenter.ts +++ b/repo-scripts/api-documenter/src/documenters/MarkdownDocumenter.ts @@ -93,6 +93,7 @@ export interface IMarkdownDocumenterOptions { outputFolder: string; addFileNameSuffix: boolean; projectName: string; + shouldSortFunctions: boolean; } /** @@ -108,6 +109,7 @@ export class MarkdownDocumenter { private readonly _pluginLoader: PluginLoader; private readonly _addFileNameSuffix: boolean; private readonly _projectName: string; + private readonly _shouldSortFunctions: boolean; public constructor(options: IMarkdownDocumenterOptions) { this._apiModel = options.apiModel; @@ -115,6 +117,7 @@ export class MarkdownDocumenter { this._outputFolder = options.outputFolder; this._addFileNameSuffix = options.addFileNameSuffix; this._projectName = options.projectName; + this._shouldSortFunctions = options.shouldSortFunctions; this._tsdocConfiguration = CustomDocNodes.configuration; this._markdownEmitter = new CustomMarkdownEmitter(this._apiModel); @@ -834,11 +837,13 @@ page_type: reference headerTitles: ['Enumeration', 'Description'] }); - const functionsTable: DocTable = new DocTable({ + const finalFunctionsTable: DocTable = new DocTable({ configuration, headerTitles: ['Function', 'Description'] }); + const functionsRowGroup: Record = {}; + const interfacesTable: DocTable = new DocTable({ configuration, headerTitles: ['Interface', 'Description'] @@ -859,7 +864,8 @@ page_type: reference headerTitles: ['Type Alias', 'Description'] }); - const functionsDefinitions: DocNode[] = []; + const functionsDefinitionsGroup: Record = {}; + const finalFunctionsDefinitions: DocNode[] = []; const variablesDefinitions: DocNode[] = []; const typeAliasDefinitions: DocNode[] = []; const enumsDefinitions: DocNode[] = []; @@ -899,10 +905,24 @@ page_type: reference break; case ApiItemKind.Function: - functionsTable.addRow(row); - functionsDefinitions.push( - ...this._createCompleteOutputForApiItem(apiMember) - ); + if (this._shouldSortFunctions) { + const firstParam = (apiMember as ApiParameterListMixin).parameters[0] || { name : '' }; + if (!functionsRowGroup[firstParam.name]) { + functionsRowGroup[firstParam.name] = []; + } + if (!functionsDefinitionsGroup[firstParam.name]) { + functionsDefinitionsGroup[firstParam.name] = []; + } + functionsRowGroup[firstParam.name].push(row); + functionsDefinitionsGroup[firstParam.name].push( + ...this._createCompleteOutputForApiItem(apiMember) + ); + } else { + finalFunctionsTable.addRow(row); + finalFunctionsDefinitions.push( + ...this._createCompleteOutputForApiItem(apiMember) + ); + } break; case ApiItemKind.TypeAlias: @@ -921,9 +941,30 @@ page_type: reference } } - if (functionsTable.rows.length > 0) { + if (this._shouldSortFunctions) { + const sortedFunctionsFirstParamKeys = Object.keys(functionsRowGroup).sort((a, b) => { + if (a === 'app') { + return -1; + } + return (a.localeCompare(b)); + }); + + for (const paramKey of sortedFunctionsFirstParamKeys) { + if (finalFunctionsTable.rows.length > 0) { + finalFunctionsTable.createAndAddRow(); + } + for (const functionsRow of functionsRowGroup[paramKey]) { + finalFunctionsTable.addRow(functionsRow); + } + for (const functionDefinition of functionsDefinitionsGroup[paramKey]) { + finalFunctionsDefinitions.push(functionDefinition); + } + } + } + + if (finalFunctionsTable.rows.length > 0) { output.push(new DocHeading({ configuration, title: 'Functions' })); - output.push(functionsTable); + output.push(finalFunctionsTable); } if (classesTable.rows.length > 0) { @@ -956,8 +997,8 @@ page_type: reference output.push(typeAliasesTable); } - if (functionsDefinitions.length > 0) { - output.push(...functionsDefinitions); + if (finalFunctionsDefinitions.length > 0) { + output.push(...finalFunctionsDefinitions); } if (variablesDefinitions.length > 0) { diff --git a/scripts/docgen/docgen.ts b/scripts/docgen/docgen.ts index 5df01925338..effdefc88d2 100644 --- a/scripts/docgen/docgen.ts +++ b/scripts/docgen/docgen.ts @@ -181,7 +181,8 @@ async function generateDocs( '--output', outputFolder, '--project', - 'js' + 'js', + '--sort-functions' ], { stdio: 'inherit' } ); From fa534e5d333510b114f136f69a5e40907341eb8c Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Thu, 22 Sep 2022 13:50:51 -0700 Subject: [PATCH 2/6] Add section headers --- .../api-documenter/src/cli/MarkdownAction.ts | 15 +++-- .../src/documenters/MarkdownDocumenter.ts | 64 +++++++++++++++---- scripts/docgen/docgen.ts | 3 +- 3 files changed, 61 insertions(+), 21 deletions(-) diff --git a/repo-scripts/api-documenter/src/cli/MarkdownAction.ts b/repo-scripts/api-documenter/src/cli/MarkdownAction.ts index f70db55cf12..494c37bc560 100644 --- a/repo-scripts/api-documenter/src/cli/MarkdownAction.ts +++ b/repo-scripts/api-documenter/src/cli/MarkdownAction.ts @@ -21,10 +21,10 @@ import { ApiDocumenterCommandLine } from './ApiDocumenterCommandLine'; import { BaseAction } from './BaseAction'; import { MarkdownDocumenter } from '../documenters/MarkdownDocumenter'; -import { CommandLineFlagParameter } from '@rushstack/ts-command-line'; +import { CommandLineStringParameter } from '@rushstack/ts-command-line'; export class MarkdownAction extends BaseAction { - private _shouldSortFunctions!: CommandLineFlagParameter; + private _sortFunctions!: CommandLineStringParameter; public constructor(parser: ApiDocumenterCommandLine) { super({ actionName: 'markdown', @@ -38,10 +38,13 @@ export class MarkdownAction extends BaseAction { protected onDefineParameters(): void { super.onDefineParameters(); - this._shouldSortFunctions = this.defineFlagParameter({ + this._sortFunctions = this.defineStringParameter({ parameterLongName: '--sort-functions', + argumentName: 'PRIORITY_PARAMS', description: - `Sorts functions tables and listings by first parameter.` + `Sorts functions tables and listings by first parameter.` + + ` Provide comma-separated strings for preferred params to be ` + + `ordered first. Alphabetical otherwise.` }); } @@ -49,7 +52,7 @@ export class MarkdownAction extends BaseAction { // override const { apiModel, outputFolder, addFileNameSuffix, projectName } = this.buildApiModel(); - const shouldSortFunctions: boolean = this._shouldSortFunctions.value; + const sortFunctions: string = this._sortFunctions.value || ''; if (!projectName) { throw new Error('No project name provided. Use --project.'); @@ -61,7 +64,7 @@ export class MarkdownAction extends BaseAction { outputFolder, addFileNameSuffix, projectName, - shouldSortFunctions + sortFunctions }); markdownDocumenter.generateFiles(); } diff --git a/repo-scripts/api-documenter/src/documenters/MarkdownDocumenter.ts b/repo-scripts/api-documenter/src/documenters/MarkdownDocumenter.ts index e7e26827149..69e87461ecf 100644 --- a/repo-scripts/api-documenter/src/documenters/MarkdownDocumenter.ts +++ b/repo-scripts/api-documenter/src/documenters/MarkdownDocumenter.ts @@ -93,7 +93,7 @@ export interface IMarkdownDocumenterOptions { outputFolder: string; addFileNameSuffix: boolean; projectName: string; - shouldSortFunctions: boolean; + sortFunctions: string; } /** @@ -109,7 +109,7 @@ export class MarkdownDocumenter { private readonly _pluginLoader: PluginLoader; private readonly _addFileNameSuffix: boolean; private readonly _projectName: string; - private readonly _shouldSortFunctions: boolean; + private readonly _sortFunctions: string; public constructor(options: IMarkdownDocumenterOptions) { this._apiModel = options.apiModel; @@ -117,7 +117,7 @@ export class MarkdownDocumenter { this._outputFolder = options.outputFolder; this._addFileNameSuffix = options.addFileNameSuffix; this._projectName = options.projectName; - this._shouldSortFunctions = options.shouldSortFunctions; + this._sortFunctions = options.sortFunctions; this._tsdocConfiguration = CustomDocNodes.configuration; this._markdownEmitter = new CustomMarkdownEmitter(this._apiModel); @@ -905,8 +905,13 @@ page_type: reference break; case ApiItemKind.Function: - if (this._shouldSortFunctions) { - const firstParam = (apiMember as ApiParameterListMixin).parameters[0] || { name : '' }; + /** + * If this option is set, group functions by first param. + * Organize using a map where the key is the first param. + */ + if (this._sortFunctions) { + const firstParam = (apiMember as ApiParameterListMixin) + .parameters[0] || { name: '' }; if (!functionsRowGroup[firstParam.name]) { functionsRowGroup[firstParam.name] = []; } @@ -941,17 +946,48 @@ page_type: reference } } - if (this._shouldSortFunctions) { - const sortedFunctionsFirstParamKeys = Object.keys(functionsRowGroup).sort((a, b) => { - if (a === 'app') { - return -1; + /** + * Sort the functions groups by first param. If priority params were + * provided to --sort-functions, will put them first in the order + * given. + */ + if (this._sortFunctions) { + let priorityParams: string[] = []; + if (this._sortFunctions.includes(',')) { + priorityParams = this._sortFunctions.split(','); + } else { + priorityParams = [this._sortFunctions]; + } + const sortedFunctionsFirstParamKeys = Object.keys(functionsRowGroup).sort( + (a, b) => { + if (!a || !b) { + console.log(`Missing one. a:${a}, b:${b}`) + } + if (priorityParams.includes(a) && priorityParams.includes(b)) { + return priorityParams.indexOf(a) - priorityParams.indexOf(b); + } else if (priorityParams.includes(a)) { + return -1; + } else if (priorityParams.includes(b)) { + return 1; + } + return a.localeCompare(b); } - return (a.localeCompare(b)); - }); - + ); + for (const paramKey of sortedFunctionsFirstParamKeys) { - if (finalFunctionsTable.rows.length > 0) { - finalFunctionsTable.createAndAddRow(); + // Header for each group of functions grouped by first param. + // Doesn't make sense if there's only one group. + const headerText = paramKey ? `function(${paramKey}...)` : 'function()'; + if (sortedFunctionsFirstParamKeys.length > 1) { + finalFunctionsTable.addRow( + new DocTableRow({ configuration }, [ + new DocTableCell({ configuration }, [ + new DocParagraph({ configuration }, [ + new DocPlainText({ configuration, text: headerText }) + ]) + ]) + ]) + ); } for (const functionsRow of functionsRowGroup[paramKey]) { finalFunctionsTable.addRow(functionsRow); diff --git a/scripts/docgen/docgen.ts b/scripts/docgen/docgen.ts index effdefc88d2..6d9a3ae478f 100644 --- a/scripts/docgen/docgen.ts +++ b/scripts/docgen/docgen.ts @@ -182,7 +182,8 @@ async function generateDocs( outputFolder, '--project', 'js', - '--sort-functions' + '--sort-functions', + 'app,appCheck,auth,analytics,database,firestore,functions,storage,installations,messaging,performance,remoteConfig' ], { stdio: 'inherit' } ); From 2ae759bbb1189fb384b9821f802bb985753a86e6 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Thu, 22 Sep 2022 13:51:07 -0700 Subject: [PATCH 3/6] format --- .../api-documenter/src/documenters/MarkdownDocumenter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/repo-scripts/api-documenter/src/documenters/MarkdownDocumenter.ts b/repo-scripts/api-documenter/src/documenters/MarkdownDocumenter.ts index 69e87461ecf..5f9b43ab298 100644 --- a/repo-scripts/api-documenter/src/documenters/MarkdownDocumenter.ts +++ b/repo-scripts/api-documenter/src/documenters/MarkdownDocumenter.ts @@ -961,7 +961,7 @@ page_type: reference const sortedFunctionsFirstParamKeys = Object.keys(functionsRowGroup).sort( (a, b) => { if (!a || !b) { - console.log(`Missing one. a:${a}, b:${b}`) + console.log(`Missing one. a:${a}, b:${b}`); } if (priorityParams.includes(a) && priorityParams.includes(b)) { return priorityParams.indexOf(a) - priorityParams.indexOf(b); From 5889d768c958f00a442fd71e8b18425d14d84dad Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Mon, 26 Sep 2022 10:02:06 -0700 Subject: [PATCH 4/6] Update priority param strings --- .../src/documenters/MarkdownDocumenter.ts | 3 --- scripts/docgen/docgen.ts | 20 ++++++++++++++++++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/repo-scripts/api-documenter/src/documenters/MarkdownDocumenter.ts b/repo-scripts/api-documenter/src/documenters/MarkdownDocumenter.ts index 5f9b43ab298..e13196261c7 100644 --- a/repo-scripts/api-documenter/src/documenters/MarkdownDocumenter.ts +++ b/repo-scripts/api-documenter/src/documenters/MarkdownDocumenter.ts @@ -960,9 +960,6 @@ page_type: reference } const sortedFunctionsFirstParamKeys = Object.keys(functionsRowGroup).sort( (a, b) => { - if (!a || !b) { - console.log(`Missing one. a:${a}, b:${b}`); - } if (priorityParams.includes(a) && priorityParams.includes(b)) { return priorityParams.indexOf(a) - priorityParams.indexOf(b); } else if (priorityParams.includes(a)) { diff --git a/scripts/docgen/docgen.ts b/scripts/docgen/docgen.ts index 6d9a3ae478f..c2f39b24469 100644 --- a/scripts/docgen/docgen.ts +++ b/scripts/docgen/docgen.ts @@ -39,6 +39,24 @@ https://github.com/firebase/firebase-js-sdk const tmpDir = `${projectRoot}/temp`; const EXCLUDED_PACKAGES = ['app-compat', 'util', 'rules-unit-testing']; +/** + * When ordering functions, will prioritize these first params at + * the top, in order. + */ +const PREFERRED_PARAMS = [ + 'app', + 'analyticsInstance', + 'appCheckInstance', + 'db', + 'firestore', + 'functionsInstance', + 'installations', + 'messaging', + 'performance', + 'remoteConfig', + 'storage' +]; + yargs .command( '$0', @@ -183,7 +201,7 @@ async function generateDocs( '--project', 'js', '--sort-functions', - 'app,appCheck,auth,analytics,database,firestore,functions,storage,installations,messaging,performance,remoteConfig' + PREFERRED_PARAMS.join(',') ], { stdio: 'inherit' } ); From 1549e385783386f8aec5fe15d33af1bf3361ae87 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Thu, 13 Oct 2022 10:27:52 -0700 Subject: [PATCH 5/6] Add strong tags --- .../api-documenter/src/documenters/MarkdownDocumenter.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/repo-scripts/api-documenter/src/documenters/MarkdownDocumenter.ts b/repo-scripts/api-documenter/src/documenters/MarkdownDocumenter.ts index e13196261c7..2be5cb87143 100644 --- a/repo-scripts/api-documenter/src/documenters/MarkdownDocumenter.ts +++ b/repo-scripts/api-documenter/src/documenters/MarkdownDocumenter.ts @@ -975,12 +975,13 @@ page_type: reference // Header for each group of functions grouped by first param. // Doesn't make sense if there's only one group. const headerText = paramKey ? `function(${paramKey}...)` : 'function()'; + const formattedHeaderText = `${headerText}`; if (sortedFunctionsFirstParamKeys.length > 1) { finalFunctionsTable.addRow( new DocTableRow({ configuration }, [ new DocTableCell({ configuration }, [ new DocParagraph({ configuration }, [ - new DocPlainText({ configuration, text: headerText }) + new DocPlainText({ configuration, text: formattedHeaderText }) ]) ]) ]) From c9cf40f3da09e91111490b7919897591133c3025 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Thu, 13 Oct 2022 11:33:22 -0700 Subject: [PATCH 6/6] Adjust formatting --- repo-scripts/api-documenter/src/cli/MarkdownAction.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/repo-scripts/api-documenter/src/cli/MarkdownAction.ts b/repo-scripts/api-documenter/src/cli/MarkdownAction.ts index 494c37bc560..903f41ebf49 100644 --- a/repo-scripts/api-documenter/src/cli/MarkdownAction.ts +++ b/repo-scripts/api-documenter/src/cli/MarkdownAction.ts @@ -42,8 +42,8 @@ export class MarkdownAction extends BaseAction { parameterLongName: '--sort-functions', argumentName: 'PRIORITY_PARAMS', description: - `Sorts functions tables and listings by first parameter.` + - ` Provide comma-separated strings for preferred params to be ` + + `Sorts functions tables and listings by first parameter. ` + + `Provide comma-separated strings for preferred params to be ` + `ordered first. Alphabetical otherwise.` }); }