This commit is contained in:
2024-02-07 01:33:07 -05:00
commit c1af19d441
4088 changed files with 1260170 additions and 0 deletions

View File

@ -0,0 +1,216 @@
import { TSDocTagDefinition, TSDocConfiguration, ParserMessageLog, ITSDocTagDefinitionParameters } from '@microsoft/tsdoc';
/**
* Represents an individual `tsdoc.json` file.
*
* @public
*/
export declare class TSDocConfigFile {
static readonly FILENAME: string;
static readonly CURRENT_SCHEMA_URL: string;
/**
* A queryable log that reports warnings and error messages that occurred during parsing.
*/
readonly log: ParserMessageLog;
private readonly _extendsFiles;
private _filePath;
private _fileNotFound;
private _fileMTime;
private _hasErrors;
private _tsdocSchema;
private readonly _extendsPaths;
private _noStandardTags;
private readonly _tagDefinitions;
private readonly _tagDefinitionNames;
private readonly _supportForTags;
private _supportedHtmlElements;
private _reportUnsupportedHtmlElements;
private constructor();
/**
* Other config files that this file extends from.
*/
get extendsFiles(): ReadonlyArray<TSDocConfigFile>;
/**
* The full path of the file that was attempted to load, or an empty string if the configuration was
* loaded from a source that is not a file.
*/
get filePath(): string;
/**
* If true, then the TSDocConfigFile object contains an empty state, because the `tsdoc.json` file
* was not found by the loader.
*
* @remarks
* A missing "tsdoc.json" file is not considered an error. It simply means that the defaults will be used.
*/
get fileNotFound(): boolean;
/**
* If true, then at least one error was encountered while loading this file or one of its "extends" files.
*
* @remarks
* You can use {@link TSDocConfigFile.getErrorSummary} to report these errors.
*
* The individual messages can be retrieved from the {@link TSDocConfigFile.log} property of each `TSDocConfigFile`
* object (including the {@link TSDocConfigFile.extendsFiles} tree).
*/
get hasErrors(): boolean;
/**
* The `$schema` field from the `tsdoc.json` file.
*/
get tsdocSchema(): string;
/**
* The `extends` field from the `tsdoc.json` file. For the parsed file contents,
* use the `extendsFiles` property instead.
*/
get extendsPaths(): ReadonlyArray<string>;
/**
* By default, the config file loader will predefine all of the standardized TSDoc tags. To disable this and
* start with a completely empty configuration, set `noStandardTags` to true.
*
* @remarks
* If a config file uses `"extends"` to include settings from base config files, then its setting will
* override any settings from the base config files. If `"noStandardTags"` is not specified, then this
* property will be `undefined`. The config files are applied in the order they are processed (a depth-first
* traversal of the `"extends"` references), and files processed later can override earlier files.
* If no config file specifies `noStandardTags` then the default value is `false`.
*/
get noStandardTags(): boolean | undefined;
set noStandardTags(value: boolean | undefined);
get tagDefinitions(): ReadonlyArray<TSDocTagDefinition>;
get supportForTags(): ReadonlyMap<string, boolean>;
get supportedHtmlElements(): ReadonlyArray<string> | undefined;
get reportUnsupportedHtmlElements(): boolean | undefined;
set reportUnsupportedHtmlElements(value: boolean | undefined);
/**
* Removes all items from the `tagDefinitions` array.
*/
clearTagDefinitions(): void;
/**
* Adds a new item to the `tagDefinitions` array.
*/
addTagDefinition(parameters: ITSDocTagDefinitionParameters): void;
private _addTagDefinitionForLoad;
/**
* Adds a new item to the `supportedHtmlElements` array.
*/
addSupportedHtmlElement(htmlElement: string): void;
/**
* Removes the explicit list of allowed html elements.
*/
clearSupportedHtmlElements(): void;
/**
* Removes all entries from the "supportForTags" map.
*/
clearSupportForTags(): void;
/**
* Sets an entry in the "supportForTags" map.
*/
setSupportForTag(tagName: string, supported: boolean): void;
/**
* This can be used for cache eviction. It returns true if the modification timestamp has changed for
* any of the files that were read when loading this `TSDocConfigFile`, which indicates that the file should be
* reloaded. It does not consider cases where `TSDocConfigFile.fileNotFound` was `true`.
*
* @remarks
* This can be used for cache eviction. An example eviction strategy might be like this:
*
* - call `checkForModifiedFiles()` once per second, and reload the configuration if it returns true
*
* - otherwise, reload the configuration when it is more than 10 seconds old (to handle less common cases such
* as creation of a missing file, or creation of a file at an earlier location in the search path).
*/
checkForModifiedFiles(): boolean;
/**
* Checks the last modification time for `TSDocConfigFile.filePath` and returns `true` if it has changed
* since the file was loaded. If the file is missing, this returns `false`. If the timestamp cannot be read,
* then this returns `true`.
*/
private _checkForModifiedFile;
private _reportError;
private _loadJsonObject;
private _loadWithExtends;
/**
* For the given folder, look for the relevant tsdoc.json file (if any), and return its path.
*
* @param folderPath - the path to a folder where the search should start
* @returns the (possibly relative) path to tsdoc.json, or an empty string if not found
*/
static findConfigPathForFolder(folderPath: string): string;
/**
* Calls `TSDocConfigFile.findConfigPathForFolder()` to find the relevant tsdoc.json config file, if one exists.
* Then calls `TSDocConfigFile.findConfigPathForFolder()` to return the loaded result.
*
* @remarks
* This API does not report loading errors by throwing exceptions. Instead, the caller is expected to check
* for errors using {@link TSDocConfigFile.hasErrors}, {@link TSDocConfigFile.log},
* or {@link TSDocConfigFile.getErrorSummary}.
*
* @param folderPath - the path to a folder where the search should start
*/
static loadForFolder(folderPath: string): TSDocConfigFile;
/**
* Loads the specified tsdoc.json and any base files that it refers to using the "extends" option.
*
* @remarks
* This API does not report loading errors by throwing exceptions. Instead, the caller is expected to check
* for errors using {@link TSDocConfigFile.hasErrors}, {@link TSDocConfigFile.log},
* or {@link TSDocConfigFile.getErrorSummary}.
*
* @param tsdocJsonFilePath - the path to the tsdoc.json config file
*/
static loadFile(tsdocJsonFilePath: string): TSDocConfigFile;
/**
* Loads the object state from a JSON-serializable object as produced by {@link TSDocConfigFile.saveToObject}.
*
* @remarks
* The serialized object has the same structure as `tsdoc.json`; however the `"extends"` field is not allowed.
*
* This API does not report loading errors by throwing exceptions. Instead, the caller is expected to check
* for errors using {@link TSDocConfigFile.hasErrors}, {@link TSDocConfigFile.log},
* or {@link TSDocConfigFile.getErrorSummary}.
*/
static loadFromObject(jsonObject: unknown): TSDocConfigFile;
/**
* Initializes a TSDocConfigFile object using the state from the provided `TSDocConfiguration` object.
*
* @remarks
* This API does not report loading errors by throwing exceptions. Instead, the caller is expected to check
* for errors using {@link TSDocConfigFile.hasErrors}, {@link TSDocConfigFile.log},
* or {@link TSDocConfigFile.getErrorSummary}.
*/
static loadFromParser(configuration: TSDocConfiguration): TSDocConfigFile;
/**
* Writes the config file content to a JSON file with the specified file path.
*/
saveFile(jsonFilePath: string): void;
/**
* Writes the object state into a JSON-serializable object.
*/
saveToObject(): unknown;
private static _serializeTagDefinition;
/**
* Returns a report of any errors that occurred while attempting to load this file or any files
* referenced via the "extends" field.
*
* @remarks
* Use {@link TSDocConfigFile.hasErrors} to determine whether any errors occurred.
*/
getErrorSummary(): string;
/**
* Applies the settings from this config file to a TSDoc parser configuration.
* Any `extendsFile` settings will also applied.
*
* @remarks
* Additional validation is performed during this operation. The caller is expected to check for errors
* using {@link TSDocConfigFile.hasErrors}, {@link TSDocConfigFile.log}, or {@link TSDocConfigFile.getErrorSummary}.
*/
configureParser(configuration: TSDocConfiguration): void;
/**
* This is the same as {@link configureParser}, but it preserves any previous state.
*
* @remarks
* Additional validation is performed during this operation. The caller is expected to check for errors
* using {@link TSDocConfigFile.hasErrors}, {@link TSDocConfigFile.log}, or {@link TSDocConfigFile.getErrorSummary}.
*/
updateParser(configuration: TSDocConfiguration): void;
private _getNoStandardTagsWithExtends;
}
//# sourceMappingURL=TSDocConfigFile.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"TSDocConfigFile.d.ts","sourceRoot":"","sources":["../src/TSDocConfigFile.ts"],"names":[],"mappings":"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"}

