Skip to content

Commit

Permalink
feat(eslint-plugin-template): [accessibility-interactive-supports-foc…
Browse files Browse the repository at this point in the history
…us] supports contenteditable
  • Loading branch information
sandikbarr committed Sep 18, 2022
1 parent b2d6a47 commit 486a6f7
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 1 deletion.
Expand Up @@ -9,6 +9,7 @@ import {
isInteractiveElement,
isNonInteractiveRole,
} from '../utils/is-interactive-element';
import { isContentEditable } from '../utils/is-content-editable';
import { isDisabledElement } from '../utils/is-disabled-element';
import { isPresentationRole } from '../utils/is-presentation-role';

Expand Down Expand Up @@ -68,7 +69,8 @@ export default createESLintRule<Options, MessageIds>({
interactiveOutput &&
!tabIndex &&
!isInteractiveElement(node) &&
!isNonInteractiveRole(node)
!isNonInteractiveRole(node) &&
!isContentEditable(node)
) {
const parserServices = getTemplateParserServices(context);
const loc = parserServices.convertNodeSourceSpanToLoc(
Expand Down
16 changes: 16 additions & 0 deletions packages/eslint-plugin-template/src/utils/is-content-editable.ts
@@ -0,0 +1,16 @@
import type { TmplAstElement } from '@angular-eslint/bundled-angular-compiler';
import { getOriginalAttributeName } from './get-original-attribute-name';
import { getAttributeValue } from './get-attribute-value';

export function isContentEditable(node: TmplAstElement): boolean {
const attributesInputs = [...node.attributes, ...node.inputs];
const contentEditableAttr = attributesInputs.find(
(attr) => getOriginalAttributeName(attr) === 'contenteditable',
);
const contentEditableValue = getAttributeValue(node, 'contenteditable');
return (
!!contentEditableAttr &&
(contentEditableValue === '' ||
String(contentEditableValue).toLowerCase() === 'true')
);
}
Expand Up @@ -154,6 +154,15 @@ export const valid = [
<div role="textbox" tabindex="0" (click)="onClick()"></div>
`,
},

// elements with contenteditable enabled are interactive by default
{
code: `
<div contenteditable="true" (keyup)="onKeyUp()">Edit this text</div>
<div [attr.contenteditable]="true" (keydown)="onKeyDown()">Edit this text</div>
<div contenteditable (keypress)="onKeyPress()">Edit this too!</div>
`,
},
];

export const invalid = [
Expand Down Expand Up @@ -267,4 +276,15 @@ export const invalid = [
`,
messageId,
}),

// contenteditable="false"
convertAnnotatedSourceToFailureCase({
description:
'should fail non-interactive element with contenteditable disabled does not support focus',
annotatedSource: `
<div [attr.contenteditable]="false" (keyup)="onKeyUp()">Cannot be focused</div>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`,
messageId,
}),
];

0 comments on commit 486a6f7

Please sign in to comment.