@angular-eslint/eslint-plugin-template 19.0.3-alpha.8 → 19.1.0

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/README.md CHANGED
@@ -87,6 +87,7 @@ Please see https://github.com/angular-eslint/angular-eslint for full usage instr
87
87
  | --- | --- | --- | --- | --- | --- |
88
88
  | [`attributes-order`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/docs/rules/attributes-order.md) | Ensures that HTML attributes and Angular bindings are sorted based on an expected order | | :wrench: | | |
89
89
  | [`prefer-self-closing-tags`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/docs/rules/prefer-self-closing-tags.md) | Ensures that self-closing tags are used for elements with a closing tag but no content. | | :wrench: | | |
90
+ | [`prefer-static-string-properties`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/docs/rules/prefer-static-string-properties.md) | Ensures that static string values use property assignment instead of property binding. | | :wrench: | | |
90
91
  <!-- prettier-ignore-end -->
91
92
 
92
93
  <!-- end layout rule list -->
@@ -27,6 +27,7 @@
27
27
  "@angular-eslint/template/prefer-control-flow": "error",
28
28
  "@angular-eslint/template/prefer-ngsrc": "error",
29
29
  "@angular-eslint/template/prefer-self-closing-tags": "error",
30
+ "@angular-eslint/template/prefer-static-string-properties": "error",
30
31
  "@angular-eslint/template/role-has-required-aria": "error",
31
32
  "@angular-eslint/template/table-scope": "error",
32
33
  "@angular-eslint/template/use-track-by-function": "error",
