chrome-devtools-frontend
Version:
Chrome DevTools UI
155 lines (146 loc) • 7.41 kB
text/typescript
// Copyright 2025 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import * as i18n from '../../core/i18n/i18n.js';
import * as Protocol from '../../generated/protocol.js';
import * as IssuesManager from '../../models/issues_manager/issues_manager.js';
const UIStrings = {
/**
* @description Tooltip text shown in the Elements panel when an element has an error.
*/
formLabelForNameError: 'Incorrect use of <label for=FORM_ELEMENT>',
/**
* @description Tooltip text shown in the Elements panel when an element has an error.
*/
formDuplicateIdForInputError: 'Duplicate form field id in the same form',
/**
* @description Tooltip text shown in the Elements panel when an element has an error.
*/
formInputWithNoLabelError: 'Form field without valid aria-labelledby attribute or associated label',
/**
* @description Tooltip text shown in the Elements panel when an element has an error.
*/
formAutocompleteAttributeEmptyError: 'Incorrect use of autocomplete attribute',
/**
* @description Tooltip text shown in the Elements panel when an element has an error.
*/
formEmptyIdAndNameAttributesForInputError: 'A form field element should have an id or name attribute',
/**
* @description Tooltip text shown in the Elements panel when an element has an error.
*/
formAriaLabelledByToNonExistingId: 'An aria-labelledby attribute doesn\'t match any element id',
/**
* @description Tooltip text shown in the Elements panel when an element has an error.
*/
formInputAssignedAutocompleteValueToIdOrNameAttributeError: 'An element doesn\'t have an autocomplete attribute',
/**
* @description Tooltip text shown in the Elements panel when an element has an error.
*/
formLabelHasNeitherForNorNestedInput: 'No label associated with a form field',
/**
* @description Tooltip text shown in the Elements panel when an element has an error.
*/
formLabelForMatchesNonExistingIdError: 'Incorrect use of <label for=FORM_ELEMENT>',
/**
* @description Tooltip text shown in the Elements panel when an element has an error.
*/
formInputHasWrongButWellIntendedAutocompleteValueError: 'Non-standard autocomplete attribute value',
/**
* @description Tooltip text shown in the Elements panel when an element has an error.
*/
disallowedSelectChild: 'Invalid element or text node within <select>',
/**
* @description Tooltip text shown in the Elements panel when an element has an error.
*/
disallowedOptGroupChild: 'Invalid element or text node within <optgroup>',
/**
* @description Tooltip text shown in the Elements panel when an element has an error.
*/
nonPhrasingContentOptionChild: 'Non-phrasing content used within an <option> element',
/**
* @description Tooltip text shown in the Elements panel when an element has an error.
*/
interactiveContentOptionChild: 'Interactive element inside of an <option> element',
/**
* @description Tooltip text shown in the Elements panel when an element has an error.
*/
interactiveContentLegendChild: 'Interactive element inside of a <legend> element',
/**
* @description Tooltip text shown in the Elements panel when an element has an error.
*/
interactiveContentAttributesSelectDescendant: 'Element with invalid attributes within a <select> element',
} as const;
const str_ = i18n.i18n.registerUIStrings('panels/elements/ElementIssueUtils.ts', UIStrings);
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
export interface ElementIssueDetails {
tooltip: string;
nodeId?: Protocol.DOM.BackendNodeId;
attribute?: string;
}
export function getElementIssueDetails(issue: IssuesManager.Issue.Issue): ElementIssueDetails|undefined {
if (issue instanceof IssuesManager.GenericIssue.GenericIssue) {
const issueDetails = issue.details();
return {
tooltip: getTooltipFromGenericIssue(issueDetails.errorType),
nodeId: issueDetails.violatingNodeId,
attribute: issueDetails.violatingNodeAttribute,
};
}
if (issue instanceof IssuesManager.SelectElementAccessibilityIssue.SelectElementAccessibilityIssue) {
const issueDetails = issue.details();
if (issue.isInteractiveContentAttributesSelectDescendantIssue()) {
return {
tooltip: i18nString(UIStrings.interactiveContentAttributesSelectDescendant),
nodeId: issueDetails.nodeId,
};
}
return {
tooltip: getTooltipFromSelectElementAccessibilityIssue(issueDetails.selectElementAccessibilityIssueReason),
nodeId: issueDetails.nodeId,
};
}
return undefined;
}
function getTooltipFromGenericIssue(errorType: Protocol.Audits.GenericIssueErrorType): string {
switch (errorType) {
case Protocol.Audits.GenericIssueErrorType.FormLabelForNameError:
return i18nString(UIStrings.formLabelForNameError);
case Protocol.Audits.GenericIssueErrorType.FormDuplicateIdForInputError:
return i18nString(UIStrings.formDuplicateIdForInputError);
case Protocol.Audits.GenericIssueErrorType.FormInputWithNoLabelError:
return i18nString(UIStrings.formInputWithNoLabelError);
case Protocol.Audits.GenericIssueErrorType.FormAutocompleteAttributeEmptyError:
return i18nString(UIStrings.formAutocompleteAttributeEmptyError);
case Protocol.Audits.GenericIssueErrorType.FormEmptyIdAndNameAttributesForInputError:
return i18nString(UIStrings.formEmptyIdAndNameAttributesForInputError);
case Protocol.Audits.GenericIssueErrorType.FormAriaLabelledByToNonExistingId:
return i18nString(UIStrings.formAriaLabelledByToNonExistingId);
case Protocol.Audits.GenericIssueErrorType.FormInputAssignedAutocompleteValueToIdOrNameAttributeError:
return i18nString(UIStrings.formInputAssignedAutocompleteValueToIdOrNameAttributeError);
case Protocol.Audits.GenericIssueErrorType.FormLabelHasNeitherForNorNestedInput:
return i18nString(UIStrings.formLabelHasNeitherForNorNestedInput);
case Protocol.Audits.GenericIssueErrorType.FormLabelForMatchesNonExistingIdError:
return i18nString(UIStrings.formLabelForMatchesNonExistingIdError);
case Protocol.Audits.GenericIssueErrorType.FormInputHasWrongButWellIntendedAutocompleteValueError:
return i18nString(UIStrings.formInputHasWrongButWellIntendedAutocompleteValueError);
default:
return '';
}
}
function getTooltipFromSelectElementAccessibilityIssue(reason: Protocol.Audits.SelectElementAccessibilityIssueReason):
string {
switch (reason) {
case Protocol.Audits.SelectElementAccessibilityIssueReason.DisallowedSelectChild:
return i18nString(UIStrings.disallowedSelectChild);
case Protocol.Audits.SelectElementAccessibilityIssueReason.DisallowedOptGroupChild:
return i18nString(UIStrings.disallowedOptGroupChild);
case Protocol.Audits.SelectElementAccessibilityIssueReason.NonPhrasingContentOptionChild:
return i18nString(UIStrings.nonPhrasingContentOptionChild);
case Protocol.Audits.SelectElementAccessibilityIssueReason.InteractiveContentOptionChild:
return i18nString(UIStrings.interactiveContentOptionChild);
case Protocol.Audits.SelectElementAccessibilityIssueReason.InteractiveContentLegendChild:
return i18nString(UIStrings.interactiveContentLegendChild);
default:
return '';
}
}