View File

@ -0,0 +1,683 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TSDocConfigFile = void 0;
const tsdoc_1 = require("@microsoft/tsdoc");
const fs = __importStar(require("fs"));
const resolve = __importStar(require("resolve"));
const path = __importStar(require("path"));
const ajv_1 = __importDefault(require("ajv"));
const jju = __importStar(require("jju"));
const ajv = new ajv_1.default({ verbose: true });
function initializeSchemaValidator() {
const jsonSchemaPath = resolve.sync('@microsoft/tsdoc/schemas/tsdoc.schema.json', { basedir: __dirname });
const jsonSchemaContent = fs.readFileSync(jsonSchemaPath).toString();
const jsonSchema = jju.parse(jsonSchemaContent, { mode: 'cjson' });
return ajv.compile(jsonSchema);
}
// Warning: AJV has a fairly strange API. Each time this function is called, the function object's
// properties get overwritten with the results of the latest validation. Thus we need to be careful
// to read the properties before a subsequent call may occur.
const tsdocSchemaValidator = initializeSchemaValidator();
/**
* Represents an individual `tsdoc.json` file.
*
* @public
*/
class TSDocConfigFile {
constructor() {
this.log = new tsdoc_1.ParserMessageLog();
this._extendsFiles = [];
this._filePath = '';
this._fileNotFound = false;
this._hasErrors = false;
this._fileMTime = 0;
this._tsdocSchema = '';
this._extendsPaths = [];
this._noStandardTags = undefined;
this._tagDefinitions = [];
this._tagDefinitionNames = new Set();
this._supportForTags = new Map();
}
/**
* Other config files that this file extends from.
*/
get extendsFiles() {
return this._extendsFiles;
}
/**
* The full path of the file that was attempted to load, or an empty string if the configuration was
* loaded from a source that is not a file.
*/
get filePath() {
return this._filePath;
}
/**
* If true, then the TSDocConfigFile object contains an empty state, because the `tsdoc.json` file
* was not found by the loader.
*
* @remarks
* A missing "tsdoc.json" file is not considered an error. It simply means that the defaults will be used.
*/
get fileNotFound() {
return this._fileNotFound;
}
/**
* If true, then at least one error was encountered while loading this file or one of its "extends" files.
*
* @remarks
* You can use {@link TSDocConfigFile.getErrorSummary} to report these errors.
*
* The individual messages can be retrieved from the {@link TSDocConfigFile.log} property of each `TSDocConfigFile`
* object (including the {@link TSDocConfigFile.extendsFiles} tree).
*/
get hasErrors() {
return this._hasErrors;
}
/**
* The `$schema` field from the `tsdoc.json` file.
*/
get tsdocSchema() {
return this._tsdocSchema;
}
/**
* The `extends` field from the `tsdoc.json` file. For the parsed file contents,
* use the `extendsFiles` property instead.
*/
get extendsPaths() {
return this._extendsPaths;
}
/**
* By default, the config file loader will predefine all of the standardized TSDoc tags. To disable this and
* start with a completely empty configuration, set `noStandardTags` to true.
*
* @remarks
* If a config file uses `"extends"` to include settings from base config files, then its setting will
* override any settings from the base config files. If `"noStandardTags"` is not specified, then this
* property will be `undefined`. The config files are applied in the order they are processed (a depth-first
* traversal of the `"extends"` references), and files processed later can override earlier files.
* If no config file specifies `noStandardTags` then the default value is `false`.
*/
get noStandardTags() {
return this._noStandardTags;
}
set noStandardTags(value) {
this._noStandardTags = value;
}
get tagDefinitions() {
return this._tagDefinitions;
}
get supportForTags() {
return this._supportForTags;
}
get supportedHtmlElements() {
return this._supportedHtmlElements && Array.from(this._supportedHtmlElements);
}
get reportUnsupportedHtmlElements() {
return this._reportUnsupportedHtmlElements;
}
set reportUnsupportedHtmlElements(value) {
this._reportUnsupportedHtmlElements = value;
}
/**
* Removes all items from the `tagDefinitions` array.
*/
clearTagDefinitions() {
this._tagDefinitions.length = 0;
this._tagDefinitionNames.clear();
}
/**
* Adds a new item to the `tagDefinitions` array.
*/
addTagDefinition(parameters) {
// This validates the tag name
const tagDefinition = new tsdoc_1.TSDocTagDefinition(parameters);
if (this._tagDefinitionNames.has(tagDefinition.tagNameWithUpperCase)) {
throw new Error(`A tag definition was already added with the tag name "${parameters.tagName}"`);
}
this._tagDefinitionNames.add(tagDefinition.tagName);
this._tagDefinitions.push(tagDefinition);
}
// Similar to addTagDefinition() but reports errors using _reportError()
_addTagDefinitionForLoad(parameters) {
let tagDefinition;
try {
// This validates the tag name
tagDefinition = new tsdoc_1.TSDocTagDefinition(parameters);
}
catch (error) {
this._reportError({
messageId: tsdoc_1.TSDocMessageId.ConfigFileInvalidTagName,
messageText: error.message,
textRange: tsdoc_1.TextRange.empty,
});
return;
}
if (this._tagDefinitionNames.has(tagDefinition.tagNameWithUpperCase)) {
this._reportError({
messageId: tsdoc_1.TSDocMessageId.ConfigFileDuplicateTagName,
messageText: `The "tagDefinitions" field specifies more than one tag with the name "${parameters.tagName}"`,
textRange: tsdoc_1.TextRange.empty,
});
}
this._tagDefinitionNames.add(tagDefinition.tagNameWithUpperCase);
this._tagDefinitions.push(tagDefinition);
}
/**
* Adds a new item to the `supportedHtmlElements` array.
*/
addSupportedHtmlElement(htmlElement) {
if (!this._supportedHtmlElements) {
this._supportedHtmlElements = new Set();
}
this._supportedHtmlElements.add(htmlElement);
}
/**
* Removes the explicit list of allowed html elements.
*/
clearSupportedHtmlElements() {
this._supportedHtmlElements = undefined;
}
/**
* Removes all entries from the "supportForTags" map.
*/
clearSupportForTags() {
this._supportForTags.clear();
}
/**
* Sets an entry in the "supportForTags" map.
*/
setSupportForTag(tagName, supported) {
tsdoc_1.TSDocTagDefinition.validateTSDocTagName(tagName);
this._supportForTags.set(tagName, supported);
}
/**
* This can be used for cache eviction. It returns true if the modification timestamp has changed for
* any of the files that were read when loading this `TSDocConfigFile`, which indicates that the file should be
* reloaded. It does not consider cases where `TSDocConfigFile.fileNotFound` was `true`.
*
* @remarks
* This can be used for cache eviction. An example eviction strategy might be like this:
*
* - call `checkForModifiedFiles()` once per second, and reload the configuration if it returns true
*
* - otherwise, reload the configuration when it is more than 10 seconds old (to handle less common cases such
* as creation of a missing file, or creation of a file at an earlier location in the search path).
*/
checkForModifiedFiles() {
if (this._checkForModifiedFile()) {
return true;
}
for (const extendsFile of this.extendsFiles) {
if (extendsFile.checkForModifiedFiles()) {
return true;
}
}
return false;
}
/**
* Checks the last modification time for `TSDocConfigFile.filePath` and returns `true` if it has changed
* since the file was loaded. If the file is missing, this returns `false`. If the timestamp cannot be read,
* then this returns `true`.
*/
_checkForModifiedFile() {
if (this._fileNotFound || !this._filePath) {
return false;
}
try {
const mtimeMs = fs.statSync(this._filePath).mtimeMs;
return mtimeMs !== this._fileMTime;
}
catch (error) {
return true;
}
}
_reportError(parserMessageParameters) {
this.log.addMessage(new tsdoc_1.ParserMessage(parserMessageParameters));
this._hasErrors = true;
}
_loadJsonObject(configJson) {
if (configJson.$schema !== TSDocConfigFile.CURRENT_SCHEMA_URL) {
this._reportError({
messageId: tsdoc_1.TSDocMessageId.ConfigFileUnsupportedSchema,
messageText: `Unsupported JSON "$schema" value; expecting "${TSDocConfigFile.CURRENT_SCHEMA_URL}"`,
textRange: tsdoc_1.TextRange.empty,
});
return;
}
const success = tsdocSchemaValidator(configJson);
if (!success) {
const description = ajv.errorsText(tsdocSchemaValidator.errors);
this._reportError({
messageId: tsdoc_1.TSDocMessageId.ConfigFileSchemaError,
messageText: 'Error loading config file: ' + description,
textRange: tsdoc_1.TextRange.empty,
});
return;
}
this._tsdocSchema = configJson.$schema;
if (configJson.extends) {
this._extendsPaths.push(...configJson.extends);
}
this.noStandardTags = configJson.noStandardTags;
for (const jsonTagDefinition of configJson.tagDefinitions || []) {
let syntaxKind;
switch (jsonTagDefinition.syntaxKind) {
case 'inline':
syntaxKind = tsdoc_1.TSDocTagSyntaxKind.InlineTag;
break;
case 'block':
syntaxKind = tsdoc_1.TSDocTagSyntaxKind.BlockTag;
break;
case 'modifier':
syntaxKind = tsdoc_1.TSDocTagSyntaxKind.ModifierTag;
break;
default:
// The JSON schema should have caught this error
throw new Error('Unexpected tag kind');
}
this._addTagDefinitionForLoad({
tagName: jsonTagDefinition.tagName,
syntaxKind: syntaxKind,
allowMultiple: jsonTagDefinition.allowMultiple,
});
}
if (configJson.supportedHtmlElements) {
this._supportedHtmlElements = new Set();
for (const htmlElement of configJson.supportedHtmlElements) {
this.addSupportedHtmlElement(htmlElement);
}
}
this._reportUnsupportedHtmlElements = configJson.reportUnsupportedHtmlElements;
if (configJson.supportForTags) {
for (const tagName of Object.keys(configJson.supportForTags)) {
const supported = configJson.supportForTags[tagName];
this._supportForTags.set(tagName, supported);
}
}
}
_loadWithExtends(configFilePath, referencingConfigFile, alreadyVisitedPaths) {
// In case an exception is thrown, start by assuming that the file was not found; we'll revise
// this later upon success
this._fileNotFound = true;
if (!configFilePath) {
this._reportError({
messageId: tsdoc_1.TSDocMessageId.ConfigFileNotFound,
messageText: 'File not found',
textRange: tsdoc_1.TextRange.empty,
});
return;
}
this._filePath = path.resolve(configFilePath);
if (!fs.existsSync(this._filePath)) {
this._reportError({
messageId: tsdoc_1.TSDocMessageId.ConfigFileNotFound,
messageText: 'File not found',
textRange: tsdoc_1.TextRange.empty,
});
return;
}
const configJsonContent = fs.readFileSync(this._filePath).toString();
this._fileMTime = fs.statSync(this._filePath).mtimeMs;
this._fileNotFound = false;
const hashKey = fs.realpathSync(this._filePath);
if (referencingConfigFile && alreadyVisitedPaths.has(hashKey)) {
this._reportError({
messageId: tsdoc_1.TSDocMessageId.ConfigFileCyclicExtends,
messageText: `Circular reference encountered for "extends" field of "${referencingConfigFile.filePath}"`,
textRange: tsdoc_1.TextRange.empty,
});
return;
}
alreadyVisitedPaths.add(hashKey);
let configJson;
try {
configJson = jju.parse(configJsonContent, { mode: 'cjson' });
}
catch (e) {
this._reportError({
messageId: tsdoc_1.TSDocMessageId.ConfigInvalidJson,
messageText: 'Error parsing JSON input: ' + e.message,
textRange: tsdoc_1.TextRange.empty,
});
return;
}
this._loadJsonObject(configJson);
const configFileFolder = path.dirname(this.filePath);
for (const extendsField of this.extendsPaths) {
let resolvedExtendsPath;
try {
resolvedExtendsPath = resolve.sync(extendsField, { basedir: configFileFolder });
}
catch (e) {
this._reportError({
messageId: tsdoc_1.TSDocMessageId.ConfigFileUnresolvedExtends,
messageText: `Unable to resolve "extends" reference to "${extendsField}": ` + e.message,
textRange: tsdoc_1.TextRange.empty,
});
return;
}
const baseConfigFile = new TSDocConfigFile();
baseConfigFile._loadWithExtends(resolvedExtendsPath, this, alreadyVisitedPaths);
if (baseConfigFile.fileNotFound) {
this._reportError({
messageId: tsdoc_1.TSDocMessageId.ConfigFileUnresolvedExtends,
messageText: `Unable to resolve "extends" reference to "${extendsField}"`,
textRange: tsdoc_1.TextRange.empty,
});
}
this._extendsFiles.push(baseConfigFile);
if (baseConfigFile.hasErrors) {
this._hasErrors = true;
}
}
}
/**
* For the given folder, look for the relevant tsdoc.json file (if any), and return its path.
*
* @param folderPath - the path to a folder where the search should start
* @returns the (possibly relative) path to tsdoc.json, or an empty string if not found
*/
static findConfigPathForFolder(folderPath) {
if (folderPath) {
let foundFolder = folderPath;
for (;;) {
const tsconfigJsonPath = path.join(foundFolder, 'tsconfig.json');
if (fs.existsSync(tsconfigJsonPath)) {
// Stop when we reach a folder containing tsconfig.json
return path.join(foundFolder, TSDocConfigFile.FILENAME);
}
const packageJsonPath = path.join(foundFolder, 'package.json');
if (fs.existsSync(packageJsonPath)) {
// Stop when we reach a folder containing package.json; this avoids crawling out of the current package
return path.join(foundFolder, TSDocConfigFile.FILENAME);
}
const previousFolder = foundFolder;
foundFolder = path.dirname(foundFolder);
if (!foundFolder || foundFolder === previousFolder) {
// Give up if we reach the filesystem root directory
break;
}
}
}
return '';
}
/**
* Calls `TSDocConfigFile.findConfigPathForFolder()` to find the relevant tsdoc.json config file, if one exists.
* Then calls `TSDocConfigFile.findConfigPathForFolder()` to return the loaded result.
*
* @remarks
* This API does not report loading errors by throwing exceptions. Instead, the caller is expected to check
* for errors using {@link TSDocConfigFile.hasErrors}, {@link TSDocConfigFile.log},
* or {@link TSDocConfigFile.getErrorSummary}.
*
* @param folderPath - the path to a folder where the search should start
*/
static loadForFolder(folderPath) {
const rootConfigPath = TSDocConfigFile.findConfigPathForFolder(folderPath);
return TSDocConfigFile.loadFile(rootConfigPath);
}
/**
* Loads the specified tsdoc.json and any base files that it refers to using the "extends" option.
*
* @remarks
* This API does not report loading errors by throwing exceptions. Instead, the caller is expected to check
* for errors using {@link TSDocConfigFile.hasErrors}, {@link TSDocConfigFile.log},
* or {@link TSDocConfigFile.getErrorSummary}.
*
* @param tsdocJsonFilePath - the path to the tsdoc.json config file
*/
static loadFile(tsdocJsonFilePath) {
const configFile = new TSDocConfigFile();
const alreadyVisitedPaths = new Set();
configFile._loadWithExtends(tsdocJsonFilePath, undefined, alreadyVisitedPaths);
return configFile;
}
/**
* Loads the object state from a JSON-serializable object as produced by {@link TSDocConfigFile.saveToObject}.
*
* @remarks
* The serialized object has the same structure as `tsdoc.json`; however the `"extends"` field is not allowed.
*
* This API does not report loading errors by throwing exceptions. Instead, the caller is expected to check
* for errors using {@link TSDocConfigFile.hasErrors}, {@link TSDocConfigFile.log},
* or {@link TSDocConfigFile.getErrorSummary}.
*/
static loadFromObject(jsonObject) {
const configFile = new TSDocConfigFile();
configFile._loadJsonObject(jsonObject);
if (configFile.extendsPaths.length > 0) {
throw new Error('The "extends" field cannot be used with TSDocConfigFile.loadFromObject()');
}
return configFile;
}
/**
* Initializes a TSDocConfigFile object using the state from the provided `TSDocConfiguration` object.
*
* @remarks
* This API does not report loading errors by throwing exceptions. Instead, the caller is expected to check
* for errors using {@link TSDocConfigFile.hasErrors}, {@link TSDocConfigFile.log},
* or {@link TSDocConfigFile.getErrorSummary}.
*/
static loadFromParser(configuration) {
const configFile = new TSDocConfigFile();
// The standard tags will be mixed together with custom definitions,
// so set noStandardTags=true to avoid defining them twice.
configFile.noStandardTags = true;
for (const tagDefinition of configuration.tagDefinitions) {
configFile.addTagDefinition({
syntaxKind: tagDefinition.syntaxKind,
tagName: tagDefinition.tagName,
allowMultiple: tagDefinition.allowMultiple,
});
}
for (const tagDefinition of configuration.supportedTagDefinitions) {
configFile.setSupportForTag(tagDefinition.tagName, true);
}
for (const htmlElement of configuration.supportedHtmlElements) {
configFile.addSupportedHtmlElement(htmlElement);
}
configFile.reportUnsupportedHtmlElements = configuration.validation.reportUnsupportedHtmlElements;
return configFile;
}
/**
* Writes the config file content to a JSON file with the specified file path.
*/
saveFile(jsonFilePath) {
const jsonObject = this.saveToObject();
const jsonContent = JSON.stringify(jsonObject, undefined, 2);
fs.writeFileSync(jsonFilePath, jsonContent);
}
/**
* Writes the object state into a JSON-serializable object.
*/
saveToObject() {
const configJson = {
$schema: TSDocConfigFile.CURRENT_SCHEMA_URL,
};
if (this.noStandardTags !== undefined) {
configJson.noStandardTags = this.noStandardTags;
}
if (this.tagDefinitions.length > 0) {
configJson.tagDefinitions = [];
for (const tagDefinition of this.tagDefinitions) {
configJson.tagDefinitions.push(TSDocConfigFile._serializeTagDefinition(tagDefinition));
}
}
if (this.supportForTags.size > 0) {
configJson.supportForTags = {};
this.supportForTags.forEach((supported, tagName) => {
configJson.supportForTags[tagName] = supported;
});
}
if (this.supportedHtmlElements) {
configJson.supportedHtmlElements = [...this.supportedHtmlElements];
}
if (this._reportUnsupportedHtmlElements !== undefined) {
configJson.reportUnsupportedHtmlElements = this._reportUnsupportedHtmlElements;
}
return configJson;
}
static _serializeTagDefinition(tagDefinition) {
let syntaxKind;
switch (tagDefinition.syntaxKind) {
case tsdoc_1.TSDocTagSyntaxKind.InlineTag:
syntaxKind = 'inline';
break;
case tsdoc_1.TSDocTagSyntaxKind.BlockTag:
syntaxKind = 'block';
break;
case tsdoc_1.TSDocTagSyntaxKind.ModifierTag:
syntaxKind = 'modifier';
break;
default:
throw new Error('Unimplemented TSDocTagSyntaxKind');
}
const tagConfigJson = {
tagName: tagDefinition.tagName,
syntaxKind,
};
if (tagDefinition.allowMultiple) {
tagConfigJson.allowMultiple = true;
}
return tagConfigJson;
}
/**
* Returns a report of any errors that occurred while attempting to load this file or any files
* referenced via the "extends" field.
*
* @remarks
* Use {@link TSDocConfigFile.hasErrors} to determine whether any errors occurred.
*/
getErrorSummary() {
if (!this._hasErrors) {
return 'No errors.';
}
let result = '';
if (this.log.messages.length > 0) {
const errorNoun = this.log.messages.length > 1 ? 'Errors' : 'Error';
if (this.filePath) {
result += `${errorNoun} encountered for ${this.filePath}:\n`;
}
else {
result += `${errorNoun} encountered when loading TSDoc configuration:\n`;
}
for (const message of this.log.messages) {
result += ` ${message.text}\n`;
}
}
for (const extendsFile of this.extendsFiles) {
if (extendsFile.hasErrors) {
if (result !== '') {
result += '\n';
}
result += extendsFile.getErrorSummary();
}
}
return result;
}
/**
* Applies the settings from this config file to a TSDoc parser configuration.
* Any `extendsFile` settings will also applied.
*
* @remarks
* Additional validation is performed during this operation. The caller is expected to check for errors
* using {@link TSDocConfigFile.hasErrors}, {@link TSDocConfigFile.log}, or {@link TSDocConfigFile.getErrorSummary}.
*/
configureParser(configuration) {
if (this._getNoStandardTagsWithExtends()) {
// Do not define standard tags
configuration.clear(true);
}
else {
// Define standard tags (the default behavior)
configuration.clear(false);
}
this.updateParser(configuration);
}
/**
* This is the same as {@link configureParser}, but it preserves any previous state.
*
* @remarks
* Additional validation is performed during this operation. The caller is expected to check for errors
* using {@link TSDocConfigFile.hasErrors}, {@link TSDocConfigFile.log}, or {@link TSDocConfigFile.getErrorSummary}.
*/
updateParser(configuration) {
// First apply the base config files
for (const extendsFile of this.extendsFiles) {
extendsFile.updateParser(configuration);
}
// Then apply this one
for (const tagDefinition of this.tagDefinitions) {
configuration.addTagDefinition(tagDefinition);
}
this.supportForTags.forEach((supported, tagName) => {
const tagDefinition = configuration.tryGetTagDefinition(tagName);
if (tagDefinition) {
// Note that setSupportForTag() automatically enables configuration.validation.reportUnsupportedTags
configuration.setSupportForTag(tagDefinition, supported);
}
else {
// Note that this validation may depend partially on the preexisting state of the TSDocConfiguration
// object, so it cannot be performed during the TSConfigFile.loadFile() stage.
this._reportError({
messageId: tsdoc_1.TSDocMessageId.ConfigFileUndefinedTag,
messageText: `The "supportForTags" field refers to an undefined tag ${JSON.stringify(tagName)}.`,
textRange: tsdoc_1.TextRange.empty,
});
}
});
if (this.supportedHtmlElements) {
configuration.setSupportedHtmlElements([...this.supportedHtmlElements]);
}
if (this._reportUnsupportedHtmlElements === false) {
configuration.validation.reportUnsupportedHtmlElements = false;
}
else if (this._reportUnsupportedHtmlElements === true) {
configuration.validation.reportUnsupportedHtmlElements = true;
}
}
_getNoStandardTagsWithExtends() {
if (this.noStandardTags !== undefined) {
return this.noStandardTags;
}
// This config file does not specify "noStandardTags", so consider any base files referenced using "extends"
let result = undefined;
for (const extendsFile of this.extendsFiles) {
const extendedValue = extendsFile._getNoStandardTagsWithExtends();
if (extendedValue !== undefined) {
result = extendedValue;
}
}
if (result === undefined) {
// If no config file specifies noStandardTags, then it defaults to false
result = false;
}
return result;
}
}
exports.TSDocConfigFile = TSDocConfigFile;
TSDocConfigFile.FILENAME = 'tsdoc.json';
TSDocConfigFile.CURRENT_SCHEMA_URL = 'https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json';
//# sourceMappingURL=TSDocConfigFile.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=ErrorHandling.test.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"ErrorHandling.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/ErrorHandling.test.ts"],"names":[],"mappings":""}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=TSDocConfigFile.test.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"TSDocConfigFile.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/TSDocConfigFile.test.ts"],"names":[],"mappings":""}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,4 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"invalidSetting": false
}