package/dist/index.d.ts CHANGED
@@ -29,6 +29,7 @@ declare const _default: {
29
29
  "@angular-eslint/template/prefer-control-flow": string;
30
30
  "@angular-eslint/template/prefer-ngsrc": string;
31
31
  "@angular-eslint/template/prefer-self-closing-tags": string;
32
+ "@angular-eslint/template/prefer-static-string-properties": string;
32
33
  "@angular-eslint/template/role-has-required-aria": string;
33
34
  "@angular-eslint/template/table-scope": string;
34
35
  "@angular-eslint/template/use-track-by-function": string;
@@ -106,6 +107,7 @@ declare const _default: {
106
107
  "no-positive-tabindex": import("@typescript-eslint/utils/ts-eslint").RuleModule<import("./rules/no-positive-tabindex").MessageIds, [], import("./utils/create-eslint-rule").RuleDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
107
108
  "prefer-control-flow": import("@typescript-eslint/utils/ts-eslint").RuleModule<"preferControlFlow", [], import("./utils/create-eslint-rule").RuleDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
108
109
  "prefer-self-closing-tags": import("@typescript-eslint/utils/ts-eslint").RuleModule<"preferSelfClosingTags", [], import("./utils/create-eslint-rule").RuleDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
110
+ "prefer-static-string-properties": import("@typescript-eslint/utils/ts-eslint").RuleModule<"preferStaticStringProperties", [], import("./utils/create-eslint-rule").RuleDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
109
111
  "prefer-ngsrc": import("@typescript-eslint/utils/ts-eslint").RuleModule<import("./rules/prefer-ngsrc").MessageIds, [], import("./utils/create-eslint-rule").RuleDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
110
112
  "role-has-required-aria": import("@typescript-eslint/utils/ts-eslint").RuleModule<import("./rules/role-has-required-aria").MessageIds, [], import("./utils/create-eslint-rule").RuleDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
111
113
  "table-scope": import("@typescript-eslint/utils/ts-eslint").RuleModule<"tableScope", [], import("./utils/create-eslint-rule").RuleDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmFA,kBAuCE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsFA,kBAwCE"}
package/dist/index.js CHANGED
@@ -55,6 +55,7 @@ const no_positive_tabindex_1 = __importStar(require("./rules/no-positive-tabinde
55
55
  const prefer_ngsrc_1 = __importStar(require("./rules/prefer-ngsrc"));
56
56
  const prefer_control_flow_1 = __importStar(require("./rules/prefer-control-flow"));
57
57
  const prefer_self_closing_tags_1 = __importStar(require("./rules/prefer-self-closing-tags"));
58
+ const prefer_static_string_properties_1 = __importStar(require("./rules/prefer-static-string-properties"));
58
59
  const role_has_required_aria_1 = __importStar(require("./rules/role-has-required-aria"));
59
60
  const table_scope_1 = __importStar(require("./rules/table-scope"));
60
61
  const use_track_by_function_1 = __importStar(require("./rules/use-track-by-function"));
@@ -92,6 +93,7 @@ module.exports = {
92
93
  [no_positive_tabindex_1.RULE_NAME]: no_positive_tabindex_1.default,
93
94
  [prefer_control_flow_1.RULE_NAME]: prefer_control_flow_1.default,
94
95
  [prefer_self_closing_tags_1.RULE_NAME]: prefer_self_closing_tags_1.default,
96
+ [prefer_static_string_properties_1.RULE_NAME]: prefer_static_string_properties_1.default,
95
97
  [prefer_ngsrc_1.RULE_NAME]: prefer_ngsrc_1.default,
96
98
  [role_has_required_aria_1.RULE_NAME]: role_has_required_aria_1.default,
97
99
  [table_scope_1.RULE_NAME]: table_scope_1.default,
@@ -211,7 +211,8 @@ function toTemplateReferenceVariableOrderType(reference) {
211
211
  };
212
212
  }
213
213
  function isImplicitTemplate(node) {
214
- return isTmplAstTemplate(node) && node.tagName !== 'ng-template';
214
+ return (isTmplAstTemplate(node) &&
215
+ (node.tagName === null || !/^(:svg:)?ng-template$/.test(node.tagName)));
215
216
  }
216
217
  function extractTemplateAttrs(node) {
217
218
  if (isTmplAstTemplate(node)) {
@@ -1 +1 @@
1
- {"version":3,"file":"prefer-self-closing-tags.d.ts","sourceRoot":"","sources":["../../src/rules/prefer-self-closing-tags.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,OAAO,GAAG,EAAE,CAAC;AACzB,MAAM,MAAM,UAAU,GAAG,uBAAuB,CAAC;AACjD,eAAO,MAAM,SAAS,6BAA6B,CAAC;;AAEpD,wBAkIG"}
1
+ {"version":3,"file":"prefer-self-closing-tags.d.ts","sourceRoot":"","sources":["../../src/rules/prefer-self-closing-tags.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,OAAO,GAAG,EAAE,CAAC;AACzB,MAAM,MAAM,UAAU,GAAG,uBAAuB,CAAC;AACjD,eAAO,MAAM,SAAS,6BAA6B,CAAC;;AAEpD,wBAuIG"}
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RULE_NAME = void 0;
4
+ const bundled_angular_compiler_1 = require("@angular-eslint/bundled-angular-compiler");
4
5
  const utils_1 = require("@angular-eslint/utils");
5
6
  const create_eslint_rule_1 = require("../utils/create-eslint-rule");
6
7
  const get_dom_elements_1 = require("../utils/get-dom-elements");
@@ -44,10 +45,16 @@ exports.default = (0, create_eslint_rule_1.createESLintRule)({
44
45
  const { children, startSourceSpan, endSourceSpan } = node;
45
46
  const noContent = !children.length ||
46
47
  children.every((node) => {
47
- const text = node.value;
48
- // If the node has no value, or only whitespace,
49
- // we can consider it empty.
50
- return (typeof text === 'string' && text.replace(/\n/g, '').trim() === '');
48
+ // If the node is only whitespace, we can consider it empty.
49
+ // We need to look at the text from the source code, rather
50
+ // than the `TmplAstText.value` property. The `value` property
51
+ // contains the HTML-decoded value, so if the raw text contains
52
+ // `&nbsp;`, that is decoded to a space, but we don't want to
53
+ // treat that as empty text.
54
+ return (node instanceof bundled_angular_compiler_1.TmplAstText &&
55
+ context.sourceCode.text
56
+ .slice(node.sourceSpan.start.offset, node.sourceSpan.end.offset)
57
+ .trim() === '');
51
58
  });
52
59
  const noCloseTag = !endSourceSpan ||
53
60
  (startSourceSpan.start.offset === endSourceSpan.start.offset &&
@@ -0,0 +1,6 @@
1
+ export type Options = [];
2
+ export type MessageIds = 'preferStaticStringProperties';
3
+ export declare const RULE_NAME = "prefer-static-string-properties";
4
+ declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"preferStaticStringProperties", [], import("../utils/create-eslint-rule").RuleDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
5
+ export default _default;
6
+ //# sourceMappingURL=prefer-static-string-properties.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prefer-static-string-properties.d.ts","sourceRoot":"","sources":["../../src/rules/prefer-static-string-properties.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,OAAO,GAAG,EAAE,CAAC;AACzB,MAAM,MAAM,UAAU,GAAG,8BAA8B,CAAC;AACxD,eAAO,MAAM,SAAS,oCAAoC,CAAC;;AAE3D,wBA6CG"}
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RULE_NAME = void 0;
4
+ const bundled_angular_compiler_1 = require("@angular-eslint/bundled-angular-compiler");
5
+ const utils_1 = require("@angular-eslint/utils");
6
+ const create_eslint_rule_1 = require("../utils/create-eslint-rule");
7
+ exports.RULE_NAME = 'prefer-static-string-properties';
8
+ exports.default = (0, create_eslint_rule_1.createESLintRule)({
9
+ name: exports.RULE_NAME,
10
+ meta: {
11
+ type: 'layout',
12
+ docs: {
13
+ description: 'Ensures that static string values use property assignment instead of property binding.',
14
+ },
15
+ fixable: 'code',
16
+ schema: [],
17
+ messages: {
18
+ preferStaticStringProperties: 'Using a property is more efficient than binding a static string.',
19
+ },
20
+ },
21
+ defaultOptions: [],
22
+ create(context) {
23
+ const parserServices = (0, utils_1.getTemplateParserServices)(context);
24
+ return {
25
+ BoundAttribute({ name, sourceSpan, value }) {
26
+ if (value instanceof bundled_angular_compiler_1.ASTWithSource &&
27
+ value.ast instanceof bundled_angular_compiler_1.LiteralPrimitive &&
28
+ typeof value.ast.value === 'string') {
29
+ // If the string literal is quoted with a double quote,
30
+ // then the property binding must be using single quotes
31
+ // to quote the value, and we should keep using single
32
+ // quotes when we convert it to a property assignment.
33
+ const quote = value.source?.trimStart().at(0) === '"' ? "'" : '"';
34
+ const literal = value.ast.value;
35
+ context.report({
36
+ loc: parserServices.convertNodeSourceSpanToLoc(sourceSpan),
37
+ messageId: 'preferStaticStringProperties',
38
+ fix: (fixer) => fixer.replaceTextRange([sourceSpan.start.offset, sourceSpan.end.offset], `${name}=${quote}${literal}${quote}`),
39
+ });
40
+ }
41
+ },
42
+ };
43
+ },
44
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@angular-eslint/eslint-plugin-template",
3
- "version": "19.0.3-alpha.8",
3
+ "version": "19.1.0",
4
4
  "description": "ESLint plugin for Angular Templates",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -20,13 +20,13 @@
20
20
  "dependencies": {
21
21
  "aria-query": "5.3.2",
22
22
  "axobject-query": "4.1.0",
23
- "@angular-eslint/bundled-angular-compiler": "19.0.3-alpha.8",
24
- "@angular-eslint/utils": "19.0.3-alpha.8"
23
+ "@angular-eslint/utils": "19.1.0",
24
+ "@angular-eslint/bundled-angular-compiler": "19.1.0"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@types/aria-query": "5.0.4",
28
- "@angular-eslint/test-utils": "19.0.3-alpha.8",
29
- "@angular-eslint/template-parser": "19.0.3-alpha.8"
28
+ "@angular-eslint/test-utils": "19.1.0",
29
+ "@angular-eslint/template-parser": "19.1.0"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "@typescript-eslint/types": "^7.11.0 || ^8.0.0",