@tony.ganchev/eslint-plugin-header 3.4.1 → 3.4.3

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
@@ -7,8 +7,8 @@
7
7
  The native ESLint 9/10 standard header-validating plugin. A zero-bloat, drop-in
8
8
  replacement for [eslint-plugin-header](https://github.com/Stuk/eslint-plugin-header)
9
9
  with first-class Flat Config & TypeScript support. Auto-fix copyright, license,
10
- and banner comments in JavaScript, TypeScript, Vue, CSS, HTML, and Markdown files.
11
- Supports _oxlint_.
10
+ and banner comments in JavaScript, TypeScript, Vue, Svelte, CSS, HTML, YAML, and
11
+ Markdown files. Supports _oxlint_.
12
12
 
13
13
  ## Table of Contents
14
14
 
@@ -31,7 +31,9 @@ Supports _oxlint_.
31
31
  5. [Linting CSS](#linting-css)
32
32
  6. [Linting HTML](#linting-html)
33
33
  7. [Linting Vue](#linting-vue)
34
- 8. [Linting Markdown](#linting-markdown)
34
+ 8. [Linting Svelte](#linting-svelte)
35
+ 9. [Linting Markdown](#linting-markdown)
36
+ 10. [Linting YAML](#linting-yaml)
35
37
  5. [Comparison to Alternatives](#comparison-to-alternatives)
36
38
  1. [Compared to eslint-plugin-headers](#compared-to-eslint-plugin-headers)
37
39
  1. [Health Scans](#health-scans)
@@ -133,9 +135,10 @@ statements. Smoke tests cover this support as well.
133
135
  ### Languages
134
136
 
135
137
  Currently the plugin supports linting copyright headers in JavaScript,
136
- TypeScript and their JSX / TSX flavors; Vue, CSS, HTML, and Markdown files. As
137
- mentioned in the previous sections, not all languages are supported for oxlint
138
- or ESLint older than 9. Refer to the table below for more details.
138
+ TypeScript and their JSX / TSX flavors; Vue, Svelte, CSS, HTML, YAML, and
139
+ Markdown files. As mentioned in the previous sections, not all languages are
140
+ supported for oxlint or ESLint older than 9. Refer to the table below for more
141
+ details.
139
142
 
140
143
  | Language | ESLint 7 / 8 | ESLint 9 / 10 | oxlint |
141
144
  |------------|---------------|---------------|--------|
@@ -144,8 +147,10 @@ or ESLint older than 9. Refer to the table below for more details.
144
147
  | JSX | ✅ Yes | ✅ Yes | ✅ Yes |
145
148
  | TSX | ✅ Yes | ✅ Yes | ✅ Yes |
146
149
  | Vue | ✅ Yes | ✅ Yes | ❌ No |
150
+ | Svelte | ✅ Yes | ✅ Yes | ❌ No |
147
151
  | CSS | ❌ No | ✅ Yes | ❌ No |
148
152
  | HTML | ❌ No | ✅ Yes | ❌ No |
153
+ | YAML | ❌ No | ✅ Yes | ❌ No |
149
154
  | Markdown | ❌ No | ✅ Yes | ❌ No |
150
155
 
151
156
  ## Usage
@@ -1379,6 +1384,55 @@ export default [
1379
1384
  As with HTML and CSS, only block comments are supported at the top of the file -
1380
1385
  no line- or shebang comments.
1381
1386
 
1387
+ ### Linting Svelte
1388
+
1389
+ The rule supports linting copyright notices in Svelte files. The rule works with
1390
+ the _eslint-plugin-svelte_ plugin and its parser.
1391
+
1392
+ To turn on header validation for Svelte files, configure the parser and the rule:
1393
+
1394
+ ```ts
1395
+ import header from "@tony.ganchev/eslint-plugin-header";
1396
+ import svelteParser from "svelte-eslint-parser";
1397
+ import sveltePlugin from "eslint-plugin-svelte";
1398
+
1399
+ export default [
1400
+ {
1401
+ files: ["**/*.svelte"],
1402
+ plugins: {
1403
+ "@tony.ganchev": header,
1404
+ svelte: sveltePlugin
1405
+ },
1406
+ languageOptions: {
1407
+ parser: svelteParser
1408
+ },
1409
+ rules: {
1410
+ "@tony.ganchev/header": [
1411
+ "error",
1412
+ {
1413
+ header: {
1414
+ commentType: "block",
1415
+ lines: [" Copyright 2025 "]
1416
+ }
1417
+ }
1418
+ ]
1419
+ }
1420
+ }
1421
+ ];
1422
+ ```
1423
+
1424
+ ```svelte
1425
+ <!-- Copyright 2025 -->
1426
+ <script>
1427
+ let name = 'world';
1428
+ </script>
1429
+
1430
+ <h1>Hello {name}!</h1>
1431
+ ```
1432
+
1433
+ As with Vue, HTML and CSS, only block comments are supported at the top of the
1434
+ file - no line- or shebang comments.
1435
+
1382
1436
  ### Linting Markdown
1383
1437
 
1384
1438
  The rule supports copyright comments in Markdown syntax in both _commonmark_ and
@@ -1437,6 +1491,50 @@ Markdown (`**/*.md/*.js`). Same applies to `*.ts`, `*.jsx`, `*.tsx`, etc.
1437
1491
 
1438
1492
  As with CSS, only block comments are supported - no line- or shebang comments.
1439
1493
 
1494
+ ### Linting YAML
1495
+
1496
+ The rule supports linting copyright notices in YAML files. The rule works with
1497
+ the _eslint-plugin-yml_ plugin and its parser.
1498
+
1499
+ Similar to CSS and Markdown, all you need to do to turn on header validation is
1500
+ to configure the _eslint-plugin-yml_ plugin, the correct language, and the rule:
1501
+
1502
+ ```ts
1503
+ import header from "@tony.ganchev/eslint-plugin-header";
1504
+ import yml from "eslint-plugin-yml";
1505
+
1506
+ export default [
1507
+ {
1508
+ files: ["**/*.yaml", "**/*.yml"],
1509
+ plugins: {
1510
+ "@tony.ganchev": header,
1511
+ yml
1512
+ },
1513
+ language: "yml/yaml",
1514
+ rules: {
1515
+ "@tony.ganchev/header": [
1516
+ "error",
1517
+ {
1518
+ header: {
1519
+ commentType: "line",
1520
+ lines: [" Copyright 2025 "]
1521
+ }
1522
+ }
1523
+ ]
1524
+ }
1525
+ }
1526
+ ];
1527
+ ```
1528
+
1529
+ ```yaml
1530
+ # Copyright 2025
1531
+
1532
+ foo: bar
1533
+ ```
1534
+
1535
+ As YAML only supports line comments, be sure to use `commentType: "line"`. If
1536
+ `commentType: "block"` is used, the rule will report a violation.
1537
+
1440
1538
  ## Comparison to Alternatives
1441
1539
 
1442
1540
  A number of projects have been aiming to solve problems similar to
@@ -37,10 +37,8 @@ const assert = require("node:assert");
37
37
  * This is a really simple and dumb parser, that looks just for a
38
38
  * single kind of comment. It won't detect multiple block comments.
39
39
  * @param {string} commentText Content to parse.
40
- * @param {Language} language The language
41
- * configuration.
42
- * @returns {[CommentType, string[]]} Comment type and
43
- * content.
40
+ * @param {Language} language The language configuration.
41
+ * @returns {[CommentType, string[]]} Comment type and content.
44
42
  * @throws {Error} If `commentText` starts with an unrecognized comment token.
45
43
  */
46
44
  module.exports = function commentParser(commentText, language) {
@@ -206,7 +206,7 @@ function match(actual, expected) {
206
206
 
207
207
  /**
208
208
  * @typedef {object} Language
209
- * @property { BlockComment } blockComment The tokens delimiting a block
209
+ * @property { BlockComment } [blockComment] The tokens delimiting a block
210
210
  * comment.
211
211
  * @property { LineComment } [lineComment] The tokens delimiting a line comment
212
212
  * if such is allowed.
@@ -348,7 +348,8 @@ function getLeadingComments(sourceCode, language) {
348
348
  */
349
349
  function genCommentBody(commentType, textArray, eol, language) {
350
350
  if (commentType === commentTypeOptions.block) {
351
- return language.blockComment.startDelimiter + textArray.join(eol) + language.blockComment.endDelimiter;
351
+ const blockComment = /** @type {BlockComment} */ (language.blockComment);
352
+ return blockComment.startDelimiter + textArray.join(eol) + blockComment.endDelimiter;
352
353
  } else {
353
354
  const lineStartDelimiter = /** @type {LineComment} */ (language.lineComment).startDelimiter;
354
355
  // We need one trailing EOL on line comments to ensure the fixed source
@@ -413,8 +414,15 @@ function genPrependFixer(commentType, sourceCode, headerLines, eol, numNewlines,
413
414
  newHeader = eol + newHeader;
414
415
  }
415
416
  }
416
- const numEmptyLines = leadingEmptyLines(sourceCode.text.substring(insertPos));
417
- const additionalEmptyLines = Math.max(0, numNewlines - numEmptyLines);
417
+ const existingSourceCodeFromInsertPos = sourceCode.text.substring(insertPos);
418
+ const numEmptyLines = leadingEmptyLines(existingSourceCodeFromInsertPos);
419
+ const additionalEmptyLines = Math.max(numNewlines - numEmptyLines,
420
+ (commentType === commentTypeOptions.line
421
+ && existingSourceCodeFromInsertPos.startsWith(
422
+ /** @type {{ startDelimiter: string }} */(language.lineComment).startDelimiter))
423
+ ? 1
424
+ : 0
425
+ );
418
426
  newHeader += eol.repeat(additionalEmptyLines);
419
427
  return fixer.insertTextBeforeRange(
420
428
  [insertPos, insertPos /* don't care */],
@@ -833,7 +841,7 @@ class CommentMatcher {
833
841
  }
834
842
  }
835
843
 
836
- const commentRange = leadingComments[this.headerLines.length - 1].range;
844
+ const commentRange = leadingComments[leadingComments.length - 1].range;
837
845
  const actualLeadingEmptyLines = leadingEmptyLines(sourceCode.text.substring(commentRange[1]));
838
846
  const missingEmptyLines = this.numLines - actualLeadingEmptyLines;
839
847
  if (missingEmptyLines > 0) {
@@ -849,6 +857,7 @@ class CommentMatcher {
849
857
 
850
858
  return null;
851
859
  }
860
+
852
861
  // if block comment pattern has more than 1 line, we also split the
853
862
  // comment
854
863
  let leadingLines = [leadingComments[0].value];
@@ -862,8 +871,9 @@ class CommentMatcher {
862
871
  let errorMessageData;
863
872
  /** @type {null | SourceLocation} */
864
873
  let errorMessageLoc = null;
865
- const blockStartLen = this.language.blockComment.startDelimiter.length;
866
- const blockEndLen = this.language.blockComment.endDelimiter.length;
874
+ const blockComment = /** @type {BlockComment} */(this.language.blockComment);
875
+ const blockStartLen = blockComment.startDelimiter.length;
876
+ const blockEndLen = blockComment.endDelimiter.length;
867
877
 
868
878
  for (let i = 0; i < this.headerLines.length; i++) {
869
879
  if (leadingLines.length - 1 < i) {
@@ -1017,7 +1027,8 @@ const headerRule = {
1017
1027
  // messages only applicable to header validation.
1018
1028
  missingHeader: "missing header",
1019
1029
  noNewlineAfterHeader: "not enough newlines after header: expected: {{expected}}, actual: {{actual}}",
1020
- unsupportedLineHeader: "line header configured but not supported for this language"
1030
+ unsupportedBlockHeader: "block-comment header configured but not supported for this language",
1031
+ unsupportedLineHeader: "line-comment header configured but not supported for this language"
1021
1032
  }
1022
1033
  },
1023
1034
 
@@ -1030,6 +1041,7 @@ const headerRule = {
1030
1041
 
1031
1042
  const newStyleOptions = transformLegacyOptions(/** @type {AllHeaderOptions} */(context.options));
1032
1043
  const sourceCode = contextSourceCode(context);
1044
+ // console.log(sourceCode);
1033
1045
 
1034
1046
  /**
1035
1047
  * Hooks into the processing of the overall script node to do the
@@ -1051,7 +1063,7 @@ const headerRule = {
1051
1063
  });
1052
1064
  const numLines = /** @type {number} */ (options.trailingEmptyLines?.minimum);
1053
1065
 
1054
- if (!language.lineComment && (/** @type {InlineConfig} */ (options.header)).commentType === "line") {
1066
+ if (!language.lineComment && header.commentType === "line") {
1055
1067
  context.report({
1056
1068
  messageId: "unsupportedLineHeader",
1057
1069
  loc: {
@@ -1062,6 +1074,17 @@ const headerRule = {
1062
1074
  return;
1063
1075
  }
1064
1076
 
1077
+ if (!language.blockComment && header.commentType === "block") {
1078
+ context.report({
1079
+ messageId: "unsupportedBlockHeader",
1080
+ loc: {
1081
+ start: sourceCode.getLocFromIndex(0),
1082
+ end: sourceCode.getLocFromIndex(1),
1083
+ },
1084
+ });
1085
+ return;
1086
+ }
1087
+
1065
1088
  const headerMatcher = new CommentMatcher(header, eol, numLines, language);
1066
1089
  const allowedLeadingComments = /** @type {LeadingComments} */ (options.leadingComments).comments;
1067
1090
  const allowedCommentsMatchers =
@@ -1205,16 +1228,74 @@ const headerRule = {
1205
1228
  }
1206
1229
  };
1207
1230
 
1231
+ /** @type {Language} */
1232
+ const yamlStyleLanguage = {
1233
+ lineComment: {
1234
+ startDelimiter: "#"
1235
+ }
1236
+ };
1237
+
1238
+ /**
1239
+ * Tests if the source code was parsed by _@html-eslint/eslint-plugin_'s
1240
+ * parser.
1241
+ * @returns {boolean} `true` if the source code is parsed by the parser.
1242
+ */
1243
+ function isHtmlParser() {
1244
+ return sourceCode.constructor.name === "HTMLSourceCode";
1245
+ }
1246
+
1247
+ /**
1248
+ * Tests if the source code was parsed by _vue-eslint-parser_.
1249
+ * @returns {boolean} `true` if the source code is parsed by the parser.
1250
+ */
1251
+ function isVueParser() {
1252
+ // Vue parser mimic JS parser identity but has a
1253
+ // template section under its AST.
1254
+ return "templateBody" in sourceCode.ast;
1255
+ }
1256
+
1257
+ /**
1258
+ * Tests if the source code was parsed by _svelte-eslint-parser_.
1259
+ * @returns {boolean} `true` if the source code is parsed by the parser.
1260
+ */
1261
+ function isSvelteParser() {
1262
+ // Svelte parser mimic JS parser identity but has an
1263
+ // identifier in its `parserServices` section.
1264
+ return sourceCode.parserServices.isSvelte;
1265
+ }
1266
+
1267
+ /**
1268
+ * Tests if the source code is parsed by a HTML-style language parser.
1269
+ * @returns {boolean} `true` if the source code is parsed by a
1270
+ * HTML-style language parser.
1271
+ */
1272
+ function isHtmlStyleLanguage() {
1273
+ return isHtmlParser() || isVueParser() || isSvelteParser();
1274
+ };
1275
+
1276
+ /**
1277
+ * Tests if the source code was parsed by _yaml-eslint-parser_.
1278
+ * @returns {boolean} `true` if the source code is parsed by the parser.
1279
+ */
1280
+ function isYamlStyleLanguage() {
1281
+ // YAML parser has distinct identity from JS parset but also has an
1282
+ // identifier in its `parserServices` section and that check is
1283
+ // faster.
1284
+ return sourceCode.parserServices.isYAML;
1285
+ }
1286
+
1287
+ const programLanguageSearchMap = [
1288
+ { test: isHtmlStyleLanguage, language: htmlStyleLanguage },
1289
+ { test: isYamlStyleLanguage, language: yamlStyleLanguage },
1290
+ { test: () => true, language: jsStyleLanguage }
1291
+ ];
1292
+
1208
1293
  const hooks = {
1209
- Program: () =>
1210
- onRootNode(
1211
- (sourceCode.constructor.name === "HTMLSourceCode"
1212
- // Vue parser mimics JS parser identity but has a
1213
- // template section.
1214
- || "templateBody" in sourceCode.ast)
1215
- ? htmlStyleLanguage
1216
- : jsStyleLanguage
1217
- ),
1294
+ Program: () => onRootNode(
1295
+ /** @type {{ test: () => boolean, language: Language}} */(
1296
+ programLanguageSearchMap.find((item) => item.test())
1297
+ ).language
1298
+ ),
1218
1299
  StyleSheet: () => onRootNode(cssStyleLanguage),
1219
1300
  // eslint/markdown
1220
1301
  root: () => onRootNode(htmlStyleLanguage),
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tony.ganchev/eslint-plugin-header",
3
- "version": "3.4.1",
4
- "description": "The native ESLint 9/10 header plugin. A zero-bloat, drop-in replacement for 'eslint-plugin-header' with first-class Flat Config & TypeScript support. Auto-fix Copyright, License, and banner comments in JavaScript, TypeScript, Vue, CSS, HTML, and Markdown files. Supports oxlint.",
3
+ "version": "3.4.3",
4
+ "description": "The native ESLint 9/10 header plugin. A zero-bloat, drop-in replacement for 'eslint-plugin-header' with first-class Flat Config & TypeScript support. Auto-fix Copyright, License, and banner comments in JavaScript, TypeScript, Vue, Svelte, CSS, HTML, YAML, and Markdown files. Supports oxlint.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
7
7
  "exports": {
@@ -21,23 +21,26 @@
21
21
  "@eslint/core": "^1.2.0",
22
22
  "@eslint/css": "^1.1.0",
23
23
  "@eslint/js": "^10.0.1",
24
- "@eslint/markdown": "^7.5.1",
24
+ "@eslint/markdown": "^8.0.1",
25
25
  "@html-eslint/eslint-plugin": "^0.58.1",
26
26
  "@stylistic/eslint-plugin": "^5.10.0",
27
27
  "@types/estree": "^1.0.8",
28
28
  "@types/json-schema": "^7.0.15",
29
29
  "@types/node": "^25.5.2",
30
30
  "c8": "^11.0.0",
31
- "eslint": "^10.1.0",
31
+ "eslint": "^10.2.0",
32
32
  "eslint-plugin-eslint-plugin": "^7.3.2",
33
33
  "eslint-plugin-jsdoc": "^62.9.0",
34
34
  "eslint-plugin-n": "^17.24.0",
35
+ "eslint-plugin-svelte": "^3.17.0",
35
36
  "eslint-plugin-vue": "^10.8.0",
37
+ "eslint-plugin-yml": "^3.3.1",
36
38
  "globals": "^17.4.0",
37
39
  "markdownlint-cli": "^0.48.0",
38
40
  "mocha": "12.0.0-beta-10",
41
+ "svelte-eslint-parser": "^1.6.0",
39
42
  "testdouble": "^3.20.2",
40
- "typescript": "^5.9.3",
43
+ "typescript": "^6.0.2",
41
44
  "typescript-eslint": "^8.58.0",
42
45
  "vue-eslint-parser": "^10.4.0"
43
46
  },
@@ -76,10 +79,15 @@
76
79
  "oxc",
77
80
  "react",
78
81
  "source-header",
82
+ "svelte",
83
+ "sveltejs",
84
+ "svelte-js",
79
85
  "typescript",
80
86
  "vue",
81
87
  "vuejs",
82
- "vue-js"
88
+ "vue-js",
89
+ "yaml",
90
+ "yml"
83
91
  ],
84
92
  "repository": {
85
93
  "type": "git",
@@ -1 +1 @@
1
- {"version":3,"file":"comment-parser.d.ts","sourceRoot":"","sources":["../../lib/comment-parser.js"],"names":[],"mappings":"AA6CiB,uCAPN,MAAM,YACN,QAAQ,GAEN,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC,CA4BnC;;8BAxCyC,gBAAgB;iCAAhB,gBAAgB"}
1
+ {"version":3,"file":"comment-parser.d.ts","sourceRoot":"","sources":["../../lib/comment-parser.js"],"names":[],"mappings":"AA2CiB,uCALN,MAAM,YACN,QAAQ,GACN,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC,CA2BnC;;8BAtCyC,gBAAgB;iCAAhB,gBAAgB"}
@@ -188,7 +188,7 @@ export type Language = {
188
188
  * The tokens delimiting a block
189
189
  * comment.
190
190
  */
191
- blockComment: BlockComment;
191
+ blockComment?: BlockComment | undefined;
192
192
  /**
193
193
  * The tokens delimiting a line comment
194
194
  * if such is allowed.
@@ -1 +1 @@
1
- {"version":3,"file":"header.d.ts","sourceRoot":"","sources":["../../../lib/rules/header.js"],"names":[],"mappings":"2BAsCa,iBAAiB;0BACjB,gBAAgB;wBAChB,cAAc;0BACd,gBAAgB;;;;;yBAIhB,IAAI,GAAG,MAAM;;;;;;;;;;aAOZ,MAAM,GAAG,MAAM;;;;;;;;;;;;yBAOhB,MAAM,GAAG,MAAM,GAAG,iBAAiB;;;;;0BAGnC,UAAU,GAAG,UAAU,EAAE;;;;;;+BAEzB,IAAI,GAAG,MAAM,GAAG,SAAS;;;;;6BAGzB;IAAE,WAAW,CAAC,EAAE,gBAAgB,CAAA;CAAE;;;;;0BAElC,OAAO,GAAG,MAAM;;;;;;;;;;UAOf,MAAM;;;;;;;;;;;;;;;iBASN,WAAW;;;;;;WACX,UAAU,EAAE;;;;;;;;;;;;cAQZ,CAAC,eAAe,GAAG,YAAY,CAAC,EAAE;;;;;;;;;;;;;;;;;;YAclC,eAAe,GAAG,YAAY;;;;;;;;;;;;;;;;;4BAU/B,4BAA4B,GAAG,cAAc;oCAK7C,CAAC,QAAQ,EAAE,MAAM,CAAC;4CAClB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,CAAC;iCAE5C,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,CAAC;yCACvC,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,CAAC;yCAEjE,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC;iDAEzD,CACV,IAAI,EAAE,WAAW,EACjB,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,cAAc,CACvB;;;;+BACS,CAAC,aAAa,CAAC,GACvB,qBAAqB,GACrB,6BAA6B,GAC7B,kBAAkB,GAClB,0BAA0B,GAC1B,0BAA0B,GAC1B,kCAAkC;;;;;+BAK1B,iBAAiB,gBAAgB,CAAC;oBAiClC,CAAC,MAAM,EAAE,MAAM,CAAC;;;;;UAKf,SAAS,GAAG,OAAO,GAAG,MAAM;;;;WAC5B,MAAM;;;;WACN,KAAK;;;;SACL,cAAc;;;;;;;oBAKd,MAAM;;;;;kBAEN,MAAM;;;;;;;oBAMN,MAAM;;;;;;;kBAML,YAAY;;;;;;;;;;;;AAmwB3B,8BAA8B;AAC9B,0BADW,eAAe,CAoPxB;AAloBF,2EAA2E;AAC3E,+BADW,MAAM,CAAC,MAAM,EAAE;IAAE,WAAW,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAC,CAAC,CAC3C;0BAniBkC,QAAQ;4BAAR,QAAQ;oCAC1B,QAAQ"}
1
+ {"version":3,"file":"header.d.ts","sourceRoot":"","sources":["../../../lib/rules/header.js"],"names":[],"mappings":"2BAsCa,iBAAiB;0BACjB,gBAAgB;wBAChB,cAAc;0BACd,gBAAgB;;;;;yBAIhB,IAAI,GAAG,MAAM;;;;;;;;;;aAOZ,MAAM,GAAG,MAAM;;;;;;;;;;;;yBAOhB,MAAM,GAAG,MAAM,GAAG,iBAAiB;;;;;0BAGnC,UAAU,GAAG,UAAU,EAAE;;;;;;+BAEzB,IAAI,GAAG,MAAM,GAAG,SAAS;;;;;6BAGzB;IAAE,WAAW,CAAC,EAAE,gBAAgB,CAAA;CAAE;;;;;0BAElC,OAAO,GAAG,MAAM;;;;;;;;;;UAOf,MAAM;;;;;;;;;;;;;;;iBASN,WAAW;;;;;;WACX,UAAU,EAAE;;;;;;;;;;;;cAQZ,CAAC,eAAe,GAAG,YAAY,CAAC,EAAE;;;;;;;;;;;;;;;;;;YAclC,eAAe,GAAG,YAAY;;;;;;;;;;;;;;;;;4BAU/B,4BAA4B,GAAG,cAAc;oCAK7C,CAAC,QAAQ,EAAE,MAAM,CAAC;4CAClB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,CAAC;iCAE5C,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,CAAC;yCACvC,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,CAAC;yCAEjE,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC;iDAEzD,CACV,IAAI,EAAE,WAAW,EACjB,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,cAAc,CACvB;;;;+BACS,CAAC,aAAa,CAAC,GACvB,qBAAqB,GACrB,6BAA6B,GAC7B,kBAAkB,GAClB,0BAA0B,GAC1B,0BAA0B,GAC1B,kCAAkC;;;;;+BAK1B,iBAAiB,gBAAgB,CAAC;oBAiClC,CAAC,MAAM,EAAE,MAAM,CAAC;;;;;UAKf,SAAS,GAAG,OAAO,GAAG,MAAM;;;;WAC5B,MAAM;;;;WACN,KAAK;;;;SACL,cAAc;;;;;;;oBAKd,MAAM;;;;;kBAEN,MAAM;;;;;;;oBAMN,MAAM;;;;;;;;;;;;;;;;;;;AAmxBpB,8BAA8B;AAC9B,0BADW,eAAe,CA2TxB;AA3sBF,2EAA2E;AAC3E,+BADW,MAAM,CAAC,MAAM,EAAE;IAAE,WAAW,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAC,CAAC,CAC3C;0BA3iBkC,QAAQ;4BAAR,QAAQ;oCAC1B,QAAQ"}