pasika 0.3.8 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,8 @@
1
+ // eslint/index.ts
2
+ import css from "@eslint/css";
3
+ import jsonPlugin from "@eslint/json";
4
+ import markdown from "@eslint/markdown";
5
+
1
6
  // eslint/rules/filename-case.ts
2
7
  import path2 from "path";
3
8
 
@@ -547,6 +552,43 @@ var enforceCnMergeRule = {
547
552
  }
548
553
  };
549
554
 
555
+ // eslint/rules/cn-helper.ts
556
+ function isIdentifier(node, name) {
557
+ return node?.type === "Identifier" && node.name === name;
558
+ }
559
+ var cnHelperRule = {
560
+ meta: {
561
+ schema: [],
562
+ type: "problem",
563
+ docs: {
564
+ description: "Require the cn helper to merge clsx and tailwind-merge."
565
+ }
566
+ },
567
+ create(context) {
568
+ return {
569
+ FunctionDeclaration(node) {
570
+ if (isIdentifier(node.id, "cn")) checkBody(context, node.body);
571
+ },
572
+ VariableDeclarator(node) {
573
+ if (node.init?.type === "ArrowFunctionExpression" && isIdentifier(node.id, "cn")) {
574
+ checkBody(context, node.init.body);
575
+ }
576
+ }
577
+ };
578
+ }
579
+ };
580
+ function checkBody(context, body) {
581
+ const source = context.sourceCode.getText(body);
582
+ const usesClsx = /\bclsx\b/.test(source);
583
+ const usesTwMerge = /\btwMerge\b|\btailwind-merge\b/.test(source);
584
+ if (!usesClsx || !usesTwMerge) {
585
+ context.report({
586
+ node: body,
587
+ message: "cn must be built from clsx and tailwind-merge (e.g. cn = twMerge(clsx(inputs)))."
588
+ });
589
+ }
590
+ }
591
+
550
592
  // eslint/rules/enforce-cva-variant-props.ts