View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,3 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"invalid

View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,3 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/invalid.json"
}

View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,18 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"tagDefinitions": [
{
"tagName": "@dupe",
"syntaxKind": "modifier"
},
{
"tagName": "@dupe",
"syntaxKind": "modifier"
}
],
"supportForTags": {
"@undefinedTag": true
}
}

View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,4 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"extends": [ "./tsdoc-b.json", "./tsdoc-c.json" ]
}

View File

@ -0,0 +1,4 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"extends": [ "./tsdoc-a.json" ]
}

View File

@ -0,0 +1,4 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"unknownSetting": 123
}

View File

@ -0,0 +1,5 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"extends": [ "./tsdoc-a.json" ]
}

View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,4 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"extends": [ "@rushstack/nonexistent-package/tsdoc.json" ]
}

View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,7 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"supportForTags": {
"@nonExistentTag": true
}
}

View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,3 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json"
}

View File

@ -0,0 +1,5 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"supportedHtmlElements": ["span", "p"],
"reportUnsupportedHtmlElements": false
}

View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,5 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"extends": ["./base1/tsdoc-base1.json"],
"reportUnsupportedHtmlElements": true
}

View File

@ -0,0 +1,4 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"reportUnsupportedHtmlElements": false
}

View File

@ -0,0 +1,4 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"supportedHtmlElements": []
}

