@isentinel/jest-roblox 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs CHANGED
@@ -23,7 +23,7 @@ import istanbulCoverage from "istanbul-lib-coverage";
23
23
  import istanbulReport from "istanbul-lib-report";
24
24
  import istanbulReports from "istanbul-reports";
25
25
  //#region package.json
26
- var version = "0.2.0";
26
+ var version = "0.2.1";
27
27
  //#endregion
28
28
  //#region src/backends/auto.ts
29
29
  var StudioWithFallback = class {
@@ -156,7 +156,7 @@ function evalTable(entries) {
156
156
  }
157
157
  //#endregion
158
158
  //#region src/luau/parse-ast.luau
159
- var parse_ast_default = "local fs = require(\"@std/fs\")\nlocal json = require(\"@std/json\")\nlocal process = require(\"@std/process\")\nlocal syntax = require(\"@std/syntax\")\n\nlocal rawArgs = process.args\nlocal userArgs: { string } = {}\nlocal pastSeparator = false\n\nfor _, arg in rawArgs do\n if pastSeparator then\n table.insert(userArgs, arg)\n elseif arg == \"--\" then\n pastSeparator = true\n end\nend\n\nlocal luauRoot = userArgs[1]\nif not luauRoot then\n error(\"Usage: lute run parse-ast.luau -- <file.luau | luau-root> [output-dir]\")\nend\n\nluauRoot = string.gsub(luauRoot, \"\\\\\", \"/\")\n\n-- Fields to keep per AST tag (beyond tag/kind/location which are always kept).\n-- Tags shared by stat/expr variants are merged — nil fields are harmless.\nlocal KEEP: { [string]: { string } } = {\n assign = { \"values\", \"variables\" },\n binary = { \"lhsoperand\", \"rhsoperand\" },\n block = { \"statements\" },\n boolean = { \"value\" },\n call = { \"arguments\", \"func\" },\n cast = { \"operand\" },\n compoundassign = { \"value\", \"variable\" },\n conditional = { \"condition\", \"thenblock\", \"elseifs\", \"elseblock\", \"thenexpr\", \"elseexpr\" },\n [\"do\"] = { \"body\" },\n expression = { \"expression\" },\n [\"for\"] = { \"body\", \"from\", \"to\", \"step\" },\n forin = { \"body\", \"values\" },\n [\"function\"] = { \"body\", \"name\", \"func\" },\n global = { \"name\" },\n group = { \"expression\" },\n index = { \"expression\", \"index\" },\n indexname = { \"expression\", \"accessor\", \"index\" },\n instantiate = { \"expr\" },\n interpolatedstring = { \"expressions\" },\n [\"local\"] = { \"values\", \"variables\" },\n localfunction = { \"name\", \"func\" },\n number = { \"value\" },\n [\"repeat\"] = { \"body\", \"condition\" },\n [\"return\"] = { \"expressions\" },\n string = { \"text\" },\n table = { \"entries\" },\n unary = { \"operand\" },\n [\"while\"] = { \"body\", \"condition\" },\n}\n\nlocal function strip(value: any): any\n if type(value) ~= \"table\" then\n return value\n end\n\n -- LuauSpan — has beginLine, no tag\n if value.beginLine ~= nil then\n return value\n end\n\n -- Token — has text but no tag, reduce to {text}\n if value.text ~= nil and value.tag == nil then\n return { text = value.text }\n end\n\n -- AST node — has tag, keep only allowlisted fields\n if value.tag ~= nil then\n local result = { tag = value.tag, kind = value.kind, location = value.location }\n local fields = KEEP[value.tag :: string]\n if fields then\n for _, field in fields do\n if value[field] ~= nil then\n result[field] = strip(value[field])\n end\n end\n end\n\n return result\n end\n\n -- Other tables (arrays, Pairs, ElseIf structs) — recurse all fields\n local result: any = {}\n for k, v in value do\n result[k] = strip(v)\n end\n\n return result\nend\n\n-- Single-file mode: parse one file, print stripped AST to stdout\nif string.sub(luauRoot, -5) == \".luau\" or string.sub(luauRoot, -4) == \".lua\" then\n local source = fs.readfiletostring(luauRoot)\n local parseResult = syntax.parse(source)\n print(json.serialize(strip(parseResult.root)))\n return\nend\n\nlocal outputDir = userArgs[2]\nif not outputDir then\n error(\"Usage: lute run parse-ast.luau -- <luau-root> <output-dir>\")\nend\n\noutputDir = string.gsub(outputDir, \"\\\\\", \"/\")\n\n-- Discover .luau files recursively, skipping node_modules, dot dirs, spec/test files\nlocal function discoverFiles(directory: string, relativeTo: string, results: { string })\n local entries = fs.listdirectory(directory)\n for _, entry in entries do\n local fullPath = directory .. \"/\" .. entry.name\n if entry.type == \"dir\" then\n if entry.name == \"node_modules\" or entry.name == \".jest-roblox-coverage\" then\n continue\n end\n\n if string.sub(entry.name, 1, 1) == \".\" then\n continue\n end\n\n discoverFiles(fullPath, relativeTo, results)\n elseif\n entry.type == \"file\"\n and (string.sub(entry.name, -5) == \".luau\" or string.sub(entry.name, -4) == \".lua\")\n then\n if\n string.sub(entry.name, -10) == \".spec.luau\"\n or string.sub(entry.name, -10) == \".test.luau\"\n or string.sub(entry.name, -9) == \".spec.lua\"\n or string.sub(entry.name, -9) == \".test.lua\"\n or string.sub(entry.name, -10) == \".snap.luau\"\n or string.sub(entry.name, -9) == \".snap.lua\"\n then\n continue\n end\n\n -- Compute relative path\n local relative = string.sub(fullPath, #relativeTo + 2)\n table.insert(results, relative)\n end\n end\nend\n\nlocal function dirname(filepath: string): string\n local pos = string.find(filepath, \"/[^/]*$\")\n if pos then\n return string.sub(filepath, 1, pos - 1)\n end\n\n return \"\"\nend\n\nlocal files: { string } = {}\ndiscoverFiles(luauRoot, luauRoot, files)\n\n-- Parse, strip, and write per-file AST JSON\nfor _, relativePath in files do\n local fullPath = luauRoot .. \"/\" .. relativePath\n local source = fs.readfiletostring(fullPath)\n local parseResult = syntax.parse(source)\n local stripped = strip(parseResult.root)\n\n local outPath = outputDir .. \"/\" .. relativePath .. \".json\"\n local dir = dirname(outPath)\n if dir ~= \"\" then\n fs.createdirectory(dir, { makeparents = true })\n end\n\n fs.writestringtofile(outPath, json.serialize(stripped))\nend\n\n-- Print file list to stdout (tiny — just paths)\nprint(json.serialize(files :: json.array))\n";
159
+ var parse_ast_default = "local fs = require(\"@std/fs\")\nlocal json = require(\"@std/json\")\nlocal process = require(\"@std/process\")\nlocal syntax = require(\"@std/syntax\")\n\nlocal rawArgs = process.args\nlocal userArgs: { string } = {}\nlocal pastSeparator = false\n\nfor _, arg in rawArgs do\n if pastSeparator then\n table.insert(userArgs, arg)\n elseif arg == \"--\" then\n pastSeparator = true\n end\nend\n\nlocal luauRoot = userArgs[1]\nif not luauRoot then\n error(\"Usage: lute run parse-ast.luau -- <file.luau | luau-root> [output-dir]\")\nend\n\nluauRoot = string.gsub(luauRoot, \"\\\\\", \"/\")\n\n-- Fields to keep per AST tag (beyond tag/kind/location which are always kept).\n-- Tags shared by stat/expr variants are merged — nil fields are harmless.\nlocal KEEP: { [string]: { string } } = {\n assign = { \"values\", \"variables\" },\n binary = { \"lhsOperand\", \"rhsOperand\" },\n block = { \"statements\" },\n boolean = { \"value\" },\n call = { \"arguments\", \"func\" },\n cast = { \"operand\" },\n compoundassign = { \"value\", \"variable\" },\n conditional = { \"condition\", \"thenBlock\", \"elseifs\", \"elseBlock\", \"thenExpr\", \"elseExpr\" },\n [\"do\"] = { \"body\" },\n expression = { \"expression\" },\n [\"for\"] = { \"body\", \"from\", \"to\", \"step\" },\n forin = { \"body\", \"values\" },\n [\"function\"] = { \"body\", \"name\", \"func\" },\n global = { \"name\" },\n group = { \"expression\" },\n index = { \"expression\", \"index\" },\n indexname = { \"expression\", \"accessor\", \"index\" },\n instantiate = { \"expr\" },\n interpolatedstring = { \"expressions\" },\n [\"local\"] = { \"values\", \"variables\" },\n localfunction = { \"name\", \"func\" },\n number = { \"value\" },\n [\"repeat\"] = { \"body\", \"condition\" },\n [\"return\"] = { \"expressions\" },\n string = { \"text\" },\n table = { \"entries\" },\n unary = { \"operand\" },\n [\"while\"] = { \"body\", \"condition\" },\n}\n\nlocal function strip(value: any): any\n if type(value) ~= \"table\" then\n return value\n end\n\n -- LuauSpan — has beginLine, no tag\n if value.beginLine ~= nil then\n return value\n end\n\n -- Token — has text but no tag, reduce to {text}\n if value.text ~= nil and value.tag == nil then\n return { text = value.text }\n end\n\n -- AST node — has tag, keep only allowlisted fields\n if value.tag ~= nil then\n local result = { tag = value.tag, kind = value.kind, location = value.location }\n local fields = KEEP[value.tag :: string]\n if fields then\n for _, field in fields do\n if value[field] ~= nil then\n result[field] = strip(value[field])\n end\n end\n end\n\n return result\n end\n\n -- Other tables (arrays, Pairs, ElseIf structs) — recurse all fields\n local result: any = {}\n for k, v in value do\n result[k] = strip(v)\n end\n\n return result\nend\n\n-- Single-file mode: parse one file, print stripped AST to stdout\nif string.sub(luauRoot, -5) == \".luau\" or string.sub(luauRoot, -4) == \".lua\" then\n local source = fs.readfiletostring(luauRoot)\n local parseResult = syntax.parse(source)\n print(json.serialize(strip(parseResult.root)))\n return\nend\n\nlocal outputDir = userArgs[2]\nif not outputDir then\n error(\"Usage: lute run parse-ast.luau -- <luau-root> <output-dir>\")\nend\n\noutputDir = string.gsub(outputDir, \"\\\\\", \"/\")\n\n-- Discover .luau files recursively, skipping node_modules, dot dirs, spec/test files\nlocal function discoverFiles(directory: string, relativeTo: string, results: { string })\n local entries = fs.listdirectory(directory)\n for _, entry in entries do\n local fullPath = directory .. \"/\" .. entry.name\n if entry.type == \"dir\" then\n if entry.name == \"node_modules\" or entry.name == \".jest-roblox-coverage\" then\n continue\n end\n\n if string.sub(entry.name, 1, 1) == \".\" then\n continue\n end\n\n discoverFiles(fullPath, relativeTo, results)\n elseif\n entry.type == \"file\"\n and (string.sub(entry.name, -5) == \".luau\" or string.sub(entry.name, -4) == \".lua\")\n then\n if\n string.sub(entry.name, -10) == \".spec.luau\"\n or string.sub(entry.name, -10) == \".test.luau\"\n or string.sub(entry.name, -9) == \".spec.lua\"\n or string.sub(entry.name, -9) == \".test.lua\"\n or string.sub(entry.name, -10) == \".snap.luau\"\n or string.sub(entry.name, -9) == \".snap.lua\"\n then\n continue\n end\n\n -- Compute relative path\n local relative = string.sub(fullPath, #relativeTo + 2)\n table.insert(results, relative)\n end\n end\nend\n\nlocal function dirname(filepath: string): string\n local pos = string.find(filepath, \"/[^/]*$\")\n if pos then\n return string.sub(filepath, 1, pos - 1)\n end\n\n return \"\"\nend\n\nlocal files: { string } = {}\ndiscoverFiles(luauRoot, luauRoot, files)\n\n-- Parse, strip, and write per-file AST JSON\nfor _, relativePath in files do\n local fullPath = luauRoot .. \"/\" .. relativePath\n local source = fs.readfiletostring(fullPath)\n local parseResult = syntax.parse(source)\n local stripped = strip(parseResult.root)\n\n local outPath = outputDir .. \"/\" .. relativePath .. \".json\"\n local dir = dirname(outPath)\n if dir ~= \"\" then\n fs.createdirectory(dir, { makeparents = true })\n end\n\n fs.writestringtofile(outPath, json.serialize(stripped))\nend\n\n-- Print file list to stdout (tiny — just paths)\nprint(json.serialize(files :: json.array))\n";
160
160
  //#endregion
161
161
  //#region src/config/luau-config-loader.ts
162
162
  let cachedTemporaryDirectory$1;
@@ -1171,13 +1171,13 @@ function visitStatDo(node, visitor) {
1171
1171
  function visitStatIf(node, visitor) {
1172
1172
  if (visitor.visitStatIf?.(node) === false) return;
1173
1173
  visitExpression(node.condition, visitor);
1174
- visitStatBlock(node.thenblock, visitor);
1174
+ visitStatBlock(node.thenBlock, visitor);
1175
1175
  for (const elseif of node.elseifs) visitElseIfStat(elseif, visitor);
1176
- if (node.elseblock) visitStatBlock(node.elseblock, visitor);
1176
+ if (node.elseBlock) visitStatBlock(node.elseBlock, visitor);
1177
1177
  }
1178
1178
  function visitElseIfStat(node, visitor) {
1179
1179
  visitExpression(node.condition, visitor);
1180
- visitStatBlock(node.thenblock, visitor);
1180
+ visitStatBlock(node.thenBlock, visitor);
1181
1181
  }
1182
1182
  function visitStatWhile(node, visitor) {
1183
1183
  if (visitor.visitStatWhile?.(node) === false) return;
@@ -1248,8 +1248,8 @@ function visitExprUnary(node, visitor) {
1248
1248
  }
1249
1249
  function visitExprBinary(node, visitor) {
1250
1250
  if (visitor.visitExprBinary?.(node) === false) return;
1251
- visitExpression(node.lhsoperand, visitor);
1252
- visitExpression(node.rhsoperand, visitor);
1251
+ visitExpression(node.lhsOperand, visitor);
1252
+ visitExpression(node.rhsOperand, visitor);
1253
1253
  }
1254
1254
  function visitExprTable(node, visitor) {
1255
1255
  if (visitor.visitExprTable?.(node) === false) return;
@@ -1284,13 +1284,13 @@ function visitExprTypeAssertion(node, visitor) {
1284
1284
  function visitExprIfElse(node, visitor) {
1285
1285
  if (visitor.visitExprIfElse?.(node) === false) return;
1286
1286
  visitExpression(node.condition, visitor);
1287
- visitExpression(node.thenexpr, visitor);
1287
+ visitExpression(node.thenExpr, visitor);
1288
1288
  for (const elseif of node.elseifs) visitElseIfExpr(elseif, visitor);
1289
- visitExpression(node.elseexpr, visitor);
1289
+ visitExpression(node.elseExpr, visitor);
1290
1290
  }
1291
1291
  function visitElseIfExpr(node, visitor) {
1292
1292
  visitExpression(node.condition, visitor);
1293
- visitExpression(node.thenexpr, visitor);
1293
+ visitExpression(node.thenExpr, visitor);
1294
1294
  }
1295
1295
  function visitExprInstantiate(node, visitor) {
1296
1296
  if (visitor.visitExprInstantiate?.(node) === false) return;
@@ -1350,36 +1350,36 @@ function collectCoverage(root) {
1350
1350
  branch.arms.push({
1351
1351
  bodyFirstColumn: 0,
1352
1352
  bodyFirstLine: 0,
1353
- location: { ...node.thenexpr.location }
1353
+ location: { ...node.thenExpr.location }
1354
1354
  });
1355
1355
  exprIfProbes.push({
1356
1356
  armIndex,
1357
1357
  branchIndex,
1358
- exprLocation: { ...node.thenexpr.location }
1358
+ exprLocation: { ...node.thenExpr.location }
1359
1359
  });
1360
1360
  armIndex++;
1361
1361
  for (const elseif of node.elseifs) {
1362
1362
  branch.arms.push({
1363
1363
  bodyFirstColumn: 0,
1364
1364
  bodyFirstLine: 0,
1365
- location: { ...elseif.thenexpr.location }
1365
+ location: { ...elseif.thenExpr.location }
1366
1366
  });
1367
1367
  exprIfProbes.push({
1368
1368
  armIndex,
1369
1369
  branchIndex,
1370
- exprLocation: { ...elseif.thenexpr.location }
1370
+ exprLocation: { ...elseif.thenExpr.location }
1371
1371
  });
1372
1372
  armIndex++;
1373
1373
  }
1374
1374
  branch.arms.push({
1375
1375
  bodyFirstColumn: 0,
1376
1376
  bodyFirstLine: 0,
1377
- location: { ...node.elseexpr.location }
1377
+ location: { ...node.elseExpr.location }
1378
1378
  });
1379
1379
  exprIfProbes.push({
1380
1380
  armIndex,
1381
1381
  branchIndex,
1382
- exprLocation: { ...node.elseexpr.location }
1382
+ exprLocation: { ...node.elseExpr.location }
1383
1383
  });
1384
1384
  branches.push(branch);
1385
1385
  branchIndex++;
@@ -1415,21 +1415,21 @@ function collectCoverage(root) {
1415
1415
  branchType: "if",
1416
1416
  index: branchIndex
1417
1417
  };
1418
- const thenFirst = getBodyFirstStatement(node.thenblock);
1418
+ const thenFirst = getBodyFirstStatement(node.thenBlock);
1419
1419
  branch.arms.push({
1420
1420
  bodyFirstColumn: thenFirst.column,
1421
1421
  bodyFirstLine: thenFirst.line,
1422
- location: { ...node.thenblock.location }
1422
+ location: { ...node.thenBlock.location }
1423
1423
  });
1424
1424
  for (const elseif of node.elseifs) {
1425
- const elseifFirst = getBodyFirstStatement(elseif.thenblock);
1425
+ const elseifFirst = getBodyFirstStatement(elseif.thenBlock);
1426
1426
  branch.arms.push({
1427
1427
  bodyFirstColumn: elseifFirst.column,
1428
1428
  bodyFirstLine: elseifFirst.line,
1429
- location: { ...elseif.thenblock.location }
1429
+ location: { ...elseif.thenBlock.location }
1430
1430
  });
1431
1431
  }
1432
- const elseBlock = node.elseblock;
1432
+ const { elseBlock } = node;
1433
1433
  const hasExplicitElse = elseBlock !== void 0 && elseBlock.statements.length > 0;
1434
1434
  if (hasExplicitElse) {
1435
1435
  const elseFirst = getBodyFirstStatement(elseBlock);
Binary file
@@ -7391,14 +7391,14 @@ const e$13 = globalThis.process?.env || Object.create(null), t$14 = globalThis.p
7391
7391
  [`gemini`, [`GEMINI_CLI`]],
7392
7392
  [`codex`, [`CODEX_SANDBOX`, `CODEX_THREAD_ID`]],
7393
7393
  [`opencode`, [`OPENCODE`]],
7394
- [`pi`, [i$19(`PATH`, /\.pi[\\/]agent/)]],
7394
+ [`pi`, [i$20(`PATH`, /\.pi[\\/]agent/)]],
7395
7395
  [`auggie`, [`AUGMENT_AGENT`]],
7396
7396
  [`goose`, [`GOOSE_PROVIDER`]],
7397
- [`devin`, [i$19(`EDITOR`, /devin/)]],
7397
+ [`devin`, [i$20(`EDITOR`, /devin/)]],
7398
7398
  [`cursor`, [`CURSOR_AGENT`]],
7399
- [`kiro`, [i$19(`TERM_PROGRAM`, /kiro/)]]
7399
+ [`kiro`, [i$20(`TERM_PROGRAM`, /kiro/)]]
7400
7400
  ];
7401
- function i$19(t, n) {
7401
+ function i$20(t, n) {
7402
7402
  return () => {
7403
7403
  let r = e$13[t];
7404
7404
  return r ? n.test(r) : !1;
@@ -7528,7 +7528,7 @@ const d$6 = u$9();
7528
7528
  d$6.name;
7529
7529
  const p$6 = t$14.platform || ``;
7530
7530
  e$13.CI || d$6.ci;
7531
- const h$7 = !!t$14.stdout?.isTTY;
7531
+ const h$6 = !!t$14.stdout?.isTTY;
7532
7532
  e$13.DEBUG;
7533
7533
  n$13 === `test` || e$13.TEST;
7534
7534
  n$13 === `production` || e$13.MODE;
@@ -7537,7 +7537,7 @@ e$13.MINIMAL;
7537
7537
  const S$4 = /^win/i.test(p$6);
7538
7538
  /^linux/i.test(p$6);
7539
7539
  /^darwin/i.test(p$6);
7540
- !e$13.NO_COLOR && (e$13.FORCE_COLOR || (h$7 || S$4) && e$13.TERM);
7540
+ !e$13.NO_COLOR && (e$13.FORCE_COLOR || (h$6 || S$4) && e$13.TERM);
7541
7541
  const E$6 = (t$14.versions?.node || ``).replace(/^v/, ``) || null;
7542
7542
  Number(E$6?.split(`.`)[0]);
7543
7543
  const O$7 = !!t$14?.versions?.node, k$3 = `Bun` in globalThis, A$4 = `Deno` in globalThis, j$5 = `fastly` in globalThis, M$3 = `Netlify` in globalThis, N$4 = `EdgeRuntime` in globalThis, P$6 = globalThis.navigator?.userAgent === `Cloudflare-Workers`, F$6 = [
@@ -7555,8 +7555,8 @@ function I$4() {
7555
7555
  }
7556
7556
  I$4()?.name;
7557
7557
  //#endregion
7558
- //#region node_modules/.pnpm/tinyrainbow@3.0.3/node_modules/tinyrainbow/dist/index.js
7559
- var d$5 = {
7558
+ //#region node_modules/.pnpm/tinyrainbow@3.1.0/node_modules/tinyrainbow/dist/index.js
7559
+ var b$3 = {
7560
7560
  reset: [0, 0],
7561
7561
  bold: [
7562
7562
  1,
@@ -7607,39 +7607,39 @@ var d$5 = {
7607
7607
  bgCyanBright: [106, 49],
7608
7608
  bgWhiteBright: [107, 49]
7609
7609
  };
7610
- function g$3(e) {
7610
+ function i$19(e) {
7611
7611
  return String(e);
7612
7612
  }
7613
- g$3.open = "";
7614
- g$3.close = "";
7615
- function h$6() {
7616
- let e = typeof process != "undefined" ? process : void 0, n = (e == null ? void 0 : e.env) || {}, a = n.FORCE_TTY !== "false", i = (e == null ? void 0 : e.argv) || [];
7617
- return !("NO_COLOR" in n || i.includes("--no-color")) && ("FORCE_COLOR" in n || i.includes("--color") || (e == null ? void 0 : e.platform) === "win32" || a && n.TERM !== "dumb" || "CI" in n) || typeof window != "undefined" && !!window.chrome;
7613
+ i$19.open = "";
7614
+ i$19.close = "";
7615
+ function B$1() {
7616
+ let e = typeof process != "undefined" ? process : void 0, r = (e == null ? void 0 : e.env) || {}, a = r.FORCE_TTY !== "false", l = (e == null ? void 0 : e.argv) || [];
7617
+ return !("NO_COLOR" in r || l.includes("--no-color")) && ("FORCE_COLOR" in r || l.includes("--color") || (e == null ? void 0 : e.platform) === "win32" || a && r.TERM !== "dumb" || "CI" in r) || typeof window != "undefined" && !!window.chrome;
7618
7618
  }
7619
- function f$9() {
7620
- let e = h$6(), n = (r, t, u, o) => {
7621
- let l = "", s = 0;
7619
+ function C$5({ force: e } = {}) {
7620
+ let r = e || B$1(), a = (t, o, u, n) => {
7621
+ let g = "", s = 0;
7622
7622
  do
7623
- l += r.substring(s, o) + u, s = o + t.length, o = r.indexOf(t, s);
7624
- while (~o);
7625
- return l + r.substring(s);
7626
- }, a = (r, t, u = r) => {
7627
- let o = (l) => {
7628
- let s = String(l), b = s.indexOf(t, r.length);
7629
- return ~b ? r + n(s, t, u, b) + t : r + s + t;
7630
- };
7631
- return o.open = r, o.close = t, o;
7632
- }, i = { isColorSupported: e }, c = (r) => `\x1B[${r}m`;
7633
- for (let r in d$5) {
7634
- let t = d$5[r];
7635
- i[r] = e ? a(c(t[0]), c(t[1]), t[2]) : g$3;
7623
+ g += t.substring(s, n) + u, s = n + o.length, n = t.indexOf(o, s);
7624
+ while (~n);
7625
+ return g + t.substring(s);
7626
+ }, l = (t, o, u = t) => {
7627
+ let n = (g) => {
7628
+ let s = String(g), h = s.indexOf(o, t.length);
7629
+ return ~h ? t + a(s, o, u, h) + o : t + s + o;
7630
+ };
7631
+ return n.open = t, n.close = o, n;
7632
+ }, c = { isColorSupported: r }, f = (t) => `\x1B[${t}m`;
7633
+ for (let t in b$3) {
7634
+ let o = b$3[t];
7635
+ c[t] = r ? l(f(o[0]), f(o[1]), o[2]) : i$19;
7636
7636
  }
7637
- return i;
7637
+ return c;
7638
7638
  }
7639
- var C$5 = f$9();
7639
+ var y$6 = C$5();
7640
7640
  //#endregion
7641
7641
  //#region package.json
7642
- var version = "0.2.0";
7642
+ var version = "0.2.1";
7643
7643
  //#endregion
7644
7644
  //#region node_modules/.pnpm/ws@8.18.0/node_modules/ws/lib/stream.js
7645
7645
  var require_stream = /* @__PURE__ */ __commonJSMin(((exports, module) => {
@@ -42822,12 +42822,12 @@ function hasExecError(file) {
42822
42822
  const SEPARATOR$1 = "⎯";
42823
42823
  const levelStyles = {
42824
42824
  error: {
42825
- badge: (text) => C$5.bgRed(C$5.white(C$5.bold(text))),
42826
- separator: C$5.red
42825
+ badge: (text) => y$6.bgRed(y$6.white(y$6.bold(text))),
42826
+ separator: y$6.red
42827
42827
  },
42828
42828
  warn: {
42829
- badge: (text) => C$5.bgYellow(C$5.black(C$5.bold(text))),
42830
- separator: C$5.yellow
42829
+ badge: (text) => y$6.bgYellow(y$6.black(y$6.bold(text))),
42830
+ separator: y$6.yellow
42831
42831
  }
42832
42832
  };
42833
42833
  function formatBannerBar({ level, termWidth, title }) {
@@ -45435,23 +45435,23 @@ function extname(path) {
45435
45435
  return EXTENSION_NAME_REGEX.exec(normalizeWindowsPath(path))?.[1] ?? "";
45436
45436
  }
45437
45437
  const HLJS_CLASS_TO_COLOR = {
45438
- "hljs-attr": C$5.blue,
45439
- "hljs-built_in": C$5.blue,
45440
- "hljs-comment": C$5.gray,
45441
- "hljs-function": C$5.blue,
45442
- "hljs-keyword": C$5.magenta,
45443
- "hljs-literal": C$5.blue,
45444
- "hljs-meta": C$5.gray,
45445
- "hljs-number": C$5.blue,
45446
- "hljs-operator": C$5.yellow,
45447
- "hljs-params": C$5.white,
45448
- "hljs-punctuation": C$5.yellow,
45449
- "hljs-regexp": C$5.cyan,
45450
- "hljs-string": C$5.green,
45451
- "hljs-subst": C$5.cyan,
45452
- "hljs-title": C$5.blue,
45453
- "hljs-type": C$5.yellow,
45454
- "hljs-variable": C$5.white
45438
+ "hljs-attr": y$6.blue,
45439
+ "hljs-built_in": y$6.blue,
45440
+ "hljs-comment": y$6.gray,
45441
+ "hljs-function": y$6.blue,
45442
+ "hljs-keyword": y$6.magenta,
45443
+ "hljs-literal": y$6.blue,
45444
+ "hljs-meta": y$6.gray,
45445
+ "hljs-number": y$6.blue,
45446
+ "hljs-operator": y$6.yellow,
45447
+ "hljs-params": y$6.white,
45448
+ "hljs-punctuation": y$6.yellow,
45449
+ "hljs-regexp": y$6.cyan,
45450
+ "hljs-string": y$6.green,
45451
+ "hljs-subst": y$6.cyan,
45452
+ "hljs-title": y$6.blue,
45453
+ "hljs-type": y$6.yellow,
45454
+ "hljs-variable": y$6.white
45455
45455
  };
45456
45456
  function convertHljsToAnsi(html) {
45457
45457
  let result = html;
@@ -45472,7 +45472,7 @@ function highlightLuau(source) {
45472
45472
  return convertHljsToAnsi(core_default.highlight(source, { language: "luau" }).value);
45473
45473
  }
45474
45474
  function highlightTypeScript(source) {
45475
- return convertHljsToAnsi(core_default.highlight(source, { language: "typescript" }).value).replace(/=>/g, C$5.yellow("=>"));
45475
+ return convertHljsToAnsi(core_default.highlight(source, { language: "typescript" }).value).replace(/=>/g, y$6.yellow("=>"));
45476
45476
  }
45477
45477
  //#endregion
45478
45478
  //#region src/formatters/formatter.ts
@@ -45700,19 +45700,19 @@ function formatTypecheckSummary(result, useColor = true) {
45700
45700
  return parts.join("\n");
45701
45701
  }
45702
45702
  const PROJECT_BADGE_COLORS = [
45703
- (text) => C$5.bgYellow(C$5.black(text)),
45704
- (text) => C$5.bgCyan(C$5.black(text)),
45705
- (text) => C$5.bgGreen(C$5.black(text)),
45706
- (text) => C$5.bgMagenta(C$5.black(text))
45703
+ (text) => y$6.bgYellow(y$6.black(text)),
45704
+ (text) => y$6.bgCyan(y$6.black(text)),
45705
+ (text) => y$6.bgGreen(y$6.black(text)),
45706
+ (text) => y$6.bgMagenta(y$6.black(text))
45707
45707
  ];
45708
45708
  const NAMED_BADGE_COLORS = {
45709
- blue: (text) => C$5.bgBlue(C$5.white(text)),
45710
- cyan: (text) => C$5.bgCyan(C$5.black(text)),
45711
- green: (text) => C$5.bgGreen(C$5.black(text)),
45712
- magenta: (text) => C$5.bgMagenta(C$5.black(text)),
45713
- red: (text) => C$5.bgRed(C$5.white(text)),
45714
- white: (text) => C$5.bgWhite(C$5.black(text)),
45715
- yellow: (text) => C$5.bgYellow(C$5.black(text))
45709
+ blue: (text) => y$6.bgBlue(y$6.white(text)),
45710
+ cyan: (text) => y$6.bgCyan(y$6.black(text)),
45711
+ green: (text) => y$6.bgGreen(y$6.black(text)),
45712
+ magenta: (text) => y$6.bgMagenta(y$6.black(text)),
45713
+ red: (text) => y$6.bgRed(y$6.white(text)),
45714
+ white: (text) => y$6.bgWhite(y$6.black(text)),
45715
+ yellow: (text) => y$6.bgYellow(y$6.black(text))
45716
45716
  };
45717
45717
  function formatProjectBadge(displayName, useColor, displayColor) {
45718
45718
  if (!useColor) return `▶ ${displayName}`;
@@ -45829,27 +45829,27 @@ function createStyles(useColor) {
45829
45829
  };
45830
45830
  return {
45831
45831
  diff: {
45832
- expected: C$5.green,
45833
- received: C$5.red
45832
+ expected: y$6.green,
45833
+ received: y$6.red
45834
45834
  },
45835
- dim: C$5.dim,
45836
- failBadge: (text) => C$5.bgRed(C$5.white(C$5.bold(text))),
45837
- lineNumber: C$5.gray,
45838
- location: C$5.cyan,
45835
+ dim: y$6.dim,
45836
+ failBadge: (text) => y$6.bgRed(y$6.white(y$6.bold(text))),
45837
+ lineNumber: y$6.gray,
45838
+ location: y$6.cyan,
45839
45839
  path: {
45840
- dir: C$5.dim,
45841
- file: C$5.bold
45840
+ dir: y$6.dim,
45841
+ file: y$6.bold
45842
45842
  },
45843
- runBadge: (text) => C$5.bgCyan(C$5.black(C$5.bold(text))),
45843
+ runBadge: (text) => y$6.bgCyan(y$6.black(y$6.bold(text))),
45844
45844
  status: {
45845
- fail: C$5.red,
45846
- pass: C$5.green,
45847
- pending: C$5.yellow
45845
+ fail: y$6.red,
45846
+ pass: y$6.green,
45847
+ pending: y$6.yellow
45848
45848
  },
45849
45849
  summary: {
45850
- failed: (text) => C$5.bold(C$5.red(text)),
45851
- passed: (text) => C$5.bold(C$5.green(text)),
45852
- pending: (text) => C$5.bold(C$5.yellow(text))
45850
+ failed: (text) => y$6.bold(y$6.red(text)),
45851
+ passed: (text) => y$6.bold(y$6.green(text)),
45852
+ pending: (text) => y$6.bold(y$6.yellow(text))
45853
45853
  }
45854
45854
  };
45855
45855
  }
@@ -46093,7 +46093,7 @@ function formatDiffBlock(parsed, styles) {
46093
46093
  return [];
46094
46094
  }
46095
46095
  function formatErrorLine(parsed, styles, useColor) {
46096
- if (useColor && parsed.message.startsWith("Error:")) return styles.status.fail(C$5.bold("Error:") + parsed.message.slice(6));
46096
+ if (useColor && parsed.message.startsWith("Error:")) return styles.status.fail(y$6.bold("Error:") + parsed.message.slice(6));
46097
46097
  return styles.status.fail(parsed.message);
46098
46098
  }
46099
46099
  function formatFallbackSnippet(message, styles, useColor) {
@@ -46888,7 +46888,7 @@ function writeSnapshots(snapshotWrites, config, tsconfigMappings) {
46888
46888
  if (written > 0) node_process.default.stderr.write(`Wrote ${String(written)} snapshot file${written === 1 ? "" : "s"}\n`);
46889
46889
  } catch (err) {
46890
46890
  if (err instanceof SyntaxError) node_process.default.stderr.write(formatBanner({
46891
- body: [C$5.red(`Failed to parse rojo project: ${err.message}`), ` ${C$5.dim("File:")} ${rojoProjectPath}`],
46891
+ body: [y$6.red(`Failed to parse rojo project: ${err.message}`), ` ${y$6.dim("File:")} ${rojoProjectPath}`],
46892
46892
  level: "warn",
46893
46893
  title: "Snapshot Warning"
46894
46894
  }));
@@ -46942,7 +46942,7 @@ function evalTable(entries) {
46942
46942
  }
46943
46943
  //#endregion
46944
46944
  //#region src/luau/parse-ast.luau
46945
- var parse_ast_default = "local fs = require(\"@std/fs\")\nlocal json = require(\"@std/json\")\nlocal process = require(\"@std/process\")\nlocal syntax = require(\"@std/syntax\")\n\nlocal rawArgs = process.args\nlocal userArgs: { string } = {}\nlocal pastSeparator = false\n\nfor _, arg in rawArgs do\n if pastSeparator then\n table.insert(userArgs, arg)\n elseif arg == \"--\" then\n pastSeparator = true\n end\nend\n\nlocal luauRoot = userArgs[1]\nif not luauRoot then\n error(\"Usage: lute run parse-ast.luau -- <file.luau | luau-root> [output-dir]\")\nend\n\nluauRoot = string.gsub(luauRoot, \"\\\\\", \"/\")\n\n-- Fields to keep per AST tag (beyond tag/kind/location which are always kept).\n-- Tags shared by stat/expr variants are merged — nil fields are harmless.\nlocal KEEP: { [string]: { string } } = {\n assign = { \"values\", \"variables\" },\n binary = { \"lhsoperand\", \"rhsoperand\" },\n block = { \"statements\" },\n boolean = { \"value\" },\n call = { \"arguments\", \"func\" },\n cast = { \"operand\" },\n compoundassign = { \"value\", \"variable\" },\n conditional = { \"condition\", \"thenblock\", \"elseifs\", \"elseblock\", \"thenexpr\", \"elseexpr\" },\n [\"do\"] = { \"body\" },\n expression = { \"expression\" },\n [\"for\"] = { \"body\", \"from\", \"to\", \"step\" },\n forin = { \"body\", \"values\" },\n [\"function\"] = { \"body\", \"name\", \"func\" },\n global = { \"name\" },\n group = { \"expression\" },\n index = { \"expression\", \"index\" },\n indexname = { \"expression\", \"accessor\", \"index\" },\n instantiate = { \"expr\" },\n interpolatedstring = { \"expressions\" },\n [\"local\"] = { \"values\", \"variables\" },\n localfunction = { \"name\", \"func\" },\n number = { \"value\" },\n [\"repeat\"] = { \"body\", \"condition\" },\n [\"return\"] = { \"expressions\" },\n string = { \"text\" },\n table = { \"entries\" },\n unary = { \"operand\" },\n [\"while\"] = { \"body\", \"condition\" },\n}\n\nlocal function strip(value: any): any\n if type(value) ~= \"table\" then\n return value\n end\n\n -- LuauSpan — has beginLine, no tag\n if value.beginLine ~= nil then\n return value\n end\n\n -- Token — has text but no tag, reduce to {text}\n if value.text ~= nil and value.tag == nil then\n return { text = value.text }\n end\n\n -- AST node — has tag, keep only allowlisted fields\n if value.tag ~= nil then\n local result = { tag = value.tag, kind = value.kind, location = value.location }\n local fields = KEEP[value.tag :: string]\n if fields then\n for _, field in fields do\n if value[field] ~= nil then\n result[field] = strip(value[field])\n end\n end\n end\n\n return result\n end\n\n -- Other tables (arrays, Pairs, ElseIf structs) — recurse all fields\n local result: any = {}\n for k, v in value do\n result[k] = strip(v)\n end\n\n return result\nend\n\n-- Single-file mode: parse one file, print stripped AST to stdout\nif string.sub(luauRoot, -5) == \".luau\" or string.sub(luauRoot, -4) == \".lua\" then\n local source = fs.readfiletostring(luauRoot)\n local parseResult = syntax.parse(source)\n print(json.serialize(strip(parseResult.root)))\n return\nend\n\nlocal outputDir = userArgs[2]\nif not outputDir then\n error(\"Usage: lute run parse-ast.luau -- <luau-root> <output-dir>\")\nend\n\noutputDir = string.gsub(outputDir, \"\\\\\", \"/\")\n\n-- Discover .luau files recursively, skipping node_modules, dot dirs, spec/test files\nlocal function discoverFiles(directory: string, relativeTo: string, results: { string })\n local entries = fs.listdirectory(directory)\n for _, entry in entries do\n local fullPath = directory .. \"/\" .. entry.name\n if entry.type == \"dir\" then\n if entry.name == \"node_modules\" or entry.name == \".jest-roblox-coverage\" then\n continue\n end\n\n if string.sub(entry.name, 1, 1) == \".\" then\n continue\n end\n\n discoverFiles(fullPath, relativeTo, results)\n elseif\n entry.type == \"file\"\n and (string.sub(entry.name, -5) == \".luau\" or string.sub(entry.name, -4) == \".lua\")\n then\n if\n string.sub(entry.name, -10) == \".spec.luau\"\n or string.sub(entry.name, -10) == \".test.luau\"\n or string.sub(entry.name, -9) == \".spec.lua\"\n or string.sub(entry.name, -9) == \".test.lua\"\n or string.sub(entry.name, -10) == \".snap.luau\"\n or string.sub(entry.name, -9) == \".snap.lua\"\n then\n continue\n end\n\n -- Compute relative path\n local relative = string.sub(fullPath, #relativeTo + 2)\n table.insert(results, relative)\n end\n end\nend\n\nlocal function dirname(filepath: string): string\n local pos = string.find(filepath, \"/[^/]*$\")\n if pos then\n return string.sub(filepath, 1, pos - 1)\n end\n\n return \"\"\nend\n\nlocal files: { string } = {}\ndiscoverFiles(luauRoot, luauRoot, files)\n\n-- Parse, strip, and write per-file AST JSON\nfor _, relativePath in files do\n local fullPath = luauRoot .. \"/\" .. relativePath\n local source = fs.readfiletostring(fullPath)\n local parseResult = syntax.parse(source)\n local stripped = strip(parseResult.root)\n\n local outPath = outputDir .. \"/\" .. relativePath .. \".json\"\n local dir = dirname(outPath)\n if dir ~= \"\" then\n fs.createdirectory(dir, { makeparents = true })\n end\n\n fs.writestringtofile(outPath, json.serialize(stripped))\nend\n\n-- Print file list to stdout (tiny — just paths)\nprint(json.serialize(files :: json.array))\n";
46945
+ var parse_ast_default = "local fs = require(\"@std/fs\")\nlocal json = require(\"@std/json\")\nlocal process = require(\"@std/process\")\nlocal syntax = require(\"@std/syntax\")\n\nlocal rawArgs = process.args\nlocal userArgs: { string } = {}\nlocal pastSeparator = false\n\nfor _, arg in rawArgs do\n if pastSeparator then\n table.insert(userArgs, arg)\n elseif arg == \"--\" then\n pastSeparator = true\n end\nend\n\nlocal luauRoot = userArgs[1]\nif not luauRoot then\n error(\"Usage: lute run parse-ast.luau -- <file.luau | luau-root> [output-dir]\")\nend\n\nluauRoot = string.gsub(luauRoot, \"\\\\\", \"/\")\n\n-- Fields to keep per AST tag (beyond tag/kind/location which are always kept).\n-- Tags shared by stat/expr variants are merged — nil fields are harmless.\nlocal KEEP: { [string]: { string } } = {\n assign = { \"values\", \"variables\" },\n binary = { \"lhsOperand\", \"rhsOperand\" },\n block = { \"statements\" },\n boolean = { \"value\" },\n call = { \"arguments\", \"func\" },\n cast = { \"operand\" },\n compoundassign = { \"value\", \"variable\" },\n conditional = { \"condition\", \"thenBlock\", \"elseifs\", \"elseBlock\", \"thenExpr\", \"elseExpr\" },\n [\"do\"] = { \"body\" },\n expression = { \"expression\" },\n [\"for\"] = { \"body\", \"from\", \"to\", \"step\" },\n forin = { \"body\", \"values\" },\n [\"function\"] = { \"body\", \"name\", \"func\" },\n global = { \"name\" },\n group = { \"expression\" },\n index = { \"expression\", \"index\" },\n indexname = { \"expression\", \"accessor\", \"index\" },\n instantiate = { \"expr\" },\n interpolatedstring = { \"expressions\" },\n [\"local\"] = { \"values\", \"variables\" },\n localfunction = { \"name\", \"func\" },\n number = { \"value\" },\n [\"repeat\"] = { \"body\", \"condition\" },\n [\"return\"] = { \"expressions\" },\n string = { \"text\" },\n table = { \"entries\" },\n unary = { \"operand\" },\n [\"while\"] = { \"body\", \"condition\" },\n}\n\nlocal function strip(value: any): any\n if type(value) ~= \"table\" then\n return value\n end\n\n -- LuauSpan — has beginLine, no tag\n if value.beginLine ~= nil then\n return value\n end\n\n -- Token — has text but no tag, reduce to {text}\n if value.text ~= nil and value.tag == nil then\n return { text = value.text }\n end\n\n -- AST node — has tag, keep only allowlisted fields\n if value.tag ~= nil then\n local result = { tag = value.tag, kind = value.kind, location = value.location }\n local fields = KEEP[value.tag :: string]\n if fields then\n for _, field in fields do\n if value[field] ~= nil then\n result[field] = strip(value[field])\n end\n end\n end\n\n return result\n end\n\n -- Other tables (arrays, Pairs, ElseIf structs) — recurse all fields\n local result: any = {}\n for k, v in value do\n result[k] = strip(v)\n end\n\n return result\nend\n\n-- Single-file mode: parse one file, print stripped AST to stdout\nif string.sub(luauRoot, -5) == \".luau\" or string.sub(luauRoot, -4) == \".lua\" then\n local source = fs.readfiletostring(luauRoot)\n local parseResult = syntax.parse(source)\n print(json.serialize(strip(parseResult.root)))\n return\nend\n\nlocal outputDir = userArgs[2]\nif not outputDir then\n error(\"Usage: lute run parse-ast.luau -- <luau-root> <output-dir>\")\nend\n\noutputDir = string.gsub(outputDir, \"\\\\\", \"/\")\n\n-- Discover .luau files recursively, skipping node_modules, dot dirs, spec/test files\nlocal function discoverFiles(directory: string, relativeTo: string, results: { string })\n local entries = fs.listdirectory(directory)\n for _, entry in entries do\n local fullPath = directory .. \"/\" .. entry.name\n if entry.type == \"dir\" then\n if entry.name == \"node_modules\" or entry.name == \".jest-roblox-coverage\" then\n continue\n end\n\n if string.sub(entry.name, 1, 1) == \".\" then\n continue\n end\n\n discoverFiles(fullPath, relativeTo, results)\n elseif\n entry.type == \"file\"\n and (string.sub(entry.name, -5) == \".luau\" or string.sub(entry.name, -4) == \".lua\")\n then\n if\n string.sub(entry.name, -10) == \".spec.luau\"\n or string.sub(entry.name, -10) == \".test.luau\"\n or string.sub(entry.name, -9) == \".spec.lua\"\n or string.sub(entry.name, -9) == \".test.lua\"\n or string.sub(entry.name, -10) == \".snap.luau\"\n or string.sub(entry.name, -9) == \".snap.lua\"\n then\n continue\n end\n\n -- Compute relative path\n local relative = string.sub(fullPath, #relativeTo + 2)\n table.insert(results, relative)\n end\n end\nend\n\nlocal function dirname(filepath: string): string\n local pos = string.find(filepath, \"/[^/]*$\")\n if pos then\n return string.sub(filepath, 1, pos - 1)\n end\n\n return \"\"\nend\n\nlocal files: { string } = {}\ndiscoverFiles(luauRoot, luauRoot, files)\n\n-- Parse, strip, and write per-file AST JSON\nfor _, relativePath in files do\n local fullPath = luauRoot .. \"/\" .. relativePath\n local source = fs.readfiletostring(fullPath)\n local parseResult = syntax.parse(source)\n local stripped = strip(parseResult.root)\n\n local outPath = outputDir .. \"/\" .. relativePath .. \".json\"\n local dir = dirname(outPath)\n if dir ~= \"\" then\n fs.createdirectory(dir, { makeparents = true })\n end\n\n fs.writestringtofile(outPath, json.serialize(stripped))\nend\n\n-- Print file list to stdout (tiny — just paths)\nprint(json.serialize(files :: json.array))\n";
46946
46946
  //#endregion
46947
46947
  //#region src/config/luau-config-loader.ts
46948
46948
  let cachedTemporaryDirectory$1;
@@ -57785,13 +57785,13 @@ function visitStatDo(node, visitor) {
57785
57785
  function visitStatIf(node, visitor) {
57786
57786
  if (visitor.visitStatIf?.(node) === false) return;
57787
57787
  visitExpression(node.condition, visitor);
57788
- visitStatBlock(node.thenblock, visitor);
57788
+ visitStatBlock(node.thenBlock, visitor);
57789
57789
  for (const elseif of node.elseifs) visitElseIfStat(elseif, visitor);
57790
- if (node.elseblock) visitStatBlock(node.elseblock, visitor);
57790
+ if (node.elseBlock) visitStatBlock(node.elseBlock, visitor);
57791
57791
  }
57792
57792
  function visitElseIfStat(node, visitor) {
57793
57793
  visitExpression(node.condition, visitor);
57794
- visitStatBlock(node.thenblock, visitor);
57794
+ visitStatBlock(node.thenBlock, visitor);
57795
57795
  }
57796
57796
  function visitStatWhile(node, visitor) {
57797
57797
  if (visitor.visitStatWhile?.(node) === false) return;
@@ -57862,8 +57862,8 @@ function visitExprUnary(node, visitor) {
57862
57862
  }
57863
57863
  function visitExprBinary(node, visitor) {
57864
57864
  if (visitor.visitExprBinary?.(node) === false) return;
57865
- visitExpression(node.lhsoperand, visitor);
57866
- visitExpression(node.rhsoperand, visitor);
57865
+ visitExpression(node.lhsOperand, visitor);
57866
+ visitExpression(node.rhsOperand, visitor);
57867
57867
  }
57868
57868
  function visitExprTable(node, visitor) {
57869
57869
  if (visitor.visitExprTable?.(node) === false) return;
@@ -57898,13 +57898,13 @@ function visitExprTypeAssertion(node, visitor) {
57898
57898
  function visitExprIfElse(node, visitor) {
57899
57899
  if (visitor.visitExprIfElse?.(node) === false) return;
57900
57900
  visitExpression(node.condition, visitor);
57901
- visitExpression(node.thenexpr, visitor);
57901
+ visitExpression(node.thenExpr, visitor);
57902
57902
  for (const elseif of node.elseifs) visitElseIfExpr(elseif, visitor);
57903
- visitExpression(node.elseexpr, visitor);
57903
+ visitExpression(node.elseExpr, visitor);
57904
57904
  }
57905
57905
  function visitElseIfExpr(node, visitor) {
57906
57906
  visitExpression(node.condition, visitor);
57907
- visitExpression(node.thenexpr, visitor);
57907
+ visitExpression(node.thenExpr, visitor);
57908
57908
  }
57909
57909
  function visitExprInstantiate(node, visitor) {
57910
57910
  if (visitor.visitExprInstantiate?.(node) === false) return;
@@ -57964,36 +57964,36 @@ function collectCoverage(root) {
57964
57964
  branch.arms.push({
57965
57965
  bodyFirstColumn: 0,
57966
57966
  bodyFirstLine: 0,
57967
- location: { ...node.thenexpr.location }
57967
+ location: { ...node.thenExpr.location }
57968
57968
  });
57969
57969
  exprIfProbes.push({
57970
57970
  armIndex,
57971
57971
  branchIndex,
57972
- exprLocation: { ...node.thenexpr.location }
57972
+ exprLocation: { ...node.thenExpr.location }
57973
57973
  });
57974
57974
  armIndex++;
57975
57975
  for (const elseif of node.elseifs) {
57976
57976
  branch.arms.push({
57977
57977
  bodyFirstColumn: 0,
57978
57978
  bodyFirstLine: 0,
57979
- location: { ...elseif.thenexpr.location }
57979
+ location: { ...elseif.thenExpr.location }
57980
57980
  });
57981
57981
  exprIfProbes.push({
57982
57982
  armIndex,
57983
57983
  branchIndex,
57984
- exprLocation: { ...elseif.thenexpr.location }
57984
+ exprLocation: { ...elseif.thenExpr.location }
57985
57985
  });
57986
57986
  armIndex++;
57987
57987
  }
57988
57988
  branch.arms.push({
57989
57989
  bodyFirstColumn: 0,
57990
57990
  bodyFirstLine: 0,
57991
- location: { ...node.elseexpr.location }
57991
+ location: { ...node.elseExpr.location }
57992
57992
  });
57993
57993
  exprIfProbes.push({
57994
57994
  armIndex,
57995
57995
  branchIndex,
57996
- exprLocation: { ...node.elseexpr.location }
57996
+ exprLocation: { ...node.elseExpr.location }
57997
57997
  });
57998
57998
  branches.push(branch);
57999
57999
  branchIndex++;
@@ -58029,21 +58029,21 @@ function collectCoverage(root) {
58029
58029
  branchType: "if",
58030
58030
  index: branchIndex
58031
58031
  };
58032
- const thenFirst = getBodyFirstStatement(node.thenblock);
58032
+ const thenFirst = getBodyFirstStatement(node.thenBlock);
58033
58033
  branch.arms.push({
58034
58034
  bodyFirstColumn: thenFirst.column,
58035
58035
  bodyFirstLine: thenFirst.line,
58036
- location: { ...node.thenblock.location }
58036
+ location: { ...node.thenBlock.location }
58037
58037
  });
58038
58038
  for (const elseif of node.elseifs) {
58039
- const elseifFirst = getBodyFirstStatement(elseif.thenblock);
58039
+ const elseifFirst = getBodyFirstStatement(elseif.thenBlock);
58040
58040
  branch.arms.push({
58041
58041
  bodyFirstColumn: elseifFirst.column,
58042
58042
  bodyFirstLine: elseifFirst.line,
58043
- location: { ...elseif.thenblock.location }
58043
+ location: { ...elseif.thenBlock.location }
58044
58044
  });
58045
58045
  }
58046
- const elseBlock = node.elseblock;
58046
+ const { elseBlock } = node;
58047
58047
  const hasExplicitElse = elseBlock !== void 0 && elseBlock.statements.length > 0;
58048
58048
  if (hasExplicitElse) {
58049
58049
  const elseFirst = getBodyFirstStatement(elseBlock);
@@ -60575,7 +60575,7 @@ const VALID_REPORTERS = new Set([
60575
60575
  "text-summary"
60576
60576
  ]);
60577
60577
  function printCoverageHeader() {
60578
- const header = ` ${C$5.blue("%")} ${C$5.dim("Coverage report from")} ${C$5.yellow("istanbul")}`;
60578
+ const header = ` ${y$6.blue("%")} ${y$6.dim("Coverage report from")} ${y$6.yellow("istanbul")}`;
60579
60579
  node_process.default.stdout.write(`\n${header}\n`);
60580
60580
  }
60581
60581
  const TEXT_REPORTERS = new Set(["text", "text-summary"]);
@@ -61414,19 +61414,19 @@ function formatGameOutputLines(raw) {
61414
61414
  }
61415
61415
  function printError(err) {
61416
61416
  if (err instanceof ConfigError) {
61417
- const body = [C$5.red(err.message)];
61418
- if (err.hint !== void 0) body.push(`\n ${C$5.dim("Hint:")} ${err.hint}`);
61417
+ const body = [y$6.red(err.message)];
61418
+ if (err.hint !== void 0) body.push(`\n ${y$6.dim("Hint:")} ${err.hint}`);
61419
61419
  node_process.default.stderr.write(formatBanner({
61420
61420
  body,
61421
61421
  level: "error",
61422
61422
  title: "Config Error"
61423
61423
  }));
61424
61424
  } else if (err instanceof LuauScriptError) {
61425
- const body = [C$5.red(err.message)];
61425
+ const body = [y$6.red(err.message)];
61426
61426
  const hint = getLuauErrorHint(err.message);
61427
- if (hint !== void 0) body.push(`\n ${C$5.dim("Hint:")} ${hint}`);
61427
+ if (hint !== void 0) body.push(`\n ${y$6.dim("Hint:")} ${hint}`);
61428
61428
  const gameLines = formatGameOutputLines(err.gameOutput);
61429
- if (gameLines !== void 0) body.push(`\n ${C$5.dim("Game output:")}\n${gameLines}`);
61429
+ if (gameLines !== void 0) body.push(`\n ${y$6.dim("Game output:")}\n${gameLines}`);
61430
61430
  node_process.default.stderr.write(formatBanner({
61431
61431
  body,
61432
61432
  level: "error",
@@ -61445,7 +61445,7 @@ function writeGameOutputIfConfigured(config, gameOutput, options) {
61445
61445
  }
61446
61446
  }
61447
61447
  function printFinalStatus(passed) {
61448
- const badge = passed ? C$5.bgGreen(C$5.black(C$5.bold(" PASS "))) : C$5.bgRed(C$5.white(C$5.bold(" FAIL ")));
61448
+ const badge = passed ? y$6.bgGreen(y$6.black(y$6.bold(" PASS "))) : y$6.bgRed(y$6.white(y$6.bold(" FAIL ")));
61449
61449
  node_process.default.stdout.write(`${badge}\n`);
61450
61450
  }
61451
61451
  function hasFormatter(config, name) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@isentinel/jest-roblox",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Jest-compatible CLI for running roblox-ts tests via Roblox Open Cloud",
5
5
  "keywords": [
6
6
  "jest",
@@ -53,7 +53,7 @@
53
53
  "oxc-parser": "0.120.0",
54
54
  "picomatch": "4.0.4",
55
55
  "std-env": "4.0.0",
56
- "tinyrainbow": "3.0.3",
56
+ "tinyrainbow": "3.1.0",
57
57
  "ws": "8.18.0"
58
58
  },
59
59
  "devDependencies": {