diff --git a/src/axe-tool-property-provider-21.test.ts b/src/axe-tool-property-provider-21.test.ts new file mode 100644 index 00000000..4d90361a --- /dev/null +++ b/src/axe-tool-property-provider-21.test.ts @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +import { getAxeToolProperties21 } from './axe-tool-property-provider-21'; +import * as Sarif from './sarif/sarif-2.1.2'; + +describe('axe-tool-property-provider 2.1', () => { + describe('getAxeToolProperties21', () => { + it("returns the axe properties as a Sarif.Run['tool']", () => { + const expectedResults: Sarif.Run['tool'] = { + driver: { + name: 'axe-core', + fullName: 'axe for Web v3.2.2', + shortDescription: { + text: + 'An open source accessibility rules library for automated testing.', + }, + version: '3.2.2', + semanticVersion: '3.2.2', + informationUri: 'https://www.deque.com/axe/axe-for-web/', + downloadUri: + 'https://www.npmjs.com/package/axe-core/v/3.2.2', + properties: { + 'microsoft/qualityDomain': 'Accessibility', + }, + supportedTaxonomies: [ + { + name: 'WCAG', + index: 0, + guid: '', + }, + ], + }, + }; + + const actualResults: Sarif.Run['tool'] = getAxeToolProperties21(); + expect(actualResults).toEqual(expectedResults); + }); + }); +}); diff --git a/src/axe-tool-property-provider-21.ts b/src/axe-tool-property-provider-21.ts new file mode 100644 index 00000000..a856f8e7 --- /dev/null +++ b/src/axe-tool-property-provider-21.ts @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +import * as Sarif from './sarif/sarif-2.1.2'; + +export function getAxeToolProperties21(): Sarif.Run['tool'] { + return { + driver: { + name: 'axe-core', + fullName: 'axe for Web v3.2.2', + shortDescription: { + text: + 'An open source accessibility rules library for automated testing.', + }, + version: '3.2.2', + semanticVersion: '3.2.2', + informationUri: 'https://www.deque.com/axe/axe-for-web/', + downloadUri: 'https://www.npmjs.com/package/axe-core/v/3.2.2', + properties: { + 'microsoft/qualityDomain': 'Accessibility', + }, + supportedTaxonomies: [ + { + name: 'WCAG', + index: 0, + guid: '', + }, + ], + }, + }; +} diff --git a/src/converter-property-provider.test.ts b/src/converter-property-provider.test.ts new file mode 100644 index 00000000..1680d283 --- /dev/null +++ b/src/converter-property-provider.test.ts @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +import { getConverterProperties } from './converter-property-provider'; +import * as Sarif from './sarif/sarif-2.1.2'; + +describe('converter-property-provider', () => { + describe('getConverterProperties', () => { + it('returns the converter properties as a Sarif.Run["conversion"', () => { + const expectedResults: Sarif.Run['conversion'] = { + tool: { + driver: { + name: 'axe-sarif-converter', + fullName: 'axe-sarif-converter v1.3.0', + version: '1.3.0', + semanticVersion: '1.3.0', + informationUri: + 'https://github.com/microsoft/axe-sarif-converter/releases/tag/v1.3.0', + downloadUri: + 'https://www.npmjs.com/package/axe-sarif-converter/v/1.3.0', + }, + }, + }; + + const actualResults: Sarif.Run['conversion'] = getConverterProperties(); + expect(actualResults).toEqual(expectedResults); + }); + }); +}); diff --git a/src/converter-property-provider.ts b/src/converter-property-provider.ts new file mode 100644 index 00000000..fdcc69d9 --- /dev/null +++ b/src/converter-property-provider.ts @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +import * as Sarif from './sarif/sarif-2.1.2'; + +export function getConverterProperties(): Sarif.Run['conversion'] { + return { + tool: { + driver: { + name: 'axe-sarif-converter', + fullName: 'axe-sarif-converter v1.3.0', + version: '1.3.0', + semanticVersion: '1.3.0', + informationUri: + 'https://github.com/microsoft/axe-sarif-converter/releases/tag/v1.3.0', + downloadUri: + 'https://www.npmjs.com/package/axe-sarif-converter/v/1.3.0', + }, + }, + }; +} diff --git a/src/invocation-provider-21.test.ts b/src/invocation-provider-21.test.ts new file mode 100644 index 00000000..9b8c89d9 --- /dev/null +++ b/src/invocation-provider-21.test.ts @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +import { EnvironmentData } from './environment-data'; +import { getInvocations21 } from './invocation-provider-21'; +import * as Sarif from './sarif/sarif-2.1.2'; + +describe('invocation-provider-2.1', () => { + describe('getInvocations21', () => { + it('populates invocations with data from environmentData parameter', () => { + const environmentDataStub: EnvironmentData = { + targetPageUrl: 'https://example.com', + targetPageTitle: 'Environment Data Stub', + timestamp: '2018-03-23T21:36:58.321Z', + }; + const invocationStub: Sarif.Invocation[] = [ + { + startTimeUtc: '2018-03-23T21:36:58.321Z', + endTimeUtc: '2018-03-23T21:36:58.321Z', + executionSuccessful: true, + }, + ]; + const actualResults: Sarif.Invocation[] = getInvocations21( + environmentDataStub, + ); + expect(actualResults).toEqual(invocationStub); + }); + }); +}); diff --git a/src/invocation-provider-21.ts b/src/invocation-provider-21.ts new file mode 100644 index 00000000..c6ed4ce7 --- /dev/null +++ b/src/invocation-provider-21.ts @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +import { EnvironmentData } from './environment-data'; +import * as Sarif from './sarif/sarif-2.1.2'; + +export function getInvocations21( + environmentData: EnvironmentData, +): Sarif.Invocation[] { + return [ + { + startTimeUtc: environmentData.timestamp, + endTimeUtc: environmentData.timestamp, + executionSuccessful: true, + }, + ]; +} diff --git a/src/sarif-converter-21.test.ts b/src/sarif-converter-21.test.ts new file mode 100644 index 00000000..a9bb401b --- /dev/null +++ b/src/sarif-converter-21.test.ts @@ -0,0 +1,151 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +import { IMock, It, Mock, Times } from 'typemoq'; +import { getAxeToolProperties21 } from './axe-tool-property-provider-21'; +import { ConverterOptions } from './converter-options'; +import { getConverterProperties } from './converter-property-provider'; +import { DecoratedAxeResults } from './decorated-axe-results'; +import { EnvironmentData } from './environment-data'; +import { getInvocations } from './invocation-provider'; +import { SarifConverter21 } from './sarif-converter-21'; +import * as Sarif from './sarif/sarif-2.1.2'; + +describe('SarifConverter21', () => { + describe('convert', () => { + const stubConverterProperties: Sarif.Run['conversion'] = { + tool: { + driver: { + name: 'stub_converter_property', + }, + }, + }; + const stubToolProperties: Sarif.Run['tool'] = { + driver: { + name: 'stub_tool_property', + }, + }; + const stubInvocations: Sarif.Invocation[] = [ + { commandLine: 'stub_invocation' }, + ]; + const stubTimestamp: string = 'stub_timestamp'; + const stubTargetPageUrl: string = 'stub_url'; + const stubTargetPageTitle: string = 'stub_title'; + const stubEnvironmentData: EnvironmentData = { + timestamp: stubTimestamp, + targetPageUrl: stubTargetPageUrl, + targetPageTitle: stubTargetPageTitle, + }; + const converterPropertyProviderStub: () => Sarif.Run['conversion'] = () => { + return {} as Sarif.Run['conversion']; + }; + const axeToolPropertyProviderStub: () => Sarif.Run['tool'] = () => { + return {} as Sarif.Run['tool']; + }; + const invocationProviderStub: () => Sarif.Invocation[] = () => { + return stubInvocations; + }; + + it('outputs a sarif log whose run uses the axeToolPropertyProvider to populate the tool property', () => { + const axeToolPropertyProviderMock: IMock< + () => Sarif.Run['tool'] + > = Mock.ofInstance(getAxeToolProperties21); + axeToolPropertyProviderMock + .setup(ap => ap()) + .returns(() => stubToolProperties) + .verifiable(Times.once()); + + const irrelevantResults: DecoratedAxeResults = {} as DecoratedAxeResults; + const irrelevantOptions: ConverterOptions = {}; + + const testSubject = new SarifConverter21( + converterPropertyProviderStub, + axeToolPropertyProviderMock.object, + invocationProviderStub, + ); + + const actualResults = testSubject.convert( + irrelevantResults, + irrelevantOptions, + ); + + axeToolPropertyProviderMock.verifyAll(); + expect(actualResults).toHaveProperty('runs'); + expect(actualResults.runs[0]).toHaveProperty( + 'tool', + stubToolProperties, + ); + }); + + it('outputs a sarif log whose run uses the invocationsProvider to populate the invocations property', () => { + const stubResults: DecoratedAxeResults = { + timestamp: stubTimestamp, + targetPageUrl: stubTargetPageUrl, + targetPageTitle: stubTargetPageTitle, + passes: [], + violations: [], + inapplicable: [], + incomplete: [], + }; + const irrelevantOptions: ConverterOptions = {}; + + const invocationProviderMock: IMock< + (environmentData: EnvironmentData) => Sarif.Invocation[] + > = Mock.ofInstance(getInvocations); + invocationProviderMock + .setup(ip => + ip(It.isObjectWith(stubEnvironmentData)), + ) + .returns(() => stubInvocations) + .verifiable(Times.once()); + + const testSubject = new SarifConverter21( + converterPropertyProviderStub, + axeToolPropertyProviderStub, + invocationProviderMock.object, + ); + + const actualResults = testSubject.convert( + stubResults, + irrelevantOptions, + ); + + invocationProviderMock.verifyAll(); + expect(actualResults).toHaveProperty('runs'); + expect(actualResults.runs[0]).toHaveProperty( + 'invocations', + stubInvocations, + ); + }); + + it('outputs a sarif log whose run uses the converterPropertyProvider to populate the conversion property', () => { + const converterPropertyProviderMock: IMock< + () => Sarif.Run['conversion'] + > = Mock.ofInstance(getConverterProperties); + converterPropertyProviderMock + .setup(cp => cp()) + .returns(() => stubConverterProperties) + .verifiable(Times.once()); + + const irrelevantResults: DecoratedAxeResults = {} as DecoratedAxeResults; + const irrelevantOptions: ConverterOptions = {}; + + const testSubject = new SarifConverter21( + converterPropertyProviderMock.object, + axeToolPropertyProviderStub, + invocationProviderStub, + ); + + const actualResults = testSubject.convert( + irrelevantResults, + irrelevantOptions, + ); + + converterPropertyProviderMock.verifyAll(); + expect(actualResults).toHaveProperty('runs'); + expect(actualResults.runs[0]).toHaveProperty( + 'conversion', + stubConverterProperties, + ); + }); + }); +}); diff --git a/src/sarif-converter-21.ts b/src/sarif-converter-21.ts new file mode 100644 index 00000000..fcf7b612 --- /dev/null +++ b/src/sarif-converter-21.ts @@ -0,0 +1,338 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +import * as Axe from 'axe-core'; +import { getAxeToolProperties21 } from './axe-tool-property-provider-21'; +import { ConverterOptions } from './converter-options'; +import { getConverterProperties } from './converter-property-provider'; +import { + DecoratedAxeResult, + DecoratedAxeResults, +} from './decorated-axe-results'; +import { DictionaryStringTo } from './dictionary-types'; +import { EnvironmentData } from './environment-data'; +import { getEnvironmentDataFromResults } from './environment-data-provider'; +import { getInvocations21 } from './invocation-provider-21'; +import * as CustomSarif from './sarif/custom-sarif-types-21'; +import * as Sarif from './sarif/sarif-2.1.2'; +import { SarifLog21 } from './sarif/sarif-log-21'; +import { isNotEmpty } from './string-utils'; + +export function defaultSarifConverter21(): SarifConverter21 { + return new SarifConverter21( + getConverterProperties, + getAxeToolProperties21, + getInvocations21, + ); +} +export class SarifConverter21 { + public constructor( + private getConverterToolProperties: () => Sarif.Run['conversion'], + private getAxeProperties: () => Sarif.Run['tool'], + private invocationConverter: ( + environmentData: EnvironmentData, + ) => Sarif.Invocation[], + ) {} + + public convert( + results: DecoratedAxeResults, + options: ConverterOptions, + ): SarifLog21 { + return { + version: CustomSarif.SarifLogVersion21.v21, + runs: [this.convertRun(results, options)], + }; + } + + private convertRun( + results: DecoratedAxeResults, + options: ConverterOptions, + ): Sarif.Run { + const files: DictionaryStringTo = {}; + files[results.targetPageUrl] = { + mimeType: 'text/html', + properties: { + tags: ['target'], + title: results.targetPageTitle, + }, + }; + + let properties: DictionaryStringTo = {}; + + if (options && options.scanName !== undefined) { + properties = { + scanName: options.scanName, + }; + } + + const run: Sarif.Run = { + conversion: this.getConverterToolProperties(), + tool: this.getAxeProperties(), + invocations: this.invocationConverter( + getEnvironmentDataFromResults(results), + ), + files: files, + results: this.convertResults(results, properties), + resources: { + rules: this.convertResultsToRules(results), + }, + properties: {}, + }; + + if (options && options.testCaseId !== undefined) { + run.properties!.testCaseId = options.testCaseId; + } + + if (options && options.scanId !== undefined) { + run.logicalId = options.scanId; + } + + return run; + } + + private convertResults( + results: DecoratedAxeResults, + properties: DictionaryStringTo, + ): Sarif.Result[] { + const resultArray: Sarif.Result[] = []; + + this.convertRuleResults( + resultArray, + results.violations, + CustomSarif.Result.level.error, + results.targetPageUrl, + properties, + ); + this.convertRuleResults( + resultArray, + results.passes, + CustomSarif.Result.level.pass, + results.targetPageUrl, + properties, + ); + this.convertRuleResults( + resultArray, + results.incomplete, + CustomSarif.Result.level.open, + results.targetPageUrl, + properties, + ); + this.convertRuleResultsWithoutNodes( + resultArray, + results.inapplicable, + CustomSarif.Result.level.notApplicable, + properties, + ); + + return resultArray; + } + + private convertRuleResults( + resultArray: Sarif.Result[], + ruleResults: DecoratedAxeResult[], + level: CustomSarif.Result.level, + targetPageUrl: string, + properties: DictionaryStringTo, + ): void { + if (ruleResults) { + for (const ruleResult of ruleResults) { + this.convertRuleResult( + resultArray, + ruleResult, + level, + targetPageUrl, + properties, + ); + } + } + } + + private convertRuleResult( + resultArray: Sarif.Result[], + ruleResult: DecoratedAxeResult, + level: CustomSarif.Result.level, + targetPageUrl: string, + properties: DictionaryStringTo, + ): void { + const partialFingerprints: DictionaryStringTo< + string + > = this.getPartialFingerprintsFromRule(ruleResult); + + for (const node of ruleResult.nodes) { + const selector = node.target.join(';'); + resultArray.push({ + ruleId: ruleResult.id, + level: level, + message: this.convertMessage(node, level), + locations: [ + { + physicalLocation: { + fileLocation: { + uri: targetPageUrl, + }, + }, + fullyQualifiedLogicalName: selector, + annotations: [ + { + snippet: { + text: node.html, + }, + }, + ], + }, + ], + properties: { + ...properties, + tags: ['Accessibility'], + }, + partialFingerprints: { + fullyQualifiedLogicalName: selector, + ...partialFingerprints, + }, + }); + } + } + + private getPartialFingerprintsFromRule( + ruleResult: DecoratedAxeResult, + ): DictionaryStringTo { + return { + ruleId: ruleResult.id, + }; + } + + private convertMessage( + node: Axe.NodeResult, + level: CustomSarif.Result.level, + ): CustomSarif.Message { + const textArray: string[] = []; + const richTextArray: string[] = []; + + if (level === CustomSarif.Result.level.error) { + const allAndNone = node.all.concat(node.none); + this.convertMessageChecks( + 'Fix all of the following:', + allAndNone, + textArray, + richTextArray, + ); + this.convertMessageChecks( + 'Fix any of the following:', + node.any, + textArray, + richTextArray, + ); + } else { + const allNodes = node.all.concat(node.none).concat(node.any); + this.convertMessageChecks( + 'The following tests passed:', + allNodes, + textArray, + richTextArray, + ); + } + + return { + text: textArray.join(' '), + richText: richTextArray.join('\n\n'), + }; + } + + private convertMessageChecks( + heading: string, + checkResults: Axe.CheckResult[], + textArray: string[], + richTextArray: string[], + ): void { + if (checkResults.length > 0) { + const textLines: string[] = []; + const richTextLines: string[] = []; + + textLines.push(heading); + richTextLines.push(this.escapeForMarkdown(heading)); + + for (const checkResult of checkResults) { + const message = isNotEmpty(checkResult.message) + ? checkResult.message + : checkResult.id; + + textLines.push(message + '.'); + richTextLines.push('- ' + this.escapeForMarkdown(message)); + } + + textArray.push(textLines.join(' ')); + richTextArray.push(richTextLines.join('\n')); + } + } + + private escapeForMarkdown(s: string): string { + return s ? s.replace(/, + ): void { + if (ruleResults) { + for (const ruleResult of ruleResults) { + const partialFingerprints = this.getPartialFingerprintsFromRule( + ruleResult, + ); + resultArray.push({ + ruleId: ruleResult.id, + level: level, + properties: { + ...properties, + tags: ['Accessibility'], + }, + partialFingerprints: partialFingerprints, + }); + } + } + } + + private convertResultsToRules( + results: DecoratedAxeResults, + ): DictionaryStringTo { + const rulesDictionary: DictionaryStringTo = {}; + + this.convertRuleResultsToRules(rulesDictionary, results.violations); + this.convertRuleResultsToRules(rulesDictionary, results.passes); + this.convertRuleResultsToRules(rulesDictionary, results.inapplicable); + this.convertRuleResultsToRules(rulesDictionary, results.incomplete); + + return rulesDictionary; + } + + private convertRuleResultsToRules( + rulesDictionary: DictionaryStringTo, + ruleResults: DecoratedAxeResult[], + ): void { + if (ruleResults) { + for (const ruleResult of ruleResults) { + this.convertRuleResultToRule(rulesDictionary, ruleResult); + } + } + } + + private convertRuleResultToRule( + rulesDictionary: DictionaryStringTo, + ruleResult: DecoratedAxeResult, + ): void { + if (!rulesDictionary.hasOwnProperty(ruleResult.id)) { + const rule: Sarif.Rule = { + id: ruleResult.id, + name: { + text: ruleResult.help, + }, + fullDescription: { + text: ruleResult.description, + }, + helpUri: ruleResult.helpUrl, + properties: {}, + }; + rulesDictionary[ruleResult.id] = rule; + } + } +} diff --git a/src/sarif/custom-sarif-types-21.ts b/src/sarif/custom-sarif-types-21.ts new file mode 100644 index 00000000..f8c67276 --- /dev/null +++ b/src/sarif/custom-sarif-types-21.ts @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +export const enum SarifLogVersion21 { + v21 = '2.1.2', +} + +export namespace Result { + export const enum level { + notApplicable = 'notApplicable', + pass = 'pass', + note = 'note', + warning = 'warning', + error = 'error', + open = 'open', + } +} + +/** + * Encapsulates a message intended to be read by the end user. + */ +export interface Message { + /** + * A plain text message string. + */ + text?: string; + + /** + * The resource id for a plain text message string. + */ + messageId?: string; + + /** + * A rich text message string. + */ + richText?: string; + + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; +} diff --git a/src/sarif/sarif-2.1.2.ts b/src/sarif/sarif-2.1.2.ts new file mode 100644 index 00000000..510187e6 --- /dev/null +++ b/src/sarif/sarif-2.1.2.ts @@ -0,0 +1,3326 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +/* tslint:disable */ +/** + * This file was automatically generated by json-schema-to-typescript. + * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, + * and run json-schema-to-typescript to regenerate this file. + */ + +/** + * Static Analysis Results Format (SARIF) Version 2.1.2 JSON Schema: a standard format for the output of static analysis tools. + */ +export interface StaticAnalysisResultsFormatSarifVersion212JsonSchema { + /** + * The URI of the JSON schema corresponding to the version. + */ + $schema?: string; + /** + * The SARIF format version of this log file. + */ + version: '2.1.2'; + /** + * The set of runs contained in this log file. + */ + runs: Run[]; +} +/** + * Describes a single run of an analysis tool, and contains the output of that run. + */ +export interface Run { + /** + * Information about the tool or tool pipeline that generated the results in this run. A run can only contain results produced by a single tool or tool pipeline. A run can aggregate results from multiple log files, as long as context around the tool run (tool command-line arguments and the like) is identical for all aggregated files. + */ + tool: { + driver: { + /** + * The name of the tool. + */ + name: string; + /** + * The name of the tool along with its version and any other useful identifying information, such as its locale. + */ + fullName?: string; + /** + * A short description about the tool. + */ + shortDescription?: { + /** + * The text for the short description about the tool. + */ + text?: string; + }; + /** + * The tool version, in whatever format the tool natively provides. + */ + version?: string; + /** + * The tool version in the format specified by Semantic Versioning 2.0. + */ + semanticVersion?: string; + /** + * The binary version of the tool's primary executable file (for operating systems such as Windows that provide that information). + */ + fileVersion?: string; + /** + * The absolute URI from which more information about the tool can be obtained. + */ + informationUri?: string; + /** + * The absolute URI from which the tool can be downloaded. + */ + downloadUri?: string; + /** + * A version that uniquely identifies the SARIF logging component that generated this file, if it is versioned separately from the tool. + */ + sarifLoggerVersion?: string; + /** + * The tool language (expressed as an ISO 649 two-letter lowercase culture code) and region (expressed as an ISO 3166 two-letter uppercase subculture code associated with a country or region). + */ + language?: string; + /** + * Key/value pairs that provide additional information about the tool. + */ + properties?: { + /** + * A set of distinct strings that provide additional information. + */ + tags?: string[]; + [k: string]: any; + }; + supportedTaxonomies?: Taxonomy[]; + }; + }; + /** + * Describes the invocation of the analysis tool. + */ + invocations?: Invocation[]; + /** + * A conversion object that describes how a converter transformed an analysis tool's native output format into the SARIF format. + */ + conversion?: { + /** + * A tool object that describes the converter. + */ + tool: { + driver: { + /** + * The name of the tool. + */ + name: string; + /** + * The name of the tool along with its version and any other useful identifying information, such as its locale. + */ + fullName?: string; + /** + * The tool version, in whatever format the tool natively provides. + */ + version?: string; + /** + * The tool version in the format specified by Semantic Versioning 2.0. + */ + semanticVersion?: string; + /** + * The absolute URI from which more information about the tool can be obtained. + */ + informationUri?: string; + /** + * The binary version of the tool's primary executable file (for operating systems such as Windows that provide that information). + */ + fileVersion?: string; + /** + * The absolute URI from which the tool can be downloaded. + */ + downloadUri?: string; + /** + * A version that uniquely identifies the SARIF logging component that generated this file, if it is versioned separately from the tool. + */ + sarifLoggerVersion?: string; + /** + * The tool language (expressed as an ISO 649 two-letter lowercase culture code) and region (expressed as an ISO 3166 two-letter uppercase subculture code associated with a country or region). + */ + language?: string; + /** + * Key/value pairs that provide additional information about the tool. + */ + properties?: { + /** + * A set of distinct strings that provide additional information. + */ + tags?: string[]; + [k: string]: any; + }; + }; + }; + /** + * An invocation object that describes the invocation of the converter. + */ + invocation?: { + /** + * The command line used to invoke the tool. + */ + commandLine?: string; + /** + * An array of strings, containing in order the command line arguments passed to the tool from the operating system. + */ + arguments?: string[]; + /** + * The locations of any response files specified on the tool's command line. + */ + responseFiles?: FileLocation[]; + /** + * A set of files relevant to the invocation of the tool. + */ + attachments?: Attachment[]; + /** + * The date and time at which the run started. See "Date/time properties" in the SARIF spec for the required format. + */ + startTime?: string; + /** + * The date and time at which the run ended. See "Date/time properties" in the SARIF spec for the required format. + */ + endTime?: string; + /** + * The process exit code. + */ + exitCode?: number; + /** + * A list of runtime conditions detected by the tool in the course of the analysis. + */ + toolNotifications?: Notification[]; + /** + * A list of conditions detected by the tool that are relevant to the tool's configuration. + */ + configurationNotifications?: Notification[]; + /** + * The reason for the process exit. + */ + exitCodeDescription?: string; + /** + * The name of the signal that caused the process to exit. + */ + exitSignalName?: string; + /** + * The numeric value of the signal that caused the process to exit. + */ + exitSignalNumber?: number; + /** + * The reason given by the operating system that the process failed to start. + */ + processStartFailureMessage?: string; + /** + * A value indicating whether the tool's execution completed successfully. + */ + toolExecutionSuccessful?: boolean; + /** + * The machine that hosted the analysis tool run. + */ + machine?: string; + /** + * The account that ran the analysis tool. + */ + account?: string; + /** + * The process id for the analysis tool run. + */ + processId?: number; + /** + * An absolute URI specifying the location of the analysis tool's executable. + */ + executableLocation?: { + /** + * A string containing a valid relative or absolute URI. + */ + uri: string; + /** + * A string which indirectly specifies the absolute URI with respect to which a relative URI in the "uri" property is interpreted. + */ + uriBaseId?: string; + }; + /** + * The working directory for the analysis rool run. + */ + workingDirectory?: { + /** + * A string containing a valid relative or absolute URI. + */ + uri: string; + /** + * A string which indirectly specifies the absolute URI with respect to which a relative URI in the "uri" property is interpreted. + */ + uriBaseId?: string; + }; + /** + * The environment variables associated with the analysis tool process, expressed as key/value pairs. + */ + environmentVariables?: { + [k: string]: any; + }; + /** + * A file containing the standard input stream to the process that was invoked. + */ + stdin?: { + /** + * A string containing a valid relative or absolute URI. + */ + uri: string; + /** + * A string which indirectly specifies the absolute URI with respect to which a relative URI in the "uri" property is interpreted. + */ + uriBaseId?: string; + }; + /** + * A file containing the standard output stream from the process that was invoked. + */ + stdout?: { + /** + * A string containing a valid relative or absolute URI. + */ + uri: string; + /** + * A string which indirectly specifies the absolute URI with respect to which a relative URI in the "uri" property is interpreted. + */ + uriBaseId?: string; + }; + /** + * A file containing the standard error stream from the process that was invoked. + */ + stderr?: { + /** + * A string containing a valid relative or absolute URI. + */ + uri: string; + /** + * A string which indirectly specifies the absolute URI with respect to which a relative URI in the "uri" property is interpreted. + */ + uriBaseId?: string; + }; + /** + * A file containing the interleaved standard output and standard error stream from the process that was invoked. + */ + stdoutStderr?: { + /** + * A string containing a valid relative or absolute URI. + */ + uri: string; + /** + * A string which indirectly specifies the absolute URI with respect to which a relative URI in the "uri" property is interpreted. + */ + uriBaseId?: string; + }; + /** + * Key/value pairs that provide additional information about the invocation. + */ + properties?: { + /** + * A set of distinct strings that provide additional information. + */ + tags?: string[]; + [k: string]: any; + }; + }; + /** + * The locations of the analysis tool's per-run log files. + */ + analysisToolLogFiles?: FileLocation[]; + }; + /** + * Specifies the revision in version control of the files that were scanned. + */ + versionControlProvenance?: VersionControlDetails[]; + /** + * The absolute URI specified by each uriBaseId symbol on the machine where the tool originally ran. + */ + originalUriBaseIds?: { + [k: string]: string; + }; + /** + * A dictionary, each of whose keys is a URI and each of whose values is a file object. + */ + files?: { + [k: string]: File; + }; + /** + * A dictionary, each of whose keys specifies a logical location such as a namespace, type or function. + */ + logicalLocations?: { + [k: string]: LogicalLocation; + }; + /** + * An array of one or more unique 'graph' objects. + */ + graphs?: Graph[]; + /** + * The set of results contained in an SARIF log. The results array can be omitted when a run is solely exporting rules metadata. It must be present (but may be empty) in the event that a log file represents an actual scan. + */ + results?: Result[]; + /** + * Items that can be localized, such as message strings and rule metadata. + */ + resources?: { + /** + * A dictionary, each of whose keys is a resource identifier and each of whose values is a localized string. + */ + messageStrings?: { + [k: string]: string; + }; + /** + * A dictionary, each of whose keys is a string and each of whose values is a 'rule' object, that describe all rules associated with an analysis tool or a specific run of an analysis tool. + */ + rules?: { + [k: string]: Rule; + }; + [k: string]: any; + }; + /** + * A stable, unique identifier for the run, in the form of a GUID. + */ + instanceGuid?: string; + /** + * A stable, unique identifier for the equivalence class of logically identical results to which this run belongs, in the form of a GUID. + */ + correlationGuid?: string; + /** + * A logical identifier for a run, for example, 'nightly Clang analyzer run'. Multiple runs of the same type can have the same logical id. + */ + logicalId?: string; + /** + * A description of the run. + */ + description?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + /** + * A global identifier that allows the run to be correlated with other artifacts produced by a larger automation process. + */ + automationLogicalId?: string; + /** + * The 'instanceGuid' property of a previous SARIF 'run' that comprises the baseline that was used to compute result 'baselineState' properties for the run. + */ + baselineInstanceGuid?: string; + /** + * The hardware architecture for which the run was targeted. + */ + architecture?: string; + /** + * The MIME type of all rich text message properties in the run. Default: "text/markdown;variant=GFM" + */ + richMessageMimeType?: string; + /** + * The string used to replace sensitive information in a redaction-aware property. + */ + redactionToken?: string; + /** + * Specifies the default encoding for any file object that refers to a text file. + */ + defaultFileEncoding?: string; + /** + * Specifies the unit in which the tool measures columns. + */ + columnKind?: 'utf16CodeUnits' | 'unicodeCodePoints'; + /** + * Key/value pairs that provide additional information about the run. + */ + properties?: { + /** + * A set of distinct strings that provide additional information about the run. + */ + tags?: string[]; + [k: string]: any; + }; +} +export interface Taxonomy { + name?: string; + index?: number; + guid?: string; +} + +/** + * The runtime environment of the analysis tool run. + */ +export interface Invocation { + /** + * The command line used to invoke the tool. + */ + commandLine?: string; + /** + * An array of strings, containing in order the command line arguments passed to the tool from the operating system. + */ + arguments?: string[]; + /** + * The locations of any response files specified on the tool's command line. + */ + responseFiles?: FileLocation[]; + /** + * A set of files relevant to the invocation of the tool. + */ + attachments?: Attachment[]; + /** + * The date and time at which the run started. See "Date/time properties" in the SARIF spec for the required format. + */ + startTimeUtc?: string; + /** + * The date and time at which the run ended. See "Date/time properties" in the SARIF spec for the required format. + */ + endTimeUtc?: string; + /** + * A value indicating whether the tool's execution completed successfully. + */ + executionSuccessful?: boolean; + /** + * The process exit code. + */ + exitCode?: number; + /** + * A list of runtime conditions detected by the tool in the course of the analysis. + */ + toolNotifications?: Notification[]; + /** + * A list of conditions detected by the tool that are relevant to the tool's configuration. + */ + configurationNotifications?: Notification[]; + /** + * The reason for the process exit. + */ + exitCodeDescription?: string; + /** + * The name of the signal that caused the process to exit. + */ + exitSignalName?: string; + /** + * The numeric value of the signal that caused the process to exit. + */ + exitSignalNumber?: number; + /** + * The reason given by the operating system that the process failed to start. + */ + processStartFailureMessage?: string; + /** + * The machine that hosted the analysis tool run. + */ + machine?: string; + /** + * The account that ran the analysis tool. + */ + account?: string; + /** + * The process id for the analysis tool run. + */ + processId?: number; + /** + * An absolute URI specifying the location of the analysis tool's executable. + */ + executableLocation?: { + /** + * A string containing a valid relative or absolute URI. + */ + uri: string; + /** + * A string which indirectly specifies the absolute URI with respect to which a relative URI in the "uri" property is interpreted. + */ + uriBaseId?: string; + }; + /** + * The working directory for the analysis rool run. + */ + workingDirectory?: { + /** + * A string containing a valid relative or absolute URI. + */ + uri: string; + /** + * A string which indirectly specifies the absolute URI with respect to which a relative URI in the "uri" property is interpreted. + */ + uriBaseId?: string; + }; + /** + * The environment variables associated with the analysis tool process, expressed as key/value pairs. + */ + environmentVariables?: { + [k: string]: any; + }; + /** + * A file containing the standard input stream to the process that was invoked. + */ + stdin?: { + /** + * A string containing a valid relative or absolute URI. + */ + uri: string; + /** + * A string which indirectly specifies the absolute URI with respect to which a relative URI in the "uri" property is interpreted. + */ + uriBaseId?: string; + }; + /** + * A file containing the standard output stream from the process that was invoked. + */ + stdout?: { + /** + * A string containing a valid relative or absolute URI. + */ + uri: string; + /** + * A string which indirectly specifies the absolute URI with respect to which a relative URI in the "uri" property is interpreted. + */ + uriBaseId?: string; + }; + /** + * A file containing the standard error stream from the process that was invoked. + */ + stderr?: { + /** + * A string containing a valid relative or absolute URI. + */ + uri: string; + /** + * A string which indirectly specifies the absolute URI with respect to which a relative URI in the "uri" property is interpreted. + */ + uriBaseId?: string; + }; + /** + * A file containing the interleaved standard output and standard error stream from the process that was invoked. + */ + stdoutStderr?: { + /** + * A string containing a valid relative or absolute URI. + */ + uri: string; + /** + * A string which indirectly specifies the absolute URI with respect to which a relative URI in the "uri" property is interpreted. + */ + uriBaseId?: string; + }; + /** + * Key/value pairs that provide additional information about the invocation. + */ + properties?: { + /** + * A set of distinct strings that provide additional information. + */ + tags?: string[]; + [k: string]: any; + }; +} +/** + * Specifies the location of a file. + */ +export interface FileLocation { + /** + * A string containing a valid relative or absolute URI. + */ + uri: string; + /** + * A string which indirectly specifies the absolute URI with respect to which a relative URI in the "uri" property is interpreted. + */ + uriBaseId?: string; +} +/** + * A file relevant to a tool invocation or to a result. + */ +export interface Attachment { + /** + * A message describing the role played by the attachment. + */ + description?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + /** + * The location of the attachment. + */ + fileLocation: { + /** + * A string containing a valid relative or absolute URI. + */ + uri: string; + /** + * A string which indirectly specifies the absolute URI with respect to which a relative URI in the "uri" property is interpreted. + */ + uriBaseId?: string; + }; + /** + * An array of regions of interest within the attachment. + */ + regions?: Region[]; + /** + * An array of rectangles specifying areas of interest within the image. + */ + rectangles?: Rectangle[]; +} +/** + * A region within a file where a result was detected. + */ +export interface Region { + /** + * The line number of the first character in the region. + */ + startLine?: number; + /** + * The column number of the first character in the region. + */ + startColumn?: number; + /** + * The line number of the last character in the region. + */ + endLine?: number; + /** + * The column number of the character following the end of the region. + */ + endColumn?: number; + /** + * The zero-based offset from the beginning of the file of the first character in the region. + */ + charOffset?: number; + /** + * The length of the region in characters. + */ + charLength?: number; + /** + * The zero-based offset from the beginning of the file of the first byte in the region. + */ + byteOffset?: number; + /** + * The length of the region in bytes. + */ + byteLength?: number; + /** + * The portion of the file contents within the specified region. + */ + snippet?: { + /** + * UTF-8-encoded content from a text file. + */ + text?: string; + /** + * MIME Base64-encoded content from a binary file, or from a text file in its original encoding. + */ + binary?: string; + }; + /** + * A message relevant to the region. + */ + message?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; +} +/** + * An area within an image. + */ +export interface Rectangle { + /** + * The Y coordinate of the top edge of the rectangle, measured in the image's natural units. + */ + top?: number; + /** + * The X coordinate of the left edge of the rectangle, measured in the image's natural units. + */ + left?: number; + /** + * The Y coordinate of the bottom edge of the rectangle, measured in the image's natural units. + */ + bottom?: number; + /** + * The X coordinate of the right edge of the rectangle, measured in the image's natural units. + */ + right?: number; + /** + * A message relevant to the rectangle. + */ + message?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; +} +/** + * Describes a condition relevant to the tool itself, as opposed to being relevant to a target being analyzed by the tool. + */ +export interface Notification { + /** + * An identifier for the condition that was encountered. + */ + id?: string; + /** + * The stable, unique identifier of the rule (if any) to which this notification is relevant. This member can be used to retrieve rule metadata from the rules dictionary, if it exists. + */ + ruleId?: string; + /** + * The file and region relevant to this notification. + */ + physicalLocation?: { + /** + * Value that distinguishes this physical location from all other physical locations in this run object. + */ + id?: number; + /** + * The location of the file. + */ + fileLocation: { + /** + * A string containing a valid relative or absolute URI. + */ + uri: string; + /** + * A string which indirectly specifies the absolute URI with respect to which a relative URI in the "uri" property is interpreted. + */ + uriBaseId?: string; + }; + /** + * Specifies a portion of the file. + */ + region?: { + /** + * The line number of the first character in the region. + */ + startLine?: number; + /** + * The column number of the first character in the region. + */ + startColumn?: number; + /** + * The line number of the last character in the region. + */ + endLine?: number; + /** + * The column number of the character following the end of the region. + */ + endColumn?: number; + /** + * The zero-based offset from the beginning of the file of the first character in the region. + */ + charOffset?: number; + /** + * The length of the region in characters. + */ + charLength?: number; + /** + * The zero-based offset from the beginning of the file of the first byte in the region. + */ + byteOffset?: number; + /** + * The length of the region in bytes. + */ + byteLength?: number; + /** + * The portion of the file contents within the specified region. + */ + snippet?: { + /** + * UTF-8-encoded content from a text file. + */ + text?: string; + /** + * MIME Base64-encoded content from a binary file, or from a text file in its original encoding. + */ + binary?: string; + }; + /** + * A message relevant to the region. + */ + message?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + }; + /** + * Specifies a portion of the file that encloses the region. Allows a viewer to display additional context around the region. + */ + contextRegion?: { + /** + * The line number of the first character in the region. + */ + startLine?: number; + /** + * The column number of the first character in the region. + */ + startColumn?: number; + /** + * The line number of the last character in the region. + */ + endLine?: number; + /** + * The column number of the character following the end of the region. + */ + endColumn?: number; + /** + * The zero-based offset from the beginning of the file of the first character in the region. + */ + charOffset?: number; + /** + * The length of the region in characters. + */ + charLength?: number; + /** + * The zero-based offset from the beginning of the file of the first byte in the region. + */ + byteOffset?: number; + /** + * The length of the region in bytes. + */ + byteLength?: number; + /** + * The portion of the file contents within the specified region. + */ + snippet?: { + /** + * UTF-8-encoded content from a text file. + */ + text?: string; + /** + * MIME Base64-encoded content from a binary file, or from a text file in its original encoding. + */ + binary?: string; + }; + /** + * A message relevant to the region. + */ + message?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + }; + }; + /** + * A message that describes the condition that was encountered. + */ + message: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + /** + * A value specifying the severity level of the notification. + */ + level?: 'note' | 'warning' | 'error'; + /** + * The thread identifier of the code that generated the notification. + */ + threadId?: number; + /** + * The date and time at which the analysis tool generated the notification. + */ + time?: string; + /** + * The runtime exception, if any, relevant to this notification. + */ + exception?: { + /** + * A string that identifies the kind of exception, for example, the fully qualified type name of an object that was thrown, or the symbolic name of a signal. + */ + kind?: string; + /** + * A plain text message that describes the exception. + */ + message?: string; + /** + * The sequence of function calls leading to the exception. + */ + stack?: { + /** + * A message relevant to this call stack. + */ + message?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + /** + * An array of stack frames that represent a sequence of calls, rendered in reverse chronological order, that comprise the call stack. + */ + frames: StackFrame[]; + /** + * Key/value pairs that provide additional information about the stack. + */ + properties?: { + /** + * A set of distinct strings that provide additional information. + */ + tags?: string[]; + [k: string]: any; + }; + }; + /** + * An array of exception objects each of which is considered a cause of this exception. + */ + innerExceptions?: Exception[]; + [k: string]: any; + }; + /** + * Key/value pairs that provide additional information about the notification. + */ + properties?: { + /** + * A set of distinct strings that provide additional information. + */ + tags?: string[]; + [k: string]: any; + }; +} +/** + * A function call within a stack trace. + */ +export interface StackFrame { + /** + * The location to which this stack frame refers. + */ + location?: { + /** + * Identifies the file and region. + */ + physicalLocation?: { + /** + * Value that distinguishes this physical location from all other physical locations in this run object. + */ + id?: number; + /** + * The location of the file. + */ + fileLocation: { + /** + * A string containing a valid relative or absolute URI. + */ + uri: string; + /** + * A string which indirectly specifies the absolute URI with respect to which a relative URI in the "uri" property is interpreted. + */ + uriBaseId?: string; + }; + /** + * Specifies a portion of the file. + */ + region?: { + /** + * The line number of the first character in the region. + */ + startLine?: number; + /** + * The column number of the first character in the region. + */ + startColumn?: number; + /** + * The line number of the last character in the region. + */ + endLine?: number; + /** + * The column number of the character following the end of the region. + */ + endColumn?: number; + /** + * The zero-based offset from the beginning of the file of the first character in the region. + */ + charOffset?: number; + /** + * The length of the region in characters. + */ + charLength?: number; + /** + * The zero-based offset from the beginning of the file of the first byte in the region. + */ + byteOffset?: number; + /** + * The length of the region in bytes. + */ + byteLength?: number; + /** + * The portion of the file contents within the specified region. + */ + snippet?: { + /** + * UTF-8-encoded content from a text file. + */ + text?: string; + /** + * MIME Base64-encoded content from a binary file, or from a text file in its original encoding. + */ + binary?: string; + }; + /** + * A message relevant to the region. + */ + message?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + }; + /** + * Specifies a portion of the file that encloses the region. Allows a viewer to display additional context around the region. + */ + contextRegion?: { + /** + * The line number of the first character in the region. + */ + startLine?: number; + /** + * The column number of the first character in the region. + */ + startColumn?: number; + /** + * The line number of the last character in the region. + */ + endLine?: number; + /** + * The column number of the character following the end of the region. + */ + endColumn?: number; + /** + * The zero-based offset from the beginning of the file of the first character in the region. + */ + charOffset?: number; + /** + * The length of the region in characters. + */ + charLength?: number; + /** + * The zero-based offset from the beginning of the file of the first byte in the region. + */ + byteOffset?: number; + /** + * The length of the region in bytes. + */ + byteLength?: number; + /** + * The portion of the file contents within the specified region. + */ + snippet?: { + /** + * UTF-8-encoded content from a text file. + */ + text?: string; + /** + * MIME Base64-encoded content from a binary file, or from a text file in its original encoding. + */ + binary?: string; + }; + /** + * A message relevant to the region. + */ + message?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + }; + }; + /** + * The human-readable fully qualified name of the logical location. If run.logicalLocations is present, this value matches a property name within that object, from which further information about the logical location can be obtained. + */ + fullyQualifiedLogicalName?: string; + /** + * A message relevant to the location. + */ + message?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + /** + * A set of regions relevant to the location. + */ + annotations?: Region[]; + /** + * Key/value pairs that provide additional information about the location. + */ + properties?: { + /** + * A set of distinct strings that provide additional information. + */ + tags?: string[]; + [k: string]: any; + }; + }; + /** + * The name of the module that contains the code of this stack frame. + */ + module?: string; + /** + * The thread identifier of the stack frame. + */ + threadId?: number; + /** + * The address of the method or function that is executing. + */ + address?: number; + /** + * The offset from the method or function that is executing. + */ + offset?: number; + /** + * The parameters of the call that is executing. + */ + parameters?: string[]; + /** + * Key/value pairs that provide additional information about the stack frame. + */ + properties?: { + /** + * A set of distinct strings that provide additional information. + */ + tags?: string[]; + [k: string]: any; + }; +} +export interface Exception { + /** + * A string that identifies the kind of exception, for example, the fully qualified type name of an object that was thrown, or the symbolic name of a signal. + */ + kind?: string; + /** + * A plain text message that describes the exception. + */ + message?: string; + /** + * The sequence of function calls leading to the exception. + */ + stack?: { + /** + * A message relevant to this call stack. + */ + message?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + /** + * An array of stack frames that represent a sequence of calls, rendered in reverse chronological order, that comprise the call stack. + */ + frames: StackFrame[]; + /** + * Key/value pairs that provide additional information about the stack. + */ + properties?: { + /** + * A set of distinct strings that provide additional information. + */ + tags?: string[]; + [k: string]: any; + }; + }; + /** + * An array of exception objects each of which is considered a cause of this exception. + */ + innerExceptions?: Exception[]; + [k: string]: any; +} +export interface VersionControlDetails { + /** + * The absolute URI of the repository. + */ + uri: string; + /** + * A string that uniquely and permanently identifies the revision within the repository. + */ + revisionId?: string; + /** + * The name of a branch containing the revision. + */ + branch?: string; + /** + * A tag that has been applied to the revision. + */ + tag?: string; + /** + * The date and time at which the revision was created. + */ + timestamp?: string; + /** + * Key/value pairs that provide additional information about the revision. + */ + properties?: { + /** + * A set of distinct strings that provide additional information. + */ + tags?: string[]; + [k: string]: any; + }; +} +/** + * A single file. In some cases, this file might be nested within another file. + */ +export interface File { + /** + * The location of the file. + */ + fileLocation?: { + /** + * A string containing a valid relative or absolute URI. + */ + uri: string; + /** + * A string which indirectly specifies the absolute URI with respect to which a relative URI in the "uri" property is interpreted. + */ + uriBaseId?: string; + }; + /** + * Identifies the key of the immediate parent of the file, if this file is nested. + */ + parentKey?: string; + /** + * The offset in bytes of the file within its containing file. + */ + offset?: number; + /** + * The length of the file in bytes. + */ + length?: number; + /** + * The role or roles played by the file in the analysis. + */ + roles?: ( + | 'analysisTarget' + | 'attachment' + | 'responseFile' + | 'resultFile' + | 'standardStream' + | 'traceFile' + | 'unmodifiedFile' + | 'modifiedFile' + | 'addedFile' + | 'deletedFile' + | 'renamedFile' + | 'uncontrolledFile')[]; + /** + * The MIME type (RFC 2045) of the file. + */ + mimeType?: string; + /** + * The contents of the file. + */ + contents?: { + /** + * UTF-8-encoded content from a text file. + */ + text?: string; + /** + * MIME Base64-encoded content from a binary file, or from a text file in its original encoding. + */ + binary?: string; + }; + /** + * Specifies the encoding for a file object that refers to a text file. + */ + encoding?: string; + /** + * An array of hash objects, each of which specifies a hashed value for the file, along with the name of the hash function used to compute the hash. + */ + hashes?: Hash[]; + /** + * The date and time at which the file was most recently modified. See "Date/time properties" in the SARIF spec for the required format. + */ + lastModifiedTime?: string; + /** + * Key/value pairs that provide additional information about the file. + */ + properties?: { + /** + * A set of distinct strings that provide additional information. + */ + tags?: string[]; + [k: string]: any; + }; +} +/** + * A hash value of some file or collection of files, together with the hash function used to compute the hash. + */ +export interface Hash { + /** + * The hash value of some file or collection of files, computed by the hash function named in the 'algorithm' property. + */ + value: string; + /** + * The name of the hash function used to compute the hash value specified in the 'value' property. + */ + algorithm: string; +} +/** + * A logical location of a construct that produced a result. + */ +export interface LogicalLocation { + /** + * Identifies the construct in which the result occurred. For example, this property might contain the name of a class or a method. + */ + name?: string; + /** + * The human-readable fully qualified name of the logical location. + */ + fullyQualifiedName?: string; + /** + * The machine-readable name for the logical location, such as a mangled function name provided by a C++ compiler that encodes calling convention, return type and other details along with the function name. + */ + decoratedName?: string; + /** + * Identifies the key of the immediate parent of the construct in which the result was detected. For example, this property might point to a logical location that represents the namespace that holds a type. + */ + parentKey?: string; + /** + * The type of construct this logicalLocationComponent refers to. Should be one of 'function', 'member', 'module', 'namespace', 'package', 'parameter', 'resource', 'returnType', 'type', or 'variable', if any of those accurately describe the construct. + */ + kind?: string; +} +/** + * A network of nodes and directed edges that describes some aspect of the structure of the code (for example, a call graph). + */ +export interface Graph { + /** + * A string that uniquely identifies the graph within a run.graphs or result.graphs array. + */ + id: string; + /** + * A description of the graph. + */ + description?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + /** + * An array of node objects representing the nodes of the graph. + */ + nodes: Node[]; + /** + * An array of edge objects representing the edges of the graph. + */ + edges: Edge[]; + /** + * Key/value pairs that provide additional information about the graph. + */ + properties?: { + /** + * A set of distinct strings that provide additional information. + */ + tags?: string[]; + [k: string]: any; + }; +} +/** + * Represents a node in a graph. + */ +export interface Node { + /** + * A string that uniquely identifies the node within its graph. + */ + id: string; + /** + * A short description of the node. + */ + label?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + /** + * A code location associated with the node. + */ + location?: { + /** + * Identifies the file and region. + */ + physicalLocation?: { + /** + * Value that distinguishes this physical location from all other physical locations in this run object. + */ + id?: number; + /** + * The location of the file. + */ + fileLocation: { + /** + * A string containing a valid relative or absolute URI. + */ + uri: string; + /** + * A string which indirectly specifies the absolute URI with respect to which a relative URI in the "uri" property is interpreted. + */ + uriBaseId?: string; + }; + /** + * Specifies a portion of the file. + */ + region?: { + /** + * The line number of the first character in the region. + */ + startLine?: number; + /** + * The column number of the first character in the region. + */ + startColumn?: number; + /** + * The line number of the last character in the region. + */ + endLine?: number; + /** + * The column number of the character following the end of the region. + */ + endColumn?: number; + /** + * The zero-based offset from the beginning of the file of the first character in the region. + */ + charOffset?: number; + /** + * The length of the region in characters. + */ + charLength?: number; + /** + * The zero-based offset from the beginning of the file of the first byte in the region. + */ + byteOffset?: number; + /** + * The length of the region in bytes. + */ + byteLength?: number; + /** + * The portion of the file contents within the specified region. + */ + snippet?: { + /** + * UTF-8-encoded content from a text file. + */ + text?: string; + /** + * MIME Base64-encoded content from a binary file, or from a text file in its original encoding. + */ + binary?: string; + }; + /** + * A message relevant to the region. + */ + message?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + }; + /** + * Specifies a portion of the file that encloses the region. Allows a viewer to display additional context around the region. + */ + contextRegion?: { + /** + * The line number of the first character in the region. + */ + startLine?: number; + /** + * The column number of the first character in the region. + */ + startColumn?: number; + /** + * The line number of the last character in the region. + */ + endLine?: number; + /** + * The column number of the character following the end of the region. + */ + endColumn?: number; + /** + * The zero-based offset from the beginning of the file of the first character in the region. + */ + charOffset?: number; + /** + * The length of the region in characters. + */ + charLength?: number; + /** + * The zero-based offset from the beginning of the file of the first byte in the region. + */ + byteOffset?: number; + /** + * The length of the region in bytes. + */ + byteLength?: number; + /** + * The portion of the file contents within the specified region. + */ + snippet?: { + /** + * UTF-8-encoded content from a text file. + */ + text?: string; + /** + * MIME Base64-encoded content from a binary file, or from a text file in its original encoding. + */ + binary?: string; + }; + /** + * A message relevant to the region. + */ + message?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + }; + }; + /** + * The human-readable fully qualified name of the logical location. If run.logicalLocations is present, this value matches a property name within that object, from which further information about the logical location can be obtained. + */ + fullyQualifiedLogicalName?: string; + /** + * A message relevant to the location. + */ + message?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + /** + * A set of regions relevant to the location. + */ + annotations?: Region[]; + /** + * Key/value pairs that provide additional information about the location. + */ + properties?: { + /** + * A set of distinct strings that provide additional information. + */ + tags?: string[]; + [k: string]: any; + }; + }; + /** + * Array of child nodes. + */ + children?: Node[]; + /** + * Key/value pairs that provide additional information about the node. + */ + properties?: { + /** + * A set of distinct strings that provide additional information. + */ + tags?: string[]; + [k: string]: any; + }; +} +/** + * Represents a directed edge in a graph. + */ +export interface Edge { + /** + * A string that uniquely identifies the edge within its graph. + */ + id: string; + /** + * A short description of the edge. + */ + label?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + /** + * Identifies the source node (the node at which the edge starts). + */ + sourceNodeId: string; + /** + * Identifies the target node (the node at which the edge ends). + */ + targetNodeId: string; + /** + * Key/value pairs that provide additional information about the edge. + */ + properties?: { + /** + * A set of distinct strings that provide additional information. + */ + tags?: string[]; + [k: string]: any; + }; +} +/** + * A result produced by an analysis tool. + */ +export interface Result { + /** + * The stable, unique identifier of the rule (if any) to which this notification is relevant. This member can be used to retrieve rule metadata from the rules dictionary, if it exists. + */ + ruleId?: string; + /** + * A value specifying the severity level of the result. + */ + level?: 'notApplicable' | 'pass' | 'note' | 'warning' | 'error' | 'open'; + /** + * A message that describes the result. The first sentence of the message only will be displayed when visible space is limited. + */ + message?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + /** + * Identifies the file that the analysis tool was instructed to scan. This need not be the same as the file where the result actually occurred. + */ + analysisTarget?: { + /** + * A string containing a valid relative or absolute URI. + */ + uri: string; + /** + * A string which indirectly specifies the absolute URI with respect to which a relative URI in the "uri" property is interpreted. + */ + uriBaseId?: string; + }; + /** + * One or more locations where the result occurred. Specify only one location unless the problem indicated by the result can only be corrected by making a change at every specified location. + */ + locations?: Location[]; + /** + * A stable, unique identifer for the result in the form of a GUID. + */ + instanceGuid?: string; + /** + * A stable, unique identifier for the equivalence class of logically identical results to which this result belongs, in the form of a GUID. + */ + correlationGuid?: string; + /** + * A set of strings that contribute to the stable, unique identity of the result. + */ + partialFingerprints?: { + [k: string]: string; + }; + /** + * A set of strings each of which individually defines a stable, unique identity for the result. + */ + fingerprints?: { + [k: string]: string; + }; + /** + * An array of 'stack' objects relevant to the result. + */ + stacks?: Stack[]; + /** + * An array of 'codeFlow' objects relevant to the result. + */ + codeFlows?: CodeFlow[]; + /** + * An array of one or more unique 'graph' objects. + */ + graphs?: Graph[]; + /** + * An array of one or more unique 'graphTraversal' objects. + */ + graphTraversals?: GraphTraversal[]; + /** + * A set of locations relevant to this result. + */ + relatedLocations?: Location[]; + /** + * A set of flags indicating one or more suppression conditions. + */ + suppressionStates?: ('suppressedInSource' | 'suppressedExternally')[]; + /** + * The state of a result relative to a baseline of a previous run. + */ + baselineState?: 'new' | 'existing' | 'absent'; + /** + * A set of files relevant to the result. + */ + attachments?: Attachment[]; + /** + * The URIs of the work items associated with this result + */ + workItemUris?: string[]; + /** + * An array of physicalLocation objects which specify the portions of an analysis tool's output that a converter transformed into the result object. + */ + conversionProvenance?: PhysicalLocation[]; + /** + * An array of 'fix' objects, each of which represents a proposed fix to the problem indicated by the result. + */ + fixes?: Fix[]; + /** + * Key/value pairs that provide additional information about the result. + */ + properties?: { + /** + * A set of distinct strings that provide additional information. + */ + tags?: string[]; + [k: string]: any; + }; +} +/** + * A location within a programming artifact. + */ +export interface Location { + /** + * Identifies the file and region. + */ + physicalLocation?: { + /** + * Value that distinguishes this physical location from all other physical locations in this run object. + */ + id?: number; + /** + * The location of the file. + */ + fileLocation: { + /** + * A string containing a valid relative or absolute URI. + */ + uri: string; + /** + * A string which indirectly specifies the absolute URI with respect to which a relative URI in the "uri" property is interpreted. + */ + uriBaseId?: string; + }; + /** + * Specifies a portion of the file. + */ + region?: { + /** + * The line number of the first character in the region. + */ + startLine?: number; + /** + * The column number of the first character in the region. + */ + startColumn?: number; + /** + * The line number of the last character in the region. + */ + endLine?: number; + /** + * The column number of the character following the end of the region. + */ + endColumn?: number; + /** + * The zero-based offset from the beginning of the file of the first character in the region. + */ + charOffset?: number; + /** + * The length of the region in characters. + */ + charLength?: number; + /** + * The zero-based offset from the beginning of the file of the first byte in the region. + */ + byteOffset?: number; + /** + * The length of the region in bytes. + */ + byteLength?: number; + /** + * The portion of the file contents within the specified region. + */ + snippet?: { + /** + * UTF-8-encoded content from a text file. + */ + text?: string; + /** + * MIME Base64-encoded content from a binary file, or from a text file in its original encoding. + */ + binary?: string; + }; + /** + * A message relevant to the region. + */ + message?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + }; + /** + * Specifies a portion of the file that encloses the region. Allows a viewer to display additional context around the region. + */ + contextRegion?: { + /** + * The line number of the first character in the region. + */ + startLine?: number; + /** + * The column number of the first character in the region. + */ + startColumn?: number; + /** + * The line number of the last character in the region. + */ + endLine?: number; + /** + * The column number of the character following the end of the region. + */ + endColumn?: number; + /** + * The zero-based offset from the beginning of the file of the first character in the region. + */ + charOffset?: number; + /** + * The length of the region in characters. + */ + charLength?: number; + /** + * The zero-based offset from the beginning of the file of the first byte in the region. + */ + byteOffset?: number; + /** + * The length of the region in bytes. + */ + byteLength?: number; + /** + * The portion of the file contents within the specified region. + */ + snippet?: { + /** + * UTF-8-encoded content from a text file. + */ + text?: string; + /** + * MIME Base64-encoded content from a binary file, or from a text file in its original encoding. + */ + binary?: string; + }; + /** + * A message relevant to the region. + */ + message?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + }; + }; + /** + * The human-readable fully qualified name of the logical location. If run.logicalLocations is present, this value matches a property name within that object, from which further information about the logical location can be obtained. + */ + fullyQualifiedLogicalName?: string; + /** + * A message relevant to the location. + */ + message?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + /** + * A set of regions relevant to the location. + */ + annotations?: Region[]; + /** + * Key/value pairs that provide additional information about the location. + */ + properties?: { + /** + * A set of distinct strings that provide additional information. + */ + tags?: string[]; + [k: string]: any; + }; +} +/** + * A call stack that is relevant to a result. + */ +export interface Stack { + /** + * A message relevant to this call stack. + */ + message?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + /** + * An array of stack frames that represent a sequence of calls, rendered in reverse chronological order, that comprise the call stack. + */ + frames: StackFrame[]; + /** + * Key/value pairs that provide additional information about the stack. + */ + properties?: { + /** + * A set of distinct strings that provide additional information. + */ + tags?: string[]; + [k: string]: any; + }; +} +/** + * A set of threadFlows which together describe a pattern of code execution relevant to detecting a result. + */ +export interface CodeFlow { + /** + * A message relevant to the code flow. + */ + message?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + /** + * An array of one or more unique threadFlow objects, each of which describes the progress of a program through a thread of execution. + */ + threadFlows: ThreadFlow[]; + /** + * Key/value pairs that provide additional information about the code flow. + */ + properties?: { + /** + * A set of distinct strings that provide additional information. + */ + tags?: string[]; + [k: string]: any; + }; +} +export interface ThreadFlow { + /** + * An string that uniquely identifies the threadFlow within the codeFlow in which it occurs. + */ + id?: string; + /** + * A message relevant to the thread flow. + */ + message?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + /** + * A temporally ordered array of 'threadFlowLocation' objects, each of which describes a location visited by the tool in the course of producing the result. + */ + locations: ThreadFlowLocation[]; + /** + * Key/value pairs that provide additional information about the thread flow. + */ + properties?: { + /** + * A set of distinct strings that provide additional information. + */ + tags?: string[]; + [k: string]: any; + }; + [k: string]: any; +} +/** + * A location visited by an analysis tool in the course of simulating or monitoring the execution of a program. + */ +export interface ThreadFlowLocation { + /** + * The 0-based sequence number of the location in the code flow within which it occurs. + */ + step?: number; + /** + * The code location. + */ + location?: { + /** + * Identifies the file and region. + */ + physicalLocation?: { + /** + * Value that distinguishes this physical location from all other physical locations in this run object. + */ + id?: number; + /** + * The location of the file. + */ + fileLocation: { + /** + * A string containing a valid relative or absolute URI. + */ + uri: string; + /** + * A string which indirectly specifies the absolute URI with respect to which a relative URI in the "uri" property is interpreted. + */ + uriBaseId?: string; + }; + /** + * Specifies a portion of the file. + */ + region?: { + /** + * The line number of the first character in the region. + */ + startLine?: number; + /** + * The column number of the first character in the region. + */ + startColumn?: number; + /** + * The line number of the last character in the region. + */ + endLine?: number; + /** + * The column number of the character following the end of the region. + */ + endColumn?: number; + /** + * The zero-based offset from the beginning of the file of the first character in the region. + */ + charOffset?: number; + /** + * The length of the region in characters. + */ + charLength?: number; + /** + * The zero-based offset from the beginning of the file of the first byte in the region. + */ + byteOffset?: number; + /** + * The length of the region in bytes. + */ + byteLength?: number; + /** + * The portion of the file contents within the specified region. + */ + snippet?: { + /** + * UTF-8-encoded content from a text file. + */ + text?: string; + /** + * MIME Base64-encoded content from a binary file, or from a text file in its original encoding. + */ + binary?: string; + }; + /** + * A message relevant to the region. + */ + message?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + }; + /** + * Specifies a portion of the file that encloses the region. Allows a viewer to display additional context around the region. + */ + contextRegion?: { + /** + * The line number of the first character in the region. + */ + startLine?: number; + /** + * The column number of the first character in the region. + */ + startColumn?: number; + /** + * The line number of the last character in the region. + */ + endLine?: number; + /** + * The column number of the character following the end of the region. + */ + endColumn?: number; + /** + * The zero-based offset from the beginning of the file of the first character in the region. + */ + charOffset?: number; + /** + * The length of the region in characters. + */ + charLength?: number; + /** + * The zero-based offset from the beginning of the file of the first byte in the region. + */ + byteOffset?: number; + /** + * The length of the region in bytes. + */ + byteLength?: number; + /** + * The portion of the file contents within the specified region. + */ + snippet?: { + /** + * UTF-8-encoded content from a text file. + */ + text?: string; + /** + * MIME Base64-encoded content from a binary file, or from a text file in its original encoding. + */ + binary?: string; + }; + /** + * A message relevant to the region. + */ + message?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + }; + }; + /** + * The human-readable fully qualified name of the logical location. If run.logicalLocations is present, this value matches a property name within that object, from which further information about the logical location can be obtained. + */ + fullyQualifiedLogicalName?: string; + /** + * A message relevant to the location. + */ + message?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + /** + * A set of regions relevant to the location. + */ + annotations?: Region[]; + /** + * Key/value pairs that provide additional information about the location. + */ + properties?: { + /** + * A set of distinct strings that provide additional information. + */ + tags?: string[]; + [k: string]: any; + }; + }; + /** + * The call stack leading to this location. + */ + stack?: { + /** + * A message relevant to this call stack. + */ + message?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + /** + * An array of stack frames that represent a sequence of calls, rendered in reverse chronological order, that comprise the call stack. + */ + frames: StackFrame[]; + /** + * Key/value pairs that provide additional information about the stack. + */ + properties?: { + /** + * A set of distinct strings that provide additional information. + */ + tags?: string[]; + [k: string]: any; + }; + }; + /** + * A string describing the type of this location. + */ + kind?: string; + /** + * The name of the module that contains the code that is executing. + */ + module?: string; + /** + * A dictionary, each of whose keys specifies a variable or expression, the associated value of which represents the variable or expression value. For an annotation of kind 'continuation', for example, this dictionary might hold the current assumed values of a set of global variables. + */ + state?: { + [k: string]: any; + }; + /** + * An integer representing a containment hierarchy within the thread flow + */ + nestingLevel?: number; + /** + * An integer representing the temporal order in which execution reached this location. + */ + executionOrder?: number; + /** + * The time at which this location was executed. + */ + timestamp?: string; + /** + * Specifies the importance of this location in understanding the code flow in which it occurs. The order from most to least important is "essential", "important", "unimportant". Default: "important". + */ + importance?: 'important' | 'essential' | 'unimportant'; + /** + * Key/value pairs that provide additional information about the code location. + */ + properties?: { + /** + * A set of distinct strings that provide additional information. + */ + tags?: string[]; + [k: string]: any; + }; +} +/** + * Represents a path through a graph. + */ +export interface GraphTraversal { + /** + * A string that uniquely identifies that graph being traversed. + */ + graphId: string; + /** + * A description of this graph traversal. + */ + description?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + /** + * Values of relevant expressions at the start of the graph traversal. + */ + initialState?: { + [k: string]: string; + }; + /** + * The sequences of edges traversed by this graph traversal. + */ + edgeTraversals: EdgeTraversal[]; + /** + * Key/value pairs that provide additional information about the graph traversal. + */ + properties?: { + /** + * A set of distinct strings that provide additional information. + */ + tags?: string[]; + [k: string]: any; + }; +} +/** + * Represents the traversal of a single edge in the course of a graph traversal. + */ +export interface EdgeTraversal { + /** + * Identifies the edge being traversed. + */ + edgeId: string; + /** + * A message to display to the user as the edge is traversed. + */ + message?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + /** + * The values of relevant expressions after the edge has been traversed. + */ + finalState?: { + [k: string]: string; + }; + /** + * The number of edge traversals necessary to return from a nested graph. + */ + stepOverEdgeCount?: number; + /** + * Key/value pairs that provide additional information about the edge traversal. + */ + properties?: { + /** + * A set of distinct strings that provide additional information. + */ + tags?: string[]; + [k: string]: any; + }; +} +/** + * A physical location relevant to a result. Specifies a reference to a programming artifact together with a range of bytes or characters within that artifact. + */ +export interface PhysicalLocation { + /** + * Value that distinguishes this physical location from all other physical locations in this run object. + */ + id?: number; + /** + * The location of the file. + */ + fileLocation: { + /** + * A string containing a valid relative or absolute URI. + */ + uri: string; + /** + * A string which indirectly specifies the absolute URI with respect to which a relative URI in the "uri" property is interpreted. + */ + uriBaseId?: string; + }; + /** + * Specifies a portion of the file. + */ + region?: { + /** + * The line number of the first character in the region. + */ + startLine?: number; + /** + * The column number of the first character in the region. + */ + startColumn?: number; + /** + * The line number of the last character in the region. + */ + endLine?: number; + /** + * The column number of the character following the end of the region. + */ + endColumn?: number; + /** + * The zero-based offset from the beginning of the file of the first character in the region. + */ + charOffset?: number; + /** + * The length of the region in characters. + */ + charLength?: number; + /** + * The zero-based offset from the beginning of the file of the first byte in the region. + */ + byteOffset?: number; + /** + * The length of the region in bytes. + */ + byteLength?: number; + /** + * The portion of the file contents within the specified region. + */ + snippet?: { + /** + * UTF-8-encoded content from a text file. + */ + text?: string; + /** + * MIME Base64-encoded content from a binary file, or from a text file in its original encoding. + */ + binary?: string; + }; + /** + * A message relevant to the region. + */ + message?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + }; + /** + * Specifies a portion of the file that encloses the region. Allows a viewer to display additional context around the region. + */ + contextRegion?: { + /** + * The line number of the first character in the region. + */ + startLine?: number; + /** + * The column number of the first character in the region. + */ + startColumn?: number; + /** + * The line number of the last character in the region. + */ + endLine?: number; + /** + * The column number of the character following the end of the region. + */ + endColumn?: number; + /** + * The zero-based offset from the beginning of the file of the first character in the region. + */ + charOffset?: number; + /** + * The length of the region in characters. + */ + charLength?: number; + /** + * The zero-based offset from the beginning of the file of the first byte in the region. + */ + byteOffset?: number; + /** + * The length of the region in bytes. + */ + byteLength?: number; + /** + * The portion of the file contents within the specified region. + */ + snippet?: { + /** + * UTF-8-encoded content from a text file. + */ + text?: string; + /** + * MIME Base64-encoded content from a binary file, or from a text file in its original encoding. + */ + binary?: string; + }; + /** + * A message relevant to the region. + */ + message?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + }; +} +/** + * A proposed fix for the problem represented by a result object. A fix specifies a set of file to modify. For each file, it specifies a set of bytes to remove, and provides a set of new bytes to replace them. + */ +export interface Fix { + /** + * A plain text message that describes the proposed fix, enabling viewers to present the proposed change to an end user. + */ + description?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + /** + * One or more file changes that comprise a fix for a result. + */ + fileChanges: FileChange[]; +} +/** + * A change to a single file. + */ +export interface FileChange { + /** + * The location of the file to change. + */ + fileLocation: { + /** + * A string containing a valid relative or absolute URI. + */ + uri: string; + /** + * A string which indirectly specifies the absolute URI with respect to which a relative URI in the "uri" property is interpreted. + */ + uriBaseId?: string; + }; + /** + * An array of replacement objects, each of which represents the replacement of a single region in a single file specified by 'fileLocation'. + */ + replacements: Replacement[]; +} +/** + * The replacement of a single region of a file. + */ +export interface Replacement { + /** + * The region of the file to delete. + */ + deletedRegion: { + /** + * The line number of the first character in the region. + */ + startLine?: number; + /** + * The column number of the first character in the region. + */ + startColumn?: number; + /** + * The line number of the last character in the region. + */ + endLine?: number; + /** + * The column number of the character following the end of the region. + */ + endColumn?: number; + /** + * The zero-based offset from the beginning of the file of the first character in the region. + */ + charOffset?: number; + /** + * The length of the region in characters. + */ + charLength?: number; + /** + * The zero-based offset from the beginning of the file of the first byte in the region. + */ + byteOffset?: number; + /** + * The length of the region in bytes. + */ + byteLength?: number; + /** + * The portion of the file contents within the specified region. + */ + snippet?: { + /** + * UTF-8-encoded content from a text file. + */ + text?: string; + /** + * MIME Base64-encoded content from a binary file, or from a text file in its original encoding. + */ + binary?: string; + }; + /** + * A message relevant to the region. + */ + message?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + }; + /** + * The content to insert at the location specified by the 'deletedRegion' property. + */ + insertedContent?: { + /** + * UTF-8-encoded content from a text file. + */ + text?: string; + /** + * MIME Base64-encoded content from a binary file, or from a text file in its original encoding. + */ + binary?: string; + }; +} +/** + * Describes an analysis rule. + */ +export interface Rule { + /** + * A stable, opaque identifier for the rule. + */ + id: string; + /** + * A rule identifier that is understandable to an end user. + */ + name?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + /** + * A concise description of the rule. Should be a single sentence that is understandable when visible space is limited to a single line of text. + */ + shortDescription?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + /** + * A description of the rule. Should, as far as possible, provide details sufficient to enable resolution of any problem indicated by the result. + */ + fullDescription?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + /** + * A set of name/value pairs with arbitrary names. The value within each name/value pair consists of plain text interspersed with placeholders, which can be used to construct a message in combination with an arbitrary number of additional string arguments. + */ + messageStrings?: { + [k: string]: string; + }; + /** + * A set of name/value pairs with arbitrary names. The value within each name/value pair consists of rich text interspersed with placeholders, which can be used to construct a message in combination with an arbitrary number of additional string arguments. + */ + richMessageStrings?: { + [k: string]: string; + }; + /** + * Information about the rule that can be configured at runtime. + */ + configuration?: { + /** + * Specifies whether the rule will be evaluated during the scan. + */ + enabled?: boolean; + /** + * Specifies the default severity level of the result. + */ + defaultLevel?: 'note' | 'warning' | 'error' | 'open'; + /** + * Contains configuration information specific to this rule. + */ + parameters?: { + /** + * A set of distinct strings that provide additional configuration information. + */ + tags?: string[]; + [k: string]: any; + }; + }; + /** + * A URI where the primary documentation for the rule can be found. + */ + helpUri?: string; + /** + * Provides the primary documentation for the rule, useful when there is no online documentation. + */ + help?: { + /** + * A plain text message string. + */ + text?: string; + /** + * The resource id for a plain text message string. + */ + messageId?: string; + /** + * A rich text message string. + */ + richText?: string; + /** + * The resource id for a rich text message string. + */ + richMessageId?: string; + /** + * An array of strings to substitute into the message string. + */ + arguments?: string[]; + }; + /** + * Key/value pairs that provide additional information about the rule. + */ + properties?: { + /** + * A set of distinct strings that provide additional information. + */ + tags?: string[]; + [k: string]: any; + }; +} diff --git a/src/sarif/sarif-log-21.ts b/src/sarif/sarif-log-21.ts new file mode 100644 index 00000000..6a5ad661 --- /dev/null +++ b/src/sarif/sarif-log-21.ts @@ -0,0 +1,5 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +import { StaticAnalysisResultsFormatSarifVersion212JsonSchema } from './sarif-2.1.2'; + +export type SarifLog21 = StaticAnalysisResultsFormatSarifVersion212JsonSchema; diff --git a/src/test-resources/simple-axe-results.json b/src/test-resources/simple-axe-results.json new file mode 100644 index 00000000..f574d095 --- /dev/null +++ b/src/test-resources/simple-axe-results.json @@ -0,0 +1,1081 @@ +{ + "testEngine": { + "name": "axe-core", + "version": "3.2.2" + }, + "testRunner": { + "name": "axe" + }, + "testEnvironment": { + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.121 Electron/5.0.1 Safari/537.36", + "windowWidth": 2560, + "windowHeight": 1358, + "orientationAngle": 0, + "orientationType": "landscape-primary" + }, + "timestamp": "2019-05-30T23:40:29.706Z", + "url": "url-stub", + "toolOptions": { + "reporter": "v1" + }, + "violations": [ + { + "id": "document-title", + "impact": "serious", + "tags": [ + "cat.text-alternatives", + "wcag2a", + "wcag242" + ], + "description": "Ensures each HTML document contains a non-empty element", + "help": "Documents must have <title> element to aid in navigation", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/document-title?application=axeAPI", + "nodes": [ + { + "any": [ + { + "id": "doc-has-title", + "data": null, + "relatedNodes": [], + "impact": "serious", + "message": "Document does not have a non-empty <title> element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "<html><head></head><body></body></html>", + "target": [ + "html" + ], + "failureSummary": "Fix any of the following:\n Document does not have a non-empty <title> element" + } + ] + }, + { + "id": "html-has-lang", + "impact": "serious", + "tags": [ + "cat.language", + "wcag2a", + "wcag311" + ], + "description": "Ensures every HTML document has a lang attribute", + "help": "<html> element must have a lang attribute", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/html-has-lang?application=axeAPI", + "nodes": [ + { + "any": [ + { + "id": "has-lang", + "data": null, + "relatedNodes": [], + "impact": "serious", + "message": "The <html> element does not have a lang attribute" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "<html><head></head><body></body></html>", + "target": [ + "html" + ], + "failureSummary": "Fix any of the following:\n The <html> element does not have a lang attribute" + } + ] + }, + { + "id": "landmark-one-main", + "impact": "moderate", + "tags": [ + "cat.semantics", + "best-practice" + ], + "description": "Ensures the document has only one main landmark and each iframe in the page has at most one main landmark", + "help": "Document must have one main landmark", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/landmark-one-main?application=axeAPI", + "nodes": [ + { + "any": [], + "all": [ + { + "id": "page-has-main", + "data": null, + "relatedNodes": [], + "impact": "moderate", + "message": "Document does not have a main landmark" + } + ], + "none": [], + "impact": "moderate", + "html": "<html><head></head><body></body></html>", + "target": [ + "html" + ], + "failureSummary": "Fix all of the following:\n Document does not have a main landmark" + } + ] + }, + { + "id": "page-has-heading-one", + "impact": "moderate", + "tags": [ + "cat.semantics", + "best-practice" + ], + "description": "Ensure that the page, or at least one of its frames contains a level-one heading", + "help": "Page must contain a level-one heading", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/page-has-heading-one?application=axeAPI", + "nodes": [ + { + "any": [], + "all": [ + { + "id": "page-has-heading-one", + "data": null, + "relatedNodes": [], + "impact": "moderate", + "message": "Page must have a level-one heading" + } + ], + "none": [], + "impact": "moderate", + "html": "<html><head></head><body></body></html>", + "target": [ + "html" + ], + "failureSummary": "Fix all of the following:\n Page must have a level-one heading" + } + ] + } + ], + "passes": [ + { + "id": "aria-hidden-body", + "impact": null, + "tags": [ + "cat.aria", + "wcag2a", + "wcag412" + ], + "description": "Ensures aria-hidden='true' is not present on the document body.", + "help": "aria-hidden='true' must not be present on the document body", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/aria-hidden-body?application=axeAPI", + "nodes": [ + { + "any": [ + { + "id": "aria-hidden-body", + "data": null, + "relatedNodes": [], + "impact": "critical", + "message": "No aria-hidden attribute is present on document body" + } + ], + "all": [], + "none": [], + "impact": null, + "html": "<body></body>", + "target": [ + "body" + ] + } + ] + }, + { + "id": "landmark-no-duplicate-banner", + "impact": null, + "tags": [ + "cat.semantics", + "best-practice" + ], + "description": "Ensures the document has at most one banner landmark", + "help": "Document must not have more than one banner landmark", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/landmark-no-duplicate-banner?application=axeAPI", + "nodes": [ + { + "any": [ + { + "id": "page-no-duplicate-banner", + "data": null, + "relatedNodes": [], + "impact": "moderate", + "message": "Document does not have more than one banner landmark" + } + ], + "all": [], + "none": [], + "impact": null, + "html": "<html><head></head><body></body></html>", + "target": [ + "html" + ] + } + ] + }, + { + "id": "landmark-no-duplicate-contentinfo", + "impact": null, + "tags": [ + "cat.semantics", + "best-practice" + ], + "description": "Ensures the document has at most one contentinfo landmark", + "help": "Document must not have more than one contentinfo landmark", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/landmark-no-duplicate-contentinfo?application=axeAPI", + "nodes": [ + { + "any": [ + { + "id": "page-no-duplicate-contentinfo", + "data": null, + "relatedNodes": [], + "impact": "moderate", + "message": "Document does not have more than one contentinfo landmark" + } + ], + "all": [], + "none": [], + "impact": null, + "html": "<html><head></head><body></body></html>", + "target": [ + "html" + ] + } + ] + }, + { + "id": "region", + "impact": null, + "tags": [ + "cat.keyboard", + "best-practice" + ], + "description": "Ensures all page content is contained by landmarks", + "help": "All page content must be contained by landmarks", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/region?application=axeAPI", + "nodes": [ + { + "any": [ + { + "id": "region", + "data": null, + "relatedNodes": [], + "impact": "moderate", + "message": "All page content is contained by landmarks" + } + ], + "all": [], + "none": [], + "impact": null, + "html": "<html><head></head><body></body></html>", + "target": [ + "html" + ] + } + ] + } + ], + "incomplete": [], + "inapplicable": [ + { + "id": "accesskeys", + "impact": null, + "tags": [ + "best-practice", + "cat.keyboard" + ], + "description": "Ensures every accesskey attribute value is unique", + "help": "accesskey attribute value must be unique", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/accesskeys?application=axeAPI", + "nodes": [] + }, + { + "id": "area-alt", + "impact": null, + "tags": [ + "cat.text-alternatives", + "wcag2a", + "wcag111", + "section508", + "section508.22.a" + ], + "description": "Ensures <area> elements of image maps have alternate text", + "help": "Active <area> elements must have alternate text", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/area-alt?application=axeAPI", + "nodes": [] + }, + { + "id": "aria-allowed-attr", + "impact": null, + "tags": [ + "cat.aria", + "wcag2a", + "wcag412" + ], + "description": "Ensures ARIA attributes are allowed for an element's role", + "help": "Elements must only use allowed ARIA attributes", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/aria-allowed-attr?application=axeAPI", + "nodes": [] + }, + { + "id": "aria-allowed-role", + "impact": null, + "tags": [ + "cat.aria", + "best-practice" + ], + "description": "Ensures role attribute has an appropriate value for the element", + "help": "ARIA role must be appropriate for the element", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/aria-allowed-role?application=axeAPI", + "nodes": [] + }, + { + "id": "aria-dpub-role-fallback", + "impact": null, + "tags": [ + "cat.aria", + "wcag2a", + "wcag131" + ], + "description": "Ensures unsupported DPUB roles are only used on elements with implicit fallback roles", + "help": "Unsupported DPUB ARIA roles should be used on elements with implicit fallback roles", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/aria-dpub-role-fallback?application=axeAPI", + "nodes": [] + }, + { + "id": "aria-hidden-focus", + "impact": null, + "tags": [ + "cat.name-role-value", + "wcag2a", + "wcag412" + ], + "description": "Ensures aria-hidden elements do not contain focusable elements", + "help": "ARIA hidden element must not contain focusable elements", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/aria-hidden-focus?application=axeAPI", + "nodes": [] + }, + { + "id": "aria-required-attr", + "impact": null, + "tags": [ + "cat.aria", + "wcag2a", + "wcag412" + ], + "description": "Ensures elements with ARIA roles have all required ARIA attributes", + "help": "Required ARIA attributes must be provided", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/aria-required-attr?application=axeAPI", + "nodes": [] + }, + { + "id": "aria-required-children", + "impact": null, + "tags": [ + "cat.aria", + "wcag2a", + "wcag131" + ], + "description": "Ensures elements with an ARIA role that require child roles contain them", + "help": "Certain ARIA roles must contain particular children", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/aria-required-children?application=axeAPI", + "nodes": [] + }, + { + "id": "aria-required-parent", + "impact": null, + "tags": [ + "cat.aria", + "wcag2a", + "wcag131" + ], + "description": "Ensures elements with an ARIA role that require parent roles are contained by them", + "help": "Certain ARIA roles must be contained by particular parents", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/aria-required-parent?application=axeAPI", + "nodes": [] + }, + { + "id": "aria-roles", + "impact": null, + "tags": [ + "cat.aria", + "wcag2a", + "wcag412" + ], + "description": "Ensures all elements with a role attribute use a valid value", + "help": "ARIA roles used must conform to valid values", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/aria-roles?application=axeAPI", + "nodes": [] + }, + { + "id": "aria-valid-attr-value", + "impact": null, + "tags": [ + "cat.aria", + "wcag2a", + "wcag412" + ], + "description": "Ensures all ARIA attributes have valid values", + "help": "ARIA attributes must conform to valid values", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/aria-valid-attr-value?application=axeAPI", + "nodes": [] + }, + { + "id": "aria-valid-attr", + "impact": null, + "tags": [ + "cat.aria", + "wcag2a", + "wcag412" + ], + "description": "Ensures attributes that begin with aria- are valid ARIA attributes", + "help": "ARIA attributes must conform to valid names", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/aria-valid-attr?application=axeAPI", + "nodes": [] + }, + { + "id": "autocomplete-valid", + "impact": null, + "tags": [ + "cat.forms", + "wcag21aa", + "wcag135" + ], + "description": "Ensure the autocomplete attribute is correct and suitable for the form field", + "help": "autocomplete attribute must be used correctly", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/autocomplete-valid?application=axeAPI", + "nodes": [] + }, + { + "id": "blink", + "impact": null, + "tags": [ + "cat.time-and-media", + "wcag2a", + "wcag222", + "section508", + "section508.22.j" + ], + "description": "Ensures <blink> elements are not used", + "help": "<blink> elements are deprecated and must not be used", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/blink?application=axeAPI", + "nodes": [] + }, + { + "id": "button-name", + "impact": null, + "tags": [ + "cat.name-role-value", + "wcag2a", + "wcag412", + "section508", + "section508.22.a" + ], + "description": "Ensures buttons have discernible text", + "help": "Buttons must have discernible text", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/button-name?application=axeAPI", + "nodes": [] + }, + { + "id": "bypass", + "impact": null, + "tags": [ + "cat.keyboard", + "wcag2a", + "wcag241", + "section508", + "section508.22.o" + ], + "description": "Ensures each page has at least one mechanism for a user to bypass navigation and jump straight to the content", + "help": "Page must have means to bypass repeated blocks", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/bypass?application=axeAPI", + "nodes": [] + }, + { + "id": "checkboxgroup", + "impact": null, + "tags": [ + "cat.forms", + "best-practice" + ], + "description": "Ensures related <input type=\"checkbox\"> elements have a group and that the group designation is consistent", + "help": "Checkbox inputs with the same name attribute value must be part of a group", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/checkboxgroup?application=axeAPI", + "nodes": [] + }, + { + "id": "color-contrast", + "impact": null, + "tags": [ + "cat.color", + "wcag2aa", + "wcag143" + ], + "description": "Ensures the contrast between foreground and background colors meets WCAG 2 AA contrast ratio thresholds", + "help": "Elements must have sufficient color contrast", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/color-contrast?application=axeAPI", + "nodes": [] + }, + { + "id": "definition-list", + "impact": null, + "tags": [ + "cat.structure", + "wcag2a", + "wcag131" + ], + "description": "Ensures <dl> elements are structured correctly", + "help": "<dl> elements must only directly contain properly-ordered <dt> and <dd> groups, <script> or <template> elements", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/definition-list?application=axeAPI", + "nodes": [] + }, + { + "id": "dlitem", + "impact": null, + "tags": [ + "cat.structure", + "wcag2a", + "wcag131" + ], + "description": "Ensures <dt> and <dd> elements are contained by a <dl>", + "help": "<dt> and <dd> elements must be contained by a <dl>", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/dlitem?application=axeAPI", + "nodes": [] + }, + { + "id": "duplicate-id-active", + "impact": null, + "tags": [ + "cat.parsing", + "wcag2a", + "wcag411" + ], + "description": "Ensures every id attribute value of active elements is unique", + "help": "IDs of active elements must be unique", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/duplicate-id-active?application=axeAPI", + "nodes": [] + }, + { + "id": "duplicate-id-aria", + "impact": null, + "tags": [ + "cat.parsing", + "wcag2a", + "wcag411" + ], + "description": "Ensures every id attribute value used in ARIA and in labels is unique", + "help": "IDs used in ARIA and labels must be unique", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/duplicate-id-aria?application=axeAPI", + "nodes": [] + }, + { + "id": "duplicate-id", + "impact": null, + "tags": [ + "cat.parsing", + "wcag2a", + "wcag411" + ], + "description": "Ensures every id attribute value is unique", + "help": "id attribute value must be unique", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/duplicate-id?application=axeAPI", + "nodes": [] + }, + { + "id": "empty-heading", + "impact": null, + "tags": [ + "cat.name-role-value", + "best-practice" + ], + "description": "Ensures headings have discernible text", + "help": "Headings must not be empty", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/empty-heading?application=axeAPI", + "nodes": [] + }, + { + "id": "form-field-multiple-labels", + "impact": null, + "tags": [ + "cat.forms", + "wcag2a", + "wcag332" + ], + "description": "Ensures form field does not have multiple label elements", + "help": "Form field must not have multiple label elements", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/form-field-multiple-labels?application=axeAPI", + "nodes": [] + }, + { + "id": "frame-tested", + "impact": null, + "tags": [ + "cat.structure", + "review-item", + "best-practice" + ], + "description": "Ensures <iframe> and <frame> elements contain the axe-core script", + "help": "Frames must be tested with axe-core", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/frame-tested?application=axeAPI", + "nodes": [] + }, + { + "id": "frame-title-unique", + "impact": null, + "tags": [ + "cat.text-alternatives", + "best-practice" + ], + "description": "Ensures <iframe> and <frame> elements contain a unique title attribute", + "help": "Frames must have a unique title attribute", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/frame-title-unique?application=axeAPI", + "nodes": [] + }, + { + "id": "frame-title", + "impact": null, + "tags": [ + "cat.text-alternatives", + "wcag2a", + "wcag241", + "wcag412", + "section508", + "section508.22.i" + ], + "description": "Ensures <iframe> and <frame> elements contain a non-empty title attribute", + "help": "Frames must have title attribute", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/frame-title?application=axeAPI", + "nodes": [] + }, + { + "id": "heading-order", + "impact": null, + "tags": [ + "cat.semantics", + "best-practice" + ], + "description": "Ensures the order of headings is semantically correct", + "help": "Heading levels should only increase by one", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/heading-order?application=axeAPI", + "nodes": [] + }, + { + "id": "html-lang-valid", + "impact": null, + "tags": [ + "cat.language", + "wcag2a", + "wcag311" + ], + "description": "Ensures the lang attribute of the <html> element has a valid value", + "help": "<html> element must have a valid value for the lang attribute", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/html-lang-valid?application=axeAPI", + "nodes": [] + }, + { + "id": "html-xml-lang-mismatch", + "impact": null, + "tags": [ + "cat.language", + "wcag2a", + "wcag311" + ], + "description": "Ensure that HTML elements with both valid lang and xml:lang attributes agree on the base language of the page", + "help": "HTML elements with lang and xml:lang must have the same base language", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/html-xml-lang-mismatch?application=axeAPI", + "nodes": [] + }, + { + "id": "image-alt", + "impact": null, + "tags": [ + "cat.text-alternatives", + "wcag2a", + "wcag111", + "section508", + "section508.22.a" + ], + "description": "Ensures <img> elements have alternate text or a role of none or presentation", + "help": "Images must have alternate text", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/image-alt?application=axeAPI", + "nodes": [] + }, + { + "id": "image-redundant-alt", + "impact": null, + "tags": [ + "cat.text-alternatives", + "best-practice" + ], + "description": "Ensure button and link text is not repeated as image alternative", + "help": "Text of buttons and links should not be repeated in the image alternative", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/image-redundant-alt?application=axeAPI", + "nodes": [] + }, + { + "id": "input-image-alt", + "impact": null, + "tags": [ + "cat.text-alternatives", + "wcag2a", + "wcag111", + "section508", + "section508.22.a" + ], + "description": "Ensures <input type=\"image\"> elements have alternate text", + "help": "Image buttons must have alternate text", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/input-image-alt?application=axeAPI", + "nodes": [] + }, + { + "id": "label-title-only", + "impact": null, + "tags": [ + "cat.forms", + "best-practice" + ], + "description": "Ensures that every form element is not solely labeled using the title or aria-describedby attributes", + "help": "Form elements should have a visible label", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/label-title-only?application=axeAPI", + "nodes": [] + }, + { + "id": "label", + "impact": null, + "tags": [ + "cat.forms", + "wcag2a", + "wcag332", + "wcag131", + "section508", + "section508.22.n" + ], + "description": "Ensures every form element has a label", + "help": "Form elements must have labels", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/label?application=axeAPI", + "nodes": [] + }, + { + "id": "landmark-banner-is-top-level", + "impact": null, + "tags": [ + "cat.semantics", + "best-practice" + ], + "description": "Ensures the banner landmark is at top level", + "help": "Banner landmark must not be contained in another landmark", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/landmark-banner-is-top-level?application=axeAPI", + "nodes": [] + }, + { + "id": "landmark-complementary-is-top-level", + "impact": null, + "tags": [ + "cat.semantics", + "best-practice" + ], + "description": "Ensures the complementary landmark or aside is at top level", + "help": "Aside must not be contained in another landmark", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/landmark-complementary-is-top-level?application=axeAPI", + "nodes": [] + }, + { + "id": "landmark-contentinfo-is-top-level", + "impact": null, + "tags": [ + "cat.semantics", + "best-practice" + ], + "description": "Ensures the contentinfo landmark is at top level", + "help": "Contentinfo landmark must not be contained in another landmark", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/landmark-contentinfo-is-top-level?application=axeAPI", + "nodes": [] + }, + { + "id": "landmark-main-is-top-level", + "impact": null, + "tags": [ + "cat.semantics", + "best-practice" + ], + "description": "Ensures the main landmark is at top level", + "help": "Main landmark must not be contained in another landmark", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/landmark-main-is-top-level?application=axeAPI", + "nodes": [] + }, + { + "id": "layout-table", + "impact": null, + "tags": [ + "cat.semantics", + "wcag2a", + "wcag131" + ], + "description": "Ensures presentational <table> elements do not use <th>, <caption> elements or the summary attribute", + "help": "Layout tables must not use data table elements", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/layout-table?application=axeAPI", + "nodes": [] + }, + { + "id": "link-name", + "impact": null, + "tags": [ + "cat.name-role-value", + "wcag2a", + "wcag412", + "wcag244", + "section508", + "section508.22.a" + ], + "description": "Ensures links have discernible text", + "help": "Links must have discernible text", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/link-name?application=axeAPI", + "nodes": [] + }, + { + "id": "list", + "impact": null, + "tags": [ + "cat.structure", + "wcag2a", + "wcag131" + ], + "description": "Ensures that lists are structured correctly", + "help": "<ul> and <ol> must only directly contain <li>, <script> or <template> elements", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/list?application=axeAPI", + "nodes": [] + }, + { + "id": "listitem", + "impact": null, + "tags": [ + "cat.structure", + "wcag2a", + "wcag131" + ], + "description": "Ensures <li> elements are used semantically", + "help": "<li> elements must be contained in a <ul> or <ol>", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/listitem?application=axeAPI", + "nodes": [] + }, + { + "id": "marquee", + "impact": null, + "tags": [ + "cat.parsing", + "wcag2a", + "wcag222" + ], + "description": "Ensures <marquee> elements are not used", + "help": "<marquee> elements are deprecated and must not be used", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/marquee?application=axeAPI", + "nodes": [] + }, + { + "id": "meta-refresh", + "impact": null, + "tags": [ + "cat.time", + "wcag2a", + "wcag2aaa", + "wcag221", + "wcag224", + "wcag325" + ], + "description": "Ensures <meta http-equiv=\"refresh\"> is not used", + "help": "Timed refresh must not exist", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/meta-refresh?application=axeAPI", + "nodes": [] + }, + { + "id": "meta-viewport-large", + "impact": null, + "tags": [ + "cat.sensory-and-visual-cues", + "best-practice" + ], + "description": "Ensures <meta name=\"viewport\"> can scale a significant amount", + "help": "Users should be able to zoom and scale the text up to 500%", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/meta-viewport-large?application=axeAPI", + "nodes": [] + }, + { + "id": "meta-viewport", + "impact": null, + "tags": [ + "cat.sensory-and-visual-cues", + "wcag2aa", + "wcag144" + ], + "description": "Ensures <meta name=\"viewport\"> does not disable text scaling and zooming", + "help": "Zooming and scaling must not be disabled", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/meta-viewport?application=axeAPI", + "nodes": [] + }, + { + "id": "object-alt", + "impact": null, + "tags": [ + "cat.text-alternatives", + "wcag2a", + "wcag111", + "section508", + "section508.22.a" + ], + "description": "Ensures <object> elements have alternate text", + "help": "<object> elements must have alternate text", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/object-alt?application=axeAPI", + "nodes": [] + }, + { + "id": "radiogroup", + "impact": null, + "tags": [ + "cat.forms", + "best-practice" + ], + "description": "Ensures related <input type=\"radio\"> elements have a group and that the group designation is consistent", + "help": "Radio inputs with the same name attribute value must be part of a group", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/radiogroup?application=axeAPI", + "nodes": [] + }, + { + "id": "scope-attr-valid", + "impact": null, + "tags": [ + "cat.tables", + "best-practice" + ], + "description": "Ensures the scope attribute is used correctly on tables", + "help": "scope attribute should be used correctly", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/scope-attr-valid?application=axeAPI", + "nodes": [] + }, + { + "id": "server-side-image-map", + "impact": null, + "tags": [ + "cat.text-alternatives", + "wcag2a", + "wcag211", + "section508", + "section508.22.f" + ], + "description": "Ensures that server-side image maps are not used", + "help": "Server-side image maps must not be used", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/server-side-image-map?application=axeAPI", + "nodes": [] + }, + { + "id": "skip-link", + "impact": null, + "tags": [ + "cat.keyboard", + "best-practice" + ], + "description": "Ensure all skip links have a focusable target", + "help": "The skip-link target should exist and be focusable", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/skip-link?application=axeAPI", + "nodes": [] + }, + { + "id": "tabindex", + "impact": null, + "tags": [ + "cat.keyboard", + "best-practice" + ], + "description": "Ensures tabindex attribute values are not greater than 0", + "help": "Elements should not have tabindex greater than zero", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/tabindex?application=axeAPI", + "nodes": [] + }, + { + "id": "table-duplicate-name", + "impact": null, + "tags": [ + "cat.tables", + "best-practice" + ], + "description": "Ensure that tables do not have the same summary and caption", + "help": "The <caption> element should not contain the same text as the summary attribute", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/table-duplicate-name?application=axeAPI", + "nodes": [] + }, + { + "id": "td-headers-attr", + "impact": null, + "tags": [ + "cat.tables", + "wcag2a", + "wcag131", + "section508", + "section508.22.g" + ], + "description": "Ensure that each cell in a table using the headers refers to another cell in that table", + "help": "All cells in a table element that use the headers attribute must only refer to other cells of that same table", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/td-headers-attr?application=axeAPI", + "nodes": [] + }, + { + "id": "th-has-data-cells", + "impact": null, + "tags": [ + "cat.tables", + "wcag2a", + "wcag131", + "section508", + "section508.22.g" + ], + "description": "Ensure that each table header in a data table refers to data cells", + "help": "All th elements and elements with role=columnheader/rowheader must have data cells they describe", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/th-has-data-cells?application=axeAPI", + "nodes": [] + }, + { + "id": "valid-lang", + "impact": null, + "tags": [ + "cat.language", + "wcag2aa", + "wcag312" + ], + "description": "Ensures lang attributes have valid values", + "help": "lang attribute must have a valid value", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/valid-lang?application=axeAPI", + "nodes": [] + }, + { + "id": "video-caption", + "impact": null, + "tags": [ + "cat.text-alternatives", + "wcag2a", + "wcag122", + "section508", + "section508.22.a" + ], + "description": "Ensures <video> elements have captions", + "help": "<video> elements must have captions", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/video-caption?application=axeAPI", + "nodes": [] + }, + { + "id": "video-description", + "impact": null, + "tags": [ + "cat.text-alternatives", + "wcag2aa", + "wcag125", + "section508", + "section508.22.b" + ], + "description": "Ensures <video> elements have audio descriptions", + "help": "<video> elements must have an audio description track", + "helpUrl": "https://dequeuniversity.com/rules/axe/3.2/video-description?application=axeAPI", + "nodes": [] + } + ] +} diff --git a/src/test-resources/simple-output-sarifv2.sarif b/src/test-resources/simple-output-sarifv2.sarif new file mode 100644 index 00000000..165980fe --- /dev/null +++ b/src/test-resources/simple-output-sarifv2.sarif @@ -0,0 +1,1780 @@ +{ + "version": "2.0.0", + "runs": [ + { + "tool": { + "name": "axe", + "fullName": "axe-core", + "semanticVersion": "3.2.2", + "version": "3.2.2", + "properties": { + "downloadUri": "https://www.deque.com/axe/" + } + }, + "invocations": [ + { + "startTime": "2019-05-30T23:40:29.706Z", + "endTime": "2019-05-30T23:40:29.706Z" + } + ], + "files": { + "url-stub": { + "mimeType": "text/html", + "properties": { + "tags": [ + "target" + ], + "title": "" + } + } + }, + "results": [ + { + "ruleId": "document-title", + "level": "error", + "message": { + "text": "Fix any of the following: Document does not have a non-empty <title> element.", + "richText": "Fix any of the following:\n- Document does not have a non-empty <title> element" + }, + "locations": [ + { + "physicalLocation": { + "fileLocation": { + "uri": "url-stub" + } + }, + "fullyQualifiedLogicalName": "html", + "annotations": [ + { + "snippet": { + "text": "<html><head></head><body></body></html>" + } + } + ] + } + ], + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "fullyQualifiedLogicalName": "html", + "ruleId": "document-title" + } + }, + { + "ruleId": "html-has-lang", + "level": "error", + "message": { + "text": "Fix any of the following: The <html> element does not have a lang attribute.", + "richText": "Fix any of the following:\n- The <html> element does not have a lang attribute" + }, + "locations": [ + { + "physicalLocation": { + "fileLocation": { + "uri": "url-stub" + } + }, + "fullyQualifiedLogicalName": "html", + "annotations": [ + { + "snippet": { + "text": "<html><head></head><body></body></html>" + } + } + ] + } + ], + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "fullyQualifiedLogicalName": "html", + "ruleId": "html-has-lang" + } + }, + { + "ruleId": "landmark-one-main", + "level": "error", + "message": { + "text": "Fix all of the following: Document does not have a main landmark.", + "richText": "Fix all of the following:\n- Document does not have a main landmark" + }, + "locations": [ + { + "physicalLocation": { + "fileLocation": { + "uri": "url-stub" + } + }, + "fullyQualifiedLogicalName": "html", + "annotations": [ + { + "snippet": { + "text": "<html><head></head><body></body></html>" + } + } + ] + } + ], + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "fullyQualifiedLogicalName": "html", + "ruleId": "landmark-one-main" + } + }, + { + "ruleId": "page-has-heading-one", + "level": "error", + "message": { + "text": "Fix all of the following: Page must have a level-one heading.", + "richText": "Fix all of the following:\n- Page must have a level-one heading" + }, + "locations": [ + { + "physicalLocation": { + "fileLocation": { + "uri": "url-stub" + } + }, + "fullyQualifiedLogicalName": "html", + "annotations": [ + { + "snippet": { + "text": "<html><head></head><body></body></html>" + } + } + ] + } + ], + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "fullyQualifiedLogicalName": "html", + "ruleId": "page-has-heading-one" + } + }, + { + "ruleId": "aria-hidden-body", + "level": "pass", + "message": { + "text": "The following tests passed: No aria-hidden attribute is present on document body.", + "richText": "The following tests passed:\n- No aria-hidden attribute is present on document body" + }, + "locations": [ + { + "physicalLocation": { + "fileLocation": { + "uri": "url-stub" + } + }, + "fullyQualifiedLogicalName": "body", + "annotations": [ + { + "snippet": { + "text": "<body></body>" + } + } + ] + } + ], + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "fullyQualifiedLogicalName": "body", + "ruleId": "aria-hidden-body" + } + }, + { + "ruleId": "landmark-no-duplicate-banner", + "level": "pass", + "message": { + "text": "The following tests passed: Document does not have more than one banner landmark.", + "richText": "The following tests passed:\n- Document does not have more than one banner landmark" + }, + "locations": [ + { + "physicalLocation": { + "fileLocation": { + "uri": "url-stub" + } + }, + "fullyQualifiedLogicalName": "html", + "annotations": [ + { + "snippet": { + "text": "<html><head></head><body></body></html>" + } + } + ] + } + ], + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "fullyQualifiedLogicalName": "html", + "ruleId": "landmark-no-duplicate-banner" + } + }, + { + "ruleId": "landmark-no-duplicate-contentinfo", + "level": "pass", + "message": { + "text": "The following tests passed: Document does not have more than one contentinfo landmark.", + "richText": "The following tests passed:\n- Document does not have more than one contentinfo landmark" + }, + "locations": [ + { + "physicalLocation": { + "fileLocation": { + "uri": "url-stub" + } + }, + "fullyQualifiedLogicalName": "html", + "annotations": [ + { + "snippet": { + "text": "<html><head></head><body></body></html>" + } + } + ] + } + ], + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "fullyQualifiedLogicalName": "html", + "ruleId": "landmark-no-duplicate-contentinfo" + } + }, + { + "ruleId": "region", + "level": "pass", + "message": { + "text": "The following tests passed: All page content is contained by landmarks.", + "richText": "The following tests passed:\n- All page content is contained by landmarks" + }, + "locations": [ + { + "physicalLocation": { + "fileLocation": { + "uri": "url-stub" + } + }, + "fullyQualifiedLogicalName": "html", + "annotations": [ + { + "snippet": { + "text": "<html><head></head><body></body></html>" + } + } + ] + } + ], + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "fullyQualifiedLogicalName": "html", + "ruleId": "region" + } + }, + { + "ruleId": "accesskeys", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "accesskeys" + } + }, + { + "ruleId": "area-alt", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "area-alt" + } + }, + { + "ruleId": "aria-allowed-attr", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "aria-allowed-attr" + } + }, + { + "ruleId": "aria-allowed-role", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "aria-allowed-role" + } + }, + { + "ruleId": "aria-dpub-role-fallback", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "aria-dpub-role-fallback" + } + }, + { + "ruleId": "aria-hidden-focus", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "aria-hidden-focus" + } + }, + { + "ruleId": "aria-required-attr", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "aria-required-attr" + } + }, + { + "ruleId": "aria-required-children", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "aria-required-children" + } + }, + { + "ruleId": "aria-required-parent", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "aria-required-parent" + } + }, + { + "ruleId": "aria-roles", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "aria-roles" + } + }, + { + "ruleId": "aria-valid-attr-value", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "aria-valid-attr-value" + } + }, + { + "ruleId": "aria-valid-attr", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "aria-valid-attr" + } + }, + { + "ruleId": "autocomplete-valid", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "autocomplete-valid" + } + }, + { + "ruleId": "blink", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "blink" + } + }, + { + "ruleId": "button-name", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "button-name" + } + }, + { + "ruleId": "bypass", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "bypass" + } + }, + { + "ruleId": "checkboxgroup", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "checkboxgroup" + } + }, + { + "ruleId": "color-contrast", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "color-contrast" + } + }, + { + "ruleId": "definition-list", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "definition-list" + } + }, + { + "ruleId": "dlitem", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "dlitem" + } + }, + { + "ruleId": "duplicate-id-active", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "duplicate-id-active" + } + }, + { + "ruleId": "duplicate-id-aria", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "duplicate-id-aria" + } + }, + { + "ruleId": "duplicate-id", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "duplicate-id" + } + }, + { + "ruleId": "empty-heading", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "empty-heading" + } + }, + { + "ruleId": "form-field-multiple-labels", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "form-field-multiple-labels" + } + }, + { + "ruleId": "frame-tested", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "frame-tested" + } + }, + { + "ruleId": "frame-title-unique", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "frame-title-unique" + } + }, + { + "ruleId": "frame-title", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "frame-title" + } + }, + { + "ruleId": "heading-order", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "heading-order" + } + }, + { + "ruleId": "html-lang-valid", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "html-lang-valid" + } + }, + { + "ruleId": "html-xml-lang-mismatch", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "html-xml-lang-mismatch" + } + }, + { + "ruleId": "image-alt", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "image-alt" + } + }, + { + "ruleId": "image-redundant-alt", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "image-redundant-alt" + } + }, + { + "ruleId": "input-image-alt", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "input-image-alt" + } + }, + { + "ruleId": "label-title-only", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "label-title-only" + } + }, + { + "ruleId": "label", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "label" + } + }, + { + "ruleId": "landmark-banner-is-top-level", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "landmark-banner-is-top-level" + } + }, + { + "ruleId": "landmark-complementary-is-top-level", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "landmark-complementary-is-top-level" + } + }, + { + "ruleId": "landmark-contentinfo-is-top-level", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "landmark-contentinfo-is-top-level" + } + }, + { + "ruleId": "landmark-main-is-top-level", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "landmark-main-is-top-level" + } + }, + { + "ruleId": "layout-table", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "layout-table" + } + }, + { + "ruleId": "link-name", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "link-name" + } + }, + { + "ruleId": "list", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "list" + } + }, + { + "ruleId": "listitem", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "listitem" + } + }, + { + "ruleId": "marquee", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "marquee" + } + }, + { + "ruleId": "meta-refresh", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "meta-refresh" + } + }, + { + "ruleId": "meta-viewport-large", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "meta-viewport-large" + } + }, + { + "ruleId": "meta-viewport", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "meta-viewport" + } + }, + { + "ruleId": "object-alt", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "object-alt" + } + }, + { + "ruleId": "radiogroup", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "radiogroup" + } + }, + { + "ruleId": "scope-attr-valid", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "scope-attr-valid" + } + }, + { + "ruleId": "server-side-image-map", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "server-side-image-map" + } + }, + { + "ruleId": "skip-link", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "skip-link" + } + }, + { + "ruleId": "tabindex", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "tabindex" + } + }, + { + "ruleId": "table-duplicate-name", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "table-duplicate-name" + } + }, + { + "ruleId": "td-headers-attr", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "td-headers-attr" + } + }, + { + "ruleId": "th-has-data-cells", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "th-has-data-cells" + } + }, + { + "ruleId": "valid-lang", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "valid-lang" + } + }, + { + "ruleId": "video-caption", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "video-caption" + } + }, + { + "ruleId": "video-description", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "video-description" + } + } + ], + "resources": { + "rules": { + "document-title": { + "id": "document-title", + "name": { + "text": "Documents must have <title> element to aid in navigation" + }, + "fullDescription": { + "text": "Ensures each HTML document contains a non-empty <title> element" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/document-title?application=axeAPI", + "properties": {} + }, + "html-has-lang": { + "id": "html-has-lang", + "name": { + "text": "<html> element must have a lang attribute" + }, + "fullDescription": { + "text": "Ensures every HTML document has a lang attribute" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/html-has-lang?application=axeAPI", + "properties": {} + }, + "landmark-one-main": { + "id": "landmark-one-main", + "name": { + "text": "Document must have one main landmark" + }, + "fullDescription": { + "text": "Ensures the document has only one main landmark and each iframe in the page has at most one main landmark" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/landmark-one-main?application=axeAPI", + "properties": {} + }, + "page-has-heading-one": { + "id": "page-has-heading-one", + "name": { + "text": "Page must contain a level-one heading" + }, + "fullDescription": { + "text": "Ensure that the page, or at least one of its frames contains a level-one heading" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/page-has-heading-one?application=axeAPI", + "properties": {} + }, + "aria-hidden-body": { + "id": "aria-hidden-body", + "name": { + "text": "aria-hidden='true' must not be present on the document body" + }, + "fullDescription": { + "text": "Ensures aria-hidden='true' is not present on the document body." + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/aria-hidden-body?application=axeAPI", + "properties": {} + }, + "landmark-no-duplicate-banner": { + "id": "landmark-no-duplicate-banner", + "name": { + "text": "Document must not have more than one banner landmark" + }, + "fullDescription": { + "text": "Ensures the document has at most one banner landmark" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/landmark-no-duplicate-banner?application=axeAPI", + "properties": {} + }, + "landmark-no-duplicate-contentinfo": { + "id": "landmark-no-duplicate-contentinfo", + "name": { + "text": "Document must not have more than one contentinfo landmark" + }, + "fullDescription": { + "text": "Ensures the document has at most one contentinfo landmark" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/landmark-no-duplicate-contentinfo?application=axeAPI", + "properties": {} + }, + "region": { + "id": "region", + "name": { + "text": "All page content must be contained by landmarks" + }, + "fullDescription": { + "text": "Ensures all page content is contained by landmarks" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/region?application=axeAPI", + "properties": {} + }, + "accesskeys": { + "id": "accesskeys", + "name": { + "text": "accesskey attribute value must be unique" + }, + "fullDescription": { + "text": "Ensures every accesskey attribute value is unique" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/accesskeys?application=axeAPI", + "properties": {} + }, + "area-alt": { + "id": "area-alt", + "name": { + "text": "Active <area> elements must have alternate text" + }, + "fullDescription": { + "text": "Ensures <area> elements of image maps have alternate text" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/area-alt?application=axeAPI", + "properties": {} + }, + "aria-allowed-attr": { + "id": "aria-allowed-attr", + "name": { + "text": "Elements must only use allowed ARIA attributes" + }, + "fullDescription": { + "text": "Ensures ARIA attributes are allowed for an element's role" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/aria-allowed-attr?application=axeAPI", + "properties": {} + }, + "aria-allowed-role": { + "id": "aria-allowed-role", + "name": { + "text": "ARIA role must be appropriate for the element" + }, + "fullDescription": { + "text": "Ensures role attribute has an appropriate value for the element" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/aria-allowed-role?application=axeAPI", + "properties": {} + }, + "aria-dpub-role-fallback": { + "id": "aria-dpub-role-fallback", + "name": { + "text": "Unsupported DPUB ARIA roles should be used on elements with implicit fallback roles" + }, + "fullDescription": { + "text": "Ensures unsupported DPUB roles are only used on elements with implicit fallback roles" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/aria-dpub-role-fallback?application=axeAPI", + "properties": {} + }, + "aria-hidden-focus": { + "id": "aria-hidden-focus", + "name": { + "text": "ARIA hidden element must not contain focusable elements" + }, + "fullDescription": { + "text": "Ensures aria-hidden elements do not contain focusable elements" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/aria-hidden-focus?application=axeAPI", + "properties": {} + }, + "aria-required-attr": { + "id": "aria-required-attr", + "name": { + "text": "Required ARIA attributes must be provided" + }, + "fullDescription": { + "text": "Ensures elements with ARIA roles have all required ARIA attributes" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/aria-required-attr?application=axeAPI", + "properties": {} + }, + "aria-required-children": { + "id": "aria-required-children", + "name": { + "text": "Certain ARIA roles must contain particular children" + }, + "fullDescription": { + "text": "Ensures elements with an ARIA role that require child roles contain them" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/aria-required-children?application=axeAPI", + "properties": {} + }, + "aria-required-parent": { + "id": "aria-required-parent", + "name": { + "text": "Certain ARIA roles must be contained by particular parents" + }, + "fullDescription": { + "text": "Ensures elements with an ARIA role that require parent roles are contained by them" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/aria-required-parent?application=axeAPI", + "properties": {} + }, + "aria-roles": { + "id": "aria-roles", + "name": { + "text": "ARIA roles used must conform to valid values" + }, + "fullDescription": { + "text": "Ensures all elements with a role attribute use a valid value" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/aria-roles?application=axeAPI", + "properties": {} + }, + "aria-valid-attr-value": { + "id": "aria-valid-attr-value", + "name": { + "text": "ARIA attributes must conform to valid values" + }, + "fullDescription": { + "text": "Ensures all ARIA attributes have valid values" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/aria-valid-attr-value?application=axeAPI", + "properties": {} + }, + "aria-valid-attr": { + "id": "aria-valid-attr", + "name": { + "text": "ARIA attributes must conform to valid names" + }, + "fullDescription": { + "text": "Ensures attributes that begin with aria- are valid ARIA attributes" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/aria-valid-attr?application=axeAPI", + "properties": {} + }, + "autocomplete-valid": { + "id": "autocomplete-valid", + "name": { + "text": "autocomplete attribute must be used correctly" + }, + "fullDescription": { + "text": "Ensure the autocomplete attribute is correct and suitable for the form field" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/autocomplete-valid?application=axeAPI", + "properties": {} + }, + "blink": { + "id": "blink", + "name": { + "text": "<blink> elements are deprecated and must not be used" + }, + "fullDescription": { + "text": "Ensures <blink> elements are not used" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/blink?application=axeAPI", + "properties": {} + }, + "button-name": { + "id": "button-name", + "name": { + "text": "Buttons must have discernible text" + }, + "fullDescription": { + "text": "Ensures buttons have discernible text" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/button-name?application=axeAPI", + "properties": {} + }, + "bypass": { + "id": "bypass", + "name": { + "text": "Page must have means to bypass repeated blocks" + }, + "fullDescription": { + "text": "Ensures each page has at least one mechanism for a user to bypass navigation and jump straight to the content" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/bypass?application=axeAPI", + "properties": {} + }, + "checkboxgroup": { + "id": "checkboxgroup", + "name": { + "text": "Checkbox inputs with the same name attribute value must be part of a group" + }, + "fullDescription": { + "text": "Ensures related <input type=\"checkbox\"> elements have a group and that the group designation is consistent" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/checkboxgroup?application=axeAPI", + "properties": {} + }, + "color-contrast": { + "id": "color-contrast", + "name": { + "text": "Elements must have sufficient color contrast" + }, + "fullDescription": { + "text": "Ensures the contrast between foreground and background colors meets WCAG 2 AA contrast ratio thresholds" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/color-contrast?application=axeAPI", + "properties": {} + }, + "definition-list": { + "id": "definition-list", + "name": { + "text": "<dl> elements must only directly contain properly-ordered <dt> and <dd> groups, <script> or <template> elements" + }, + "fullDescription": { + "text": "Ensures <dl> elements are structured correctly" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/definition-list?application=axeAPI", + "properties": {} + }, + "dlitem": { + "id": "dlitem", + "name": { + "text": "<dt> and <dd> elements must be contained by a <dl>" + }, + "fullDescription": { + "text": "Ensures <dt> and <dd> elements are contained by a <dl>" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/dlitem?application=axeAPI", + "properties": {} + }, + "duplicate-id-active": { + "id": "duplicate-id-active", + "name": { + "text": "IDs of active elements must be unique" + }, + "fullDescription": { + "text": "Ensures every id attribute value of active elements is unique" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/duplicate-id-active?application=axeAPI", + "properties": {} + }, + "duplicate-id-aria": { + "id": "duplicate-id-aria", + "name": { + "text": "IDs used in ARIA and labels must be unique" + }, + "fullDescription": { + "text": "Ensures every id attribute value used in ARIA and in labels is unique" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/duplicate-id-aria?application=axeAPI", + "properties": {} + }, + "duplicate-id": { + "id": "duplicate-id", + "name": { + "text": "id attribute value must be unique" + }, + "fullDescription": { + "text": "Ensures every id attribute value is unique" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/duplicate-id?application=axeAPI", + "properties": {} + }, + "empty-heading": { + "id": "empty-heading", + "name": { + "text": "Headings must not be empty" + }, + "fullDescription": { + "text": "Ensures headings have discernible text" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/empty-heading?application=axeAPI", + "properties": {} + }, + "form-field-multiple-labels": { + "id": "form-field-multiple-labels", + "name": { + "text": "Form field must not have multiple label elements" + }, + "fullDescription": { + "text": "Ensures form field does not have multiple label elements" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/form-field-multiple-labels?application=axeAPI", + "properties": {} + }, + "frame-tested": { + "id": "frame-tested", + "name": { + "text": "Frames must be tested with axe-core" + }, + "fullDescription": { + "text": "Ensures <iframe> and <frame> elements contain the axe-core script" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/frame-tested?application=axeAPI", + "properties": {} + }, + "frame-title-unique": { + "id": "frame-title-unique", + "name": { + "text": "Frames must have a unique title attribute" + }, + "fullDescription": { + "text": "Ensures <iframe> and <frame> elements contain a unique title attribute" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/frame-title-unique?application=axeAPI", + "properties": {} + }, + "frame-title": { + "id": "frame-title", + "name": { + "text": "Frames must have title attribute" + }, + "fullDescription": { + "text": "Ensures <iframe> and <frame> elements contain a non-empty title attribute" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/frame-title?application=axeAPI", + "properties": {} + }, + "heading-order": { + "id": "heading-order", + "name": { + "text": "Heading levels should only increase by one" + }, + "fullDescription": { + "text": "Ensures the order of headings is semantically correct" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/heading-order?application=axeAPI", + "properties": {} + }, + "html-lang-valid": { + "id": "html-lang-valid", + "name": { + "text": "<html> element must have a valid value for the lang attribute" + }, + "fullDescription": { + "text": "Ensures the lang attribute of the <html> element has a valid value" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/html-lang-valid?application=axeAPI", + "properties": {} + }, + "html-xml-lang-mismatch": { + "id": "html-xml-lang-mismatch", + "name": { + "text": "HTML elements with lang and xml:lang must have the same base language" + }, + "fullDescription": { + "text": "Ensure that HTML elements with both valid lang and xml:lang attributes agree on the base language of the page" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/html-xml-lang-mismatch?application=axeAPI", + "properties": {} + }, + "image-alt": { + "id": "image-alt", + "name": { + "text": "Images must have alternate text" + }, + "fullDescription": { + "text": "Ensures <img> elements have alternate text or a role of none or presentation" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/image-alt?application=axeAPI", + "properties": {} + }, + "image-redundant-alt": { + "id": "image-redundant-alt", + "name": { + "text": "Text of buttons and links should not be repeated in the image alternative" + }, + "fullDescription": { + "text": "Ensure button and link text is not repeated as image alternative" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/image-redundant-alt?application=axeAPI", + "properties": {} + }, + "input-image-alt": { + "id": "input-image-alt", + "name": { + "text": "Image buttons must have alternate text" + }, + "fullDescription": { + "text": "Ensures <input type=\"image\"> elements have alternate text" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/input-image-alt?application=axeAPI", + "properties": {} + }, + "label-title-only": { + "id": "label-title-only", + "name": { + "text": "Form elements should have a visible label" + }, + "fullDescription": { + "text": "Ensures that every form element is not solely labeled using the title or aria-describedby attributes" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/label-title-only?application=axeAPI", + "properties": {} + }, + "label": { + "id": "label", + "name": { + "text": "Form elements must have labels" + }, + "fullDescription": { + "text": "Ensures every form element has a label" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/label?application=axeAPI", + "properties": {} + }, + "landmark-banner-is-top-level": { + "id": "landmark-banner-is-top-level", + "name": { + "text": "Banner landmark must not be contained in another landmark" + }, + "fullDescription": { + "text": "Ensures the banner landmark is at top level" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/landmark-banner-is-top-level?application=axeAPI", + "properties": {} + }, + "landmark-complementary-is-top-level": { + "id": "landmark-complementary-is-top-level", + "name": { + "text": "Aside must not be contained in another landmark" + }, + "fullDescription": { + "text": "Ensures the complementary landmark or aside is at top level" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/landmark-complementary-is-top-level?application=axeAPI", + "properties": {} + }, + "landmark-contentinfo-is-top-level": { + "id": "landmark-contentinfo-is-top-level", + "name": { + "text": "Contentinfo landmark must not be contained in another landmark" + }, + "fullDescription": { + "text": "Ensures the contentinfo landmark is at top level" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/landmark-contentinfo-is-top-level?application=axeAPI", + "properties": {} + }, + "landmark-main-is-top-level": { + "id": "landmark-main-is-top-level", + "name": { + "text": "Main landmark must not be contained in another landmark" + }, + "fullDescription": { + "text": "Ensures the main landmark is at top level" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/landmark-main-is-top-level?application=axeAPI", + "properties": {} + }, + "layout-table": { + "id": "layout-table", + "name": { + "text": "Layout tables must not use data table elements" + }, + "fullDescription": { + "text": "Ensures presentational <table> elements do not use <th>, <caption> elements or the summary attribute" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/layout-table?application=axeAPI", + "properties": {} + }, + "link-name": { + "id": "link-name", + "name": { + "text": "Links must have discernible text" + }, + "fullDescription": { + "text": "Ensures links have discernible text" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/link-name?application=axeAPI", + "properties": {} + }, + "list": { + "id": "list", + "name": { + "text": "<ul> and <ol> must only directly contain <li>, <script> or <template> elements" + }, + "fullDescription": { + "text": "Ensures that lists are structured correctly" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/list?application=axeAPI", + "properties": {} + }, + "listitem": { + "id": "listitem", + "name": { + "text": "<li> elements must be contained in a <ul> or <ol>" + }, + "fullDescription": { + "text": "Ensures <li> elements are used semantically" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/listitem?application=axeAPI", + "properties": {} + }, + "marquee": { + "id": "marquee", + "name": { + "text": "<marquee> elements are deprecated and must not be used" + }, + "fullDescription": { + "text": "Ensures <marquee> elements are not used" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/marquee?application=axeAPI", + "properties": {} + }, + "meta-refresh": { + "id": "meta-refresh", + "name": { + "text": "Timed refresh must not exist" + }, + "fullDescription": { + "text": "Ensures <meta http-equiv=\"refresh\"> is not used" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/meta-refresh?application=axeAPI", + "properties": {} + }, + "meta-viewport-large": { + "id": "meta-viewport-large", + "name": { + "text": "Users should be able to zoom and scale the text up to 500%" + }, + "fullDescription": { + "text": "Ensures <meta name=\"viewport\"> can scale a significant amount" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/meta-viewport-large?application=axeAPI", + "properties": {} + }, + "meta-viewport": { + "id": "meta-viewport", + "name": { + "text": "Zooming and scaling must not be disabled" + }, + "fullDescription": { + "text": "Ensures <meta name=\"viewport\"> does not disable text scaling and zooming" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/meta-viewport?application=axeAPI", + "properties": {} + }, + "object-alt": { + "id": "object-alt", + "name": { + "text": "<object> elements must have alternate text" + }, + "fullDescription": { + "text": "Ensures <object> elements have alternate text" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/object-alt?application=axeAPI", + "properties": {} + }, + "radiogroup": { + "id": "radiogroup", + "name": { + "text": "Radio inputs with the same name attribute value must be part of a group" + }, + "fullDescription": { + "text": "Ensures related <input type=\"radio\"> elements have a group and that the group designation is consistent" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/radiogroup?application=axeAPI", + "properties": {} + }, + "scope-attr-valid": { + "id": "scope-attr-valid", + "name": { + "text": "scope attribute should be used correctly" + }, + "fullDescription": { + "text": "Ensures the scope attribute is used correctly on tables" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/scope-attr-valid?application=axeAPI", + "properties": {} + }, + "server-side-image-map": { + "id": "server-side-image-map", + "name": { + "text": "Server-side image maps must not be used" + }, + "fullDescription": { + "text": "Ensures that server-side image maps are not used" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/server-side-image-map?application=axeAPI", + "properties": {} + }, + "skip-link": { + "id": "skip-link", + "name": { + "text": "The skip-link target should exist and be focusable" + }, + "fullDescription": { + "text": "Ensure all skip links have a focusable target" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/skip-link?application=axeAPI", + "properties": {} + }, + "tabindex": { + "id": "tabindex", + "name": { + "text": "Elements should not have tabindex greater than zero" + }, + "fullDescription": { + "text": "Ensures tabindex attribute values are not greater than 0" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/tabindex?application=axeAPI", + "properties": {} + }, + "table-duplicate-name": { + "id": "table-duplicate-name", + "name": { + "text": "The <caption> element should not contain the same text as the summary attribute" + }, + "fullDescription": { + "text": "Ensure that tables do not have the same summary and caption" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/table-duplicate-name?application=axeAPI", + "properties": {} + }, + "td-headers-attr": { + "id": "td-headers-attr", + "name": { + "text": "All cells in a table element that use the headers attribute must only refer to other cells of that same table" + }, + "fullDescription": { + "text": "Ensure that each cell in a table using the headers refers to another cell in that table" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/td-headers-attr?application=axeAPI", + "properties": {} + }, + "th-has-data-cells": { + "id": "th-has-data-cells", + "name": { + "text": "All th elements and elements with role=columnheader/rowheader must have data cells they describe" + }, + "fullDescription": { + "text": "Ensure that each table header in a data table refers to data cells" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/th-has-data-cells?application=axeAPI", + "properties": {} + }, + "valid-lang": { + "id": "valid-lang", + "name": { + "text": "lang attribute must have a valid value" + }, + "fullDescription": { + "text": "Ensures lang attributes have valid values" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/valid-lang?application=axeAPI", + "properties": {} + }, + "video-caption": { + "id": "video-caption", + "name": { + "text": "<video> elements must have captions" + }, + "fullDescription": { + "text": "Ensures <video> elements have captions" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/video-caption?application=axeAPI", + "properties": {} + }, + "video-description": { + "id": "video-description", + "name": { + "text": "<video> elements must have an audio description track" + }, + "fullDescription": { + "text": "Ensures <video> elements have audio descriptions" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/video-description?application=axeAPI", + "properties": {} + } + } + }, + "properties": {} + } + ] +} \ No newline at end of file diff --git a/src/test-resources/simple-output-sarifv21.sarif b/src/test-resources/simple-output-sarifv21.sarif new file mode 100644 index 00000000..98d5ef16 --- /dev/null +++ b/src/test-resources/simple-output-sarifv21.sarif @@ -0,0 +1,1816 @@ +{ + "version": "2.1.0", + "runs": [ + { + "conversion": { + "tool": { + "driver": { + "name": "axe-sarif-converter", + "fullName": "axe-sarif-converter v1.3.0", + "version": "1.3.0", + "semanticVersion": "1.3.0", + "informationUri": "https://github.com/microsoft/axe-sarif-converter/releases/tag/v1.3.0", + "downloadUri": "https://www.npmjs.com/package/axe-sarif-converter/v/1.3.0" + } + } + }, + "tool": { + "driver": { + "name": "axe-core", + "fullName": "axe for Web v3.2.2", + "shortDescription": { + "text": "An open source accessibility rules library for automated testing." + }, + "version": "3.2.2", + "semanticVersion": "3.2.2", + "informationUri": "https://www.deque.com/axe/axe-for-web/", + "downloadUri": "https://www.npmjs.com/package/axe-core/v/3.2.2", + "properties": { + "microsoft/qualityDomain": "Accessibility" + }, + "supportedTaxonomies": [ + { + "name": "WCAG", + "index": 0, + "guid": "ca34e0e1-5faf-4f55-a989-cdae42a98f18" + } + ], + "rules": [ + { + + } + ] + } + }, + "invocations": [ + { + "startTimeUtc": "2019-05-30T23:40:29.706Z", + "endTimeUtc": "2019-05-30T23:40:29.706Z", + "executionSuccessful": true + } + ], + "artifacts": [ + { + "location": { + "uri": "url-stub", + "index": 0 + }, + "sourceLanguage": "html", + "roles": [ + "analysisTarget" + ], + "description": { + "text": "" + } + } + ], + "results": [ + { + "ruleId": "document-title", + "level": "error", + "message": { + "text": "Fix any of the following: Document does not have a non-empty <title> element.", + "richText": "Fix any of the following:\n- Document does not have a non-empty <title> element" + }, + "locations": [ + { + "physicalLocation": { + "fileLocation": { + "uri": "url-stub" + } + }, + "fullyQualifiedLogicalName": "html", + "annotations": [ + { + "snippet": { + "text": "<html><head></head><body></body></html>" + } + } + ] + } + ], + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "fullyQualifiedLogicalName": "html", + "ruleId": "document-title" + } + }, + { + "ruleId": "html-has-lang", + "level": "error", + "message": { + "text": "Fix any of the following: The <html> element does not have a lang attribute.", + "richText": "Fix any of the following:\n- The <html> element does not have a lang attribute" + }, + "locations": [ + { + "physicalLocation": { + "fileLocation": { + "uri": "url-stub" + } + }, + "fullyQualifiedLogicalName": "html", + "annotations": [ + { + "snippet": { + "text": "<html><head></head><body></body></html>" + } + } + ] + } + ], + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "fullyQualifiedLogicalName": "html", + "ruleId": "html-has-lang" + } + }, + { + "ruleId": "landmark-one-main", + "level": "error", + "message": { + "text": "Fix all of the following: Document does not have a main landmark.", + "richText": "Fix all of the following:\n- Document does not have a main landmark" + }, + "locations": [ + { + "physicalLocation": { + "fileLocation": { + "uri": "url-stub" + } + }, + "fullyQualifiedLogicalName": "html", + "annotations": [ + { + "snippet": { + "text": "<html><head></head><body></body></html>" + } + } + ] + } + ], + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "fullyQualifiedLogicalName": "html", + "ruleId": "landmark-one-main" + } + }, + { + "ruleId": "page-has-heading-one", + "level": "error", + "message": { + "text": "Fix all of the following: Page must have a level-one heading.", + "richText": "Fix all of the following:\n- Page must have a level-one heading" + }, + "locations": [ + { + "physicalLocation": { + "fileLocation": { + "uri": "url-stub" + } + }, + "fullyQualifiedLogicalName": "html", + "annotations": [ + { + "snippet": { + "text": "<html><head></head><body></body></html>" + } + } + ] + } + ], + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "fullyQualifiedLogicalName": "html", + "ruleId": "page-has-heading-one" + } + }, + { + "ruleId": "aria-hidden-body", + "level": "pass", + "message": { + "text": "The following tests passed: No aria-hidden attribute is present on document body.", + "richText": "The following tests passed:\n- No aria-hidden attribute is present on document body" + }, + "locations": [ + { + "physicalLocation": { + "fileLocation": { + "uri": "url-stub" + } + }, + "fullyQualifiedLogicalName": "body", + "annotations": [ + { + "snippet": { + "text": "<body></body>" + } + } + ] + } + ], + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "fullyQualifiedLogicalName": "body", + "ruleId": "aria-hidden-body" + } + }, + { + "ruleId": "landmark-no-duplicate-banner", + "level": "pass", + "message": { + "text": "The following tests passed: Document does not have more than one banner landmark.", + "richText": "The following tests passed:\n- Document does not have more than one banner landmark" + }, + "locations": [ + { + "physicalLocation": { + "fileLocation": { + "uri": "url-stub" + } + }, + "fullyQualifiedLogicalName": "html", + "annotations": [ + { + "snippet": { + "text": "<html><head></head><body></body></html>" + } + } + ] + } + ], + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "fullyQualifiedLogicalName": "html", + "ruleId": "landmark-no-duplicate-banner" + } + }, + { + "ruleId": "landmark-no-duplicate-contentinfo", + "level": "pass", + "message": { + "text": "The following tests passed: Document does not have more than one contentinfo landmark.", + "richText": "The following tests passed:\n- Document does not have more than one contentinfo landmark" + }, + "locations": [ + { + "physicalLocation": { + "fileLocation": { + "uri": "url-stub" + } + }, + "fullyQualifiedLogicalName": "html", + "annotations": [ + { + "snippet": { + "text": "<html><head></head><body></body></html>" + } + } + ] + } + ], + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "fullyQualifiedLogicalName": "html", + "ruleId": "landmark-no-duplicate-contentinfo" + } + }, + { + "ruleId": "region", + "level": "pass", + "message": { + "text": "The following tests passed: All page content is contained by landmarks.", + "richText": "The following tests passed:\n- All page content is contained by landmarks" + }, + "locations": [ + { + "physicalLocation": { + "fileLocation": { + "uri": "url-stub" + } + }, + "fullyQualifiedLogicalName": "html", + "annotations": [ + { + "snippet": { + "text": "<html><head></head><body></body></html>" + } + } + ] + } + ], + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "fullyQualifiedLogicalName": "html", + "ruleId": "region" + } + }, + { + "ruleId": "accesskeys", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "accesskeys" + } + }, + { + "ruleId": "area-alt", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "area-alt" + } + }, + { + "ruleId": "aria-allowed-attr", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "aria-allowed-attr" + } + }, + { + "ruleId": "aria-allowed-role", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "aria-allowed-role" + } + }, + { + "ruleId": "aria-dpub-role-fallback", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "aria-dpub-role-fallback" + } + }, + { + "ruleId": "aria-hidden-focus", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "aria-hidden-focus" + } + }, + { + "ruleId": "aria-required-attr", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "aria-required-attr" + } + }, + { + "ruleId": "aria-required-children", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "aria-required-children" + } + }, + { + "ruleId": "aria-required-parent", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "aria-required-parent" + } + }, + { + "ruleId": "aria-roles", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "aria-roles" + } + }, + { + "ruleId": "aria-valid-attr-value", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "aria-valid-attr-value" + } + }, + { + "ruleId": "aria-valid-attr", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "aria-valid-attr" + } + }, + { + "ruleId": "autocomplete-valid", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "autocomplete-valid" + } + }, + { + "ruleId": "blink", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "blink" + } + }, + { + "ruleId": "button-name", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "button-name" + } + }, + { + "ruleId": "bypass", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "bypass" + } + }, + { + "ruleId": "checkboxgroup", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "checkboxgroup" + } + }, + { + "ruleId": "color-contrast", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "color-contrast" + } + }, + { + "ruleId": "definition-list", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "definition-list" + } + }, + { + "ruleId": "dlitem", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "dlitem" + } + }, + { + "ruleId": "duplicate-id-active", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "duplicate-id-active" + } + }, + { + "ruleId": "duplicate-id-aria", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "duplicate-id-aria" + } + }, + { + "ruleId": "duplicate-id", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "duplicate-id" + } + }, + { + "ruleId": "empty-heading", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "empty-heading" + } + }, + { + "ruleId": "form-field-multiple-labels", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "form-field-multiple-labels" + } + }, + { + "ruleId": "frame-tested", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "frame-tested" + } + }, + { + "ruleId": "frame-title-unique", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "frame-title-unique" + } + }, + { + "ruleId": "frame-title", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "frame-title" + } + }, + { + "ruleId": "heading-order", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "heading-order" + } + }, + { + "ruleId": "html-lang-valid", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "html-lang-valid" + } + }, + { + "ruleId": "html-xml-lang-mismatch", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "html-xml-lang-mismatch" + } + }, + { + "ruleId": "image-alt", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "image-alt" + } + }, + { + "ruleId": "image-redundant-alt", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "image-redundant-alt" + } + }, + { + "ruleId": "input-image-alt", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "input-image-alt" + } + }, + { + "ruleId": "label-title-only", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "label-title-only" + } + }, + { + "ruleId": "label", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "label" + } + }, + { + "ruleId": "landmark-banner-is-top-level", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "landmark-banner-is-top-level" + } + }, + { + "ruleId": "landmark-complementary-is-top-level", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "landmark-complementary-is-top-level" + } + }, + { + "ruleId": "landmark-contentinfo-is-top-level", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "landmark-contentinfo-is-top-level" + } + }, + { + "ruleId": "landmark-main-is-top-level", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "landmark-main-is-top-level" + } + }, + { + "ruleId": "layout-table", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "layout-table" + } + }, + { + "ruleId": "link-name", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "link-name" + } + }, + { + "ruleId": "list", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "list" + } + }, + { + "ruleId": "listitem", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "listitem" + } + }, + { + "ruleId": "marquee", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "marquee" + } + }, + { + "ruleId": "meta-refresh", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "meta-refresh" + } + }, + { + "ruleId": "meta-viewport-large", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "meta-viewport-large" + } + }, + { + "ruleId": "meta-viewport", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "meta-viewport" + } + }, + { + "ruleId": "object-alt", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "object-alt" + } + }, + { + "ruleId": "radiogroup", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "radiogroup" + } + }, + { + "ruleId": "scope-attr-valid", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "scope-attr-valid" + } + }, + { + "ruleId": "server-side-image-map", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "server-side-image-map" + } + }, + { + "ruleId": "skip-link", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "skip-link" + } + }, + { + "ruleId": "tabindex", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "tabindex" + } + }, + { + "ruleId": "table-duplicate-name", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "table-duplicate-name" + } + }, + { + "ruleId": "td-headers-attr", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "td-headers-attr" + } + }, + { + "ruleId": "th-has-data-cells", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "th-has-data-cells" + } + }, + { + "ruleId": "valid-lang", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "valid-lang" + } + }, + { + "ruleId": "video-caption", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "video-caption" + } + }, + { + "ruleId": "video-description", + "level": "notApplicable", + "properties": { + "tags": [ + "Accessibility" + ] + }, + "partialFingerprints": { + "ruleId": "video-description" + } + } + ], + "resources": { + "rules": { + "document-title": { + "id": "document-title", + "name": { + "text": "Documents must have <title> element to aid in navigation" + }, + "fullDescription": { + "text": "Ensures each HTML document contains a non-empty <title> element" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/document-title?application=axeAPI", + "properties": {} + }, + "html-has-lang": { + "id": "html-has-lang", + "name": { + "text": "<html> element must have a lang attribute" + }, + "fullDescription": { + "text": "Ensures every HTML document has a lang attribute" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/html-has-lang?application=axeAPI", + "properties": {} + }, + "landmark-one-main": { + "id": "landmark-one-main", + "name": { + "text": "Document must have one main landmark" + }, + "fullDescription": { + "text": "Ensures the document has only one main landmark and each iframe in the page has at most one main landmark" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/landmark-one-main?application=axeAPI", + "properties": {} + }, + "page-has-heading-one": { + "id": "page-has-heading-one", + "name": { + "text": "Page must contain a level-one heading" + }, + "fullDescription": { + "text": "Ensure that the page, or at least one of its frames contains a level-one heading" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/page-has-heading-one?application=axeAPI", + "properties": {} + }, + "aria-hidden-body": { + "id": "aria-hidden-body", + "name": { + "text": "aria-hidden='true' must not be present on the document body" + }, + "fullDescription": { + "text": "Ensures aria-hidden='true' is not present on the document body." + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/aria-hidden-body?application=axeAPI", + "properties": {} + }, + "landmark-no-duplicate-banner": { + "id": "landmark-no-duplicate-banner", + "name": { + "text": "Document must not have more than one banner landmark" + }, + "fullDescription": { + "text": "Ensures the document has at most one banner landmark" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/landmark-no-duplicate-banner?application=axeAPI", + "properties": {} + }, + "landmark-no-duplicate-contentinfo": { + "id": "landmark-no-duplicate-contentinfo", + "name": { + "text": "Document must not have more than one contentinfo landmark" + }, + "fullDescription": { + "text": "Ensures the document has at most one contentinfo landmark" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/landmark-no-duplicate-contentinfo?application=axeAPI", + "properties": {} + }, + "region": { + "id": "region", + "name": { + "text": "All page content must be contained by landmarks" + }, + "fullDescription": { + "text": "Ensures all page content is contained by landmarks" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/region?application=axeAPI", + "properties": {} + }, + "accesskeys": { + "id": "accesskeys", + "name": { + "text": "accesskey attribute value must be unique" + }, + "fullDescription": { + "text": "Ensures every accesskey attribute value is unique" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/accesskeys?application=axeAPI", + "properties": {} + }, + "area-alt": { + "id": "area-alt", + "name": { + "text": "Active <area> elements must have alternate text" + }, + "fullDescription": { + "text": "Ensures <area> elements of image maps have alternate text" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/area-alt?application=axeAPI", + "properties": {} + }, + "aria-allowed-attr": { + "id": "aria-allowed-attr", + "name": { + "text": "Elements must only use allowed ARIA attributes" + }, + "fullDescription": { + "text": "Ensures ARIA attributes are allowed for an element's role" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/aria-allowed-attr?application=axeAPI", + "properties": {} + }, + "aria-allowed-role": { + "id": "aria-allowed-role", + "name": { + "text": "ARIA role must be appropriate for the element" + }, + "fullDescription": { + "text": "Ensures role attribute has an appropriate value for the element" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/aria-allowed-role?application=axeAPI", + "properties": {} + }, + "aria-dpub-role-fallback": { + "id": "aria-dpub-role-fallback", + "name": { + "text": "Unsupported DPUB ARIA roles should be used on elements with implicit fallback roles" + }, + "fullDescription": { + "text": "Ensures unsupported DPUB roles are only used on elements with implicit fallback roles" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/aria-dpub-role-fallback?application=axeAPI", + "properties": {} + }, + "aria-hidden-focus": { + "id": "aria-hidden-focus", + "name": { + "text": "ARIA hidden element must not contain focusable elements" + }, + "fullDescription": { + "text": "Ensures aria-hidden elements do not contain focusable elements" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/aria-hidden-focus?application=axeAPI", + "properties": {} + }, + "aria-required-attr": { + "id": "aria-required-attr", + "name": { + "text": "Required ARIA attributes must be provided" + }, + "fullDescription": { + "text": "Ensures elements with ARIA roles have all required ARIA attributes" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/aria-required-attr?application=axeAPI", + "properties": {} + }, + "aria-required-children": { + "id": "aria-required-children", + "name": { + "text": "Certain ARIA roles must contain particular children" + }, + "fullDescription": { + "text": "Ensures elements with an ARIA role that require child roles contain them" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/aria-required-children?application=axeAPI", + "properties": {} + }, + "aria-required-parent": { + "id": "aria-required-parent", + "name": { + "text": "Certain ARIA roles must be contained by particular parents" + }, + "fullDescription": { + "text": "Ensures elements with an ARIA role that require parent roles are contained by them" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/aria-required-parent?application=axeAPI", + "properties": {} + }, + "aria-roles": { + "id": "aria-roles", + "name": { + "text": "ARIA roles used must conform to valid values" + }, + "fullDescription": { + "text": "Ensures all elements with a role attribute use a valid value" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/aria-roles?application=axeAPI", + "properties": {} + }, + "aria-valid-attr-value": { + "id": "aria-valid-attr-value", + "name": { + "text": "ARIA attributes must conform to valid values" + }, + "fullDescription": { + "text": "Ensures all ARIA attributes have valid values" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/aria-valid-attr-value?application=axeAPI", + "properties": {} + }, + "aria-valid-attr": { + "id": "aria-valid-attr", + "name": { + "text": "ARIA attributes must conform to valid names" + }, + "fullDescription": { + "text": "Ensures attributes that begin with aria- are valid ARIA attributes" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/aria-valid-attr?application=axeAPI", + "properties": {} + }, + "autocomplete-valid": { + "id": "autocomplete-valid", + "name": { + "text": "autocomplete attribute must be used correctly" + }, + "fullDescription": { + "text": "Ensure the autocomplete attribute is correct and suitable for the form field" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/autocomplete-valid?application=axeAPI", + "properties": {} + }, + "blink": { + "id": "blink", + "name": { + "text": "<blink> elements are deprecated and must not be used" + }, + "fullDescription": { + "text": "Ensures <blink> elements are not used" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/blink?application=axeAPI", + "properties": {} + }, + "button-name": { + "id": "button-name", + "name": { + "text": "Buttons must have discernible text" + }, + "fullDescription": { + "text": "Ensures buttons have discernible text" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/button-name?application=axeAPI", + "properties": {} + }, + "bypass": { + "id": "bypass", + "name": { + "text": "Page must have means to bypass repeated blocks" + }, + "fullDescription": { + "text": "Ensures each page has at least one mechanism for a user to bypass navigation and jump straight to the content" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/bypass?application=axeAPI", + "properties": {} + }, + "checkboxgroup": { + "id": "checkboxgroup", + "name": { + "text": "Checkbox inputs with the same name attribute value must be part of a group" + }, + "fullDescription": { + "text": "Ensures related <input type=\"checkbox\"> elements have a group and that the group designation is consistent" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/checkboxgroup?application=axeAPI", + "properties": {} + }, + "color-contrast": { + "id": "color-contrast", + "name": { + "text": "Elements must have sufficient color contrast" + }, + "fullDescription": { + "text": "Ensures the contrast between foreground and background colors meets WCAG 2 AA contrast ratio thresholds" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/color-contrast?application=axeAPI", + "properties": {} + }, + "definition-list": { + "id": "definition-list", + "name": { + "text": "<dl> elements must only directly contain properly-ordered <dt> and <dd> groups, <script> or <template> elements" + }, + "fullDescription": { + "text": "Ensures <dl> elements are structured correctly" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/definition-list?application=axeAPI", + "properties": {} + }, + "dlitem": { + "id": "dlitem", + "name": { + "text": "<dt> and <dd> elements must be contained by a <dl>" + }, + "fullDescription": { + "text": "Ensures <dt> and <dd> elements are contained by a <dl>" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/dlitem?application=axeAPI", + "properties": {} + }, + "duplicate-id-active": { + "id": "duplicate-id-active", + "name": { + "text": "IDs of active elements must be unique" + }, + "fullDescription": { + "text": "Ensures every id attribute value of active elements is unique" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/duplicate-id-active?application=axeAPI", + "properties": {} + }, + "duplicate-id-aria": { + "id": "duplicate-id-aria", + "name": { + "text": "IDs used in ARIA and labels must be unique" + }, + "fullDescription": { + "text": "Ensures every id attribute value used in ARIA and in labels is unique" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/duplicate-id-aria?application=axeAPI", + "properties": {} + }, + "duplicate-id": { + "id": "duplicate-id", + "name": { + "text": "id attribute value must be unique" + }, + "fullDescription": { + "text": "Ensures every id attribute value is unique" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/duplicate-id?application=axeAPI", + "properties": {} + }, + "empty-heading": { + "id": "empty-heading", + "name": { + "text": "Headings must not be empty" + }, + "fullDescription": { + "text": "Ensures headings have discernible text" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/empty-heading?application=axeAPI", + "properties": {} + }, + "form-field-multiple-labels": { + "id": "form-field-multiple-labels", + "name": { + "text": "Form field must not have multiple label elements" + }, + "fullDescription": { + "text": "Ensures form field does not have multiple label elements" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/form-field-multiple-labels?application=axeAPI", + "properties": {} + }, + "frame-tested": { + "id": "frame-tested", + "name": { + "text": "Frames must be tested with axe-core" + }, + "fullDescription": { + "text": "Ensures <iframe> and <frame> elements contain the axe-core script" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/frame-tested?application=axeAPI", + "properties": {} + }, + "frame-title-unique": { + "id": "frame-title-unique", + "name": { + "text": "Frames must have a unique title attribute" + }, + "fullDescription": { + "text": "Ensures <iframe> and <frame> elements contain a unique title attribute" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/frame-title-unique?application=axeAPI", + "properties": {} + }, + "frame-title": { + "id": "frame-title", + "name": { + "text": "Frames must have title attribute" + }, + "fullDescription": { + "text": "Ensures <iframe> and <frame> elements contain a non-empty title attribute" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/frame-title?application=axeAPI", + "properties": {} + }, + "heading-order": { + "id": "heading-order", + "name": { + "text": "Heading levels should only increase by one" + }, + "fullDescription": { + "text": "Ensures the order of headings is semantically correct" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/heading-order?application=axeAPI", + "properties": {} + }, + "html-lang-valid": { + "id": "html-lang-valid", + "name": { + "text": "<html> element must have a valid value for the lang attribute" + }, + "fullDescription": { + "text": "Ensures the lang attribute of the <html> element has a valid value" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/html-lang-valid?application=axeAPI", + "properties": {} + }, + "html-xml-lang-mismatch": { + "id": "html-xml-lang-mismatch", + "name": { + "text": "HTML elements with lang and xml:lang must have the same base language" + }, + "fullDescription": { + "text": "Ensure that HTML elements with both valid lang and xml:lang attributes agree on the base language of the page" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/html-xml-lang-mismatch?application=axeAPI", + "properties": {} + }, + "image-alt": { + "id": "image-alt", + "name": { + "text": "Images must have alternate text" + }, + "fullDescription": { + "text": "Ensures <img> elements have alternate text or a role of none or presentation" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/image-alt?application=axeAPI", + "properties": {} + }, + "image-redundant-alt": { + "id": "image-redundant-alt", + "name": { + "text": "Text of buttons and links should not be repeated in the image alternative" + }, + "fullDescription": { + "text": "Ensure button and link text is not repeated as image alternative" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/image-redundant-alt?application=axeAPI", + "properties": {} + }, + "input-image-alt": { + "id": "input-image-alt", + "name": { + "text": "Image buttons must have alternate text" + }, + "fullDescription": { + "text": "Ensures <input type=\"image\"> elements have alternate text" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/input-image-alt?application=axeAPI", + "properties": {} + }, + "label-title-only": { + "id": "label-title-only", + "name": { + "text": "Form elements should have a visible label" + }, + "fullDescription": { + "text": "Ensures that every form element is not solely labeled using the title or aria-describedby attributes" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/label-title-only?application=axeAPI", + "properties": {} + }, + "label": { + "id": "label", + "name": { + "text": "Form elements must have labels" + }, + "fullDescription": { + "text": "Ensures every form element has a label" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/label?application=axeAPI", + "properties": {} + }, + "landmark-banner-is-top-level": { + "id": "landmark-banner-is-top-level", + "name": { + "text": "Banner landmark must not be contained in another landmark" + }, + "fullDescription": { + "text": "Ensures the banner landmark is at top level" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/landmark-banner-is-top-level?application=axeAPI", + "properties": {} + }, + "landmark-complementary-is-top-level": { + "id": "landmark-complementary-is-top-level", + "name": { + "text": "Aside must not be contained in another landmark" + }, + "fullDescription": { + "text": "Ensures the complementary landmark or aside is at top level" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/landmark-complementary-is-top-level?application=axeAPI", + "properties": {} + }, + "landmark-contentinfo-is-top-level": { + "id": "landmark-contentinfo-is-top-level", + "name": { + "text": "Contentinfo landmark must not be contained in another landmark" + }, + "fullDescription": { + "text": "Ensures the contentinfo landmark is at top level" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/landmark-contentinfo-is-top-level?application=axeAPI", + "properties": {} + }, + "landmark-main-is-top-level": { + "id": "landmark-main-is-top-level", + "name": { + "text": "Main landmark must not be contained in another landmark" + }, + "fullDescription": { + "text": "Ensures the main landmark is at top level" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/landmark-main-is-top-level?application=axeAPI", + "properties": {} + }, + "layout-table": { + "id": "layout-table", + "name": { + "text": "Layout tables must not use data table elements" + }, + "fullDescription": { + "text": "Ensures presentational <table> elements do not use <th>, <caption> elements or the summary attribute" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/layout-table?application=axeAPI", + "properties": {} + }, + "link-name": { + "id": "link-name", + "name": { + "text": "Links must have discernible text" + }, + "fullDescription": { + "text": "Ensures links have discernible text" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/link-name?application=axeAPI", + "properties": {} + }, + "list": { + "id": "list", + "name": { + "text": "<ul> and <ol> must only directly contain <li>, <script> or <template> elements" + }, + "fullDescription": { + "text": "Ensures that lists are structured correctly" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/list?application=axeAPI", + "properties": {} + }, + "listitem": { + "id": "listitem", + "name": { + "text": "<li> elements must be contained in a <ul> or <ol>" + }, + "fullDescription": { + "text": "Ensures <li> elements are used semantically" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/listitem?application=axeAPI", + "properties": {} + }, + "marquee": { + "id": "marquee", + "name": { + "text": "<marquee> elements are deprecated and must not be used" + }, + "fullDescription": { + "text": "Ensures <marquee> elements are not used" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/marquee?application=axeAPI", + "properties": {} + }, + "meta-refresh": { + "id": "meta-refresh", + "name": { + "text": "Timed refresh must not exist" + }, + "fullDescription": { + "text": "Ensures <meta http-equiv=\"refresh\"> is not used" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/meta-refresh?application=axeAPI", + "properties": {} + }, + "meta-viewport-large": { + "id": "meta-viewport-large", + "name": { + "text": "Users should be able to zoom and scale the text up to 500%" + }, + "fullDescription": { + "text": "Ensures <meta name=\"viewport\"> can scale a significant amount" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/meta-viewport-large?application=axeAPI", + "properties": {} + }, + "meta-viewport": { + "id": "meta-viewport", + "name": { + "text": "Zooming and scaling must not be disabled" + }, + "fullDescription": { + "text": "Ensures <meta name=\"viewport\"> does not disable text scaling and zooming" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/meta-viewport?application=axeAPI", + "properties": {} + }, + "object-alt": { + "id": "object-alt", + "name": { + "text": "<object> elements must have alternate text" + }, + "fullDescription": { + "text": "Ensures <object> elements have alternate text" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/object-alt?application=axeAPI", + "properties": {} + }, + "radiogroup": { + "id": "radiogroup", + "name": { + "text": "Radio inputs with the same name attribute value must be part of a group" + }, + "fullDescription": { + "text": "Ensures related <input type=\"radio\"> elements have a group and that the group designation is consistent" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/radiogroup?application=axeAPI", + "properties": {} + }, + "scope-attr-valid": { + "id": "scope-attr-valid", + "name": { + "text": "scope attribute should be used correctly" + }, + "fullDescription": { + "text": "Ensures the scope attribute is used correctly on tables" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/scope-attr-valid?application=axeAPI", + "properties": {} + }, + "server-side-image-map": { + "id": "server-side-image-map", + "name": { + "text": "Server-side image maps must not be used" + }, + "fullDescription": { + "text": "Ensures that server-side image maps are not used" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/server-side-image-map?application=axeAPI", + "properties": {} + }, + "skip-link": { + "id": "skip-link", + "name": { + "text": "The skip-link target should exist and be focusable" + }, + "fullDescription": { + "text": "Ensure all skip links have a focusable target" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/skip-link?application=axeAPI", + "properties": {} + }, + "tabindex": { + "id": "tabindex", + "name": { + "text": "Elements should not have tabindex greater than zero" + }, + "fullDescription": { + "text": "Ensures tabindex attribute values are not greater than 0" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/tabindex?application=axeAPI", + "properties": {} + }, + "table-duplicate-name": { + "id": "table-duplicate-name", + "name": { + "text": "The <caption> element should not contain the same text as the summary attribute" + }, + "fullDescription": { + "text": "Ensure that tables do not have the same summary and caption" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/table-duplicate-name?application=axeAPI", + "properties": {} + }, + "td-headers-attr": { + "id": "td-headers-attr", + "name": { + "text": "All cells in a table element that use the headers attribute must only refer to other cells of that same table" + }, + "fullDescription": { + "text": "Ensure that each cell in a table using the headers refers to another cell in that table" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/td-headers-attr?application=axeAPI", + "properties": {} + }, + "th-has-data-cells": { + "id": "th-has-data-cells", + "name": { + "text": "All th elements and elements with role=columnheader/rowheader must have data cells they describe" + }, + "fullDescription": { + "text": "Ensure that each table header in a data table refers to data cells" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/th-has-data-cells?application=axeAPI", + "properties": {} + }, + "valid-lang": { + "id": "valid-lang", + "name": { + "text": "lang attribute must have a valid value" + }, + "fullDescription": { + "text": "Ensures lang attributes have valid values" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/valid-lang?application=axeAPI", + "properties": {} + }, + "video-caption": { + "id": "video-caption", + "name": { + "text": "<video> elements must have captions" + }, + "fullDescription": { + "text": "Ensures <video> elements have captions" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/video-caption?application=axeAPI", + "properties": {} + }, + "video-description": { + "id": "video-description", + "name": { + "text": "<video> elements must have an audio description track" + }, + "fullDescription": { + "text": "Ensures <video> elements have audio descriptions" + }, + "helpUri": "https://dequeuniversity.com/rules/axe/3.2/video-description?application=axeAPI", + "properties": {} + } + } + }, + "properties": {} + } + ] +}