@angular-eslint/eslint-plugin-template 4.3.1-alpha.16 → 4.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/configs/all.json
CHANGED
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
"@angular-eslint/template/click-events-have-key-events": "error",
|
|
12
12
|
"@angular-eslint/template/conditional-complexity": "error",
|
|
13
13
|
"@angular-eslint/template/cyclomatic-complexity": "error",
|
|
14
|
-
"@angular-eslint/template/eqeqeq": "error",
|
|
15
14
|
"@angular-eslint/template/i18n": "error",
|
|
16
15
|
"@angular-eslint/template/mouse-events-have-key-events": "error",
|
|
17
16
|
"@angular-eslint/template/no-any": "error",
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
import { RULE_NAME as accessibilityAltTextRuleName } from './rules/accessibility-alt-text';
|
|
2
|
+
import { RULE_NAME as accessibilityElementsContentRuleName } from './rules/accessibility-elements-content';
|
|
3
|
+
import { RULE_NAME as accessibilityLabelForRuleName } from './rules/accessibility-label-for';
|
|
4
|
+
import { RULE_NAME as accessibilityLabelHasAssociatedControlRuleName } from './rules/accessibility-label-has-associated-control';
|
|
5
|
+
import { RULE_NAME as accessibilityTableScopeRuleName } from './rules/accessibility-table-scope';
|
|
6
|
+
import { RULE_NAME as accessibilityValidAriaRuleName } from './rules/accessibility-valid-aria';
|
|
7
|
+
import { RULE_NAME as bananaInBoxRuleName } from './rules/banana-in-box';
|
|
8
|
+
import { RULE_NAME as clickEventsHaveKeyEventsRuleName } from './rules/click-events-have-key-events';
|
|
9
|
+
import { RULE_NAME as conditionalСomplexityRuleName } from './rules/conditional-complexity';
|
|
10
|
+
import { RULE_NAME as cyclomaticComplexityRuleName } from './rules/cyclomatic-complexity';
|
|
11
|
+
import { RULE_NAME as i18nRuleName } from './rules/i18n';
|
|
12
|
+
import { RULE_NAME as mouseEventsHaveKeyEventsRuleName } from './rules/mouse-events-have-key-events-rule';
|
|
13
|
+
import { RULE_NAME as noAnyRuleName } from './rules/no-any';
|
|
14
|
+
import { RULE_NAME as noAutofocusRuleName } from './rules/no-autofocus';
|
|
15
|
+
import { RULE_NAME as noCallExpressionRuleName } from './rules/no-call-expression';
|
|
16
|
+
import { RULE_NAME as noDistractingElementsRuleName } from './rules/no-distracting-elements';
|
|
17
|
+
import { RULE_NAME as noDuplicateAttributesRuleName } from './rules/no-duplicate-attributes';
|
|
18
|
+
import { RULE_NAME as noNegatedAsyncRuleName } from './rules/no-negated-async';
|
|
19
|
+
import { RULE_NAME as noPositiveTabindexRuleName } from './rules/no-positive-tabindex';
|
|
20
|
+
import { RULE_NAME as useTrackByFunctionRuleName } from './rules/use-track-by-function';
|
|
1
21
|
declare const _default: {
|
|
2
22
|
configs: {
|
|
3
23
|
all: {
|
|
@@ -13,7 +33,6 @@ declare const _default: {
|
|
|
13
33
|
"@angular-eslint/template/click-events-have-key-events": string;
|
|
14
34
|
"@angular-eslint/template/conditional-complexity": string;
|
|
15
35
|
"@angular-eslint/template/cyclomatic-complexity": string;
|
|
16
|
-
"@angular-eslint/template/eqeqeq": string;
|
|
17
36
|
"@angular-eslint/template/i18n": string;
|
|
18
37
|
"@angular-eslint/template/mouse-events-have-key-events": string;
|
|
19
38
|
"@angular-eslint/template/no-any": string;
|
|
@@ -34,7 +53,6 @@ declare const _default: {
|
|
|
34
53
|
extends: string;
|
|
35
54
|
rules: {
|
|
36
55
|
"@angular-eslint/template/banana-in-box": string;
|
|
37
|
-
"@angular-eslint/template/eqeqeq": string;
|
|
38
56
|
"@angular-eslint/template/no-negated-async": string;
|
|
39
57
|
};
|
|
40
58
|
};
|
|
@@ -80,9 +98,6 @@ declare const _default: {
|
|
|
80
98
|
"cyclomatic-complexity": import("@typescript-eslint/experimental-utils/dist/ts-eslint/Rule").RuleModule<"cyclomaticComplexity", [{
|
|
81
99
|
maxComplexity: number;
|
|
82
100
|
}], import("@typescript-eslint/experimental-utils/dist/ts-eslint/Rule").RuleListener>;
|
|
83
|
-
eqeqeq: import("@typescript-eslint/experimental-utils/dist/ts-eslint/Rule").RuleModule<"eqeqeq", [{
|
|
84
|
-
readonly allowNullOrUndefined?: boolean | undefined;
|
|
85
|
-
}], import("@typescript-eslint/experimental-utils/dist/ts-eslint/Rule").RuleListener>;
|
|
86
101
|
i18n: import("@typescript-eslint/experimental-utils/dist/ts-eslint/Rule").RuleModule<import("./rules/i18n").MessageIds, [{
|
|
87
102
|
readonly boundTextAllowedPattern?: string | undefined;
|
|
88
103
|
readonly checkId?: boolean | undefined;
|
|
@@ -99,7 +114,7 @@ declare const _default: {
|
|
|
99
114
|
"no-duplicate-attributes": import("@typescript-eslint/experimental-utils/dist/ts-eslint/Rule").RuleModule<"noDuplicateAttributes", [{
|
|
100
115
|
allowTwoWayDataBinding?: boolean | undefined;
|
|
101
116
|
}], import("@typescript-eslint/experimental-utils/dist/ts-eslint/Rule").RuleListener>;
|
|
102
|
-
"no-negated-async": import("@typescript-eslint/experimental-utils/dist/ts-eslint/Rule").RuleModule<"
|
|
117
|
+
"no-negated-async": import("@typescript-eslint/experimental-utils/dist/ts-eslint/Rule").RuleModule<import("./rules/no-negated-async").MessageIds, [], import("@typescript-eslint/experimental-utils/dist/ts-eslint/Rule").RuleListener>;
|
|
103
118
|
"no-positive-tabindex": import("@typescript-eslint/experimental-utils/dist/ts-eslint/Rule").RuleModule<"noPositiveTabindex", [], import("@typescript-eslint/experimental-utils/dist/ts-eslint/Rule").RuleListener>;
|
|
104
119
|
"use-track-by-function": import("@typescript-eslint/experimental-utils/dist/ts-eslint/Rule").RuleModule<"useTrackByFunction", [], import("@typescript-eslint/experimental-utils/dist/ts-eslint/Rule").RuleListener>;
|
|
105
120
|
};
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var e=require("typescript"),t=require("@typescript-eslint/experimental-utils"),n=require("@angular/compiler"),a=require("aria-query");function r(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var o=r(e);function s(e,t){const n=(e=e.replace(/\r\n/g,"\n")).indexOf(t);return[n,n+t.length]}const i=new Map;var c={"extract-inline-html":{preprocess:function(e,t){const n=[e];if(!function(e,t){return!![".component.ts",".page.ts",".dialog.ts",".modal.ts",".popover.ts",".bottomsheet.ts",".snackbar.ts"].some(e=>t.endsWith(e))||!(!e.includes("Component")||!e.includes("@angular/core"))}(e,t))return n;try{const a=o.default.createSourceFile(t,e,o.default.ScriptTarget.Latest,!0),r=a.statements.filter(e=>o.default.isClassDeclaration(e));if(!r||!r.length)return n;const c=[];for(const e of r)if(e.decorators)for(const t of e.decorators)o.default.isCallExpression(t.expression)&&o.default.isIdentifier(t.expression.expression)&&"Component"===t.expression.expression.text&&c.push(t);if(!c||!c.length)return n;const l=[e];let u=0;for(const t of c){if(!o.default.isDecorator(t)||!o.default.isCallExpression(t.expression)||1!==t.expression.arguments.length)continue;const n=t.expression.arguments[0];if(!o.default.isObjectLiteralExpression(n))continue;const r=n.properties.find(e=>e&&e.name&&"template"===e.name.getText());if(n.properties.find(e=>e&&e.name&&"templateUrl"===e.name.getText())||!r)continue;if(!o.default.isPropertyAssignment(r)||!o.default.isStringLiteralLike(r.initializer))continue;const c=r.initializer.text,m=s(e,c),p=`inline-template-${++u}.component.html`;i.set(p,{range:m,lineAndCharacter:{start:a.getLineAndCharacterOfPosition(m[0]),end:a.getLineAndCharacterOfPosition(m[1])}}),l.push({text:c,filename:p})}return l}catch(e){return console.log(e),console.error("preprocess: ERROR could not parse @Component() metadata",t),n}},postprocess:function(e,t){const n=e[0];if(1===e.length)return n;const a=e.slice(1);return[...n,...[].concat(...a.map((e,t)=>{const n=`inline-template-${++t}.component.html`,a=i.get(n);return a?e.map(e=>{if(e.line=e.line+a.lineAndCharacter.start.line,e.endLine=e.endLine+a.lineAndCharacter.start.line,e.fix){const t=a.range[0];e.fix.range=[t+e.fix.range[0],t+e.fix.range[1]]}return e}):[]}))]},supportsAutofix:!0}};const l=t.ESLintUtils.RuleCreator(e=>"https://github.com/angular-eslint/angular-eslint");function u(e){return m(e),e.parserServices}function m(e){var t,n;if(null==(t=e.parserServices)||!t.convertNodeSourceSpanToLoc||null==(n=e.parserServices)||!n.convertElementSourceSpanToLoc)throw new Error("You have used a rule which requires '@angular-eslint/template-parser' to be used as the 'parser' in your ESLint config.")}const p=Symbol("PROPERTY");function d(e,t){const a=e.attributes.find(e=>e.name===t);if(a)return a.value;const r=e.inputs.find(e=>e.name===t);return r&&r.value instanceof n.ASTWithSource?r.value.ast instanceof n.LiteralPrimitive?r.value.ast.value:p:null}var g=l({name:"accessibility-alt-text",meta:{type:"suggestion",docs:{description:"Enforces alternate text for elements which require the alt, aria-label, aria-labelledby attributes.",category:"Best Practices",recommended:!1},schema:[],messages:{accessibilityAltText:"<{{element}}/> element must have a text alternative."}},defaultOptions:[],create(e){const t=u(e);return{"Element[name=/^(img|area|object|input)$/]"(n){if(!function(e){return"img"===e.name?function(e){return e.attributes.some(({name:e})=>b(e))||e.inputs.some(({name:e})=>b(e))}(e):"object"===e.name?function(e){let t=!1,n=!1;for(const a of e.attributes)t="title"===a.name,n=y(a.name);if(t||n)return!0;let a=!1,r=!1;for(const t of e.inputs)a="title"===t.name,r=y(t.name);return!(!a&&!r)||e.children.length>0&&!!e.children[0].value}(e):"area"===e.name?f(e):function(e){return"image"!==d(e,"type")||f(e)}(e)}(n)){const a=t.convertElementSourceSpanToLoc(e,n);e.report({loc:a,messageId:"accessibilityAltText",data:{element:n.name}})}}}}});function f(e){let t=!1,n=!1;for(const a of e.attributes)t=b(a.name),n=y(a.name);if(t||n)return!0;let a=!1,r=!1;for(const t of e.inputs)a=b(t.name),r=y(t.name);return a||r}function y(e){return"aria-label"===e||"aria-labelledby"===e}function b(e){return"alt"===e}function h(e){if("string"==typeof e){if("true"===e)return!0;if("false"===e)return!1}return e}function x(e){if("INPUT"===e.name.toUpperCase()){const t=d(e,"type");if("string"==typeof t&&"HIDDEN"===t.toUpperCase())return!0}const t=h(d(e,"aria-hidden"));return""===t||t===p||!0===t}const v=new Set(["aria-label","innerHtml","innerHTML","innerText","outerHTML","title"]);var S=l({name:"accessibility-elements-content",meta:{type:"suggestion",docs:{description:"Ensures that the heading, anchor and button elements have content in it",category:"Best Practices",recommended:!1},schema:[],messages:{accessibilityElementsContent:"<{{element}}> should have content"}},defaultOptions:[],create(e){const t=u(e);return{"Element[name=/^(a|button|h1|h2|h3|h4|h5|h6)$/][children.length=0]"(n){if(x(n))return;const{attributes:a,inputs:r,name:o,sourceSpan:s}=n;if([...a,...r].map(({name:e})=>e).some(e=>v.has(e)))return;const i=t.convertNodeSourceSpanToLoc(s);e.report({loc:i,messageId:"accessibilityElementsContent",data:{element:o}})}}}});function A(e,t){return function e({children:a}){return a.some(a=>a instanceof n.TmplAstElement&&(a.name===t||e(a)))}(e)}const T={items:{type:"string"},type:"array",uniqueItems:!0},C=["button","input","meter","output","progress","select","textarea"],I=["for","htmlFor"],E=["label"];var B=l({name:"accessibility-label-for",meta:{deprecated:!0,replacedBy:["accessibility-label-has-associated-control"],type:"suggestion",docs:{description:"Ensures that a label element/component is associated with a form element",category:"Best Practices",recommended:!1},schema:[{additionalProperties:!1,properties:{controlComponents:T,labelAttributes:T,labelComponents:T},type:"object"}],messages:{accessibilityLabelFor:"A label element/component must be associated with a form element"}},defaultOptions:[{controlComponents:C,labelAttributes:I,labelComponents:E}],create(e,[t]){const n=u(e),{controlComponents:a,labelAttributes:r,labelComponents:o}=function({controlComponents:e,labelAttributes:t,labelComponents:n}){return{controlComponents:new Set([...C,...null!=e?e:[]]),labelAttributes:new Set([...I,...null!=t?t:[]]),labelComponents:new Set([...E,...null!=n?n:[]])}}(t);var s;return{[`Element[name=${s=[...o],RegExp(`^(${s.join("|")})$`)}]`](t){const o=new Set([...t.attributes,...t.inputs].map(({name:e})=>e));if([...r].some(e=>o.has(e))||function(e,t){return Boolean([...e].some(e=>A(t,e)))}(a,t))return;const s=n.convertNodeSourceSpanToLoc(t.sourceSpan);e.report({loc:s,messageId:"accessibilityLabelFor"})}}}});const k="accessibility-label-has-associated-control",w=["input","meter","output","progress","select","textarea"],L=[{inputs:["for","htmlFor"],selector:"label"}];var O=l({name:k,meta:{type:"suggestion",docs:{description:"Ensures that a label element/component is associated with a form element",category:"Best Practices",recommended:!1},schema:[{additionalProperties:!1,properties:{controlComponents:{items:{type:"string"},type:"array",uniqueItems:!0},labelComponents:{items:{additionalProperties:!1,properties:{inputs:{items:{type:"string"},type:"array",uniqueItems:!0},selector:{type:"string"}},required:["selector"],type:"object"},type:"array",uniqueItems:!0}},type:"object"}],messages:{accessibilityLabelHasAssociatedControl:"A label component must be associated with a form element"}},defaultOptions:[{controlComponents:w,labelComponents:L}],create(e,[{controlComponents:t,labelComponents:n}]){const a=u(e),r=new Set([...w,...null!=t?t:[]]),o=[...L,...null!=n?n:[]],s=o.map(({selector:e})=>e);return{[`Element[name=${RegExp(`^(${s.join("|")})$`)}]`](t){var n;const s=o.find(({selector:e})=>e===t.name);if(!s)return;const i=new Set([...t.attributes,...t.inputs].map(({name:e})=>e));if((null==(n=s.inputs)?void 0:n.some(e=>i.has(e)))||function(e,t){return Boolean([...e].some(e=>A(t,e)))}(r,t))return;const c=a.convertNodeSourceSpanToLoc(t.sourceSpan);e.report({loc:c,messageId:"accessibilityLabelHasAssociatedControl"})}}}}),N=l({name:"accessibility-table-scope",meta:{type:"suggestion",docs:{description:"Ensures that scope is not used on any element except <th>",category:"Best Practices",recommended:!1},schema:[],messages:{accessibilityTableScope:"Scope attribute can only be on <th> element"}},defaultOptions:[],create(e){const t=u(e);return{'Element[name!="th"] > :matches(BoundAttribute[name="scope"], TextAttribute[name="scope"])'({sourceSpan:n}){const a=t.convertNodeSourceSpanToLoc(n);e.report({loc:a,messageId:"accessibilityTableScope"})}}}}),P=l({name:"accessibility-valid-aria",meta:{type:"suggestion",docs:{description:"Ensures that correct ARIA attributes and respective values are used",category:"Best Practices",recommended:!1},schema:[],messages:{accessibilityValidAria:"The `{{attribute}}` is an invalid ARIA attribute",accessibilityValidAriaValue:"The `{{attribute}}` has an invalid value. Check the valid values at https://raw.githack.com/w3c/aria/stable/#roles"}},defaultOptions:[],create(e){const t=u(e);return{"BoundAttribute[name=/^aria-.*/], TextAttribute[name=/^aria-.*/]"(r){const{name:o,sourceSpan:s}=r,i=a.aria.get(o),c=t.convertNodeSourceSpanToLoc(s);if(!i)return void e.report({loc:c,messageId:"accessibilityValidAria",data:{attribute:o}});const l=function(e){return e instanceof n.TmplAstBoundAttribute?e.value.ast:e}(r);(function(e){return!function(e){return e instanceof n.LiteralArray||e instanceof n.LiteralMap}(e)&&!function(e){return e instanceof n.LiteralPrimitive||e instanceof n.TmplAstTextAttribute}(e)})(l)||function({allowundefined:e,type:t,values:n},a){if(e&&F(a))return!0;switch(t){case"boolean":return q(a);case"tristate":return q(a)||F(a);case"id":case"idlist":return!0;case"integer":return r=a,!Number.isNaN(r)&&parseInt(Number(r))==r&&!Number.isNaN(parseInt(r,10));case"number":return function(e){return!Number.isNaN(Number.parseFloat(e))&&Number.isFinite(e)}(a);case"string":return function(e){return"string"==typeof e}(a);case"token":case"tokenlist":{const e=q(a)?JSON.parse(a):a;return Boolean(null==n?void 0:n.includes(e))}}var r}(i,l.value)||e.report({loc:c,messageId:"accessibilityValidAriaValue",data:{attribute:o}})}}}});function q(e){return"boolean"==typeof e||"false"===e||"true"===e}function F(e){return null==e}const $=/\[(.*)\]/;var j=l({name:"banana-in-box",meta:{type:"suggestion",docs:{description:"Ensures that the two-way data binding syntax is correct",category:"Best Practices",recommended:"error"},fixable:"code",schema:[],messages:{bananaInBox:"Invalid binding syntax. Use [(expr)] instead"}},defaultOptions:[],create(e){const t=u(e),n=e.getSourceCode();return{BoundEvent({name:a,sourceSpan:r}){const o=a.match($);if(!o)return;const[,s]=o,i=`[(${s})]`,c=t.convertNodeSourceSpanToLoc(r),l=n.getIndexFromLoc(c.start);e.report({messageId:"bananaInBox",loc:c,fix:e=>e.replaceTextRange([l,l+a.length+2],i)})}}}});let R=null;function D(){return R||(R=new Set(a.dom.keys()))}const H=new Set(["presentation","none",p]);let M=null,U=null,W=null;var V=l({name:"click-events-have-key-events",meta:{type:"suggestion",docs:{description:"Ensures that the click event is accompanied with at least one key event keyup, keydown or keypress.",category:"Best Practices",recommended:!1},schema:[],messages:{clickEventsHaveKeyEvents:"click must be accompanied by either keyup, keydown or keypress event for accessibility."}},defaultOptions:[],create:e=>({Element(t){if(!D().has(t.name))return;if(function(e){const t=d(e,"role");return null!==t&&H.has(t)}(t)||x(t)||function(e){return D().has(e.name)&&function(e){function t(t){return e.name===t.name&&function(e=[],t){const n=[...t.attributes,...t.inputs];return e.every(e=>n.some(n=>"a"===t.name&&"routerLink"===n.name||e.name===n.name&&(!e.value||e.value===h(d(t,e.name)))))}(t.attributes,e)}return!!function(){if(null===M){const e=[...a.roles.keys()],t=[...a.elementRoles],n=new Set(e.filter(e=>{const t=a.roles.get(e);return!t.abstract&&"progressbar"!==e&&t.superClass.some(e=>e.includes("widget"))}).concat("toolbar"));M=t.reduce((e,[t,a])=>([...a].some(e=>n.has(e))&&e.push(t),e),[])}return M}().some(t)||!function(){if(null===U){const e=[...a.roles.keys()],t=[...a.elementRoles],n=new Set(e.filter(e=>{const t=a.roles.get(e);return!t.abstract&&"toolbar"!==e&&!t.superClass.some(e=>e.includes("widget"))}).concat("progressbar"));U=t.reduce((e,[t,a])=>([...a].every(e=>n.has(e))&&e.push(t),e),[])}return U}().some(t)&&!!function(){if(null===W){const{AXObjects:e,elementAXObjects:t}=require("axobject-query"),n=new Set(Array.from(e.keys()).filter(t=>"widget"===e.get(t).type));W=[...t].reduce((e,[t,a])=>([...a].every(e=>n.has(e))&&e.push(t),e),[])}return W}().some(t)}(e)}(t))return;let n=!1,r=!1;for(const e of t.outputs)n="click"===e.name,r=e.name.startsWith("keyup")||e.name.startsWith("keydown")||e.name.startsWith("keypress");if(!n||r)return;const o=u(e).convertNodeSourceSpanToLoc(t.sourceSpan);e.report({loc:o,messageId:"clickEventsHaveKeyEvents"})}})}),_=l({name:"conditional-complexity",meta:{type:"suggestion",docs:{description:"The conditional complexity should not exceed a rational limit",category:"Best Practices",recommended:!1},schema:[{type:"object",properties:{maxComplexity:{minimum:1,type:"number"}},additionalProperties:!1}],messages:{"conditionalСomplexity":'The conditional complexity "{{totalComplexity}}" exceeds the defined limit "{{maxComplexity}}"'}},defaultOptions:[{maxComplexity:5}],create(e,[{maxComplexity:t}]){m(e);const a=e.getSourceCode();return{BoundAttribute(r){if(!r.value.source)return;const o=X(z((K||(K=new n.Parser(new n.Lexer))).parseBinding(r.value.source,"",0).ast));if(o<=t)return;const{sourceSpan:{start:s,end:i}}=r.value;e.report({loc:{start:a.getLocFromIndex(s),end:a.getLocFromIndex(i)},messageId:"conditionalСomplexity",data:{maxComplexity:t,totalComplexity:o}})},Interpolation({expressions:n}){for(const r of n){const n=X(r);if(n<=t)continue;const{sourceSpan:{start:o,end:s}}=r;e.report({loc:{start:a.getLocFromIndex(o),end:a.getLocFromIndex(s)},messageId:"conditionalСomplexity",data:{maxComplexity:t,totalComplexity:n}})}}}}});function z(e){return e instanceof n.BindingPipe?e.exp:e}let K=null;function X(e){const t=z(e);if(!(t instanceof n.Binary||t instanceof n.Conditional))return 0;let a=1;return t instanceof n.Binary&&(t.left instanceof n.Binary&&(a+=X(t.left)),t.right instanceof n.Binary&&(a+=X(t.right))),t instanceof n.Conditional&&(a+=X(t.condition)+X(t.trueExp)+X(t.falseExp)),a}var Y=l({name:"cyclomatic-complexity",meta:{type:"suggestion",docs:{description:"Checks cyclomatic complexity against a specified limit. It is a quantitative measure of the number of linearly independent paths through a program's source code",category:"Best Practices",recommended:!1},schema:[{type:"object",properties:{maxComplexity:{type:"number",minimum:1}},additionalProperties:!1}],messages:{cyclomaticComplexity:'The cyclomatic complexity "{{totalComplexity}}" exceeds the defined limit "{{maxComplexity}}"'}},defaultOptions:[{maxComplexity:5}],create(e,[{maxComplexity:t}]){let n=0;const a=u(e);return{'BoundAttribute[name=/^(ngForOf|ngIf|ngSwitchCase)$/], TextAttribute[name="ngSwitchDefault"]'({sourceSpan:r}){if(n+=1,n<=t)return;const o=a.convertNodeSourceSpanToLoc(r);e.report({messageId:"cyclomaticComplexity",loc:o,data:{maxComplexity:t,totalComplexity:n}})}}}});function J({type:e}){return"Program"===e}function G({parent:e},t){for(;e&&!J(e);){if(t(e))return e;e=e.parent}return null}const Q={allowNullOrUndefined:!1};var Z=l({name:"eqeqeq",meta:{type:"suggestion",docs:{description:"Requires `===` and `!==` in place of `==` and `!=`",category:"Best Practices",recommended:"error"},fixable:"code",schema:[{type:"object",properties:{allowNullOrUndefined:{type:"boolean",default:Q.allowNullOrUndefined}},additionalProperties:!1}],messages:{eqeqeq:"Expected `{{expectedOperation}}` but received `{{actualOperation}}`"}},defaultOptions:[Q],create(e,[{allowNullOrUndefined:t}]){m(e);const n=e.getSourceCode();return{"Binary[operation=/^(==|!=)$/]"(a){const{left:r,operation:o,right:s,sourceSpan:{start:i,end:c}}=a,l=[r,s].some(ne);t&&l||e.report({loc:{start:n.getLocFromIndex(i),end:n.getLocFromIndex(c)},messageId:"eqeqeq",data:{actualOperation:o,expectedOperation:`${o}=`},fix:e=>{var t;const{source:n}=null!=(t=G(a,te))?t:{};return n?e.insertTextAfterRange([i+ee(r)+1,c-ee(s)-1],"="):[]}})}}}});function ee({span:{start:e,end:t}}){return t-e}function te(e){return e instanceof n.ASTWithSource}function ne(e){return e instanceof n.LiteralPrimitive&&null==e.value}const ae=/[a-z]/i,re=new Set(["charset","class","color","colspan","fill","formControlName","height","href","id","lang","src","stroke","stroke-width","style","svgIcon","tabindex","target","type","viewBox","width","xmlns"]),oe={checkAttributes:!0,checkId:!0,checkText:!0,ignoreAttributes:[...re]};var se=l({name:"i18n",meta:{type:"suggestion",docs:{description:"Helps to ensure following best practices for i18n. Checks for missing i18n attributes on elements and non-ignored attributes containing text. Can also highlight tags that do not use custom ID (@@) feature. ",category:"Best Practices",recommended:!1,suggestion:!0},fixable:"code",schema:[{type:"object",properties:{boundTextAllowedPattern:{type:"string"},checkId:{type:"boolean",default:oe.checkId},checkText:{type:"boolean",default:oe.checkText},checkAttributes:{type:"boolean",default:oe.checkAttributes},ignoreAttributes:{type:"array",items:{type:"string"},default:[...re]},ignoreTags:{type:"array",items:{type:"string"}}},additionalProperties:!1}],messages:{i18nAttribute:"Attribute '{{attributeName}}' has no corresponding i18n attribute. See more at https://angular.io/guide/i18n#translate-attributes",i18nId:"Missing custom message identifier. See more at https://angular.io/guide/i18n#use-a-custom-id-with-a-description",i18nIdOnAttribute:'Missing custom message identifier on attribute "{{attributeName}}". See more at https://angular.io/guide/i18n#use-a-custom-id-with-a-description',i18nSuggestIgnore:'Add the attribute name "{{attributeName}}" to the `ignoreAttributes` option in the eslint config',i18nText:"Each element containing text node should have an i18n attribute. See more at https://angular.io/guide/i18n"}},defaultOptions:[oe],create(e,[{boundTextAllowedPattern:t,checkAttributes:a,checkId:r,checkText:o,ignoreAttributes:s,ignoreTags:i}]){const c=u(e),l=e.getSourceCode(),m=RegExp(null!=t?t:ae),p=new Set([...re,...null!=s?s:[]]),d=new Set(i);function g(e){return e.customId}function f(e){return e instanceof n.TmplAstText&&/\S/.test(e.value)||e instanceof n.TmplAstBoundText&&e.value instanceof n.ASTWithSource&&e.value.ast instanceof n.Interpolation&&m.test(e.value.ast.strings.join("").trim())}function y(e,t,n){return p.has(t)||p.has(`${e}[${t}]`)||0===n.trim().length||"true"===n||"false"===n}function b({attributes:t,children:s,i18n:i,parent:u,sourceSpan:m},p){const d=c.convertNodeSourceSpanToLoc(m);for(const{i18n:n,name:o,value:s}of t)n?r&&!g(n)&&e.report({messageId:"i18nIdOnAttribute",loc:d,data:{attributeName:o}}):a&&y(p,o,s)||e.report({messageId:"i18nAttribute",loc:d,data:{attributeName:o},fix:e=>{const t=l.getIndexFromLoc(d.start)+1+p.length;return e.replaceTextRange([t,t],` i18n-${o}`)},suggest:[{messageId:"i18nSuggestIgnore",data:{attributeName:o},fix:e=>e.insertTextBeforeRange([0,0],"")}]});i?r&&!function(e,t){return!((e instanceof n.TmplAstElement||e instanceof n.TmplAstTemplate)&&(null==e||!e.i18n)&&!g(t))}(u,i)&&e.report({messageId:"i18nId",loc:d}):o&&s.some(f)&&e.report({messageId:"i18nText",loc:d})}return{Element(e){d.has(e.name)||b(e,e.name)},Template(e){b(e,e.tagName)}}}}),ie=l({name:"mouse-events-have-key-events",meta:{type:"suggestion",docs:{description:"Ensures that the Mouse Events mouseover and mouseout are accompanied with Key Events focus and blur.",category:"Best Practices",recommended:!1},schema:[],messages:{mouseOverEventHasFocusEvent:"mouseover must be accompanied by focus event for accessibility.",mouseOutEventHasBlurEvent:"mouseout must be accompanied by blur event for accessibility"}},defaultOptions:[],create(e){const t=u(e);return{Element(n){let a=!1,r=!1,o=!1,s=!1;for(const e of n.outputs)a="mouseover"===e.name,r="mouseout"===e.name,o="focus"===e.name,s="blur"===e.name;if(!a&&!r)return;const i=t.convertNodeSourceSpanToLoc(n.sourceSpan);a&&!o&&e.report({loc:i,messageId:"mouseOverEventHasFocusEvent"}),r&&!s&&e.report({loc:i,messageId:"mouseOutEventHasBlurEvent"})}}}}),ce=l({name:"no-any",meta:{type:"suggestion",docs:{description:'The use of "$any" nullifies the compile-time benefits of the Angular\'s type system.',category:"Best Practices",recommended:!1},schema:[],messages:{noAny:'Avoid using "$any" in templates'}},defaultOptions:[],create(e){m(e);const t=e.getSourceCode();return{'MethodCall[name="$any"][receiver.expression=undefined][receiver.name=undefined]'({sourceSpan:{end:n,start:a}}){e.report({messageId:"noAny",loc:{start:t.getLocFromIndex(a),end:t.getLocFromIndex(n)}})}}}}),le=l({name:"no-autofocus",meta:{type:"suggestion",docs:{description:"Ensure that autofocus attribute is not used",category:"Best Practices",recommended:!1},schema:[],messages:{noAutofocus:"autofocus attribute should not be used, as it reduces usability and accessibility for users"}},defaultOptions:[],create(e){const t=u(e);return{'TextAttribute[name="autofocus"], BoundAttribute[name="autofocus"]'(n){const a=t.convertNodeSourceSpanToLoc(n.sourceSpan);e.report({loc:a,messageId:"noAutofocus"})}}}}),ue=l({name:"no-call-expression",meta:{type:"suggestion",docs:{description:"Disallows calling expressions in templates, except for output handlers",category:"Best Practices",recommended:!1},schema:[],messages:{noCallExpression:"Avoid calling expressions in templates"}},defaultOptions:[],create(e){m(e);const t=e.getSourceCode();return{'MethodCall[name!="$any"], SafeMethodCall'(n){if(G(n,me))return;const{sourceSpan:{start:a,end:r}}=n;e.report({messageId:"noCallExpression",loc:{start:t.getLocFromIndex(a),end:t.getLocFromIndex(r)}})}}}});function me(e){return e instanceof n.TmplAstBoundEvent}var pe=l({name:"no-distracting-elements",meta:{type:"suggestion",docs:{description:"Enforces that no distracting elements are used",category:"Best Practices",recommended:!1},schema:[],messages:{noDistractingElements:"Do not use <{{element}}> elements as they can create visual accessibility issues and are deprecated"}},defaultOptions:[],create(e){const t=u(e);return{"Element[name=/^(blink|marquee)$/]"({name:n,sourceSpan:a}){const r=t.convertNodeSourceSpanToLoc(a);e.report({loc:r,messageId:"noDistractingElements",data:{element:n}})}}}}),de=l({name:"no-duplicate-attributes",meta:{type:"problem",docs:{description:"Ensures that there are no duplicate input properties or output event listeners",category:"Possible Errors",recommended:!1},schema:[{type:"object",properties:{allowTwoWayDataBinding:{type:"boolean"}},additionalProperties:!1}],messages:{noDuplicateAttributes:'Duplicate attribute "{{attributeName}}"'}},defaultOptions:[{allowTwoWayDataBinding:!0}],create(e,[{allowTwoWayDataBinding:t}]){const n=u(e);return{Element({inputs:a,outputs:r,attributes:o}){[...fe([...a,...o]),...fe(t?r.filter(e=>!a.some(t=>t.sourceSpan.start===e.sourceSpan.start&&t.sourceSpan.end===e.sourceSpan.end)):r)].forEach(t=>{const a=n.convertNodeSourceSpanToLoc(t.sourceSpan);e.report({messageId:"noDuplicateAttributes",loc:a,data:{attributeName:ge(t)}})})}}}});function ge(e){if("type"in e)if("BoundAttribute"===e.type)switch(e.__originalType){case 2:return`class.${e.name}`;case 3:return`style.${e.name}${e.unit?"."+e.unit:""}`;case 4:return`@${e.name}`}else if("BoundEvent"===e.type){if(1===e.__originalType)return`@${e.name}${e.phase?"."+e.phase:""}`;if(e.target)return`${e.target}:${e.name}`}return e.name}function fe(e){return e.filter(t=>e.some(e=>e!==t&&ge(e)===ge(t)))}var ye=l({name:"no-negated-async",meta:{type:"suggestion",docs:{description:"Ensures that async pipe results are not negated",category:"Best Practices",recommended:"error"},schema:[],messages:{noNegatedAsync:"Async pipe results should not be negated. Use (observable | async) === (false || null || undefined) to check its value instead"}},defaultOptions:[],create(e){m(e);const t=e.getSourceCode();return{'PrefixNot > BindingPipe[name="async"]'({parent:{sourceSpan:n}}){e.report({messageId:"noNegatedAsync",loc:{start:t.getLocFromIndex(n.start),end:t.getLocFromIndex(n.end)}})}}}}),be=l({name:"no-positive-tabindex",meta:{type:"suggestion",docs:{description:"Ensures that the tabindex attribute is not positive",category:"Best Practices",recommended:!1},schema:[],messages:{noPositiveTabindex:"tabindex attribute cannot be positive"}},defaultOptions:[],create(e){const t=u(e);return{'BoundAttribute[name="tabindex"][value.ast.value>0], TextAttribute[name="tabindex"][value>0]'({sourceSpan:n}){const a=t.convertNodeSourceSpanToLoc(n);e.report({loc:a,messageId:"noPositiveTabindex"})}}}});function he(){return(he=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var a in n)Object.prototype.hasOwnProperty.call(n,a)&&(e[a]=n[a])}return e}).apply(this,arguments)}var xe=l({name:"use-track-by-function",meta:{type:"suggestion",docs:{description:"Ensures trackBy function is used.",category:"Best Practices",recommended:!1},schema:[],messages:{useTrackByFunction:"Missing trackBy function in ngFor directive"}},defaultOptions:[],create(e){const t=u(e);return{'BoundAttribute.inputs[name="ngForOf"]'(n){if(n.parent.inputs.some(e=>"BoundAttribute"===e.type&&"ngForTrackBy"===e.name))return;const a=t.convertNodeSourceSpanToLoc(n.sourceSpan);e.report({messageId:"useTrackByFunction",loc:a})},'BoundAttribute.templateAttrs[name="ngForOf"]'(n){const a=n.parent.templateAttrs;if(a.some(e=>"BoundAttribute"===e.type&&"ngForTrackBy"===e.name))return;const r=t.convertNodeSourceSpanToLoc(a[0].sourceSpan).start,o=t.convertNodeSourceSpanToLoc(a[a.length-1].sourceSpan).end,s={start:he({},r,{column:r.column-1}),end:he({},o,{column:o.column+1})};e.report({messageId:"useTrackByFunction",loc:s})}}}});module.exports={configs:{all:{extends:"./configs/base.json",rules:{"@angular-eslint/template/accessibility-alt-text":"error","@angular-eslint/template/accessibility-elements-content":"error","@angular-eslint/template/accessibility-label-for":"error","@angular-eslint/template/accessibility-label-has-associated-control":"error","@angular-eslint/template/accessibility-table-scope":"error","@angular-eslint/template/accessibility-valid-aria":"error","@angular-eslint/template/banana-in-box":"error","@angular-eslint/template/click-events-have-key-events":"error","@angular-eslint/template/conditional-complexity":"error","@angular-eslint/template/cyclomatic-complexity":"error","@angular-eslint/template/eqeqeq":"error","@angular-eslint/template/i18n":"error","@angular-eslint/template/mouse-events-have-key-events":"error","@angular-eslint/template/no-any":"error","@angular-eslint/template/no-autofocus":"error","@angular-eslint/template/no-call-expression":"error","@angular-eslint/template/no-distracting-elements":"error","@angular-eslint/template/no-duplicate-attributes":"error","@angular-eslint/template/no-negated-async":"error","@angular-eslint/template/no-positive-tabindex":"error","@angular-eslint/template/use-track-by-function":"error"}},base:{parser:"@angular-eslint/template-parser",plugins:["@angular-eslint/template"]},recommended:{extends:"./configs/base.json",rules:{"@angular-eslint/template/banana-in-box":"error","@angular-eslint/template/eqeqeq":"error","@angular-eslint/template/no-negated-async":"error"}},"process-inline-templates":{parser:"@typescript-eslint/parser",parserOptions:{ecmaVersion:2020,sourceType:"module"},plugins:["@angular-eslint/template"],processor:"@angular-eslint/template/extract-inline-html"}},processors:c,rules:{"accessibility-alt-text":g,"accessibility-elements-content":S,"accessibility-label-for":B,[k]:O,"accessibility-table-scope":N,"accessibility-valid-aria":P,"banana-in-box":j,"conditional-complexity":_,"click-events-have-key-events":V,"cyclomatic-complexity":Y,eqeqeq:Z,i18n:se,"mouse-events-have-key-events":ie,"no-any":ce,"no-autofocus":le,"no-call-expression":ue,"no-distracting-elements":pe,"no-duplicate-attributes":de,"no-negated-async":ye,"no-positive-tabindex":be,"use-track-by-function":xe}};
|
|
1
|
+
var e=require("typescript"),t=require("@typescript-eslint/experimental-utils"),n=require("@angular/compiler"),a=require("aria-query");function o(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var s=o(e);function r(e,t){const n=(e=e.replace(/\r\n/g,"\n")).indexOf(t);return[n,n+t.length]}const i=new Map;var c={"extract-inline-html":{preprocess:function(e,t){const n=[e];if(!function(e,t){return!![".component.ts",".page.ts",".dialog.ts",".modal.ts",".popover.ts",".bottomsheet.ts",".snackbar.ts"].some(e=>t.endsWith(e))||!(!e.includes("Component")||!e.includes("@angular/core"))}(e,t))return n;try{const a=s.default.createSourceFile(t,e,s.default.ScriptTarget.Latest,!0),o=a.statements.filter(e=>s.default.isClassDeclaration(e));if(!o||!o.length)return n;const c=[];for(const e of o)if(e.decorators)for(const t of e.decorators)s.default.isCallExpression(t.expression)&&s.default.isIdentifier(t.expression.expression)&&"Component"===t.expression.expression.text&&c.push(t);if(!c||!c.length)return n;const l=[e];let u=0;for(const t of c){if(!s.default.isDecorator(t)||!s.default.isCallExpression(t.expression)||1!==t.expression.arguments.length)continue;const n=t.expression.arguments[0];if(!s.default.isObjectLiteralExpression(n))continue;const o=n.properties.find(e=>e&&e.name&&"template"===e.name.getText());if(n.properties.find(e=>e&&e.name&&"templateUrl"===e.name.getText())||!o)continue;if(!s.default.isPropertyAssignment(o)||!s.default.isStringLiteralLike(o.initializer))continue;const c=o.initializer.text,m=r(e,c),p=`inline-template-${++u}.component.html`;i.set(p,{range:m,lineAndCharacter:{start:a.getLineAndCharacterOfPosition(m[0]),end:a.getLineAndCharacterOfPosition(m[1])}}),l.push({text:c,filename:p})}return l}catch(e){return console.log(e),console.error("preprocess: ERROR could not parse @Component() metadata",t),n}},postprocess:function(e,t){const n=e[0];if(1===e.length)return n;const a=e.slice(1);return[...n,...[].concat(...a.map((e,t)=>{const n=`inline-template-${++t}.component.html`,a=i.get(n);return a?e.map(e=>{if(e.line=e.line+a.lineAndCharacter.start.line,e.endLine=e.endLine+a.lineAndCharacter.start.line,e.fix){const t=a.range[0];e.fix.range=[t+e.fix.range[0],t+e.fix.range[1]]}return e}):[]}))]},supportsAutofix:!0}};const l=t.ESLintUtils.RuleCreator(e=>"https://github.com/angular-eslint/angular-eslint");function u(e){return m(e),e.parserServices}function m(e){var t,n;if(null==(t=e.parserServices)||!t.convertNodeSourceSpanToLoc||null==(n=e.parserServices)||!n.convertElementSourceSpanToLoc)throw new Error("You have used a rule which requires '@angular-eslint/template-parser' to be used as the 'parser' in your ESLint config.")}const p=Symbol("PROPERTY");function d(e,t){const a=e.attributes.find(e=>e.name===t);if(a)return a.value;const o=e.inputs.find(e=>e.name===t);return o&&o.value instanceof n.ASTWithSource?o.value.ast instanceof n.LiteralPrimitive?o.value.ast.value:p:null}var g=l({name:"accessibility-alt-text",meta:{type:"suggestion",docs:{description:"Enforces alternate text for elements which require the alt, aria-label, aria-labelledby attributes.",category:"Best Practices",recommended:!1},schema:[],messages:{accessibilityAltText:"<{{element}}/> element must have a text alternative."}},defaultOptions:[],create(e){const t=u(e);return{"Element[name=/^(img|area|object|input)$/]"(n){if(!function(e){return"img"===e.name?function(e){return e.attributes.some(({name:e})=>b(e))||e.inputs.some(({name:e})=>b(e))}(e):"object"===e.name?function(e){let t=!1,n=!1;for(const a of e.attributes)t="title"===a.name,n=y(a.name);if(t||n)return!0;let a=!1,o=!1;for(const t of e.inputs)a="title"===t.name,o=y(t.name);return!(!a&&!o)||e.children.length>0&&!!e.children[0].value}(e):"area"===e.name?f(e):function(e){return"image"!==d(e,"type")||f(e)}(e)}(n)){const a=t.convertElementSourceSpanToLoc(e,n);e.report({loc:a,messageId:"accessibilityAltText",data:{element:n.name}})}}}}});function f(e){let t=!1,n=!1;for(const a of e.attributes)t=b(a.name),n=y(a.name);if(t||n)return!0;let a=!1,o=!1;for(const t of e.inputs)a=b(t.name),o=y(t.name);return a||o}function y(e){return"aria-label"===e||"aria-labelledby"===e}function b(e){return"alt"===e}function h(e){if("string"==typeof e){if("true"===e)return!0;if("false"===e)return!1}return e}function x(e){if("INPUT"===e.name.toUpperCase()){const t=d(e,"type");if("string"==typeof t&&"HIDDEN"===t.toUpperCase())return!0}const t=h(d(e,"aria-hidden"));return""===t||t===p||!0===t}const v=new Set(["aria-label","innerHtml","innerHTML","innerText","outerHTML","title"]);var S=l({name:"accessibility-elements-content",meta:{type:"suggestion",docs:{description:"Ensures that the heading, anchor and button elements have content in it",category:"Best Practices",recommended:!1},schema:[],messages:{accessibilityElementsContent:"<{{element}}> should have content"}},defaultOptions:[],create(e){const t=u(e);return{"Element[name=/^(a|button|h1|h2|h3|h4|h5|h6)$/][children.length=0]"(n){if(x(n))return;const{attributes:a,inputs:o,name:s,sourceSpan:r}=n;if([...a,...o].map(({name:e})=>e).some(e=>v.has(e)))return;const i=t.convertNodeSourceSpanToLoc(r);e.report({loc:i,messageId:"accessibilityElementsContent",data:{element:s}})}}}});function A(e,t){return function e({children:a}){return a.some(a=>a instanceof n.TmplAstElement&&(a.name===t||e(a)))}(e)}const T={items:{type:"string"},type:"array",uniqueItems:!0},C=["button","input","meter","output","progress","select","textarea"],E=["for","htmlFor"],I=["label"];var B=l({name:"accessibility-label-for",meta:{deprecated:!0,replacedBy:["accessibility-label-has-associated-control"],type:"suggestion",docs:{description:"Ensures that a label element/component is associated with a form element",category:"Best Practices",recommended:!1},schema:[{additionalProperties:!1,properties:{controlComponents:T,labelAttributes:T,labelComponents:T},type:"object"}],messages:{accessibilityLabelFor:"A label element/component must be associated with a form element"}},defaultOptions:[{controlComponents:C,labelAttributes:E,labelComponents:I}],create(e,[t]){const n=u(e),{controlComponents:a,labelAttributes:o,labelComponents:s}=function({controlComponents:e,labelAttributes:t,labelComponents:n}){return{controlComponents:new Set([...C,...null!=e?e:[]]),labelAttributes:new Set([...E,...null!=t?t:[]]),labelComponents:new Set([...I,...null!=n?n:[]])}}(t);var r;return{[`Element[name=${r=[...s],RegExp(`^(${r.join("|")})$`)}]`](t){const s=new Set([...t.attributes,...t.inputs].map(({name:e})=>e));if([...o].some(e=>s.has(e))||function(e,t){return Boolean([...e].some(e=>A(t,e)))}(a,t))return;const r=n.convertNodeSourceSpanToLoc(t.sourceSpan);e.report({loc:r,messageId:"accessibilityLabelFor"})}}}});const k="accessibility-label-has-associated-control",w=["input","meter","output","progress","select","textarea"],L=[{inputs:["for","htmlFor"],selector:"label"}];var N=l({name:k,meta:{type:"suggestion",docs:{description:"Ensures that a label element/component is associated with a form element",category:"Best Practices",recommended:!1},schema:[{additionalProperties:!1,properties:{controlComponents:{items:{type:"string"},type:"array",uniqueItems:!0},labelComponents:{items:{required:["selector"],type:"object"},type:"array",uniqueItems:!0}},type:"object"}],messages:{accessibilityLabelHasAssociatedControl:"A label component must be associated with a form element"}},defaultOptions:[{controlComponents:w,labelComponents:L}],create(e,[{controlComponents:t,labelComponents:n}]){const a=u(e),o=new Set([...w,...null!=t?t:[]]),s=[...L,...null!=n?n:[]],r=s.map(({selector:e})=>e);return{[`Element[name=${RegExp(`^(${r.join("|")})$`)}]`](t){var n;const r=s.find(({selector:e})=>e===t.name);if(!r)return;const i=new Set([...t.attributes,...t.inputs].map(({name:e})=>e));if((null==(n=r.inputs)?void 0:n.some(e=>i.has(e)))||function(e,t){return Boolean([...e].some(e=>A(t,e)))}(o,t))return;const c=a.convertNodeSourceSpanToLoc(t.sourceSpan);e.report({loc:c,messageId:"accessibilityLabelHasAssociatedControl"})}}}}),P=l({name:"accessibility-table-scope",meta:{type:"suggestion",docs:{description:"Ensures that scope is not used on any element except <th>",category:"Best Practices",recommended:!1},schema:[],messages:{accessibilityTableScope:"Scope attribute can only be on <th> element"}},defaultOptions:[],create(e){const t=u(e);return{'Element[name!="th"] > :matches(BoundAttribute[name="scope"], TextAttribute[name="scope"])'({sourceSpan:n}){const a=t.convertNodeSourceSpanToLoc(n);e.report({loc:a,messageId:"accessibilityTableScope"})}}}}),O=l({name:"accessibility-valid-aria",meta:{type:"suggestion",docs:{description:"Ensures that correct ARIA attributes and respective values are used",category:"Best Practices",recommended:!1},schema:[],messages:{accessibilityValidAria:"The `{{attribute}}` is an invalid ARIA attribute",accessibilityValidAriaValue:"The `{{attribute}}` has an invalid value. Check the valid values at https://raw.githack.com/w3c/aria/stable/#roles"}},defaultOptions:[],create(e){const t=u(e);return{"BoundAttribute[name=/^aria-.*/], TextAttribute[name=/^aria-.*/]"(o){const{name:s,sourceSpan:r}=o,i=a.aria.get(s),c=t.convertNodeSourceSpanToLoc(r);if(!i)return void e.report({loc:c,messageId:"accessibilityValidAria",data:{attribute:s}});const l=function(e){return e instanceof n.TmplAstBoundAttribute?e.value.ast:e}(o);(function(e){return!function(e){return e instanceof n.LiteralArray||e instanceof n.LiteralMap}(e)&&!function(e){return e instanceof n.LiteralPrimitive||e instanceof n.TmplAstTextAttribute}(e)})(l)||function({allowundefined:e,type:t,values:n},a){if(e&&$(a))return!0;switch(t){case"boolean":return F(a);case"tristate":return F(a)||$(a);case"id":case"idlist":return!0;case"integer":return o=a,!Number.isNaN(o)&&parseInt(Number(o))==o&&!Number.isNaN(parseInt(o,10));case"number":return function(e){return!Number.isNaN(Number.parseFloat(e))&&Number.isFinite(e)}(a);case"string":return function(e){return"string"==typeof e}(a);case"token":case"tokenlist":{const e=F(a)?JSON.parse(a):a;return Boolean(null==n?void 0:n.includes(e))}}var o}(i,l.value)||e.report({loc:c,messageId:"accessibilityValidAriaValue",data:{attribute:s}})}}}});function F(e){return"boolean"==typeof e||"false"===e||"true"===e}function $(e){return null==e}const j=/\[(.*)\]/;var q=l({name:"banana-in-box",meta:{type:"suggestion",docs:{description:"Ensures that the two-way data binding syntax is correct",category:"Best Practices",recommended:"error"},fixable:"code",schema:[],messages:{bananaInBox:"Invalid binding syntax. Use [(expr)] instead"}},defaultOptions:[],create(e){const t=u(e),n=e.getSourceCode();return{BoundEvent({name:a,sourceSpan:o}){const s=a.match(j);if(!s)return;const[,r]=s,i=`[(${r})]`,c=t.convertNodeSourceSpanToLoc(o),l=n.getIndexFromLoc(c.start);e.report({messageId:"bananaInBox",loc:c,fix:e=>e.replaceTextRange([l,l+a.length+2],i)})}}}});let D=null;function R(){return D||(D=new Set(a.dom.keys()))}const H=new Set(["presentation","none",p]);let M=null,W=null,U=null;var V=l({name:"click-events-have-key-events",meta:{type:"suggestion",docs:{description:"Ensures that the click event is accompanied with at least one key event keyup, keydown or keypress.",category:"Best Practices",recommended:!1},schema:[],messages:{clickEventsHaveKeyEvents:"click must be accompanied by either keyup, keydown or keypress event for accessibility."}},defaultOptions:[],create:e=>({Element(t){if(!R().has(t.name))return;if(function(e){const t=d(e,"role");return null!==t&&H.has(t)}(t)||x(t)||function(e){return R().has(e.name)&&function(e){function t(t){return e.name===t.name&&function(e=[],t){const n=[...t.attributes,...t.inputs];return e.every(e=>n.some(n=>"a"===t.name&&"routerLink"===n.name||e.name===n.name&&(!e.value||e.value===h(d(t,e.name)))))}(t.attributes,e)}return!!function(){if(null===M){const e=[...a.roles.keys()],t=[...a.elementRoles],n=new Set(e.filter(e=>{const t=a.roles.get(e);return!t.abstract&&"progressbar"!==e&&t.superClass.some(e=>e.includes("widget"))}).concat("toolbar"));M=t.reduce((e,[t,a])=>([...a].some(e=>n.has(e))&&e.push(t),e),[])}return M}().some(t)||!function(){if(null===W){const e=[...a.roles.keys()],t=[...a.elementRoles],n=new Set(e.filter(e=>{const t=a.roles.get(e);return!t.abstract&&"toolbar"!==e&&!t.superClass.some(e=>e.includes("widget"))}).concat("progressbar"));W=t.reduce((e,[t,a])=>([...a].every(e=>n.has(e))&&e.push(t),e),[])}return W}().some(t)&&!!function(){if(null===U){const{AXObjects:e,elementAXObjects:t}=require("axobject-query"),n=new Set(Array.from(e.keys()).filter(t=>"widget"===e.get(t).type));U=[...t].reduce((e,[t,a])=>([...a].every(e=>n.has(e))&&e.push(t),e),[])}return U}().some(t)}(e)}(t))return;let n=!1,o=!1;for(const e of t.outputs)n="click"===e.name,o=e.name.startsWith("keyup")||e.name.startsWith("keydown")||e.name.startsWith("keypress");if(!n||o)return;const s=u(e).convertNodeSourceSpanToLoc(t.sourceSpan);e.report({loc:s,messageId:"clickEventsHaveKeyEvents"})}})}),_=l({name:"conditional-complexity",meta:{type:"suggestion",docs:{description:"The conditional complexity should not exceed a rational limit",category:"Best Practices",recommended:!1},schema:[{type:"object",properties:{maxComplexity:{minimum:1,type:"number"}},additionalProperties:!1}],messages:{"conditionalСomplexity":'The conditional complexity "{{totalComplexity}}" exceeds the defined limit "{{maxComplexity}}"'}},defaultOptions:[{maxComplexity:5}],create(e,[{maxComplexity:t}]){m(e);const a=e.getSourceCode();return{BoundAttribute(o){if(!o.value.source)return;const s=X(z((K||(K=new n.Parser(new n.Lexer))).parseBinding(o.value.source,"",0).ast));if(s<=t)return;const{sourceSpan:{start:r,end:i}}=o.value;e.report({loc:{start:a.getLocFromIndex(r),end:a.getLocFromIndex(i)},messageId:"conditionalСomplexity",data:{maxComplexity:t,totalComplexity:s}})},Interpolation({expressions:n}){for(const o of n){const n=X(o);if(n<=t)continue;const{sourceSpan:{start:s,end:r}}=o;e.report({loc:{start:a.getLocFromIndex(s),end:a.getLocFromIndex(r)},messageId:"conditionalСomplexity",data:{maxComplexity:t,totalComplexity:n}})}}}}});function z(e){return e instanceof n.BindingPipe?e.exp:e}let K=null;function X(e){const t=z(e);if(!(t instanceof n.Binary||t instanceof n.Conditional))return 0;let a=1;return t instanceof n.Binary&&(t.left instanceof n.Binary&&(a+=X(t.left)),t.right instanceof n.Binary&&(a+=X(t.right))),t instanceof n.Conditional&&(a+=X(t.condition)+X(t.trueExp)+X(t.falseExp)),a}var Y=l({name:"cyclomatic-complexity",meta:{type:"suggestion",docs:{description:"Checks cyclomatic complexity against a specified limit. It is a quantitative measure of the number of linearly independent paths through a program's source code",category:"Best Practices",recommended:!1},schema:[{type:"object",properties:{maxComplexity:{type:"number",minimum:1}},additionalProperties:!1}],messages:{cyclomaticComplexity:'The cyclomatic complexity "{{totalComplexity}}" exceeds the defined limit "{{maxComplexity}}"'}},defaultOptions:[{maxComplexity:5}],create(e,[{maxComplexity:t}]){let n=0;const a=u(e);return{'BoundAttribute[name=/^(ngForOf|ngIf|ngSwitchCase)$/], TextAttribute[name="ngSwitchDefault"]'({sourceSpan:o}){if(n+=1,n<=t)return;const s=a.convertNodeSourceSpanToLoc(o);e.report({messageId:"cyclomaticComplexity",loc:s,data:{maxComplexity:t,totalComplexity:n}})}}}});const J=/[a-z]/i,G=new Set(["charset","class","color","colspan","fill","formControlName","height","href","id","lang","src","stroke","stroke-width","style","svgIcon","tabindex","target","type","viewBox","width","xmlns"]),Q={checkAttributes:!0,checkId:!0,checkText:!0,ignoreAttributes:[...G]};var Z=l({name:"i18n",meta:{type:"suggestion",docs:{description:"Helps to ensure following best practices for i18n. Checks for missing i18n attributes on elements and non-ignored attributes containing text. Can also highlight tags that do not use custom ID (@@) feature. ",category:"Best Practices",recommended:!1,suggestion:!0},fixable:"code",schema:[{type:"object",properties:{boundTextAllowedPattern:{type:"string"},checkId:{type:"boolean",default:Q.checkId},checkText:{type:"boolean",default:Q.checkText},checkAttributes:{type:"boolean",default:Q.checkAttributes},ignoreAttributes:{type:"array",items:{type:"string"},default:[...G]},ignoreTags:{type:"array",items:{type:"string"}}},additionalProperties:!1}],messages:{i18nAttribute:"Attribute '{{attributeName}}' has no corresponding i18n attribute. See more at https://angular.io/guide/i18n#translate-attributes",i18nId:"Missing custom message identifier. See more at https://angular.io/guide/i18n#use-a-custom-id-with-a-description",i18nIdOnAttribute:'Missing custom message identifier on attribute "{{attributeName}}". See more at https://angular.io/guide/i18n#use-a-custom-id-with-a-description',i18nSuggestIgnore:'Add the attribute name "{{attributeName}}" to the `ignoreAttributes` option in the eslint config',i18nText:"Each element containing text node should have an i18n attribute. See more at https://angular.io/guide/i18n"}},defaultOptions:[Q],create(e,[{boundTextAllowedPattern:t,checkAttributes:a,checkId:o,checkText:s,ignoreAttributes:r,ignoreTags:i}]){const c=u(e),l=e.getSourceCode(),m=RegExp(null!=t?t:J),p=new Set([...G,...null!=r?r:[]]),d=new Set(i);function g(e){return e.customId}function f(e){return e instanceof n.TmplAstText&&/\S/.test(e.value)||e instanceof n.TmplAstBoundText&&e.value instanceof n.ASTWithSource&&e.value.ast instanceof n.Interpolation&&m.test(e.value.ast.strings.join("").trim())}function y(e,t,n){return p.has(t)||p.has(`${e}[${t}]`)||0===n.trim().length||"true"===n||"false"===n}function b({attributes:t,children:r,i18n:i,parent:u,sourceSpan:m},p){const d=c.convertNodeSourceSpanToLoc(m);for(const{i18n:n,name:s,value:r}of t)n?o&&!g(n)&&e.report({messageId:"i18nIdOnAttribute",loc:d,data:{attributeName:s}}):a&&y(p,s,r)||e.report({messageId:"i18nAttribute",loc:d,data:{attributeName:s},fix:e=>{const t=l.getIndexFromLoc(d.start)+1+p.length;return e.replaceTextRange([t,t],` i18n-${s}`)},suggest:[{messageId:"i18nSuggestIgnore",data:{attributeName:s},fix:e=>e.insertTextBeforeRange([0,0],"")}]});i?o&&!function(e,t){return!((e instanceof n.TmplAstElement||e instanceof n.TmplAstTemplate)&&(null==e||!e.i18n)&&!g(t))}(u,i)&&e.report({messageId:"i18nId",loc:d}):s&&r.some(f)&&e.report({messageId:"i18nText",loc:d})}return{Element(e){d.has(e.name)||b(e,e.name)},Template(e){b(e,e.tagName)}}}}),ee=l({name:"mouse-events-have-key-events",meta:{type:"suggestion",docs:{description:"Ensures that the Mouse Events mouseover and mouseout are accompanied with Key Events focus and blur.",category:"Best Practices",recommended:!1},schema:[],messages:{mouseOverEventHasFocusEvent:"mouseover must be accompanied by focus event for accessibility.",mouseOutEventHasBlurEvent:"mouseout must be accompanied by blur event for accessibility"}},defaultOptions:[],create(e){const t=u(e);return{Element(n){let a=!1,o=!1,s=!1,r=!1;for(const e of n.outputs)a="mouseover"===e.name,o="mouseout"===e.name,s="focus"===e.name,r="blur"===e.name;if(!a&&!o)return;const i=t.convertNodeSourceSpanToLoc(n.sourceSpan);a&&!s&&e.report({loc:i,messageId:"mouseOverEventHasFocusEvent"}),o&&!r&&e.report({loc:i,messageId:"mouseOutEventHasBlurEvent"})}}}}),te=l({name:"no-any",meta:{type:"suggestion",docs:{description:'The use of "$any" nullifies the compile-time benefits of the Angular\'s type system.',category:"Best Practices",recommended:!1},schema:[],messages:{noAny:'Avoid using "$any" in templates'}},defaultOptions:[],create(e){m(e);const t=e.getSourceCode();return{'MethodCall[name="$any"][receiver.expression=undefined][receiver.name=undefined]'({sourceSpan:{end:n,start:a}}){e.report({messageId:"noAny",loc:{start:t.getLocFromIndex(a),end:t.getLocFromIndex(n)}})}}}}),ne=l({name:"no-autofocus",meta:{type:"suggestion",docs:{description:"Ensure that autofocus attribute is not used",category:"Best Practices",recommended:!1},schema:[],messages:{noAutofocus:"autofocus attribute should not be used, as it reduces usability and accessibility for users"}},defaultOptions:[],create(e){const t=u(e);return{'TextAttribute[name="autofocus"], BoundAttribute[name="autofocus"]'(n){const a=t.convertNodeSourceSpanToLoc(n.sourceSpan);e.report({loc:a,messageId:"noAutofocus"})}}}});function ae({type:e}){return"Program"===e}var oe=l({name:"no-call-expression",meta:{type:"suggestion",docs:{description:"Disallows calling expressions in templates, except for output handlers",category:"Best Practices",recommended:!1},schema:[],messages:{noCallExpression:"Avoid calling expressions in templates"}},defaultOptions:[],create(e){m(e);const t=e.getSourceCode();function a({sourceSpan:{end:n,start:a}}){e.report({messageId:"noCallExpression",loc:{start:t.getLocFromIndex(a),end:t.getLocFromIndex(n)}})}return{'Conditional, MethodCall[name!="$any"], SafeMethodCall'(e){if(function({parent:e},t){for(;e&&!ae(e);){if(t(e))return e;e=e.parent}return null}(e,se))return;if(!(e instanceof n.Conditional))return void a(e);const{falseExp:t,trueExp:o}=e;re(t)&&a(t),re(o)&&a(o)}}}});function se(e){return e instanceof n.TmplAstBoundEvent}function re(e){return e instanceof n.MethodCall||e instanceof n.SafeMethodCall}var ie=l({name:"no-distracting-elements",meta:{type:"suggestion",docs:{description:"Enforces that no distracting elements are used",category:"Best Practices",recommended:!1},schema:[],messages:{noDistractingElements:"Do not use <{{element}}> elements as they can create visual accessibility issues and are deprecated"}},defaultOptions:[],create(e){const t=u(e);return{"Element[name=/^(blink|marquee)$/]"({name:n,sourceSpan:a}){const o=t.convertNodeSourceSpanToLoc(a);e.report({loc:o,messageId:"noDistractingElements",data:{element:n}})}}}}),ce=l({name:"no-duplicate-attributes",meta:{type:"problem",docs:{description:"Ensures that there are no duplicate input properties or output event listeners",category:"Possible Errors",recommended:!1},schema:[{type:"object",properties:{allowTwoWayDataBinding:{type:"boolean"}},additionalProperties:!1}],messages:{noDuplicateAttributes:'Duplicate attribute "{{attributeName}}"'}},defaultOptions:[{allowTwoWayDataBinding:!0}],create(e,[{allowTwoWayDataBinding:t}]){const n=u(e);return{Element({inputs:a,outputs:o,attributes:s}){[...ue([...a,...s]),...ue(t?o.filter(e=>!a.some(t=>t.sourceSpan.start===e.sourceSpan.start&&t.sourceSpan.end===e.sourceSpan.end)):o)].forEach(t=>{const a=n.convertNodeSourceSpanToLoc(t.sourceSpan);e.report({messageId:"noDuplicateAttributes",loc:a,data:{attributeName:le(t)}})})}}}});function le(e){if("type"in e)if("BoundAttribute"===e.type)switch(e.__originalType){case 2:return`class.${e.name}`;case 3:return`style.${e.name}${e.unit?"."+e.unit:""}`;case 4:return`@${e.name}`}else if("BoundEvent"===e.type){if(1===e.__originalType)return`@${e.name}${e.phase?"."+e.phase:""}`;if(e.target)return`${e.target}:${e.name}`}return e.name}function ue(e){return e.filter(t=>e.some(e=>e!==t&&le(e)===le(t)))}var me=l({name:"no-negated-async",meta:{type:"suggestion",docs:{description:"Ensures that strict equality is used when evaluating negations on async pipe output",category:"Best Practices",recommended:"error"},schema:[],messages:{noNegatedAsync:"Async pipes should not be negated. Use (observable | async) === (false || null || undefined) to check its value instead",noLooseEquality:"Async pipes must use strict equality `===` when comparing with `false`"}},defaultOptions:[],create(e){m(e);const t=e.getSourceCode();return{"PrefixNot > BindingPipe[name=async]"({parent:n}){e.report({messageId:"noNegatedAsync",loc:{start:t.getLocFromIndex(n.sourceSpan.start),end:t.getLocFromIndex(n.sourceSpan.end)}})},'Binary[operation="=="] > BindingPipe[name=async]'({parent:n}){e.report({messageId:"noLooseEquality",loc:{start:t.getLocFromIndex(n.sourceSpan.start),end:t.getLocFromIndex(n.sourceSpan.end)}})}}}}),pe=l({name:"no-positive-tabindex",meta:{type:"suggestion",docs:{description:"Ensures that the tabindex attribute is not positive",category:"Best Practices",recommended:!1},schema:[],messages:{noPositiveTabindex:"tabindex attribute cannot be positive"}},defaultOptions:[],create(e){const t=u(e);return{'BoundAttribute[name="tabindex"][value.ast.value>0], TextAttribute[name="tabindex"][value>0]'({sourceSpan:n}){const a=t.convertNodeSourceSpanToLoc(n);e.report({loc:a,messageId:"noPositiveTabindex"})}}}});function de(){return(de=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var a in n)Object.prototype.hasOwnProperty.call(n,a)&&(e[a]=n[a])}return e}).apply(this,arguments)}var ge=l({name:"use-track-by-function",meta:{type:"suggestion",docs:{description:"Ensures trackBy function is used.",category:"Best Practices",recommended:!1},schema:[],messages:{useTrackByFunction:"Missing trackBy function in ngFor directive"}},defaultOptions:[],create(e){const t=u(e);return{'BoundAttribute.inputs[name="ngForOf"]'(n){if(n.parent.inputs.some(e=>"BoundAttribute"===e.type&&"ngForTrackBy"===e.name))return;const a=t.convertNodeSourceSpanToLoc(n.sourceSpan);e.report({messageId:"useTrackByFunction",loc:a})},'BoundAttribute.templateAttrs[name="ngForOf"]'(n){const a=n.parent.templateAttrs;if(a.some(e=>"BoundAttribute"===e.type&&"ngForTrackBy"===e.name))return;const o=t.convertNodeSourceSpanToLoc(a[0].sourceSpan).start,s=t.convertNodeSourceSpanToLoc(a[a.length-1].sourceSpan).end,r={start:de({},o,{column:o.column-1}),end:de({},s,{column:s.column+1})};e.report({messageId:"useTrackByFunction",loc:r})}}}});module.exports={configs:{all:{extends:"./configs/base.json",rules:{"@angular-eslint/template/accessibility-alt-text":"error","@angular-eslint/template/accessibility-elements-content":"error","@angular-eslint/template/accessibility-label-for":"error","@angular-eslint/template/accessibility-label-has-associated-control":"error","@angular-eslint/template/accessibility-table-scope":"error","@angular-eslint/template/accessibility-valid-aria":"error","@angular-eslint/template/banana-in-box":"error","@angular-eslint/template/click-events-have-key-events":"error","@angular-eslint/template/conditional-complexity":"error","@angular-eslint/template/cyclomatic-complexity":"error","@angular-eslint/template/i18n":"error","@angular-eslint/template/mouse-events-have-key-events":"error","@angular-eslint/template/no-any":"error","@angular-eslint/template/no-autofocus":"error","@angular-eslint/template/no-call-expression":"error","@angular-eslint/template/no-distracting-elements":"error","@angular-eslint/template/no-duplicate-attributes":"error","@angular-eslint/template/no-negated-async":"error","@angular-eslint/template/no-positive-tabindex":"error","@angular-eslint/template/use-track-by-function":"error"}},base:{parser:"@angular-eslint/template-parser",plugins:["@angular-eslint/template"]},recommended:{extends:"./configs/base.json",rules:{"@angular-eslint/template/banana-in-box":"error","@angular-eslint/template/no-negated-async":"error"}},"process-inline-templates":{parser:"@typescript-eslint/parser",parserOptions:{ecmaVersion:2020,sourceType:"module"},plugins:["@angular-eslint/template"],processor:"@angular-eslint/template/extract-inline-html"}},processors:c,rules:{"accessibility-alt-text":g,"accessibility-elements-content":S,"accessibility-label-for":B,[k]:N,"accessibility-table-scope":P,"accessibility-valid-aria":O,"banana-in-box":q,"conditional-complexity":_,"click-events-have-key-events":V,"cyclomatic-complexity":Y,i18n:Z,"mouse-events-have-key-events":ee,"no-any":te,"no-autofocus":ne,"no-call-expression":oe,"no-distracting-elements":ie,"no-duplicate-attributes":ce,"no-negated-async":me,"no-positive-tabindex":pe,"use-track-by-function":ge}};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare type MessageIds = 'noNegatedAsync';
|
|
1
|
+
export declare type MessageIds = 'noNegatedAsync' | 'noLooseEquality';
|
|
2
2
|
export declare const RULE_NAME = "no-negated-async";
|
|
3
|
-
declare const _default: import("@typescript-eslint/experimental-utils/dist/ts-eslint/Rule").RuleModule<
|
|
3
|
+
declare const _default: import("@typescript-eslint/experimental-utils/dist/ts-eslint/Rule").RuleModule<MessageIds, [], import("@typescript-eslint/experimental-utils/dist/ts-eslint/Rule").RuleListener>;
|
|
4
4
|
export default _default;
|
|
@@ -2,15 +2,8 @@ import type { TSESLint } from '@typescript-eslint/experimental-utils';
|
|
|
2
2
|
export declare const createESLintRule: <TOptions extends readonly unknown[], TMessageIds extends string, TRuleListener extends TSESLint.RuleListener = TSESLint.RuleListener>({ name, meta, defaultOptions, create, }: Readonly<{
|
|
3
3
|
name: string;
|
|
4
4
|
meta: {
|
|
5
|
-
docs:
|
|
6
|
-
|
|
7
|
-
description: string;
|
|
8
|
-
recommended: false | "error" | "warn";
|
|
9
|
-
suggestion?: boolean | undefined;
|
|
10
|
-
requiresTypeChecking?: boolean | undefined;
|
|
11
|
-
extendsBaseRule?: string | boolean | undefined;
|
|
12
|
-
};
|
|
13
|
-
} & Omit<TSESLint.RuleMetaData<TMessageIds>, "docs">;
|
|
5
|
+
docs: Pick<TSESLint.RuleMetaDataDocs, "category" | "description" | "recommended" | "suggestion" | "requiresTypeChecking" | "extendsBaseRule">;
|
|
6
|
+
} & Pick<TSESLint.RuleMetaData<TMessageIds>, "deprecated" | "fixable" | "messages" | "type" | "replacedBy" | "schema">;
|
|
14
7
|
defaultOptions: Readonly<TOptions>;
|
|
15
8
|
create: (context: Readonly<TSESLint.RuleContext<TMessageIds, TOptions>>, optionsWithDefault: Readonly<TOptions>) => TRuleListener;
|
|
16
9
|
}>) => TSESLint.RuleModule<TMessageIds, TOptions, TRuleListener>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular-eslint/eslint-plugin-template",
|
|
3
|
-
"version": "4.3.1
|
|
3
|
+
"version": "4.3.1",
|
|
4
4
|
"description": "ESLint plugin for Angular Templates",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -24,18 +24,19 @@
|
|
|
24
24
|
"LICENSE"
|
|
25
25
|
],
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@typescript-eslint/experimental-utils": "4.
|
|
27
|
+
"@typescript-eslint/experimental-utils": "4.16.1",
|
|
28
28
|
"aria-query": "^4.2.2",
|
|
29
29
|
"axobject-query": "^2.2.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@angular-eslint/utils": "
|
|
32
|
+
"@angular-eslint/utils": "4.3.1",
|
|
33
33
|
"@types/aria-query": "^4.2.0"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
|
-
"@angular/
|
|
36
|
+
"@angular-eslint/template-parser": ">= 4.0.0 < 12.0.0",
|
|
37
|
+
"@angular/compiler": ">= 11.2.0 < 12.0.0",
|
|
37
38
|
"eslint": "*",
|
|
38
39
|
"typescript": "*"
|
|
39
40
|
},
|
|
40
|
-
"gitHead": "
|
|
41
|
+
"gitHead": "3c3e9e87199a229429edfe863117ba4e8f37f424"
|
|
41
42
|
}
|
package/dist/rules/eqeqeq.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
declare type Options = [{
|
|
2
|
-
readonly allowNullOrUndefined?: boolean;
|
|
3
|
-
}];
|
|
4
|
-
export declare type MessageIds = 'eqeqeq';
|
|
5
|
-
export declare const RULE_NAME = "eqeqeq";
|
|
6
|
-
declare const _default: import("@typescript-eslint/experimental-utils/dist/ts-eslint/Rule").RuleModule<"eqeqeq", Options, import("@typescript-eslint/experimental-utils/dist/ts-eslint/Rule").RuleListener>;
|
|
7
|
-
export default _default;
|