projecte_ionic/node_modules/@angular-eslint/eslint-plugin-template/dist/index.js
2022-02-09 18:30:03 +01:00

1 line
28 KiB
JavaScript
Executable file
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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}};