pasika 0.5.16 → 0.5.18
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 +9 -9
- package/dist/eslint/pasika/index.d.ts +8 -5
- package/dist/eslint/pasika/index.js +146 -87
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,10 +9,10 @@ Documentation, the lint rules derived from it, and the checks that apply and dia
|
|
|
9
9
|
```text
|
|
10
10
|
docs/
|
|
11
11
|
repository-policy.md # repo-wide code and documentation requirements (Policy)
|
|
12
|
-
|
|
12
|
+
next-codebase-guide/ # placement, extraction, module conventions
|
|
13
13
|
documentation-guide/ # how documents themselves are written
|
|
14
14
|
pasika-adoption-guide/ # adopting and updating the framework
|
|
15
|
-
|
|
15
|
+
next-tailwind-guide/ # Tailwind theme, composition, variants, states
|
|
16
16
|
scripts/
|
|
17
17
|
registry.json # requirement → enforcement, keyed by content hash
|
|
18
18
|
coverage.ts # reconciles the docs against the registry
|
|
@@ -39,7 +39,7 @@ Requirements are identified by a hash of their canonical text, not by a hand-wri
|
|
|
39
39
|
|
|
40
40
|
```jsonc
|
|
41
41
|
{
|
|
42
|
-
"doc": "
|
|
42
|
+
"doc": "next-codebase-guide/rules/no-mixed-concerns-rule.md",
|
|
43
43
|
"text": "A .tsx file that defines a component MUST contain exactly one component.",
|
|
44
44
|
"hash": "b19fe3bd34",
|
|
45
45
|
"ref": "pasika/no-mixed-concerns",
|
|
@@ -88,8 +88,8 @@ The script refuses a hash no requirement has, a `ref` naming a rule that does no
|
|
|
88
88
|
|
|
89
89
|
```bash
|
|
90
90
|
npm run build
|
|
91
|
-
npm run dogfood -- ../some/repo #
|
|
92
|
-
npm run dogfood -- ../some/repo --preset=
|
|
91
|
+
npm run dogfood -- ../some/repo # pasikaNextjsApp preset (default)
|
|
92
|
+
npm run dogfood -- ../some/repo --preset=pasikaApp
|
|
93
93
|
npm run dogfood -- ../some/repo --pasika-only # tally only pasika/* rules
|
|
94
94
|
npm run dogfood -- ../some/repo --rule=css-entry-point --findings
|
|
95
95
|
npm run dogfood -- ../some/repo --json # machine-readable report
|
|
@@ -115,18 +115,18 @@ const { eslintConfig } = styleguide({
|
|
|
115
115
|
export default eslintConfig;
|
|
116
116
|
```
|
|
117
117
|
|
|
118
|
-
For a plain TypeScript repository, enable `
|
|
118
|
+
For a plain TypeScript repository, enable `pasikaApp` instead of `pasikaNextjsApp`; that preset covers the manifest, the zirka contract, and the docs only — the `src/**` source rules belong to the Next.js app preset. `zirka` composes the pasika ruleset over four file scopes: TS/TSX under `src/**`, `globals.css` and other stylesheets, `package.json`, and markdown — each with its own ESLint language.
|
|
119
119
|
|
|
120
120
|
### Without Zirka
|
|
121
121
|
|
|
122
122
|
```ts
|
|
123
123
|
// eslint.config.ts — plain TypeScript repository
|
|
124
|
-
import {
|
|
124
|
+
import { pasikaApp } from "pasika/eslint";
|
|
125
125
|
|
|
126
|
-
export default
|
|
126
|
+
export default pasikaApp;
|
|
127
127
|
```
|
|
128
128
|
|
|
129
|
-
`
|
|
129
|
+
`pasikaApp` is the plain-TypeScript-repository preset — the package.json manifest, the zirka configuration contract, and the docs. It carries no `src/**` source block: source linting is the Next.js app's job. `pasikaNextjsApp` is the full framework preset: everything in `pasikaApp` plus the Next.js-stack manifest requirement, the `src/**` app source rules, and the Tailwind stylesheet blocks. The granular rule objects (`tailwindRules`, `repoPackageJsonRules`, `documentationRules`) stay exported for manual wiring.
|
|
130
130
|
|
|
131
131
|
The `src/**` blocks ship `@typescript-eslint/parser` themselves, so a standalone preset parses `.ts`/`.tsx` correctly on its own (`pasika` lists it as a runtime dependency).
|
|
132
132
|
|
|
@@ -246,13 +246,16 @@ declare const allPasikaRuleIds: string[];
|
|
|
246
246
|
* source block: source linting is the Next.js app's job.
|
|
247
247
|
* Use this for a plain TypeScript repository that does not adopt the framework.
|
|
248
248
|
*/
|
|
249
|
-
declare const
|
|
249
|
+
declare const pasikaApp: Linter.Config[];
|
|
250
250
|
/**
|
|
251
251
|
* Next.js app preset: the full adopted-to-the-framework stack. Anything in
|
|
252
|
-
* `
|
|
252
|
+
* `pasikaApp` plus the framework-only blocks — the Next.js-stack manifest
|
|
253
253
|
* requirement, the `src/**` app source rules, and the Tailwind stylesheet
|
|
254
|
-
* rules. `
|
|
254
|
+
* rules. `pasikaApp` is a strict subset of `pasikaNextjsApp`. Consuming this
|
|
255
|
+
* preset (spreading or iterating it) runs the TypeScript alignment diagnostic
|
|
256
|
+
* first, so a mismatched compiler major fails config load with an actionable
|
|
257
|
+
* error instead of crashing every type-aware rule later.
|
|
255
258
|
*/
|
|
256
|
-
declare const
|
|
259
|
+
declare const pasikaNextjsApp: Linter.Config[];
|
|
257
260
|
|
|
258
|
-
export { allPasikaRuleIds, documentationRules, huskyRules,
|
|
261
|
+
export { allPasikaRuleIds, documentationRules, huskyRules, nextjsPackageJsonRules, pasikaApp, pasikaNextjsApp, pasikaPlugin, repoPackageJsonRules, tailwindRules, vulykRules };
|
|
@@ -4,6 +4,53 @@ import jsonPlugin from "@eslint/json";
|
|
|
4
4
|
import markdown from "@eslint/markdown";
|
|
5
5
|
import tsParser from "@typescript-eslint/parser";
|
|
6
6
|
|
|
7
|
+
// eslint/ts-alignment.ts
|
|
8
|
+
import { readFileSync } from "fs";
|
|
9
|
+
import { createRequire } from "module";
|
|
10
|
+
import { join } from "path";
|
|
11
|
+
var ownRequire = createRequire(import.meta.url);
|
|
12
|
+
var majorOf = (version) => Number(version.split(".")[0]);
|
|
13
|
+
function versionOf(packagePath) {
|
|
14
|
+
try {
|
|
15
|
+
const parsed = JSON.parse(readFileSync(packagePath, "utf8"));
|
|
16
|
+
if (typeof parsed !== "object" || parsed === null || !("version" in parsed)) return null;
|
|
17
|
+
return typeof parsed.version === "string" ? parsed.version : null;
|
|
18
|
+
} catch {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function resolveTypescriptAlignment() {
|
|
23
|
+
let bundled = null;
|
|
24
|
+
try {
|
|
25
|
+
bundled = versionOf(ownRequire.resolve("typescript/package.json"));
|
|
26
|
+
} catch {
|
|
27
|
+
bundled = null;
|
|
28
|
+
}
|
|
29
|
+
let resolved = null;
|
|
30
|
+
try {
|
|
31
|
+
const consumerRequire = createRequire(join(process.cwd(), "package.json"));
|
|
32
|
+
resolved = versionOf(consumerRequire.resolve("typescript/package.json"));
|
|
33
|
+
} catch {
|
|
34
|
+
resolved = null;
|
|
35
|
+
}
|
|
36
|
+
return { bundled, resolved };
|
|
37
|
+
}
|
|
38
|
+
function alignmentError(bundled, resolved) {
|
|
39
|
+
if (bundled === null || resolved === null) return null;
|
|
40
|
+
const bundledMajor = majorOf(bundled);
|
|
41
|
+
const resolvedMajor = majorOf(resolved);
|
|
42
|
+
if (bundledMajor === resolvedMajor) return null;
|
|
43
|
+
const direction = resolvedMajor < bundledMajor ? `Upgrade your typescript to ^${String(bundledMajor)} (pinned exact) so a single hoisted copy serves the whole pipeline.` : `Your repository is ahead of the compiler pasika ships. Pin typescript to ^${String(bundledMajor)} for now and upgrade pasika when it bundles the newer major.`;
|
|
44
|
+
return new Error(
|
|
45
|
+
`[pasika] TypeScript major mismatch: the pasikaNextjsApp preset parses src/** with its bundled @typescript-eslint/parser, which runs on typescript ${bundled}; your repository resolves typescript ${resolved} for the type-aware rules. Two TypeScript majors mean the types the parser builds use a different TypeFlags layout than the rules expect, so every type-aware rule crashes (e.g. "undefined is not iterable" in ts-api-utils). Align them on ${String(bundledMajor)}, then lint will run again. ${direction}`
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
function assertTypescriptAlignment() {
|
|
49
|
+
const { bundled, resolved } = resolveTypescriptAlignment();
|
|
50
|
+
const error = alignmentError(bundled, resolved);
|
|
51
|
+
if (error) throw error;
|
|
52
|
+
}
|
|
53
|
+
|
|
7
54
|
// eslint/rules/filename-case.ts
|
|
8
55
|
import path2 from "path";
|
|
9
56
|
|
|
@@ -395,7 +442,7 @@ var noMixedConcernsRule = {
|
|
|
395
442
|
for (const extra of components.slice(1)) {
|
|
396
443
|
context.report({
|
|
397
444
|
loc: { line: 1, column: 0 },
|
|
398
|
-
message: `File defines multiple components. "${extra.name}" is an extra component. Move it to its own file. Each component file MUST define exactly one component. See docs/
|
|
445
|
+
message: `File defines multiple components. "${extra.name}" is an extra component. Move it to its own file. Each component file MUST define exactly one component. See docs/next-codebase-guide/rules/no-mixed-concerns-rule.md`
|
|
399
446
|
});
|
|
400
447
|
}
|
|
401
448
|
}
|
|
@@ -421,7 +468,7 @@ var noArbitraryTailwindRule = {
|
|
|
421
468
|
if (!match) return;
|
|
422
469
|
context.report({
|
|
423
470
|
node,
|
|
424
|
-
message: `Tailwind arbitrary-value class "${match[0]}" is not allowed. Use a named token or custom utility. See docs/
|
|
471
|
+
message: `Tailwind arbitrary-value class "${match[0]}" is not allowed. Use a named token or custom utility. See docs/next-tailwind-guide/rules/arbitrary-value-rule.md`
|
|
425
472
|
});
|
|
426
473
|
}
|
|
427
474
|
function checkExpression(node, expression) {
|
|
@@ -473,7 +520,7 @@ var noArbitraryTailwindRule = {
|
|
|
473
520
|
};
|
|
474
521
|
|
|
475
522
|
// eslint/rules/unknown-utility.ts
|
|
476
|
-
import { readdirSync, readFileSync, statSync } from "fs";
|
|
523
|
+
import { readdirSync, readFileSync as readFileSync2, statSync } from "fs";
|
|
477
524
|
import path5 from "path";
|
|
478
525
|
var PREFIX_NAMESPACES = {
|
|
479
526
|
bg: ["color"],
|
|
@@ -752,7 +799,7 @@ function readInventory(files) {
|
|
|
752
799
|
for (const file of files) {
|
|
753
800
|
let css2;
|
|
754
801
|
try {
|
|
755
|
-
css2 =
|
|
802
|
+
css2 = readFileSync2(file, "utf8");
|
|
756
803
|
} catch {
|
|
757
804
|
continue;
|
|
758
805
|
}
|
|
@@ -922,7 +969,7 @@ import path7 from "path";
|
|
|
922
969
|
|
|
923
970
|
// eslint/project/parse-module.ts
|
|
924
971
|
import path6 from "path";
|
|
925
|
-
import { readFileSync as
|
|
972
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
926
973
|
import ts2 from "typescript";
|
|
927
974
|
var isPascalCase3 = (name) => /^[A-Z][A-Za-z0-9]*$/.test(name);
|
|
928
975
|
var isHookName = (name) => /^use[A-Z]/.test(name);
|
|
@@ -959,7 +1006,7 @@ function classifyValue(name, initializer, isTsx) {
|
|
|
959
1006
|
return "constant";
|
|
960
1007
|
}
|
|
961
1008
|
function parseModule(file) {
|
|
962
|
-
const text =
|
|
1009
|
+
const text = readFileSync3(file, "utf8");
|
|
963
1010
|
const isTsx = file.endsWith(".tsx") || file.endsWith(".jsx");
|
|
964
1011
|
const sourceFile = ts2.createSourceFile(file, text, ts2.ScriptTarget.Latest, true, ts2.ScriptKind.TSX);
|
|
965
1012
|
const imports = [];
|
|
@@ -1178,7 +1225,7 @@ var enforceCnMergeRule = {
|
|
|
1178
1225
|
if (isComponentProp && attributeName !== "className" && attributeName.endsWith("ClassName")) {
|
|
1179
1226
|
context.report({
|
|
1180
1227
|
node,
|
|
1181
|
-
message: "Expose appearance through typed variant props instead of separate internal class-name props. See docs/
|
|
1228
|
+
message: "Expose appearance through typed variant props instead of separate internal class-name props. See docs/next-tailwind-guide/rules/class-composition-rule.md"
|
|
1182
1229
|
});
|
|
1183
1230
|
return;
|
|
1184
1231
|
}
|
|
@@ -1192,7 +1239,7 @@ var enforceCnMergeRule = {
|
|
|
1192
1239
|
if (invalidClass) {
|
|
1193
1240
|
context.report({
|
|
1194
1241
|
node,
|
|
1195
|
-
message: `Passed className contains non-layout utility "${invalidClass}". Expose appearance through typed variant props. See docs/
|
|
1242
|
+
message: `Passed className contains non-layout utility "${invalidClass}". Expose appearance through typed variant props. See docs/next-tailwind-guide/rules/class-composition-rule.md`
|
|
1196
1243
|
});
|
|
1197
1244
|
}
|
|
1198
1245
|
return;
|
|
@@ -1201,7 +1248,7 @@ var enforceCnMergeRule = {
|
|
|
1201
1248
|
if (classCount(valueNode.value) > 5) {
|
|
1202
1249
|
context.report({
|
|
1203
1250
|
node,
|
|
1204
|
-
message: "Static className with more than 5 classes must use cn() with grouped string literals. See docs/
|
|
1251
|
+
message: "Static className with more than 5 classes must use cn() with grouped string literals. See docs/next-tailwind-guide/rules/class-composition-rule.md"
|
|
1205
1252
|
});
|
|
1206
1253
|
}
|
|
1207
1254
|
return;
|
|
@@ -1211,28 +1258,28 @@ var enforceCnMergeRule = {
|
|
|
1211
1258
|
if (expr.type === "BinaryExpression" && expr.operator === "+") {
|
|
1212
1259
|
context.report({
|
|
1213
1260
|
node,
|
|
1214
|
-
message: "Use cn() instead of + operator for className. See docs/
|
|
1261
|
+
message: "Use cn() instead of + operator for className. See docs/next-tailwind-guide/rules/class-composition-rule.md"
|
|
1215
1262
|
});
|
|
1216
1263
|
return;
|
|
1217
1264
|
}
|
|
1218
1265
|
if (expr.type === "TemplateLiteral" && expr.expressions.length > 0) {
|
|
1219
1266
|
context.report({
|
|
1220
1267
|
node,
|
|
1221
|
-
message: "Use cn() instead of template literals with conditionals for className. See docs/
|
|
1268
|
+
message: "Use cn() instead of template literals with conditionals for className. See docs/next-tailwind-guide/rules/class-composition-rule.md"
|
|
1222
1269
|
});
|
|
1223
1270
|
return;
|
|
1224
1271
|
}
|
|
1225
1272
|
if (expr.type === "LogicalExpression" || expr.type === "ConditionalExpression") {
|
|
1226
1273
|
context.report({
|
|
1227
1274
|
node,
|
|
1228
|
-
message: "Use cn() for conditional classes in className. See docs/
|
|
1275
|
+
message: "Use cn() for conditional classes in className. See docs/next-tailwind-guide/rules/class-composition-rule.md"
|
|
1229
1276
|
});
|
|
1230
1277
|
return;
|
|
1231
1278
|
}
|
|
1232
1279
|
if (expr.type === "Literal" && typeof expr.value === "string" && classCount(expr.value) > 5) {
|
|
1233
1280
|
context.report({
|
|
1234
1281
|
node,
|
|
1235
|
-
message: "Static className with more than 5 classes must use cn() with grouped string literals. See docs/
|
|
1282
|
+
message: "Static className with more than 5 classes must use cn() with grouped string literals. See docs/next-tailwind-guide/rules/class-composition-rule.md"
|
|
1236
1283
|
});
|
|
1237
1284
|
return;
|
|
1238
1285
|
}
|
|
@@ -1241,7 +1288,7 @@ var enforceCnMergeRule = {
|
|
|
1241
1288
|
if (arg.type === "Literal" && typeof arg.value === "string" && classCount(arg.value) > 5) {
|
|
1242
1289
|
context.report({
|
|
1243
1290
|
node: arg,
|
|
1244
|
-
message: "Each cn() string argument must contain at most 5 class names. Group by styling concern. See docs/
|
|
1291
|
+
message: "Each cn() string argument must contain at most 5 class names. Group by styling concern. See docs/next-tailwind-guide/rules/class-composition-rule.md"
|
|
1245
1292
|
});
|
|
1246
1293
|
}
|
|
1247
1294
|
}
|
|
@@ -1339,7 +1386,7 @@ var enforceCvaVariantPropsRule = {
|
|
|
1339
1386
|
if (variantNames.includes(keyName2)) {
|
|
1340
1387
|
context.report({
|
|
1341
1388
|
node,
|
|
1342
|
-
message: `Variant prop "${keyName2}" duplicates CVA variant values. Use VariantProps<typeof variants> instead of manually writing union types. See docs/
|
|
1389
|
+
message: `Variant prop "${keyName2}" duplicates CVA variant values. Use VariantProps<typeof variants> instead of manually writing union types. See docs/next-tailwind-guide/rules/component-variant-rule.md`
|
|
1343
1390
|
});
|
|
1344
1391
|
return;
|
|
1345
1392
|
}
|
|
@@ -1407,7 +1454,7 @@ var enforceBarrelExportsRule = {
|
|
|
1407
1454
|
if (!reExportedNames.has(parentName)) {
|
|
1408
1455
|
context.report({
|
|
1409
1456
|
loc: { line: 1, column: 0 },
|
|
1410
|
-
message: `index.ts in "${folderName}/" must re-export "${parentName}". See docs/
|
|
1457
|
+
message: `index.ts in "${folderName}/" must re-export "${parentName}". See docs/next-codebase-guide/rules/folder-nesting-rule.md`
|
|
1411
1458
|
});
|
|
1412
1459
|
return;
|
|
1413
1460
|
}
|
|
@@ -1415,7 +1462,7 @@ var enforceBarrelExportsRule = {
|
|
|
1415
1462
|
if (nonParentExports.length > 0) {
|
|
1416
1463
|
context.report({
|
|
1417
1464
|
loc: { line: 1, column: 0 },
|
|
1418
|
-
message: `index.ts must not re-export exclusive children: ${nonParentExports.join(", ")}. Only "${parentName}" may be re-exported. See docs/
|
|
1465
|
+
message: `index.ts must not re-export exclusive children: ${nonParentExports.join(", ")}. Only "${parentName}" may be re-exported. See docs/next-codebase-guide/rules/folder-nesting-rule.md`
|
|
1419
1466
|
});
|
|
1420
1467
|
}
|
|
1421
1468
|
}
|
|
@@ -1559,7 +1606,7 @@ var componentPlacementRule = {
|
|
|
1559
1606
|
context.report({
|
|
1560
1607
|
node,
|
|
1561
1608
|
loc: { line: 1, column: 0 },
|
|
1562
|
-
message: `This component has no consumer outside src/app/ or a configuration module, so it belongs in the feature folder it represents, not in ${formatFolder(currentFolder)}. See docs/
|
|
1609
|
+
message: `This component has no consumer outside src/app/ or a configuration module, so it belongs in the feature folder it represents, not in ${formatFolder(currentFolder)}. See docs/next-codebase-guide/rules/component-placement-rule.md`
|
|
1563
1610
|
});
|
|
1564
1611
|
}
|
|
1565
1612
|
return;
|
|
@@ -1570,7 +1617,7 @@ var componentPlacementRule = {
|
|
|
1570
1617
|
context.report({
|
|
1571
1618
|
node,
|
|
1572
1619
|
loc: { line: 1, column: 0 },
|
|
1573
|
-
message: `Move this component to ${formatFolder(placement.expectedFolder)} \u2014 ${explanation}. Imported by ${describeConsumers(placement.countedConsumers, sourceRoot)}. See docs/
|
|
1620
|
+
message: `Move this component to ${formatFolder(placement.expectedFolder)} \u2014 ${explanation}. Imported by ${describeConsumers(placement.countedConsumers, sourceRoot)}. See docs/next-codebase-guide/rules/component-placement-rule.md`
|
|
1574
1621
|
});
|
|
1575
1622
|
}
|
|
1576
1623
|
};
|
|
@@ -1857,7 +1904,7 @@ var namedExportsRule = {
|
|
|
1857
1904
|
ExportDefaultDeclaration(node) {
|
|
1858
1905
|
context.report({
|
|
1859
1906
|
node,
|
|
1860
|
-
message: "Files that export values must use named exports unless a framework or third-party package requires a different export style for that file. See docs/
|
|
1907
|
+
message: "Files that export values must use named exports unless a framework or third-party package requires a different export style for that file. See docs/next-codebase-guide/rules/exports-and-imports-rule.md"
|
|
1861
1908
|
});
|
|
1862
1909
|
}
|
|
1863
1910
|
};
|
|
@@ -1928,7 +1975,7 @@ var dataTestIdCaseRule = {
|
|
|
1928
1975
|
} else if (component.smart) {
|
|
1929
1976
|
context.report({
|
|
1930
1977
|
node,
|
|
1931
|
-
message: `Smart component "${component.name}" has no single outer element; wrap its content in one outer element with data-testid="${component.name}" instead of rendering multiple roots. See docs/
|
|
1978
|
+
message: `Smart component "${component.name}" has no single outer element; wrap its content in one outer element with data-testid="${component.name}" instead of rendering multiple roots. See docs/next-codebase-guide/rules/smart-vs-dumb-component-rule.md`
|
|
1932
1979
|
});
|
|
1933
1980
|
}
|
|
1934
1981
|
}
|
|
@@ -1986,7 +2033,7 @@ var supportFolderShapeRule = {
|
|
|
1986
2033
|
if (missing.length === 0) return;
|
|
1987
2034
|
context.report({
|
|
1988
2035
|
node,
|
|
1989
|
-
message: `${folder}/index.ts must named-re-export every support file: ${missing.join(", ")}. See docs/
|
|
2036
|
+
message: `${folder}/index.ts must named-re-export every support file: ${missing.join(", ")}. See docs/next-codebase-guide/rules/${folder === "constants" ? "constants" : "types-and-schemas"}-rule.md`
|
|
1990
2037
|
});
|
|
1991
2038
|
}
|
|
1992
2039
|
};
|
|
@@ -2021,7 +2068,7 @@ var importThroughIndexRule = {
|
|
|
2021
2068
|
const expected = `@/${folderIndex.join("/")}`;
|
|
2022
2069
|
context.report({
|
|
2023
2070
|
node,
|
|
2024
|
-
message: `Import support files through ${expected} instead of "${specifier}". See the
|
|
2071
|
+
message: `Import support files through ${expected} instead of "${specifier}". See the next-codebase-guide exports and imports rules.`
|
|
2025
2072
|
});
|
|
2026
2073
|
}
|
|
2027
2074
|
}
|
|
@@ -2108,7 +2155,7 @@ var noUtilBarrelRule = {
|
|
|
2108
2155
|
if (utilsIndex < 0 || !path19.basename(target).startsWith("index.")) continue;
|
|
2109
2156
|
context.report({
|
|
2110
2157
|
node,
|
|
2111
|
-
message: `Import utilities directly instead of through "${specifier}". See docs/
|
|
2158
|
+
message: `Import utilities directly instead of through "${specifier}". See docs/next-codebase-guide/rules/utilities-rule.md`
|
|
2112
2159
|
});
|
|
2113
2160
|
}
|
|
2114
2161
|
}
|
|
@@ -2207,7 +2254,7 @@ var jsxHygieneRule = {
|
|
|
2207
2254
|
if (!violation) return;
|
|
2208
2255
|
context.report({
|
|
2209
2256
|
node,
|
|
2210
|
-
message: `Extract ${violation} from JSX before return. See docs/
|
|
2257
|
+
message: `Extract ${violation} from JSX before return. See docs/next-codebase-guide/rules/jsx-hygiene-rule.md`
|
|
2211
2258
|
});
|
|
2212
2259
|
}
|
|
2213
2260
|
return {
|
|
@@ -2389,7 +2436,7 @@ var interactiveComponentRule = {
|
|
|
2389
2436
|
if (name === void 0) return;
|
|
2390
2437
|
context.report({
|
|
2391
2438
|
node,
|
|
2392
|
-
message: `Extract the interactive <${name}> into a descriptive component. See docs/
|
|
2439
|
+
message: `Extract the interactive <${name}> into a descriptive component. See docs/next-codebase-guide/rules/interactive-component-rule.md`
|
|
2393
2440
|
});
|
|
2394
2441
|
}
|
|
2395
2442
|
};
|
|
@@ -2453,7 +2500,7 @@ var uiStateRule = {
|
|
|
2453
2500
|
if (!hasNativeState) {
|
|
2454
2501
|
context.report({
|
|
2455
2502
|
node: attribute,
|
|
2456
|
-
message: `UI state prop "${name}" should be expressed with a native or ARIA state attribute. See docs/
|
|
2503
|
+
message: `UI state prop "${name}" should be expressed with a native or ARIA state attribute. See docs/next-tailwind-guide/rules/component-ui-state-rule.md`
|
|
2457
2504
|
});
|
|
2458
2505
|
}
|
|
2459
2506
|
}
|
|
@@ -2470,7 +2517,7 @@ var uiStateRule = {
|
|
|
2470
2517
|
if (classes.length > 0 && !classes.some((className) => STATE_CLASS_RE.test(className))) {
|
|
2471
2518
|
context.report({
|
|
2472
2519
|
node: attribute,
|
|
2473
|
-
message: "Use a Tailwind state variant for a UI state instead of conditional replacement classes. See docs/
|
|
2520
|
+
message: "Use a Tailwind state variant for a UI state instead of conditional replacement classes. See docs/next-tailwind-guide/rules/component-ui-state-rule.md"
|
|
2474
2521
|
});
|
|
2475
2522
|
}
|
|
2476
2523
|
}
|
|
@@ -2532,7 +2579,7 @@ var cvaAppearancePropsRule = {
|
|
|
2532
2579
|
if (typeAnnotation.type === "TSUnionType" || typeAnnotation.type === "TSTypeLiteral") {
|
|
2533
2580
|
context.report({
|
|
2534
2581
|
node,
|
|
2535
|
-
message: `Visual option prop "${keyName2}" must be defined through a cva() call rather than a manual union type. See docs/
|
|
2582
|
+
message: `Visual option prop "${keyName2}" must be defined through a cva() call rather than a manual union type. See docs/next-tailwind-guide/rules/component-variant-rule.md`
|
|
2536
2583
|
});
|
|
2537
2584
|
}
|
|
2538
2585
|
}
|
|
@@ -2606,7 +2653,7 @@ var cvaBooleanVariantsRule = {
|
|
|
2606
2653
|
if (info.variantNames.has(propName)) {
|
|
2607
2654
|
context.report({
|
|
2608
2655
|
node,
|
|
2609
|
-
message: `Boolean prop "${propName}" is used as a standalone conditional in cn() but is also defined as a CVA variant. Move it to one place: either CVA (with both true/false treatments) or cn() (standalone). See docs/
|
|
2656
|
+
message: `Boolean prop "${propName}" is used as a standalone conditional in cn() but is also defined as a CVA variant. Move it to one place: either CVA (with both true/false treatments) or cn() (standalone). See docs/next-tailwind-guide/rules/component-variant-rule.md`
|
|
2610
2657
|
});
|
|
2611
2658
|
}
|
|
2612
2659
|
}
|
|
@@ -2665,7 +2712,7 @@ var crossFeatureImportRule = {
|
|
|
2665
2712
|
const names = [...importedFeatures].sort().join(", ");
|
|
2666
2713
|
context.report({
|
|
2667
2714
|
node,
|
|
2668
|
-
message: `This component imports from two or more feature folders (${names}) and must live in src/compositions/. See docs/
|
|
2715
|
+
message: `This component imports from two or more feature folders (${names}) and must live in src/compositions/. See docs/next-codebase-guide/rules/component-placement-rule.md`
|
|
2669
2716
|
});
|
|
2670
2717
|
}
|
|
2671
2718
|
}
|
|
@@ -2713,7 +2760,7 @@ var pureFunctionExtractRule = {
|
|
|
2713
2760
|
function report3(node, name) {
|
|
2714
2761
|
context.report({
|
|
2715
2762
|
node,
|
|
2716
|
-
message: `Extract pure function "${name}" to utils/. See docs/
|
|
2763
|
+
message: `Extract pure function "${name}" to utils/. See docs/next-codebase-guide/rules/utilities-rule.md`
|
|
2717
2764
|
});
|
|
2718
2765
|
}
|
|
2719
2766
|
return {
|
|
@@ -2812,12 +2859,12 @@ var hookComplexityRule = {
|
|
|
2812
2859
|
if (imperativeCount >= 2 && !inSupportFolder) {
|
|
2813
2860
|
context.report({
|
|
2814
2861
|
node,
|
|
2815
|
-
message: `Hook "${name}" has ${String(imperativeCount)} imperative categories and must be extracted to a hooks/ folder. See docs/
|
|
2862
|
+
message: `Hook "${name}" has ${String(imperativeCount)} imperative categories and must be extracted to a hooks/ folder. See docs/next-codebase-guide/rules/hook-extraction-rule.md`
|
|
2816
2863
|
});
|
|
2817
2864
|
} else if (imperativeCount < 2 && inSupportFolder) {
|
|
2818
2865
|
context.report({
|
|
2819
2866
|
node,
|
|
2820
|
-
message: `Hook "${name}" has fewer than two imperative categories and must stay inline in its consumer file. See docs/
|
|
2867
|
+
message: `Hook "${name}" has fewer than two imperative categories and must stay inline in its consumer file. See docs/next-codebase-guide/rules/hook-extraction-rule.md`
|
|
2821
2868
|
});
|
|
2822
2869
|
}
|
|
2823
2870
|
}
|
|
@@ -2964,7 +3011,7 @@ var hookExtractionRule = {
|
|
|
2964
3011
|
context.report({
|
|
2965
3012
|
node,
|
|
2966
3013
|
loc: { line: exp.line, column: 0 },
|
|
2967
|
-
message: `Hook "${exp.name}" has ${String(consumers?.size ?? 0)} consumers; extract it to its own file in a hooks/ folder. See docs/
|
|
3014
|
+
message: `Hook "${exp.name}" has ${String(consumers?.size ?? 0)} consumers; extract it to its own file in a hooks/ folder. See docs/next-codebase-guide/rules/hook-extraction-rule.md`
|
|
2968
3015
|
});
|
|
2969
3016
|
}
|
|
2970
3017
|
}
|
|
@@ -2997,7 +3044,7 @@ var valueExtractionRule = {
|
|
|
2997
3044
|
context.report({
|
|
2998
3045
|
node,
|
|
2999
3046
|
loc: { line: 1, column: 0 },
|
|
3000
|
-
message: `This file in src/app/ is imported by ${describeConsumers(outsideApp, sourceRoot)} outside src/app/. Extract the value to a shared or feature folder so it can be imported independently. See docs/
|
|
3047
|
+
message: `This file in src/app/ is imported by ${describeConsumers(outsideApp, sourceRoot)} outside src/app/. Extract the value to a shared or feature folder so it can be imported independently. See docs/next-codebase-guide/rules/constants-rule.md`
|
|
3001
3048
|
});
|
|
3002
3049
|
}
|
|
3003
3050
|
};
|
|
@@ -3033,12 +3080,12 @@ var configExtractionRule = {
|
|
|
3033
3080
|
if (outsideConfig.length > 0) {
|
|
3034
3081
|
findings.push({
|
|
3035
3082
|
line: exp.line,
|
|
3036
|
-
message: `${exp.kind} "${exp.name}" in a configuration module is imported by ${describeConsumers(outsideConfig, sourceRoot)} outside src/config/. Move it to the matching root support folder. See docs/
|
|
3083
|
+
message: `${exp.kind} "${exp.name}" in a configuration module is imported by ${describeConsumers(outsideConfig, sourceRoot)} outside src/config/. Move it to the matching root support folder. See docs/next-codebase-guide/rules/configuration-rule.md`
|
|
3037
3084
|
});
|
|
3038
3085
|
} else if (consumers.length > 0) {
|
|
3039
3086
|
findings.push({
|
|
3040
3087
|
line: exp.line,
|
|
3041
|
-
message: `${exp.kind} "${exp.name}" is used only to implement this configuration module; extract it to the module's ${exp.kind === "schema" ? "schemas/" : "types/"} folder even with one consumer. See docs/
|
|
3088
|
+
message: `${exp.kind} "${exp.name}" is used only to implement this configuration module; extract it to the module's ${exp.kind === "schema" ? "schemas/" : "types/"} folder even with one consumer. See docs/next-codebase-guide/rules/configuration-rule.md`
|
|
3042
3089
|
});
|
|
3043
3090
|
}
|
|
3044
3091
|
}
|
|
@@ -3090,7 +3137,7 @@ var componentNestingRule = {
|
|
|
3090
3137
|
context.report({
|
|
3091
3138
|
node,
|
|
3092
3139
|
loc: { line: 1, column: 0 },
|
|
3093
|
-
message: `This component is nested in src/${folder.join("/")}/ but its folder has no exclusive child components \u2014 only support files. Flatten it back into src/${flatFolder}/. See docs/
|
|
3140
|
+
message: `This component is nested in src/${folder.join("/")}/ but its folder has no exclusive child components \u2014 only support files. Flatten it back into src/${flatFolder}/. See docs/next-codebase-guide/rules/folder-nesting-rule.md`
|
|
3094
3141
|
});
|
|
3095
3142
|
}
|
|
3096
3143
|
};
|
|
@@ -3141,7 +3188,7 @@ var stayFlatRule = {
|
|
|
3141
3188
|
context.report({
|
|
3142
3189
|
node,
|
|
3143
3190
|
loc: { line: 1, column: 0 },
|
|
3144
|
-
message: `This component has exclusive child component(s) ${childNames.join(", ")}; nest it in a folder named after it inside src/features/${featureName}/. See docs/
|
|
3191
|
+
message: `This component has exclusive child component(s) ${childNames.join(", ")}; nest it in a folder named after it inside src/features/${featureName}/. See docs/next-codebase-guide/rules/folder-nesting-rule.md`
|
|
3145
3192
|
});
|
|
3146
3193
|
}
|
|
3147
3194
|
};
|
|
@@ -3180,7 +3227,7 @@ var typeExtractionRule = {
|
|
|
3180
3227
|
if (independent2.length === 0) continue;
|
|
3181
3228
|
findings.push({
|
|
3182
3229
|
line: exp.line,
|
|
3183
|
-
message: `${exp.kind} "${exp.name}" is imported by ${describeConsumers(independent2, sourceRoot)} without the component "${componentExport.name}" that defines it. Extract it to a types/ or schemas/ folder. See docs/
|
|
3230
|
+
message: `${exp.kind} "${exp.name}" is imported by ${describeConsumers(independent2, sourceRoot)} without the component "${componentExport.name}" that defines it. Extract it to a types/ or schemas/ folder. See docs/next-codebase-guide/rules/types-and-schemas-rule.md`
|
|
3184
3231
|
});
|
|
3185
3232
|
continue;
|
|
3186
3233
|
}
|
|
@@ -3191,7 +3238,7 @@ var typeExtractionRule = {
|
|
|
3191
3238
|
if (independent.length === 0) continue;
|
|
3192
3239
|
findings.push({
|
|
3193
3240
|
line: exp.line,
|
|
3194
|
-
message: `${exp.kind} "${exp.name}" is imported by ${describeConsumers(independent, sourceRoot)} without using the code in this file. Extract it to a types/ or schemas/ folder. See docs/
|
|
3241
|
+
message: `${exp.kind} "${exp.name}" is imported by ${describeConsumers(independent, sourceRoot)} without using the code in this file. Extract it to a types/ or schemas/ folder. See docs/next-codebase-guide/rules/types-and-schemas-rule.md`
|
|
3195
3242
|
});
|
|
3196
3243
|
}
|
|
3197
3244
|
if (findings.length === 0) return {};
|
|
@@ -3207,7 +3254,7 @@ var typeExtractionRule = {
|
|
|
3207
3254
|
|
|
3208
3255
|
// eslint/rules/locale-placement.ts
|
|
3209
3256
|
import path32 from "path";
|
|
3210
|
-
import { readFileSync as
|
|
3257
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
3211
3258
|
import ts5 from "typescript";
|
|
3212
3259
|
var LOCALE_ACCESS = /\blocales\.(?<key>[A-Za-z_$][\w$]*)/g;
|
|
3213
3260
|
var camelCase = (name) => name.replace(/-[a-z]/g, (match) => match.slice(1).toUpperCase());
|
|
@@ -3264,7 +3311,7 @@ var localePlacementRule = {
|
|
|
3264
3311
|
return candidateSegments.length === 2 && candidateSegments[0] === "locales" && candidateSegments[1]?.startsWith("index.");
|
|
3265
3312
|
});
|
|
3266
3313
|
if (!localesFile || file !== localesFile) return {};
|
|
3267
|
-
const placement = localePlacement(
|
|
3314
|
+
const placement = localePlacement(readFileSync4(localesFile, "utf8"));
|
|
3268
3315
|
if (!placement) return {};
|
|
3269
3316
|
const keyReaders = /* @__PURE__ */ new Map();
|
|
3270
3317
|
const keyFeatures = /* @__PURE__ */ new Map();
|
|
@@ -3276,7 +3323,7 @@ var localePlacementRule = {
|
|
|
3276
3323
|
);
|
|
3277
3324
|
if (!importsLocales) continue;
|
|
3278
3325
|
const candidateSegments = segmentsOf(candidateFile, sourceRoot);
|
|
3279
|
-
for (const match of
|
|
3326
|
+
for (const match of readFileSync4(candidateFile, "utf8").matchAll(LOCALE_ACCESS)) {
|
|
3280
3327
|
const key = match.groups?.key;
|
|
3281
3328
|
if (key === void 0) continue;
|
|
3282
3329
|
const readers = keyReaders.get(key) ?? /* @__PURE__ */ new Set();
|
|
@@ -3300,7 +3347,7 @@ var localePlacementRule = {
|
|
|
3300
3347
|
if (current?.kind === "nested") {
|
|
3301
3348
|
findings.push({
|
|
3302
3349
|
line: current.line,
|
|
3303
|
-
message: `Locale "${key}" is read by ${describeConsumers([...readers], sourceRoot)} and must live at the top level of locales. See docs/
|
|
3350
|
+
message: `Locale "${key}" is read by ${describeConsumers([...readers], sourceRoot)} and must live at the top level of locales. See docs/next-codebase-guide/rules/locales-rule.md`
|
|
3304
3351
|
});
|
|
3305
3352
|
}
|
|
3306
3353
|
continue;
|
|
@@ -3311,12 +3358,12 @@ var localePlacementRule = {
|
|
|
3311
3358
|
if (current?.kind === "top") {
|
|
3312
3359
|
findings.push({
|
|
3313
3360
|
line: current.line,
|
|
3314
|
-
message: `Locale "${key}" is read only by the ${featureName} feature; it must live in an object named "${expected}". See docs/
|
|
3361
|
+
message: `Locale "${key}" is read only by the ${featureName} feature; it must live in an object named "${expected}". See docs/next-codebase-guide/rules/locales-rule.md`
|
|
3315
3362
|
});
|
|
3316
3363
|
} else if (current?.kind === "nested" && key !== expected) {
|
|
3317
3364
|
findings.push({
|
|
3318
3365
|
line: current.line,
|
|
3319
|
-
message: `Locale "${key}" is read only by the ${featureName} feature; it must live in an object named "${expected}", not "${key}". See docs/
|
|
3366
|
+
message: `Locale "${key}" is read only by the ${featureName} feature; it must live in an object named "${expected}", not "${key}". See docs/next-codebase-guide/rules/locales-rule.md`
|
|
3320
3367
|
});
|
|
3321
3368
|
}
|
|
3322
3369
|
}
|
|
@@ -3428,7 +3475,7 @@ var soleStateOwnerRule = {
|
|
|
3428
3475
|
context.report({
|
|
3429
3476
|
node,
|
|
3430
3477
|
loc: { line: 1, column: 0 },
|
|
3431
|
-
message: `Component "${component.name}" uses state "${hook.value}" in ${String(run)} contiguous top-level JSX part${run === 1 ? "" : "s"}; extract that part into a named component that owns useState instead of reading it in the parent. See docs/
|
|
3478
|
+
message: `Component "${component.name}" uses state "${hook.value}" in ${String(run)} contiguous top-level JSX part${run === 1 ? "" : "s"}; extract that part into a named component that owns useState instead of reading it in the parent. See docs/next-codebase-guide/rules/sole-state-owner-rule.md`
|
|
3432
3479
|
});
|
|
3433
3480
|
}
|
|
3434
3481
|
}
|
|
@@ -3558,7 +3605,7 @@ function checkKey(context, node, name) {
|
|
|
3558
3605
|
reportFor(
|
|
3559
3606
|
context,
|
|
3560
3607
|
node,
|
|
3561
|
-
`Locale key "${name}" must be English; write it in the Latin alphabet. See docs/
|
|
3608
|
+
`Locale key "${name}" must be English; write it in the Latin alphabet. See docs/next-codebase-guide/rules/locales-rule.md`
|
|
3562
3609
|
);
|
|
3563
3610
|
return;
|
|
3564
3611
|
}
|
|
@@ -3566,7 +3613,7 @@ function checkKey(context, node, name) {
|
|
|
3566
3613
|
reportFor(
|
|
3567
3614
|
context,
|
|
3568
3615
|
node,
|
|
3569
|
-
`Locale key "${name}" must be camelCase English based on the text. See docs/
|
|
3616
|
+
`Locale key "${name}" must be camelCase English based on the text. See docs/next-codebase-guide/rules/locales-rule.md`
|
|
3570
3617
|
);
|
|
3571
3618
|
return;
|
|
3572
3619
|
}
|
|
@@ -3576,7 +3623,7 @@ function checkKey(context, node, name) {
|
|
|
3576
3623
|
reportFor(
|
|
3577
3624
|
context,
|
|
3578
3625
|
node,
|
|
3579
|
-
`Locale key "${name}" is longer than ${String(MAX_KEY_LENGTH)} characters, so it must describe the message's purpose instead of the text; end it with an element role such as "Button", "Link", or "Dialog" (see WAI-ARIA roles). See docs/
|
|
3626
|
+
`Locale key "${name}" is longer than ${String(MAX_KEY_LENGTH)} characters, so it must describe the message's purpose instead of the text; end it with an element role such as "Button", "Link", or "Dialog" (see WAI-ARIA roles). See docs/next-codebase-guide/rules/locales-rule.md`
|
|
3580
3627
|
);
|
|
3581
3628
|
}
|
|
3582
3629
|
var localeKeyShapeRule = {
|
|
@@ -3613,7 +3660,7 @@ var localeKeyShapeRule = {
|
|
|
3613
3660
|
|
|
3614
3661
|
// eslint/rules/shared-style-dedup.ts
|
|
3615
3662
|
import path35 from "path";
|
|
3616
|
-
import { readFileSync as
|
|
3663
|
+
import { readFileSync as readFileSync5, statSync as statSync3 } from "fs";
|
|
3617
3664
|
var CLASS_NAME = /className="(?<classes>[^"]+)"/g;
|
|
3618
3665
|
var comboCache;
|
|
3619
3666
|
function combosFor(index) {
|
|
@@ -3631,7 +3678,7 @@ function combosFor(index) {
|
|
|
3631
3678
|
}
|
|
3632
3679
|
const combos = /* @__PURE__ */ new Map();
|
|
3633
3680
|
for (const file of files) {
|
|
3634
|
-
const text =
|
|
3681
|
+
const text = readFileSync5(file, "utf8");
|
|
3635
3682
|
for (const match of text.matchAll(CLASS_NAME)) {
|
|
3636
3683
|
const classes = (match.groups?.classes ?? "").split(/\s+/).filter(Boolean);
|
|
3637
3684
|
if (classes.length < 2) continue;
|
|
@@ -3668,7 +3715,7 @@ var sharedStyleDedupRule = {
|
|
|
3668
3715
|
context.report({
|
|
3669
3716
|
node,
|
|
3670
3717
|
loc: { line: 1, column: 0 },
|
|
3671
|
-
message: `Class combination "${combo}" is used by ${String(users.size)} components and should change together; create a named custom Tailwind utility for it. See docs/
|
|
3718
|
+
message: `Class combination "${combo}" is used by ${String(users.size)} components and should change together; create a named custom Tailwind utility for it. See docs/next-tailwind-guide/rules/theme-and-utility-definition-rule.md`
|
|
3672
3719
|
});
|
|
3673
3720
|
}
|
|
3674
3721
|
}
|
|
@@ -3777,7 +3824,7 @@ var repeatedStructureRule = {
|
|
|
3777
3824
|
if (!first || !isSubstantial(first)) continue;
|
|
3778
3825
|
context.report({
|
|
3779
3826
|
node: first,
|
|
3780
|
-
message: `The same arrangement of elements appears ${String(group.length)} times here; extract it as a named component. Different data or labels do not prevent extraction. See docs/
|
|
3827
|
+
message: `The same arrangement of elements appears ${String(group.length)} times here; extract it as a named component. Different data or labels do not prevent extraction. See docs/next-codebase-guide/rules/repeated-structure-rule.md`
|
|
3781
3828
|
});
|
|
3782
3829
|
}
|
|
3783
3830
|
}
|
|
@@ -4541,7 +4588,7 @@ var noTemplatePromptRule = {
|
|
|
4541
4588
|
import path41 from "path";
|
|
4542
4589
|
|
|
4543
4590
|
// eslint/rules/documentation/project-index.ts
|
|
4544
|
-
import { readdirSync as readdirSync3, readFileSync as
|
|
4591
|
+
import { readdirSync as readdirSync3, readFileSync as readFileSync6, statSync as statSync4 } from "fs";
|
|
4545
4592
|
import path40 from "path";
|
|
4546
4593
|
var KIND_BY_SUFFIX = [
|
|
4547
4594
|
["-rule.md", "rule"],
|
|
@@ -4559,7 +4606,7 @@ function listMarkdownFiles(dir) {
|
|
|
4559
4606
|
});
|
|
4560
4607
|
}
|
|
4561
4608
|
function extractTitle(filePath) {
|
|
4562
|
-
const content =
|
|
4609
|
+
const content = readFileSync6(filePath, "utf8");
|
|
4563
4610
|
const match = /^# (?<title>.+)$/m.exec(content);
|
|
4564
4611
|
return match?.groups?.title?.trim() ?? "";
|
|
4565
4612
|
}
|
|
@@ -4842,10 +4889,10 @@ var noNestedHowToRule = {
|
|
|
4842
4889
|
};
|
|
4843
4890
|
|
|
4844
4891
|
// eslint/rules/documentation/glossary-term-linking.ts
|
|
4845
|
-
import { readFileSync as
|
|
4892
|
+
import { readFileSync as readFileSync7 } from "fs";
|
|
4846
4893
|
import path42 from "path";
|
|
4847
4894
|
function extractGlossaryTerms(filePath) {
|
|
4848
|
-
const content =
|
|
4895
|
+
const content = readFileSync7(filePath, "utf8");
|
|
4849
4896
|
const terms = [];
|
|
4850
4897
|
const headingPattern = /^## (?<term>.+)$/gm;
|
|
4851
4898
|
let match;
|
|
@@ -5444,7 +5491,7 @@ import { statSync as statSync6 } from "fs";
|
|
|
5444
5491
|
import path46 from "path";
|
|
5445
5492
|
|
|
5446
5493
|
// eslint/rules/tailwind/source-files.ts
|
|
5447
|
-
import { readdirSync as readdirSync4, readFileSync as
|
|
5494
|
+
import { readdirSync as readdirSync4, readFileSync as readFileSync8, statSync as statSync5 } from "fs";
|
|
5448
5495
|
import path44 from "path";
|
|
5449
5496
|
var CSS_EXTENSIONS = [".css"];
|
|
5450
5497
|
var MODULE_EXTENSIONS3 = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
|
|
@@ -5475,7 +5522,7 @@ function cachedTextReader() {
|
|
|
5475
5522
|
let text = texts.get(file);
|
|
5476
5523
|
if (text === void 0) {
|
|
5477
5524
|
try {
|
|
5478
|
-
text =
|
|
5525
|
+
text = readFileSync8(file, "utf8");
|
|
5479
5526
|
} catch {
|
|
5480
5527
|
text = "";
|
|
5481
5528
|
}
|
|
@@ -5843,7 +5890,7 @@ var nextjsPackageJsonRules = {
|
|
|
5843
5890
|
};
|
|
5844
5891
|
|
|
5845
5892
|
// eslint/rules/husky/husky-hook.ts
|
|
5846
|
-
import { existsSync as existsSync2, readFileSync as
|
|
5893
|
+
import { existsSync as existsSync2, readFileSync as readFileSync9 } from "fs";
|
|
5847
5894
|
import path47 from "path";
|
|
5848
5895
|
function memberName4(member) {
|
|
5849
5896
|
return member.name.type === "String" ? member.name.value : member.name.name;
|
|
@@ -5871,7 +5918,7 @@ var huskyHookRule = {
|
|
|
5871
5918
|
});
|
|
5872
5919
|
return;
|
|
5873
5920
|
}
|
|
5874
|
-
const content =
|
|
5921
|
+
const content = readFileSync9(hookPath, "utf8");
|
|
5875
5922
|
if (!content.includes("lint-staged")) {
|
|
5876
5923
|
context.report({ node, message: ".husky/pre-commit must run lint-staged." });
|
|
5877
5924
|
}
|
|
@@ -5902,7 +5949,7 @@ var huskyRules = {
|
|
|
5902
5949
|
};
|
|
5903
5950
|
|
|
5904
5951
|
// eslint/rules/vulyk/vulyk-docs.ts
|
|
5905
|
-
import { existsSync as existsSync3, readFileSync as
|
|
5952
|
+
import { existsSync as existsSync3, readFileSync as readFileSync10 } from "fs";
|
|
5906
5953
|
import path48 from "path";
|
|
5907
5954
|
var PASIKA_REPO = "Bredansky/pasika";
|
|
5908
5955
|
var BASE_REQUIRED_DOCS = [
|
|
@@ -5911,8 +5958,8 @@ var BASE_REQUIRED_DOCS = [
|
|
|
5911
5958
|
{ name: "repository-policy", path: "docs/repository-policy.md" }
|
|
5912
5959
|
];
|
|
5913
5960
|
var NEXTJS_REQUIRED_DOCS = [
|
|
5914
|
-
{ name: "
|
|
5915
|
-
{ name: "
|
|
5961
|
+
{ name: "next-codebase-guide", path: "docs/next-codebase-guide" },
|
|
5962
|
+
{ name: "next-tailwind-guide", path: "docs/next-tailwind-guide" }
|
|
5916
5963
|
];
|
|
5917
5964
|
function memberName5(member) {
|
|
5918
5965
|
return member.name.type === "String" ? member.name.value : member.name.name;
|
|
@@ -5945,7 +5992,7 @@ var vulykDocsRule = {
|
|
|
5945
5992
|
});
|
|
5946
5993
|
return;
|
|
5947
5994
|
}
|
|
5948
|
-
const config =
|
|
5995
|
+
const config = readFileSync10(configPath, "utf8");
|
|
5949
5996
|
if (!config.includes(PASIKA_REPO)) {
|
|
5950
5997
|
context.report({
|
|
5951
5998
|
node,
|
|
@@ -5980,7 +6027,7 @@ var vulykRules = {
|
|
|
5980
6027
|
};
|
|
5981
6028
|
|
|
5982
6029
|
// eslint/index.ts
|
|
5983
|
-
var
|
|
6030
|
+
var pasikaNextjsAppRules = {
|
|
5984
6031
|
// Framework-agnostic TypeScript rules.
|
|
5985
6032
|
"filename-case": filenameCaseRule,
|
|
5986
6033
|
"import-boundaries": importBoundariesRule,
|
|
@@ -6030,7 +6077,7 @@ var pasikaPlugin = {
|
|
|
6030
6077
|
rules: {
|
|
6031
6078
|
// The shared plugin must register every rule the preset blocks reference,
|
|
6032
6079
|
// so all rule sets live here.
|
|
6033
|
-
...
|
|
6080
|
+
...pasikaNextjsAppRules,
|
|
6034
6081
|
...documentationRules,
|
|
6035
6082
|
...tailwindRules,
|
|
6036
6083
|
...repoPackageJsonRules,
|
|
@@ -6043,7 +6090,7 @@ var jsonLanguage = { languages: { json: jsonPlugin.languages.json } };
|
|
|
6043
6090
|
function ruleIds(rules2) {
|
|
6044
6091
|
return Object.keys(rules2).map((name) => `pasika/${name}`);
|
|
6045
6092
|
}
|
|
6046
|
-
var
|
|
6093
|
+
var pasikaNextjsAppRuleIds = ruleIds(pasikaNextjsAppRules);
|
|
6047
6094
|
var documentationRuleIds = ruleIds(documentationRules);
|
|
6048
6095
|
var tailwindRuleIds = ruleIds(tailwindRules);
|
|
6049
6096
|
var repoPackageJsonRuleIds = ruleIds(repoPackageJsonRules);
|
|
@@ -6051,7 +6098,7 @@ var nextjsPackageJsonRuleIds = ruleIds(nextjsPackageJsonRules);
|
|
|
6051
6098
|
var huskyRuleIds = ruleIds(huskyRules);
|
|
6052
6099
|
var vulykRuleIds = ruleIds(vulykRules);
|
|
6053
6100
|
var allPasikaRuleIds = [
|
|
6054
|
-
...
|
|
6101
|
+
...pasikaNextjsAppRuleIds,
|
|
6055
6102
|
...documentationRuleIds,
|
|
6056
6103
|
...tailwindRuleIds,
|
|
6057
6104
|
...repoPackageJsonRuleIds,
|
|
@@ -6059,7 +6106,7 @@ var allPasikaRuleIds = [
|
|
|
6059
6106
|
...huskyRuleIds,
|
|
6060
6107
|
...vulykRuleIds
|
|
6061
6108
|
];
|
|
6062
|
-
var
|
|
6109
|
+
var pasikaAppLanguageOptions = {
|
|
6063
6110
|
parser: tsParser,
|
|
6064
6111
|
parserOptions: {
|
|
6065
6112
|
ecmaVersion: "latest",
|
|
@@ -6067,13 +6114,13 @@ var typescriptAppLanguageOptions = {
|
|
|
6067
6114
|
ecmaFeatures: { jsx: true }
|
|
6068
6115
|
}
|
|
6069
6116
|
};
|
|
6070
|
-
var
|
|
6117
|
+
var pasikaNextjsAppConfig = {
|
|
6071
6118
|
files: ["src/**/*.{cjs,cts,js,jsx,mjs,mts,ts,tsx}"],
|
|
6072
|
-
languageOptions:
|
|
6119
|
+
languageOptions: pasikaAppLanguageOptions,
|
|
6073
6120
|
plugins: {
|
|
6074
6121
|
pasika: pasikaPlugin
|
|
6075
6122
|
},
|
|
6076
|
-
rules: Object.fromEntries(
|
|
6123
|
+
rules: Object.fromEntries(pasikaNextjsAppRuleIds.map((id) => [id, "error"]))
|
|
6077
6124
|
};
|
|
6078
6125
|
var tailwindStructureRules = {
|
|
6079
6126
|
files: ["src/**/globals.css"],
|
|
@@ -6097,7 +6144,7 @@ var tailwindImportGraph = {
|
|
|
6097
6144
|
languageOptions: { tolerant: true },
|
|
6098
6145
|
rules: { "pasika/css-entry-point": "error" }
|
|
6099
6146
|
};
|
|
6100
|
-
var
|
|
6147
|
+
var pasikaAppPackageJsonConfig = {
|
|
6101
6148
|
files: ["package.json"],
|
|
6102
6149
|
plugins: {
|
|
6103
6150
|
json: jsonLanguage,
|
|
@@ -6106,7 +6153,7 @@ var typescriptAppPackageJsonConfig = {
|
|
|
6106
6153
|
language: "json/json",
|
|
6107
6154
|
rules: Object.fromEntries([...repoPackageJsonRuleIds, ...huskyRuleIds, ...vulykRuleIds].map((id) => [id, "error"]))
|
|
6108
6155
|
};
|
|
6109
|
-
var
|
|
6156
|
+
var pasikaNextjsAppPackageJsonConfig = {
|
|
6110
6157
|
files: ["package.json"],
|
|
6111
6158
|
plugins: {
|
|
6112
6159
|
json: jsonLanguage,
|
|
@@ -6133,27 +6180,39 @@ var documentationConfig = {
|
|
|
6133
6180
|
language: "markdown/gfm",
|
|
6134
6181
|
rules: Object.fromEntries(documentationRuleIds.map((id) => [id, "error"]))
|
|
6135
6182
|
};
|
|
6136
|
-
var
|
|
6137
|
-
|
|
6183
|
+
var pasikaApp = [
|
|
6184
|
+
pasikaAppPackageJsonConfig,
|
|
6138
6185
|
zirkaConfig,
|
|
6139
6186
|
documentationConfig
|
|
6140
6187
|
];
|
|
6141
|
-
var
|
|
6142
|
-
|
|
6143
|
-
|
|
6144
|
-
|
|
6188
|
+
var pasikaNextjsAppWithDiagnostic = (preset) => {
|
|
6189
|
+
let checked = false;
|
|
6190
|
+
return new Proxy(preset, {
|
|
6191
|
+
get(target, property, receiver) {
|
|
6192
|
+
if (!checked && (property === Symbol.iterator || property === "length")) {
|
|
6193
|
+
checked = true;
|
|
6194
|
+
assertTypescriptAlignment();
|
|
6195
|
+
}
|
|
6196
|
+
return Reflect.get(target, property, receiver);
|
|
6197
|
+
}
|
|
6198
|
+
});
|
|
6199
|
+
};
|
|
6200
|
+
var pasikaNextjsApp = pasikaNextjsAppWithDiagnostic([
|
|
6201
|
+
...pasikaApp,
|
|
6202
|
+
pasikaNextjsAppPackageJsonConfig,
|
|
6203
|
+
pasikaNextjsAppConfig,
|
|
6145
6204
|
tailwindStructureRules,
|
|
6146
6205
|
tailwindImportGraph
|
|
6147
|
-
];
|
|
6206
|
+
]);
|
|
6148
6207
|
export {
|
|
6149
6208
|
allPasikaRuleIds,
|
|
6150
6209
|
documentationRules,
|
|
6151
6210
|
huskyRules,
|
|
6152
|
-
nextjsApp,
|
|
6153
6211
|
nextjsPackageJsonRules,
|
|
6212
|
+
pasikaApp,
|
|
6213
|
+
pasikaNextjsApp,
|
|
6154
6214
|
pasikaPlugin,
|
|
6155
6215
|
repoPackageJsonRules,
|
|
6156
6216
|
tailwindRules,
|
|
6157
|
-
typescriptApp,
|
|
6158
6217
|
vulykRules
|
|
6159
6218
|
};
|