@depup/angular-eslint__template-parser 21.3.1-depup.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/LICENSE +21 -0
- package/README.md +25 -0
- package/changes.json +5 -0
- package/dist/convert-source-span-to-loc.d.ts +7 -0
- package/dist/convert-source-span-to-loc.d.ts.map +1 -0
- package/dist/convert-source-span-to-loc.js +68 -0
- package/dist/index.d.ts +50 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +331 -0
- package/package.json +46 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 James Henry
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# @depup/angular-eslint__template-parser
|
|
2
|
+
|
|
3
|
+
> Dependency-bumped version of [@angular-eslint/template-parser](https://www.npmjs.com/package/@angular-eslint/template-parser)
|
|
4
|
+
|
|
5
|
+
Generated by [DepUp](https://github.com/depup/npm) -- all production
|
|
6
|
+
dependencies bumped to latest versions.
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install @depup/angular-eslint__template-parser
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
| Field | Value |
|
|
15
|
+
|-------|-------|
|
|
16
|
+
| Original | [@angular-eslint/template-parser](https://www.npmjs.com/package/@angular-eslint/template-parser) @ 21.3.1 |
|
|
17
|
+
| Processed | 2026-03-22 |
|
|
18
|
+
| Smoke test | passed |
|
|
19
|
+
| Deps updated | 0 |
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
Source: https://github.com/depup/npm | Original: https://www.npmjs.com/package/@angular-eslint/template-parser
|
|
24
|
+
|
|
25
|
+
License inherited from the original package.
|
package/changes.json
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ParseSourceSpan, TmplAstElement } from '@angular-eslint/bundled-angular-compiler';
|
|
2
|
+
import type { TSESLint, TSESTree } from '@typescript-eslint/utils';
|
|
3
|
+
export declare function convertNodeSourceSpanToLoc(sourceSpan: ParseSourceSpan): TSESTree.SourceLocation;
|
|
4
|
+
export declare function convertElementSourceSpanToLoc(context: Readonly<TSESLint.RuleContext<string, readonly unknown[]>>, node: TmplAstElement & {
|
|
5
|
+
type: string;
|
|
6
|
+
}): TSESTree.SourceLocation;
|
|
7
|
+
//# sourceMappingURL=convert-source-span-to-loc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert-source-span-to-loc.d.ts","sourceRoot":"","sources":["../src/convert-source-span-to-loc.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,eAAe,EACf,cAAc,EACf,MAAM,0CAA0C,CAAC;AAMlD,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEnE,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,eAAe,GAC1B,QAAQ,CAAC,cAAc,CAWzB;AAED,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,CAAC,CAAC,EACnE,IAAI,EAAE,cAAc,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GACtC,QAAQ,CAAC,cAAc,CAoBzB"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.convertNodeSourceSpanToLoc = convertNodeSourceSpanToLoc;
|
|
4
|
+
exports.convertElementSourceSpanToLoc = convertElementSourceSpanToLoc;
|
|
5
|
+
const bundled_angular_compiler_1 = require("@angular-eslint/bundled-angular-compiler");
|
|
6
|
+
function convertNodeSourceSpanToLoc(sourceSpan) {
|
|
7
|
+
return {
|
|
8
|
+
start: {
|
|
9
|
+
line: sourceSpan.start.line + 1,
|
|
10
|
+
column: sourceSpan.start.col,
|
|
11
|
+
},
|
|
12
|
+
end: {
|
|
13
|
+
line: sourceSpan.end.line + 1,
|
|
14
|
+
column: sourceSpan.end.col,
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function convertElementSourceSpanToLoc(context, node) {
|
|
19
|
+
if (node.type !== 'Element') {
|
|
20
|
+
// We explicitly throw an exception since this function should not be used
|
|
21
|
+
// with non-element nodes, e.g. `TextAttribute` or `MethodDefinition`, etc.
|
|
22
|
+
throw new Error('convertElementSourceSpanToLoc is intended to be used only with elements.');
|
|
23
|
+
}
|
|
24
|
+
// Void elements are "self-closed" elements, e.g. `<img />` or `<area />`.
|
|
25
|
+
// The Angular compiler explicitly doesn't set the end source span for void
|
|
26
|
+
// elements, but we still have to find its location to be able to report failures.
|
|
27
|
+
if ((0, bundled_angular_compiler_1.getHtmlTagDefinition)(node.name).isVoid) {
|
|
28
|
+
// Fallback to the original `node` if the
|
|
29
|
+
// `tryToFindTheVoidNodeThatMatchesTheSourceSpan` returns nothing.
|
|
30
|
+
node = (tryToFindTheVoidNodeThatMatchesTheSourceSpan(context, node) ||
|
|
31
|
+
node);
|
|
32
|
+
}
|
|
33
|
+
return convertNodeSourceSpanToLoc(node.sourceSpan);
|
|
34
|
+
}
|
|
35
|
+
function tryToFindTheVoidNodeThatMatchesTheSourceSpan(context, node) {
|
|
36
|
+
// Previously, `codelyzer` used `TemplateParser` to parse a template into an AST tree.
|
|
37
|
+
// The `TemplateParser` used `HtmlParser`, because `HtmlParser` still sets the end span
|
|
38
|
+
// for void elements.
|
|
39
|
+
const { rootNodes } = getHtmlParser().parse(context.sourceCode.getText(), context.filename);
|
|
40
|
+
return lookupTheVoidNode(rootNodes, node.sourceSpan);
|
|
41
|
+
}
|
|
42
|
+
function lookupTheVoidNode(rootNodes, sourceSpan) {
|
|
43
|
+
for (const node of rootNodes) {
|
|
44
|
+
if (
|
|
45
|
+
// We can't compare by `node.sourceSpan == sourceSpan` since references
|
|
46
|
+
// will differ. But comparing `line` and` offset` is the
|
|
47
|
+
// correct way, because they will not differ.
|
|
48
|
+
node.sourceSpan.start.line === sourceSpan.start.line &&
|
|
49
|
+
node.sourceSpan.start.offset === sourceSpan.start.offset) {
|
|
50
|
+
return node;
|
|
51
|
+
}
|
|
52
|
+
// `HtmlParser` will return a list of root nodes, these nodes
|
|
53
|
+
// can be either text or elements. Elements might have child elements.
|
|
54
|
+
if (node instanceof bundled_angular_compiler_1.Element) {
|
|
55
|
+
const voidNodeBeingLookedUp = lookupTheVoidNode(node.children, sourceSpan);
|
|
56
|
+
if (voidNodeBeingLookedUp !== null) {
|
|
57
|
+
return voidNodeBeingLookedUp;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
let htmlParser = null;
|
|
64
|
+
// Initialize the `HtmlParser` class lazily only when the function is
|
|
65
|
+
// invoked for the first time.
|
|
66
|
+
function getHtmlParser() {
|
|
67
|
+
return htmlParser || (htmlParser = new bundled_angular_compiler_1.HtmlParser());
|
|
68
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { ParseError } from '@angular-eslint/bundled-angular-compiler';
|
|
2
|
+
import type { TSESTree } from '@typescript-eslint/types';
|
|
3
|
+
import { ScopeManager } from 'eslint-scope';
|
|
4
|
+
import { convertElementSourceSpanToLoc, convertNodeSourceSpanToLoc } from './convert-source-span-to-loc';
|
|
5
|
+
type NodeOrTokenType = any;
|
|
6
|
+
interface Node {
|
|
7
|
+
[key: string]: any;
|
|
8
|
+
type: NodeOrTokenType;
|
|
9
|
+
}
|
|
10
|
+
interface VisitorKeys {
|
|
11
|
+
[nodeName: string]: string[];
|
|
12
|
+
}
|
|
13
|
+
interface Token extends TSESTree.BaseNode {
|
|
14
|
+
type: NodeOrTokenType;
|
|
15
|
+
value: string;
|
|
16
|
+
}
|
|
17
|
+
interface AST extends Node, Omit<Token, 'parent'> {
|
|
18
|
+
comments: Token[];
|
|
19
|
+
tokens: Token[];
|
|
20
|
+
templateNodes: any[];
|
|
21
|
+
}
|
|
22
|
+
export declare class TemplateParseError extends Error {
|
|
23
|
+
readonly fileName: string;
|
|
24
|
+
readonly index: number;
|
|
25
|
+
readonly lineNumber: number;
|
|
26
|
+
readonly column: number;
|
|
27
|
+
constructor(message: string, fileName: string, index: number, lineNumber: number, column: number);
|
|
28
|
+
}
|
|
29
|
+
export declare function createTemplateParseError(parseError: ParseError): TemplateParseError;
|
|
30
|
+
export interface ParserOptions {
|
|
31
|
+
filePath: string;
|
|
32
|
+
suppressParseErrors?: boolean;
|
|
33
|
+
}
|
|
34
|
+
declare function parseForESLint(code: string, options: ParserOptions): {
|
|
35
|
+
ast: AST;
|
|
36
|
+
scopeManager: InstanceType<typeof ScopeManager>;
|
|
37
|
+
visitorKeys: VisitorKeys;
|
|
38
|
+
services: {
|
|
39
|
+
convertElementSourceSpanToLoc: typeof convertElementSourceSpanToLoc;
|
|
40
|
+
convertNodeSourceSpanToLoc: typeof convertNodeSourceSpanToLoc;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
export { parseForESLint };
|
|
44
|
+
export declare function parse(code: string, options: ParserOptions): AST;
|
|
45
|
+
export declare const version: string;
|
|
46
|
+
export declare const meta: {
|
|
47
|
+
name: string;
|
|
48
|
+
version: string;
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,UAAU,EAEX,MAAM,0CAA0C,CAAC;AAElD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAW,YAAY,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EACL,6BAA6B,EAC7B,0BAA0B,EAC3B,MAAM,8BAA8B,CAAC;AAEtC,KAAK,eAAe,GAAG,GAAG,CAAC;AAE3B,UAAU,IAAI;IAEZ,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;IACnB,IAAI,EAAE,eAAe,CAAC;CACvB;AAED,UAAU,WAAW;IACnB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC9B;AAED,UAAU,KAAM,SAAQ,QAAQ,CAAC,QAAQ;IACvC,IAAI,EAAE,eAAe,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,UAAU,GAAI,SAAQ,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC;IAC/C,QAAQ,EAAE,KAAK,EAAE,CAAC;IAClB,MAAM,EAAE,KAAK,EAAE,CAAC;IAEhB,aAAa,EAAE,GAAG,EAAE,CAAC;CACtB;AA2QD,qBAAa,kBAAmB,SAAQ,KAAK;aAGzB,QAAQ,EAAE,MAAM;aAChB,KAAK,EAAE,MAAM;aACb,UAAU,EAAE,MAAM;aAClB,MAAM,EAAE,MAAM;gBAJ9B,OAAO,EAAE,MAAM,EACC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM;CASjC;AAED,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,UAAU,GACrB,kBAAkB,CAOpB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,iBAAS,cAAc,CACrB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,aAAa,GACrB;IACD,GAAG,EAAE,GAAG,CAAC;IACT,YAAY,EAAE,YAAY,CAAC,OAAO,YAAY,CAAC,CAAC;IAChD,WAAW,EAAE,WAAW,CAAC;IACzB,QAAQ,EAAE;QACR,6BAA6B,EAAE,OAAO,6BAA6B,CAAC;QACpE,0BAA0B,EAAE,OAAO,0BAA0B,CAAC;KAC/D,CAAC;CACH,CA+DA;AAED,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,GAAG,CAE/D;AAGD,eAAO,MAAM,OAAO,EAAE,MAA2C,CAAC;AAElE,eAAO,MAAM,IAAI;;;CAGhB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.meta = exports.version = exports.TemplateParseError = void 0;
|
|
4
|
+
exports.createTemplateParseError = createTemplateParseError;
|
|
5
|
+
exports.parseForESLint = parseForESLint;
|
|
6
|
+
exports.parse = parse;
|
|
7
|
+
const bundled_angular_compiler_1 = require("@angular-eslint/bundled-angular-compiler");
|
|
8
|
+
const eslint_scope_1 = require("eslint-scope");
|
|
9
|
+
const convert_source_span_to_loc_1 = require("./convert-source-span-to-loc");
|
|
10
|
+
const KEYS = {
|
|
11
|
+
ASTWithSource: ['ast'],
|
|
12
|
+
Binary: ['left', 'right'],
|
|
13
|
+
BoundAttribute: ['value'],
|
|
14
|
+
BoundEvent: ['handler'],
|
|
15
|
+
BoundText: ['value'],
|
|
16
|
+
Call: ['receiver', 'args'],
|
|
17
|
+
SafeCall: ['receiver', 'args'],
|
|
18
|
+
Conditional: ['condition', 'trueExp', 'falseExp'],
|
|
19
|
+
Element: ['children', 'inputs', 'outputs', 'attributes'],
|
|
20
|
+
Interpolation: ['expressions'],
|
|
21
|
+
KeyedRead: ['receiver', 'key'],
|
|
22
|
+
NonNullAssert: ['expression'],
|
|
23
|
+
PrefixNot: ['expression'],
|
|
24
|
+
Program: ['templateNodes'],
|
|
25
|
+
PropertyRead: ['receiver'],
|
|
26
|
+
SafePropertyRead: ['receiver'],
|
|
27
|
+
Template: ['templateAttrs', 'children', 'inputs'],
|
|
28
|
+
BindingPipe: ['exp', 'args'],
|
|
29
|
+
DeferredBlock: [
|
|
30
|
+
'children',
|
|
31
|
+
'placeholder',
|
|
32
|
+
'loading',
|
|
33
|
+
'error',
|
|
34
|
+
'triggers',
|
|
35
|
+
'prefetchTriggers',
|
|
36
|
+
],
|
|
37
|
+
DeferredBlockLoading: ['children'],
|
|
38
|
+
DeferredBlockError: ['children'],
|
|
39
|
+
DeferredBlockPlaceholder: ['children'],
|
|
40
|
+
Object: ['when'],
|
|
41
|
+
BoundDeferredTrigger: ['value'],
|
|
42
|
+
IfBlock: ['branches'],
|
|
43
|
+
IfBlockBranch: ['children', 'expression'],
|
|
44
|
+
SwitchBlock: ['groups', 'expression'],
|
|
45
|
+
SwitchBlockCaseGroup: ['cases', 'children'],
|
|
46
|
+
SwitchBlockCase: ['expression'],
|
|
47
|
+
ForLoopBlock: ['children', 'empty', 'expression', 'trackBy'],
|
|
48
|
+
ForLoopBlockEmpty: ['children'],
|
|
49
|
+
Content: ['children'],
|
|
50
|
+
LetDeclaration: ['value'],
|
|
51
|
+
ParenthesizedExpression: ['expression'],
|
|
52
|
+
};
|
|
53
|
+
function fallbackKeysFilter(key) {
|
|
54
|
+
let value = null;
|
|
55
|
+
return (key !== 'comments' &&
|
|
56
|
+
key !== 'leadingComments' &&
|
|
57
|
+
key !== 'loc' &&
|
|
58
|
+
key !== 'parent' &&
|
|
59
|
+
key !== 'range' &&
|
|
60
|
+
key !== 'tokens' &&
|
|
61
|
+
key !== 'trailingComments' &&
|
|
62
|
+
(value = this[key]) !== null &&
|
|
63
|
+
typeof value === 'object' &&
|
|
64
|
+
(typeof value.type === 'string' || Array.isArray(value)));
|
|
65
|
+
}
|
|
66
|
+
function getFallbackKeys(node) {
|
|
67
|
+
return Object.keys(node).filter(fallbackKeysFilter, node);
|
|
68
|
+
}
|
|
69
|
+
function isNode(node) {
|
|
70
|
+
return (node !== null &&
|
|
71
|
+
typeof node === 'object' &&
|
|
72
|
+
typeof node.type === 'string');
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Get line offsets for a source code string (cached for performance)
|
|
76
|
+
*/
|
|
77
|
+
let lineOffsetsCache = null;
|
|
78
|
+
function getLineOffsets(sourceCode) {
|
|
79
|
+
if (!lineOffsetsCache) {
|
|
80
|
+
lineOffsetsCache = new Map();
|
|
81
|
+
}
|
|
82
|
+
let offsets = lineOffsetsCache.get(sourceCode);
|
|
83
|
+
if (!offsets) {
|
|
84
|
+
offsets = [0];
|
|
85
|
+
for (let i = 0; i < sourceCode.length; i++) {
|
|
86
|
+
if (sourceCode[i] === '\n') {
|
|
87
|
+
offsets.push(i + 1);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
lineOffsetsCache.set(sourceCode, offsets);
|
|
91
|
+
}
|
|
92
|
+
return offsets;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Convert absolute offsets to line/column positions
|
|
96
|
+
*/
|
|
97
|
+
function convertAbsoluteSourceSpanToLoc(sourceCode, span) {
|
|
98
|
+
const lineOffsets = getLineOffsets(sourceCode);
|
|
99
|
+
// Binary search for start line
|
|
100
|
+
let startLine = 0;
|
|
101
|
+
let left = 0;
|
|
102
|
+
let right = lineOffsets.length - 1;
|
|
103
|
+
while (left <= right) {
|
|
104
|
+
const mid = Math.floor((left + right) / 2);
|
|
105
|
+
if (lineOffsets[mid] <= span.start) {
|
|
106
|
+
startLine = mid;
|
|
107
|
+
left = mid + 1;
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
right = mid - 1;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
const startColumn = span.start - lineOffsets[startLine];
|
|
114
|
+
// Binary search for end line
|
|
115
|
+
let endLine = startLine; // Start from startLine as optimization
|
|
116
|
+
left = startLine;
|
|
117
|
+
right = lineOffsets.length - 1;
|
|
118
|
+
while (left <= right) {
|
|
119
|
+
const mid = Math.floor((left + right) / 2);
|
|
120
|
+
if (lineOffsets[mid] <= span.end) {
|
|
121
|
+
endLine = mid;
|
|
122
|
+
left = mid + 1;
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
right = mid - 1;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const endColumn = span.end - lineOffsets[endLine];
|
|
129
|
+
return {
|
|
130
|
+
start: { line: startLine + 1, column: startColumn },
|
|
131
|
+
end: { line: endLine + 1, column: endColumn },
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* ESLint requires all Nodes to have `type` and `loc` properties before it can
|
|
136
|
+
* work with the custom AST.
|
|
137
|
+
*/
|
|
138
|
+
function preprocessNode(node, sourceCode) {
|
|
139
|
+
let i = 0;
|
|
140
|
+
let j = 0;
|
|
141
|
+
const keys = KEYS[node.type] || getFallbackKeys(node);
|
|
142
|
+
if (!node.loc) {
|
|
143
|
+
if (node.sourceSpan &&
|
|
144
|
+
node.sourceSpan.start &&
|
|
145
|
+
typeof node.sourceSpan.start.line === 'number') {
|
|
146
|
+
// Regular ParseSourceSpan
|
|
147
|
+
node.loc = (0, convert_source_span_to_loc_1.convertNodeSourceSpanToLoc)(node.sourceSpan);
|
|
148
|
+
}
|
|
149
|
+
else if (node.sourceSpan &&
|
|
150
|
+
typeof node.sourceSpan.start === 'number' &&
|
|
151
|
+
sourceCode) {
|
|
152
|
+
// AbsoluteSourceSpan
|
|
153
|
+
node.loc = convertAbsoluteSourceSpanToLoc(sourceCode, node.sourceSpan);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
for (i = 0; i < keys.length; ++i) {
|
|
157
|
+
const child = node[keys[i]];
|
|
158
|
+
if (child == null) {
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
const isArr = Array.isArray(child);
|
|
162
|
+
if (child.type !== undefined) {
|
|
163
|
+
// Angular sometimes uses a prop called type already
|
|
164
|
+
child.__originalType = child.type;
|
|
165
|
+
}
|
|
166
|
+
if (!isArr && !child.type) {
|
|
167
|
+
child.type = child.constructor.name;
|
|
168
|
+
}
|
|
169
|
+
if (isArr) {
|
|
170
|
+
for (j = 0; j < child.length; ++j) {
|
|
171
|
+
const c = child[j];
|
|
172
|
+
if (c.type !== undefined) {
|
|
173
|
+
// Angular sometimes uses a prop called type already
|
|
174
|
+
c.__originalType = c.type;
|
|
175
|
+
}
|
|
176
|
+
// Pay attention to the condition `typeof c.type === number`,
|
|
177
|
+
// Angular compiler sets `type` property for some AST nodes,
|
|
178
|
+
// e.g. for the `BoundAttribute`, which is a `BindingType`.
|
|
179
|
+
if (!c.type || typeof c.type === 'number') {
|
|
180
|
+
c.type = c.constructor.name;
|
|
181
|
+
}
|
|
182
|
+
if (isNode(c)) {
|
|
183
|
+
preprocessNode(c, sourceCode);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
else if (isNode(child)) {
|
|
188
|
+
preprocessNode(child, sourceCode);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
function getStartSourceSpanFromAST(ast) {
|
|
193
|
+
let startSourceSpan = null;
|
|
194
|
+
ast.templateNodes.forEach((node) => {
|
|
195
|
+
const nodeSourceSpan = node.startSourceSpan || node.sourceSpan;
|
|
196
|
+
if (!startSourceSpan) {
|
|
197
|
+
startSourceSpan = nodeSourceSpan;
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
if (nodeSourceSpan &&
|
|
201
|
+
nodeSourceSpan.start.offset < startSourceSpan.start.offset) {
|
|
202
|
+
startSourceSpan = nodeSourceSpan;
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
return startSourceSpan;
|
|
207
|
+
}
|
|
208
|
+
function getEndSourceSpanFromAST(ast) {
|
|
209
|
+
let endSourceSpan = null;
|
|
210
|
+
ast.templateNodes.forEach((node) => {
|
|
211
|
+
const nodeSourceSpan = node.endSourceSpan || node.sourceSpan;
|
|
212
|
+
if (!endSourceSpan) {
|
|
213
|
+
endSourceSpan = nodeSourceSpan;
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
if (nodeSourceSpan &&
|
|
217
|
+
nodeSourceSpan.end.offset > endSourceSpan.end.offset) {
|
|
218
|
+
endSourceSpan = nodeSourceSpan;
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
return endSourceSpan;
|
|
223
|
+
}
|
|
224
|
+
function convertNgAstCommentsToTokens(comments) {
|
|
225
|
+
const commentTokens = comments.map((comment) => {
|
|
226
|
+
return {
|
|
227
|
+
// In an HTML context, effectively all our comments are Block comments
|
|
228
|
+
type: 'Block',
|
|
229
|
+
value: comment.value,
|
|
230
|
+
loc: (0, convert_source_span_to_loc_1.convertNodeSourceSpanToLoc)(comment.sourceSpan),
|
|
231
|
+
range: [comment.sourceSpan.start.offset, comment.sourceSpan.end.offset],
|
|
232
|
+
};
|
|
233
|
+
});
|
|
234
|
+
/**
|
|
235
|
+
* ESLint requires this to be sorted by Token#range[0]
|
|
236
|
+
* https://eslint.org/docs/developer-guide/working-with-custom-parsers
|
|
237
|
+
*/
|
|
238
|
+
return commentTokens.sort((a, b) => a.range[0] - b.range[0]);
|
|
239
|
+
}
|
|
240
|
+
class TemplateParseError extends Error {
|
|
241
|
+
fileName;
|
|
242
|
+
index;
|
|
243
|
+
lineNumber;
|
|
244
|
+
column;
|
|
245
|
+
constructor(message, fileName, index, lineNumber, column) {
|
|
246
|
+
super(message);
|
|
247
|
+
this.fileName = fileName;
|
|
248
|
+
this.index = index;
|
|
249
|
+
this.lineNumber = lineNumber;
|
|
250
|
+
this.column = column;
|
|
251
|
+
Object.defineProperty(this, 'name', {
|
|
252
|
+
value: new.target.name,
|
|
253
|
+
enumerable: false,
|
|
254
|
+
configurable: true,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
exports.TemplateParseError = TemplateParseError;
|
|
259
|
+
function createTemplateParseError(parseError) {
|
|
260
|
+
const message = parseError.msg;
|
|
261
|
+
const fileName = parseError.span.start.file.url;
|
|
262
|
+
const index = parseError.span.start.offset;
|
|
263
|
+
const lineNumber = parseError.span.start.line + 1;
|
|
264
|
+
const column = parseError.span.start.col + 1;
|
|
265
|
+
return new TemplateParseError(message, fileName, index, lineNumber, column);
|
|
266
|
+
}
|
|
267
|
+
function parseForESLint(code, options) {
|
|
268
|
+
const angularCompilerResult = (0, bundled_angular_compiler_1.parseTemplate)(code, options.filePath, {
|
|
269
|
+
preserveWhitespaces: true,
|
|
270
|
+
preserveLineEndings: true,
|
|
271
|
+
collectCommentNodes: true,
|
|
272
|
+
});
|
|
273
|
+
let ngAstCommentNodes = [];
|
|
274
|
+
if (Array.isArray(angularCompilerResult.commentNodes)) {
|
|
275
|
+
ngAstCommentNodes = angularCompilerResult.commentNodes;
|
|
276
|
+
}
|
|
277
|
+
const ast = {
|
|
278
|
+
type: 'Program',
|
|
279
|
+
comments: convertNgAstCommentsToTokens(ngAstCommentNodes),
|
|
280
|
+
tokens: [],
|
|
281
|
+
range: [0, 0],
|
|
282
|
+
loc: {
|
|
283
|
+
start: { line: 0, column: 0 },
|
|
284
|
+
end: { line: 0, column: 0 },
|
|
285
|
+
},
|
|
286
|
+
templateNodes: angularCompilerResult.nodes,
|
|
287
|
+
value: code,
|
|
288
|
+
};
|
|
289
|
+
const astAsProgram = Object.defineProperties(ast, {
|
|
290
|
+
body: {
|
|
291
|
+
value: [],
|
|
292
|
+
enumerable: false,
|
|
293
|
+
},
|
|
294
|
+
sourceType: {
|
|
295
|
+
value: 'module',
|
|
296
|
+
enumerable: false,
|
|
297
|
+
},
|
|
298
|
+
});
|
|
299
|
+
const scopeManager = (0, eslint_scope_1.analyze)(astAsProgram);
|
|
300
|
+
preprocessNode(ast, code);
|
|
301
|
+
const startSourceSpan = getStartSourceSpanFromAST(ast);
|
|
302
|
+
const endSourceSpan = getEndSourceSpanFromAST(ast);
|
|
303
|
+
if (startSourceSpan && endSourceSpan) {
|
|
304
|
+
ast.range = [startSourceSpan.start.offset, endSourceSpan.end.offset];
|
|
305
|
+
ast.loc = {
|
|
306
|
+
start: (0, convert_source_span_to_loc_1.convertNodeSourceSpanToLoc)(startSourceSpan).start,
|
|
307
|
+
end: (0, convert_source_span_to_loc_1.convertNodeSourceSpanToLoc)(endSourceSpan).end,
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
if (!options.suppressParseErrors && angularCompilerResult.errors?.length) {
|
|
311
|
+
throw createTemplateParseError(angularCompilerResult.errors[0]);
|
|
312
|
+
}
|
|
313
|
+
return {
|
|
314
|
+
ast,
|
|
315
|
+
scopeManager,
|
|
316
|
+
visitorKeys: KEYS,
|
|
317
|
+
services: {
|
|
318
|
+
convertNodeSourceSpanToLoc: convert_source_span_to_loc_1.convertNodeSourceSpanToLoc,
|
|
319
|
+
convertElementSourceSpanToLoc: convert_source_span_to_loc_1.convertElementSourceSpanToLoc,
|
|
320
|
+
},
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
function parse(code, options) {
|
|
324
|
+
return parseForESLint(code, options).ast;
|
|
325
|
+
}
|
|
326
|
+
// NOTE - we cannot migrate this to an import statement because it will make TSC copy the package.json to the dist folder
|
|
327
|
+
exports.version = require('../package.json').version;
|
|
328
|
+
exports.meta = {
|
|
329
|
+
name: 'angular-eslint/template-parser',
|
|
330
|
+
version: exports.version,
|
|
331
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@depup/angular-eslint__template-parser",
|
|
3
|
+
"version": "21.3.1-depup.0",
|
|
4
|
+
"description": "Angular Template parser for ESLint (with updated dependencies)",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/angular-eslint/angular-eslint.git",
|
|
11
|
+
"directory": "packages/template-parser"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist",
|
|
15
|
+
"!**/*.tsbuildinfo",
|
|
16
|
+
"package.json",
|
|
17
|
+
"README.md",
|
|
18
|
+
"LICENSE",
|
|
19
|
+
"changes.json"
|
|
20
|
+
],
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"eslint-scope": "9.1.2",
|
|
23
|
+
"@angular-eslint/bundled-angular-compiler": "21.3.1"
|
|
24
|
+
},
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
|
|
27
|
+
"typescript": "*"
|
|
28
|
+
},
|
|
29
|
+
"gitHead": "e2006e5e9c99e5a943d1a999e0efa5247d29ec24",
|
|
30
|
+
"keywords": [
|
|
31
|
+
"@angular-eslint/template-parser",
|
|
32
|
+
"depup",
|
|
33
|
+
"updated-dependencies",
|
|
34
|
+
"security",
|
|
35
|
+
"latest",
|
|
36
|
+
"patched"
|
|
37
|
+
],
|
|
38
|
+
"depup": {
|
|
39
|
+
"changes": {},
|
|
40
|
+
"depsUpdated": 0,
|
|
41
|
+
"originalPackage": "@angular-eslint/template-parser",
|
|
42
|
+
"originalVersion": "21.3.1",
|
|
43
|
+
"processedAt": "2026-03-22T00:36:57.675Z",
|
|
44
|
+
"smokeTest": "passed"
|
|
45
|
+
}
|
|
46
|
+
}
|