diff --git a/tsdoc-config/src/TSDocConfigFile.ts b/tsdoc-config/src/TSDocConfigFile.ts index 17d2403..fb4e1bf 100644 --- a/tsdoc-config/src/TSDocConfigFile.ts +++ b/tsdoc-config/src/TSDocConfigFile.ts @@ -41,7 +41,8 @@ interface IConfigJson { noStandardTags?: boolean; tagDefinitions?: ITagConfigJson[]; supportForTags?: { [tagName: string]: boolean }; - allowedHtmlTags?: string[]; + supportedHtmlElements?: string[]; + reportUnsupportedHtmlElements?: boolean; } /** @@ -70,8 +71,8 @@ export class TSDocConfigFile { private readonly _tagDefinitions: TSDocTagDefinition[]; private readonly _tagDefinitionNames: Set; private readonly _supportForTags: Map; - private readonly _allowedHtmlTags: Set; - private _specifiesAllowedHtmlTags: boolean; + private _supportedHtmlElements: Set | undefined; + private _reportUnsupportedHtmlElements: boolean | undefined; private constructor() { this.log = new ParserMessageLog(); @@ -87,8 +88,6 @@ export class TSDocConfigFile { this._tagDefinitions = []; this._tagDefinitionNames = new Set(); this._supportForTags = new Map(); - this._allowedHtmlTags = new Set(); - this._specifiesAllowedHtmlTags = false; } /** @@ -172,8 +171,12 @@ export class TSDocConfigFile { return this._supportForTags; } - public get allowedHtmlTags(): ReadonlyArray | undefined { - return this._specifiesAllowedHtmlTags ? Array.from(this._allowedHtmlTags) : undefined; + public get supportedHtmlElements(): ReadonlyArray | undefined { + return this._supportedHtmlElements && Array.from(this._supportedHtmlElements); + } + + public get reportUnsupportedHtmlElements(): boolean | undefined { + return this._reportUnsupportedHtmlElements; } /** @@ -227,20 +230,24 @@ export class TSDocConfigFile { } /** - * Adds a new item to the `allowedHtmlTags` array. + * Adds a new item to the `supportedHtmlElements` array. */ - public addAllowedHtmlTag(htmlTag: string): void { - this._specifiesAllowedHtmlTags = true; - this._allowedHtmlTags.add(htmlTag); + public addSupportedHtmlElement(htmlElement: string): void { + if (!this._supportedHtmlElements) { + this._supportedHtmlElements = new Set(); + } + this._supportedHtmlElements.add(htmlElement); } /** - * Removes the explicit list of allowed html tags. When no tags are explicitly listed, - * all tags will be permitted. + * Removes the explicit list of allowed html elements. */ - public clearAllowedHtmlTags(): void { - this._specifiesAllowedHtmlTags = false; - this._allowedHtmlTags.clear(); + public clearSupportedHtmlElements(): void { + this._supportedHtmlElements = undefined; + } + + public setReportUnsupportedHtmlElements(reportUnsupportedHtmlElements: boolean): void { + this._reportUnsupportedHtmlElements = reportUnsupportedHtmlElements; } /** @@ -360,13 +367,15 @@ export class TSDocConfigFile { }); } - if (configJson.allowedHtmlTags) { - this._specifiesAllowedHtmlTags = true; - for (const htmlTag of configJson.allowedHtmlTags) { - this._allowedHtmlTags.add(htmlTag); + 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: boolean = configJson.supportForTags[tagName]; @@ -586,10 +595,12 @@ export class TSDocConfigFile { configFile.setSupportForTag(tagDefinition.tagName, true); } - for (const htmlTag of configuration.allowedHtmlTags) { - configFile.addAllowedHtmlTag(htmlTag); + for (const htmlElement of configuration.supportedHtmlElements) { + configFile.addSupportedHtmlElement(htmlElement); } + configFile.setReportUnsupportedHtmlElements(configuration.validation.reportUnsupportedHtmlElements); + return configFile; } @@ -628,11 +639,12 @@ export class TSDocConfigFile { }); } - if (this.allowedHtmlTags) { - configJson.allowedHtmlTags = []; - for (const htmlTag of this.allowedHtmlTags) { - configJson.allowedHtmlTags.push(htmlTag); - } + if (this.supportedHtmlElements) { + configJson.supportedHtmlElements = [...this.supportedHtmlElements]; + } + + if (this._reportUnsupportedHtmlElements !== undefined) { + configJson.reportUnsupportedHtmlElements = this._reportUnsupportedHtmlElements; } return configJson; @@ -757,8 +769,19 @@ export class TSDocConfigFile { } }); - if (this.allowedHtmlTags) { - configuration.setAllowedHtmlTags([...this.allowedHtmlTags]); + if (this._reportUnsupportedHtmlElements === false) { + configuration.setReportUnsupportedHtmlElements(false); + } + + if ( + this._reportUnsupportedHtmlElements || + (this._reportUnsupportedHtmlElements === undefined && this.supportedHtmlElements) + ) { + configuration.setReportUnsupportedHtmlElements(true); + } + + if (this.supportedHtmlElements) { + configuration.setSupportedHtmlElements([...this.supportedHtmlElements]); } } diff --git a/tsdoc-config/src/__tests__/TSDocConfigFile.test.ts b/tsdoc-config/src/__tests__/TSDocConfigFile.test.ts index 87d519a..8a8f8b5 100644 --- a/tsdoc-config/src/__tests__/TSDocConfigFile.test.ts +++ b/tsdoc-config/src/__tests__/TSDocConfigFile.test.ts @@ -25,7 +25,8 @@ expect.addSnapshotSerializer({ tagDefinitions: configFile.tagDefinitions, supportForTags: Array.from(configFile.supportForTags).map(([tagName, supported]) => ({ tagName, supported })), messages: configFile.log.messages, - allowedHtmlTags: configFile.allowedHtmlTags, + supportedHtmlElements: configFile.supportedHtmlElements, + reportUnsupportedHtmlElements: configFile.reportUnsupportedHtmlElements, }); }, }); @@ -37,14 +38,15 @@ function testLoadingFolder(assetPath: string): TSDocConfigFile { test('Load p1', () => { expect(testLoadingFolder('assets/p1')).toMatchInlineSnapshot(` Object { - "allowedHtmlTags": undefined, "extendsFiles": Array [], "extendsPaths": Array [], "fileNotFound": false, "filePath": "assets/p1/tsdoc.json", "messages": Array [], "noStandardTags": undefined, + "reportUnsupportedHtmlElements": undefined, "supportForTags": Array [], + "supportedHtmlElements": undefined, "tagDefinitions": Array [], "tsdocSchema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", } @@ -54,7 +56,6 @@ test('Load p1', () => { test('Load p2', () => { expect(testLoadingFolder('assets/p2')).toMatchInlineSnapshot(` Object { - "allowedHtmlTags": undefined, "extendsFiles": Array [], "extendsPaths": Array [], "fileNotFound": true, @@ -74,7 +75,9 @@ test('Load p2', () => { }, ], "noStandardTags": undefined, + "reportUnsupportedHtmlElements": undefined, "supportForTags": Array [], + "supportedHtmlElements": undefined, "tagDefinitions": Array [], "tsdocSchema": "", } @@ -84,22 +87,22 @@ test('Load p2', () => { test('Load p3', () => { expect(testLoadingFolder('assets/p3')).toMatchInlineSnapshot(` Object { - "allowedHtmlTags": undefined, "extendsFiles": Array [ Object { - "allowedHtmlTags": undefined, "extendsFiles": Array [], "extendsPaths": Array [], "fileNotFound": false, "filePath": "assets/p3/base1/tsdoc-base1.json", "messages": Array [], "noStandardTags": undefined, + "reportUnsupportedHtmlElements": undefined, "supportForTags": Array [ Object { "supported": true, "tagName": "@base1", }, ], + "supportedHtmlElements": undefined, "tagDefinitions": Array [ TSDocTagDefinition { "allowMultiple": false, @@ -112,19 +115,20 @@ test('Load p3', () => { "tsdocSchema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", }, Object { - "allowedHtmlTags": undefined, "extendsFiles": Array [], "extendsPaths": Array [], "fileNotFound": false, "filePath": "assets/p3/base2/tsdoc-base2.json", "messages": Array [], "noStandardTags": undefined, + "reportUnsupportedHtmlElements": undefined, "supportForTags": Array [ Object { "supported": false, "tagName": "@base2", }, ], + "supportedHtmlElements": undefined, "tagDefinitions": Array [ TSDocTagDefinition { "allowMultiple": false, @@ -145,12 +149,14 @@ test('Load p3', () => { "filePath": "assets/p3/tsdoc.json", "messages": Array [], "noStandardTags": undefined, + "reportUnsupportedHtmlElements": undefined, "supportForTags": Array [ Object { "supported": true, "tagName": "@base2", }, ], + "supportedHtmlElements": undefined, "tagDefinitions": Array [ TSDocTagDefinition { "allowMultiple": false, @@ -168,17 +174,17 @@ test('Load p3', () => { test('Load p4', () => { expect(testLoadingFolder('assets/p4')).toMatchInlineSnapshot(` Object { - "allowedHtmlTags": undefined, "extendsFiles": Array [ Object { - "allowedHtmlTags": undefined, "extendsFiles": Array [], "extendsPaths": Array [], "fileNotFound": false, "filePath": "assets/p4/node_modules/example-lib/dist/tsdoc-example.json", "messages": Array [], "noStandardTags": undefined, + "reportUnsupportedHtmlElements": undefined, "supportForTags": Array [], + "supportedHtmlElements": undefined, "tagDefinitions": Array [ TSDocTagDefinition { "allowMultiple": false, @@ -198,7 +204,9 @@ test('Load p4', () => { "filePath": "assets/p4/tsdoc.json", "messages": Array [], "noStandardTags": undefined, + "reportUnsupportedHtmlElements": undefined, "supportForTags": Array [], + "supportedHtmlElements": undefined, "tagDefinitions": Array [ TSDocTagDefinition { "allowMultiple": false, @@ -246,6 +254,7 @@ test('Re-serialize p3 without defaults', () => { Object { "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", "noStandardTags": true, + "reportUnsupportedHtmlElements": false, } `); @@ -262,6 +271,7 @@ test('Re-serialize p3 without defaults', () => { Object { "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", "noStandardTags": true, + "reportUnsupportedHtmlElements": false, "supportForTags": Object { "@base1": true, "@base2": true, @@ -295,6 +305,7 @@ test('Re-serialize p3 with defaults', () => { Object { "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", "noStandardTags": true, + "reportUnsupportedHtmlElements": false, "tagDefinitions": Array [ Object { "syntaxKind": "modifier", @@ -418,6 +429,7 @@ test('Re-serialize p3 with defaults', () => { Object { "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", "noStandardTags": true, + "reportUnsupportedHtmlElements": false, "supportForTags": Object { "@base1": true, "@base2": true, @@ -571,29 +583,37 @@ test('Test noStandardTags for p6', () => { test('Test load p7', () => { expect(testLoadingFolder('assets/p7')).toMatchInlineSnapshot(` Object { - "allowedHtmlTags": Array [ - "b", - "u", - ], "extendsFiles": Array [], "extendsPaths": Array [], "fileNotFound": false, "filePath": "assets/p7/tsdoc.json", "messages": Array [], "noStandardTags": undefined, + "reportUnsupportedHtmlElements": undefined, "supportForTags": Array [], + "supportedHtmlElements": Array [ + "b", + "u", + ], "tagDefinitions": Array [], "tsdocSchema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", } `); }); +test('p7 reportUnsupportedHtmlElements defaults to true when supportedHtmlElements is specified', () => { + const configFile: TSDocConfigFile = TSDocConfigFile.loadForFolder(path.join(__dirname, 'assets/p7')); + const flattened = new TSDocConfiguration(); + configFile.updateParser(flattened); + expect(flattened.validation.reportUnsupportedHtmlElements).toEqual(true); +}); + test('Test re-serialize p7', () => { const configFile: TSDocConfigFile = TSDocConfigFile.loadForFolder(path.join(__dirname, 'assets/p7')); expect(configFile.saveToObject()).toMatchInlineSnapshot(` Object { "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", - "allowedHtmlTags": Array [ + "supportedHtmlElements": Array [ "b", "u", ], @@ -604,20 +624,20 @@ test('Test re-serialize p7', () => { test('Test load p8', () => { expect(testLoadingFolder('assets/p8')).toMatchInlineSnapshot(` Object { - "allowedHtmlTags": Array [], "extendsFiles": Array [ Object { - "allowedHtmlTags": Array [ - "span", - "p", - ], "extendsFiles": Array [], "extendsPaths": Array [], "fileNotFound": false, "filePath": "assets/p8/base1/tsdoc-base1.json", "messages": Array [], "noStandardTags": undefined, + "reportUnsupportedHtmlElements": undefined, "supportForTags": Array [], + "supportedHtmlElements": Array [ + "span", + "p", + ], "tagDefinitions": Array [], "tsdocSchema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", }, @@ -629,18 +649,20 @@ test('Test load p8', () => { "filePath": "assets/p8/tsdoc.json", "messages": Array [], "noStandardTags": undefined, + "reportUnsupportedHtmlElements": undefined, "supportForTags": Array [], + "supportedHtmlElements": Array [], "tagDefinitions": Array [], "tsdocSchema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", } `); }); -test('p8 allowedHtmlTags are not inherited when an empty array is specified', () => { +test('p8 supportedHtmlElements are not inherited when an empty array is specified', () => { const configFile: TSDocConfigFile = TSDocConfigFile.loadForFolder(path.join(__dirname, 'assets/p8')); const flattened = new TSDocConfiguration(); configFile.updateParser(flattened); - expect(flattened.allowedHtmlTags).toEqual([]); + expect(flattened.supportedHtmlElements).toEqual([]); }); test('Test re-serialize p8', () => { @@ -648,7 +670,7 @@ test('Test re-serialize p8', () => { expect(configFile.saveToObject()).toMatchInlineSnapshot(` Object { "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", - "allowedHtmlTags": Array [], + "supportedHtmlElements": Array [], } `); }); @@ -656,20 +678,20 @@ test('Test re-serialize p8', () => { test('Test load p9', () => { expect(testLoadingFolder('assets/p9')).toMatchInlineSnapshot(` Object { - "allowedHtmlTags": undefined, "extendsFiles": Array [ Object { - "allowedHtmlTags": Array [ - "span", - "p", - ], "extendsFiles": Array [], "extendsPaths": Array [], "fileNotFound": false, "filePath": "assets/p9/base1/tsdoc-base1.json", "messages": Array [], "noStandardTags": undefined, + "reportUnsupportedHtmlElements": true, "supportForTags": Array [], + "supportedHtmlElements": Array [ + "span", + "p", + ], "tagDefinitions": Array [], "tsdocSchema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", }, @@ -681,18 +703,27 @@ test('Test load p9', () => { "filePath": "assets/p9/tsdoc.json", "messages": Array [], "noStandardTags": undefined, + "reportUnsupportedHtmlElements": false, "supportForTags": Array [], + "supportedHtmlElements": undefined, "tagDefinitions": Array [], "tsdocSchema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", } `); }); -test('p9 allowedHtmlTags are inherited', () => { +test('p9 supportedHtmlElements are inherited', () => { const configFile: TSDocConfigFile = TSDocConfigFile.loadForFolder(path.join(__dirname, 'assets/p9')); const flattened = new TSDocConfiguration(); configFile.updateParser(flattened); - expect(flattened.allowedHtmlTags).toEqual(['span', 'p']); + expect(flattened.supportedHtmlElements).toEqual(['span', 'p']); +}); + +test('p9 reportUnsupportedHtmlElements is overridden', () => { + const configFile: TSDocConfigFile = TSDocConfigFile.loadForFolder(path.join(__dirname, 'assets/p9')); + const flattened = new TSDocConfiguration(); + configFile.updateParser(flattened); + expect(flattened.validation.reportUnsupportedHtmlElements).toEqual(false); }); test('Test re-serialize p9', () => { @@ -700,6 +731,7 @@ test('Test re-serialize p9', () => { expect(configFile.saveToObject()).toMatchInlineSnapshot(` Object { "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", + "reportUnsupportedHtmlElements": false, } `); }); @@ -728,6 +760,7 @@ test('Test loadFromObject()', () => { Object { "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", "noStandardTags": true, + "reportUnsupportedHtmlElements": false, "supportForTags": Object { "@tag1": true, }, diff --git a/tsdoc-config/src/__tests__/assets/p7/tsdoc.json b/tsdoc-config/src/__tests__/assets/p7/tsdoc.json index 89b859d..59a3638 100644 --- a/tsdoc-config/src/__tests__/assets/p7/tsdoc.json +++ b/tsdoc-config/src/__tests__/assets/p7/tsdoc.json @@ -1,4 +1,4 @@ { "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", - "allowedHtmlTags": ["b", "u"] + "supportedHtmlElements": ["b", "u"] } diff --git a/tsdoc-config/src/__tests__/assets/p8/base1/tsdoc-base1.json b/tsdoc-config/src/__tests__/assets/p8/base1/tsdoc-base1.json index b43de62..44c7433 100644 --- a/tsdoc-config/src/__tests__/assets/p8/base1/tsdoc-base1.json +++ b/tsdoc-config/src/__tests__/assets/p8/base1/tsdoc-base1.json @@ -1,4 +1,4 @@ { "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", - "allowedHtmlTags": ["span", "p"] + "supportedHtmlElements": ["span", "p"] } diff --git a/tsdoc-config/src/__tests__/assets/p8/tsdoc.json b/tsdoc-config/src/__tests__/assets/p8/tsdoc.json index 1a39bc4..436a09c 100644 --- a/tsdoc-config/src/__tests__/assets/p8/tsdoc.json +++ b/tsdoc-config/src/__tests__/assets/p8/tsdoc.json @@ -1,5 +1,5 @@ { "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", "extends": ["./base1/tsdoc-base1.json"], - "allowedHtmlTags": [] + "supportedHtmlElements": [] } diff --git a/tsdoc-config/src/__tests__/assets/p9/base1/tsdoc-base1.json b/tsdoc-config/src/__tests__/assets/p9/base1/tsdoc-base1.json index b43de62..860615a 100644 --- a/tsdoc-config/src/__tests__/assets/p9/base1/tsdoc-base1.json +++ b/tsdoc-config/src/__tests__/assets/p9/base1/tsdoc-base1.json @@ -1,4 +1,5 @@ { "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", - "allowedHtmlTags": ["span", "p"] + "supportedHtmlElements": ["span", "p"], + "reportUnsupportedHtmlElements": true } diff --git a/tsdoc-config/src/__tests__/assets/p9/tsdoc.json b/tsdoc-config/src/__tests__/assets/p9/tsdoc.json index 7293652..6e8cd82 100644 --- a/tsdoc-config/src/__tests__/assets/p9/tsdoc.json +++ b/tsdoc-config/src/__tests__/assets/p9/tsdoc.json @@ -1,4 +1,5 @@ { "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", - "extends": ["./base1/tsdoc-base1.json"] + "extends": ["./base1/tsdoc-base1.json"], + "reportUnsupportedHtmlElements": false } diff --git a/tsdoc/etc/tsdoc.api.md b/tsdoc/etc/tsdoc.api.md index 15e2b2c..21a21b5 100644 --- a/tsdoc/etc/tsdoc.api.md +++ b/tsdoc/etc/tsdoc.api.md @@ -1242,16 +1242,17 @@ export class TSDocConfiguration { constructor(); addTagDefinition(tagDefinition: TSDocTagDefinition): void; addTagDefinitions(tagDefinitions: ReadonlyArray, supported?: boolean | undefined): void; - get allowedHtmlTags(): string[]; get allTsdocMessageIds(): ReadonlyArray; clear(noStandardTags?: boolean): void; get docNodeManager(): DocNodeManager; - isHtmlTagAllowed(htmlTag: string): boolean; + isHtmlTagSupported(htmlTag: string): boolean; isKnownMessageId(messageId: TSDocMessageId | string): boolean; isTagSupported(tagDefinition: TSDocTagDefinition): boolean; - setAllowedHtmlTags(htmlTags: string[]): void; + setReportUnsupportedHtmlElements(reportUnsupportedHtmlElements: boolean): void; + setSupportedHtmlElements(htmlTags: string[]): void; setSupportForTag(tagDefinition: TSDocTagDefinition, supported: boolean): void; setSupportForTags(tagDefinitions: ReadonlyArray, supported: boolean): void; + get supportedHtmlElements(): string[]; get supportedTagDefinitions(): ReadonlyArray; get tagDefinitions(): ReadonlyArray; tryGetTagDefinition(tagName: string): TSDocTagDefinition | undefined; @@ -1296,7 +1297,6 @@ export const enum TSDocMessageId { ConfigFileUnresolvedExtends = "tsdoc-config-unresolved-extends", ConfigFileUnsupportedSchema = "tsdoc-config-unsupported-schema", ConfigInvalidJson = "tsdoc-config-invalid-json", - DisallowedHtmlName = "tsdoc-disallowed-html-name", EscapeGreaterThan = "tsdoc-escape-greater-than", EscapeRightBrace = "tsdoc-escape-right-brace", ExtraInheritDocTag = "tsdoc-extra-inheritdoc-tag", @@ -1345,6 +1345,7 @@ export const enum TSDocMessageId { TextAfterHtmlString = "tsdoc-text-after-html-string", UndefinedTag = "tsdoc-undefined-tag", UnnecessaryBackslash = "tsdoc-unnecessary-backslash", + UnsupportedHtmlElementName = "tsdoc-unsupported-html-name", UnsupportedTag = "tsdoc-unsupported-tag" } @@ -1379,6 +1380,7 @@ export enum TSDocTagSyntaxKind { // @public export class TSDocValidationConfiguration { ignoreUndefinedTags: boolean; + reportUnsupportedHtmlElements: boolean; reportUnsupportedTags: boolean; } diff --git a/tsdoc/schemas/tsdoc.schema.json b/tsdoc/schemas/tsdoc.schema.json index 40f2ebd..061a4d3 100644 --- a/tsdoc/schemas/tsdoc.schema.json +++ b/tsdoc/schemas/tsdoc.schema.json @@ -29,8 +29,8 @@ } }, - "allowedHtmlTags": { - "description": "HTML tags to permit in TSDoc comments. If not specified, all tags will be allowed.", + "supportedHtmlElements": { + "description": "HTML element names to permit in TSDoc comments. If not specified, all tags will be allowed.", "type": "array", "items": { "type": "string", @@ -38,6 +38,11 @@ } }, + "reportUnsupportedHtmlElements": { + "description": "Whether an error should be reported when an unsupported HTML element is encountered. Defaults to \"true\" if \"supportedHtmlElements\" is defined, \"false\" if it is not.", + "type": "boolean" + }, + "supportForTags": { "description": "A collection of key/value pairs. The key is a TSDoc tag name (e.g. \"@myTag\") that must be defined in this configuration. The value is a boolean indicating whether the tag is supported. The TSDoc parser may report warnings when unsupported tags are encountered. If \"supportForTags\" is specified for at least one tag, then the \"reportUnsupportedTags\" validation check is enabled by default.", "type": "object", diff --git a/tsdoc/src/configuration/TSDocConfiguration.ts b/tsdoc/src/configuration/TSDocConfiguration.ts index d842216..05b3a9f 100644 --- a/tsdoc/src/configuration/TSDocConfiguration.ts +++ b/tsdoc/src/configuration/TSDocConfiguration.ts @@ -14,7 +14,7 @@ export class TSDocConfiguration { private readonly _supportedTagDefinitions: Set; private readonly _validation: TSDocValidationConfiguration; private readonly _docNodeManager: DocNodeManager; - private readonly _allowedHtmlTags: Set; + private readonly _supportedHtmlElements: Set; public constructor() { this._tagDefinitions = []; @@ -22,7 +22,7 @@ export class TSDocConfiguration { this._supportedTagDefinitions = new Set(); this._validation = new TSDocValidationConfiguration(); this._docNodeManager = new DocNodeManager(); - this._allowedHtmlTags = new Set(); + this._supportedHtmlElements = new Set(); this.clear(false); @@ -41,7 +41,7 @@ export class TSDocConfiguration { this._supportedTagDefinitions.clear(); this._validation.ignoreUndefinedTags = false; this._validation.reportUnsupportedTags = false; - this._allowedHtmlTags.clear(); + this._supportedHtmlElements.clear(); if (!noStandardTags) { // Define all the standard tags @@ -79,11 +79,10 @@ export class TSDocConfiguration { } /** - * The html tags that are supported in this configuration. If this array is empty, - * then all tags are permitted. + * The html tags that are supported in this configuration. */ - public get allowedHtmlTags(): string[] { - return Array.from(this._allowedHtmlTags.values()); + public get supportedHtmlElements(): string[] { + return Array.from(this._supportedHtmlElements.values()); } /** @@ -194,24 +193,30 @@ export class TSDocConfiguration { } /** - * Overwrite the supported HTML tags. If an empty array is specified, - * all tags will be allowed. + * Overwrite the supported HTML elements. */ - public setAllowedHtmlTags(htmlTags: string[]): void { - this._allowedHtmlTags.clear(); + public setSupportedHtmlElements(htmlTags: string[]): void { + this._supportedHtmlElements.clear(); for (const htmlTag of htmlTags) { - this._allowedHtmlTags.add(htmlTag); + this._supportedHtmlElements.add(htmlTag); } } + /** + * Overwrite the validator's existing value for `reportUnsupportedHtmlElements`. + */ + public setReportUnsupportedHtmlElements(reportUnsupportedHtmlElements: boolean): void { + this.validation.reportUnsupportedHtmlElements = reportUnsupportedHtmlElements; + } + /** * Returns true if the html tag is supported in this configuration. */ - public isHtmlTagAllowed(htmlTag: string): boolean { - if (this._allowedHtmlTags.size === 0) { + public isHtmlTagSupported(htmlTag: string): boolean { + if (this._supportedHtmlElements.size === 0) { return true; } - return this._allowedHtmlTags.has(htmlTag); + return this._supportedHtmlElements.has(htmlTag); } /** diff --git a/tsdoc/src/configuration/TSDocValidationConfiguration.ts b/tsdoc/src/configuration/TSDocValidationConfiguration.ts index 6121c07..8d4e285 100644 --- a/tsdoc/src/configuration/TSDocValidationConfiguration.ts +++ b/tsdoc/src/configuration/TSDocValidationConfiguration.ts @@ -33,4 +33,10 @@ export class TSDocValidationConfiguration { * @defaultValue `false` */ public reportUnsupportedTags: boolean = false; + + /** + * Set `reportUnsupportedHtmlElements` to true to issue a warning for HTML elements which + * are not defined in your TSDoc configuration's `supportedHtmlElements` field. + */ + public reportUnsupportedHtmlElements: boolean = false; } diff --git a/tsdoc/src/parser/NodeParser.ts b/tsdoc/src/parser/NodeParser.ts index bee3a8c..dfd1d58 100644 --- a/tsdoc/src/parser/NodeParser.ts +++ b/tsdoc/src/parser/NodeParser.ts @@ -2136,11 +2136,14 @@ export class NodeParser { ); } - if (!this._configuration.isHtmlTagAllowed(htmlName)) { + if ( + this._configuration.validation.reportUnsupportedHtmlElements && + !this._configuration.isHtmlTagSupported(htmlName) + ) { return this._createFailureForToken( tokenReader, - TSDocMessageId.DisallowedHtmlName, - "This HTML tag is disallowed by the project's current TSDoc configuration", + TSDocMessageId.UnsupportedHtmlElementName, + 'This HTML element name is not defined by your TSDoc configuration', marker ); } diff --git a/tsdoc/src/parser/TSDocMessageId.ts b/tsdoc/src/parser/TSDocMessageId.ts index ae9595f..3ccc5e0 100644 --- a/tsdoc/src/parser/TSDocMessageId.ts +++ b/tsdoc/src/parser/TSDocMessageId.ts @@ -374,9 +374,9 @@ export const enum TSDocMessageId { MalformedHtmlName = 'tsdoc-malformed-html-name', /** - * This HTML tag is disallowed by the project's current TSDoc configuration. + * This HTML element name is not defined by your TSDoc configuration. */ - DisallowedHtmlName = 'tsdoc-disallowed-html-name', + UnsupportedHtmlElementName = 'tsdoc-unsupported-html-name', /** * The opening backtick for a code fence must appear at the start of the line. diff --git a/tsdoc/src/parser/__tests__/NodeParserHtml.test.ts b/tsdoc/src/parser/__tests__/NodeParserHtml.test.ts index 91276c7..e131783 100644 --- a/tsdoc/src/parser/__tests__/NodeParserHtml.test.ts +++ b/tsdoc/src/parser/__tests__/NodeParserHtml.test.ts @@ -101,9 +101,9 @@ test('09 Unusual HTML names, negative', () => { TestHelpers.parseAndMatchNodeParserSnapshot(['/**', ' * <1a/>', ' * ', ' * <_a>', ' */'].join('\n')); }); -test('10 Allowed HTML names, positive', () => { +test('10 Supported HTML elements, positive', () => { const config: TSDocConfiguration = new TSDocConfiguration(); - config.setAllowedHtmlTags(['a', 'b', 'c']); + config.setSupportedHtmlElements(['a', 'b', 'c']); TestHelpers.parseAndMatchNodeParserSnapshot( ['/**', ' * ', ' * ', ' * ', ' */'].join('\n'), @@ -111,9 +111,9 @@ test('10 Allowed HTML names, positive', () => { ); }); -test('11 Disallowed HTML names, negative', () => { +test('11 Supported HTML elements, negative', () => { const config: TSDocConfiguration = new TSDocConfiguration(); - config.setAllowedHtmlTags(['d']); + config.setSupportedHtmlElements(['d']); TestHelpers.parseAndMatchNodeParserSnapshot( ['/**', ' * ', ' * ', ' * ', ' */'].join('\n'), diff --git a/tsdoc/src/parser/__tests__/__snapshots__/NodeParserHtml.test.ts.snap b/tsdoc/src/parser/__tests__/__snapshots__/NodeParserHtml.test.ts.snap index 962ece3..02d9af8 100644 --- a/tsdoc/src/parser/__tests__/__snapshots__/NodeParserHtml.test.ts.snap +++ b/tsdoc/src/parser/__tests__/__snapshots__/NodeParserHtml.test.ts.snap @@ -1969,7 +1969,7 @@ Object { } `; -exports[`10 Allowed HTML names, positive 1`] = ` +exports[`10 Supported HTML elements, positive 1`] = ` Object { "buffer": "/**[n] * [<]a[>][n] * [<]b/[>][n] * [<]/c[>][n] */", "gaps": Array [], @@ -2075,7 +2075,7 @@ Object { } `; -exports[`11 Disallowed HTML names, negative 1`] = ` +exports[`11 Supported HTML elements, negative 1`] = ` Object { "buffer": "/**[n] * [<]a[>][n] * [<]b[>][n] * [<]c[>][n] */", "gaps": Array [], @@ -2084,14 +2084,7 @@ Object { "[<]b[>]", "[<]c[>]", ], - "logMessages": Array [ - "(2,4): Invalid HTML element: This HTML tag is disallowed by the project's current TSDoc configuration", - "(2,6): The \\">\\" character should be escaped using a backslash to avoid confusion with an HTML tag", - "(3,4): Invalid HTML element: This HTML tag is disallowed by the project's current TSDoc configuration", - "(3,6): The \\">\\" character should be escaped using a backslash to avoid confusion with an HTML tag", - "(4,4): Invalid HTML element: This HTML tag is disallowed by the project's current TSDoc configuration", - "(4,6): The \\">\\" character should be escaped using a backslash to avoid confusion with an HTML tag", - ], + "logMessages": Array [], "nodes": Object { "kind": "Comment", "nodes": Array [ @@ -2102,34 +2095,18 @@ Object { "kind": "Paragraph", "nodes": Array [ Object { - "errorLocation": "a", - "errorLocationPrecedingToken": "<", - "errorMessage": "Invalid HTML element: This HTML tag is disallowed by the project's current TSDoc configuration", - "kind": "ErrorText", + "kind": "HtmlStartTag", "nodes": Array [ Object { - "kind": "Excerpt: ErrorText", + "kind": "Excerpt: HtmlStartTag_OpeningDelimiter", "nodeExcerpt": "[<]", }, - ], - }, - Object { - "kind": "PlainText", - "nodes": Array [ Object { - "kind": "Excerpt: PlainText", + "kind": "Excerpt: HtmlStartTag_Name", "nodeExcerpt": "a", }, - ], - }, - Object { - "errorLocation": "[>]", - "errorLocationPrecedingToken": "a", - "errorMessage": "The [q][>][q] character should be escaped using a backslash to avoid confusion with an HTML tag", - "kind": "ErrorText", - "nodes": Array [ Object { - "kind": "Excerpt: ErrorText", + "kind": "Excerpt: HtmlStartTag_ClosingDelimiter", "nodeExcerpt": "[>]", }, ], @@ -2144,34 +2121,18 @@ Object { ], }, Object { - "errorLocation": "b", - "errorLocationPrecedingToken": "<", - "errorMessage": "Invalid HTML element: This HTML tag is disallowed by the project's current TSDoc configuration", - "kind": "ErrorText", + "kind": "HtmlStartTag", "nodes": Array [ Object { - "kind": "Excerpt: ErrorText", + "kind": "Excerpt: HtmlStartTag_OpeningDelimiter", "nodeExcerpt": "[<]", }, - ], - }, - Object { - "kind": "PlainText", - "nodes": Array [ Object { - "kind": "Excerpt: PlainText", + "kind": "Excerpt: HtmlStartTag_Name", "nodeExcerpt": "b", }, - ], - }, - Object { - "errorLocation": "[>]", - "errorLocationPrecedingToken": "b", - "errorMessage": "The [q][>][q] character should be escaped using a backslash to avoid confusion with an HTML tag", - "kind": "ErrorText", - "nodes": Array [ Object { - "kind": "Excerpt: ErrorText", + "kind": "Excerpt: HtmlStartTag_ClosingDelimiter", "nodeExcerpt": "[>]", }, ], @@ -2186,34 +2147,18 @@ Object { ], }, Object { - "errorLocation": "c", - "errorLocationPrecedingToken": "<", - "errorMessage": "Invalid HTML element: This HTML tag is disallowed by the project's current TSDoc configuration", - "kind": "ErrorText", + "kind": "HtmlStartTag", "nodes": Array [ Object { - "kind": "Excerpt: ErrorText", + "kind": "Excerpt: HtmlStartTag_OpeningDelimiter", "nodeExcerpt": "[<]", }, - ], - }, - Object { - "kind": "PlainText", - "nodes": Array [ Object { - "kind": "Excerpt: PlainText", + "kind": "Excerpt: HtmlStartTag_Name", "nodeExcerpt": "c", }, - ], - }, - Object { - "errorLocation": "[>]", - "errorLocationPrecedingToken": "c", - "errorMessage": "The [q][>][q] character should be escaped using a backslash to avoid confusion with an HTML tag", - "kind": "ErrorText", - "nodes": Array [ Object { - "kind": "Excerpt: ErrorText", + "kind": "Excerpt: HtmlStartTag_ClosingDelimiter", "nodeExcerpt": "[>]", }, ],