View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,5 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"extends": ["./base1/tsdoc-base1.json"],
"reportUnsupportedHtmlElements": true
}

View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,5 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"supportedHtmlElements": [],
"reportUnsupportedHtmlElements": false
}

View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,12 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"tagDefinitions": [
{
"tagName": "@base1",
"syntaxKind": "modifier"
}
],
"supportForTags": {
"@base1": true
}
}

View File

@ -0,0 +1,12 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"tagDefinitions": [
{
"tagName": "@base2",
"syntaxKind": "modifier"
}
],
"supportForTags": {
"@base2": false
}
}

View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,13 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"extends": ["./base1/tsdoc-base1.json", "./base2/tsdoc-base2.json"],
"tagDefinitions": [
{
"tagName": "@root",
"syntaxKind": "modifier"
}
],
"supportForTags": {
"@base2": true
}
}

View File

@ -0,0 +1,9 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"tagDefinitions": [
{
"tagName": "@example",
"syntaxKind": "modifier"
}
]
}

View File

@ -0,0 +1,4 @@
{
"name": "example-lib",
"version": "1.0.0"
}

View File

@ -0,0 +1,7 @@
{
"name": "p4",
"version": "1.0.0",
"dependencies": {
"example-lib": "1.0.0"
}
}

View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,10 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"extends": ["example-lib/dist/tsdoc-example.json"],
"tagDefinitions": [
{
"tagName": "@root",
"syntaxKind": "modifier"
}
]
}

