@fluentui/api-docs
Advanced tools
+2
-2
| # Change Log - @fluentui/api-docs | ||
| This log was last generated on Mon, 19 Jun 2023 07:34:49 GMT and should not be manually modified. | ||
| This log was last generated on Mon, 19 Jun 2023 07:36:38 GMT and should not be manually modified. | ||
@@ -9,3 +9,3 @@ <!-- Start content --> | ||
| Mon, 19 Jun 2023 07:34:49 GMT | ||
| Mon, 19 Jun 2023 07:36:38 GMT | ||
| [Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/api-docs_v8.2.10..@fluentui/api-docs_v8.2.11) | ||
@@ -12,0 +12,0 @@ |
+1
-1
| { | ||
| "name": "@fluentui/api-docs", | ||
| "version": "8.2.11", | ||
| "version": "8.2.12", | ||
| "description": "Transforms API Extractor .api.json files into .page.json files", | ||
@@ -5,0 +5,0 @@ "repository": { |
| { | ||
| "extends": ["plugin:@fluentui/eslint-plugin/node--legacy"], | ||
| "root": true | ||
| } |
| import * as fse from 'fs-extra'; | ||
| import * as os from 'os'; | ||
| import * as path from 'path'; | ||
| import { ApiModel } from '@microsoft/api-extractor-model'; | ||
| import { IPageJsonOptions } from './types'; | ||
| import { generatePageJson } from './pageJson'; | ||
| const tmpFile = path.join(os.tmpdir(), 'compat.api.json'); | ||
| /** | ||
| * Main entry point to create API \*.page.json files. | ||
| */ | ||
| export function generatePageJsonFiles(options: IPageJsonOptions): void { | ||
| const { pageGroups = {}, fallbackGroup, outputRoot, apiJsonPaths, min } = options; | ||
| // Create and/or empty output folders | ||
| fse.emptyDirSync(outputRoot); | ||
| for (const group of Object.keys(pageGroups)) { | ||
| fse.emptyDirSync(path.join(outputRoot, group)); | ||
| } | ||
| if (fallbackGroup) { | ||
| fse.emptyDirSync(path.join(outputRoot, fallbackGroup)); | ||
| } | ||
| // Load api-extractor output from packages into a model | ||
| const apiModel = new ApiModel(); | ||
| for (const apiJsonPath of apiJsonPaths) { | ||
| // eslint-disable-next-line no-console | ||
| console.log('Loading ' + apiJsonPath); | ||
| // If the file belongs to the compat layer. | ||
| if (apiJsonPath.indexOf('compat') !== -1) { | ||
| // Get the json info and change the package name. | ||
| const jsonObject = require(apiJsonPath); | ||
| jsonObject.name = jsonObject.name + '-compat'; | ||
| // Write the info into a temporary file. | ||
| fse.writeJSONSync(tmpFile, jsonObject); | ||
| // Load the package info into the API model. | ||
| apiModel.loadPackage(tmpFile); | ||
| // Delete the temporary file. | ||
| fse.unlinkSync(tmpFile); | ||
| } else { | ||
| apiModel.loadPackage(apiJsonPath); | ||
| } | ||
| } | ||
| // Generate the page data | ||
| const pageJsonByName = generatePageJson(apiModel, pageGroups, fallbackGroup); | ||
| // Warn if any requested page names didn't correspond to a docCategory found in the API info | ||
| const requestedPages = ([] as string[]).concat(...Object.values(pageGroups)); | ||
| for (const pageName of requestedPages) { | ||
| if (!pageJsonByName.has(pageName)) { | ||
| // eslint-disable-next-line no-console | ||
| console.warn('Warning: no API items found for expected @docCategory ' + pageName); | ||
| } | ||
| } | ||
| // Write the files | ||
| for (const [pageName, pageJson] of pageJsonByName.entries()) { | ||
| const pageJsonPath = path.join(outputRoot, pageJson.group || '', pageName + '.page.json'); | ||
| // eslint-disable-next-line no-console | ||
| console.log('Writing ' + pageJsonPath); | ||
| const json = min ? JSON.stringify(pageJson) : JSON.stringify(pageJson, null, 2); | ||
| fse.writeFileSync(pageJsonPath, json); | ||
| } | ||
| } |
| export * from './types'; | ||
| export { generatePageJsonFiles } from './generatePageJsonFiles'; | ||
| export { generatePageJson } from './pageJson'; |
| import { ApiItem, ApiDocumentedItem, ApiModel, ApiItemKind } from '@microsoft/api-extractor-model'; | ||
| import { findInlineTagByName } from './rendering'; | ||
| import { ICollectedData } from './types-private'; | ||
| import { ITableJson, IPageJson, PageGroups } from './types'; | ||
| import { createTableJson } from './tableJson'; | ||
| const supportedApiItems = [ApiItemKind.Interface, ApiItemKind.Enum, ApiItemKind.Class, ApiItemKind.TypeAlias]; | ||
| /** | ||
| * Given `apiModel` with API package info already loaded into it, generate page data for each | ||
| * `docCategory` tag (page name) and the APIs within it. | ||
| */ | ||
| export function generatePageJson( | ||
| apiModel: ApiModel, | ||
| pageGroups: PageGroups = {}, | ||
| fallbackGroup?: string, | ||
| ): Map<string, IPageJson> { | ||
| const collectedData = initPageData(apiModel, pageGroups, fallbackGroup); | ||
| const result = new Map<string, IPageJson>(); | ||
| for (const [pageName, pageData] of collectedData.pagesByName.entries()) { | ||
| result.set(pageName, { | ||
| tables: pageData.apiItems | ||
| .map((apiItem: ApiItem) => createTableJson(collectedData, apiItem)) | ||
| .filter((table: ITableJson | undefined) => !!table) as ITableJson[], | ||
| name: pageName, | ||
| group: pageData.group, | ||
| }); | ||
| } | ||
| return result; | ||
| } | ||
| /** | ||
| * Walk all the APIs from `apiModel.packages` and generate an empty page data object for each | ||
| * `docCategory` tag (page name) encountered. The returned object contains a mapping from page name | ||
| * (`docCategory`) to page data (`pagesByName`), and from API name to page data (`pagesByApi`). | ||
| * The page data objects referenced in both maps are the same. | ||
| */ | ||
| function initPageData(apiModel: ApiModel, pageGroups: PageGroups, fallbackGroup?: string): ICollectedData { | ||
| // Map the pages to groups all at once for convenience later | ||
| const groupsByPage: { [pageName: string]: string } = {}; | ||
| for (const [group, pageNames] of Object.entries(pageGroups)) { | ||
| for (const pageName of pageNames) { | ||
| groupsByPage[pageName] = group; | ||
| } | ||
| } | ||
| const collectedData: ICollectedData = { apiModel, pagesByName: new Map(), pagesByApi: new Map() }; | ||
| // Generate empty page data objects for each docCategory | ||
| for (const apiPackage of collectedData.apiModel.packages) { | ||
| for (const entryPoint of apiPackage.entryPoints) { | ||
| initPageDataForItem(collectedData, entryPoint, groupsByPage, fallbackGroup); | ||
| } | ||
| } | ||
| return collectedData; | ||
| } | ||
| /** | ||
| * Walk this API item and its members, adding an empty page data object to `collectedData.pagesByName` | ||
| * for each new `docCategory` tag (page name) encountered. Also update `collectedData.pagesByApi` with | ||
| * mappings for every API item encountered. | ||
| */ | ||
| function initPageDataForItem( | ||
| collectedData: ICollectedData, | ||
| apiItem: ApiItem, | ||
| groupsByPage: { [pageName: string]: string }, | ||
| fallbackGroup?: string, | ||
| ): void { | ||
| if ( | ||
| supportedApiItems.includes(apiItem.kind as unknown as ApiItemKind) && | ||
| apiItem instanceof ApiDocumentedItem && | ||
| apiItem.tsdocComment | ||
| ) { | ||
| const docCategoryTag = findInlineTagByName('@docCategory', apiItem.tsdocComment); | ||
| if (docCategoryTag) { | ||
| const pageName = docCategoryTag.tagContent.trim(); | ||
| let pageData = collectedData.pagesByName.get(pageName); | ||
| if (!pageData) { | ||
| pageData = { | ||
| name: pageName, | ||
| apiItems: [], | ||
| group: groupsByPage[pageName] || fallbackGroup, | ||
| }; | ||
| collectedData.pagesByName.set(pageName, pageData); | ||
| } | ||
| collectedData.pagesByApi.set(apiItem.displayName, pageData); | ||
| pageData.apiItems.push(apiItem); | ||
| } | ||
| } | ||
| for (const memberApiItem of apiItem.members) { | ||
| initPageDataForItem(collectedData, memberApiItem, groupsByPage, fallbackGroup); | ||
| } | ||
| } |
-183
| import { | ||
| DocExcerpt, | ||
| DocInlineTag, | ||
| DocSection, | ||
| DocComment, | ||
| DocPlainText, | ||
| DocParagraph, | ||
| DocNode, | ||
| DocNodeTransforms, | ||
| DocLinkTag, | ||
| DocNodeContainer, | ||
| DocCodeSpan, | ||
| DocBlock, | ||
| DocNodeKind, | ||
| } from '@microsoft/tsdoc'; | ||
| import { ApiItem, ApiModel, ExcerptToken, IExcerptTokenRange } from '@microsoft/api-extractor-model'; | ||
| import { ILinkToken } from './types'; | ||
| import { ICollectedData } from './types-private'; | ||
| /** | ||
| * Render nodes from `section` (which is part of `apiItem`) into text. | ||
| */ | ||
| export function renderNodes(apiModel: ApiModel, apiItem: ApiItem, section: DocNodeContainer): string { | ||
| return section.nodes | ||
| .map((node: DocNode) => renderNode(apiModel, apiItem, node)) | ||
| .join('') | ||
| .trim(); | ||
| } | ||
| /** | ||
| * Extracts text from a doc node | ||
| * | ||
| * @param apiModel - Model containing all API info | ||
| * @param apiItem - API item the node came from | ||
| * @param node - Node from which to extract text | ||
| */ | ||
| function renderNode(apiModel: ApiModel, apiItem: ApiItem, node: DocNode): string { | ||
| switch (node.kind) { | ||
| case 'Paragraph': | ||
| const transformedParagraph: DocParagraph = DocNodeTransforms.trimSpacesInParagraph(node as DocParagraph); | ||
| return renderNodes(apiModel, apiItem, transformedParagraph); | ||
| case 'LinkTag': | ||
| return renderLinkTag(apiModel, apiItem, node as DocLinkTag); | ||
| case 'CodeSpan': | ||
| return '`' + (node as DocCodeSpan).code + '`'; | ||
| case 'PlainText': | ||
| return (node as DocPlainText).text; | ||
| case 'SoftBreak': | ||
| return ' '; | ||
| default: | ||
| return ''; | ||
| } | ||
| } | ||
| /** | ||
| * Render a link into text. For now we just extract the text or the code item name | ||
| * (rather than returning an actual link). | ||
| */ | ||
| function renderLinkTag(apiModel: ApiModel, apiItem: ApiItem, link: DocLinkTag): string { | ||
| if (link.linkText) { | ||
| return link.linkText; | ||
| } else if (link.codeDestination) { | ||
| const result = apiModel.resolveDeclarationReference(link.codeDestination, apiItem); | ||
| if (result.resolvedApiItem) { | ||
| return result.resolvedApiItem.getScopedNameWithinPackage(); | ||
| } | ||
| } | ||
| return ''; | ||
| } | ||
| /** | ||
| * Loops through excerpt tokens and returns a token array with hyperlink data. | ||
| * In cases where multiple consecutive original tokens don't contain a link, they will be combined | ||
| * to decrease file size and client processing time. | ||
| * @param collectedData - Used to create links from reference tokens | ||
| * @param excerptTokens - Token list containing the relevant info | ||
| * @param excerptTokenRange - Specific relevant range within `excerptTokens` | ||
| * @param isTypeAlias - If true, remove the "export declare" part from the result and don't make | ||
| * a link from the type name (since it will be a self-link). | ||
| */ | ||
| export function getTokenHyperlinks( | ||
| collectedData: ICollectedData, | ||
| excerptTokens: ReadonlyArray<ExcerptToken>, | ||
| excerptTokenRange: Readonly<IExcerptTokenRange>, | ||
| isTypeAlias?: boolean, | ||
| ): ILinkToken[] { | ||
| const initialTokens = getTokensInRange(excerptTokens, excerptTokenRange).map((token: ExcerptToken) => { | ||
| const result: ILinkToken = { text: token.text }; | ||
| if (token.kind === 'Reference') { | ||
| const page = collectedData.pagesByApi.get(token.text); | ||
| if (page) { | ||
| result.linkedPage = page.name; | ||
| result.linkedPageGroup = page.group; | ||
| } | ||
| } | ||
| return result; | ||
| }); | ||
| const conciseTokens: ILinkToken[] = []; | ||
| for (const token of initialTokens) { | ||
| const prevToken = conciseTokens.slice(-1)[0]; | ||
| if (prevToken && !prevToken.linkedPage && !token.linkedPage) { | ||
| prevToken.text += token.text; | ||
| } else { | ||
| conciseTokens.push(token); | ||
| } | ||
| } | ||
| if (isTypeAlias && conciseTokens.length >= 2) { | ||
| const [firstToken, secondToken] = conciseTokens; | ||
| // The "export declare" part for a type alias (from firstToken) isn't very helpful, | ||
| // and neither is a self-link for the type name (secondToken). Get rid of them. | ||
| if (firstToken.text === 'export declare type ' && secondToken.linkedPage) { | ||
| firstToken.text = firstToken.text.replace('export declare ', '') + secondToken.text; | ||
| conciseTokens.splice(1, 1); | ||
| } | ||
| } | ||
| return conciseTokens; | ||
| } | ||
| /** | ||
| * Renders the doc node (likely a DocComment's DocSection) without the inline tag | ||
| */ | ||
| export function renderDocNodeWithoutInlineTag(docSection?: DocSection): string { | ||
| let result = ''; | ||
| if (docSection) { | ||
| if (docSection.kind === DocNodeKind.InlineTag) { | ||
| return result.trim(); | ||
| } else if (docSection instanceof DocExcerpt) { | ||
| result += docSection.content.toString(); | ||
| } | ||
| for (const childNode of docSection.getChildNodes()) { | ||
| result += renderDocNodeWithoutInlineTag(childNode as DocSection); | ||
| } | ||
| } | ||
| return result; | ||
| } | ||
| /** | ||
| * Finds an inline tag by name from the provided doc comment | ||
| */ | ||
| export function findInlineTagByName(tagName: string, docComment: DocComment): DocInlineTag | undefined { | ||
| if (docComment instanceof DocInlineTag && docComment.tagName === tagName) { | ||
| return docComment; | ||
| } | ||
| for (const childNode of docComment.getChildNodes()) { | ||
| const result: DocInlineTag | undefined = findInlineTagByName(tagName, childNode as DocComment); | ||
| if (result) { | ||
| return result; | ||
| } | ||
| } | ||
| return undefined; | ||
| } | ||
| /** | ||
| * Gets the block tag by name | ||
| */ | ||
| export function getBlockTagByName(tagName: string, docComment: DocComment): DocSection | undefined { | ||
| const tag = docComment.customBlocks.find( | ||
| (customBlock: DocBlock) => customBlock.blockTag.tagName === tagName.toLowerCase(), | ||
| ); | ||
| return tag && tag.content; | ||
| } | ||
| /** | ||
| * Convert a range of tokens to a string. | ||
| */ | ||
| export function renderTokens( | ||
| excerptTokens: ReadonlyArray<ExcerptToken>, | ||
| excerptTokenRange: Readonly<IExcerptTokenRange>, | ||
| ): string { | ||
| return getTokensInRange(excerptTokens, excerptTokenRange) | ||
| .map((token: ExcerptToken) => token.text) | ||
| .join(''); | ||
| } | ||
| function getTokensInRange( | ||
| excerptTokens: ReadonlyArray<ExcerptToken>, | ||
| excerptTokenRange: Readonly<IExcerptTokenRange>, | ||
| ): ReadonlyArray<ExcerptToken> { | ||
| return excerptTokens.slice(excerptTokenRange.startIndex, excerptTokenRange.endIndex); | ||
| } |
-116
| import { | ||
| ApiClass, | ||
| ApiEnum, | ||
| ApiEnumMember, | ||
| ApiInterface, | ||
| ApiTypeAlias, | ||
| ApiDeclaredItem, | ||
| HeritageType, | ||
| ApiItem, | ||
| ApiItemKind, | ||
| } from '@microsoft/api-extractor-model'; | ||
| import { ITableJson, ITableRowJson } from './types'; | ||
| import { renderDocNodeWithoutInlineTag, getTokenHyperlinks, renderNodes } from './rendering'; | ||
| import { ICollectedData } from './types-private'; | ||
| import { createTableRowJson, createEnumTableRowJson } from './tableRowJson'; | ||
| export function createTableJson(collectedData: ICollectedData, apiItem: ApiItem): ITableJson | undefined { | ||
| switch (apiItem.kind as unknown as ApiItemKind) { | ||
| case ApiItemKind.Interface: { | ||
| return createInterfacePageJson(collectedData, apiItem as ApiInterface); | ||
| } | ||
| case ApiItemKind.Enum: { | ||
| return createEnumPageJson(collectedData, apiItem as ApiEnum); | ||
| } | ||
| case ApiItemKind.Class: { | ||
| return createClassPageJson(collectedData, apiItem as ApiClass); | ||
| } | ||
| case ApiItemKind.TypeAlias: { | ||
| return createTypeAliasPageJson(collectedData, apiItem as ApiTypeAlias); | ||
| } | ||
| } | ||
| return undefined; | ||
| } | ||
| /** | ||
| * Generate an ITableJson for a top-level API item (interface, class, enum, type alias) | ||
| * with the name, description, deprecated message, and optionally extends tokens pre-filled. | ||
| */ | ||
| function createBasicTableJson( | ||
| collectedData: ICollectedData, | ||
| apiItem: ApiDeclaredItem, | ||
| kind: ITableJson['kind'], | ||
| extendsTypes?: HeritageType | readonly HeritageType[], | ||
| ): ITableJson { | ||
| const { tsdocComment } = apiItem; | ||
| const tableJson: ITableJson = { | ||
| kind, | ||
| name: apiItem.displayName, | ||
| description: (tsdocComment && renderDocNodeWithoutInlineTag(tsdocComment.summarySection)) || undefined, | ||
| }; | ||
| const extendsArr: HeritageType[] | undefined = | ||
| !extendsTypes || Array.isArray(extendsTypes) ? extendsTypes : [extendsTypes as HeritageType]; | ||
| if (extendsArr && extendsArr.length) { | ||
| tableJson.extendsTokens = []; | ||
| for (const extendsType of extendsArr) { | ||
| if (tableJson.extendsTokens.length) { | ||
| // if there are multiple extends types, we should separate them with a comma | ||
| tableJson.extendsTokens.push({ text: ', ' }); | ||
| } | ||
| tableJson.extendsTokens.push( | ||
| ...getTokenHyperlinks(collectedData, extendsType.excerpt.tokens, extendsType.excerpt.tokenRange), | ||
| ); | ||
| } | ||
| } | ||
| if (tsdocComment && tsdocComment.deprecatedBlock) { | ||
| tableJson.deprecated = true; | ||
| tableJson.deprecatedMessage = renderNodes(collectedData.apiModel, apiItem, tsdocComment.deprecatedBlock.content); | ||
| } | ||
| return tableJson; | ||
| } | ||
| function createInterfacePageJson(collectedData: ICollectedData, interfaceItem: ApiInterface): ITableJson { | ||
| const tableJson = createBasicTableJson(collectedData, interfaceItem, 'interface', interfaceItem.extendsTypes); | ||
| tableJson.members = interfaceItem.members | ||
| .map((member: ApiItem) => createTableRowJson(collectedData, member)) | ||
| .filter((row: ITableRowJson | undefined): row is ITableRowJson => !!row); | ||
| return tableJson; | ||
| } | ||
| function createEnumPageJson(collectedData: ICollectedData, enumItem: ApiEnum): ITableJson { | ||
| const tableJson = createBasicTableJson(collectedData, enumItem, 'enum'); | ||
| tableJson.members = enumItem.members.map((member: ApiEnumMember) => createEnumTableRowJson(collectedData, member)); | ||
| return tableJson; | ||
| } | ||
| function createClassPageJson(collectedData: ICollectedData, classItem: ApiClass): ITableJson { | ||
| const tableJson = createBasicTableJson(collectedData, classItem, 'class', classItem.extendsType); | ||
| tableJson.members = classItem.members | ||
| .map((member: ApiItem) => createTableRowJson(collectedData, member)) | ||
| .filter((row: ITableRowJson | undefined): row is ITableRowJson => !!row) | ||
| // Constructor goes first | ||
| .sort((a: ITableRowJson, b: ITableRowJson) => (a.name === 'constructor' ? -1 : 0)); | ||
| return tableJson; | ||
| } | ||
| function createTypeAliasPageJson(collectedData: ICollectedData, typeAliasItem: ApiTypeAlias): ITableJson { | ||
| const tableJson = createBasicTableJson(collectedData, typeAliasItem, 'typeAlias'); | ||
| tableJson.extendsTokens = getTokenHyperlinks( | ||
| collectedData, | ||
| typeAliasItem.excerptTokens, | ||
| typeAliasItem.excerpt.tokenRange, | ||
| true, | ||
| ); | ||
| return tableJson; | ||
| } |
| import { | ||
| ApiDeclaredItem, | ||
| ExcerptToken, | ||
| IExcerptTokenRange, | ||
| ApiPropertySignature, | ||
| ApiMethodSignature, | ||
| ApiEnumMember, | ||
| ApiItem, | ||
| ApiProperty, | ||
| ApiConstructor, | ||
| ApiMethod, | ||
| ApiItemKind, | ||
| } from '@microsoft/api-extractor-model'; | ||
| import { ICollectedData } from './types-private'; | ||
| import { ITableRowJson, IEnumTableRowJson } from './types'; | ||
| import { | ||
| renderDocNodeWithoutInlineTag, | ||
| getBlockTagByName, | ||
| renderNodes, | ||
| getTokenHyperlinks, | ||
| renderTokens, | ||
| } from './rendering'; | ||
| export function createTableRowJson(collectedData: ICollectedData, apiItem: ApiItem): ITableRowJson | undefined { | ||
| let tableRowJson: ITableRowJson | undefined; | ||
| const apiKind = apiItem.kind as unknown as ApiItemKind; | ||
| switch (apiKind) { | ||
| case ApiItemKind.Property: | ||
| case ApiItemKind.PropertySignature: { | ||
| const apiProperty = apiItem as ApiPropertySignature | ApiProperty; | ||
| tableRowJson = createBasicTableRowJson( | ||
| collectedData, | ||
| apiProperty, | ||
| 'property', | ||
| apiProperty.excerptTokens, | ||
| apiProperty.propertyTypeExcerpt.tokenRange, | ||
| ); | ||
| break; | ||
| } | ||
| case ApiItemKind.Constructor: | ||
| case ApiItemKind.Method: | ||
| case ApiItemKind.MethodSignature: { | ||
| const apiMethod = apiItem as ApiMethod | ApiMethodSignature | ApiConstructor; | ||
| tableRowJson = createBasicTableRowJson( | ||
| collectedData, | ||
| apiMethod, | ||
| 'method', | ||
| apiMethod.excerptTokens, | ||
| apiMethod.excerpt.tokenRange, | ||
| ); | ||
| if ((apiMethod.kind as unknown as ApiItemKind) === ApiItemKind.Constructor) { | ||
| // The constructor is similar to a method, but we have to manually add the name. | ||
| tableRowJson.name = 'constructor'; | ||
| } | ||
| break; | ||
| } | ||
| case ApiItemKind.Function: | ||
| break; | ||
| case ApiItemKind.Class: | ||
| break; | ||
| } | ||
| // For property or method signatures, check if it's required based on the text of the declaration | ||
| // (item.excerpt.text). It's required if there's no ? after the name. | ||
| if ( | ||
| tableRowJson && | ||
| (apiKind === ApiItemKind.PropertySignature || apiKind === ApiItemKind.MethodSignature) && | ||
| /^\w+[:(]/.test((apiItem as ApiDeclaredItem).excerpt.text) | ||
| ) { | ||
| tableRowJson.required = true; | ||
| } | ||
| return tableRowJson; | ||
| } | ||
| export function createEnumTableRowJson( | ||
| collectedData: ICollectedData, | ||
| apiItem: ApiDeclaredItem & { name?: string }, | ||
| ): IEnumTableRowJson { | ||
| const apiEnumMember = apiItem as ApiEnumMember; | ||
| const { name, description, deprecated, deprecatedMessage } = createBasicTableRowJson(collectedData, apiEnumMember); | ||
| return { | ||
| name, | ||
| description, | ||
| deprecated, | ||
| deprecatedMessage, | ||
| value: renderTokens(apiEnumMember.excerptTokens, apiEnumMember.excerpt.tokenRange), | ||
| }; | ||
| } | ||
| /** | ||
| * Generate an ITableRowJson for a class/interface/enum member with the name, description, | ||
| * deprecated message, default value, and (optionally) type tokens pre-filled. | ||
| * @param typeTokens - Optional list of tokens which includes the item type info. | ||
| * @param typeTokenRange - Specific location of the item type within `typeTokens`. | ||
| */ | ||
| function createBasicTableRowJson( | ||
| collectedData: ICollectedData, | ||
| apiItem: ApiDeclaredItem & { name?: string }, | ||
| kind?: ITableRowJson['kind'], | ||
| typeTokens?: readonly ExcerptToken[], | ||
| typeTokenRange?: Readonly<IExcerptTokenRange>, | ||
| ): ITableRowJson { | ||
| const { tsdocComment } = apiItem; | ||
| const tableRowJson: ITableRowJson = { | ||
| name: apiItem.name || '', | ||
| typeTokens: [], | ||
| kind, | ||
| description: (tsdocComment && renderDocNodeWithoutInlineTag(tsdocComment.summarySection)) || undefined, | ||
| }; | ||
| if (tsdocComment) { | ||
| const defaultValue = | ||
| getBlockTagByName('@defaultValue', tsdocComment) || | ||
| getBlockTagByName('@defaultvalue', tsdocComment) || | ||
| getBlockTagByName('@default', tsdocComment); | ||
| if (defaultValue) { | ||
| tableRowJson.defaultValue = renderNodes(collectedData.apiModel, apiItem, defaultValue); | ||
| } | ||
| if (tsdocComment.deprecatedBlock) { | ||
| tableRowJson.deprecated = true; | ||
| tableRowJson.deprecatedMessage = renderNodes( | ||
| collectedData.apiModel, | ||
| apiItem, | ||
| tsdocComment.deprecatedBlock.content, | ||
| ); | ||
| } | ||
| } | ||
| if (typeTokens && typeTokenRange) { | ||
| tableRowJson.typeTokens = getTokenHyperlinks(collectedData, typeTokens, typeTokenRange); | ||
| } | ||
| return tableRowJson; | ||
| } |
| import { ApiItem, ApiModel } from '@microsoft/api-extractor-model'; | ||
| /** | ||
| * A page and its associated API items. | ||
| */ | ||
| export interface IPageData { | ||
| /** The name (`@docCategory` tag value) of the page */ | ||
| readonly name: string; | ||
| readonly apiItems: ApiItem[]; | ||
| readonly group?: string; | ||
| } | ||
| export interface ICollectedData { | ||
| // readonly pageGroups: readonly string[]; | ||
| // readonly fallbackGroup: string; | ||
| readonly apiModel: ApiModel; | ||
| /** | ||
| * Page data keyed by page name (`@docCategory` tag value). | ||
| * Entries in this object are unique. | ||
| */ | ||
| readonly pagesByName: Map<string, IPageData>; | ||
| /** | ||
| * `pagesByName` re-keyed by API name for lookup convenience. | ||
| * Entries are the same objects from `pagesByName`, but each page may appear multiple times. | ||
| */ | ||
| readonly pagesByApi: Map<string, IPageData>; | ||
| } |
-95
| /** | ||
| * Options that define the information necessary to find the api.json file | ||
| * and create individual page json files out of it | ||
| */ | ||
| export interface IPageJsonOptions { | ||
| /** Input files generated by api-extractor (one per package) */ | ||
| apiJsonPaths: string[]; | ||
| /** Output \*.page.json folder path. Page groups (if used) will go in subfolders. */ | ||
| outputRoot: string; | ||
| /** If true, the generated files won't be pretty-formatted */ | ||
| min?: boolean; | ||
| /** | ||
| * List of allowed page names (`@docCategory` tag values) grouped by any desired criteria, | ||
| * such as package name. | ||
| */ | ||
| pageGroups?: PageGroups; | ||
| /** | ||
| * Group for any page names (`@docCategory` tag values) not listed in `pageGroups`. | ||
| * If unspecified, unlisted pages will go under the root. | ||
| */ | ||
| fallbackGroup?: string; | ||
| } | ||
| /** Map from group name to page names */ | ||
| export type PageGroups = { [groupName: string]: string[] }; | ||
| /** | ||
| * Structure of the page.json files | ||
| */ | ||
| export interface IPageJson { | ||
| tables: ITableJson[]; | ||
| name: string; | ||
| group?: string; | ||
| } | ||
| export type ApiKind = 'interface' | 'enum' | 'class' | 'typeAlias'; | ||
| /** | ||
| * Info for a table representing a top-level API item: interface, enum, class, or type alias. | ||
| */ | ||
| export interface ITableJson { | ||
| kind: ApiKind; | ||
| name: string; | ||
| description?: string; | ||
| /** | ||
| * Any types the item extends, translated to an array of text elements and links to other types. | ||
| * For classes and interfaces only. | ||
| * | ||
| * Example: `Readonly<IFoo>` might translate to: | ||
| * `[{ text: 'Readonly<' }, { text: 'IFoo', linkedPage: 'Foo', linkedPageGroup: 'components' }, { text: '>' }]` | ||
| */ | ||
| extendsTokens?: ILinkToken[]; | ||
| members?: ITableRowJson[] | IEnumTableRowJson[]; | ||
| deprecated?: boolean; | ||
| deprecatedMessage?: string; | ||
| } | ||
| /** | ||
| * Generic row for API reference tables. | ||
| * It can represent a member (property or method) of an interface or class. | ||
| */ | ||
| export interface ITableRowJson { | ||
| name: string; | ||
| kind?: 'method' | 'property'; | ||
| /** | ||
| * The row's type translated to an array of text elements and links to other types. | ||
| * For example, `Readonly<IFoo>` might translate to: | ||
| * `[{ text: 'Readonly<' }, { text: 'IFoo', linkedPage: 'Foo', linkedPageGroup: 'components' }, { text: '>' }]` | ||
| */ | ||
| typeTokens: ILinkToken[]; | ||
| defaultValue?: string; | ||
| description?: string; | ||
| deprecated?: boolean; | ||
| deprecatedMessage?: string; | ||
| required?: boolean; | ||
| } | ||
| /** | ||
| * Enum member row for API reference tables. | ||
| */ | ||
| export type IEnumTableRowJson = Omit<ITableRowJson, 'kind' | 'typeTokens' | 'defaultValue' | 'required'> & { | ||
| value: string; | ||
| }; | ||
| /** | ||
| * Text excerpt token that is part of a type definition or extends block and may have a link | ||
| * to another doc page. | ||
| */ | ||
| export interface ILinkToken { | ||
| text: string; | ||
| /** If this token is a link, name of the doc page it points to */ | ||
| linkedPage?: string; | ||
| /** If this token is a link, group/category of the doc page it points to */ | ||
| linkedPageGroup?: string; | ||
| } |
| { | ||
| "compilerOptions": { | ||
| "baseUrl": ".", | ||
| "outDir": "dist", | ||
| "target": "es5", | ||
| "module": "commonjs", | ||
| "jsx": "react", | ||
| "declaration": true, | ||
| "sourceMap": true, | ||
| "experimentalDecorators": true, | ||
| "importHelpers": true, | ||
| "noUnusedLocals": true, | ||
| "forceConsistentCasingInFileNames": true, | ||
| "strictNullChecks": true, | ||
| "noImplicitAny": true, | ||
| "noImplicitThis": true, | ||
| "skipLibCheck": true, | ||
| "moduleResolution": "node", | ||
| "preserveConstEnums": true, | ||
| "downlevelIteration": true, | ||
| "lib": ["es2017"], | ||
| "types": [], | ||
| "isolatedModules": true | ||
| }, | ||
| "include": ["src"] | ||
| } |
Sorry, the diff of this file is too big to display
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
3
-50%219405
-10.16%30
-25%3525
-16.05%