react-doctor 0.2.0-beta.6 → 0.2.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/README.md CHANGED
@@ -447,16 +447,16 @@ Top React codebases scanned by React Doctor, ranked by score. Updated automatica
447
447
  <!-- prettier-ignore -->
448
448
  | # | Repo | Score |
449
449
  | -- | ---- | ----: |
450
- | 1 | [executor](https://github.com/RhysSullivan/executor) | 94 |
450
+ | 1 | [executor](https://github.com/RhysSullivan/executor) | 96 |
451
451
  | 2 | [nodejs.org](https://github.com/nodejs/nodejs.org) | 86 |
452
- | 3 | [tldraw](https://github.com/tldraw/tldraw) | 70 |
453
- | 4 | [t3code](https://github.com/pingdotgg/t3code) | 68 |
452
+ | 3 | [tldraw](https://github.com/tldraw/tldraw) | 71 |
453
+ | 4 | [t3code](https://github.com/pingdotgg/t3code) | 69 |
454
454
  | 5 | [better-auth](https://github.com/better-auth/better-auth) | 64 |
455
- | 6 | [excalidraw](https://github.com/excalidraw/excalidraw) | 63 |
456
- | 7 | [mastra](https://github.com/mastra-ai/mastra) | 63 |
455
+ | 6 | [mastra](https://github.com/mastra-ai/mastra) | 63 |
456
+ | 7 | [excalidraw](https://github.com/excalidraw/excalidraw) | 62 |
457
457
  | 8 | [payload](https://github.com/payloadcms/payload) | 60 |
458
458
  | 9 | [typebot](https://github.com/baptisteArno/typebot.io) | 57 |
459
- | 10 | [plane](https://github.com/makeplane/plane) | 56 |
459
+ | 10 | [medusajs/admin](https://github.com/medusajs/medusa) | 56 |
460
460
 
461
461
  <!-- LEADERBOARD:END -->
462
462
 
package/dist/cli.js CHANGED
@@ -34,7 +34,6 @@ var __toESM$1 = (mod, isNodeMode, target) => (target = mod != null ? __create$1(
34
34
  value: mod,
35
35
  enumerable: true
36
36
  }) : target, mod));
37
- var __require = /* @__PURE__ */ createRequire(import.meta.url);
38
37
  //#endregion
39
38
  //#region ../types/dist/index.js
40
39
  const REACT_NATIVE_DEPENDENCY_NAMES = new Set([
@@ -938,11 +937,11 @@ const isTailwindAtLeast = (detected, required) => {
938
937
  return detected.minor >= required.minor;
939
938
  };
940
939
  //#endregion
941
- //#region ../../node_modules/.pnpm/picomatch@2.3.1/node_modules/picomatch/lib/constants.js
940
+ //#region ../../node_modules/.pnpm/picomatch@4.0.4/node_modules/picomatch/lib/constants.js
942
941
  var require_constants = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
943
- const path$3 = __require("path");
944
942
  const WIN_SLASH = "\\\\/";
945
943
  const WIN_NO_SLASH = `[^${WIN_SLASH}]`;
944
+ const DEFAULT_MAX_EXTGLOB_RECURSION = 0;
946
945
  /**
947
946
  * Posix glob regex
948
947
  */
@@ -970,7 +969,8 @@ var require_constants = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
970
969
  NO_DOTS_SLASH: `(?!${DOTS_SLASH})`,
971
970
  QMARK_NO_DOT: `[^.${SLASH_LITERAL}]`,
972
971
  STAR: `${QMARK}*?`,
973
- START_ANCHOR
972
+ START_ANCHOR,
973
+ SEP: "/"
974
974
  };
975
975
  /**
976
976
  * Windows glob regex
@@ -987,11 +987,14 @@ var require_constants = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
987
987
  NO_DOTS_SLASH: `(?!${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`,
988
988
  QMARK_NO_DOT: `[^.${WIN_SLASH}]`,
989
989
  START_ANCHOR: `(?:^|[${WIN_SLASH}])`,
990
- END_ANCHOR: `(?:[${WIN_SLASH}]|$)`
990
+ END_ANCHOR: `(?:[${WIN_SLASH}]|$)`,
991
+ SEP: "\\"
991
992
  };
992
993
  module.exports = {
994
+ DEFAULT_MAX_EXTGLOB_RECURSION,
993
995
  MAX_LENGTH: 1024 * 64,
994
996
  POSIX_REGEX_SOURCE: {
997
+ __proto__: null,
995
998
  alnum: "a-zA-Z0-9",
996
999
  alpha: "a-zA-Z",
997
1000
  ascii: "\\x00-\\x7F",
@@ -1014,6 +1017,7 @@ var require_constants = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
1014
1017
  REGEX_SPECIAL_CHARS_GLOBAL: /([-*+?.^${}(|)[\]])/g,
1015
1018
  REGEX_REMOVE_BACKSLASH: /(?:\[.*?[^\\]\]|\\(?=.))/g,
1016
1019
  REPLACEMENTS: {
1020
+ __proto__: null,
1017
1021
  "***": "*",
1018
1022
  "**/**": "**",
1019
1023
  "**/**/**": "**"
@@ -1061,7 +1065,6 @@ var require_constants = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
1061
1065
  CHAR_UNDERSCORE: 95,
1062
1066
  CHAR_VERTICAL_LINE: 124,
1063
1067
  CHAR_ZERO_WIDTH_NOBREAK_SPACE: 65279,
1064
- SEP: path$3.sep,
1065
1068
  /**
1066
1069
  * Create EXTGLOB_CHARS
1067
1070
  */
@@ -1103,30 +1106,27 @@ var require_constants = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
1103
1106
  };
1104
1107
  }));
1105
1108
  //#endregion
1106
- //#region ../../node_modules/.pnpm/picomatch@2.3.1/node_modules/picomatch/lib/utils.js
1109
+ //#region ../../node_modules/.pnpm/picomatch@4.0.4/node_modules/picomatch/lib/utils.js
1107
1110
  var require_utils = /* @__PURE__ */ __commonJSMin$1(((exports) => {
1108
- const path$2 = __require("path");
1109
- const win32 = process.platform === "win32";
1110
1111
  const { REGEX_BACKSLASH, REGEX_REMOVE_BACKSLASH, REGEX_SPECIAL_CHARS, REGEX_SPECIAL_CHARS_GLOBAL } = require_constants();
1111
1112
  exports.isObject = (val) => val !== null && typeof val === "object" && !Array.isArray(val);
1112
1113
  exports.hasRegexChars = (str) => REGEX_SPECIAL_CHARS.test(str);
1113
1114
  exports.isRegexChar = (str) => str.length === 1 && exports.hasRegexChars(str);
1114
1115
  exports.escapeRegex = (str) => str.replace(REGEX_SPECIAL_CHARS_GLOBAL, "\\$1");
1115
1116
  exports.toPosixSlashes = (str) => str.replace(REGEX_BACKSLASH, "/");
1117
+ exports.isWindows = () => {
1118
+ if (typeof navigator !== "undefined" && navigator.platform) {
1119
+ const platform = navigator.platform.toLowerCase();
1120
+ return platform === "win32" || platform === "windows";
1121
+ }
1122
+ if (typeof process !== "undefined" && process.platform) return process.platform === "win32";
1123
+ return false;
1124
+ };
1116
1125
  exports.removeBackslashes = (str) => {
1117
1126
  return str.replace(REGEX_REMOVE_BACKSLASH, (match) => {
1118
1127
  return match === "\\" ? "" : match;
1119
1128
  });
1120
1129
  };
1121
- exports.supportsLookbehinds = () => {
1122
- const segs = process.version.slice(1).split(".").map(Number);
1123
- if (segs.length === 3 && segs[0] >= 9 || segs[0] === 8 && segs[1] >= 10) return true;
1124
- return false;
1125
- };
1126
- exports.isWindows = (options) => {
1127
- if (options && typeof options.windows === "boolean") return options.windows;
1128
- return win32 === true || path$2.sep === "\\";
1129
- };
1130
1130
  exports.escapeLast = (input, char, lastIdx) => {
1131
1131
  const idx = input.lastIndexOf(char, lastIdx);
1132
1132
  if (idx === -1) return input;
@@ -1146,9 +1146,15 @@ var require_utils = /* @__PURE__ */ __commonJSMin$1(((exports) => {
1146
1146
  if (state.negated === true) output = `(?:^(?!${output}).*$)`;
1147
1147
  return output;
1148
1148
  };
1149
+ exports.basename = (path, { windows } = {}) => {
1150
+ const segs = path.split(windows ? /[\\/]/ : "/");
1151
+ const last = segs[segs.length - 1];
1152
+ if (last === "") return segs[segs.length - 2];
1153
+ return last;
1154
+ };
1149
1155
  }));
1150
1156
  //#endregion
1151
- //#region ../../node_modules/.pnpm/picomatch@2.3.1/node_modules/picomatch/lib/scan.js
1157
+ //#region ../../node_modules/.pnpm/picomatch@4.0.4/node_modules/picomatch/lib/scan.js
1152
1158
  var require_scan = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
1153
1159
  const utils = require_utils();
1154
1160
  const { CHAR_ASTERISK, CHAR_AT, CHAR_BACKWARD_SLASH, CHAR_COMMA, CHAR_DOT, CHAR_EXCLAMATION_MARK, CHAR_FORWARD_SLASH, CHAR_LEFT_CURLY_BRACE, CHAR_LEFT_PARENTHESES, CHAR_LEFT_SQUARE_BRACKET, CHAR_PLUS, CHAR_QUESTION_MARK, CHAR_RIGHT_CURLY_BRACE, CHAR_RIGHT_PARENTHESES, CHAR_RIGHT_SQUARE_BRACKET } = require_constants();
@@ -1435,7 +1441,7 @@ var require_scan = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
1435
1441
  module.exports = scan;
1436
1442
  }));
1437
1443
  //#endregion
1438
- //#region ../../node_modules/.pnpm/picomatch@2.3.1/node_modules/picomatch/lib/parse.js
1444
+ //#region ../../node_modules/.pnpm/picomatch@4.0.4/node_modules/picomatch/lib/parse.js
1439
1445
  var require_parse = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
1440
1446
  const constants = require_constants();
1441
1447
  const utils = require_utils();
@@ -1463,6 +1469,177 @@ var require_parse = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
1463
1469
  const syntaxError = (type, char) => {
1464
1470
  return `Missing ${type}: "${char}" - use "\\\\${char}" to match literal characters`;
1465
1471
  };
1472
+ const splitTopLevel = (input) => {
1473
+ const parts = [];
1474
+ let bracket = 0;
1475
+ let paren = 0;
1476
+ let quote = 0;
1477
+ let value = "";
1478
+ let escaped = false;
1479
+ for (const ch of input) {
1480
+ if (escaped === true) {
1481
+ value += ch;
1482
+ escaped = false;
1483
+ continue;
1484
+ }
1485
+ if (ch === "\\") {
1486
+ value += ch;
1487
+ escaped = true;
1488
+ continue;
1489
+ }
1490
+ if (ch === "\"") {
1491
+ quote = quote === 1 ? 0 : 1;
1492
+ value += ch;
1493
+ continue;
1494
+ }
1495
+ if (quote === 0) {
1496
+ if (ch === "[") bracket++;
1497
+ else if (ch === "]" && bracket > 0) bracket--;
1498
+ else if (bracket === 0) {
1499
+ if (ch === "(") paren++;
1500
+ else if (ch === ")" && paren > 0) paren--;
1501
+ else if (ch === "|" && paren === 0) {
1502
+ parts.push(value);
1503
+ value = "";
1504
+ continue;
1505
+ }
1506
+ }
1507
+ }
1508
+ value += ch;
1509
+ }
1510
+ parts.push(value);
1511
+ return parts;
1512
+ };
1513
+ const isPlainBranch = (branch) => {
1514
+ let escaped = false;
1515
+ for (const ch of branch) {
1516
+ if (escaped === true) {
1517
+ escaped = false;
1518
+ continue;
1519
+ }
1520
+ if (ch === "\\") {
1521
+ escaped = true;
1522
+ continue;
1523
+ }
1524
+ if (/[?*+@!()[\]{}]/.test(ch)) return false;
1525
+ }
1526
+ return true;
1527
+ };
1528
+ const normalizeSimpleBranch = (branch) => {
1529
+ let value = branch.trim();
1530
+ let changed = true;
1531
+ while (changed === true) {
1532
+ changed = false;
1533
+ if (/^@\([^\\()[\]{}|]+\)$/.test(value)) {
1534
+ value = value.slice(2, -1);
1535
+ changed = true;
1536
+ }
1537
+ }
1538
+ if (!isPlainBranch(value)) return;
1539
+ return value.replace(/\\(.)/g, "$1");
1540
+ };
1541
+ const hasRepeatedCharPrefixOverlap = (branches) => {
1542
+ const values = branches.map(normalizeSimpleBranch).filter(Boolean);
1543
+ for (let i = 0; i < values.length; i++) for (let j = i + 1; j < values.length; j++) {
1544
+ const a = values[i];
1545
+ const b = values[j];
1546
+ const char = a[0];
1547
+ if (!char || a !== char.repeat(a.length) || b !== char.repeat(b.length)) continue;
1548
+ if (a === b || a.startsWith(b) || b.startsWith(a)) return true;
1549
+ }
1550
+ return false;
1551
+ };
1552
+ const parseRepeatedExtglob = (pattern, requireEnd = true) => {
1553
+ if (pattern[0] !== "+" && pattern[0] !== "*" || pattern[1] !== "(") return;
1554
+ let bracket = 0;
1555
+ let paren = 0;
1556
+ let quote = 0;
1557
+ let escaped = false;
1558
+ for (let i = 1; i < pattern.length; i++) {
1559
+ const ch = pattern[i];
1560
+ if (escaped === true) {
1561
+ escaped = false;
1562
+ continue;
1563
+ }
1564
+ if (ch === "\\") {
1565
+ escaped = true;
1566
+ continue;
1567
+ }
1568
+ if (ch === "\"") {
1569
+ quote = quote === 1 ? 0 : 1;
1570
+ continue;
1571
+ }
1572
+ if (quote === 1) continue;
1573
+ if (ch === "[") {
1574
+ bracket++;
1575
+ continue;
1576
+ }
1577
+ if (ch === "]" && bracket > 0) {
1578
+ bracket--;
1579
+ continue;
1580
+ }
1581
+ if (bracket > 0) continue;
1582
+ if (ch === "(") {
1583
+ paren++;
1584
+ continue;
1585
+ }
1586
+ if (ch === ")") {
1587
+ paren--;
1588
+ if (paren === 0) {
1589
+ if (requireEnd === true && i !== pattern.length - 1) return;
1590
+ return {
1591
+ type: pattern[0],
1592
+ body: pattern.slice(2, i),
1593
+ end: i
1594
+ };
1595
+ }
1596
+ }
1597
+ }
1598
+ };
1599
+ const getStarExtglobSequenceOutput = (pattern) => {
1600
+ let index = 0;
1601
+ const chars = [];
1602
+ while (index < pattern.length) {
1603
+ const match = parseRepeatedExtglob(pattern.slice(index), false);
1604
+ if (!match || match.type !== "*") return;
1605
+ const branches = splitTopLevel(match.body).map((branch) => branch.trim());
1606
+ if (branches.length !== 1) return;
1607
+ const branch = normalizeSimpleBranch(branches[0]);
1608
+ if (!branch || branch.length !== 1) return;
1609
+ chars.push(branch);
1610
+ index += match.end + 1;
1611
+ }
1612
+ if (chars.length < 1) return;
1613
+ return `${chars.length === 1 ? utils.escapeRegex(chars[0]) : `[${chars.map((ch) => utils.escapeRegex(ch)).join("")}]`}*`;
1614
+ };
1615
+ const repeatedExtglobRecursion = (pattern) => {
1616
+ let depth = 0;
1617
+ let value = pattern.trim();
1618
+ let match = parseRepeatedExtglob(value);
1619
+ while (match) {
1620
+ depth++;
1621
+ value = match.body.trim();
1622
+ match = parseRepeatedExtglob(value);
1623
+ }
1624
+ return depth;
1625
+ };
1626
+ const analyzeRepeatedExtglob = (body, options) => {
1627
+ if (options.maxExtglobRecursion === false) return { risky: false };
1628
+ const max = typeof options.maxExtglobRecursion === "number" ? options.maxExtglobRecursion : constants.DEFAULT_MAX_EXTGLOB_RECURSION;
1629
+ const branches = splitTopLevel(body).map((branch) => branch.trim());
1630
+ if (branches.length > 1) {
1631
+ if (branches.some((branch) => branch === "") || branches.some((branch) => /^[*?]+$/.test(branch)) || hasRepeatedCharPrefixOverlap(branches)) return { risky: true };
1632
+ }
1633
+ for (const branch of branches) {
1634
+ const safeOutput = getStarExtglobSequenceOutput(branch);
1635
+ if (safeOutput) return {
1636
+ risky: true,
1637
+ safeOutput
1638
+ };
1639
+ if (repeatedExtglobRecursion(branch) > max) return { risky: true };
1640
+ }
1641
+ return { risky: false };
1642
+ };
1466
1643
  /**
1467
1644
  * Parse the given input string.
1468
1645
  * @param {String} input
@@ -1483,8 +1660,7 @@ var require_parse = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
1483
1660
  };
1484
1661
  const tokens = [bos];
1485
1662
  const capture = opts.capture ? "" : "?:";
1486
- const win32 = utils.isWindows(options);
1487
- const PLATFORM_CHARS = constants.globChars(win32);
1663
+ const PLATFORM_CHARS = constants.globChars(opts.windows);
1488
1664
  const EXTGLOB_CHARS = constants.extglobChars(PLATFORM_CHARS);
1489
1665
  const { DOT_LITERAL, PLUS_LITERAL, SLASH_LITERAL, ONE_CHAR, DOTS_SLASH, NO_DOT, NO_DOT_SLASH, NO_DOTS_SLASH, QMARK, QMARK_NO_DOT, STAR, START_ANCHOR } = PLATFORM_CHARS;
1490
1666
  const globstar = (opts) => {
@@ -1576,8 +1752,8 @@ var require_parse = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
1576
1752
  if (extglobs.length && tok.type !== "paren") extglobs[extglobs.length - 1].inner += tok.value;
1577
1753
  if (tok.value || tok.output) append(tok);
1578
1754
  if (prev && prev.type === "text" && tok.type === "text") {
1755
+ prev.output = (prev.output || prev.value) + tok.value;
1579
1756
  prev.value += tok.value;
1580
- prev.output = (prev.output || "") + tok.value;
1581
1757
  return;
1582
1758
  }
1583
1759
  tok.prev = prev;
@@ -1593,6 +1769,8 @@ var require_parse = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
1593
1769
  token.prev = prev;
1594
1770
  token.parens = state.parens;
1595
1771
  token.output = state.output;
1772
+ token.startIndex = state.index;
1773
+ token.tokensIndex = tokens.length;
1596
1774
  const output = (opts.capture ? "(" : "") + token.open;
1597
1775
  increment("parens");
1598
1776
  push({
@@ -1609,6 +1787,30 @@ var require_parse = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
1609
1787
  extglobs.push(token);
1610
1788
  };
1611
1789
  const extglobClose = (token) => {
1790
+ const literal = input.slice(token.startIndex, state.index + 1);
1791
+ const analysis = analyzeRepeatedExtglob(input.slice(token.startIndex + 2, state.index), opts);
1792
+ if ((token.type === "plus" || token.type === "star") && analysis.risky) {
1793
+ const safeOutput = analysis.safeOutput ? (token.output ? "" : ONE_CHAR) + (opts.capture ? `(${analysis.safeOutput})` : analysis.safeOutput) : void 0;
1794
+ const open = tokens[token.tokensIndex];
1795
+ open.type = "text";
1796
+ open.value = literal;
1797
+ open.output = safeOutput || utils.escapeRegex(literal);
1798
+ for (let i = token.tokensIndex + 1; i < tokens.length; i++) {
1799
+ tokens[i].value = "";
1800
+ tokens[i].output = "";
1801
+ delete tokens[i].suffix;
1802
+ }
1803
+ state.output = token.output + open.output;
1804
+ state.backtrack = true;
1805
+ push({
1806
+ type: "paren",
1807
+ extglob: true,
1808
+ value,
1809
+ output: ""
1810
+ });
1811
+ decrement("parens");
1812
+ return;
1813
+ }
1612
1814
  let output = token.close + (opts.capture ? ")" : "");
1613
1815
  let rest;
1614
1816
  if (token.type === "negate") {
@@ -1967,7 +2169,6 @@ var require_parse = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
1967
2169
  if (prev && prev.type === "paren") {
1968
2170
  const next = peek();
1969
2171
  let output = value;
1970
- if (next === "<" && !utils.supportsLookbehinds()) throw new Error("Node.js v10 or higher is required for regex lookbehinds");
1971
2172
  if (prev.value === "(" && !/[!=<:]/.test(next) || next === "<" && !/<([!=]|\w+>)/.test(remaining())) output = `\\${value}`;
1972
2173
  push({
1973
2174
  type: "text",
@@ -2255,8 +2456,7 @@ var require_parse = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
2255
2456
  const len = input.length;
2256
2457
  if (len > max) throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`);
2257
2458
  input = REPLACEMENTS[input] || input;
2258
- const win32 = utils.isWindows(options);
2259
- const { DOT_LITERAL, SLASH_LITERAL, ONE_CHAR, DOTS_SLASH, NO_DOT, NO_DOTS, NO_DOTS_SLASH, STAR, START_ANCHOR } = constants.globChars(win32);
2459
+ const { DOT_LITERAL, SLASH_LITERAL, ONE_CHAR, DOTS_SLASH, NO_DOT, NO_DOTS, NO_DOTS_SLASH, STAR, START_ANCHOR } = constants.globChars(opts.windows);
2260
2460
  const nodot = opts.dot ? NO_DOTS : NO_DOT;
2261
2461
  const slashDot = opts.dot ? NO_DOTS_SLASH : NO_DOT;
2262
2462
  const capture = opts.capture ? "" : "?:";
@@ -2296,9 +2496,8 @@ var require_parse = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
2296
2496
  module.exports = parse;
2297
2497
  }));
2298
2498
  //#endregion
2299
- //#region ../../node_modules/.pnpm/picomatch@2.3.1/node_modules/picomatch/lib/picomatch.js
2499
+ //#region ../../node_modules/.pnpm/picomatch@4.0.4/node_modules/picomatch/lib/picomatch.js
2300
2500
  var require_picomatch$1 = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
2301
- const path$1 = __require("path");
2302
2501
  const scan = require_scan();
2303
2502
  const parse = require_parse();
2304
2503
  const utils = require_utils();
@@ -2340,7 +2539,7 @@ var require_picomatch$1 = /* @__PURE__ */ __commonJSMin$1(((exports, module) =>
2340
2539
  const isState = isObject(glob) && glob.tokens && glob.input;
2341
2540
  if (glob === "" || typeof glob !== "string" && !isState) throw new TypeError("Expected pattern to be a non-empty string");
2342
2541
  const opts = options || {};
2343
- const posix = utils.isWindows(options);
2542
+ const posix = opts.windows;
2344
2543
  const regex = isState ? picomatch.compileRe(glob, options) : picomatch.makeRe(glob, options, false, true);
2345
2544
  const state = regex.state;
2346
2545
  delete regex.state;
@@ -2436,8 +2635,8 @@ var require_picomatch$1 = /* @__PURE__ */ __commonJSMin$1(((exports, module) =>
2436
2635
  * @return {Boolean}
2437
2636
  * @api public
2438
2637
  */
2439
- picomatch.matchBase = (input, glob, options, posix = utils.isWindows(options)) => {
2440
- return (glob instanceof RegExp ? glob : picomatch.makeRe(glob, options)).test(path$1.basename(input));
2638
+ picomatch.matchBase = (input, glob, options) => {
2639
+ return (glob instanceof RegExp ? glob : picomatch.makeRe(glob, options)).test(utils.basename(input));
2441
2640
  };
2442
2641
  /**
2443
2642
  * Returns true if **any** of the given glob `patterns` match the specified `string`.
@@ -2507,6 +2706,14 @@ var require_picomatch$1 = /* @__PURE__ */ __commonJSMin$1(((exports, module) =>
2507
2706
  * Compile a regular expression from the `state` object returned by the
2508
2707
  * [parse()](#parse) method.
2509
2708
  *
2709
+ * ```js
2710
+ * const picomatch = require('picomatch');
2711
+ * const state = picomatch.parse('*.js');
2712
+ * // picomatch.compileRe(state[, options]);
2713
+ *
2714
+ * console.log(picomatch.compileRe(state));
2715
+ * //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/
2716
+ * ```
2510
2717
  * @param {Object} `state`
2511
2718
  * @param {Object} `options`
2512
2719
  * @param {Boolean} `returnOutput` Intended for implementors, this argument allows you to return the raw output from the parser.
@@ -2530,10 +2737,10 @@ var require_picomatch$1 = /* @__PURE__ */ __commonJSMin$1(((exports, module) =>
2530
2737
  *
2531
2738
  * ```js
2532
2739
  * const picomatch = require('picomatch');
2533
- * const state = picomatch.parse('*.js');
2534
- * // picomatch.compileRe(state[, options]);
2740
+ * // picomatch.makeRe(state[, options]);
2535
2741
  *
2536
- * console.log(picomatch.compileRe(state));
2742
+ * const result = picomatch.makeRe('*.js');
2743
+ * console.log(result);
2537
2744
  * //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/
2538
2745
  * ```
2539
2746
  * @param {String} `state` The object returned from the `.parse` method.
@@ -2591,7 +2798,17 @@ var require_picomatch$1 = /* @__PURE__ */ __commonJSMin$1(((exports, module) =>
2591
2798
  //#endregion
2592
2799
  //#region ../core/dist/index.js
2593
2800
  var import_picomatch = /* @__PURE__ */ __toESM$1((/* @__PURE__ */ __commonJSMin$1(((exports, module) => {
2594
- module.exports = require_picomatch$1();
2801
+ const pico = require_picomatch$1();
2802
+ const utils = require_utils();
2803
+ function picomatch(glob, options, returnState = false) {
2804
+ if (options && (options.windows === null || options.windows === void 0)) options = {
2805
+ ...options,
2806
+ windows: utils.isWindows()
2807
+ };
2808
+ return pico(glob, options, returnState);
2809
+ }
2810
+ Object.assign(picomatch, pico);
2811
+ module.exports = picomatch;
2595
2812
  })))(), 1);
2596
2813
  var __create = Object.create;
2597
2814
  var __defProp = Object.defineProperty;
@@ -2618,6 +2835,7 @@ const JSX_FILE_PATTERN = /\.(tsx|jsx)$/;
2618
2835
  const MILLISECONDS_PER_SECOND = 1e3;
2619
2836
  const SCORE_API_URL = "https://www.react.doctor/api/score";
2620
2837
  const SHARE_BASE_URL = "https://www.react.doctor/share";
2838
+ const REACT_REVIEW_URL = "https://react.review";
2621
2839
  const FETCH_TIMEOUT_MS = 1e4;
2622
2840
  const DEFAULT_BRANCH_CANDIDATES = ["main", "master"];
2623
2841
  const ADOPTABLE_LINT_CONFIG_FILENAMES = [".oxlintrc.json", ".eslintrc.json"];
@@ -5356,6 +5574,12 @@ const printNoScoreHeader = (noScoreMessage) => {
5356
5574
  logger.log(` ${highlighter.gray(noScoreMessage)}`);
5357
5575
  logger.break();
5358
5576
  };
5577
+ const printReactReviewCta = () => {
5578
+ logger.log(` ${highlighter.bold("→ Catch these issues on every PR:")} ${highlighter.info(REACT_REVIEW_URL)}`);
5579
+ logger.log(` ${highlighter.dim("React Review is a GitHub App built on React Doctor, and it runs on each pull request,")}`);
5580
+ logger.log(` ${highlighter.dim("posts new issues as inline review comments, and tracks your team's score over time.")}`);
5581
+ logger.break();
5582
+ };
5359
5583
  //#endregion
5360
5584
  //#region src/cli/utils/write-diagnostics-directory.ts
5361
5585
  const writeDiagnosticsDirectory = (diagnostics) => {
@@ -5404,6 +5628,8 @@ const printSummary = (diagnostics, elapsedMilliseconds, scoreResult, projectName
5404
5628
  logger.break();
5405
5629
  const shareUrl = buildShareUrl(diagnostics, scoreResult, projectName);
5406
5630
  logger.log(` ${highlighter.bold("→ Share your results:")} ${highlighter.info(shareUrl)}`);
5631
+ logger.break();
5632
+ printReactReviewCta();
5407
5633
  }
5408
5634
  };
5409
5635
  //#endregion
@@ -5751,7 +5977,7 @@ const CI_ENVIRONMENT_VARIABLES = [
5751
5977
  const isCiEnvironment = () => CI_ENVIRONMENT_VARIABLES.some((envVariable) => Boolean(process.env[envVariable])) || process.env.CI === "true";
5752
5978
  //#endregion
5753
5979
  //#region src/cli/utils/version.ts
5754
- const VERSION = "0.2.0-beta.6";
5980
+ const VERSION = "0.2.0";
5755
5981
  //#endregion
5756
5982
  //#region src/cli/utils/json-mode.ts
5757
5983
  let context = null;
package/dist/index.js CHANGED
@@ -27,7 +27,6 @@ var __toESM$1 = (mod, isNodeMode, target) => (target = mod != null ? __create$1(
27
27
  value: mod,
28
28
  enumerable: true
29
29
  }) : target, mod));
30
- var __require = /* @__PURE__ */ createRequire(import.meta.url);
31
30
  //#endregion
32
31
  //#region ../types/dist/index.js
33
32
  const REACT_NATIVE_DEPENDENCY_NAMES = new Set([
@@ -956,11 +955,11 @@ const isTailwindAtLeast = (detected, required) => {
956
955
  return detected.minor >= required.minor;
957
956
  };
958
957
  //#endregion
959
- //#region ../../node_modules/.pnpm/picomatch@2.3.1/node_modules/picomatch/lib/constants.js
958
+ //#region ../../node_modules/.pnpm/picomatch@4.0.4/node_modules/picomatch/lib/constants.js
960
959
  var require_constants = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
961
- const path$3 = __require("path");
962
960
  const WIN_SLASH = "\\\\/";
963
961
  const WIN_NO_SLASH = `[^${WIN_SLASH}]`;
962
+ const DEFAULT_MAX_EXTGLOB_RECURSION = 0;
964
963
  /**
965
964
  * Posix glob regex
966
965
  */
@@ -988,7 +987,8 @@ var require_constants = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
988
987
  NO_DOTS_SLASH: `(?!${DOTS_SLASH})`,
989
988
  QMARK_NO_DOT: `[^.${SLASH_LITERAL}]`,
990
989
  STAR: `${QMARK}*?`,
991
- START_ANCHOR
990
+ START_ANCHOR,
991
+ SEP: "/"
992
992
  };
993
993
  /**
994
994
  * Windows glob regex
@@ -1005,11 +1005,14 @@ var require_constants = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
1005
1005
  NO_DOTS_SLASH: `(?!${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`,
1006
1006
  QMARK_NO_DOT: `[^.${WIN_SLASH}]`,
1007
1007
  START_ANCHOR: `(?:^|[${WIN_SLASH}])`,
1008
- END_ANCHOR: `(?:[${WIN_SLASH}]|$)`
1008
+ END_ANCHOR: `(?:[${WIN_SLASH}]|$)`,
1009
+ SEP: "\\"
1009
1010
  };
1010
1011
  module.exports = {
1012
+ DEFAULT_MAX_EXTGLOB_RECURSION,
1011
1013
  MAX_LENGTH: 1024 * 64,
1012
1014
  POSIX_REGEX_SOURCE: {
1015
+ __proto__: null,
1013
1016
  alnum: "a-zA-Z0-9",
1014
1017
  alpha: "a-zA-Z",
1015
1018
  ascii: "\\x00-\\x7F",
@@ -1032,6 +1035,7 @@ var require_constants = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
1032
1035
  REGEX_SPECIAL_CHARS_GLOBAL: /([-*+?.^${}(|)[\]])/g,
1033
1036
  REGEX_REMOVE_BACKSLASH: /(?:\[.*?[^\\]\]|\\(?=.))/g,
1034
1037
  REPLACEMENTS: {
1038
+ __proto__: null,
1035
1039
  "***": "*",
1036
1040
  "**/**": "**",
1037
1041
  "**/**/**": "**"
@@ -1079,7 +1083,6 @@ var require_constants = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
1079
1083
  CHAR_UNDERSCORE: 95,
1080
1084
  CHAR_VERTICAL_LINE: 124,
1081
1085
  CHAR_ZERO_WIDTH_NOBREAK_SPACE: 65279,
1082
- SEP: path$3.sep,
1083
1086
  /**
1084
1087
  * Create EXTGLOB_CHARS
1085
1088
  */
@@ -1121,30 +1124,27 @@ var require_constants = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
1121
1124
  };
1122
1125
  }));
1123
1126
  //#endregion
1124
- //#region ../../node_modules/.pnpm/picomatch@2.3.1/node_modules/picomatch/lib/utils.js
1127
+ //#region ../../node_modules/.pnpm/picomatch@4.0.4/node_modules/picomatch/lib/utils.js
1125
1128
  var require_utils = /* @__PURE__ */ __commonJSMin$1(((exports) => {
1126
- const path$2 = __require("path");
1127
- const win32 = process.platform === "win32";
1128
1129
  const { REGEX_BACKSLASH, REGEX_REMOVE_BACKSLASH, REGEX_SPECIAL_CHARS, REGEX_SPECIAL_CHARS_GLOBAL } = require_constants();
1129
1130
  exports.isObject = (val) => val !== null && typeof val === "object" && !Array.isArray(val);
1130
1131
  exports.hasRegexChars = (str) => REGEX_SPECIAL_CHARS.test(str);
1131
1132
  exports.isRegexChar = (str) => str.length === 1 && exports.hasRegexChars(str);
1132
1133
  exports.escapeRegex = (str) => str.replace(REGEX_SPECIAL_CHARS_GLOBAL, "\\$1");
1133
1134
  exports.toPosixSlashes = (str) => str.replace(REGEX_BACKSLASH, "/");
1135
+ exports.isWindows = () => {
1136
+ if (typeof navigator !== "undefined" && navigator.platform) {
1137
+ const platform = navigator.platform.toLowerCase();
1138
+ return platform === "win32" || platform === "windows";
1139
+ }
1140
+ if (typeof process !== "undefined" && process.platform) return process.platform === "win32";
1141
+ return false;
1142
+ };
1134
1143
  exports.removeBackslashes = (str) => {
1135
1144
  return str.replace(REGEX_REMOVE_BACKSLASH, (match) => {
1136
1145
  return match === "\\" ? "" : match;
1137
1146
  });
1138
1147
  };
1139
- exports.supportsLookbehinds = () => {
1140
- const segs = process.version.slice(1).split(".").map(Number);
1141
- if (segs.length === 3 && segs[0] >= 9 || segs[0] === 8 && segs[1] >= 10) return true;
1142
- return false;
1143
- };
1144
- exports.isWindows = (options) => {
1145
- if (options && typeof options.windows === "boolean") return options.windows;
1146
- return win32 === true || path$2.sep === "\\";
1147
- };
1148
1148
  exports.escapeLast = (input, char, lastIdx) => {
1149
1149
  const idx = input.lastIndexOf(char, lastIdx);
1150
1150
  if (idx === -1) return input;
@@ -1164,9 +1164,15 @@ var require_utils = /* @__PURE__ */ __commonJSMin$1(((exports) => {
1164
1164
  if (state.negated === true) output = `(?:^(?!${output}).*$)`;
1165
1165
  return output;
1166
1166
  };
1167
+ exports.basename = (path, { windows } = {}) => {
1168
+ const segs = path.split(windows ? /[\\/]/ : "/");
1169
+ const last = segs[segs.length - 1];
1170
+ if (last === "") return segs[segs.length - 2];
1171
+ return last;
1172
+ };
1167
1173
  }));
1168
1174
  //#endregion
1169
- //#region ../../node_modules/.pnpm/picomatch@2.3.1/node_modules/picomatch/lib/scan.js
1175
+ //#region ../../node_modules/.pnpm/picomatch@4.0.4/node_modules/picomatch/lib/scan.js
1170
1176
  var require_scan = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
1171
1177
  const utils = require_utils();
1172
1178
  const { CHAR_ASTERISK, CHAR_AT, CHAR_BACKWARD_SLASH, CHAR_COMMA, CHAR_DOT, CHAR_EXCLAMATION_MARK, CHAR_FORWARD_SLASH, CHAR_LEFT_CURLY_BRACE, CHAR_LEFT_PARENTHESES, CHAR_LEFT_SQUARE_BRACKET, CHAR_PLUS, CHAR_QUESTION_MARK, CHAR_RIGHT_CURLY_BRACE, CHAR_RIGHT_PARENTHESES, CHAR_RIGHT_SQUARE_BRACKET } = require_constants();
@@ -1453,7 +1459,7 @@ var require_scan = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
1453
1459
  module.exports = scan;
1454
1460
  }));
1455
1461
  //#endregion
1456
- //#region ../../node_modules/.pnpm/picomatch@2.3.1/node_modules/picomatch/lib/parse.js
1462
+ //#region ../../node_modules/.pnpm/picomatch@4.0.4/node_modules/picomatch/lib/parse.js
1457
1463
  var require_parse = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
1458
1464
  const constants = require_constants();
1459
1465
  const utils = require_utils();
@@ -1481,6 +1487,177 @@ var require_parse = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
1481
1487
  const syntaxError = (type, char) => {
1482
1488
  return `Missing ${type}: "${char}" - use "\\\\${char}" to match literal characters`;
1483
1489
  };
1490
+ const splitTopLevel = (input) => {
1491
+ const parts = [];
1492
+ let bracket = 0;
1493
+ let paren = 0;
1494
+ let quote = 0;
1495
+ let value = "";
1496
+ let escaped = false;
1497
+ for (const ch of input) {
1498
+ if (escaped === true) {
1499
+ value += ch;
1500
+ escaped = false;
1501
+ continue;
1502
+ }
1503
+ if (ch === "\\") {
1504
+ value += ch;
1505
+ escaped = true;
1506
+ continue;
1507
+ }
1508
+ if (ch === "\"") {
1509
+ quote = quote === 1 ? 0 : 1;
1510
+ value += ch;
1511
+ continue;
1512
+ }
1513
+ if (quote === 0) {
1514
+ if (ch === "[") bracket++;
1515
+ else if (ch === "]" && bracket > 0) bracket--;
1516
+ else if (bracket === 0) {
1517
+ if (ch === "(") paren++;
1518
+ else if (ch === ")" && paren > 0) paren--;
1519
+ else if (ch === "|" && paren === 0) {
1520
+ parts.push(value);
1521
+ value = "";
1522
+ continue;
1523
+ }
1524
+ }
1525
+ }
1526
+ value += ch;
1527
+ }
1528
+ parts.push(value);
1529
+ return parts;
1530
+ };
1531
+ const isPlainBranch = (branch) => {
1532
+ let escaped = false;
1533
+ for (const ch of branch) {
1534
+ if (escaped === true) {
1535
+ escaped = false;
1536
+ continue;
1537
+ }
1538
+ if (ch === "\\") {
1539
+ escaped = true;
1540
+ continue;
1541
+ }
1542
+ if (/[?*+@!()[\]{}]/.test(ch)) return false;
1543
+ }
1544
+ return true;
1545
+ };
1546
+ const normalizeSimpleBranch = (branch) => {
1547
+ let value = branch.trim();
1548
+ let changed = true;
1549
+ while (changed === true) {
1550
+ changed = false;
1551
+ if (/^@\([^\\()[\]{}|]+\)$/.test(value)) {
1552
+ value = value.slice(2, -1);
1553
+ changed = true;
1554
+ }
1555
+ }
1556
+ if (!isPlainBranch(value)) return;
1557
+ return value.replace(/\\(.)/g, "$1");
1558
+ };
1559
+ const hasRepeatedCharPrefixOverlap = (branches) => {
1560
+ const values = branches.map(normalizeSimpleBranch).filter(Boolean);
1561
+ for (let i = 0; i < values.length; i++) for (let j = i + 1; j < values.length; j++) {
1562
+ const a = values[i];
1563
+ const b = values[j];
1564
+ const char = a[0];
1565
+ if (!char || a !== char.repeat(a.length) || b !== char.repeat(b.length)) continue;
1566
+ if (a === b || a.startsWith(b) || b.startsWith(a)) return true;
1567
+ }
1568
+ return false;
1569
+ };
1570
+ const parseRepeatedExtglob = (pattern, requireEnd = true) => {
1571
+ if (pattern[0] !== "+" && pattern[0] !== "*" || pattern[1] !== "(") return;
1572
+ let bracket = 0;
1573
+ let paren = 0;
1574
+ let quote = 0;
1575
+ let escaped = false;
1576
+ for (let i = 1; i < pattern.length; i++) {
1577
+ const ch = pattern[i];
1578
+ if (escaped === true) {
1579
+ escaped = false;
1580
+ continue;
1581
+ }
1582
+ if (ch === "\\") {
1583
+ escaped = true;
1584
+ continue;
1585
+ }
1586
+ if (ch === "\"") {
1587
+ quote = quote === 1 ? 0 : 1;
1588
+ continue;
1589
+ }
1590
+ if (quote === 1) continue;
1591
+ if (ch === "[") {
1592
+ bracket++;
1593
+ continue;
1594
+ }
1595
+ if (ch === "]" && bracket > 0) {
1596
+ bracket--;
1597
+ continue;
1598
+ }
1599
+ if (bracket > 0) continue;
1600
+ if (ch === "(") {
1601
+ paren++;
1602
+ continue;
1603
+ }
1604
+ if (ch === ")") {
1605
+ paren--;
1606
+ if (paren === 0) {
1607
+ if (requireEnd === true && i !== pattern.length - 1) return;
1608
+ return {
1609
+ type: pattern[0],
1610
+ body: pattern.slice(2, i),
1611
+ end: i
1612
+ };
1613
+ }
1614
+ }
1615
+ }
1616
+ };
1617
+ const getStarExtglobSequenceOutput = (pattern) => {
1618
+ let index = 0;
1619
+ const chars = [];
1620
+ while (index < pattern.length) {
1621
+ const match = parseRepeatedExtglob(pattern.slice(index), false);
1622
+ if (!match || match.type !== "*") return;
1623
+ const branches = splitTopLevel(match.body).map((branch) => branch.trim());
1624
+ if (branches.length !== 1) return;
1625
+ const branch = normalizeSimpleBranch(branches[0]);
1626
+ if (!branch || branch.length !== 1) return;
1627
+ chars.push(branch);
1628
+ index += match.end + 1;
1629
+ }
1630
+ if (chars.length < 1) return;
1631
+ return `${chars.length === 1 ? utils.escapeRegex(chars[0]) : `[${chars.map((ch) => utils.escapeRegex(ch)).join("")}]`}*`;
1632
+ };
1633
+ const repeatedExtglobRecursion = (pattern) => {
1634
+ let depth = 0;
1635
+ let value = pattern.trim();
1636
+ let match = parseRepeatedExtglob(value);
1637
+ while (match) {
1638
+ depth++;
1639
+ value = match.body.trim();
1640
+ match = parseRepeatedExtglob(value);
1641
+ }
1642
+ return depth;
1643
+ };
1644
+ const analyzeRepeatedExtglob = (body, options) => {
1645
+ if (options.maxExtglobRecursion === false) return { risky: false };
1646
+ const max = typeof options.maxExtglobRecursion === "number" ? options.maxExtglobRecursion : constants.DEFAULT_MAX_EXTGLOB_RECURSION;
1647
+ const branches = splitTopLevel(body).map((branch) => branch.trim());
1648
+ if (branches.length > 1) {
1649
+ if (branches.some((branch) => branch === "") || branches.some((branch) => /^[*?]+$/.test(branch)) || hasRepeatedCharPrefixOverlap(branches)) return { risky: true };
1650
+ }
1651
+ for (const branch of branches) {
1652
+ const safeOutput = getStarExtglobSequenceOutput(branch);
1653
+ if (safeOutput) return {
1654
+ risky: true,
1655
+ safeOutput
1656
+ };
1657
+ if (repeatedExtglobRecursion(branch) > max) return { risky: true };
1658
+ }
1659
+ return { risky: false };
1660
+ };
1484
1661
  /**
1485
1662
  * Parse the given input string.
1486
1663
  * @param {String} input
@@ -1501,8 +1678,7 @@ var require_parse = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
1501
1678
  };
1502
1679
  const tokens = [bos];
1503
1680
  const capture = opts.capture ? "" : "?:";
1504
- const win32 = utils.isWindows(options);
1505
- const PLATFORM_CHARS = constants.globChars(win32);
1681
+ const PLATFORM_CHARS = constants.globChars(opts.windows);
1506
1682
  const EXTGLOB_CHARS = constants.extglobChars(PLATFORM_CHARS);
1507
1683
  const { DOT_LITERAL, PLUS_LITERAL, SLASH_LITERAL, ONE_CHAR, DOTS_SLASH, NO_DOT, NO_DOT_SLASH, NO_DOTS_SLASH, QMARK, QMARK_NO_DOT, STAR, START_ANCHOR } = PLATFORM_CHARS;
1508
1684
  const globstar = (opts) => {
@@ -1594,8 +1770,8 @@ var require_parse = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
1594
1770
  if (extglobs.length && tok.type !== "paren") extglobs[extglobs.length - 1].inner += tok.value;
1595
1771
  if (tok.value || tok.output) append(tok);
1596
1772
  if (prev && prev.type === "text" && tok.type === "text") {
1773
+ prev.output = (prev.output || prev.value) + tok.value;
1597
1774
  prev.value += tok.value;
1598
- prev.output = (prev.output || "") + tok.value;
1599
1775
  return;
1600
1776
  }
1601
1777
  tok.prev = prev;
@@ -1611,6 +1787,8 @@ var require_parse = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
1611
1787
  token.prev = prev;
1612
1788
  token.parens = state.parens;
1613
1789
  token.output = state.output;
1790
+ token.startIndex = state.index;
1791
+ token.tokensIndex = tokens.length;
1614
1792
  const output = (opts.capture ? "(" : "") + token.open;
1615
1793
  increment("parens");
1616
1794
  push({
@@ -1627,6 +1805,30 @@ var require_parse = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
1627
1805
  extglobs.push(token);
1628
1806
  };
1629
1807
  const extglobClose = (token) => {
1808
+ const literal = input.slice(token.startIndex, state.index + 1);
1809
+ const analysis = analyzeRepeatedExtglob(input.slice(token.startIndex + 2, state.index), opts);
1810
+ if ((token.type === "plus" || token.type === "star") && analysis.risky) {
1811
+ const safeOutput = analysis.safeOutput ? (token.output ? "" : ONE_CHAR) + (opts.capture ? `(${analysis.safeOutput})` : analysis.safeOutput) : void 0;
1812
+ const open = tokens[token.tokensIndex];
1813
+ open.type = "text";
1814
+ open.value = literal;
1815
+ open.output = safeOutput || utils.escapeRegex(literal);
1816
+ for (let i = token.tokensIndex + 1; i < tokens.length; i++) {
1817
+ tokens[i].value = "";
1818
+ tokens[i].output = "";
1819
+ delete tokens[i].suffix;
1820
+ }
1821
+ state.output = token.output + open.output;
1822
+ state.backtrack = true;
1823
+ push({
1824
+ type: "paren",
1825
+ extglob: true,
1826
+ value,
1827
+ output: ""
1828
+ });
1829
+ decrement("parens");
1830
+ return;
1831
+ }
1630
1832
  let output = token.close + (opts.capture ? ")" : "");
1631
1833
  let rest;
1632
1834
  if (token.type === "negate") {
@@ -1985,7 +2187,6 @@ var require_parse = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
1985
2187
  if (prev && prev.type === "paren") {
1986
2188
  const next = peek();
1987
2189
  let output = value;
1988
- if (next === "<" && !utils.supportsLookbehinds()) throw new Error("Node.js v10 or higher is required for regex lookbehinds");
1989
2190
  if (prev.value === "(" && !/[!=<:]/.test(next) || next === "<" && !/<([!=]|\w+>)/.test(remaining())) output = `\\${value}`;
1990
2191
  push({
1991
2192
  type: "text",
@@ -2273,8 +2474,7 @@ var require_parse = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
2273
2474
  const len = input.length;
2274
2475
  if (len > max) throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`);
2275
2476
  input = REPLACEMENTS[input] || input;
2276
- const win32 = utils.isWindows(options);
2277
- const { DOT_LITERAL, SLASH_LITERAL, ONE_CHAR, DOTS_SLASH, NO_DOT, NO_DOTS, NO_DOTS_SLASH, STAR, START_ANCHOR } = constants.globChars(win32);
2477
+ const { DOT_LITERAL, SLASH_LITERAL, ONE_CHAR, DOTS_SLASH, NO_DOT, NO_DOTS, NO_DOTS_SLASH, STAR, START_ANCHOR } = constants.globChars(opts.windows);
2278
2478
  const nodot = opts.dot ? NO_DOTS : NO_DOT;
2279
2479
  const slashDot = opts.dot ? NO_DOTS_SLASH : NO_DOT;
2280
2480
  const capture = opts.capture ? "" : "?:";
@@ -2314,9 +2514,8 @@ var require_parse = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
2314
2514
  module.exports = parse;
2315
2515
  }));
2316
2516
  //#endregion
2317
- //#region ../../node_modules/.pnpm/picomatch@2.3.1/node_modules/picomatch/lib/picomatch.js
2517
+ //#region ../../node_modules/.pnpm/picomatch@4.0.4/node_modules/picomatch/lib/picomatch.js
2318
2518
  var require_picomatch$1 = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
2319
- const path$1 = __require("path");
2320
2519
  const scan = require_scan();
2321
2520
  const parse = require_parse();
2322
2521
  const utils = require_utils();
@@ -2358,7 +2557,7 @@ var require_picomatch$1 = /* @__PURE__ */ __commonJSMin$1(((exports, module) =>
2358
2557
  const isState = isObject(glob) && glob.tokens && glob.input;
2359
2558
  if (glob === "" || typeof glob !== "string" && !isState) throw new TypeError("Expected pattern to be a non-empty string");
2360
2559
  const opts = options || {};
2361
- const posix = utils.isWindows(options);
2560
+ const posix = opts.windows;
2362
2561
  const regex = isState ? picomatch.compileRe(glob, options) : picomatch.makeRe(glob, options, false, true);
2363
2562
  const state = regex.state;
2364
2563
  delete regex.state;
@@ -2454,8 +2653,8 @@ var require_picomatch$1 = /* @__PURE__ */ __commonJSMin$1(((exports, module) =>
2454
2653
  * @return {Boolean}
2455
2654
  * @api public
2456
2655
  */
2457
- picomatch.matchBase = (input, glob, options, posix = utils.isWindows(options)) => {
2458
- return (glob instanceof RegExp ? glob : picomatch.makeRe(glob, options)).test(path$1.basename(input));
2656
+ picomatch.matchBase = (input, glob, options) => {
2657
+ return (glob instanceof RegExp ? glob : picomatch.makeRe(glob, options)).test(utils.basename(input));
2459
2658
  };
2460
2659
  /**
2461
2660
  * Returns true if **any** of the given glob `patterns` match the specified `string`.
@@ -2525,6 +2724,14 @@ var require_picomatch$1 = /* @__PURE__ */ __commonJSMin$1(((exports, module) =>
2525
2724
  * Compile a regular expression from the `state` object returned by the
2526
2725
  * [parse()](#parse) method.
2527
2726
  *
2727
+ * ```js
2728
+ * const picomatch = require('picomatch');
2729
+ * const state = picomatch.parse('*.js');
2730
+ * // picomatch.compileRe(state[, options]);
2731
+ *
2732
+ * console.log(picomatch.compileRe(state));
2733
+ * //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/
2734
+ * ```
2528
2735
  * @param {Object} `state`
2529
2736
  * @param {Object} `options`
2530
2737
  * @param {Boolean} `returnOutput` Intended for implementors, this argument allows you to return the raw output from the parser.
@@ -2548,10 +2755,10 @@ var require_picomatch$1 = /* @__PURE__ */ __commonJSMin$1(((exports, module) =>
2548
2755
  *
2549
2756
  * ```js
2550
2757
  * const picomatch = require('picomatch');
2551
- * const state = picomatch.parse('*.js');
2552
- * // picomatch.compileRe(state[, options]);
2758
+ * // picomatch.makeRe(state[, options]);
2553
2759
  *
2554
- * console.log(picomatch.compileRe(state));
2760
+ * const result = picomatch.makeRe('*.js');
2761
+ * console.log(result);
2555
2762
  * //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/
2556
2763
  * ```
2557
2764
  * @param {String} `state` The object returned from the `.parse` method.
@@ -2609,7 +2816,17 @@ var require_picomatch$1 = /* @__PURE__ */ __commonJSMin$1(((exports, module) =>
2609
2816
  //#endregion
2610
2817
  //#region ../core/dist/index.js
2611
2818
  var import_picomatch = /* @__PURE__ */ __toESM$1((/* @__PURE__ */ __commonJSMin$1(((exports, module) => {
2612
- module.exports = require_picomatch$1();
2819
+ const pico = require_picomatch$1();
2820
+ const utils = require_utils();
2821
+ function picomatch(glob, options, returnState = false) {
2822
+ if (options && (options.windows === null || options.windows === void 0)) options = {
2823
+ ...options,
2824
+ windows: utils.isWindows()
2825
+ };
2826
+ return pico(glob, options, returnState);
2827
+ }
2828
+ Object.assign(picomatch, pico);
2829
+ module.exports = picomatch;
2613
2830
  })))(), 1);
2614
2831
  var __create = Object.create;
2615
2832
  var __defProp = Object.defineProperty;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-doctor",
3
- "version": "0.2.0-beta.6",
3
+ "version": "0.2.0",
4
4
  "description": "Diagnose and fix React codebases for security, performance, correctness, accessibility, bundle-size, and architecture issues",
5
5
  "keywords": [
6
6
  "accessibility",
@@ -56,15 +56,15 @@
56
56
  "picocolors": "^1.1.1",
57
57
  "prompts": "^2.4.2",
58
58
  "typescript": ">=5.0.4 <7",
59
- "oxlint-plugin-react-doctor": "0.2.0-beta.6"
59
+ "oxlint-plugin-react-doctor": "0.2.0"
60
60
  },
61
61
  "devDependencies": {
62
62
  "@types/prompts": "^2.4.9",
63
63
  "eslint-plugin-react-hooks": "^7.1.1",
64
64
  "eslint-plugin-react-you-might-not-need-an-effect": "^0.10.1",
65
- "@react-doctor/project-info": "0.2.0-beta.6",
66
- "@react-doctor/types": "0.2.0-beta.6",
67
- "@react-doctor/core": "0.2.0-beta.6"
65
+ "@react-doctor/core": "0.2.0",
66
+ "@react-doctor/project-info": "0.2.0",
67
+ "@react-doctor/types": "0.2.0"
68
68
  },
69
69
  "peerDependencies": {
70
70
  "eslint-plugin-react-hooks": "^6 || ^7",