View File

@ -0,0 +1,4 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"noStandardTags": false
}

View File

@ -0,0 +1,4 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"noStandardTags": true
}

View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,4 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"extends": ["./base1/tsdoc-base1.json", "./base2/tsdoc-base2.json"]
}

View File

@ -0,0 +1,4 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"noStandardTags": true
}

View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,5 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"extends": ["./base1/tsdoc-base1.json"],
"noStandardTags": false
}

View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,4 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"supportedHtmlElements": ["b", "u"]
}

View File

@ -0,0 +1,4 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"supportedHtmlElements": ["span", "p"]
}

View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,5 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"extends": ["./base1/tsdoc-base1.json"],
"supportedHtmlElements": []
}

View File

@ -0,0 +1,5 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"supportedHtmlElements": ["span", "p"],
"reportUnsupportedHtmlElements": true
}

View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,5 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"extends": ["./base1/tsdoc-base1.json"],
"reportUnsupportedHtmlElements": false
}

2
node_modules/@microsoft/tsdoc-config/lib/index.d.ts generated vendored Normal file
View File

@ -0,0 +1,2 @@
export { TSDocConfigFile } from './TSDocConfigFile';
//# sourceMappingURL=index.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}

5
node_modules/@microsoft/tsdoc-config/lib/index.js generated vendored Normal file
View File

@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var TSDocConfigFile_1 = require("./TSDocConfigFile");
Object.defineProperty(exports, "TSDocConfigFile", { enumerable: true, get: function () { return TSDocConfigFile_1.TSDocConfigFile; } });
//# sourceMappingURL=index.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAAA,qDAAoD;AAA3C,kHAAA,eAAe,OAAA","sourcesContent":["export { TSDocConfigFile } from './TSDocConfigFile';\r\n"]}