diff --git a/tools/api-markdown-documenter/api-report/api-markdown-documenter.api.md b/tools/api-markdown-documenter/api-report/api-markdown-documenter.api.md index 07b3ea8dfff3..d454ef3d39ad 100644 --- a/tools/api-markdown-documenter/api-report/api-markdown-documenter.api.md +++ b/tools/api-markdown-documenter/api-report/api-markdown-documenter.api.md @@ -265,6 +265,7 @@ export interface DocumentationSuiteOptions { hierarchyBoundaries?: HierarchyBoundaries; includeBreadcrumb?: boolean; includeTopLevelDocumentHeading?: boolean; + minimumReleaseLevel?: Omit; skipPackage?: (apiPackage: ApiPackage) => boolean; } diff --git a/tools/api-markdown-documenter/package.json b/tools/api-markdown-documenter/package.json index cb7a581b34ff..76d771b67a85 100644 --- a/tools/api-markdown-documenter/package.json +++ b/tools/api-markdown-documenter/package.json @@ -1,6 +1,6 @@ { "name": "@fluid-tools/api-markdown-documenter", - "version": "0.11.1", + "version": "0.11.2", "description": "Processes .api.json files generated by API-Extractor and generates Markdown documentation from them.", "homepage": "https://fluidframework.com", "repository": { diff --git a/tools/api-markdown-documenter/src/api-item-transforms/ApiItemTransformUtilities.ts b/tools/api-markdown-documenter/src/api-item-transforms/ApiItemTransformUtilities.ts index 836b10a1a613..247fca1f8514 100644 --- a/tools/api-markdown-documenter/src/api-item-transforms/ApiItemTransformUtilities.ts +++ b/tools/api-markdown-documenter/src/api-item-transforms/ApiItemTransformUtilities.ts @@ -4,15 +4,15 @@ */ import * as Path from "node:path"; -import { ApiItem, ApiItemKind } from "@microsoft/api-extractor-model"; +import { type ApiItem, ApiItemKind, ReleaseTag } from "@microsoft/api-extractor-model"; import { Heading } from "../Heading"; import { Link } from "../Link"; -import { getQualifiedApiItemName } from "../utilities"; +import { getQualifiedApiItemName, getReleaseTag } from "../utilities"; import { - ApiItemTransformationConfiguration, - DocumentBoundaries, - HierarchyBoundaries, + type ApiItemTransformationConfiguration, + type DocumentBoundaries, + type HierarchyBoundaries, } from "./configuration"; /** @@ -459,3 +459,65 @@ function doesItemGenerateHierarchy( ): boolean { return doesItemKindGenerateHierarchy(apiItem.kind, hierarchyBoundaries); } + +/** + * Determines whether or not the specified API item should have documentation generated for it. + * This is determined based on its release tag (or inherited release scope) compared to + * {@link ApiItemTransformationConfiguration.minimumReleaseLevel}. + * + * @remarks + * + * If an item does not have its own release tag, it will inherit its release scope from its nearest ancestor. + * + * Items without an associated release tag (directly or in their ancestry) will always be included as a precaution. + * + * @param apiItem - The API item being queried. + * @param config - See {@link ApiItemTransformationConfiguration}. + * + * @example Hierarchical inheritance + * + * Items with tagged ancestors inherit their release scope when one is not specified. + * This includes class/interface members... + * + * ```typescript + * // @public + * export interface Foo { + * // `@public` inherited from the interface + * bar: string; + * } + * ``` + * + * This also includes scopes like namespaces, which can add further hierarchy... + * + * ```typescript + * // @public + * export namespace Foo { + * // `@public` inherited from the namespace + * export interface Bar { + * // `@public` inherited from the namespace + * baz: string; + * } + * } + * ``` + */ +export function shouldItemBeIncluded( + apiItem: ApiItem, + config: Required, +): boolean { + const releaseTag = getReleaseTag(apiItem); + if (releaseTag === undefined || releaseTag === ReleaseTag.None) { + // If the item does not have a release tag, then it inherits the release scope of its ancestry. + const parent = getFilteredParent(apiItem); + if (parent === undefined) { + // If we encounter an item with no release tag in its ancestry, we can't make a determination as to whether + // or not it is intended to be included in the generated documentation suite. + // To be safe, log a warning but return true. + config.logger.warning("Encountered an API item with no release tag in ancestry."); + return true; + } + + return shouldItemBeIncluded(parent, config); + } + + return releaseTag >= (config.minimumReleaseLevel as ReleaseTag); +} diff --git a/tools/api-markdown-documenter/src/api-item-transforms/TransformApiItem.ts b/tools/api-markdown-documenter/src/api-item-transforms/TransformApiItem.ts index c8118057e2f3..8a0700359db3 100644 --- a/tools/api-markdown-documenter/src/api-item-transforms/TransformApiItem.ts +++ b/tools/api-markdown-documenter/src/api-item-transforms/TransformApiItem.ts @@ -23,7 +23,7 @@ import { } from "@microsoft/api-extractor-model"; import { DocumentNode, SectionNode } from "../documentation-domain"; -import { doesItemRequireOwnDocument } from "./ApiItemTransformUtilities"; +import { doesItemRequireOwnDocument, shouldItemBeIncluded } from "./ApiItemTransformUtilities"; import { createDocument } from "./Utilities"; import { ApiItemTransformationConfiguration } from "./configuration"; import { createBreadcrumbParagraph, wrapInSection } from "./helpers"; @@ -53,7 +53,7 @@ export function apiItemToDocument( config: Required, ): DocumentNode { if (apiItem.kind === ApiItemKind.None) { - throw new Error(`Encountered API item with a kind of "None".`); + throw new Error(`Encountered API item "${apiItem.displayName}" with a kind of "None".`); } if ( @@ -64,6 +64,12 @@ export function apiItemToDocument( throw new Error(`Provided API item kind must be handled specially: "${apiItem.kind}".`); } + if (!shouldItemBeIncluded(apiItem, config)) { + throw new Error( + `Provided API item "${apiItem.displayName}" should not be included in documentation suite per configuration. Cannot generate a document for it.`, + ); + } + if (!doesItemRequireOwnDocument(apiItem, config.documentBoundaries)) { throw new Error( `"renderApiDocument" called for an API item kind that is not intended to be rendered to its own document. Provided item kind: "${apiItem.kind}".`, @@ -105,7 +111,7 @@ export function apiItemToSections( config: Required, ): SectionNode[] { if (apiItem.kind === ApiItemKind.None) { - throw new Error(`Encountered API item with a kind of "None".`); + throw new Error(`Encountered API item "${apiItem.displayName}" with a kind of "None".`); } if ( @@ -116,6 +122,12 @@ export function apiItemToSections( throw new Error(`Provided API item kind must be handled specially: "${apiItem.kind}".`); } + if (!shouldItemBeIncluded(apiItem, config)) { + // If a parent item has requested we render contents for an item not desired by the configuration, + // return an empty set of sections. + return []; + } + const logger = config.logger; logger.verbose(`Rendering section for ${apiItem.displayName}...`); diff --git a/tools/api-markdown-documenter/src/api-item-transforms/TransformApiModel.ts b/tools/api-markdown-documenter/src/api-item-transforms/TransformApiModel.ts index 8ec69514655e..44f2d6258dcb 100644 --- a/tools/api-markdown-documenter/src/api-item-transforms/TransformApiModel.ts +++ b/tools/api-markdown-documenter/src/api-item-transforms/TransformApiModel.ts @@ -10,7 +10,7 @@ import { ApiItemTransformationConfiguration, getApiItemTransformationConfigurationWithDefaults, } from "./configuration"; -import { doesItemRequireOwnDocument } from "./ApiItemTransformUtilities"; +import { doesItemRequireOwnDocument, shouldItemBeIncluded } from "./ApiItemTransformUtilities"; import { createBreadcrumbParagraph, createEntryPointList, wrapInSection } from "./helpers"; import { apiItemToDocument, apiItemToSections } from "./TransformApiItem"; @@ -140,7 +140,10 @@ function getDocumentItems( const result: ApiItem[] = []; for (const childItem of apiItem.members) { - if (doesItemRequireOwnDocument(childItem, documentBoundaries)) { + if ( + shouldItemBeIncluded(childItem, config) && + doesItemRequireOwnDocument(childItem, documentBoundaries) + ) { result.push(childItem); } result.push(...getDocumentItems(childItem, config)); diff --git a/tools/api-markdown-documenter/src/api-item-transforms/configuration/DocumentationSuiteOptions.ts b/tools/api-markdown-documenter/src/api-item-transforms/configuration/DocumentationSuiteOptions.ts index c4aaabee37a2..3db9d4a1a8fb 100644 --- a/tools/api-markdown-documenter/src/api-item-transforms/configuration/DocumentationSuiteOptions.ts +++ b/tools/api-markdown-documenter/src/api-item-transforms/configuration/DocumentationSuiteOptions.ts @@ -209,6 +209,29 @@ export interface DocumentationSuiteOptions { * @defaultValue No front matter is generated. */ frontMatter?: string | ((documentItem: ApiItem) => string | undefined); + + /** + * Minimal release scope to include in generated documentation suite. + * API members with matching or higher scope will be included, while lower scoped items will be omitted. + * + * @remarks + * + * Note that items tagged as `@internal` are not included in the models generated by API-Extractor, + * so `@internal` items will never be included for such models. + * + * Hierarchy: `@public` \> `@beta` \> `@alpha` \> `@internal` + * + * @defaultValue Include everything in the input model. + * + * @example `@beta` and `@public` + * + * To only include `@beta` and `@public` items (and omit `@alpha` items), specify: + * + * ```typescript + * releaseLevel: ReleaseTag.Beta + * ``` + */ + minimumReleaseLevel?: Omit; } /** @@ -359,6 +382,7 @@ const defaultDocumentationSuiteOptions: Required = { getLinkTextForItem: DefaultDocumentationSuiteOptions.defaultGetLinkTextForItem, skipPackage: DefaultDocumentationSuiteOptions.defaultSkipPackage, frontMatter: DefaultDocumentationSuiteOptions.defaultFrontMatter, + minimumReleaseLevel: ReleaseTag.Internal, // Include everything in the input model }; /** diff --git a/tools/api-markdown-documenter/src/test/HtmlEndToEnd.test.ts b/tools/api-markdown-documenter/src/test/HtmlEndToEnd.test.ts index a4103a69e0bb..f0da00ade71f 100644 --- a/tools/api-markdown-documenter/src/test/HtmlEndToEnd.test.ts +++ b/tools/api-markdown-documenter/src/test/HtmlEndToEnd.test.ts @@ -4,7 +4,7 @@ */ import * as Path from "node:path"; -import { ApiItemKind, ApiModel } from "@microsoft/api-extractor-model"; +import { ApiItemKind, ApiModel, ReleaseTag } from "@microsoft/api-extractor-model"; import { FileSystem } from "@rushstack/node-core-library"; import { expect } from "chai"; import { Suite } from "mocha"; @@ -186,6 +186,7 @@ describe("HTML rendering end-to-end tests", () => { hierarchyBoundaries: [], // No additional hierarchy beyond the package level frontMatter: (documentItem): string => ``, + minimumReleaseLevel: ReleaseTag.Beta, // Only include `@public` and `beta` items in the docs suite }, renderConfig: {}, }, @@ -219,6 +220,7 @@ describe("HTML rendering end-to-end tests", () => { ApiItemKind.Variable, ], hierarchyBoundaries: [], // No additional hierarchy beyond the package level + minimumReleaseLevel: ReleaseTag.Public, // Only include `@public` items in the docs suite }, renderConfig: { startingHeadingLevel: 2, diff --git a/tools/api-markdown-documenter/src/test/MarkdownEndToEnd.test.ts b/tools/api-markdown-documenter/src/test/MarkdownEndToEnd.test.ts index f20dd452553d..3b157c61ad1a 100644 --- a/tools/api-markdown-documenter/src/test/MarkdownEndToEnd.test.ts +++ b/tools/api-markdown-documenter/src/test/MarkdownEndToEnd.test.ts @@ -4,7 +4,7 @@ */ import * as Path from "node:path"; -import { ApiItemKind, ApiModel } from "@microsoft/api-extractor-model"; +import { ApiItemKind, ApiModel, ReleaseTag } from "@microsoft/api-extractor-model"; import { FileSystem } from "@rushstack/node-core-library"; import { expect } from "chai"; import { Suite } from "mocha"; @@ -184,6 +184,7 @@ describe("Markdown rendering end-to-end tests", () => { hierarchyBoundaries: [], // No additional hierarchy beyond the package level frontMatter: (documentItem): string => ``, + minimumReleaseLevel: ReleaseTag.Beta, // Only include `@public` and `beta` items in the docs suite }, renderConfig: {}, }, @@ -217,6 +218,7 @@ describe("Markdown rendering end-to-end tests", () => { ApiItemKind.Variable, ], hierarchyBoundaries: [], // No additional hierarchy beyond the package level + minimumReleaseLevel: ReleaseTag.Public, // Only include `@public` items in the docs suite }, renderConfig: { startingHeadingLevel: 2, diff --git a/tools/api-markdown-documenter/src/test/snapshots/html/simple-suite-test/flat-config/simple-suite-test.html b/tools/api-markdown-documenter/src/test/snapshots/html/simple-suite-test/flat-config/simple-suite-test.html index 749ea2fd159a..ae24af3a0668 100644 --- a/tools/api-markdown-documenter/src/test/snapshots/html/simple-suite-test/flat-config/simple-suite-test.html +++ b/tools/api-markdown-documenter/src/test/snapshots/html/simple-suite-test/flat-config/simple-suite-test.html @@ -2578,105 +2578,6 @@

Function Details

-
-

- testFunction (ALPHA) -

-
-

- Test function -

-
-
- WARNING: This API is provided as an alpha preview and may change without notice. Use at your own risk. -
-
-

- Signature -

- - export declare function testFunction<TTypeParameter>(testParameter: TTypeParameter, testOptionalParameter?: TTypeParameter): TTypeParameter; - -
-
-

- Remarks -

-

- This is a test link to another API member -

-
-
-

- Parameters -

- - - - - - - - - - - - - - - - - - - - - - - -
- Parameter - - Modifiers - - Type - - Description -
- testParameter - - - TTypeParameter - - A test parameter -
- testOptionalParameter - - optional - - TTypeParameter - -
-
-
-

- Returns -

-

- The provided parameter -

-

- Return type: TTypeParameter -

-
-
-

- Throws -

-

- An Error when something bad happens. -

-
-

testFunctionReturningInlineType diff --git a/tools/api-markdown-documenter/src/test/snapshots/html/simple-suite-test/sparse-config/simple-suite-test/testconst-variable.html b/tools/api-markdown-documenter/src/test/snapshots/html/simple-suite-test/sparse-config/simple-suite-test/testconst-variable.html deleted file mode 100644 index 910075bda1f1..000000000000 --- a/tools/api-markdown-documenter/src/test/snapshots/html/simple-suite-test/sparse-config/simple-suite-test/testconst-variable.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - -
-

- testConst (BETA) -

-
-

- Test Constant -

-
-
- WARNING: This API is provided as a beta preview and may change without notice. Use at your own risk. -
-
-

- Signature -

- - testConst = 42 - -
-
-

- Remarks -

-

- Here are some remarks about the variable -

-
-
- - diff --git a/tools/api-markdown-documenter/src/test/snapshots/html/simple-suite-test/sparse-config/simple-suite-test/testfunction-function.html b/tools/api-markdown-documenter/src/test/snapshots/html/simple-suite-test/sparse-config/simple-suite-test/testfunction-function.html deleted file mode 100644 index c4a09eb01601..000000000000 --- a/tools/api-markdown-documenter/src/test/snapshots/html/simple-suite-test/sparse-config/simple-suite-test/testfunction-function.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - -
-

- testFunction (ALPHA) -

-
-

- Test function -

-
-
- WARNING: This API is provided as an alpha preview and may change without notice. Use at your own risk. -
-
-

- Signature -

- - export declare function testFunction<TTypeParameter>(testParameter: TTypeParameter, testOptionalParameter?: TTypeParameter): TTypeParameter; - -
-
-

- Remarks -

-

- This is a test link to another API member -

-
-
-

- Parameters -

- - - - - - - - - - - - - - - - - - - - - - - -
- Parameter - - Modifiers - - Type - - Description -
- testParameter - - - TTypeParameter - - A test parameter -
- testOptionalParameter - - optional - - TTypeParameter - -
-
-
-

- Returns -

-

- The provided parameter -

-

- Return type: TTypeParameter -

-
-
-

- Throws -

-

- An Error when something bad happens. -

-
-
- - diff --git a/tools/api-markdown-documenter/src/test/snapshots/markdown/simple-suite-test/flat-config/simple-suite-test.md b/tools/api-markdown-documenter/src/test/snapshots/markdown/simple-suite-test/flat-config/simple-suite-test.md index 4ef01faf5543..bd2010bc00b7 100644 --- a/tools/api-markdown-documenter/src/test/snapshots/markdown/simple-suite-test/flat-config/simple-suite-test.md +++ b/tools/api-markdown-documenter/src/test/snapshots/markdown/simple-suite-test/flat-config/simple-suite-test.md @@ -870,39 +870,6 @@ Here are some remarks about the type alias # Function Details -## testFunction (ALPHA) {#testfunction-function} - -Test function - -**WARNING: This API is provided as an alpha preview and may change without notice. Use at your own risk.** - -### Signature {#testfunction-signature} - -```typescript -export declare function testFunction(testParameter: TTypeParameter, testOptionalParameter?: TTypeParameter): TTypeParameter; -``` - -### Remarks {#testfunction-remarks} - -This is a test [link](docs/simple-suite-test#testinterface-interface) to another API member - -### Parameters {#testfunction-parameters} - -| Parameter | Modifiers | Type | Description | -| --- | --- | --- | --- | -| testParameter | | TTypeParameter | A test parameter | -| testOptionalParameter | optional | TTypeParameter | | - -### Returns {#testfunction-returns} - -The provided parameter - -**Return type:** TTypeParameter - -### Throws {#testfunction-throws} - -An Error when something bad happens. - ## testFunctionReturningInlineType {#testfunctionreturninginlinetype-function} Test function that returns an inline type diff --git a/tools/api-markdown-documenter/src/test/snapshots/markdown/simple-suite-test/sparse-config/simple-suite-test/testconst-variable.md b/tools/api-markdown-documenter/src/test/snapshots/markdown/simple-suite-test/sparse-config/simple-suite-test/testconst-variable.md deleted file mode 100644 index abdf91e233c5..000000000000 --- a/tools/api-markdown-documenter/src/test/snapshots/markdown/simple-suite-test/sparse-config/simple-suite-test/testconst-variable.md +++ /dev/null @@ -1,15 +0,0 @@ -## testConst (BETA) - -Test Constant - -**WARNING: This API is provided as a beta preview and may change without notice. Use at your own risk.** - -### Signature {#testconst-signature} - -```typescript -testConst = 42 -``` - -### Remarks {#testconst-remarks} - -Here are some remarks about the variable diff --git a/tools/api-markdown-documenter/src/test/snapshots/markdown/simple-suite-test/sparse-config/simple-suite-test/testfunction-function.md b/tools/api-markdown-documenter/src/test/snapshots/markdown/simple-suite-test/sparse-config/simple-suite-test/testfunction-function.md deleted file mode 100644 index c081364d0e65..000000000000 --- a/tools/api-markdown-documenter/src/test/snapshots/markdown/simple-suite-test/sparse-config/simple-suite-test/testfunction-function.md +++ /dev/null @@ -1,32 +0,0 @@ -## testFunction (ALPHA) - -Test function - -**WARNING: This API is provided as an alpha preview and may change without notice. Use at your own risk.** - -### Signature {#testfunction-signature} - -```typescript -export declare function testFunction(testParameter: TTypeParameter, testOptionalParameter?: TTypeParameter): TTypeParameter; -``` - -### Remarks {#testfunction-remarks} - -This is a test [link](docs/simple-suite-test/testinterface-interface) to another API member - -### Parameters {#testfunction-parameters} - -| Parameter | Modifiers | Type | Description | -| --- | --- | --- | --- | -| testParameter | | TTypeParameter | A test parameter | -| testOptionalParameter | optional | TTypeParameter | | - -### Returns {#testfunction-returns} - -The provided parameter - -**Return type:** TTypeParameter - -### Throws {#testfunction-throws} - -An Error when something bad happens.