@gaia-react/lint 1.2.0 → 1.3.1
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 +85 -66
- package/dist/configs/base.d.ts +1 -1
- package/dist/configs/base.d.ts.map +1 -1
- package/dist/configs/guardrails.d.ts +1 -1
- package/dist/configs/guardrails.d.ts.map +1 -1
- package/dist/configs/ignores.d.ts +10 -2
- package/dist/configs/ignores.d.ts.map +1 -1
- package/dist/configs/style-hygiene.d.ts +1 -1
- package/dist/configs/style-hygiene.d.ts.map +1 -1
- package/dist/index.d.ts +44 -31
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +442 -431
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -79,7 +79,7 @@ var typescriptConfig = [
|
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
];
|
|
82
|
-
var
|
|
82
|
+
var buildTsEslintConfig = (sourceDir) => [
|
|
83
83
|
{
|
|
84
84
|
files: ["**/*.ts?(x)"],
|
|
85
85
|
name: "typescript/config",
|
|
@@ -121,14 +121,22 @@ var tsEslintConfig = [
|
|
|
121
121
|
}
|
|
122
122
|
},
|
|
123
123
|
{
|
|
124
|
-
files: [
|
|
124
|
+
files: [
|
|
125
|
+
`${sourceDir}/hooks/**/*`,
|
|
126
|
+
`${sourceDir}/routes/**/*`,
|
|
127
|
+
`${sourceDir}/sessions.server/**/*`
|
|
128
|
+
],
|
|
125
129
|
name: "typescript/only-throw-error",
|
|
126
130
|
rules: {
|
|
127
131
|
"@typescript-eslint/only-throw-error": "off"
|
|
128
132
|
}
|
|
129
133
|
},
|
|
130
134
|
{
|
|
131
|
-
files: [
|
|
135
|
+
files: [
|
|
136
|
+
`${sourceDir}/utils/**`,
|
|
137
|
+
`${sourceDir}/services/**`,
|
|
138
|
+
`${sourceDir}/hooks/**`
|
|
139
|
+
],
|
|
132
140
|
name: "typescript/explicit-return-types",
|
|
133
141
|
rules: {
|
|
134
142
|
"@typescript-eslint/explicit-module-boundary-types": "error"
|
|
@@ -161,7 +169,7 @@ var tsEslintConfig = [
|
|
|
161
169
|
}
|
|
162
170
|
}
|
|
163
171
|
];
|
|
164
|
-
var
|
|
172
|
+
var buildImportXConfig = (sourceDir) => [
|
|
165
173
|
{
|
|
166
174
|
name: "import-x-all-files",
|
|
167
175
|
rules: {
|
|
@@ -200,14 +208,14 @@ var importXConfig = [
|
|
|
200
208
|
}
|
|
201
209
|
},
|
|
202
210
|
{
|
|
203
|
-
files: [
|
|
211
|
+
files: [`${sourceDir}/**/!(*.test|*.stories).ts?(x)`],
|
|
204
212
|
name: "import-x/app-test-files",
|
|
205
213
|
rules: {
|
|
206
214
|
"import-x/no-unresolved": "error"
|
|
207
215
|
}
|
|
208
216
|
},
|
|
209
217
|
{
|
|
210
|
-
files: [
|
|
218
|
+
files: [`${sourceDir}/**/hooks/*.ts?(x)`],
|
|
211
219
|
name: "import-x/hooks",
|
|
212
220
|
rules: {
|
|
213
221
|
"import-x/no-default-export": "error"
|
|
@@ -290,138 +298,438 @@ var lodashUnderscoreConfig = [
|
|
|
290
298
|
}
|
|
291
299
|
}
|
|
292
300
|
];
|
|
293
|
-
var
|
|
301
|
+
var buildBase = (sourceDir) => [
|
|
294
302
|
...jsConfig,
|
|
295
303
|
...jsCustomConfig,
|
|
296
304
|
...typescriptConfig,
|
|
297
|
-
...
|
|
298
|
-
...
|
|
305
|
+
...buildTsEslintConfig(sourceDir),
|
|
306
|
+
...buildImportXConfig(sourceDir),
|
|
299
307
|
...eslintCommentsConfig,
|
|
300
308
|
...preferArrowFunctionsConfig,
|
|
301
309
|
...lodashUnderscoreConfig
|
|
302
310
|
];
|
|
303
311
|
|
|
304
|
-
// src/configs/
|
|
305
|
-
import
|
|
306
|
-
var
|
|
307
|
-
// React plugin
|
|
308
|
-
plugins2.react,
|
|
309
|
-
// React hooks plugin
|
|
310
|
-
plugins2.reactHooks,
|
|
311
|
-
// React JSX A11y plugin
|
|
312
|
-
plugins2.reactA11y,
|
|
313
|
-
// Airbnb React recommended config
|
|
314
|
-
...configs2.react.recommended,
|
|
312
|
+
// src/configs/better-tailwind.ts
|
|
313
|
+
import betterTailwindPlugin from "eslint-plugin-better-tailwindcss";
|
|
314
|
+
var betterTailwind = (opts) => [
|
|
315
315
|
{
|
|
316
|
-
name: "
|
|
316
|
+
name: "better-tailwindcss",
|
|
317
|
+
plugins: {
|
|
318
|
+
"better-tailwindcss": betterTailwindPlugin
|
|
319
|
+
},
|
|
317
320
|
rules: {
|
|
318
|
-
"
|
|
319
|
-
"
|
|
320
|
-
"
|
|
321
|
+
"better-tailwindcss/enforce-canonical-classes": "error",
|
|
322
|
+
"better-tailwindcss/enforce-consistent-important-position": "error",
|
|
323
|
+
"better-tailwindcss/enforce-consistent-variable-syntax": "error",
|
|
324
|
+
"better-tailwindcss/enforce-shorthand-classes": "error",
|
|
325
|
+
"better-tailwindcss/no-conflicting-classes": "error",
|
|
326
|
+
"better-tailwindcss/no-deprecated-classes": "error",
|
|
327
|
+
"better-tailwindcss/no-unknown-classes": [
|
|
321
328
|
"error",
|
|
322
|
-
{
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
329
|
+
{ ignore: opts.ignore ?? [] }
|
|
330
|
+
]
|
|
331
|
+
},
|
|
332
|
+
settings: {
|
|
333
|
+
"better-tailwindcss": {
|
|
334
|
+
detectComponentClasses: true,
|
|
335
|
+
entryPoint: opts.entryPoint
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
];
|
|
340
|
+
|
|
341
|
+
// src/configs/guardrails.ts
|
|
342
|
+
import noRelativeImportPaths from "eslint-plugin-no-relative-import-paths";
|
|
343
|
+
import sonarjs from "eslint-plugin-sonarjs";
|
|
344
|
+
|
|
345
|
+
// src/plugins/no-enum.ts
|
|
346
|
+
var noEnumRule = {
|
|
347
|
+
create: (context) => ({
|
|
348
|
+
TSEnumDeclaration: (node) => {
|
|
349
|
+
context.report({ messageId: "noEnum", node });
|
|
342
350
|
}
|
|
351
|
+
}),
|
|
352
|
+
meta: {
|
|
353
|
+
docs: { description: "Disallow TypeScript enums" },
|
|
354
|
+
messages: {
|
|
355
|
+
noEnum: "Do not use TypeScript enums. Use an object with `as const` instead."
|
|
356
|
+
},
|
|
357
|
+
schema: [],
|
|
358
|
+
type: "problem"
|
|
359
|
+
}
|
|
360
|
+
};
|
|
361
|
+
var plugin = {
|
|
362
|
+
meta: {
|
|
363
|
+
name: "no-enum",
|
|
364
|
+
version: "0.1.0"
|
|
343
365
|
},
|
|
344
|
-
{
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
366
|
+
rules: {
|
|
367
|
+
"no-enum": noEnumRule
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
var no_enum_default = plugin;
|
|
371
|
+
|
|
372
|
+
// src/plugins/no-jsx-iife.ts
|
|
373
|
+
var noJsxIifeRule = {
|
|
374
|
+
create: (context) => ({
|
|
375
|
+
"JSXExpressionContainer > CallExpression > ArrowFunctionExpression.callee": (node) => {
|
|
376
|
+
context.report({ messageId: "noJsxIife", node });
|
|
377
|
+
},
|
|
378
|
+
"JSXExpressionContainer > CallExpression > FunctionExpression.callee": (node) => {
|
|
379
|
+
context.report({ messageId: "noJsxIife", node });
|
|
350
380
|
}
|
|
381
|
+
}),
|
|
382
|
+
meta: {
|
|
383
|
+
docs: { description: "Disallow IIFEs in JSX expressions" },
|
|
384
|
+
messages: {
|
|
385
|
+
noJsxIife: "Do not use IIFEs in JSX. Use a computed variable before the return or extract a component instead."
|
|
386
|
+
},
|
|
387
|
+
schema: [],
|
|
388
|
+
type: "problem"
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
var plugin2 = {
|
|
392
|
+
meta: {
|
|
393
|
+
name: "no-jsx-iife",
|
|
394
|
+
version: "0.1.0"
|
|
351
395
|
},
|
|
352
|
-
{
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
396
|
+
rules: {
|
|
397
|
+
"no-jsx-iife": noJsxIifeRule
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
var no_jsx_iife_default = plugin2;
|
|
401
|
+
|
|
402
|
+
// src/plugins/no-switch.ts
|
|
403
|
+
var noSwitchRule = {
|
|
404
|
+
create: (context) => ({
|
|
405
|
+
SwitchStatement: (node) => {
|
|
406
|
+
context.report({ messageId: "noSwitch", node });
|
|
357
407
|
}
|
|
408
|
+
}),
|
|
409
|
+
meta: {
|
|
410
|
+
docs: { description: "Disallow switch statements" },
|
|
411
|
+
messages: {
|
|
412
|
+
noSwitch: "Do not use switch statements. Use an object map or if/else instead."
|
|
413
|
+
},
|
|
414
|
+
schema: [],
|
|
415
|
+
type: "problem"
|
|
358
416
|
}
|
|
359
|
-
|
|
417
|
+
};
|
|
418
|
+
var plugin3 = {
|
|
419
|
+
meta: {
|
|
420
|
+
name: "no-switch",
|
|
421
|
+
version: "0.1.0"
|
|
422
|
+
},
|
|
423
|
+
rules: {
|
|
424
|
+
"no-switch": noSwitchRule
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
var no_switch_default = plugin3;
|
|
360
428
|
|
|
361
|
-
// src/configs/
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
import perfectionist from "eslint-plugin-perfectionist";
|
|
365
|
-
import unicorn from "eslint-plugin-unicorn";
|
|
366
|
-
import unusedImports from "eslint-plugin-unused-imports";
|
|
367
|
-
var canonicalConfig = [
|
|
368
|
-
canonical.configs["flat/recommended"],
|
|
429
|
+
// src/configs/guardrails.ts
|
|
430
|
+
var buildSonarConfig = (sourceDir) => [
|
|
431
|
+
sonarjs.configs.recommended,
|
|
369
432
|
{
|
|
370
|
-
name: "
|
|
433
|
+
name: "sonarjs",
|
|
371
434
|
rules: {
|
|
372
|
-
"
|
|
373
|
-
"
|
|
374
|
-
"
|
|
375
|
-
"
|
|
435
|
+
"sonarjs/cognitive-complexity": "error",
|
|
436
|
+
"sonarjs/fixme-tag": "off",
|
|
437
|
+
"sonarjs/no-commented-code": "off",
|
|
438
|
+
"sonarjs/no-nested-conditional": "off",
|
|
439
|
+
"sonarjs/no-nested-functions": "off",
|
|
440
|
+
"sonarjs/no-selector-parameter": "off",
|
|
441
|
+
"sonarjs/regex-complexity": "off",
|
|
442
|
+
"sonarjs/todo-tag": "off"
|
|
376
443
|
}
|
|
377
444
|
},
|
|
378
445
|
{
|
|
379
446
|
files: ["**/*.tsx", "**/hooks/*.ts?(x)"],
|
|
380
|
-
name: "
|
|
447
|
+
name: "sonarjs/react-files",
|
|
381
448
|
rules: {
|
|
382
|
-
"
|
|
449
|
+
"sonarjs/cognitive-complexity": "off",
|
|
450
|
+
"sonarjs/function-return-type": "off"
|
|
383
451
|
}
|
|
384
452
|
},
|
|
385
453
|
{
|
|
386
|
-
files: [
|
|
387
|
-
|
|
388
|
-
"app/entry.server.tsx",
|
|
389
|
-
"app/**/tests/*",
|
|
390
|
-
"test/**/*.ts?(x)",
|
|
391
|
-
"**/*.stories.tsx",
|
|
392
|
-
"**/routes/**/*.tsx",
|
|
393
|
-
"**/hooks/*.ts?(x)",
|
|
394
|
-
".storybook/**/*.ts?(x)",
|
|
395
|
-
".playwright/**/*.ts?(x)"
|
|
396
|
-
],
|
|
397
|
-
name: "canonical/filename-match-exported-disabled",
|
|
454
|
+
files: ["**/*.test.ts?(x)", "**/*.stories.ts?(x)"],
|
|
455
|
+
name: "sonarjs/test-files",
|
|
398
456
|
rules: {
|
|
399
|
-
"
|
|
457
|
+
"sonarjs/no-duplicate-string": "off",
|
|
458
|
+
"sonarjs/no-identical-functions": "off"
|
|
459
|
+
}
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
files: [`${sourceDir}/languages/**/*.ts`, "eslint.config.mjs"],
|
|
463
|
+
name: "sonarjs/credential-checks",
|
|
464
|
+
rules: {
|
|
465
|
+
"sonarjs/no-hardcoded-credentials": "off",
|
|
466
|
+
"sonarjs/no-hardcoded-passwords": "off"
|
|
400
467
|
}
|
|
401
468
|
}
|
|
402
469
|
];
|
|
403
|
-
var
|
|
404
|
-
perfectionist.configs["recommended-natural"],
|
|
470
|
+
var noEnumConfig = [
|
|
405
471
|
{
|
|
406
|
-
|
|
472
|
+
files: ["**/*.ts?(x)"],
|
|
473
|
+
name: "no-enum",
|
|
474
|
+
plugins: { "no-enum": no_enum_default },
|
|
407
475
|
rules: {
|
|
408
|
-
"
|
|
476
|
+
"no-enum/no-enum": "error"
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
];
|
|
480
|
+
var noJsxIifeConfig = [
|
|
481
|
+
{
|
|
482
|
+
files: ["**/*.tsx", "**/*.jsx"],
|
|
483
|
+
name: "no-jsx-iife",
|
|
484
|
+
plugins: { "no-jsx-iife": no_jsx_iife_default },
|
|
485
|
+
rules: { "no-jsx-iife/no-jsx-iife": "error" }
|
|
486
|
+
}
|
|
487
|
+
];
|
|
488
|
+
var noSwitchConfig = [
|
|
489
|
+
{
|
|
490
|
+
files: ["**/*.ts?(x)", "**/*.js?(x)"],
|
|
491
|
+
name: "no-switch",
|
|
492
|
+
plugins: { "no-switch": no_switch_default },
|
|
493
|
+
rules: { "no-switch/no-switch": "error" }
|
|
494
|
+
}
|
|
495
|
+
];
|
|
496
|
+
var buildNoRelativeImportPathsConfig = (sourceDir) => [
|
|
497
|
+
{
|
|
498
|
+
name: "no-relative-import-paths",
|
|
499
|
+
plugins: {
|
|
500
|
+
"no-relative-import-paths": noRelativeImportPaths
|
|
501
|
+
},
|
|
502
|
+
rules: {
|
|
503
|
+
"no-relative-import-paths/no-relative-import-paths": [
|
|
409
504
|
"error",
|
|
410
505
|
{
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
506
|
+
allowedDepth: 2,
|
|
507
|
+
allowSameFolder: true,
|
|
508
|
+
prefix: "~",
|
|
509
|
+
rootDir: sourceDir
|
|
510
|
+
}
|
|
511
|
+
]
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
];
|
|
515
|
+
var buildGuardrails = (sourceDir) => [
|
|
516
|
+
...buildSonarConfig(sourceDir),
|
|
517
|
+
...noEnumConfig,
|
|
518
|
+
...noJsxIifeConfig,
|
|
519
|
+
...noSwitchConfig,
|
|
520
|
+
...buildNoRelativeImportPathsConfig(sourceDir)
|
|
521
|
+
];
|
|
522
|
+
|
|
523
|
+
// src/configs/ignores.ts
|
|
524
|
+
import { includeIgnoreFile } from "@eslint/config-helpers";
|
|
525
|
+
import fs from "fs";
|
|
526
|
+
import path from "path";
|
|
527
|
+
var defaultIgnores = [
|
|
528
|
+
".storybook",
|
|
529
|
+
".playwright",
|
|
530
|
+
"/.react-router/**",
|
|
531
|
+
".claude/**/*.js",
|
|
532
|
+
".claude/**/*.cjs",
|
|
533
|
+
"scripts",
|
|
534
|
+
"public/**",
|
|
535
|
+
"**/*.css",
|
|
536
|
+
"**/*.svg",
|
|
537
|
+
"**/*.md"
|
|
538
|
+
];
|
|
539
|
+
var ignores = (opts) => {
|
|
540
|
+
const out = [];
|
|
541
|
+
const gitignore = opts?.gitignore ?? ".gitignore";
|
|
542
|
+
if (gitignore !== false) {
|
|
543
|
+
const resolved = path.isAbsolute(gitignore) ? gitignore : path.resolve(process.cwd(), gitignore);
|
|
544
|
+
if (fs.existsSync(resolved)) {
|
|
545
|
+
out.push(includeIgnoreFile(resolved));
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
out.push({
|
|
549
|
+
ignores: [...defaultIgnores, ...opts?.extra ?? []],
|
|
550
|
+
name: "ignored-files"
|
|
551
|
+
});
|
|
552
|
+
return out;
|
|
553
|
+
};
|
|
554
|
+
|
|
555
|
+
// src/configs/playwright.ts
|
|
556
|
+
import playwrightPlugin from "eslint-plugin-playwright";
|
|
557
|
+
var playwright = [
|
|
558
|
+
{
|
|
559
|
+
name: "playwright",
|
|
560
|
+
...playwrightPlugin.configs["flat/recommended"],
|
|
561
|
+
files: [".playwright/**/*.ts?(x)"],
|
|
562
|
+
rules: {
|
|
563
|
+
...playwrightPlugin.configs["flat/recommended"].rules,
|
|
564
|
+
"playwright/expect-expect": [
|
|
565
|
+
"warn",
|
|
566
|
+
{ assertFunctionPatterns: ["^expect[A-Z]"] }
|
|
567
|
+
]
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
];
|
|
571
|
+
|
|
572
|
+
// src/configs/prettier.ts
|
|
573
|
+
import { rules as prettierConfigRules } from "eslint-config-prettier";
|
|
574
|
+
import prettierPlugin from "eslint-plugin-prettier";
|
|
575
|
+
var prettier = [
|
|
576
|
+
{
|
|
577
|
+
name: "prettier/plugin/config",
|
|
578
|
+
plugins: { prettier: prettierPlugin }
|
|
579
|
+
},
|
|
580
|
+
{
|
|
581
|
+
name: "prettier/config",
|
|
582
|
+
rules: {
|
|
583
|
+
...prettierConfigRules,
|
|
584
|
+
"@stylistic/padding-line-between-statements": [
|
|
585
|
+
"error",
|
|
586
|
+
{
|
|
587
|
+
blankLine: "always",
|
|
588
|
+
next: ["block-like", "export", "return", "throw"],
|
|
589
|
+
prev: "*"
|
|
590
|
+
}
|
|
591
|
+
],
|
|
592
|
+
"@stylistic/quotes": [
|
|
593
|
+
"error",
|
|
594
|
+
"single",
|
|
595
|
+
{
|
|
596
|
+
allowTemplateLiterals: "avoidEscape",
|
|
597
|
+
avoidEscape: true
|
|
598
|
+
}
|
|
599
|
+
],
|
|
600
|
+
"@stylistic/spaced-comment": "off",
|
|
601
|
+
"prettier/prettier": ["error", { endOfLine: "auto" }]
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
];
|
|
605
|
+
|
|
606
|
+
// src/configs/react.ts
|
|
607
|
+
import { configs as configs2, plugins as plugins2 } from "eslint-config-airbnb-extended";
|
|
608
|
+
var react = [
|
|
609
|
+
// React plugin
|
|
610
|
+
plugins2.react,
|
|
611
|
+
// React hooks plugin
|
|
612
|
+
plugins2.reactHooks,
|
|
613
|
+
// React JSX A11y plugin
|
|
614
|
+
plugins2.reactA11y,
|
|
615
|
+
// Airbnb React recommended config
|
|
616
|
+
...configs2.react.recommended,
|
|
617
|
+
{
|
|
618
|
+
name: "react-custom",
|
|
619
|
+
rules: {
|
|
620
|
+
"jsx-a11y/control-has-associated-label": "off",
|
|
621
|
+
"jsx-a11y/no-autofocus": "off",
|
|
622
|
+
"react/boolean-prop-naming": [
|
|
623
|
+
"error",
|
|
624
|
+
{
|
|
625
|
+
propTypeNames: ["bool", "mutuallyExclusiveTrueProps"],
|
|
626
|
+
rule: "^((can|has|hide|is|show)[A-Z]([A-Za-z0-9]?)+|(checked|disabled|hide|required|show))"
|
|
627
|
+
}
|
|
628
|
+
],
|
|
629
|
+
"react/function-component-definition": "off",
|
|
630
|
+
"react/jsx-boolean-value": ["error", "always"],
|
|
631
|
+
"react/jsx-curly-brace-presence": "error",
|
|
632
|
+
"react/jsx-filename-extension": "off",
|
|
633
|
+
"react/jsx-fragments": "error",
|
|
634
|
+
// off by default because it doesn't handle props onXyz function names correctly
|
|
635
|
+
// turn this on from time to time to check for misnamed handlers elsewhere
|
|
636
|
+
"react/jsx-handler-names": ["off", { checkLocalVariables: true }],
|
|
637
|
+
"react/jsx-newline": ["error", { prevent: true }],
|
|
638
|
+
"react/jsx-no-useless-fragment": ["error", { allowExpressions: true }],
|
|
639
|
+
"react/no-children-prop": "off",
|
|
640
|
+
"react/no-danger": "off",
|
|
641
|
+
"react/prop-types": "off",
|
|
642
|
+
"react/react-in-jsx-scope": "off",
|
|
643
|
+
"react/require-default-props": "off"
|
|
644
|
+
}
|
|
645
|
+
},
|
|
646
|
+
{
|
|
647
|
+
files: ["**/routes/**/*.tsx"],
|
|
648
|
+
name: "react-router/routes",
|
|
649
|
+
rules: {
|
|
650
|
+
"no-empty-pattern": "off",
|
|
651
|
+
"react/display-name": "off"
|
|
652
|
+
}
|
|
653
|
+
},
|
|
654
|
+
{
|
|
655
|
+
files: ["**/*.test.ts?(x)", "**/*.stories.ts?(x)"],
|
|
656
|
+
name: "react/test-files",
|
|
657
|
+
rules: {
|
|
658
|
+
"react/jsx-props-no-spreading": "off"
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
];
|
|
662
|
+
|
|
663
|
+
// src/configs/storybook.ts
|
|
664
|
+
import storybookPlugin from "eslint-plugin-storybook";
|
|
665
|
+
var storybook = [
|
|
666
|
+
...storybookPlugin.configs["flat/recommended"]
|
|
667
|
+
];
|
|
668
|
+
|
|
669
|
+
// src/configs/style-hygiene.ts
|
|
670
|
+
import canonical from "eslint-plugin-canonical";
|
|
671
|
+
import checkFile from "eslint-plugin-check-file";
|
|
672
|
+
import perfectionist from "eslint-plugin-perfectionist";
|
|
673
|
+
import unicorn from "eslint-plugin-unicorn";
|
|
674
|
+
import unusedImports from "eslint-plugin-unused-imports";
|
|
675
|
+
var buildCanonicalConfig = (sourceDir) => [
|
|
676
|
+
canonical.configs["flat/recommended"],
|
|
677
|
+
{
|
|
678
|
+
name: "canonical",
|
|
679
|
+
rules: {
|
|
680
|
+
"canonical/destructuring-property-newline": "off",
|
|
681
|
+
"canonical/filename-match-exported": "error",
|
|
682
|
+
"canonical/id-match": "off",
|
|
683
|
+
"canonical/import-specifier-newline": "off"
|
|
684
|
+
}
|
|
685
|
+
},
|
|
686
|
+
{
|
|
687
|
+
files: ["**/*.tsx", "**/hooks/*.ts?(x)"],
|
|
688
|
+
name: "canonical/sort-react-dependencies",
|
|
689
|
+
rules: {
|
|
690
|
+
"canonical/sort-react-dependencies": "error"
|
|
691
|
+
}
|
|
692
|
+
},
|
|
693
|
+
{
|
|
694
|
+
files: [
|
|
695
|
+
`${sourceDir}/root.tsx`,
|
|
696
|
+
`${sourceDir}/entry.server.tsx`,
|
|
697
|
+
`${sourceDir}/**/tests/*`,
|
|
698
|
+
"test/**/*.ts?(x)",
|
|
699
|
+
"**/*.stories.tsx",
|
|
700
|
+
"**/routes/**/*.tsx",
|
|
701
|
+
"**/hooks/*.ts?(x)",
|
|
702
|
+
".storybook/**/*.ts?(x)",
|
|
703
|
+
".playwright/**/*.ts?(x)"
|
|
704
|
+
],
|
|
705
|
+
name: "canonical/filename-match-exported-disabled",
|
|
706
|
+
rules: {
|
|
707
|
+
"canonical/filename-match-exported": "off"
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
];
|
|
711
|
+
var perfectionistConfig = [
|
|
712
|
+
perfectionist.configs["recommended-natural"],
|
|
713
|
+
{
|
|
714
|
+
name: "perfectionist",
|
|
715
|
+
rules: {
|
|
716
|
+
"perfectionist/sort-imports": [
|
|
717
|
+
"error",
|
|
718
|
+
{
|
|
719
|
+
customGroups: [
|
|
720
|
+
{
|
|
721
|
+
elementNamePattern: "^react$",
|
|
722
|
+
groupName: "react-type",
|
|
723
|
+
selector: "type"
|
|
724
|
+
},
|
|
725
|
+
{
|
|
726
|
+
elementNamePattern: "^react$",
|
|
727
|
+
groupName: "react"
|
|
728
|
+
},
|
|
729
|
+
{
|
|
730
|
+
elementNamePattern: "^react-.+",
|
|
731
|
+
groupName: "react-other-type",
|
|
732
|
+
selector: "type"
|
|
425
733
|
},
|
|
426
734
|
{
|
|
427
735
|
elementNamePattern: "^react-.+",
|
|
@@ -551,14 +859,14 @@ var unusedImportsConfig = [
|
|
|
551
859
|
}
|
|
552
860
|
}
|
|
553
861
|
];
|
|
554
|
-
var
|
|
862
|
+
var buildCheckFileConfig = (sourceDir) => [
|
|
555
863
|
{
|
|
556
864
|
plugins: {
|
|
557
865
|
"check-file": checkFile
|
|
558
866
|
}
|
|
559
867
|
},
|
|
560
868
|
{
|
|
561
|
-
files: [
|
|
869
|
+
files: [`${sourceDir}/**/*`],
|
|
562
870
|
name: "check-file",
|
|
563
871
|
rules: {
|
|
564
872
|
"check-file/filename-naming-convention": [
|
|
@@ -566,13 +874,13 @@ var checkFileConfig = [
|
|
|
566
874
|
{
|
|
567
875
|
// React hook files must be camelCase (to match the hook name)
|
|
568
876
|
"**/hooks/*.{ts,tsx}": "CAMEL_CASE",
|
|
569
|
-
|
|
877
|
+
[`${sourceDir}/state/*.tsx`]: "KEBAB_CASE",
|
|
570
878
|
// React component files must be named index.tsx
|
|
571
|
-
|
|
879
|
+
[`${sourceDir}/{components,pages}/**/!(assets|hooks|state|tests|utils)/*.tsx`]: "index+()",
|
|
572
880
|
// Generally, non-component files must be named kebab-case
|
|
573
|
-
|
|
881
|
+
[`${sourceDir}/{components,pages}/**/!(hooks)/*.ts`]: "KEBAB_CASE",
|
|
574
882
|
// Non-component files inside specific components folders must be kebab-case
|
|
575
|
-
|
|
883
|
+
[`${sourceDir}/{components,pages}/**/(assets|state|tests|utils)/*.{ts,tsx}`]: "KEBAB_CASE",
|
|
576
884
|
"test/**/*.ts?(x)": "KEBAB_CASE"
|
|
577
885
|
},
|
|
578
886
|
{
|
|
@@ -583,14 +891,14 @@ var checkFileConfig = [
|
|
|
583
891
|
"error",
|
|
584
892
|
{
|
|
585
893
|
// require stories and test files to be inside tests folders
|
|
586
|
-
"*.(stories|test).{ts,tsx}":
|
|
894
|
+
"*.(stories|test).{ts,tsx}": `${sourceDir}/**/tests/`
|
|
587
895
|
}
|
|
588
896
|
],
|
|
589
897
|
"check-file/folder-naming-convention": [
|
|
590
898
|
"error",
|
|
591
899
|
{
|
|
592
900
|
// enforce PascalCase component folders, and allow assets, hooks, tests, and utils subfolders
|
|
593
|
-
|
|
901
|
+
[`${sourceDir}/components/**/`]: "(assets|hooks|state|tests|utils|[A-Z][a-zA-Z0-9]*)"
|
|
594
902
|
}
|
|
595
903
|
]
|
|
596
904
|
}
|
|
@@ -611,194 +919,12 @@ var checkFileConfig = [
|
|
|
611
919
|
}
|
|
612
920
|
}
|
|
613
921
|
];
|
|
614
|
-
var
|
|
615
|
-
...
|
|
922
|
+
var buildStyleHygiene = (sourceDir) => [
|
|
923
|
+
...buildCanonicalConfig(sourceDir),
|
|
616
924
|
...perfectionistConfig,
|
|
617
925
|
...unicornConfig,
|
|
618
926
|
...unusedImportsConfig,
|
|
619
|
-
...
|
|
620
|
-
];
|
|
621
|
-
|
|
622
|
-
// src/configs/guardrails.ts
|
|
623
|
-
import noRelativeImportPaths from "eslint-plugin-no-relative-import-paths";
|
|
624
|
-
import sonarjs from "eslint-plugin-sonarjs";
|
|
625
|
-
|
|
626
|
-
// src/plugins/no-enum.ts
|
|
627
|
-
var noEnumRule = {
|
|
628
|
-
create: (context) => ({
|
|
629
|
-
TSEnumDeclaration: (node) => {
|
|
630
|
-
context.report({ messageId: "noEnum", node });
|
|
631
|
-
}
|
|
632
|
-
}),
|
|
633
|
-
meta: {
|
|
634
|
-
docs: { description: "Disallow TypeScript enums" },
|
|
635
|
-
messages: {
|
|
636
|
-
noEnum: "Do not use TypeScript enums. Use an object with `as const` instead."
|
|
637
|
-
},
|
|
638
|
-
schema: [],
|
|
639
|
-
type: "problem"
|
|
640
|
-
}
|
|
641
|
-
};
|
|
642
|
-
var plugin = {
|
|
643
|
-
meta: {
|
|
644
|
-
name: "no-enum",
|
|
645
|
-
version: "0.1.0"
|
|
646
|
-
},
|
|
647
|
-
rules: {
|
|
648
|
-
"no-enum": noEnumRule
|
|
649
|
-
}
|
|
650
|
-
};
|
|
651
|
-
var no_enum_default = plugin;
|
|
652
|
-
|
|
653
|
-
// src/plugins/no-jsx-iife.ts
|
|
654
|
-
var noJsxIifeRule = {
|
|
655
|
-
create: (context) => ({
|
|
656
|
-
"JSXExpressionContainer > CallExpression > ArrowFunctionExpression.callee": (node) => {
|
|
657
|
-
context.report({ messageId: "noJsxIife", node });
|
|
658
|
-
},
|
|
659
|
-
"JSXExpressionContainer > CallExpression > FunctionExpression.callee": (node) => {
|
|
660
|
-
context.report({ messageId: "noJsxIife", node });
|
|
661
|
-
}
|
|
662
|
-
}),
|
|
663
|
-
meta: {
|
|
664
|
-
docs: { description: "Disallow IIFEs in JSX expressions" },
|
|
665
|
-
messages: {
|
|
666
|
-
noJsxIife: "Do not use IIFEs in JSX. Use a computed variable before the return or extract a component instead."
|
|
667
|
-
},
|
|
668
|
-
schema: [],
|
|
669
|
-
type: "problem"
|
|
670
|
-
}
|
|
671
|
-
};
|
|
672
|
-
var plugin2 = {
|
|
673
|
-
meta: {
|
|
674
|
-
name: "no-jsx-iife",
|
|
675
|
-
version: "0.1.0"
|
|
676
|
-
},
|
|
677
|
-
rules: {
|
|
678
|
-
"no-jsx-iife": noJsxIifeRule
|
|
679
|
-
}
|
|
680
|
-
};
|
|
681
|
-
var no_jsx_iife_default = plugin2;
|
|
682
|
-
|
|
683
|
-
// src/plugins/no-switch.ts
|
|
684
|
-
var noSwitchRule = {
|
|
685
|
-
create: (context) => ({
|
|
686
|
-
SwitchStatement: (node) => {
|
|
687
|
-
context.report({ messageId: "noSwitch", node });
|
|
688
|
-
}
|
|
689
|
-
}),
|
|
690
|
-
meta: {
|
|
691
|
-
docs: { description: "Disallow switch statements" },
|
|
692
|
-
messages: {
|
|
693
|
-
noSwitch: "Do not use switch statements. Use an object map or if/else instead."
|
|
694
|
-
},
|
|
695
|
-
schema: [],
|
|
696
|
-
type: "problem"
|
|
697
|
-
}
|
|
698
|
-
};
|
|
699
|
-
var plugin3 = {
|
|
700
|
-
meta: {
|
|
701
|
-
name: "no-switch",
|
|
702
|
-
version: "0.1.0"
|
|
703
|
-
},
|
|
704
|
-
rules: {
|
|
705
|
-
"no-switch": noSwitchRule
|
|
706
|
-
}
|
|
707
|
-
};
|
|
708
|
-
var no_switch_default = plugin3;
|
|
709
|
-
|
|
710
|
-
// src/configs/guardrails.ts
|
|
711
|
-
var sonarConfig = [
|
|
712
|
-
sonarjs.configs.recommended,
|
|
713
|
-
{
|
|
714
|
-
name: "sonarjs",
|
|
715
|
-
rules: {
|
|
716
|
-
"sonarjs/cognitive-complexity": "error",
|
|
717
|
-
"sonarjs/fixme-tag": "off",
|
|
718
|
-
"sonarjs/no-commented-code": "off",
|
|
719
|
-
"sonarjs/no-nested-conditional": "off",
|
|
720
|
-
"sonarjs/no-nested-functions": "off",
|
|
721
|
-
"sonarjs/no-selector-parameter": "off",
|
|
722
|
-
"sonarjs/regex-complexity": "off",
|
|
723
|
-
"sonarjs/todo-tag": "off"
|
|
724
|
-
}
|
|
725
|
-
},
|
|
726
|
-
{
|
|
727
|
-
files: ["**/*.tsx", "**/hooks/*.ts?(x)"],
|
|
728
|
-
name: "sonarjs/react-files",
|
|
729
|
-
rules: {
|
|
730
|
-
"sonarjs/cognitive-complexity": "off",
|
|
731
|
-
"sonarjs/function-return-type": "off"
|
|
732
|
-
}
|
|
733
|
-
},
|
|
734
|
-
{
|
|
735
|
-
files: ["**/*.test.ts?(x)", "**/*.stories.ts?(x)"],
|
|
736
|
-
name: "sonarjs/test-files",
|
|
737
|
-
rules: {
|
|
738
|
-
"sonarjs/no-duplicate-string": "off",
|
|
739
|
-
"sonarjs/no-identical-functions": "off"
|
|
740
|
-
}
|
|
741
|
-
},
|
|
742
|
-
{
|
|
743
|
-
files: ["app/languages/**/*.ts", "eslint.config.mjs"],
|
|
744
|
-
name: "sonarjs/credential-checks",
|
|
745
|
-
rules: {
|
|
746
|
-
"sonarjs/no-hardcoded-credentials": "off",
|
|
747
|
-
"sonarjs/no-hardcoded-passwords": "off"
|
|
748
|
-
}
|
|
749
|
-
}
|
|
750
|
-
];
|
|
751
|
-
var noEnumConfig = [
|
|
752
|
-
{
|
|
753
|
-
files: ["**/*.ts?(x)"],
|
|
754
|
-
name: "no-enum",
|
|
755
|
-
plugins: { "no-enum": no_enum_default },
|
|
756
|
-
rules: {
|
|
757
|
-
"no-enum/no-enum": "error"
|
|
758
|
-
}
|
|
759
|
-
}
|
|
760
|
-
];
|
|
761
|
-
var noJsxIifeConfig = [
|
|
762
|
-
{
|
|
763
|
-
files: ["**/*.tsx", "**/*.jsx"],
|
|
764
|
-
name: "no-jsx-iife",
|
|
765
|
-
plugins: { "no-jsx-iife": no_jsx_iife_default },
|
|
766
|
-
rules: { "no-jsx-iife/no-jsx-iife": "error" }
|
|
767
|
-
}
|
|
768
|
-
];
|
|
769
|
-
var noSwitchConfig = [
|
|
770
|
-
{
|
|
771
|
-
files: ["**/*.ts?(x)", "**/*.js?(x)"],
|
|
772
|
-
name: "no-switch",
|
|
773
|
-
plugins: { "no-switch": no_switch_default },
|
|
774
|
-
rules: { "no-switch/no-switch": "error" }
|
|
775
|
-
}
|
|
776
|
-
];
|
|
777
|
-
var noRelativeImportPathsConfig = [
|
|
778
|
-
{
|
|
779
|
-
name: "no-relative-import-paths",
|
|
780
|
-
plugins: {
|
|
781
|
-
"no-relative-import-paths": noRelativeImportPaths
|
|
782
|
-
},
|
|
783
|
-
rules: {
|
|
784
|
-
"no-relative-import-paths/no-relative-import-paths": [
|
|
785
|
-
"error",
|
|
786
|
-
{
|
|
787
|
-
allowedDepth: 2,
|
|
788
|
-
allowSameFolder: true,
|
|
789
|
-
prefix: "~",
|
|
790
|
-
rootDir: "app"
|
|
791
|
-
}
|
|
792
|
-
]
|
|
793
|
-
}
|
|
794
|
-
}
|
|
795
|
-
];
|
|
796
|
-
var guardrails = [
|
|
797
|
-
...sonarConfig,
|
|
798
|
-
...noEnumConfig,
|
|
799
|
-
...noJsxIifeConfig,
|
|
800
|
-
...noSwitchConfig,
|
|
801
|
-
...noRelativeImportPathsConfig
|
|
927
|
+
...buildCheckFileConfig(sourceDir)
|
|
802
928
|
];
|
|
803
929
|
|
|
804
930
|
// src/configs/testing.ts
|
|
@@ -837,145 +963,30 @@ var testing = [
|
|
|
837
963
|
}
|
|
838
964
|
];
|
|
839
965
|
|
|
840
|
-
// src/configs/storybook.ts
|
|
841
|
-
import storybookPlugin from "eslint-plugin-storybook";
|
|
842
|
-
var storybook = [
|
|
843
|
-
...storybookPlugin.configs["flat/recommended"]
|
|
844
|
-
];
|
|
845
|
-
|
|
846
|
-
// src/configs/playwright.ts
|
|
847
|
-
import playwrightPlugin from "eslint-plugin-playwright";
|
|
848
|
-
var playwright = [
|
|
849
|
-
{
|
|
850
|
-
name: "playwright",
|
|
851
|
-
...playwrightPlugin.configs["flat/recommended"],
|
|
852
|
-
files: [".playwright/**/*.ts?(x)"],
|
|
853
|
-
rules: {
|
|
854
|
-
...playwrightPlugin.configs["flat/recommended"].rules,
|
|
855
|
-
"playwright/expect-expect": [
|
|
856
|
-
"warn",
|
|
857
|
-
{ assertFunctionPatterns: ["^expect[A-Z]"] }
|
|
858
|
-
]
|
|
859
|
-
}
|
|
860
|
-
}
|
|
861
|
-
];
|
|
862
|
-
|
|
863
|
-
// src/configs/prettier.ts
|
|
864
|
-
import { rules as prettierConfigRules } from "eslint-config-prettier";
|
|
865
|
-
import prettierPlugin from "eslint-plugin-prettier";
|
|
866
|
-
var prettier = [
|
|
867
|
-
{
|
|
868
|
-
name: "prettier/plugin/config",
|
|
869
|
-
plugins: { prettier: prettierPlugin }
|
|
870
|
-
},
|
|
871
|
-
{
|
|
872
|
-
name: "prettier/config",
|
|
873
|
-
rules: {
|
|
874
|
-
...prettierConfigRules,
|
|
875
|
-
"@stylistic/padding-line-between-statements": [
|
|
876
|
-
"error",
|
|
877
|
-
{
|
|
878
|
-
blankLine: "always",
|
|
879
|
-
next: ["block-like", "export", "return", "throw"],
|
|
880
|
-
prev: "*"
|
|
881
|
-
}
|
|
882
|
-
],
|
|
883
|
-
"@stylistic/quotes": [
|
|
884
|
-
"error",
|
|
885
|
-
"single",
|
|
886
|
-
{
|
|
887
|
-
allowTemplateLiterals: "avoidEscape",
|
|
888
|
-
avoidEscape: true
|
|
889
|
-
}
|
|
890
|
-
],
|
|
891
|
-
"@stylistic/spaced-comment": "off",
|
|
892
|
-
"prettier/prettier": ["error", { endOfLine: "auto" }]
|
|
893
|
-
}
|
|
894
|
-
}
|
|
895
|
-
];
|
|
896
|
-
|
|
897
|
-
// src/configs/better-tailwind.ts
|
|
898
|
-
import betterTailwindPlugin from "eslint-plugin-better-tailwindcss";
|
|
899
|
-
var betterTailwind = (opts) => [
|
|
900
|
-
{
|
|
901
|
-
name: "better-tailwindcss",
|
|
902
|
-
plugins: {
|
|
903
|
-
"better-tailwindcss": betterTailwindPlugin
|
|
904
|
-
},
|
|
905
|
-
rules: {
|
|
906
|
-
"better-tailwindcss/enforce-canonical-classes": "error",
|
|
907
|
-
"better-tailwindcss/enforce-consistent-important-position": "error",
|
|
908
|
-
"better-tailwindcss/enforce-consistent-variable-syntax": "error",
|
|
909
|
-
"better-tailwindcss/enforce-shorthand-classes": "error",
|
|
910
|
-
"better-tailwindcss/no-conflicting-classes": "error",
|
|
911
|
-
"better-tailwindcss/no-deprecated-classes": "error",
|
|
912
|
-
"better-tailwindcss/no-unknown-classes": [
|
|
913
|
-
"error",
|
|
914
|
-
{ ignore: opts.ignore ?? [] }
|
|
915
|
-
]
|
|
916
|
-
},
|
|
917
|
-
settings: {
|
|
918
|
-
"better-tailwindcss": {
|
|
919
|
-
detectComponentClasses: true,
|
|
920
|
-
entryPoint: opts.entryPoint
|
|
921
|
-
}
|
|
922
|
-
}
|
|
923
|
-
}
|
|
924
|
-
];
|
|
925
|
-
|
|
926
|
-
// src/configs/ignores.ts
|
|
927
|
-
import { includeIgnoreFile } from "@eslint/compat";
|
|
928
|
-
import path from "path";
|
|
929
|
-
var defaultIgnores = [
|
|
930
|
-
".storybook",
|
|
931
|
-
".playwright",
|
|
932
|
-
"/.react-router/**",
|
|
933
|
-
".claude/**/*.js",
|
|
934
|
-
".claude/**/*.cjs",
|
|
935
|
-
"scripts",
|
|
936
|
-
"public/**",
|
|
937
|
-
"**/*.css",
|
|
938
|
-
"**/*.svg",
|
|
939
|
-
"**/*.md"
|
|
940
|
-
];
|
|
941
|
-
var ignores = (opts) => {
|
|
942
|
-
const out = [];
|
|
943
|
-
if (opts?.gitignore) {
|
|
944
|
-
const resolved = path.isAbsolute(opts.gitignore) ? opts.gitignore : path.resolve(process.cwd(), opts.gitignore);
|
|
945
|
-
out.push(includeIgnoreFile(resolved));
|
|
946
|
-
}
|
|
947
|
-
out.push({
|
|
948
|
-
ignores: [...defaultIgnores, ...opts?.extra ?? []],
|
|
949
|
-
name: "ignored-files"
|
|
950
|
-
});
|
|
951
|
-
return out;
|
|
952
|
-
};
|
|
953
|
-
|
|
954
966
|
// src/index.ts
|
|
955
|
-
var
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
967
|
+
var buildIgnoresAccessor = () => {
|
|
968
|
+
const defaults = ignores();
|
|
969
|
+
const accessor = ((opts) => ignores(opts));
|
|
970
|
+
accessor[Symbol.iterator] = () => defaults[Symbol.iterator]();
|
|
971
|
+
return accessor;
|
|
972
|
+
};
|
|
973
|
+
var gaiaLint = (opts) => {
|
|
974
|
+
const sourceDir = opts?.sourceDir ?? "app";
|
|
975
|
+
return {
|
|
976
|
+
base: buildBase(sourceDir),
|
|
977
|
+
betterTailwind,
|
|
978
|
+
guardrails: buildGuardrails(sourceDir),
|
|
979
|
+
ignores: buildIgnoresAccessor(),
|
|
980
|
+
playwright,
|
|
981
|
+
prettier,
|
|
982
|
+
react,
|
|
983
|
+
storybook,
|
|
984
|
+
styleHygiene: buildStyleHygiene(sourceDir),
|
|
985
|
+
testing
|
|
986
|
+
};
|
|
966
987
|
};
|
|
967
988
|
var index_default = gaiaLint;
|
|
968
989
|
export {
|
|
969
|
-
|
|
970
|
-
betterTailwind,
|
|
971
|
-
index_default as default,
|
|
972
|
-
guardrails,
|
|
973
|
-
ignores,
|
|
974
|
-
playwright,
|
|
975
|
-
prettier,
|
|
976
|
-
react,
|
|
977
|
-
storybook,
|
|
978
|
-
styleHygiene,
|
|
979
|
-
testing
|
|
990
|
+
index_default as default
|
|
980
991
|
};
|
|
981
992
|
//# sourceMappingURL=index.js.map
|