feat(api-markdown-documenter): Add `lintApiModel` API (#22250)

See the documentation updates for more details.
This commit is contained in:
Joshua Smithrud 2024-08-21 11:34:09 -07:00 коммит произвёл GitHub
Родитель ecd60634c3
Коммит d25f328779
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
6 изменённых файлов: 98 добавлений и 20 удалений

Просмотреть файл

@ -5,6 +5,14 @@
- Added the following new utility function to `ApiItemUtilities`:
1. `ancestryHasModifierTag`: Checks if the provided API item or ancestor items are tagged with the specified [modifier tag](https://tsdoc.org/pages/spec/tag_kinds/#modifier-tags).
### Beta
- Adds prototype functionality for "linting" an API Model (i.e., the set of packages whose docs are published as a single "suite").
Can be invoked by importing `lintApiModel` from `@fluid-tools/api-markdown-documenter/beta`.
Returns a set of TSDoc-related "errors" discovered while walking the API Model.
- The primary goal of this tool is to detect issues that `API-Extractor` cannot validate on a per-package basis when generating API reports.
For now, this is limited to validating `@link` and `@inheritDoc` tags to ensure that symbolic references are valid within the API Model.
### ⚠ BREAKING CHANGES
- Updated `loadModel` to take a configuration object, rather than individual parameters.

Просмотреть файл

@ -16,7 +16,7 @@ One may be added in the future, but for now this library is intended to be consu
The following terms are leveraged heavily in this package's APIs and documentation.
- **API Model**: Refers to a complete API suite, comprised of one or more packages.
This often corresponds to all of the packages in the mono-repo, or a series of packages that are published together.
This often corresponds to all of the packages in the mono-repo, or a series of packages whose API docs are published together.
It is generally represented via the [ApiModel][] type, from the [@microsoft/api-extractor-model](https://github.com/microsoft/rushstack/tree/main/libraries/api-extractor-model) library.
- In some places, this library refers to an `API Model` in terms of a directory or directory path.
In these cases, it is referring to a directory that contains the set of `.api.json` files (generated per-package by `API-Extractor`).
@ -203,29 +203,41 @@ If you would like to add rendering support for a custom `Documentation Domain` n
If you would like to change any or all of this library's default rendering policies, you may simply override the default policies for the desired `type`s.
## ToHtml Transformation
This library now includes preview APIs for transforming `Documentation Domain` trees to HTML syntax trees using [hast](https://github.com/syntax-tree/hast).
The main entry-point for this functionality is `documentToHtml`.
## HtmlRenderer
This library now includes preview APIs for HTML rendering.
Like the [MarkdownRenderer](#markdownrenderer), we offer a `HtmlRenderer.renderApiModel` function that operates in much the same way, but outputs `HTML`-formatted documents instead of Markdown.
These APIs are still in preview, and may change without notice.
## Preview APIs
The following APIs are still in preview, and may change without notice.
Use at your own risk.
## ToHtml Transformation
This library now includes preview APIs for transforming `Documentation Domain` trees to HTML syntax trees using [hast](https://github.com/syntax-tree/hast).
To use, import the `documentToHtml` function from `@fluid-tools/api-markdown-documenter/beta`.
### lintApiModel
This library includes a preview API for "linting" an API Model.
To use, import the `lintApiModel` function from `@fluid-tools/api-markdown-documenter/beta`.
This function returns a set of TSDoc-related "errors" discovered while walking the API Model.
The primary goal of this tool is to detect issues that `API-Extractor` cannot validate on a per-package basis when generating API reports.
For now, this is limited to validating `@link` and `@inheritDoc` tags to ensure that symbolic references are valid within the API Model.
Other validation may be added in the future as needed.
## Upcoming Work
- Add extensibility options for `DocNode` transformations
- If a consumer has a custom tsdoc config associated with their API-Extractor setup, this will be needed.
### Known Bugs
- Types that extend or implement types with generic parameters result in signatures rendered with missing closing `>`s.
### Documentation Improvements
- Intro sandbox (api report)
@ -247,8 +259,8 @@ Use at your own risk.
- Support placing documents _within_ their own hierarchy (support for the "index" model used by systems like DocFX)
- Pre-canned policies (flat, index, adjacency)
- Handle multiple package entry-points
- Add separate HTML transformation path, for consumers that want to go straight to HTML
- Add `documentToHtml` API that generates `mdast` output.
- Update rendering APIs to leverage the `mdast` and `hast` domain outputs.
<!-- AUTO-GENERATED-CONTENT:START (README_FOOTER) -->

Просмотреть файл

@ -516,6 +516,28 @@ export class LinkNode extends DocumentationParentNodeBase<SingleLineDocumentatio
readonly type = DocumentationNodeType.Link;
}
// @beta
export function lintApiModel(configuration: LintApiModelConfiguration): Promise<LinterErrors | undefined>;
// @beta
export interface LintApiModelConfiguration extends ConfigurationBase {
apiModel: ApiModel;
}
// @beta
export interface LinterErrors {
readonly referenceErrors: ReadonlySet<LinterReferenceError>;
}
// @beta
export interface LinterReferenceError {
readonly linkText: string | undefined;
readonly packageName: string;
readonly referenceTarget: string;
readonly sourceItem: string;
readonly tagName: string;
}
// @public
export function loadModel(options: LoadModelOptions): Promise<ApiModel>;

Просмотреть файл

@ -488,6 +488,28 @@ export class LinkNode extends DocumentationParentNodeBase<SingleLineDocumentatio
readonly type = DocumentationNodeType.Link;
}
// @beta
export function lintApiModel(configuration: LintApiModelConfiguration): Promise<LinterErrors | undefined>;
// @beta
export interface LintApiModelConfiguration extends ConfigurationBase {
apiModel: ApiModel;
}
// @beta
export interface LinterErrors {
readonly referenceErrors: ReadonlySet<LinterReferenceError>;
}
// @beta
export interface LinterReferenceError {
readonly linkText: string | undefined;
readonly packageName: string;
readonly referenceTarget: string;
readonly sourceItem: string;
readonly tagName: string;
}
// @public
export function loadModel(options: LoadModelOptions): Promise<ApiModel>;

Просмотреть файл

@ -26,6 +26,8 @@ import type { ConfigurationBase } from "./ConfigurationBase.js";
/**
* {@link lintApiModel} configuration.
*
* @beta
*/
export interface LintApiModelConfiguration extends ConfigurationBase {
/**
@ -45,8 +47,10 @@ const defaultLintApiModelConfiguration: Required<Omit<LintApiModelConfiguration,
/**
* An error resulting from a reference tag (e.g., `link` or `inheritDoc` tags) with an invalid target.
*
* @beta
*/
export interface ReferenceError {
export interface LinterReferenceError {
/**
* The tag name with the invalid reference.
*/
@ -58,7 +62,7 @@ export interface ReferenceError {
readonly sourceItem: string;
/**
* The name of the package that the {@link ReferenceError.sourceItem} belongs to.
* The name of the package that the {@link LinterReferenceError.sourceItem} belongs to.
*/
readonly packageName: string;
@ -78,11 +82,13 @@ export interface ReferenceError {
* @remarks Used while walking the API model to accumulate errors, and converted to {@link LinterErrors} to return to the caller.
*/
interface MutableLinterErrors {
readonly referenceErrors: Set<ReferenceError>;
readonly referenceErrors: Set<LinterReferenceError>;
}
/**
* Errors found during linting.
*
* @beta
*/
export interface LinterErrors {
// TODO: malformed tag errors
@ -90,7 +96,7 @@ export interface LinterErrors {
/**
* Errors related to reference tags (e.g., `link` or `inheritDoc` tags) with invalid targets.
*/
readonly referenceErrors: ReadonlySet<ReferenceError>;
readonly referenceErrors: ReadonlySet<LinterReferenceError>;
// TODO: add other error kinds as needed.
}
@ -100,6 +106,8 @@ export interface LinterErrors {
*
* @returns The set of errors encountered during linting, if any were found.
* Otherwise, `undefined`.
*
* @beta
*/
export async function lintApiModel(
configuration: LintApiModelConfiguration,
@ -113,7 +121,7 @@ export async function lintApiModel(
logger.verbose("Linting API model...");
const errors: MutableLinterErrors = {
referenceErrors: new Set<ReferenceError>(),
referenceErrors: new Set<LinterReferenceError>(),
};
lintApiItem(apiModel, apiModel, optionsWithDefaults, errors);
const anyErrors = errors.referenceErrors.size > 0;
@ -291,7 +299,7 @@ function checkLinkTag(
linkTag: DocLinkTag,
apiItem: ApiItem,
apiModel: ApiModel,
): ReferenceError | undefined {
): LinterReferenceError | undefined {
// If the link tag was parsed correctly (which we know it was in this case, because we have a `DocLinkTag`), then we don't have to worry about syntax validation.
// If the link points to some external URL, no-op.
@ -331,7 +339,7 @@ function checkInheritDocTag(
inheritDocTag: DocInheritDocTag,
associatedItem: ApiDocumentedItem,
apiModel: ApiModel,
): ReferenceError | undefined {
): LinterReferenceError | undefined {
if (inheritDocTag?.declarationReference === undefined) {
return undefined;
}

Просмотреть файл

@ -54,6 +54,12 @@ export type { ConfigurationBase } from "./ConfigurationBase.js";
export type { FileSystemConfiguration } from "./FileSystemConfiguration.js";
export type { Heading } from "./Heading.js";
export type { Link, UrlTarget } from "./Link.js";
export {
lintApiModel,
type LintApiModelConfiguration,
type LinterErrors,
type LinterReferenceError,
} from "./LintApiModel.js";
export { loadModel, type LoadModelOptions } from "./LoadModel.js";
export {
defaultConsoleLogger,