@html-eslint/eslint-plugin 0.48.0 → 0.50.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/lib/configs/all.js +10 -0
- package/lib/index.js +14 -1
- package/lib/languages/html-language.js +3 -3
- package/lib/languages/html-source-code.js +13 -87
- package/lib/rules/indent/indent.js +45 -5
- package/lib/rules/no-empty-headings.js +18 -3
- package/lib/rules/require-closing-tags.js +17 -5
- package/lib/rules/utils/node.js +15 -0
- package/package.json +9 -9
- package/types/configs/all.d.ts +2 -0
- package/types/configs/all.d.ts.map +1 -0
- package/types/index.d.ts +8 -56
- package/types/index.d.ts.map +1 -1
- package/types/languages/html-language.d.ts +12 -3
- package/types/languages/html-language.d.ts.map +1 -1
- package/types/languages/html-source-code.d.ts +13 -55
- package/types/languages/html-source-code.d.ts.map +1 -1
- package/types/rules/indent/indent.d.ts +1 -0
- package/types/rules/indent/indent.d.ts.map +1 -1
- package/types/rules/no-empty-headings.d.ts.map +1 -1
- package/types/rules/require-closing-tags.d.ts.map +1 -1
- package/types/rules/utils/node.d.ts +5 -0
- package/types/rules/utils/node.d.ts.map +1 -1
package/lib/index.js
CHANGED
|
@@ -3,6 +3,7 @@ const {
|
|
|
3
3
|
recommendedRules,
|
|
4
4
|
recommendedLegacyRules,
|
|
5
5
|
} = require("./configs/recommended");
|
|
6
|
+
const { allRules } = require("./configs/all");
|
|
6
7
|
const { HTMLLanguage } = require("./languages/html-language");
|
|
7
8
|
const { name, version } = require("../package.json");
|
|
8
9
|
const parser = require("@html-eslint/parser");
|
|
@@ -11,7 +12,7 @@ const parser = require("@html-eslint/parser");
|
|
|
11
12
|
*/
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
|
-
* @
|
|
15
|
+
* @type {ESLint.Plugin}
|
|
15
16
|
*/
|
|
16
17
|
const plugin = {
|
|
17
18
|
meta: {
|
|
@@ -42,6 +43,18 @@ const plugin = {
|
|
|
42
43
|
},
|
|
43
44
|
rules: recommendedLegacyRules,
|
|
44
45
|
},
|
|
46
|
+
"flat/all": {
|
|
47
|
+
plugins: {
|
|
48
|
+
/** @type {ESLint.Plugin} */
|
|
49
|
+
get "@html-eslint"() {
|
|
50
|
+
return plugin;
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
languageOptions: {
|
|
54
|
+
parser,
|
|
55
|
+
},
|
|
56
|
+
rules: allRules,
|
|
57
|
+
},
|
|
45
58
|
},
|
|
46
59
|
};
|
|
47
60
|
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
const { visitorKeys, parseForESLint } = require("@html-eslint/parser");
|
|
8
|
-
const {
|
|
8
|
+
const { createHTMLSourceCode } = require("./html-source-code");
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* @implements {Language<{ LangOptions: ParserOptions; Code:
|
|
11
|
+
* @implements {Language<{ LangOptions: ParserOptions; Code: ReturnType<typeof createHTMLSourceCode>; RootNode: AST.Program; Node: {}}>}
|
|
12
12
|
*/
|
|
13
13
|
class HTMLLanguage {
|
|
14
14
|
constructor() {
|
|
@@ -104,7 +104,7 @@ class HTMLLanguage {
|
|
|
104
104
|
* @param {OkParseResult<AST.Program>} parseResult
|
|
105
105
|
*/
|
|
106
106
|
createSourceCode(file, parseResult) {
|
|
107
|
-
return
|
|
107
|
+
return createHTMLSourceCode({
|
|
108
108
|
text: /** @type {string} */ (file.body),
|
|
109
109
|
ast: parseResult.ast,
|
|
110
110
|
comments: parseResult.comments,
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @import {AST} from 'eslint';
|
|
3
3
|
* @import {SourceLocation, DirectiveType} from '@eslint/plugin-kit';
|
|
4
|
-
* @import {TraversalStep,
|
|
4
|
+
* @import {TraversalStep, SourceCode} from '@eslint/core';
|
|
5
5
|
* @import {CommentContent, AnyHTMLNode} from '@html-eslint/types';
|
|
6
6
|
* @import {BaseNode} from '../types';
|
|
7
|
+
*
|
|
7
8
|
*/
|
|
8
|
-
|
|
9
9
|
const {
|
|
10
10
|
TextSourceCodeBase,
|
|
11
11
|
ConfigCommentParser,
|
|
@@ -71,90 +71,6 @@ class HTMLSourceCode extends TextSourceCodeBase {
|
|
|
71
71
|
return this.lines;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
// Copied from eslint source code
|
|
75
|
-
/**
|
|
76
|
-
* @see https://github.com/eslint/eslint/blob/f60f2764971a33e252be13e560dccf21f554dbf1/lib/languages/js/source-code/source-code.js#L745
|
|
77
|
-
* @param {Position} loc
|
|
78
|
-
* @returns {number}
|
|
79
|
-
*/
|
|
80
|
-
getIndexFromLoc(loc) {
|
|
81
|
-
if (
|
|
82
|
-
typeof loc !== "object" ||
|
|
83
|
-
typeof loc.line !== "number" ||
|
|
84
|
-
typeof loc.column !== "number"
|
|
85
|
-
) {
|
|
86
|
-
throw new TypeError(
|
|
87
|
-
"Expected `loc` to be an object with numeric `line` and `column` properties."
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (loc.line <= 0) {
|
|
92
|
-
throw new RangeError(
|
|
93
|
-
`Line number out of range (line ${loc.line} requested). Line numbers should be 1-based.`
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (loc.line > this.lineStartIndices.length) {
|
|
98
|
-
throw new RangeError(
|
|
99
|
-
`Line number out of range (line ${loc.line} requested, but only ${this.lineStartIndices.length} lines present).`
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const lineStartIndex = this.lineStartIndices[loc.line - 1];
|
|
104
|
-
const lineEndIndex =
|
|
105
|
-
loc.line === this.lineStartIndices.length
|
|
106
|
-
? this.text.length
|
|
107
|
-
: this.lineStartIndices[loc.line];
|
|
108
|
-
const positionIndex = lineStartIndex + loc.column;
|
|
109
|
-
if (
|
|
110
|
-
(loc.line === this.lineStartIndices.length &&
|
|
111
|
-
positionIndex > lineEndIndex) ||
|
|
112
|
-
(loc.line < this.lineStartIndices.length && positionIndex >= lineEndIndex)
|
|
113
|
-
) {
|
|
114
|
-
throw new RangeError(
|
|
115
|
-
`Column number out of range (column ${loc.column} requested, but the length of line ${loc.line} is ${lineEndIndex - lineStartIndex}).`
|
|
116
|
-
);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return positionIndex;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// Copied from eslint source code
|
|
123
|
-
/**
|
|
124
|
-
* @see https://github.com/eslint/eslint/blob/f60f2764971a33e252be13e560dccf21f554dbf1/lib/languages/js/source-code/source-code.js#L694
|
|
125
|
-
* @param {number} index
|
|
126
|
-
* @returns {Position}
|
|
127
|
-
*/
|
|
128
|
-
getLocFromIndex(index) {
|
|
129
|
-
if (typeof index !== "number") {
|
|
130
|
-
throw new TypeError("Expected `index` to be a number.");
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
if (index < 0 || index > this.text.length) {
|
|
134
|
-
throw new RangeError(
|
|
135
|
-
`Index out of range (requested index ${index}, but source text has length ${this.text.length}).`
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
if (index === this.text.length) {
|
|
139
|
-
return {
|
|
140
|
-
line: this.lines.length,
|
|
141
|
-
// @ts-ignore
|
|
142
|
-
column: this.lines.at(-1).length,
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
const lineNumber =
|
|
147
|
-
// @ts-ignore
|
|
148
|
-
index >= this.lineStartIndices.at(-1)
|
|
149
|
-
? this.lineStartIndices.length
|
|
150
|
-
: this.lineStartIndices.findIndex((el) => index < el);
|
|
151
|
-
|
|
152
|
-
return {
|
|
153
|
-
line: lineNumber,
|
|
154
|
-
column: index - this.lineStartIndices[lineNumber - 1],
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
|
|
158
74
|
getInlineConfigNodes() {
|
|
159
75
|
return this.comments.filter((comment) => INLINE_CONFIG.test(comment.value));
|
|
160
76
|
}
|
|
@@ -267,7 +183,17 @@ class HTMLSourceCode extends TextSourceCodeBase {
|
|
|
267
183
|
return this.parentsMap.get(node);
|
|
268
184
|
}
|
|
269
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* @param {{ast: AST.Program, text: string, comments: CommentContent[]}} config
|
|
188
|
+
* @returns {TextSourceCodeBase<any> & {
|
|
189
|
+
* getDisableDirectives(): { problems: {ruleId: null | string, message: string; loc: SourceLocation}[]; directives: Directive[]}
|
|
190
|
+
* getInlineConfigNodes(): CommentContent[]
|
|
191
|
+
* }}
|
|
192
|
+
*/
|
|
193
|
+
function createHTMLSourceCode(config) {
|
|
194
|
+
return new HTMLSourceCode(config);
|
|
195
|
+
}
|
|
270
196
|
|
|
271
197
|
module.exports = {
|
|
272
|
-
|
|
198
|
+
createHTMLSourceCode,
|
|
273
199
|
};
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
* @property {number} [Option2.Attribute]
|
|
20
20
|
* @property {Record<string, number>} [Option2.tagChildrenIndent]
|
|
21
21
|
* @property {boolean} [Option2.ignoreComment]
|
|
22
|
+
* @property {"first" | "templateTag"} [Option2.templateIndentBase]
|
|
22
23
|
*/
|
|
23
24
|
|
|
24
25
|
const { parseTemplateLiteral } = require("../utils/template-literal");
|
|
@@ -102,6 +103,11 @@ module.exports = {
|
|
|
102
103
|
type: "boolean",
|
|
103
104
|
default: false,
|
|
104
105
|
},
|
|
106
|
+
templateIndentBase: {
|
|
107
|
+
type: "string",
|
|
108
|
+
enum: ["first", "templateTag"],
|
|
109
|
+
default: "templateTag",
|
|
110
|
+
},
|
|
105
111
|
},
|
|
106
112
|
additionalProperties: false,
|
|
107
113
|
},
|
|
@@ -116,6 +122,7 @@ module.exports = {
|
|
|
116
122
|
const indentLevelOptions = (context.options && context.options[1]) || {};
|
|
117
123
|
const lines = sourceCode.getLines();
|
|
118
124
|
const ignoreComment = indentLevelOptions.ignoreComment === true;
|
|
125
|
+
const autoBaseIndent = indentLevelOptions.templateIndentBase === "first";
|
|
119
126
|
const { indentType, indentSize, indentChar } = getIndentOptionInfo(context);
|
|
120
127
|
|
|
121
128
|
/**
|
|
@@ -161,12 +168,35 @@ module.exports = {
|
|
|
161
168
|
return 1;
|
|
162
169
|
}
|
|
163
170
|
|
|
171
|
+
/**
|
|
172
|
+
* @param {TemplateLiteral} node
|
|
173
|
+
* @returns {number}
|
|
174
|
+
*/
|
|
175
|
+
function getAutoBaseSpaces(node) {
|
|
176
|
+
if (!autoBaseIndent) {
|
|
177
|
+
return 0;
|
|
178
|
+
}
|
|
179
|
+
const startLineIndex = node.loc.start.line;
|
|
180
|
+
const endLineIndex = node.loc.end.line - 1;
|
|
181
|
+
const templateLines = lines.slice(startLineIndex, endLineIndex);
|
|
182
|
+
for (let i = 0; i < templateLines.length; i++) {
|
|
183
|
+
const line = templateLines[i];
|
|
184
|
+
if (line.trim()) {
|
|
185
|
+
return countLeftPadding(line);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return 0;
|
|
189
|
+
}
|
|
190
|
+
|
|
164
191
|
/**
|
|
165
192
|
*
|
|
166
193
|
* @param {TemplateLiteral} node
|
|
167
194
|
* @returns {number}
|
|
168
195
|
*/
|
|
169
196
|
function getTemplateLiteralBaseIndentLevel(node) {
|
|
197
|
+
if (autoBaseIndent) {
|
|
198
|
+
return 0;
|
|
199
|
+
}
|
|
170
200
|
// @ts-ignore
|
|
171
201
|
const lineIndex = node.loc.start.line - 1;
|
|
172
202
|
const line = lines[lineIndex];
|
|
@@ -181,8 +211,9 @@ module.exports = {
|
|
|
181
211
|
|
|
182
212
|
/**
|
|
183
213
|
* @param {number} baseLevel
|
|
214
|
+
* @param {number} baseSpaces
|
|
184
215
|
*/
|
|
185
|
-
function createIndentVisitor(baseLevel) {
|
|
216
|
+
function createIndentVisitor(baseLevel, baseSpaces) {
|
|
186
217
|
const indentLevel = new IndentLevel({
|
|
187
218
|
getIncreasingLevel,
|
|
188
219
|
});
|
|
@@ -210,7 +241,14 @@ module.exports = {
|
|
|
210
241
|
* @returns {string}
|
|
211
242
|
*/
|
|
212
243
|
function getExpectedIndent() {
|
|
213
|
-
|
|
244
|
+
let base = "";
|
|
245
|
+
if (indentType === "space") {
|
|
246
|
+
base = " ".repeat(baseSpaces);
|
|
247
|
+
} else {
|
|
248
|
+
base = indentChar.repeat(baseSpaces);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return base + indentChar.repeat(indentLevel.value());
|
|
214
252
|
}
|
|
215
253
|
|
|
216
254
|
/**
|
|
@@ -396,24 +434,26 @@ module.exports = {
|
|
|
396
434
|
}
|
|
397
435
|
|
|
398
436
|
return {
|
|
399
|
-
...createIndentVisitor(0),
|
|
437
|
+
...createIndentVisitor(0, 0),
|
|
400
438
|
TaggedTemplateExpression(node) {
|
|
401
439
|
if (shouldCheckTaggedTemplateExpression(node, context)) {
|
|
402
440
|
const base = getTemplateLiteralBaseIndentLevel(node.quasi);
|
|
441
|
+
const baseSpaces = getAutoBaseSpaces(node.quasi);
|
|
403
442
|
parseTemplateLiteral(
|
|
404
443
|
node.quasi,
|
|
405
444
|
getSourceCode(context),
|
|
406
|
-
createIndentVisitor(base)
|
|
445
|
+
createIndentVisitor(base, baseSpaces)
|
|
407
446
|
);
|
|
408
447
|
}
|
|
409
448
|
},
|
|
410
449
|
TemplateLiteral(node) {
|
|
411
450
|
if (shouldCheckTemplateLiteral(node, context)) {
|
|
412
451
|
const base = getTemplateLiteralBaseIndentLevel(node);
|
|
452
|
+
const baseSpaces = getAutoBaseSpaces(node);
|
|
413
453
|
parseTemplateLiteral(
|
|
414
454
|
node,
|
|
415
455
|
getSourceCode(context),
|
|
416
|
-
createIndentVisitor(base)
|
|
456
|
+
createIndentVisitor(base, baseSpaces)
|
|
417
457
|
);
|
|
418
458
|
}
|
|
419
459
|
},
|
|
@@ -36,18 +36,33 @@ function isRoleHeading(node) {
|
|
|
36
36
|
return !!roleAttr && !!roleAttr.value && roleAttr.value.value === "heading";
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
/**
|
|
40
|
+
* @param {Tag} node
|
|
41
|
+
* @returns {string}
|
|
42
|
+
*/
|
|
43
|
+
function getAltText(node) {
|
|
44
|
+
if (node.name.toLowerCase() === "img") {
|
|
45
|
+
const altAttr = findAttr(node, "alt");
|
|
46
|
+
if (altAttr && altAttr.value && altAttr.value.value) {
|
|
47
|
+
return altAttr.value.value;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return "";
|
|
51
|
+
}
|
|
52
|
+
|
|
39
53
|
/**
|
|
40
54
|
* @param {Text | Tag} node
|
|
41
55
|
* @returns {string}
|
|
42
56
|
*/
|
|
43
57
|
function getAllText(node) {
|
|
44
|
-
if (!isTag(node)
|
|
58
|
+
if (!isTag(node)) return "";
|
|
59
|
+
|
|
45
60
|
let text = "";
|
|
46
61
|
for (const child of node.children) {
|
|
47
62
|
if (isText(child)) {
|
|
48
63
|
text += child.value.trim();
|
|
49
64
|
} else if (isTag(child)) {
|
|
50
|
-
text += getAllText(child);
|
|
65
|
+
text += getAllText(child) || getAltText(child);
|
|
51
66
|
}
|
|
52
67
|
}
|
|
53
68
|
return text;
|
|
@@ -64,7 +79,7 @@ function getAccessibleText(node) {
|
|
|
64
79
|
if (isText(child)) {
|
|
65
80
|
text += child.value.trim();
|
|
66
81
|
} else if (isTag(child) && !isAriaHidden(child)) {
|
|
67
|
-
text += getAccessibleText(child);
|
|
82
|
+
text += getAccessibleText(child) || getAltText(child);
|
|
68
83
|
}
|
|
69
84
|
}
|
|
70
85
|
return text;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {Tag} from "@html-eslint/types";
|
|
2
|
+
* @import {ScriptTag, StyleTag, Tag} from "@html-eslint/types";
|
|
3
3
|
* @import {RuleModule} from "../types";
|
|
4
4
|
*
|
|
5
5
|
* @typedef {Object} Option
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
const { RULE_CATEGORY, VOID_ELEMENTS } = require("../constants");
|
|
11
11
|
const { createVisitors } = require("./utils/visitors");
|
|
12
12
|
const { getRuleUrl } = require("./utils/rule");
|
|
13
|
+
const { getNameOf } = require("./utils/node");
|
|
13
14
|
|
|
14
15
|
const VOID_ELEMENTS_SET = new Set(VOID_ELEMENTS);
|
|
15
16
|
|
|
@@ -76,14 +77,15 @@ module.exports = {
|
|
|
76
77
|
);
|
|
77
78
|
|
|
78
79
|
/**
|
|
79
|
-
* @param {Tag} node
|
|
80
|
+
* @param {Tag | ScriptTag | StyleTag} node
|
|
80
81
|
*/
|
|
81
|
-
function
|
|
82
|
+
function checkClosing(node) {
|
|
83
|
+
const name = getNameOf(node);
|
|
82
84
|
if (!node.close) {
|
|
83
85
|
context.report({
|
|
84
86
|
node: node,
|
|
85
87
|
data: {
|
|
86
|
-
tag:
|
|
88
|
+
tag: name,
|
|
87
89
|
},
|
|
88
90
|
messageId: MESSAGE_IDS.MISSING,
|
|
89
91
|
});
|
|
@@ -151,7 +153,7 @@ module.exports = {
|
|
|
151
153
|
if (node.selfClosing || canSelfClose) {
|
|
152
154
|
checkVoidElement(node, shouldSelfClose, canSelfClose);
|
|
153
155
|
} else if (node.openEnd.value !== "/>") {
|
|
154
|
-
|
|
156
|
+
checkClosing(node);
|
|
155
157
|
}
|
|
156
158
|
if (["svg", "math"].includes(node.name)) foreignContext.push(node.name);
|
|
157
159
|
},
|
|
@@ -163,6 +165,16 @@ module.exports = {
|
|
|
163
165
|
foreignContext.pop();
|
|
164
166
|
}
|
|
165
167
|
},
|
|
168
|
+
ScriptTag(node) {
|
|
169
|
+
if (!node.close) {
|
|
170
|
+
checkClosing(node);
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
StyleTag(node) {
|
|
174
|
+
if (!node.close) {
|
|
175
|
+
checkClosing(node);
|
|
176
|
+
}
|
|
177
|
+
},
|
|
166
178
|
});
|
|
167
179
|
},
|
|
168
180
|
};
|
package/lib/rules/utils/node.js
CHANGED
|
@@ -247,6 +247,20 @@ function getTemplateTokens(tokens) {
|
|
|
247
247
|
);
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
+
/**
|
|
251
|
+
* @param {Tag | ScriptTag | StyleTag} node
|
|
252
|
+
* @returns {string}
|
|
253
|
+
*/
|
|
254
|
+
function getNameOf(node) {
|
|
255
|
+
if (isScript(node)) {
|
|
256
|
+
return "script";
|
|
257
|
+
}
|
|
258
|
+
if (isStyle(node)) {
|
|
259
|
+
return "style";
|
|
260
|
+
}
|
|
261
|
+
return node.name;
|
|
262
|
+
}
|
|
263
|
+
|
|
250
264
|
module.exports = {
|
|
251
265
|
findAttr,
|
|
252
266
|
isAttributesEmpty,
|
|
@@ -266,4 +280,5 @@ module.exports = {
|
|
|
266
280
|
getTemplateTokens,
|
|
267
281
|
hasTemplate,
|
|
268
282
|
hasAttr,
|
|
283
|
+
getNameOf,
|
|
269
284
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@html-eslint/eslint-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.50.0",
|
|
4
4
|
"type": "commonjs",
|
|
5
5
|
"description": "ESLint plugin for HTML",
|
|
6
6
|
"author": "yeonjuan",
|
|
@@ -39,25 +39,25 @@
|
|
|
39
39
|
"accessibility"
|
|
40
40
|
],
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@eslint/plugin-kit": "^0.
|
|
43
|
-
"@html-eslint/parser": "^0.
|
|
44
|
-
"@html-eslint/template-parser": "^0.
|
|
45
|
-
"@html-eslint/template-syntax-parser": "^0.
|
|
46
|
-
"@html-eslint/types": "^0.
|
|
42
|
+
"@eslint/plugin-kit": "^0.4.1",
|
|
43
|
+
"@html-eslint/parser": "^0.50.0",
|
|
44
|
+
"@html-eslint/template-parser": "^0.50.0",
|
|
45
|
+
"@html-eslint/template-syntax-parser": "^0.50.0",
|
|
46
|
+
"@html-eslint/types": "^0.50.0"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"eslint": "^8.0.0 || ^9.0.0"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@eslint/core": "^0.
|
|
52
|
+
"@eslint/core": "^1.0.0",
|
|
53
53
|
"@types/estree": "^0.0.47",
|
|
54
54
|
"es-html-parser": "0.3.1",
|
|
55
|
-
"eslint": "^9.
|
|
55
|
+
"eslint": "^9.39.1",
|
|
56
56
|
"espree": "^10.3.0",
|
|
57
57
|
"typescript": "^5.8.3"
|
|
58
58
|
},
|
|
59
59
|
"engines": {
|
|
60
60
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "68100e43c5da0e3edb3d288f428a18d729d981d3"
|
|
63
63
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"all.d.ts","sourceRoot":"","sources":["../../lib/configs/all.js"],"names":[],"mappings":"AAEA,+CAGgD"}
|
package/types/index.d.ts
CHANGED
|
@@ -1,58 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
|
|
1
|
+
export = plugin;
|
|
2
|
+
/**
|
|
3
|
+
* @import { ESLint } from "eslint";
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* @type {ESLint.Plugin}
|
|
7
|
+
*/
|
|
8
|
+
declare const plugin: ESLint.Plugin;
|
|
5
9
|
import type { ESLint } from "eslint";
|
|
6
|
-
import parser = require("@html-eslint/parser");
|
|
7
|
-
export declare namespace meta {
|
|
8
|
-
export { name };
|
|
9
|
-
export { version };
|
|
10
|
-
}
|
|
11
|
-
export declare namespace languages {
|
|
12
|
-
let html: HTMLLanguage;
|
|
13
|
-
}
|
|
14
|
-
export { rules };
|
|
15
|
-
export declare let configs: {
|
|
16
|
-
recommended: {
|
|
17
|
-
rules: {
|
|
18
|
-
"html/require-lang": "error";
|
|
19
|
-
"html/require-img-alt": "error";
|
|
20
|
-
"html/require-doctype": "error";
|
|
21
|
-
"html/require-title": "error";
|
|
22
|
-
"html/no-multiple-h1": "error";
|
|
23
|
-
"html/no-extra-spacing-attrs": "error";
|
|
24
|
-
"html/attrs-newline": "error";
|
|
25
|
-
"html/element-newline": ["error", {
|
|
26
|
-
inline: string[];
|
|
27
|
-
}];
|
|
28
|
-
"html/no-duplicate-id": "error";
|
|
29
|
-
"html/indent": "error";
|
|
30
|
-
"html/require-li-container": "error";
|
|
31
|
-
"html/quotes": "error";
|
|
32
|
-
"html/no-obsolete-tags": "error";
|
|
33
|
-
"html/require-closing-tags": "error";
|
|
34
|
-
"html/no-duplicate-attrs": "error";
|
|
35
|
-
"html/use-baseline": "error";
|
|
36
|
-
"html/no-duplicate-in-head": "error";
|
|
37
|
-
};
|
|
38
|
-
plugins: {};
|
|
39
|
-
};
|
|
40
|
-
"recommended-legacy": {
|
|
41
|
-
rules: Record<string, "error" | ["error", {
|
|
42
|
-
inline: string[];
|
|
43
|
-
}]>;
|
|
44
|
-
};
|
|
45
|
-
"flat/recommended": {
|
|
46
|
-
plugins: {
|
|
47
|
-
/** @type {ESLint.Plugin} */
|
|
48
|
-
readonly "@html-eslint": ESLint.Plugin;
|
|
49
|
-
};
|
|
50
|
-
languageOptions: {
|
|
51
|
-
parser: typeof parser;
|
|
52
|
-
};
|
|
53
|
-
rules: Record<string, "error" | ["error", {
|
|
54
|
-
inline: string[];
|
|
55
|
-
}]>;
|
|
56
|
-
};
|
|
57
|
-
};
|
|
58
10
|
//# sourceMappingURL=index.d.ts.map
|
package/types/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../lib/index.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../lib/index.js"],"names":[],"mappings":";AASA;;GAEG;AAEH;;GAEG;AACH,sBAFU,aAAa,CA4CrB;4BAhDyB,QAAQ"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @implements {Language<{ LangOptions: ParserOptions; Code:
|
|
2
|
+
* @implements {Language<{ LangOptions: ParserOptions; Code: ReturnType<typeof createHTMLSourceCode>; RootNode: AST.Program; Node: {}}>}
|
|
3
3
|
*/
|
|
4
4
|
export class HTMLLanguage implements Language {
|
|
5
5
|
/**
|
|
@@ -43,7 +43,17 @@ export class HTMLLanguage implements Language {
|
|
|
43
43
|
* @param {File} file
|
|
44
44
|
* @param {OkParseResult<AST.Program>} parseResult
|
|
45
45
|
*/
|
|
46
|
-
createSourceCode(file: File, parseResult: OkParseResult<AST.Program>):
|
|
46
|
+
createSourceCode(file: File, parseResult: OkParseResult<AST.Program>): import("@eslint/plugin-kit").TextSourceCodeBase<any> & {
|
|
47
|
+
getDisableDirectives(): {
|
|
48
|
+
problems: {
|
|
49
|
+
ruleId: null | string;
|
|
50
|
+
message: string;
|
|
51
|
+
loc: import("@eslint/plugin-kit").SourceLocation;
|
|
52
|
+
}[];
|
|
53
|
+
directives: import("@eslint/plugin-kit").Directive[];
|
|
54
|
+
};
|
|
55
|
+
getInlineConfigNodes(): import("@html-eslint/types").CommentContent[];
|
|
56
|
+
};
|
|
47
57
|
}
|
|
48
58
|
import type { Language } from "@eslint/core";
|
|
49
59
|
import type { ParserOptions } from "@html-eslint/parser";
|
|
@@ -51,5 +61,4 @@ import type { File } from "@eslint/core";
|
|
|
51
61
|
import type { AST } from "eslint";
|
|
52
62
|
import type { ParseResult } from "@eslint/core";
|
|
53
63
|
import type { OkParseResult } from "@eslint/core";
|
|
54
|
-
import { HTMLSourceCode } from "./html-source-code";
|
|
55
64
|
//# sourceMappingURL=html-language.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"html-language.d.ts","sourceRoot":"","sources":["../../lib/languages/html-language.js"],"names":[],"mappings":"AASA;;GAEG;AACH;IAEI;;;OAGG;IACH,UAFU,MAAM,CAEM;IAEtB;;;OAGG;IACH,WAFU,CAAC,GAAC,CAAC,CAEK;IAElB;;;OAGG;IACH,aAFU,CAAC,GAAC,CAAC,CAEO;IAEpB;;OAEG;IACH,aAFU,MAAM,CAES;IAEzB;;;OAGG;IACH,aAFU,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAEJ;IAGhC;;OAEG;IACH,yCAFW,aAAa,QA8BvB;IAED;;;;;OAKG;IACH,YALW,IAAI,YAEZ;QAA+B,eAAe,EAAtC,aAAa;KACrB,GAAU,YAAY,WAAW,CAAC,CAkBpC;IAED;;;OAGG;IACH,uBAHW,IAAI,eACJ,cAAc,WAAW,CAAC
|
|
1
|
+
{"version":3,"file":"html-language.d.ts","sourceRoot":"","sources":["../../lib/languages/html-language.js"],"names":[],"mappings":"AASA;;GAEG;AACH;IAEI;;;OAGG;IACH,UAFU,MAAM,CAEM;IAEtB;;;OAGG;IACH,WAFU,CAAC,GAAC,CAAC,CAEK;IAElB;;;OAGG;IACH,aAFU,CAAC,GAAC,CAAC,CAEO;IAEpB;;OAEG;IACH,aAFU,MAAM,CAES;IAEzB;;;OAGG;IACH,aAFU,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAEJ;IAGhC;;OAEG;IACH,yCAFW,aAAa,QA8BvB;IAED;;;;;OAKG;IACH,YALW,IAAI,YAEZ;QAA+B,eAAe,EAAtC,aAAa;KACrB,GAAU,YAAY,WAAW,CAAC,CAkBpC;IAED;;;OAGG;IACH,uBAHW,IAAI,eACJ,cAAc,WAAW,CAAC;;;;;;;;;;MAQpC;CACF;8BA/GyE,cAAc;mCACtD,qBAAqB;0BADmB,cAAc;yBAEhE,QAAQ;iCAF0C,cAAc;mCAAd,cAAc"}
|
|
@@ -1,48 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
text: string;
|
|
10
|
-
comments: CommentContent[];
|
|
11
|
-
});
|
|
12
|
-
/**
|
|
13
|
-
* @property
|
|
14
|
-
*/
|
|
1
|
+
/**
|
|
2
|
+
* @param {{ast: AST.Program, text: string, comments: CommentContent[]}} config
|
|
3
|
+
* @returns {TextSourceCodeBase<any> & {
|
|
4
|
+
* getDisableDirectives(): { problems: {ruleId: null | string, message: string; loc: SourceLocation}[]; directives: Directive[]}
|
|
5
|
+
* getInlineConfigNodes(): CommentContent[]
|
|
6
|
+
* }}
|
|
7
|
+
*/
|
|
8
|
+
export function createHTMLSourceCode(config: {
|
|
15
9
|
ast: AST.Program;
|
|
16
|
-
|
|
17
|
-
* @property
|
|
18
|
-
*/
|
|
10
|
+
text: string;
|
|
19
11
|
comments: CommentContent[];
|
|
20
|
-
|
|
21
|
-
lineStartIndices: number[];
|
|
22
|
-
/**
|
|
23
|
-
* @param {BaseNode} node
|
|
24
|
-
* @returns {[number, number]}
|
|
25
|
-
*/
|
|
26
|
-
getRange(node: BaseNode): [number, number];
|
|
27
|
-
/**
|
|
28
|
-
* @param {BaseNode} node
|
|
29
|
-
* @returns {import("@eslint/plugin-kit").SourceLocation}
|
|
30
|
-
*/
|
|
31
|
-
getLoc(node: BaseNode): import("@eslint/plugin-kit").SourceLocation;
|
|
32
|
-
getLines(): string[];
|
|
33
|
-
/**
|
|
34
|
-
* @see https://github.com/eslint/eslint/blob/f60f2764971a33e252be13e560dccf21f554dbf1/lib/languages/js/source-code/source-code.js#L745
|
|
35
|
-
* @param {Position} loc
|
|
36
|
-
* @returns {number}
|
|
37
|
-
*/
|
|
38
|
-
getIndexFromLoc(loc: Position): number;
|
|
39
|
-
/**
|
|
40
|
-
* @see https://github.com/eslint/eslint/blob/f60f2764971a33e252be13e560dccf21f554dbf1/lib/languages/js/source-code/source-code.js#L694
|
|
41
|
-
* @param {number} index
|
|
42
|
-
* @returns {Position}
|
|
43
|
-
*/
|
|
44
|
-
getLocFromIndex(index: number): Position;
|
|
45
|
-
getInlineConfigNodes(): CommentContent[];
|
|
12
|
+
}): TextSourceCodeBase<any> & {
|
|
46
13
|
getDisableDirectives(): {
|
|
47
14
|
problems: {
|
|
48
15
|
ruleId: null | string;
|
|
@@ -51,20 +18,11 @@ export class HTMLSourceCode extends TextSourceCodeBase<import("@eslint/core").So
|
|
|
51
18
|
}[];
|
|
52
19
|
directives: Directive[];
|
|
53
20
|
};
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
* @param {AnyHTMLNode} node
|
|
57
|
-
* @returns
|
|
58
|
-
*/
|
|
59
|
-
getParent(node: AnyHTMLNode): any;
|
|
60
|
-
}
|
|
61
|
-
import { TextSourceCodeBase } from "@eslint/plugin-kit";
|
|
21
|
+
getInlineConfigNodes(): CommentContent[];
|
|
22
|
+
};
|
|
62
23
|
import type { AST } from 'eslint';
|
|
63
24
|
import type { CommentContent } from '@html-eslint/types';
|
|
64
|
-
import
|
|
65
|
-
import type { Position } from '@eslint/core';
|
|
25
|
+
import { TextSourceCodeBase } from "@eslint/plugin-kit";
|
|
66
26
|
import type { SourceLocation } from '@eslint/plugin-kit';
|
|
67
27
|
import { Directive } from "@eslint/plugin-kit";
|
|
68
|
-
import type { TraversalStep } from '@eslint/core';
|
|
69
|
-
import type { AnyHTMLNode } from '@html-eslint/types';
|
|
70
28
|
//# sourceMappingURL=html-source-code.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"html-source-code.d.ts","sourceRoot":"","sources":["../../lib/languages/html-source-code.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"html-source-code.d.ts","sourceRoot":"","sources":["../../lib/languages/html-source-code.js"],"names":[],"mappings":"AAyLA;;;;;;GAMG;AACH,6CANW;IAAC,GAAG,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,cAAc,EAAE,CAAA;CAAC,GAC1D,kBAAkB,CAAC,GAAG,CAAC,GAAG;IAClC,oBAAoB,IAAI;QAAE,QAAQ,EAAE;YAAC,MAAM,EAAE,IAAI,GAAG,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,GAAG,EAAE,cAAc,CAAA;SAAC,EAAE,CAAC;QAAC,UAAU,EAAE,SAAS,EAAE,CAAA;KAAC,CAAA;IAC7H,oBAAoB,IAAI,cAAc,EAAE,CAAA;CACzC,CAIH;yBAjMqB,QAAQ;oCAGgB,oBAAoB;;oCAFlB,oBAAoB"}
|
|
@@ -21,6 +21,7 @@ type Option2 = {
|
|
|
21
21
|
Attribute?: number | undefined;
|
|
22
22
|
tagChildrenIndent?: Record<string, number> | undefined;
|
|
23
23
|
ignoreComment?: boolean | undefined;
|
|
24
|
+
templateIndentBase?: "first" | "templateTag" | undefined;
|
|
24
25
|
};
|
|
25
26
|
import type { RuleModule } from "../../types";
|
|
26
27
|
import type { AnyNode } from "@html-eslint/types";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"indent.d.ts","sourceRoot":"","sources":["../../../lib/rules/indent/indent.js"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"indent.d.ts","sourceRoot":"","sources":["../../../lib/rules/indent/indent.js"],"names":[],"mappings":";;;wBAyDU,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;;qBApD3B,OAAO,GAAG,IAAI;;SAEb,KAAK;WACL,OAAO;;;kBAEP,aAAa;;;gBAEb,UAAU,CAAC,KAAK,CAAC,GAAG,UAAU,CAAC,OAAO,CAAC;gBACvC,MAAM;gBACN,MAAM;;eAEP,KAAK,GAAG,MAAM;;;;;;;gCAd+B,aAAa;6BAD+C,oBAAoB;0BAChF,aAAa"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-empty-headings.d.ts","sourceRoot":"","sources":["../../lib/rules/no-empty-headings.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"no-empty-headings.d.ts","sourceRoot":"","sources":["../../lib/rules/no-empty-headings.js"],"names":[],"mappings":"wBAwFU,WAAW,EAAE,CAAC;;gCAtFK,UAAU"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"require-closing-tags.d.ts","sourceRoot":"","sources":["../../lib/rules/require-closing-tags.js"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"require-closing-tags.d.ts","sourceRoot":"","sources":["../../lib/rules/require-closing-tags.js"],"names":[],"mappings":";;;wBAuBU,WAAW,CAAC,MAAM,CAAC,CAAC;;;;;;gCArBD,UAAU"}
|
|
@@ -104,6 +104,11 @@ export function hasTemplate(node: AttributeKey | AttributeValue | Text | Comment
|
|
|
104
104
|
* @returns {boolean}
|
|
105
105
|
*/
|
|
106
106
|
export function hasAttr(node: Tag | ScriptTag, attrName: string): boolean;
|
|
107
|
+
/**
|
|
108
|
+
* @param {Tag | ScriptTag | StyleTag} node
|
|
109
|
+
* @returns {string}
|
|
110
|
+
*/
|
|
111
|
+
export function getNameOf(node: Tag | ScriptTag | StyleTag): string;
|
|
107
112
|
import type { Tag } from "@html-eslint/types";
|
|
108
113
|
import type { ScriptTag } from "@html-eslint/types";
|
|
109
114
|
import type { StyleTag } from "@html-eslint/types";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../../lib/rules/utils/node.js"],"names":[],"mappings":"AAQA;;;;GAIG;AACH,+BAJW,GAAG,GAAG,SAAS,GAAG,QAAQ,OAC1B,MAAM,GACJ,SAAS,GAAG,SAAS,CAMjC;AAaD;;;;GAIG;AACH,wCAHW,GAAG,GAAG,SAAS,GAAG,QAAQ,GACxB,OAAO,CAInB;AAED;;;;GAIG;AACH,6CAHW,OAAO,GACL,OAAO,CAInB;AA+BD;;;;GAIG;AACH,uCAHW,IAAI,GAAG,cAAc,GACnB,IAAI,EAAE,CAwDlB;AAED;;;;;GAKG;AACH,sCAJW;IAAC,GAAG,EAAE,kBAAkB,CAAA;CAAC,SACzB;IAAC,GAAG,EAAE,kBAAkB,CAAA;CAAC,GACvB,kBAAkB,CAO9B;AA4DD;;;;GAIG;AACH,iCAJW,OAAO,aACP,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,GACxB,IAAI,GAAG,OAAO,CAiB1B;AA9ED;;;GAGG;AACH,4BAHW,QAAQ,GACN,IAAI,IAAI,GAAG,CAIvB;AAkBD;;;GAGG;AACH,gCAHW,QAAQ,GACN,IAAI,IAAI,OAAO,CAI3B;AAED;;;GAGG;AACH,6BAHW,QAAQ,GACN,IAAI,IAAI,IAAI,CAIxB;AAED;;;GAGG;AACH,6BAHW,QAAQ,GACN,IAAI,IAAI,IAAI,CAIxB;AAtCD;;;GAGG;AACH,+BAHW,QAAQ,GACN,IAAI,IAAI,SAAS,CAI7B;AAED;;;GAGG;AACH,8BAHW,QAAQ,GACN,IAAI,IAAI,QAAQ,CAI5B;AAnHD;;;;GAIG;AACH,8CAJW,CAAC,IAAI,GAAG,cAAc,CAAC,CAAC,OAAO,CAAC,SAChC,SAAS,GACP,OAAO,CAMnB;AAsID;;;GAGG;AACH,oCAHW,MAAM,GACJ,MAAM,EAAE,CAIpB;AA/JD;;;;;GAKG;AACH,wCAJW,SAAS,UACT,SAAS,GACP,OAAO,CAInB;AA+KD;;;;GAIG;AACH,0CAHW,QAAQ,EAAE,GACR,CAAC,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAaxD;AAlLD;;;GAGG;AACH,kCAHW,YAAY,GAAG,cAAc,GAAG,IAAI,GAAG,cAAc,GACnD,OAAO,CAInB;AAxDD;;;;GAIG;AACH,8BAJW,GAAG,GAAG,SAAS,YACf,MAAM,GACJ,OAAO,CAMnB;
|
|
1
|
+
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../../lib/rules/utils/node.js"],"names":[],"mappings":"AAQA;;;;GAIG;AACH,+BAJW,GAAG,GAAG,SAAS,GAAG,QAAQ,OAC1B,MAAM,GACJ,SAAS,GAAG,SAAS,CAMjC;AAaD;;;;GAIG;AACH,wCAHW,GAAG,GAAG,SAAS,GAAG,QAAQ,GACxB,OAAO,CAInB;AAED;;;;GAIG;AACH,6CAHW,OAAO,GACL,OAAO,CAInB;AA+BD;;;;GAIG;AACH,uCAHW,IAAI,GAAG,cAAc,GACnB,IAAI,EAAE,CAwDlB;AAED;;;;;GAKG;AACH,sCAJW;IAAC,GAAG,EAAE,kBAAkB,CAAA;CAAC,SACzB;IAAC,GAAG,EAAE,kBAAkB,CAAA;CAAC,GACvB,kBAAkB,CAO9B;AA4DD;;;;GAIG;AACH,iCAJW,OAAO,aACP,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,GACxB,IAAI,GAAG,OAAO,CAiB1B;AA9ED;;;GAGG;AACH,4BAHW,QAAQ,GACN,IAAI,IAAI,GAAG,CAIvB;AAkBD;;;GAGG;AACH,gCAHW,QAAQ,GACN,IAAI,IAAI,OAAO,CAI3B;AAED;;;GAGG;AACH,6BAHW,QAAQ,GACN,IAAI,IAAI,IAAI,CAIxB;AAED;;;GAGG;AACH,6BAHW,QAAQ,GACN,IAAI,IAAI,IAAI,CAIxB;AAtCD;;;GAGG;AACH,+BAHW,QAAQ,GACN,IAAI,IAAI,SAAS,CAI7B;AAED;;;GAGG;AACH,8BAHW,QAAQ,GACN,IAAI,IAAI,QAAQ,CAI5B;AAnHD;;;;GAIG;AACH,8CAJW,CAAC,IAAI,GAAG,cAAc,CAAC,CAAC,OAAO,CAAC,SAChC,SAAS,GACP,OAAO,CAMnB;AAsID;;;GAGG;AACH,oCAHW,MAAM,GACJ,MAAM,EAAE,CAIpB;AA/JD;;;;;GAKG;AACH,wCAJW,SAAS,UACT,SAAS,GACP,OAAO,CAInB;AA+KD;;;;GAIG;AACH,0CAHW,QAAQ,EAAE,GACR,CAAC,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAaxD;AAlLD;;;GAGG;AACH,kCAHW,YAAY,GAAG,cAAc,GAAG,IAAI,GAAG,cAAc,GACnD,OAAO,CAInB;AAxDD;;;;GAIG;AACH,8BAJW,GAAG,GAAG,SAAS,YACf,MAAM,GACJ,OAAO,CAMnB;AA6ND;;;GAGG;AACH,gCAHW,GAAG,GAAG,SAAS,GAAG,QAAQ,GACxB,MAAM,CAUlB;yBApQqI,oBAAoB;+BAApB,oBAAoB;8BAApB,oBAAoB;+BAApB,oBAAoB;6BAApB,oBAAoB;0BAApB,oBAAoB;oCAApB,oBAAoB;0BACzH,aAAa;yBACxB,QAAQ;8BADG,aAAa;6BADwF,oBAAoB;8BAApB,oBAAoB;kCAApB,oBAAoB;oCAApB,oBAAoB"}
|