@sarj/eslint-plugin 9.1.0 → 9.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -534,7 +534,72 @@ function restatesStatementHead(body, statement) {
534
534
  // src/rules/no-comment-cruft.ts
535
535
  var LEADING_PREAMBLE_MIN = 4;
536
536
  var STEP_NARRATION_RE = /^(?:first(?:ly)?|second(?:ly)?|third(?:ly)?|then|next|after(?:wards| that)?|finally|lastly|now)\s*[,:]\s*\S/i;
537
- var META_COMMENTARY_RE = /\b(?:for now|keeping (?:it|this) simple|could be (?:refactored|improved|cleaned up|simplified)|refactor(?:ed|ing)? (?:later|this)|not sure (?:if|whether|why|how)|quick[- ](?:and[- ]dirty|fix)|(?:a |bit of a )?hacky|is a hack|temporary (?:solution|workaround|fix|hack)|revisit (?:this|later|below)|clean (?:this|it) up|not ideal|placeholder for now)\b/i;
537
+ var META_COMMENTARY_RE = /\b(?:keeping (?:it|this) simple|could be (?:refactored|improved|cleaned up|simplified)|refactor(?:ed|ing)? (?:later|this)|not sure (?:if|whether|why|how)|quick[- ](?:and[- ]dirty|fix)|(?:a |bit of a )?hacky|is a hack|temporary (?:solution|workaround|fix|hack)|revisit (?:this|later|below)|clean (?:this|it) up|not ideal|placeholder for now)\b/i;
538
+ var FOR_NOW_RE = /\bfor now\b/i;
539
+ var DEFERRAL_STOPWORDS = /* @__PURE__ */ new Set([
540
+ "a",
541
+ "an",
542
+ "and",
543
+ "are",
544
+ "as",
545
+ "at",
546
+ "be",
547
+ "but",
548
+ "by",
549
+ "can",
550
+ "could",
551
+ "do",
552
+ "does",
553
+ "for",
554
+ "from",
555
+ "had",
556
+ "has",
557
+ "have",
558
+ "here",
559
+ "i",
560
+ "in",
561
+ "is",
562
+ "it",
563
+ "its",
564
+ "just",
565
+ "may",
566
+ "might",
567
+ "no",
568
+ "not",
569
+ "now",
570
+ "of",
571
+ "on",
572
+ "only",
573
+ "our",
574
+ "shall",
575
+ "should",
576
+ "so",
577
+ "still",
578
+ "that",
579
+ "the",
580
+ "then",
581
+ "there",
582
+ "this",
583
+ "to",
584
+ "us",
585
+ "was",
586
+ "we",
587
+ "were",
588
+ "will",
589
+ "with",
590
+ "would",
591
+ "you",
592
+ "your"
593
+ ]);
594
+ var DEFERRAL_MAX_CONTENT_WORDS = 2;
595
+ function isBareDeferral(text) {
596
+ if (!FOR_NOW_RE.test(text)) return false;
597
+ const rest = text.replace(FOR_NOW_RE, " ");
598
+ const content = (rest.match(/[A-Za-z][\w']*/g) ?? []).filter(
599
+ (word) => !DEFERRAL_STOPWORDS.has(word.toLowerCase())
600
+ );
601
+ return content.length <= DEFERRAL_MAX_CONTENT_WORDS;
602
+ }
538
603
  var DIRECTIVE_RE = /^(eslint\b|eslint-|sarj-noqa\b|@ts-|prettier-ignore|prettier\b|biome-|c8\b|v8\b|istanbul\b|@type\b|@vite|webpack|<reference|<amd|global\b|noinspection|hack\b|xxx\b)/i;
539
604
  var LICENSE_RE = /copyright|licen[cs]ed?|spdx|permission is hereby granted|all rights reserved/i;
540
605
  var ENUMERATED_ITEM_RE = /^(?:\d+[.):]|[-*•])\s+\S/;
@@ -655,6 +720,7 @@ function isRedundantNarration(body, statementBelow, standalone, isolatedEnumerat
655
720
  const justified = JUSTIFICATION_RE.test(t);
656
721
  if (STEP_NARRATION_RE.test(t) && !justified) return true;
657
722
  if (META_COMMENTARY_RE.test(t) && !justified) return true;
723
+ if (isBareDeferral(t) && !justified) return true;
658
724
  if (HELPER_OPENER_RE.test(t) || LETS_RE.test(t)) return true;
659
725
  const words = t.split(/\s+/);
660
726
  if (words.length > 1 && words.length <= 4 && DUMMY_TRANSLATION_RE.test(t) && !/[():=]/.test(t)) {
@@ -1581,12 +1647,6 @@ var no_dynamic_sql_default = createRule({
1581
1647
 
1582
1648
  // src/rules/no-enum.ts
1583
1649
  var import_utils11 = require("@typescript-eslint/utils");
1584
- var DEFAULT_IGNORE_PATTERNS = [
1585
- /[\\/]generated[\\/]/,
1586
- /[\\/]openapi-gen[\\/]/,
1587
- /\.gen\.tsx?$/,
1588
- /\.generated\.tsx?$/
1589
- ];
1590
1650
  function matchesAnyPattern(filename, patterns) {
1591
1651
  for (const pattern of patterns) {
1592
1652
  const regexSource = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "::DOUBLESTAR::").replace(/\*/g, "[^/\\\\]*").replace(/::DOUBLESTAR::/g, ".*");
@@ -1596,10 +1656,6 @@ function matchesAnyPattern(filename, patterns) {
1596
1656
  }
1597
1657
  return false;
1598
1658
  }
1599
- function hasGeneratedMarker(sourceText) {
1600
- const head = sourceText.slice(0, 1024);
1601
- return /@generated\b/.test(head);
1602
- }
1603
1659
  var no_enum_default = createRule({
1604
1660
  name: "no-enum",
1605
1661
  meta: {
@@ -1629,12 +1685,8 @@ var no_enum_default = createRule({
1629
1685
  const ignoreFiles = options.ignoreFiles ?? [];
1630
1686
  const filename = context.filename;
1631
1687
  const sourceText = context.sourceCode.getText();
1632
- const isIgnoredByDefault = DEFAULT_IGNORE_PATTERNS.some(
1633
- (re) => re.test(filename)
1634
- );
1635
1688
  const isIgnoredByOption = ignoreFiles.length > 0 && matchesAnyPattern(filename, ignoreFiles);
1636
- const isGenerated = hasGeneratedMarker(sourceText) || isGeneratedFile(filename, sourceText);
1637
- if (isIgnoredByDefault || isIgnoredByOption || isGenerated) {
1689
+ if (isIgnoredByOption || isGeneratedFile(filename, sourceText)) {
1638
1690
  return {};
1639
1691
  }
1640
1692
  return {
@@ -3382,35 +3434,6 @@ var no_restated_comment_default = createRule({
3382
3434
 
3383
3435
  // src/rules/no-restated-jsdoc.ts
3384
3436
  var import_utils24 = require("@typescript-eslint/utils");
3385
- var VALUE_TAGS = /* @__PURE__ */ new Set([
3386
- "alpha",
3387
- "author",
3388
- "beta",
3389
- "category",
3390
- "copyright",
3391
- "default",
3392
- "defaultvalue",
3393
- "deprecated",
3394
- "example",
3395
- "experimental",
3396
- "fileoverview",
3397
- "fixme",
3398
- "group",
3399
- "inheritdoc",
3400
- "internal",
3401
- "license",
3402
- "link",
3403
- "module",
3404
- "override",
3405
- "packagedocumentation",
3406
- "remarks",
3407
- "see",
3408
- "since",
3409
- "template",
3410
- "throws",
3411
- "todo",
3412
- "typeparam"
3413
- ]);
3414
3437
  var MODELLED_TAGS = /* @__PURE__ */ new Set([
3415
3438
  "arg",
3416
3439
  "argument",
@@ -3535,7 +3558,6 @@ var no_restated_jsdoc_default = createRule({
3535
3558
  const { description, tags } = parseJsDoc(comment.value);
3536
3559
  if (DIRECTIVE_RE3.test(description)) continue;
3537
3560
  const tagNames = new Set(tags.map((tag) => tag.name));
3538
- if ([...tagNames].some((name) => VALUE_TAGS.has(name))) continue;
3539
3561
  if ([...tagNames].some((name) => !MODELLED_TAGS.has(name))) continue;
3540
3562
  if (isProtected(description)) continue;
3541
3563
  const token = sourceCode.getTokenAfter(comment, { includeComments: false });
@@ -7013,25 +7035,32 @@ var STYLE_COLOR_PROPS = /* @__PURE__ */ new Set([
7013
7035
  var RAW_COLOR_VALUE_RE = new RegExp(`#[0-9a-fA-F]{3,8}\\b|\\b(?:${COLOR_FN})\\s*\\(`, "i");
7014
7036
  var CSS_VAR_REFERENCE_RE = /var\(\s*--/;
7015
7037
  var STORIES_FILE_RE = /\.stories\.[cm]?[jt]sx?$/i;
7016
- var SEMANTIC_TOKEN_RE = /@theme\b|--(?:background|foreground|primary|secondary|muted|accent|destructive|border|card|popover)\b|(?:bg|text|border)-(?:background|foreground|primary|secondary|muted|accent|destructive|border|card|popover)\b/;
7017
- var CONFIG_IS_SUFFICIENT = /* @__PURE__ */ new Set([
7018
- "components.json",
7019
- "tailwind.config.cjs",
7020
- "tailwind.config.js",
7021
- "tailwind.config.mjs",
7022
- "tailwind.config.ts"
7023
- ]);
7024
- var DETECTION_FILES = [
7038
+ var TOKEN_ROLES = "background|foreground|primary|secondary|muted|accent|destructive|danger|success|warning|info|border|card|popover|surface|content|base|subtle|default|ring|input|fg|bg";
7039
+ var SEMANTIC_TOKEN_RE = new RegExp(
7040
+ `--(?:color-)?(?:${TOKEN_ROLES})\\b|(?:bg|text|border|ring|fill|stroke)-(?:ui-)?(?:${TOKEN_ROLES})\\b`
7041
+ );
7042
+ var THEME_BLOCK_RE = /@theme\b/;
7043
+ var PRESENCE_MARKERS = [
7025
7044
  "components.json",
7026
7045
  "tailwind.config.js",
7027
7046
  "tailwind.config.cjs",
7028
7047
  "tailwind.config.mjs",
7029
7048
  "tailwind.config.ts",
7049
+ "tailwind.config.mts",
7050
+ "tailwind.config.cts"
7051
+ ];
7052
+ var CSS_DETECTION_FILES = [
7030
7053
  "app/globals.css",
7054
+ "app/global.css",
7055
+ "app/styles/globals.css",
7031
7056
  "src/app/globals.css",
7057
+ "src/app/global.css",
7058
+ "src/global.css",
7032
7059
  "src/index.css",
7033
7060
  "src/styles/globals.css",
7034
- "styles/globals.css"
7061
+ "src/styles/index.css",
7062
+ "styles/globals.css",
7063
+ "styles/index.css"
7035
7064
  ];
7036
7065
  var WORKSPACE_ROOT_FILES = [
7037
7066
  "pnpm-workspace.yaml",
@@ -7110,12 +7139,13 @@ var isInsideIconFactoryPath = (node) => {
7110
7139
  return false;
7111
7140
  };
7112
7141
  var hasMarkerAt = (dir) => {
7113
- for (const rel of DETECTION_FILES) {
7142
+ if (PRESENCE_MARKERS.some((rel) => (0, import_fs.existsSync)((0, import_path.join)(dir, rel)))) return true;
7143
+ for (const rel of CSS_DETECTION_FILES) {
7114
7144
  const candidate = (0, import_path.join)(dir, rel);
7115
7145
  if (!(0, import_fs.existsSync)(candidate)) continue;
7116
- if (CONFIG_IS_SUFFICIENT.has(rel)) return true;
7117
7146
  try {
7118
- if (SEMANTIC_TOKEN_RE.test((0, import_fs.readFileSync)(candidate, "utf8"))) return true;
7147
+ const css = (0, import_fs.readFileSync)(candidate, "utf8");
7148
+ if (SEMANTIC_TOKEN_RE.test(css) || THEME_BLOCK_RE.test(css)) return true;
7119
7149
  } catch {
7120
7150
  }
7121
7151
  }
@@ -8577,32 +8607,6 @@ var prefer_zod_infer_default = createRule({
8577
8607
 
8578
8608
  // src/rules/require-assert-never.ts
8579
8609
  var import_utils54 = require("@typescript-eslint/utils");
8580
- var isAssertNeverCall = (expression) => {
8581
- if (expression.type !== import_utils54.AST_NODE_TYPES.CallExpression) return false;
8582
- const callee = expression.callee;
8583
- if (callee.type === import_utils54.AST_NODE_TYPES.Identifier) {
8584
- return callee.name === "assertNever";
8585
- }
8586
- if (callee.type === import_utils54.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils54.AST_NODE_TYPES.Identifier) {
8587
- return callee.property.name === "assertNever";
8588
- }
8589
- return false;
8590
- };
8591
- var statementContainsAssertNever = (statement) => {
8592
- if (statement.type === import_utils54.AST_NODE_TYPES.ExpressionStatement) {
8593
- return isAssertNeverCall(statement.expression);
8594
- }
8595
- if (statement.type === import_utils54.AST_NODE_TYPES.ThrowStatement) {
8596
- return isAssertNeverCall(statement.argument);
8597
- }
8598
- if (statement.type === import_utils54.AST_NODE_TYPES.ReturnStatement) {
8599
- return statement.argument !== null && isAssertNeverCall(statement.argument);
8600
- }
8601
- if (statement.type === import_utils54.AST_NODE_TYPES.BlockStatement) {
8602
- return statement.body.some(statementContainsAssertNever);
8603
- }
8604
- return false;
8605
- };
8606
8610
  var isRuntimeHandlingStatement = (statement) => {
8607
8611
  if (statement.type === import_utils54.AST_NODE_TYPES.EmptyStatement) return false;
8608
8612
  if (statement.type === import_utils54.AST_NODE_TYPES.BlockStatement) {
@@ -8648,7 +8652,6 @@ var require_assert_never_default = createRule({
8648
8652
  if (defaultIndex === -1) return;
8649
8653
  const defaultCase = node.cases[defaultIndex];
8650
8654
  if (defaultCase === void 0) return;
8651
- if (defaultCase.consequent.some(statementContainsAssertNever)) return;
8652
8655
  if (defaultCase.consequent.some(isRuntimeHandlingStatement)) return;
8653
8656
  if (isFallthroughDefault(node, defaultIndex)) return;
8654
8657
  if (isCommentOnlyNoopDefault(defaultCase, context.sourceCode)) return;
@@ -8663,7 +8666,6 @@ var require_assert_never_default = createRule({
8663
8666
 
8664
8667
  // src/rules/require-fetch-timeout.ts
8665
8668
  var import_utils55 = require("@typescript-eslint/utils");
8666
- var CODEMOD_FIXTURE_RE = /[\\/]__testfixtures__[\\/]/;
8667
8669
  var GLOBAL_OBJECTS2 = /* @__PURE__ */ new Set([
8668
8670
  "globalThis",
8669
8671
  "window",
@@ -8724,7 +8726,7 @@ var require_fetch_timeout_default = createRule({
8724
8726
  },
8725
8727
  defaultOptions: [{}],
8726
8728
  create(context, [optionsArg]) {
8727
- if (isTestFile(context.filename) || isScriptFile(context.filename) || CODEMOD_FIXTURE_RE.test(context.filename)) {
8729
+ if (isTestFile(context.filename) || isScriptFile(context.filename)) {
8728
8730
  return {};
8729
8731
  }
8730
8732
  const allowIn = optionsArg?.allowIn ?? [];
@@ -9383,7 +9385,7 @@ var rules = {
9383
9385
  };
9384
9386
  var meta = {
9385
9387
  name: "@sarj/eslint-plugin",
9386
- version: "9.1.0"
9388
+ version: "9.3.0"
9387
9389
  };
9388
9390
  var recommendedRules = {
9389
9391
  "@sarj/enforce-file-structure": "warn",