551
593
  var enforceCvaVariantPropsRule = {
552
594
  meta: {
@@ -3224,48 +3266,96 @@ var sourceUnderSrcRule = {
3224
3266
  }
3225
3267
  };
3226
3268
 
3227
- // eslint/rules/config-baseline.ts
3269
+ // eslint/rules/zirka-baseline.ts
3228
3270
  import fs4 from "fs";
3229
3271
  import path33 from "path";
3230
- var configBaselineRule = {
3272
+ var ESLINT_CONFIG = /^eslint\.config\.(?:ts|mts|cts|js|mjs|cjs)$/;
3273
+ var PRETTIER_CONFIGS = [
3274
+ "prettier.config.mjs",
3275
+ "prettier.config.cjs",
3276
+ "prettier.config.js",
3277
+ "prettier.config.ts",
3278
+ "prettier.config.mts",
3279
+ "prettier.config.cts"
3280
+ ];
3281
+ var zirkaBaselineRule = {
3231
3282
  meta: {
3232
3283
  schema: [],
3233
3284
  type: "problem",
3234
3285
  docs: {
3235
- description: "Require eslint config to reference zirka and tsconfig.json to exist."
3286
+ description: "Require eslint, prettier, and TypeScript configuration to come from zirka."
3236
3287
  }
3237
3288
  },
3238
3289
  create(context) {
3239
3290
  const filename = path33.resolve(context.filename);
3240
3291
  const basename = path33.basename(filename);
3241
- if (!/^eslint\.config\.(?:ts|mts|cts|js|mjs|cjs)$/.test(basename)) return {};
3292
+ if (!ESLINT_CONFIG.test(basename)) return {};
3293
+ const projectRoot = path33.dirname(filename);
3294
+ const report3 = (message) => {
3295
+ context.report({
3296
+ node: context.sourceCode.ast,
3297
+ loc: { line: 1, column: 0 },
3298
+ message
3299
+ });
3300
+ };
3242
3301
  return {
3243
- Program(node) {
3244
- const content = context.sourceCode.getText();
3245
- if (!content.includes("zirka")) {
3246
- context.report({
3247
- node,
3248
- loc: { line: 1, column: 0 },
3249
- message: "ESLint config must reference zirka. Use the pasika/zirka baseline configuration."
3250
- });
3302
+ Program() {
3303
+ if (!referencesZirka(context.sourceCode)) {
3304
+ report3(
3305
+ 'ESLint config must take its configuration from zirka (import { styleguide } from "zirka") instead of restating rules locally.'
3306
+ );
3251
3307
  }
3252
- const projectRoot = path33.dirname(filename);
3253
- if (!fs4.existsSync(path33.join(projectRoot, "tsconfig.json"))) {
3254
- context.report({
3255
- node,
3256
- loc: { line: 1, column: 0 },
3257
- message: "No tsconfig.json found. Create one extending the pasika baseline."
3258
- });
3308
+ const tsconfigPath = path33.join(projectRoot, "tsconfig.json");
3309
+ if (!fs4.existsSync(tsconfigPath)) {
3310
+ report3('No tsconfig.json found. Create one extending the zirka TypeScript base config ("zirka/typescript").');
3311
+ } else {
3312
+ let extendsValue;
3313
+ try {
3314
+ const parsed = JSON.parse(fs4.readFileSync(tsconfigPath, "utf8"));
3315
+ extendsValue = typeof parsed === "object" && parsed !== null && "extends" in parsed ? parsed.extends : void 0;
3316
+ } catch {
3317
+ report3(
3318
+ 'tsconfig.json must be valid JSON and extend the zirka TypeScript base config ("zirka/typescript").'
3319
+ );
3320
+ return;
3321
+ }
3322
+ if (typeof extendsValue !== "string" || !extendsValue.startsWith("zirka")) {
3323
+ report3('tsconfig.json must extend the zirka TypeScript base config ("zirka/typescript").');
3324
+ }
3325
+ }
3326
+ const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs4.existsSync(path33.join(projectRoot, name)));
3327
+ if (!prettierConfigFile) {
3328
+ report3(
3329
+ "No prettier config found. Create one that takes its configuration from zirka (styleguide({ prettier: true }).prettierConfig)."
3330
+ );
3331
+ } else {
3332
+ const content = fs4.readFileSync(path33.join(projectRoot, prettierConfigFile), "utf8");
3333
+ if (!content.includes("zirka")) {
3334
+ report3(
3335
+ "The prettier config must take its configuration from zirka (styleguide({ prettier: true }).prettierConfig) instead of restating it locally."
3336
+ );
3337
+ }
3259
3338
  }
3260
3339
  }
3261
3340
  };
3262
3341
  }
3263
3342
  };
3343
+ function referencesZirka(sourceCode) {
3344
+ for (const statement of sourceCode.ast.body) {
3345
+ if (statement.type === "ImportDeclaration" && typeof statement.source.value === "string" && statement.source.value.startsWith("zirka")) {
3346
+ return true;
3347
+ }
3348
+ }
3349
+ return /require\(\s*["']zirka["']\s*\)/.test(sourceCode.getText());
3350
+ }
3351
+
3352
+ // constants/rfc2119.ts
3353
+ var RFC_2119_KEYWORDS = ["MUST NOT", "MUST", "SHOULD NOT", "SHOULD", "MAY"];
3354
+ var RFC_2119_PATTERN = new RegExp(`\\b(?<keyword>${RFC_2119_KEYWORDS.join("|")})\\b`);
3264
3355
 
3265
- // eslint/rules/md/helpers.ts
3266
- var RFC_PATTERN = /\b(?<keyword>MUST NOT|MUST|SHALL NOT|SHALL|SHOULD NOT|SHOULD|MAY|RECOMMENDED|NOT RECOMMENDED|OPTIONAL|REQUIRED)\b/;
3356
+ // eslint/rules/documentation/helpers.ts
3267
3357
  function containsRfcKeyword(text) {
3268
- const match = RFC_PATTERN.exec(text);
3358
+ const match = RFC_2119_PATTERN.exec(text);
3269
3359
  return match?.groups?.keyword ?? null;
3270
3360
  }
3271
3361
  function getFilename(context) {
@@ -3282,7 +3372,7 @@ function getLine(node) {
3282
3372
  return node.position?.start.line ?? 0;
3283
3373
  }
3284
3374
 
3285
- // eslint/rules/md/doc-kind-suffix.ts
3375
+ // eslint/rules/documentation/doc-kind-suffix.ts
3286
3376
  var docKindSuffixRule = {
3287
3377
  meta: {
3288
3378
  type: "problem",
@@ -3308,7 +3398,7 @@ var docKindSuffixRule = {
3308
3398
  }
3309
3399
  };
3310
3400
 
3311
- // eslint/rules/md/title-matches-file-name.ts
3401
+ // eslint/rules/documentation/title-matches-file-name.ts
3312
3402
  import path34 from "path";
3313
3403
  function toExpectedFileName(title) {
3314
3404
  return `${title.toLowerCase().replaceAll(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "")}.md`;
@@ -3346,90 +3436,10 @@ var titleMatchesFileNameRule = {
3346
3436
  }
3347
3437
  };
3348
3438
 
3349
- // eslint/rules/md/overview-present.ts
3350
- var overviewPresentRule = {
3351
- meta: {
3352
- type: "problem",
3353
- docs: {
3354
- description: "Overview must follow the title in a documentation file.",
3355
- recommended: true
3356
- }
3357
- },
3358
- create(context) {
3359
- return {
3360
- root(node) {
3361
- const filename = getFilename(context);
3362
- if (!filename.endsWith(".md")) return;
3363
- let titleLine = 0;
3364
- for (const child of node.children) {
3365
- if (child.type === "heading" && child.depth === 1) {
3366
- titleLine = getLine(child);
3367
- break;
3368
- }
3369
- }
3370
- if (!titleLine) return;
3371
- let hasOverview = false;
3372
- for (const child of node.children) {
3373
- if (child.type === "paragraph" && getLine(child) > titleLine && getTextContent(child).trim()) {
3374
- hasOverview = true;
3375
- break;
3376
- }
3377
- }
3378
- if (!hasOverview) {
3379
- context.report({
3380
- node,
3381
- message: "no overview follows the title"
3382
- });
3383
- }
3384
- }
3385
- };
3386
- }
3387
- };
3388
-
3389
- // eslint/rules/md/overview-length.ts
3439
+ // eslint/rules/documentation/overview.ts
3390
3440
  function countSentences(text) {
3391
3441
  return text.split(/[.!?](?:\s+|$)/).filter((part) => part.trim() !== "").length;
3392
3442
  }
3393
- var overviewLengthRule = {
3394
- meta: {
3395
- type: "problem",
3396
- docs: {
3397
- description: "Overview must contain at most two sentences.",
3398
- recommended: true
3399
- }
3400
- },
3401
- create(context) {
3402
- return {
3403
- root(node) {
3404
- const filename = getFilename(context);
3405
- if (!filename.endsWith(".md")) return;
3406
- let titleLine = 0;
3407
- for (const child of node.children) {
3408
- if (child.type === "heading" && child.depth === 1) {
3409
- titleLine = getLine(child);
3410
- break;
3411
- }
3412
- }
3413
- if (!titleLine) return;
3414
- for (const child of node.children) {
3415
- if (child.type !== "paragraph" || getLine(child) <= titleLine) continue;
3416
- const text = getTextContent(child).trim();
3417
- if (!text || text.startsWith("#")) continue;
3418
- const sentenceCount = countSentences(text);
3419
- if (sentenceCount > 2) {
3420
- context.report({
3421
- node: child,
3422
- message: `overview uses ${String(sentenceCount)} sentences, at most two are allowed`
3423
- });
3424
- }
3425
- break;
3426
- }
3427
- }
3428
- };
3429
- }
3430
- };
3431
-
3432
- // eslint/rules/md/guide-overview-no-links.ts
3433
3443
  function containsLink(node) {
3434
3444
  if (node.type === "link") return true;
3435
3445
  if ("children" in node) {
@@ -3437,11 +3447,11 @@ function containsLink(node) {
3437
3447
  }
3438
3448
  return false;
3439
3449
  }
3440
- var guideOverviewNoLinksRule = {
3450
+ var overviewRule = {
3441
3451
  meta: {
3442
3452
  type: "problem",
3443
3453
  docs: {
3444
- description: "Guide overview must not link to other documents.",
3454
+ description: "Overview must exist, contain at most two sentences, and not link to other documents.",
3445
3455
  recommended: true
3446
3456
  }
3447
3457
  },
@@ -3449,7 +3459,7 @@ var guideOverviewNoLinksRule = {
3449
3459
  return {
3450
3460
  root(node) {
3451
3461
  const filename = getFilename(context);
3452
- if (!filename.endsWith("-guide.md")) return;
3462
+ if (!filename.endsWith(".md")) return;
3453
3463
  let titleLine = 0;
3454
3464
  for (const child of node.children) {
3455
3465
  if (child.type === "heading" && child.depth === 1) {
@@ -3458,24 +3468,38 @@ var guideOverviewNoLinksRule = {
3458
3468
  }
3459
3469
  }
3460
3470
  if (!titleLine) return;
3471
+ let sentenceCount = 0;
3472
+ let found = false;
3461
3473
  for (const child of node.children) {
3474
+ if (child.type === "heading" && getLine(child) > titleLine) break;
3462
3475
  if (child.type !== "paragraph" || getLine(child) <= titleLine) continue;
3463
3476
  const text = getTextContent(child).trim();
3464
3477
  if (!text || text.startsWith("#")) continue;
3478
+ found = true;
3465
3479
  if (containsLink(child)) {
3466
3480
  context.report({
3467
3481
  node: child,
3468
- message: "guide overview links another document"
3482
+ message: "overview links another document"
3469
3483
  });
3470
3484
  }
3471
- break;
3485
+ sentenceCount += countSentences(text);
3486
+ if (sentenceCount > 2) {
3487
+ context.report({
3488
+ node: child,
3489
+ message: `overview uses ${String(sentenceCount)} sentences, at most two are allowed`
3490
+ });
3491
+ break;
3492
+ }
3493
+ }
3494
+ if (!found) {
3495
+ context.report({ node, message: "no overview follows the title" });
3472
3496
  }
3473
3497
  }
3474
3498
  };
3475
3499
  }
3476
3500
  };
3477
3501
 
3478
- // eslint/rules/md/guide-step-single-sentence.ts
3502
+ // eslint/rules/documentation/guide-step-single-sentence.ts
3479
3503
  function countSentences2(text) {
3480
3504
  return text.split(/[.!?](?:\s+|$)/).filter((part) => part.trim() !== "").length;
3481
3505
  }
@@ -3513,7 +3537,7 @@ var guideStepSingleSentenceRule = {
3513
3537
  }
3514
3538
  };
3515
3539
 
3516
- // eslint/rules/md/guide-step-single-link.ts
3540
+ // eslint/rules/documentation/guide-step-single-link.ts
3517
3541
  function countDocLinks(node) {
3518
3542
  if (node.type === "link" && node.url.endsWith(".md")) return 1;
3519
3543
  if ("children" in node) {
@@ -3556,7 +3580,7 @@ var guideStepSingleLinkRule = {
3556
3580
  }
3557
3581
  };
3558
3582
 
3559
- // eslint/rules/md/guide-states-no-requirement.ts
3583
+ // eslint/rules/documentation/guide-states-no-requirement.ts
3560
3584
  var guideStatesNoRequirementRule = {
3561
3585
  meta: {
3562
3586
  type: "problem",
@@ -3582,7 +3606,7 @@ var guideStatesNoRequirementRule = {
3582
3606
  }
3583
3607
  };
3584
3608
 
3585
- // eslint/rules/md/requirement-present.ts
3609
+ // eslint/rules/documentation/requirement-present.ts
3586
3610
  function hasRequirement(node) {
3587
3611
  if (node.type === "listItem") {
3588
3612
  if (containsRfcKeyword(getTextContent(node))) return true;
@@ -3621,7 +3645,7 @@ var requirementPresentRule = {
3621
3645
  }
3622
3646
  };
3623
3647
 
3624
- // eslint/rules/md/rule-paired-examples.ts
3648
+ // eslint/rules/documentation/rule-paired-examples.ts
3625
3649
  var rulePairedExamplesRule = {
3626
3650
  meta: {
3627
3651
  type: "problem",
@@ -3657,7 +3681,7 @@ var rulePairedExamplesRule = {
3657
3681
  }
3658
3682
  };
3659
3683
 
3660
- // eslint/rules/md/example-heading-description.ts
3684
+ // eslint/rules/documentation/example-heading-description.ts
3661
3685
  var exampleHeadingDescriptionRule = {
3662
3686
  meta: {
3663
3687
  type: "problem",
@@ -3685,7 +3709,7 @@ var exampleHeadingDescriptionRule = {
3685
3709
  }
3686
3710
  };
3687
3711
 
3688
- // eslint/rules/md/policy-no-examples.ts
3712
+ // eslint/rules/documentation/policy-no-examples.ts
3689
3713
  var policyNoExamplesRule = {
3690
3714
  meta: {
3691
3715
  type: "problem",
@@ -3712,7 +3736,7 @@ var policyNoExamplesRule = {
3712
3736
  }
3713
3737
  };
3714
3738
 
3715
- // eslint/rules/md/no-cross-document-link.ts
3739
+ // eslint/rules/documentation/no-cross-document-link.ts
3716
3740
  function linkedKind(filename) {
3717
3741
  if (filename.endsWith("-rule.md")) return "rule";
3718
3742
  if (filename.endsWith("-reference.md")) return "reference";
@@ -3744,7 +3768,7 @@ var noCrossDocumentLinkRule = {
3744
3768
  }
3745
3769
  };
3746
3770
 
3747
- // eslint/rules/md/reference-no-rfc-vocabulary.ts
3771
+ // eslint/rules/documentation/reference-no-rfc-vocabulary.ts
3748
3772
  var referenceNoRfcVocabularyRule = {
3749
3773
  meta: {
3750
3774
  type: "problem",
@@ -3770,7 +3794,7 @@ var referenceNoRfcVocabularyRule = {
3770
3794
  }
3771
3795
  };
3772
3796
 
3773
- // eslint/rules/md/reference-block-headings.ts
3797
+ // eslint/rules/documentation/reference-block-headings.ts
3774
3798
  var referenceBlockHeadingsRule = {
3775
3799
  meta: {
3776
3800
  type: "problem",
@@ -3801,7 +3825,7 @@ var referenceBlockHeadingsRule = {
3801
3825
  }
3802
3826
  };
3803
3827
 
3804
- // eslint/rules/md/support-document-placement.ts
3828
+ // eslint/rules/documentation/support-document-placement.ts
3805
3829
  import path35 from "path";
3806
3830
  var supportDocumentPlacementRule = {
3807
3831
  meta: {
@@ -3834,7 +3858,7 @@ var supportDocumentPlacementRule = {
3834
3858
  }
3835
3859
  };
3836
3860
 
3837
- // eslint/rules/md/no-template-prompt.ts
3861
+ // eslint/rules/documentation/no-template-prompt.ts
3838
3862
  var TEMPLATE_PROMPT = /^\s*\[[A-Z0-9].*\]\s*$/;
3839
3863
  var noTemplatePromptRule = {
3840
3864
  meta: {
@@ -3858,10 +3882,10 @@ var noTemplatePromptRule = {
3858
3882
  }
3859
3883
  };
3860
3884
 
3861
- // eslint/rules/md/guide-folder-entry-point.ts
3885
+ // eslint/rules/documentation/guide-folder-entry-point.ts
3862
3886
  import path37 from "path";
3863
3887
 
3864
- // eslint/rules/md/project-index.ts
3888
+ // eslint/rules/documentation/project-index.ts
3865
3889
  import { readdirSync as readdirSync2, readFileSync as readFileSync4, statSync as statSync3 } from "fs";
3866
3890
  import path36 from "path";
3867
3891
  var KIND_BY_SUFFIX = [
@@ -3915,7 +3939,7 @@ function findDocsRoot(filePath) {
3915
3939
  }
3916
3940
  }
3917
3941
 
3918
- // eslint/rules/md/guide-folder-entry-point.ts
3942
+ // eslint/rules/documentation/guide-folder-entry-point.ts
3919
3943
  var guideFolderEntryPointRule = {
3920
3944
  meta: {
3921
3945
  type: "problem",
@@ -3953,7 +3977,7 @@ var guideFolderEntryPointRule = {
3953
3977
  }
3954
3978
  };
3955
3979
 
3956
- // eslint/rules/md/rfc-only-in-bullets.ts
3980
+ // eslint/rules/documentation/rfc-only-in-bullets.ts
3957
3981
  function checkOutsideBullets(node, context, insideBullet) {
3958
3982
  if (node.type === "listItem") {
3959
3983
  for (const child of node.children) {
@@ -3996,7 +4020,7 @@ var rfcOnlyInBulletsRule = {
3996
4020
  }
3997
4021
  };
3998
4022
 
3999
- // eslint/rules/md/rfc-keyword-in-every-bullet.ts
4023
+ // eslint/rules/documentation/rfc-keyword-in-every-bullet.ts
4000
4024
  function checkBullets(node, context) {
4001
4025
  if (node.type === "listItem" && !containsRfcKeyword(getTextContent(node))) {
4002
4026
  context.report({
@@ -4029,7 +4053,7 @@ var rfcKeywordInEveryBulletRule = {
4029
4053
  }
4030
4054
  };
4031
4055
 
4032
- // eslint/rules/md/policy-subject-headings.ts
4056
+ // eslint/rules/documentation/policy-subject-headings.ts
4033
4057
  var policySubjectHeadingsRule = {
4034
4058
  meta: {
4035
4059
  type: "problem",
@@ -4082,7 +4106,7 @@ var policySubjectHeadingsRule = {
4082
4106
  }
4083
4107
  };
4084
4108
 
4085
- // eslint/rules/md/guide-link-anchors.ts
4109
+ // eslint/rules/documentation/guide-link-anchors.ts
4086
4110
  function visitSteps2(node, check) {
4087
4111
  if (node.type === "list" && node.ordered) {
4088
4112
  for (const child of node.children) check(child);
@@ -4126,7 +4150,7 @@ var guideLinkAnchorsRule = {
4126
4150
  }
4127
4151
  };
4128
4152
 
4129
- // eslint/rules/md/no-nested-how-to.ts
4153
+ // eslint/rules/documentation/no-nested-how-to.ts
4130
4154
  var noNestedHowToRule = {
4131
4155
  meta: {
4132
4156
  type: "problem",
@@ -4162,7 +4186,7 @@ var noNestedHowToRule = {
4162
4186
  }
4163
4187
  };
4164
4188
 
4165
- // eslint/rules/md/glossary-term-linking.ts
4189
+ // eslint/rules/documentation/glossary-term-linking.ts
4166
4190
  import { readFileSync as readFileSync5 } from "fs";
4167
4191
  import path38 from "path";
4168
4192
  function extractGlossaryTerms(filePath) {
@@ -4243,13 +4267,91 @@ var glossaryTermLinkingRule = {
4243
4267
  }
4244
4268
  };
4245
4269
 
4246
- // eslint/rules/md/index.ts
4247
- var mdRules = {
4270
+ // eslint/rules/documentation/guide-mentions-documents.ts
4271
+ import { existsSync } from "fs";
4272
+ import path39 from "path";
4273
+ function visitSteps3(node, check) {
4274
+ if (node.type === "list" && node.ordered) {
4275
+ for (const child of node.children) check(child);
4276
+ }
4277
+ if ("children" in node) {
4278
+ for (const child of node.children) visitSteps3(child, check);
4279
+ }
4280
+ }
4281
+ function collectMarkdownLinks(node, out) {
4282
+ if (node.type === "link" && node.url.endsWith(".md")) out.push(node);
4283
+ if ("children" in node) {
4284
+ for (const child of node.children) collectMarkdownLinks(child, out);
4285
+ }
4286
+ }
4287
+ function linkTarget(url) {
4288
+ return url.split("#")[0] ?? url;
4289
+ }
4290
+ var guideMentionsDocumentsRule = {
4291
+ meta: {
4292
+ type: "problem",
4293
+ docs: {
4294
+ description: "A Guide entry point must reference each owned Rule from a How To step, mention every Reference, and not link a missing document.",
4295
+ recommended: true
4296
+ }
4297
+ },
4298
+ create(context) {
4299
+ return {
4300
+ root(node) {
4301
+ const filename = getFilename(context);
4302
+ if (!filename.endsWith("-guide.md")) return;
4303
+ const docsRoot = findDocsRoot(filename);
4304
+ if (!docsRoot) return;
4305
+ const guideDir = path39.dirname(filename);
4306
+ if (path39.basename(filename, ".md") !== path39.basename(guideDir)) return;
4307
+ const docs = getProjectDocs(docsRoot);
4308
+ const owned = docs.filter((doc) => {
4309
+ const parent = path39.dirname(doc.filePath);
4310
+ return parent === path39.join(guideDir, "rules") || parent === path39.join(guideDir, "references");
4311
+ });
4312
+ const allLinks = [];
4313
+ collectMarkdownLinks(node, allLinks);
4314
+ const stepLinks = [];
4315
+ visitSteps3(node, (item) => {
4316
+ collectMarkdownLinks(item, stepLinks);
4317
+ });
4318
+ const mentionsOf = (links, fileName) => links.some((link) => link.url.split("/").pop() === fileName);
4319
+ for (const doc of owned) {
4320
+ if (doc.kind === "rule") {
4321
+ if (!mentionsOf(stepLinks, doc.fileName)) {
4322
+ context.report({
4323
+ node,
4324
+ message: `Guide entry point does not reference a Rule it owns from a How To step: ${doc.doc}`
4325
+ });
4326
+ }
4327
+ } else if (!mentionsOf(allLinks, doc.fileName)) {
4328
+ context.report({
4329
+ node,
4330
+ message: `Guide entry point does not mention a document it owns: ${doc.doc}`
4331
+ });
4332
+ }
4333
+ }
4334
+ for (const link of allLinks) {
4335
+ const target = linkTarget(link.url);
4336
+ if (!target.endsWith(".md")) continue;
4337
+ const resolved = path39.normalize(path39.join(guideDir, target));
4338
+ if (!existsSync(resolved)) {
4339
+ context.report({
4340
+ node: link,
4341
+ message: `Guide links a document that does not exist: ${link.url}`
4342
+ });
4343
+ }
4344
+ }
4345
+ }
4346
+ };
4347
+ }
4348
+ };
4349
+
4350
+ // eslint/rules/documentation/index.ts
4351
+ var documentationRules = {
4248
4352
  "doc-kind-suffix": docKindSuffixRule,
4249
4353
  "title-matches-file-name": titleMatchesFileNameRule,
4250
- "overview-present": overviewPresentRule,
4251
- "overview-length": overviewLengthRule,
4252
- "guide-overview-no-links": guideOverviewNoLinksRule,
4354
+ overview: overviewRule,
4253
4355
  "guide-step-single-sentence": guideStepSingleSentenceRule,
4254
4356
  "guide-step-single-link": guideStepSingleLinkRule,
4255
4357
  "guide-states-no-requirement": guideStatesNoRequirementRule,
@@ -4268,10 +4370,11 @@ var mdRules = {
4268
4370
  "policy-subject-headings": policySubjectHeadingsRule,
4269
4371
  "guide-link-anchors": guideLinkAnchorsRule,
4270
4372
  "no-nested-how-to": noNestedHowToRule,
4271
- "glossary-term-linking": glossaryTermLinkingRule
4373
+ "glossary-term-linking": glossaryTermLinkingRule,
4374
+ "guide-mentions-documents": guideMentionsDocumentsRule
4272
4375
  };
4273
4376
 
4274
- // eslint/rules/css/helpers.ts
4377
+ // eslint/rules/tailwind/helpers.ts
4275
4378
  function walkNodes(node, visit) {
4276
4379
  visit(node);
4277
4380
  if ("children" in node && node.children) {
@@ -4328,7 +4431,7 @@ function selectorNames(node) {
4328
4431
  return names;
4329
4432
  }
4330
4433
 
4331
- // eslint/rules/css/theme-reset.ts
4434
+ // eslint/rules/tailwind/theme-reset.ts
4332
4435
  var themeResetRule = {
4333
4436
  meta: {
4334
4437
  schema: [],
@@ -4358,7 +4461,7 @@ var themeResetRule = {
4358
4461
  }
4359
4462
  };
4360
4463
 
4361
- // eslint/rules/css/root-variables.ts
4464
+ // eslint/rules/tailwind/root-variables.ts
4362
4465
  var rootVariablesRule = {
4363
4466
  meta: {
4364
4467
  schema: [],
@@ -4401,7 +4504,7 @@ var rootVariablesRule = {
4401
4504
  }
4402
4505
  };
4403
4506
 
4404
- // eslint/rules/css/apply-usage.ts
4507
+ // eslint/rules/tailwind/apply-usage.ts
4405
4508
  var applyUsageRule = {
4406
4509
  meta: {
4407
4510
  schema: [],
@@ -4431,7 +4534,7 @@ var applyUsageRule = {
4431
4534
  }
4432
4535
  };
4433
4536
 
4434
- // eslint/rules/css/base-layer-pair.ts
4537
+ // eslint/rules/tailwind/base-layer-pair.ts
4435
4538
  var baseLayerPairRule = {
4436
4539
  meta: {
4437
4540
  schema: [],
@@ -4469,7 +4572,7 @@ var baseLayerPairRule = {
4469
4572
  }
4470
4573
  };
4471
4574
 
4472
- // eslint/rules/css/stylesheet-ordering.ts
4575
+ // eslint/rules/tailwind/stylesheet-ordering.ts
4473
4576
  var SECTION_ORDER = ["imports", "custom-variant", "root", "theme", "utility", "base styles", "keyframes"];
4474
4577
  var stylesheetOrderingRule = {
4475
4578
  meta: {
@@ -4526,7 +4629,7 @@ var stylesheetOrderingRule = {
4526
4629
  }
4527
4630
  };
4528
4631
 
4529
- // eslint/rules/css/css-variable-naming.ts
4632
+ // eslint/rules/tailwind/css-variable-naming.ts
4530
4633
  var cssVariableNamingRule = {
4531
4634
  meta: {
4532
4635
  schema: [],
@@ -4558,7 +4661,7 @@ var cssVariableNamingRule = {
4558
4661
  }
4559
4662
  };
4560
4663
 
4561
- // eslint/rules/css/custom-utility-apply.ts
4664
+ // eslint/rules/tailwind/custom-utility-apply.ts
4562
4665
  function rawProperty(raw) {
4563
4666
  const match = /^\s*(?<property>[a-z][a-z-]*)\s*:/.exec(raw);
4564
4667
  return match?.groups?.property;
@@ -4600,7 +4703,7 @@ var customUtilityApplyRule = {
4600
4703
  }
4601
4704
  };
4602
4705
 
4603
- // eslint/rules/css/surface-utility.ts
4706
+ // eslint/rules/tailwind/surface-utility.ts
4604
4707
  var surfaceUtilityRule = {
4605
4708
  meta: {
4606
4709
  schema: [],
@@ -4633,7 +4736,7 @@ var surfaceUtilityRule = {
4633
4736
  }
4634
4737
  };
4635
4738
 
4636
- // eslint/rules/css/theme-variable-namespace.ts
4739
+ // eslint/rules/tailwind/theme-variable-namespace.ts
4637
4740
  var themeVariableNamespaceRule = {
4638
4741
  meta: {
4639
4742
  schema: [],
@@ -4672,7 +4775,7 @@ var themeVariableNamespaceRule = {
4672
4775
  }
4673
4776
  };
4674
4777
 
4675
- // eslint/rules/css/global-css-location.ts
4778
+ // eslint/rules/tailwind/global-css-location.ts
4676
4779
  var globalCssLocationRule = {
4677
4780
  meta: {
4678
4781
  schema: [],
@@ -4703,7 +4806,7 @@ var globalCssLocationRule = {
4703
4806
  }
4704
4807
  };
4705
4808
 
4706
- // eslint/rules/css/global-stylesheet.ts
4809
+ // eslint/rules/tailwind/global-stylesheet.ts
4707
4810
  var globalStylesheetRule = {
4708
4811
  meta: {
4709
4812
  schema: [],
@@ -4736,8 +4839,8 @@ var globalStylesheetRule = {
4736
4839
  }
4737
4840
  };
4738
4841
 
4739
- // eslint/rules/css/index.ts
4740
- var cssRules = {
4842
+ // eslint/rules/tailwind/index.ts
4843
+ var tailwindRules = {
4741
4844
  "theme-reset": themeResetRule,
4742
4845
  "root-variables": rootVariablesRule,
4743
4846
  "apply-usage": applyUsageRule,
@@ -4751,10 +4854,50 @@ var cssRules = {
4751
4854
  "global-stylesheet": globalStylesheetRule
4752
4855
  };
4753
4856
 
4754
- // eslint/rules/json/no-vulyk-dependency.ts
4857
+ // eslint/rules/package-json/exact-version.ts
4755
4858
  function memberName(member) {
4756
4859
  return member.name.type === "String" ? member.name.value : member.name.name;
4757
4860
  }
4861
+ var EXACT_VERSION_PATTERN = /^\d+\.\d+\.\d+$/;
4862
+ function memberValue(member) {
4863
+ return member.value.type === "String" ? member.value.value : null;
4864
+ }
4865
+ var exactVersionRule = {
4866
+ meta: {
4867
+ schema: [],
4868
+ type: "problem",
4869
+ docs: {
4870
+ description: "Require dependency and devDependency versions to be pinned exactly."
4871
+ }
4872
+ },
4873
+ create(context) {
4874
+ return {
4875
+ Document(node) {
4876
+ const root = node.body;
4877
+ if (root.type !== "Object") return;
4878
+ for (const key of ["dependencies", "devDependencies"]) {
4879
+ const section = root.members.find((member) => memberName(member) === key);
4880
+ if (section?.value.type !== "Object") continue;
4881
+ for (const member of section.value.members) {
4882
+ const version = memberValue(member);
4883
+ if (version === null) continue;
4884
+ if (!EXACT_VERSION_PATTERN.test(version)) {
4885
+ context.report({
4886
+ node: member,
4887
+ message: `${memberName(member)} must pin an exact version (e.g. "1.2.3"), not a range or cap such as "${version}".`
4888
+ });
4889
+ }
4890
+ }
4891
+ }
4892
+ }
4893
+ };
4894
+ }
4895
+ };
4896
+
4897
+ // eslint/rules/package-json/no-vulyk-dependency.ts
4898
+ function memberName2(member) {
4899
+ return member.name.type === "String" ? member.name.value : member.name.name;
4900
+ }
4758
4901
  var noVulykDependencyRule = {
4759
4902
  meta: {
4760
4903
  schema: [],
@@ -4769,9 +4912,9 @@ var noVulykDependencyRule = {
4769
4912
  const root = node.body;
4770
4913
  if (root.type !== "Object") return;
4771
4914
  for (const key of ["dependencies", "devDependencies"]) {
4772
- const section = root.members.find((member) => memberName(member) === key);
4915
+ const section = root.members.find((member) => memberName2(member) === key);
4773
4916
  if (section?.value.type !== "Object") continue;
4774
- const vulyk = section.value.members.find((member) => memberName(member) === "vulyk");
4917
+ const vulyk = section.value.members.find((member) => memberName2(member) === "vulyk");
4775
4918
  if (vulyk) {
4776
4919
  context.report({
4777
4920
  node: vulyk,
@@ -4784,16 +4927,39 @@ var noVulykDependencyRule = {
4784
4927
  }
4785
4928
  };
4786
4929
 
4787
- // eslint/rules/json/zirka-installed.ts
4788
- function memberName2(member) {
4930
+ // eslint/rules/package-json/nextjs-stack.ts
4931
+ var NEXTJS_STACK_DEPENDENCIES = [
4932
+ "next",
4933
+ "react",
4934
+ "react-dom",
4935
+ "zod",
4936
+ "class-variance-authority",
4937
+ "clsx",
4938
+ "tailwind-merge"
4939
+ ];
4940
+ var NEXTJS_STACK_DEV_DEPENDENCIES = [
4941
+ "typescript",
4942
+ "tailwindcss",
4943
+ "eslint",
4944
+ "prettier",
4945
+ "husky",
4946
+ "lint-staged",
4947
+ "zirka"
4948
+ ];
4949
+ function memberName3(member) {
4789
4950
  return member.name.type === "String" ? member.name.value : member.name.name;
4790
4951
  }
4791
- var zirkaInstalledRule = {
4952
+ function sectionPackages(root, section) {
4953
+ const member = root.type === "Object" ? root.members.find((entry) => memberName3(entry) === section) : void 0;
4954
+ if (member?.value.type !== "Object") return /* @__PURE__ */ new Set();
4955
+ return new Set(member.value.members.map(memberName3));
4956
+ }
4957
+ var nextjsStackRule = {
4792
4958
  meta: {
4793
4959
  schema: [],
4794
4960
  type: "problem",
4795
4961
  docs: {
4796
- description: "Require zirka to be listed in package.json as a devDependency."
4962
+ description: "Require the framework's runtime packages in dependencies and toolchain packages in devDependencies."
4797
4963
  }
4798
4964
  },
4799
4965
  create(context) {
@@ -4801,18 +4967,20 @@ var zirkaInstalledRule = {
4801
4967
  Document(node) {
4802
4968
  const root = node.body;
4803
4969
  if (root.type !== "Object") return;
4804
- const allDeps = [];
4805
- for (const key of ["dependencies", "devDependencies"]) {
4806
- const section = root.members.find((member) => memberName2(member) === key);
4807
- if (section?.value.type !== "Object") continue;
4808
- for (const member of section.value.members) {
4809
- allDeps.push(memberName2(member));
4810
- }
4970
+ const dependencies = sectionPackages(root, "dependencies");
4971
+ const devDependencies = sectionPackages(root, "devDependencies");
4972
+ for (const pkg of NEXTJS_STACK_DEPENDENCIES) {
4973
+ if (dependencies.has(pkg)) continue;
4974
+ context.report({
4975
+ node,
4976
+ message: `${pkg} must be listed in package.json as a dependency.`
4977
+ });
4811
4978
  }
4812
- if (!allDeps.includes("zirka")) {
4979
+ for (const pkg of NEXTJS_STACK_DEV_DEPENDENCIES) {
4980
+ if (devDependencies.has(pkg)) continue;
4813
4981
  context.report({
4814
4982
  node,
4815
- message: "zirka must be listed in package.json as a devDependency."
4983
+ message: `${pkg} must be listed in package.json as a devDependency.`
4816
4984
  });
4817
4985
  }
4818
4986
  }
@@ -4820,76 +4988,280 @@ var zirkaInstalledRule = {
4820
4988
  }
4821
4989
  };
4822
4990
 
4823
- // eslint/rules/json/index.ts
4824
- var jsonRules = {
4991
+ // eslint/rules/package-json/index.ts
4992
+ var repoPackageJsonRules = {
4825
4993
  "no-vulyk-dependency": noVulykDependencyRule,
4826
- "zirka-installed": zirkaInstalledRule
4994
+ "exact-version": exactVersionRule
4995
+ };
4996
+ var nextPackageJsonRules = {
4997
+ "nextjs-stack": nextjsStackRule
4998
+ };
4999
+
5000
+ // eslint/rules/husky/husky-hook.ts
5001
+ import { existsSync as existsSync2, readFileSync as readFileSync6 } from "fs";
5002
+ import path40 from "path";
5003
+ function memberName4(member) {
5004
+ return member.name.type === "String" ? member.name.value : member.name.name;
5005
+ }
5006
+ var huskyHookRule = {
5007
+ meta: {
5008
+ schema: [],
5009
+ type: "problem",
5010
+ docs: {
5011
+ description: "Require a pre-commit hook that runs lint-staged, typecheck, and the libyear drift check."
5012
+ }
5013
+ },
5014
+ create(context) {
5015
+ return {
5016
+ Document(node) {
5017
+ const root = node.body;
5018
+ if (root.type !== "Object") return;
5019
+ const scriptName = context.filename;
5020
+ if (!scriptName.endsWith("package.json")) return;
5021
+ const hookPath = path40.join(process.cwd(), ".husky", "pre-commit");
5022
+ if (!existsSync2(hookPath)) {
5023
+ context.report({
5024
+ node,
5025
+ message: "No .husky/pre-commit hook found. Configure husky to run checks before commits."
5026
+ });
5027
+ return;
5028
+ }
5029
+ const content = readFileSync6(hookPath, "utf8");
5030
+ if (!content.includes("lint-staged")) {
5031
+ context.report({ node, message: ".husky/pre-commit must run lint-staged." });
5032
+ }
5033
+ if (!content.includes("typecheck")) {
5034
+ context.report({ node, message: ".husky/pre-commit must run npm run typecheck." });
5035
+ }
5036
+ if (!content.includes("libyear --limit-major-individual=1")) {
5037
+ context.report({ node, message: ".husky/pre-commit must run npx libyear --limit-major-individual=1." });
5038
+ }
5039
+ const scripts = root.members.find((member) => memberName4(member) === "scripts");
5040
+ if (scripts?.value.type === "Object") {
5041
+ const prepare = scripts.value.members.find((member) => memberName4(member) === "prepare");
5042
+ if (prepare?.value.type === "String" && !prepare.value.value.includes("husky")) {
5043
+ context.report({
5044
+ node: prepare,
5045
+ message: 'package.json "prepare" script must run husky (e.g. "prepare": "husky").'
5046
+ });
5047
+ }
5048
+ }
5049
+ }
5050
+ };
5051
+ }
5052
+ };
5053
+
5054
+ // eslint/rules/husky/index.ts
5055
+ var huskyRules = {
5056
+ "husky-hook": huskyHookRule
5057
+ };
5058
+
5059
+ // eslint/rules/vulyk/vulyk-docs.ts
5060
+ import { existsSync as existsSync3, readFileSync as readFileSync7 } from "fs";
5061
+ import path41 from "path";
5062
+ var PASIKA_REPO = "Bredansky/pasika";
5063
+ var vulykDocsRule = {
5064
+ meta: {
5065
+ schema: [],
5066
+ type: "problem",
5067
+ docs: {
5068
+ description: "Require vulyk.config.ts to track the framework's docs from pasika and the generated AGENTS.md."
5069
+ }
5070
+ },
5071
+ create(context) {
5072
+ return {
5073
+ Document(node) {
5074
+ if (!context.filename.endsWith("package.json")) return;
5075
+ const projectRoot = path41.dirname(path41.resolve(context.filename));
5076
+ const configPath = path41.join(projectRoot, "vulyk.config.ts");
5077
+ if (!existsSync3(configPath)) {
5078
+ context.report({
5079
+ node,
5080
+ message: "No vulyk.config.ts found. Run npx vulyk@latest init to create one that tracks the framework's docs."
5081
+ });
5082
+ return;
5083
+ }
5084
+ const config = readFileSync7(configPath, "utf8");
5085
+ if (!config.includes(PASIKA_REPO)) {
5086
+ context.report({
5087
+ node,
5088
+ message: "vulyk.config.ts must track the framework's docs from the pasika repository."
5089
+ });
5090
+ }
5091
+ const agentsPath = path41.join(projectRoot, "AGENTS.md");
5092
+ if (!existsSync3(agentsPath)) {
5093
+ context.report({
5094
+ node,
5095
+ message: "No AGENTS.md found. Run npx vulyk@latest agents to generate the agent file that routes to the tracked docs."
5096
+ });
5097
+ }
5098
+ }
5099
+ };
5100
+ }
5101
+ };
5102
+
5103
+ // eslint/rules/vulyk/index.ts
5104
+ var vulykRules = {
5105
+ "vulyk-docs": vulykDocsRule
4827
5106
  };
4828
5107
 
4829
5108
  // eslint/index.ts
4830
- var pasikaRules = {
4831
- "component-placement": componentPlacementRule,
4832
- "support-file-placement": supportFilePlacementRule,
4833
- "application-structure": applicationStructureRule,
5109
+ var typescriptAppRules = {
5110
+ "filename-case": filenameCaseRule,
5111
+ "import-boundaries": importBoundariesRule,
4834
5112
  "named-exports": namedExportsRule,
4835
- "data-testid-case": dataTestIdCaseRule,
5113
+ "support-file-placement": supportFilePlacementRule,
4836
5114
  "support-folder-shape": supportFolderShapeRule,
4837
5115
  "import-through-index": importThroughIndexRule,
4838
5116
  "util-file-name": utilFileNameRule,
4839
5117
  "no-util-barrel": noUtilBarrelRule,
5118
+ "enforce-barrel-exports": enforceBarrelExportsRule,
5119
+ "config-extraction": configExtractionRule,
5120
+ "value-extraction": valueExtractionRule,
5121
+ "type-extraction": typeExtractionRule,
5122
+ "zod-schema-validation": zodSchemaValidationRule,
5123
+ "source-under-src": sourceUnderSrcRule,
5124
+ "zirka-baseline": zirkaBaselineRule
5125
+ };
5126
+ var nextjsAppRules = {
5127
+ "component-placement": componentPlacementRule,
5128
+ "application-structure": applicationStructureRule,
5129
+ "data-testid-case": dataTestIdCaseRule,
4840
5130
  "jsx-hygiene": jsxHygieneRule,
4841
5131
  "interactive-component": interactiveComponentRule,
4842
5132
  "ui-state": uiStateRule,
4843
- "filename-case": filenameCaseRule,
4844
- "import-boundaries": importBoundariesRule,
4845
5133
  "no-mixed-concerns": noMixedConcernsRule,
4846
5134
  "no-arbitrary-tailwind": noArbitraryTailwindRule,
4847
5135
  "enforce-cn-merge": enforceCnMergeRule,
5136
+ "cn-helper": cnHelperRule,
4848
5137
  "enforce-cva-variant-props": enforceCvaVariantPropsRule,
4849
5138
  "cva-appearance-props": cvaAppearancePropsRule,
4850
5139
  "cva-boolean-variants": cvaBooleanVariantsRule,
4851
- "enforce-barrel-exports": enforceBarrelExportsRule,
4852
5140
  "cross-feature-import": crossFeatureImportRule,
4853
5141
  "pure-function-extract": pureFunctionExtractRule,
4854
5142
  "hook-complexity": hookComplexityRule,
4855
5143
  "locale-dotted-path": localeDottedPathRule,
4856
5144
  "locales-location": localesLocationRule,
4857
5145
  "hook-extraction": hookExtractionRule,
4858
- "value-extraction": valueExtractionRule,
4859
- "config-extraction": configExtractionRule,
4860
5146
  "component-nesting": componentNestingRule,
4861
5147
  "stay-flat": stayFlatRule,
4862
- "type-extraction": typeExtractionRule,
4863
5148
  "locale-placement": localePlacementRule,
4864
5149
  "sole-state-owner": soleStateOwnerRule,
4865
5150
  "locale-key-shape": localeKeyShapeRule,
4866
5151
  "shared-style-dedup": sharedStyleDedupRule,
4867
- "repeated-structure": repeatedStructureRule,
4868
- "zod-schema-validation": zodSchemaValidationRule,
4869
- "source-under-src": sourceUnderSrcRule,
4870
- "config-baseline": configBaselineRule
5152
+ "repeated-structure": repeatedStructureRule
5153
+ };
5154
+ var pasikaRules = {
5155
+ ...typescriptAppRules,
5156
+ ...nextjsAppRules
4871
5157
  };
4872
- var pasikaRuleIds = Object.keys(pasikaRules).map((name) => `pasika/${name}`);
4873
- var pasikaMdRuleIds = Object.keys(mdRules).map((name) => `pasika/${name}`);
4874
- var pasikaCssRuleIds = Object.keys(cssRules).map((name) => `pasika/${name}`);
4875
- var pasikaJsonRuleIds = Object.keys(jsonRules).map((name) => `pasika/${name}`);
4876
- var allPasikaRuleIds = [...pasikaRuleIds, ...pasikaMdRuleIds, ...pasikaCssRuleIds, ...pasikaJsonRuleIds];
4877
- var pasikaConfig = {
5158
+ function ruleIds(rules2) {
5159
+ return Object.keys(rules2).map((name) => `pasika/${name}`);
5160
+ }
5161
+ var typescriptAppRuleIds = ruleIds(typescriptAppRules);
5162
+ var nextjsAppRuleIds = ruleIds(nextjsAppRules);
5163
+ var pasikaRuleIds = ruleIds(pasikaRules);
5164
+ var documentationRuleIds = ruleIds(documentationRules);
5165
+ var tailwindRuleIds = ruleIds(tailwindRules);
5166
+ var repoPackageJsonRuleIds = ruleIds(repoPackageJsonRules);
5167
+ var nextPackageJsonRuleIds = ruleIds(nextPackageJsonRules);
5168
+ var huskyRuleIds = ruleIds(huskyRules);
5169
+ var vulykRuleIds = ruleIds(vulykRules);
5170
+ var allPasikaRuleIds = [
5171
+ ...pasikaRuleIds,
5172
+ ...documentationRuleIds,
5173
+ ...tailwindRuleIds,
5174
+ ...repoPackageJsonRuleIds,
5175
+ ...nextPackageJsonRuleIds,
5176
+ ...huskyRuleIds,
5177
+ ...vulykRuleIds
5178
+ ];
5179
+ var typescriptAppBlock = {
4878
5180
  files: ["src/**/*.{cjs,cts,js,jsx,mjs,mts,ts,tsx}"],
4879
5181
  plugins: {
4880
- pasika: { rules: pasikaRules }
5182
+ pasika: { rules: typescriptAppRules }
4881
5183
  },
4882
- rules: Object.fromEntries(pasikaRuleIds.map((id) => [id, "error"]))
5184
+ rules: Object.fromEntries(typescriptAppRuleIds.map((id) => [id, "error"]))
4883
5185
  };
5186
+ var nextjsAppBlock = {
5187
+ files: ["src/**/*.{cjs,cts,js,jsx,mjs,mts,ts,tsx}"],
5188
+ plugins: {
5189
+ pasika: { rules: nextjsAppRules }
5190
+ },
5191
+ rules: Object.fromEntries(nextjsAppRuleIds.map((id) => [id, "error"]))
5192
+ };
5193
+ var tailwindGlobalsBlock = {
5194
+ files: ["src/**/globals.css"],
5195
+ plugins: {
5196
+ css,
5197
+ pasika: { rules: tailwindRules }
5198
+ },
5199
+ language: "css/css",
5200
+ languageOptions: { tolerant: true },
5201
+ rules: Object.fromEntries(
5202
+ tailwindRuleIds.filter((id) => id !== "pasika/global-css-location").map((id) => [id, "error"])
5203
+ )
5204
+ };
5205
+ var tailwindAnyCssBlock = {
5206
+ files: ["src/**/*.css"],
5207
+ plugins: {
5208
+ css,
5209
+ pasika: { rules: tailwindRules }
5210
+ },
5211
+ language: "css/css",
5212
+ languageOptions: { tolerant: true },
5213
+ rules: { "pasika/global-css-location": "error" }
5214
+ };
5215
+ var repoManifestBlock = {
5216
+ files: ["package.json"],
5217
+ plugins: {
5218
+ json: { languages: { json: jsonPlugin.languages.json } },
5219
+ pasika: { rules: { ...repoPackageJsonRules, ...huskyRules, ...vulykRules } }
5220
+ },
5221
+ language: "json/json",
5222
+ rules: Object.fromEntries([...repoPackageJsonRuleIds, ...huskyRuleIds, ...vulykRuleIds].map((id) => [id, "error"]))
5223
+ };
5224
+ var nextManifestBlock = {
5225
+ files: ["package.json"],
5226
+ plugins: {
5227
+ json: { languages: { json: jsonPlugin.languages.json } },
5228
+ pasika: { rules: nextPackageJsonRules }
5229
+ },
5230
+ language: "json/json",
5231
+ rules: Object.fromEntries(nextPackageJsonRuleIds.map((id) => [id, "error"]))
5232
+ };
5233
+ var zirkaBlock = {
5234
+ files: ["eslint.config.{ts,mts,cts,js,mjs,cjs}"],
5235
+ plugins: { pasika: { rules: { "zirka-baseline": zirkaBaselineRule } } },
5236
+ rules: { "pasika/zirka-baseline": "error" }
5237
+ };
5238
+ var docsBlock = {
5239
+ files: ["docs/**/*.md"],
5240
+ ignores: ["**/_*/**"],
5241
+ plugins: {
5242
+ markdown,
5243
+ pasika: { rules: documentationRules }
5244
+ },
5245
+ language: "markdown/gfm",
5246
+ rules: Object.fromEntries(documentationRuleIds.map((id) => [id, "error"]))
5247
+ };
5248
+ var typescriptApp = [repoManifestBlock, zirkaBlock, typescriptAppBlock, docsBlock];
5249
+ var nextjsApp = [
5250
+ ...typescriptApp,
5251
+ nextManifestBlock,
5252
+ nextjsAppBlock,
5253
+ tailwindGlobalsBlock,
5254
+ tailwindAnyCssBlock
5255
+ ];
4884
5256
  export {
4885
5257
  allPasikaRuleIds,
4886
- cssRules,
4887
- jsonRules,
4888
- mdRules,
4889
- pasikaConfig,
4890
- pasikaCssRuleIds,
4891
- pasikaJsonRuleIds,
4892
- pasikaMdRuleIds,
4893
- pasikaRuleIds,
4894
- pasikaRules
5258
+ documentationRules,
5259
+ huskyRules,
5260
+ nextPackageJsonRules,
5261
+ nextjsApp,
5262
+ pasikaRules,
5263
+ repoPackageJsonRules,
5264
+ tailwindRules,
5265
+ typescriptApp,
5266
+ vulykRules
4895
5267
  };