react-doctor 0.9.2-dev.201106e → 0.9.2-dev.b31fd85
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.js +42 -10
- package/dist/lsp.js +7 -2
- package/dist/{run-scan-app-DZ5jGWFf.js → run-scan-app-C9MJnVwv.js} +281 -210
- package/package.json +3 -3
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="3ced4c14-18cb-5b0c-811c-3448b5c2f139")}catch(e){}}();
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import * as NodeChildProcess from "node:child_process";
|
|
5
5
|
import { execFile, execFileSync, spawn, spawnSync } from "node:child_process";
|
|
@@ -78326,6 +78326,7 @@ const BASELINE_FILES_TEMP_DIR_PREFIX = "react-doctor-baseline-";
|
|
|
78326
78326
|
const SCAN_RESULT_CACHE_FILENAME = "scan-cache.json";
|
|
78327
78327
|
const RUN_GIT_MAX_BUFFER_BYTES = 64 * 1024 * 1024;
|
|
78328
78328
|
const GH_DEFAULT_BRANCH_PROBE_TIMEOUT_MS = 5e3;
|
|
78329
|
+
const TUI_REPORT_COMPACT_MAX_ROWS = 29;
|
|
78329
78330
|
const TUI_REPORT_DETAIL_WIDTH_FRACTION = .6;
|
|
78330
78331
|
const CI_TRUST_COMPANIES = "PayPal, Rippling, and Alibaba";
|
|
78331
78332
|
const WELCOME_EXPLANATION_HOLD_MS = 1e3;
|
|
@@ -78343,6 +78344,7 @@ const METRIC = {
|
|
|
78343
78344
|
projectConfigSelected: "project.config_selected",
|
|
78344
78345
|
scanCompleted: "scan.completed",
|
|
78345
78346
|
scanDuration: "scan.duration",
|
|
78347
|
+
scanFeedbackDelay: "scan.feedback_delay",
|
|
78346
78348
|
scanPhaseDuration: "scan.phase_duration",
|
|
78347
78349
|
scanFiles: "scan.files",
|
|
78348
78350
|
scanScore: "scan.score",
|
|
@@ -78374,6 +78376,10 @@ const METRIC = {
|
|
|
78374
78376
|
lspScanCompleted: "lsp.scan.completed",
|
|
78375
78377
|
lspScanDuration: "lsp.scan.duration",
|
|
78376
78378
|
lspScanDiagnostics: "lsp.scan.diagnostics",
|
|
78379
|
+
tuiActionMenuOpened: "tui.action_menu_opened",
|
|
78380
|
+
tuiCompactReportShown: "tui.compact_report_shown",
|
|
78381
|
+
tuiFindingNavigated: "tui.finding_navigated",
|
|
78382
|
+
tuiStackedReportCapped: "tui.stacked_report_capped",
|
|
78377
78383
|
aiTrainingWarningShown: "ai.training.warning_shown",
|
|
78378
78384
|
jsonOutUsed: "json.out_used"
|
|
78379
78385
|
};
|
|
@@ -78418,7 +78424,7 @@ const makeNoopConsole = () => ({
|
|
|
78418
78424
|
});
|
|
78419
78425
|
//#endregion
|
|
78420
78426
|
//#region src/cli/utils/version.ts
|
|
78421
|
-
const VERSION = "0.9.2-dev.
|
|
78427
|
+
const VERSION = "0.9.2-dev.b31fd85";
|
|
78422
78428
|
//#endregion
|
|
78423
78429
|
//#region src/cli/utils/json-mode.ts
|
|
78424
78430
|
let context = null;
|
|
@@ -78776,13 +78782,13 @@ const isDevVersion = (version) => version === "0.0.0" || version.includes("-");
|
|
|
78776
78782
|
* uploads source-map artifacts under, so stack frames symbolicate. Honors the
|
|
78777
78783
|
* standard `SENTRY_RELEASE` override.
|
|
78778
78784
|
*/
|
|
78779
|
-
const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.9.2-dev.
|
|
78785
|
+
const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.9.2-dev.b31fd85`;
|
|
78780
78786
|
/**
|
|
78781
78787
|
* Deployment environment shown in Sentry's environment filter. Defaults to
|
|
78782
78788
|
* `production` for tagged releases and `development` for dev/unbuilt versions,
|
|
78783
78789
|
* overridable via the standard `SENTRY_ENVIRONMENT` env var.
|
|
78784
78790
|
*/
|
|
78785
|
-
const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.9.2-dev.
|
|
78791
|
+
const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.9.2-dev.b31fd85") ? "development" : "production");
|
|
78786
78792
|
/**
|
|
78787
78793
|
* Performance-tracing sample rate in `[0, 1]`. Reads `SENTRY_TRACES_SAMPLE_RATE`
|
|
78788
78794
|
* (set to `0` to disable tracing) and falls back to
|
|
@@ -96100,6 +96106,7 @@ const inspectAction = async (directory, flags, invocationCommand = "inspect") =>
|
|
|
96100
96106
|
const isQuiet = isScoreOnly || isJsonMode;
|
|
96101
96107
|
const requestedDirectory = Path.resolve(directory);
|
|
96102
96108
|
const startTime = performance$1.now();
|
|
96109
|
+
let scanStartupSpinner = null;
|
|
96103
96110
|
if (isJsonMode) {
|
|
96104
96111
|
enableJsonMode({
|
|
96105
96112
|
compact: Boolean(flags.jsonCompact),
|
|
@@ -96233,7 +96240,20 @@ const inspectAction = async (directory, flags, invocationCommand = "inspect") =>
|
|
|
96233
96240
|
return;
|
|
96234
96241
|
}
|
|
96235
96242
|
const projectDirectories = await selectProjects(resolvedDirectory, flags.project, skipPrompts, userConfig?.projects);
|
|
96236
|
-
const
|
|
96243
|
+
const projectSelectionCompletedTime = performance$1.now();
|
|
96244
|
+
let changedFilesDiffInfo = flags.changedFilesFrom ? buildChangedFilesDiffInfo(readChangedFilesFrom(Path.resolve(flags.changedFilesFrom))) : null;
|
|
96245
|
+
if (changedFilesDiffInfo !== null && scanTarget.didRedirectViaRootDir) {
|
|
96246
|
+
const relativeProjectDirectory = resolveProjectRelativeDirectory(requestedDirectory, resolvedDirectory);
|
|
96247
|
+
if (relativeProjectDirectory) {
|
|
96248
|
+
const projectPrefix = `${relativeProjectDirectory}/`;
|
|
96249
|
+
changedFilesDiffInfo = {
|
|
96250
|
+
...changedFilesDiffInfo,
|
|
96251
|
+
changedFiles: changedFilesDiffInfo.changedFiles.flatMap((filePath) => {
|
|
96252
|
+
return filePath.startsWith(projectPrefix) ? [filePath.slice(projectPrefix.length)] : [];
|
|
96253
|
+
})
|
|
96254
|
+
};
|
|
96255
|
+
}
|
|
96256
|
+
}
|
|
96237
96257
|
const requestedScope = resolveScope(flags, userConfig);
|
|
96238
96258
|
const includeUntracked = flags.includeUntracked ?? false;
|
|
96239
96259
|
const scopeRequest = requestedScope.scope === void 0 && changedFilesDiffInfo !== null ? {
|
|
@@ -96241,15 +96261,20 @@ const inspectAction = async (directory, flags, invocationCommand = "inspect") =>
|
|
|
96241
96261
|
scope: "changed"
|
|
96242
96262
|
} : requestedScope;
|
|
96243
96263
|
validateIncludeUntrackedScope(includeUntracked, scopeRequest.scope);
|
|
96264
|
+
scanStartupSpinner = !isQuiet ? spinner("Scanning...").start() : null;
|
|
96265
|
+
if (scanStartupSpinner !== null) recordDistribution(METRIC.scanFeedbackDelay, performance$1.now() - projectSelectionCompletedTime, { unit: "millisecond" });
|
|
96244
96266
|
const wantsDiffMode = scopeRequest.scope !== void 0 && scopeRequest.scope !== "full";
|
|
96245
96267
|
const shouldDetectDiff = changedFilesDiffInfo === null && (wantsDiffMode || scopeRequest.scope === void 0 && !skipPrompts && !isQuiet);
|
|
96246
96268
|
const diffInfo = changedFilesDiffInfo ?? (shouldDetectDiff ? await getDiffInfo(resolvedDirectory, scopeRequest.base, includeUntracked) : null);
|
|
96269
|
+
scanStartupSpinner?.stop();
|
|
96270
|
+
scanStartupSpinner = null;
|
|
96247
96271
|
const scope = await finalizeScope({
|
|
96248
96272
|
requested: scopeRequest,
|
|
96249
96273
|
diffInfo,
|
|
96250
96274
|
skipPrompts,
|
|
96251
96275
|
isQuiet
|
|
96252
96276
|
});
|
|
96277
|
+
scanStartupSpinner = !isQuiet ? spinner("Scanning...").start() : null;
|
|
96253
96278
|
const isDiffMode = scope !== "full";
|
|
96254
96279
|
const comparisonBaseRef = isDiffMode && diffInfo && !diffInfo.isCurrentChanges ? diffInfo.baseSha ? await resolveMergeBaseRef(resolvedDirectory, diffInfo.baseSha) : diffInfo.diffBaseRef ?? await resolveMergeBaseRef(resolvedDirectory, diffInfo.baseBranch) : null;
|
|
96255
96280
|
const baselineRef = scope === "changed" ? comparisonBaseRef : null;
|
|
@@ -96261,6 +96286,8 @@ const inspectAction = async (directory, flags, invocationCommand = "inspect") =>
|
|
|
96261
96286
|
files: [...diffInfo.changedFiles],
|
|
96262
96287
|
includeUntracked
|
|
96263
96288
|
}) : null;
|
|
96289
|
+
scanStartupSpinner?.stop();
|
|
96290
|
+
scanStartupSpinner = null;
|
|
96264
96291
|
if (scope === "lines" && changedLineRanges === null && !isQuiet) {
|
|
96265
96292
|
cliLogger.warn("Could not determine changed lines (no base ref or git diff failed); reporting all issues in changed files.");
|
|
96266
96293
|
cliLogger.break();
|
|
@@ -96404,6 +96431,7 @@ const inspectAction = async (directory, flags, invocationCommand = "inspect") =>
|
|
|
96404
96431
|
}
|
|
96405
96432
|
}
|
|
96406
96433
|
} catch (error) {
|
|
96434
|
+
scanStartupSpinner?.stop();
|
|
96407
96435
|
const isUserError = isExpectedUserError(error);
|
|
96408
96436
|
const sentryEventId = isUserError ? void 0 : await reportErrorToSentry(error);
|
|
96409
96437
|
if (isDebugFlagEnabled()) await flushSentry();
|
|
@@ -97338,6 +97366,7 @@ const COMMAND_FLAG_SPECS = new Map([
|
|
|
97338
97366
|
"--no-color",
|
|
97339
97367
|
"--no-dead-code",
|
|
97340
97368
|
"--no-score",
|
|
97369
|
+
"--no-supply-chain",
|
|
97341
97370
|
"--yes"
|
|
97342
97371
|
]),
|
|
97343
97372
|
longOptionsWithRequiredValues: new Set(["--blocking", "--project"]),
|
|
@@ -97523,15 +97552,17 @@ rules.command("category <category> <severity>").description("Set the severity fo
|
|
|
97523
97552
|
rules.command("ignore-tag <tag>").description("Skip a whole rule family by tag before linting (e.g. design)").option("-c, --cwd <cwd>", "working directory", process.cwd()).action((tag, _options, command) => rulesIgnoreTagAction(tag, command.optsWithGlobals()));
|
|
97524
97553
|
rules.command("unignore-tag <tag>").description("Stop ignoring a tag previously skipped via ignore-tag").option("-c, --cwd <cwd>", "working directory", process.cwd()).action((tag, _options, command) => rulesUnignoreTagAction(tag, command.optsWithGlobals()));
|
|
97525
97554
|
program.command("experimental-lsp", { hidden: false }).description("[experimental] run the React Doctor language server over stdio (for editors)").allowUnknownOption().action(() => {});
|
|
97526
|
-
program.command("experimental-tui [directory]", { hidden: true }).description("[experimental] interactive, scrollable scan report").option("--blocking <level>", "severity that fails CI: error (default), warning, or none (advisory)").option("--color", "force colored output").option("--no-color", "disable colored output (also honors NO_COLOR)").option("--no-dead-code", "skip dead-code analysis").option("--no-score", "skip the score API, the share URL, and crash reporting").option("-p, --project <names>", "scan specific workspace projects (comma-separated, or *)").option("-y, --yes", "skip the project prompt and scan every discovered project").action(async (directory = ".", _localOptions, command) => {
|
|
97555
|
+
program.command("experimental-tui [directory]", { hidden: true }).description("[experimental] interactive, scrollable scan report").option("--blocking <level>", "severity that fails CI: error (default), warning, or none (advisory)").option("--color", "force colored output").option("--no-color", "disable colored output (also honors NO_COLOR)").option("--no-dead-code", "skip dead-code analysis").option("--no-supply-chain", "skip the dependency supply-chain scan").option("--no-score", "skip the score API, the share URL, and crash reporting").option("-p, --project <names>", "scan specific workspace projects (comma-separated, or *)").option("-y, --yes", "skip the project prompt and scan every discovered project").action(async (directory = ".", _localOptions, command) => {
|
|
97527
97556
|
const options = command.optsWithGlobals();
|
|
97528
97557
|
const deadCode = options.deadCode === false ? false : void 0;
|
|
97529
97558
|
const noScore = options.score === false ? true : void 0;
|
|
97559
|
+
const supplyChain = options.supplyChain === false ? false : void 0;
|
|
97530
97560
|
const nodeMajorVersion = Number(process.versions.node.split(".")[0]);
|
|
97531
97561
|
if (process.stdout.isTTY !== true || process.stdin.isTTY !== true || isNonInteractiveEnvironment() || nodeMajorVersion < 22) {
|
|
97532
97562
|
await inspectAction(directory, {
|
|
97533
97563
|
deadCode,
|
|
97534
97564
|
score: options.score === false ? false : void 0,
|
|
97565
|
+
supplyChain,
|
|
97535
97566
|
project: options.project,
|
|
97536
97567
|
yes: options.yes,
|
|
97537
97568
|
blocking: options.blocking
|
|
@@ -97539,12 +97570,13 @@ program.command("experimental-tui [directory]", { hidden: true }).description("[
|
|
|
97539
97570
|
return;
|
|
97540
97571
|
}
|
|
97541
97572
|
recordCount(METRIC.cliInvoked, 1, { command: "experimental-tui" });
|
|
97542
|
-
const { runScanApp } = await import("./run-scan-app-
|
|
97573
|
+
const { runScanApp } = await import("./run-scan-app-C9MJnVwv.js");
|
|
97543
97574
|
const { shouldFail } = await runScanApp({
|
|
97544
97575
|
directory,
|
|
97545
97576
|
options: {
|
|
97546
97577
|
deadCode,
|
|
97547
|
-
noScore
|
|
97578
|
+
noScore,
|
|
97579
|
+
supplyChain
|
|
97548
97580
|
},
|
|
97549
97581
|
projectFlag: options.project,
|
|
97550
97582
|
skipPrompts: options.yes ?? false,
|
|
@@ -97578,7 +97610,7 @@ Promise.resolve().then(() => assertNoRemovedFlags(process.argv)).then(() => prog
|
|
|
97578
97610
|
handleError(error, { sentryEventId });
|
|
97579
97611
|
});
|
|
97580
97612
|
//#endregion
|
|
97581
|
-
export { toForwardSlashes as A,
|
|
97613
|
+
export { toForwardSlashes as A, getCategoryImpact as B, buildRulePriorityMap as C, resolveBlockingLevel as D, formatLearnMoreLine as E, TUI_REPORT_DETAIL_WIDTH_FRACTION as F, runPromise as G, mapWithConcurrency as H, isCiEnvironment as I, succeed$3 as J, sync as K, DIAGNOSTIC_CATEGORY_BUCKETS as L, isUnicodeSupported as M, METRIC as N, isReactDoctorWorkflowInstalled as O, TUI_REPORT_COMPACT_MAX_ROWS as P, Progress as R, hasLintHardFailure as S, formatFixRecipeLine as T, mergeReactDoctorConfigs as U, highlighter as V, resolveScanTarget as W, canAnimateOnboarding as _, resolveCliInspectOptions as a, buildCodeFrame as b, detectLaunchableAgents as c, launchCliAgent as d, isShareOptedOut as f, doctorFace as g, easeOutCubic as h, selectProjects as i, findNearestPackageDirectory as j, recordCount as k, CLI_AGENT_BINARIES as l, printFooter as m, shouldFailScanGate as n, countUniqueScannedFiles as o, inspect as p, void_ as q, discoverWorkspacePackages as r, setUpGitHubActions as s, exitGracefully as t, copyToClipboard as u, computeProjectedScore as v, buildSortedRuleGroups as w, buildNoScoreMessage as x, formatElapsedTime as y, Reporter as z };
|
|
97582
97614
|
|
|
97583
97615
|
//# sourceMappingURL=cli.js.map
|
|
97584
|
-
//# debugId=
|
|
97616
|
+
//# debugId=3ced4c14-18cb-5b0c-811c-3448b5c2f139
|
package/dist/lsp.js
CHANGED
|
@@ -76182,6 +76182,7 @@ const METRIC = {
|
|
|
76182
76182
|
projectConfigSelected: "project.config_selected",
|
|
76183
76183
|
scanCompleted: "scan.completed",
|
|
76184
76184
|
scanDuration: "scan.duration",
|
|
76185
|
+
scanFeedbackDelay: "scan.feedback_delay",
|
|
76185
76186
|
scanPhaseDuration: "scan.phase_duration",
|
|
76186
76187
|
scanFiles: "scan.files",
|
|
76187
76188
|
scanScore: "scan.score",
|
|
@@ -76213,6 +76214,10 @@ const METRIC = {
|
|
|
76213
76214
|
lspScanCompleted: "lsp.scan.completed",
|
|
76214
76215
|
lspScanDuration: "lsp.scan.duration",
|
|
76215
76216
|
lspScanDiagnostics: "lsp.scan.diagnostics",
|
|
76217
|
+
tuiActionMenuOpened: "tui.action_menu_opened",
|
|
76218
|
+
tuiCompactReportShown: "tui.compact_report_shown",
|
|
76219
|
+
tuiFindingNavigated: "tui.finding_navigated",
|
|
76220
|
+
tuiStackedReportCapped: "tui.stacked_report_capped",
|
|
76216
76221
|
aiTrainingWarningShown: "ai.training.warning_shown",
|
|
76217
76222
|
jsonOutUsed: "json.out_used"
|
|
76218
76223
|
};
|
|
@@ -76514,5 +76519,5 @@ const startLanguageServer = () => {
|
|
|
76514
76519
|
};
|
|
76515
76520
|
//#endregion
|
|
76516
76521
|
export { startLanguageServer };
|
|
76517
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
76518
|
-
//# debugId=
|
|
76522
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="26eb6ceb-bf30-5c1a-b80b-534117e1557d")}catch(e){}}();
|
|
76523
|
+
//# debugId=26eb6ceb-bf30-5c1a-b80b-534117e1557d
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
3
|
-
import { A as toForwardSlashes, B as
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="90f58187-6a1d-56d1-a411-800f7bc51d28")}catch(e){}}();
|
|
3
|
+
import { A as toForwardSlashes, B as getCategoryImpact, C as buildRulePriorityMap, D as resolveBlockingLevel, E as formatLearnMoreLine, F as TUI_REPORT_DETAIL_WIDTH_FRACTION, G as runPromise, H as mapWithConcurrency, I as isCiEnvironment, J as succeed, K as sync, L as DIAGNOSTIC_CATEGORY_BUCKETS, M as isUnicodeSupported, N as METRIC, O as isReactDoctorWorkflowInstalled, P as TUI_REPORT_COMPACT_MAX_ROWS, R as Progress, S as hasLintHardFailure, T as formatFixRecipeLine, U as mergeReactDoctorConfigs, V as highlighter, W as resolveScanTarget, _ as canAnimateOnboarding, a as resolveCliInspectOptions, b as buildCodeFrame, c as detectLaunchableAgents, d as launchCliAgent, f as isShareOptedOut, g as doctorFace, h as easeOutCubic, i as selectProjects, j as findNearestPackageDirectory, k as recordCount, l as CLI_AGENT_BINARIES, m as printFooter, n as shouldFailScanGate, o as countUniqueScannedFiles, p as inspect, q as void_, r as discoverWorkspacePackages, s as setUpGitHubActions, t as exitGracefully, u as copyToClipboard, v as computeProjectedScore, w as buildSortedRuleGroups, x as buildNoScoreMessage, y as formatElapsedTime, z as Reporter } from "./cli.js";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { performance } from "node:perf_hooks";
|
|
6
6
|
import { getSkillAgentConfig } from "agent-install";
|
|
@@ -428,14 +428,11 @@ const buildIssuePrompt = ({ row, projectName }) => {
|
|
|
428
428
|
};
|
|
429
429
|
//#endregion
|
|
430
430
|
//#region src/cli/ink/components/diagnostic-action-menu.tsx
|
|
431
|
-
const MODAL_BACKGROUND = "black";
|
|
432
|
-
const MODAL_SELECTED_BACKGROUND = "white";
|
|
433
431
|
const DiagnosticActionMenu = ({ title, itemLabels, focusedIndex, maxWidth }) => {
|
|
434
432
|
return /* @__PURE__ */ jsxs(Box, {
|
|
435
433
|
width: Math.max(24, Math.min(44, maxWidth)),
|
|
436
434
|
borderStyle: "round",
|
|
437
|
-
borderColor: "
|
|
438
|
-
backgroundColor: MODAL_BACKGROUND,
|
|
435
|
+
borderColor: "cyan",
|
|
439
436
|
paddingX: 2,
|
|
440
437
|
paddingY: 1,
|
|
441
438
|
flexDirection: "column",
|
|
@@ -455,14 +452,12 @@ const DiagnosticActionMenu = ({ title, itemLabels, focusedIndex, maxWidth }) =>
|
|
|
455
452
|
flexDirection: "column",
|
|
456
453
|
children: itemLabels.map((label, index) => {
|
|
457
454
|
const isFocused = index === focusedIndex;
|
|
458
|
-
return /* @__PURE__ */
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
children: [isFocused ? "› " : " ", label]
|
|
465
|
-
})
|
|
455
|
+
return /* @__PURE__ */ jsxs(Text, {
|
|
456
|
+
wrap: "truncate-end",
|
|
457
|
+
bold: isFocused,
|
|
458
|
+
color: isFocused ? "cyan" : void 0,
|
|
459
|
+
dimColor: !isFocused,
|
|
460
|
+
children: [isFocused ? "› " : " ", label]
|
|
466
461
|
}, label);
|
|
467
462
|
})
|
|
468
463
|
}),
|
|
@@ -514,110 +509,97 @@ const DiagnosticDetail = ({ row, rootDirectory }) => {
|
|
|
514
509
|
const impact = getCategoryImpact(row.category);
|
|
515
510
|
return /* @__PURE__ */ jsxs(Box, {
|
|
516
511
|
flexDirection: "column",
|
|
517
|
-
children: [
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
512
|
+
children: [/* @__PURE__ */ jsxs(Text, {
|
|
513
|
+
wrap: "truncate-end",
|
|
514
|
+
children: [
|
|
515
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
516
|
+
color: variant.color,
|
|
517
|
+
children: [variant.icon, " "]
|
|
518
|
+
}),
|
|
519
|
+
/* @__PURE__ */ jsx(Text, {
|
|
520
|
+
color: variant.color,
|
|
521
|
+
bold: true,
|
|
522
|
+
children: row.title
|
|
523
|
+
}),
|
|
524
|
+
row.siteCount > 1 ? /* @__PURE__ */ jsxs(Text, {
|
|
525
|
+
dimColor: true,
|
|
526
|
+
children: [" ×", row.siteCount]
|
|
527
|
+
}) : null
|
|
528
|
+
]
|
|
529
|
+
}), /* @__PURE__ */ jsxs(Box, {
|
|
530
|
+
flexDirection: "column",
|
|
531
|
+
paddingLeft: 2,
|
|
532
|
+
children: [
|
|
533
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
534
|
+
dimColor: true,
|
|
535
|
+
wrap: "truncate-end",
|
|
536
|
+
children: [
|
|
537
|
+
row.category,
|
|
538
|
+
" · ",
|
|
539
|
+
variant.label,
|
|
540
|
+
" · ",
|
|
541
|
+
row.location
|
|
542
|
+
]
|
|
543
|
+
}),
|
|
544
|
+
impact ? /* @__PURE__ */ jsx(Text, {
|
|
545
|
+
dimColor: true,
|
|
546
|
+
wrap: "wrap",
|
|
547
|
+
children: impact
|
|
548
|
+
}) : null,
|
|
549
|
+
/* @__PURE__ */ jsx(Text, {
|
|
550
|
+
wrap: "wrap",
|
|
551
|
+
children: representative.message
|
|
552
|
+
}),
|
|
553
|
+
codeFrame ? /* @__PURE__ */ jsx(Box, {
|
|
554
|
+
marginTop: 1,
|
|
555
|
+
children: /* @__PURE__ */ jsx(Text, { children: codeFrame })
|
|
556
|
+
}) : null,
|
|
557
|
+
representative.help ? /* @__PURE__ */ jsx(Box, {
|
|
558
|
+
marginTop: 1,
|
|
559
|
+
children: /* @__PURE__ */ jsxs(Text, {
|
|
559
560
|
wrap: "wrap",
|
|
560
|
-
children:
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
561
|
+
children: [/* @__PURE__ */ jsx(Text, {
|
|
562
|
+
color: "cyan",
|
|
563
|
+
children: "Fix "
|
|
564
|
+
}), representative.help]
|
|
565
|
+
})
|
|
566
|
+
}) : null,
|
|
567
|
+
row.learnMore ? /* @__PURE__ */ jsx(Box, {
|
|
568
|
+
marginTop: 1,
|
|
569
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
570
|
+
color: "blue",
|
|
564
571
|
wrap: "truncate-end",
|
|
565
|
-
children: row.
|
|
572
|
+
children: row.learnMore
|
|
566
573
|
})
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
marginTop: 1,
|
|
571
|
-
marginLeft: 4,
|
|
572
|
-
borderStyle: "round",
|
|
573
|
-
borderColor: "gray",
|
|
574
|
-
paddingX: 1,
|
|
575
|
-
alignSelf: "flex-start",
|
|
576
|
-
children: /* @__PURE__ */ jsx(Text, { children: codeFrame })
|
|
577
|
-
}) : null,
|
|
578
|
-
representative.help ? /* @__PURE__ */ jsx(Box, {
|
|
579
|
-
marginTop: 1,
|
|
580
|
-
paddingLeft: 4,
|
|
581
|
-
children: /* @__PURE__ */ jsxs(Text, {
|
|
582
|
-
dimColor: true,
|
|
583
|
-
wrap: "wrap",
|
|
584
|
-
children: ["→ ", representative.help]
|
|
585
|
-
})
|
|
586
|
-
}) : null,
|
|
587
|
-
row.learnMore ? /* @__PURE__ */ jsx(Box, {
|
|
588
|
-
marginTop: 1,
|
|
589
|
-
paddingLeft: 4,
|
|
590
|
-
children: /* @__PURE__ */ jsx(Text, {
|
|
591
|
-
color: "cyan",
|
|
592
|
-
wrap: "truncate-end",
|
|
593
|
-
children: row.learnMore
|
|
594
|
-
})
|
|
595
|
-
}) : null
|
|
596
|
-
]
|
|
574
|
+
}) : null
|
|
575
|
+
]
|
|
576
|
+
})]
|
|
597
577
|
});
|
|
598
578
|
};
|
|
599
579
|
//#endregion
|
|
600
580
|
//#region src/cli/ink/components/diagnostic-item.tsx
|
|
601
581
|
const DiagnosticItem = ({ row, isSelected, isRead }) => {
|
|
602
582
|
const variant = severityVariant(row.severity);
|
|
583
|
+
const shouldHighlightSeverity = isSelected || !isRead;
|
|
584
|
+
let marker = "• ";
|
|
585
|
+
if (isRead) marker = " ";
|
|
586
|
+
if (isSelected) marker = "› ";
|
|
587
|
+
let markerColor = shouldHighlightSeverity ? variant.color : void 0;
|
|
588
|
+
if (isSelected) markerColor = "cyan";
|
|
603
589
|
return /* @__PURE__ */ jsxs(Text, {
|
|
604
590
|
wrap: "truncate-end",
|
|
605
|
-
dimColor: isRead,
|
|
591
|
+
dimColor: isRead && !isSelected,
|
|
606
592
|
children: [
|
|
607
593
|
/* @__PURE__ */ jsx(Text, {
|
|
608
|
-
color:
|
|
609
|
-
children:
|
|
610
|
-
}),
|
|
611
|
-
/* @__PURE__ */ jsx(Text, {
|
|
612
|
-
color: isRead ? void 0 : variant.color,
|
|
613
|
-
children: isRead ? " " : " •"
|
|
594
|
+
color: markerColor,
|
|
595
|
+
children: marker
|
|
614
596
|
}),
|
|
615
597
|
/* @__PURE__ */ jsx(Text, {
|
|
616
|
-
color:
|
|
617
|
-
children:
|
|
598
|
+
color: shouldHighlightSeverity ? variant.color : void 0,
|
|
599
|
+
children: `${variant.icon} `
|
|
618
600
|
}),
|
|
619
601
|
/* @__PURE__ */ jsx(Text, {
|
|
620
|
-
color:
|
|
602
|
+
color: shouldHighlightSeverity ? variant.color : void 0,
|
|
621
603
|
bold: isSelected,
|
|
622
604
|
children: row.title
|
|
623
605
|
}),
|
|
@@ -633,9 +615,8 @@ const DiagnosticItem = ({ row, isSelected, isRead }) => {
|
|
|
633
615
|
const StatusBar = ({ total, errorCount, warningCount, position, groupCount, unreadCount, projectCount, keyHints = /* @__PURE__ */ jsx(Text, {
|
|
634
616
|
dimColor: true,
|
|
635
617
|
children: "↑/↓ to move"
|
|
636
|
-
}), exitHint = "q to quit" }) =>
|
|
637
|
-
|
|
638
|
-
children: [
|
|
618
|
+
}), exitHint = "q to quit", compact = false }) => {
|
|
619
|
+
const counts = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
639
620
|
/* @__PURE__ */ jsxs(Text, {
|
|
640
621
|
bold: true,
|
|
641
622
|
children: [
|
|
@@ -646,7 +627,7 @@ const StatusBar = ({ total, errorCount, warningCount, position, groupCount, unre
|
|
|
646
627
|
}),
|
|
647
628
|
/* @__PURE__ */ jsx(Text, {
|
|
648
629
|
dimColor: true,
|
|
649
|
-
children: "
|
|
630
|
+
children: " "
|
|
650
631
|
}),
|
|
651
632
|
/* @__PURE__ */ jsxs(Text, {
|
|
652
633
|
color: "red",
|
|
@@ -654,46 +635,80 @@ const StatusBar = ({ total, errorCount, warningCount, position, groupCount, unre
|
|
|
654
635
|
}),
|
|
655
636
|
/* @__PURE__ */ jsx(Text, {
|
|
656
637
|
dimColor: true,
|
|
657
|
-
children: "
|
|
638
|
+
children: " "
|
|
658
639
|
}),
|
|
659
640
|
/* @__PURE__ */ jsxs(Text, {
|
|
660
641
|
color: "yellow",
|
|
661
|
-
dimColor: true,
|
|
662
642
|
children: [warningCount, " warnings"]
|
|
663
|
-
})
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
643
|
+
})
|
|
644
|
+
] });
|
|
645
|
+
if (compact) return /* @__PURE__ */ jsxs(Text, {
|
|
646
|
+
wrap: "truncate-end",
|
|
647
|
+
children: [
|
|
648
|
+
counts,
|
|
649
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
650
|
+
dimColor: true,
|
|
651
|
+
children: [
|
|
652
|
+
" · ",
|
|
653
|
+
position,
|
|
654
|
+
"/",
|
|
655
|
+
groupCount,
|
|
656
|
+
" · "
|
|
657
|
+
]
|
|
658
|
+
}),
|
|
659
|
+
keyHints,
|
|
660
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
661
|
+
dimColor: true,
|
|
662
|
+
children: [" · ", exitHint]
|
|
663
|
+
})
|
|
664
|
+
]
|
|
665
|
+
});
|
|
666
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
667
|
+
flexDirection: "column",
|
|
668
|
+
children: [/* @__PURE__ */ jsxs(Text, {
|
|
669
|
+
wrap: "truncate-end",
|
|
675
670
|
children: [
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
671
|
+
counts,
|
|
672
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
673
|
+
dimColor: true,
|
|
674
|
+
children: [
|
|
675
|
+
" · ",
|
|
676
|
+
position,
|
|
677
|
+
"/",
|
|
678
|
+
groupCount
|
|
679
|
+
]
|
|
680
|
+
}),
|
|
681
|
+
projectCount !== void 0 ? /* @__PURE__ */ jsxs(Text, {
|
|
682
|
+
dimColor: true,
|
|
683
|
+
children: [
|
|
684
|
+
" · ",
|
|
685
|
+
projectCount,
|
|
686
|
+
" ",
|
|
687
|
+
projectCount === 1 ? "project" : "projects"
|
|
688
|
+
]
|
|
689
|
+
}) : null
|
|
680
690
|
]
|
|
681
|
-
})
|
|
682
|
-
|
|
683
|
-
dimColor: true,
|
|
691
|
+
}), /* @__PURE__ */ jsxs(Text, {
|
|
692
|
+
wrap: "truncate-end",
|
|
684
693
|
children: [
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
694
|
+
unreadCount !== void 0 ? /* @__PURE__ */ jsxs(Text, {
|
|
695
|
+
color: unreadCount > 0 ? "cyan" : void 0,
|
|
696
|
+
dimColor: unreadCount === 0,
|
|
697
|
+
children: [
|
|
698
|
+
unreadCount,
|
|
699
|
+
" unread",
|
|
700
|
+
" · "
|
|
701
|
+
]
|
|
702
|
+
}) : null,
|
|
690
703
|
keyHints,
|
|
691
|
-
|
|
692
|
-
|
|
704
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
705
|
+
dimColor: true,
|
|
706
|
+
children: [" · ", exitHint]
|
|
707
|
+
})
|
|
693
708
|
]
|
|
694
|
-
})
|
|
695
|
-
|
|
696
|
-
}
|
|
709
|
+
})]
|
|
710
|
+
});
|
|
711
|
+
};
|
|
697
712
|
//#endregion
|
|
698
713
|
//#region src/cli/ink/components/diagnostic-list.tsx
|
|
699
714
|
const ADD_TO_CI_KEY = "a";
|
|
@@ -715,6 +730,7 @@ const DiagnosticList = ({ header, rows, width, listColumnWidth, detailColumnWidt
|
|
|
715
730
|
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
|
716
731
|
const [menuIndex, setMenuIndex] = useState(0);
|
|
717
732
|
const isSplit = layout === "split";
|
|
733
|
+
const isCompact = layout === "compact";
|
|
718
734
|
const { rows: terminalRows } = useStdoutDimensions();
|
|
719
735
|
const { selectedIndex, visibleStart, visibleEnd } = useScrollViewport({
|
|
720
736
|
itemCount: entries.length,
|
|
@@ -726,6 +742,8 @@ const DiagnosticList = ({ header, rows, width, listColumnWidth, detailColumnWidt
|
|
|
726
742
|
const selectedEntry = entries[selectedIndex];
|
|
727
743
|
const selected = selectedEntry?.kind === "item" ? selectedEntry.row : null;
|
|
728
744
|
const selectedRuleKey = selected?.ruleKey ?? null;
|
|
745
|
+
const initialSelectedRuleKey = useRef(selectedRuleKey);
|
|
746
|
+
const didRecordFindingNavigation = useRef(false);
|
|
729
747
|
const [readRuleKeys, setReadRuleKeys] = useState(() => /* @__PURE__ */ new Set());
|
|
730
748
|
const [copiedRuleKey, setCopiedRuleKey] = useState(null);
|
|
731
749
|
const menuLabels = useMemo(() => ["Copy prompt", ...launchableAgents.map((agentId) => getSkillAgentConfig(agentId).displayName)], [launchableAgents]);
|
|
@@ -733,6 +751,11 @@ const DiagnosticList = ({ header, rows, width, listColumnWidth, detailColumnWidt
|
|
|
733
751
|
if (!selectedRuleKey) return;
|
|
734
752
|
setReadRuleKeys((previous) => previous.has(selectedRuleKey) ? previous : new Set(previous).add(selectedRuleKey));
|
|
735
753
|
}, [selectedRuleKey]);
|
|
754
|
+
useEffect(() => {
|
|
755
|
+
if (!selectedRuleKey || selectedRuleKey === initialSelectedRuleKey.current || didRecordFindingNavigation.current) return;
|
|
756
|
+
didRecordFindingNavigation.current = true;
|
|
757
|
+
recordCount(METRIC.tuiFindingNavigated);
|
|
758
|
+
}, [selectedRuleKey]);
|
|
736
759
|
const copySelectedPrompt = () => {
|
|
737
760
|
if (!selected) return;
|
|
738
761
|
const prompt = buildIssuePrompt({
|
|
@@ -772,6 +795,7 @@ const DiagnosticList = ({ header, rows, width, listColumnWidth, detailColumnWidt
|
|
|
772
795
|
return onExit();
|
|
773
796
|
}
|
|
774
797
|
if (key.return && selected) {
|
|
798
|
+
recordCount(METRIC.tuiActionMenuOpened);
|
|
775
799
|
setMenuIndex(0);
|
|
776
800
|
setIsMenuOpen(true);
|
|
777
801
|
}
|
|
@@ -782,6 +806,18 @@ const DiagnosticList = ({ header, rows, width, listColumnWidth, detailColumnWidt
|
|
|
782
806
|
if (key.downArrow || input === "j") return setMenuIndex((index) => Math.min(menuLabels.length - 1, index + 1));
|
|
783
807
|
if (key.return) return runMenuItem();
|
|
784
808
|
}, { isActive: isMenuOpen });
|
|
809
|
+
if (isMenuOpen && selected) return /* @__PURE__ */ jsx(Box, {
|
|
810
|
+
width,
|
|
811
|
+
height: Math.max(6, terminalRows - 2),
|
|
812
|
+
justifyContent: "center",
|
|
813
|
+
alignItems: "center",
|
|
814
|
+
children: /* @__PURE__ */ jsx(DiagnosticActionMenu, {
|
|
815
|
+
title: selected.title,
|
|
816
|
+
itemLabels: menuLabels,
|
|
817
|
+
focusedIndex: menuIndex,
|
|
818
|
+
maxWidth: width
|
|
819
|
+
})
|
|
820
|
+
});
|
|
785
821
|
const errorRows = rows.filter((row) => row.severity === "error");
|
|
786
822
|
const warningRows = rows.filter((row) => row.severity === "warning");
|
|
787
823
|
const itemPosition = entries.slice(0, selectedIndex + 1).filter((entry) => entry.kind === "item").length;
|
|
@@ -802,20 +838,7 @@ const DiagnosticList = ({ header, rows, width, listColumnWidth, detailColumnWidt
|
|
|
802
838
|
children: "✓ Copied fix prompt"
|
|
803
839
|
})
|
|
804
840
|
}) : null] });
|
|
805
|
-
const keyHints =
|
|
806
|
-
/* @__PURE__ */ jsx(Text, {
|
|
807
|
-
dimColor: true,
|
|
808
|
-
children: "↑/↓ select · "
|
|
809
|
-
}),
|
|
810
|
-
/* @__PURE__ */ jsx(Text, {
|
|
811
|
-
color: "cyan",
|
|
812
|
-
children: "enter"
|
|
813
|
-
}),
|
|
814
|
-
/* @__PURE__ */ jsx(Text, {
|
|
815
|
-
dimColor: true,
|
|
816
|
-
children: " run · esc close"
|
|
817
|
-
})
|
|
818
|
-
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
841
|
+
const keyHints = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
819
842
|
/* @__PURE__ */ jsx(Text, {
|
|
820
843
|
dimColor: true,
|
|
821
844
|
children: "↑/↓ move · "
|
|
@@ -842,9 +865,9 @@ const DiagnosticList = ({ header, rows, width, listColumnWidth, detailColumnWidt
|
|
|
842
865
|
children: " add CI"
|
|
843
866
|
})
|
|
844
867
|
] }) : null
|
|
845
|
-
] })
|
|
868
|
+
] });
|
|
846
869
|
const statusBar = /* @__PURE__ */ jsx(Box, {
|
|
847
|
-
marginTop: 1,
|
|
870
|
+
marginTop: isCompact ? 0 : 1,
|
|
848
871
|
children: /* @__PURE__ */ jsx(StatusBar, {
|
|
849
872
|
total: sumSites(rows),
|
|
850
873
|
errorCount: sumSites(errorRows),
|
|
@@ -853,62 +876,54 @@ const DiagnosticList = ({ header, rows, width, listColumnWidth, detailColumnWidt
|
|
|
853
876
|
groupCount: rows.length,
|
|
854
877
|
unreadCount,
|
|
855
878
|
projectCount,
|
|
856
|
-
keyHints,
|
|
857
|
-
|
|
879
|
+
keyHints: isCompact && copiedRuleKey === selectedRuleKey ? /* @__PURE__ */ jsx(Text, {
|
|
880
|
+
color: "green",
|
|
881
|
+
children: "✓ Copied fix prompt"
|
|
882
|
+
}) : keyHints,
|
|
883
|
+
exitHint,
|
|
884
|
+
compact: isCompact
|
|
858
885
|
})
|
|
859
886
|
});
|
|
860
|
-
const overlay = isMenuOpen && selected ? /* @__PURE__ */ jsx(Box, {
|
|
861
|
-
position: "absolute",
|
|
862
|
-
top: 0,
|
|
863
|
-
left: 0,
|
|
864
|
-
width,
|
|
865
|
-
height: Math.max(6, terminalRows - 2),
|
|
866
|
-
justifyContent: "center",
|
|
867
|
-
alignItems: "center",
|
|
868
|
-
children: /* @__PURE__ */ jsx(DiagnosticActionMenu, {
|
|
869
|
-
title: selected.title,
|
|
870
|
-
itemLabels: menuLabels,
|
|
871
|
-
focusedIndex: menuIndex,
|
|
872
|
-
maxWidth: width
|
|
873
|
-
})
|
|
874
|
-
}) : null;
|
|
875
887
|
if (isSplit) return /* @__PURE__ */ jsxs(Box, {
|
|
876
888
|
flexDirection: "column",
|
|
877
889
|
width,
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
/* @__PURE__ */ jsxs(Box, {
|
|
881
|
-
flexDirection: "
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
children:
|
|
887
|
-
marginTop: 1,
|
|
888
|
-
children: listColumn
|
|
889
|
-
})]
|
|
890
|
-
}), /* @__PURE__ */ jsx(Box, {
|
|
891
|
-
flexDirection: "column",
|
|
892
|
-
width: detailColumnWidth,
|
|
893
|
-
borderStyle: "single",
|
|
894
|
-
borderColor: "gray",
|
|
895
|
-
borderTop: false,
|
|
896
|
-
borderRight: false,
|
|
897
|
-
borderBottom: false,
|
|
898
|
-
paddingLeft: 1,
|
|
899
|
-
height: detailHeight,
|
|
900
|
-
overflowY: "hidden",
|
|
901
|
-
children: detailContent
|
|
890
|
+
children: [/* @__PURE__ */ jsxs(Box, {
|
|
891
|
+
flexDirection: "row",
|
|
892
|
+
children: [/* @__PURE__ */ jsxs(Box, {
|
|
893
|
+
flexDirection: "column",
|
|
894
|
+
width: listColumnWidth,
|
|
895
|
+
marginRight: 1,
|
|
896
|
+
children: [header, /* @__PURE__ */ jsx(Box, {
|
|
897
|
+
marginTop: 1,
|
|
898
|
+
children: listColumn
|
|
902
899
|
})]
|
|
903
|
-
}),
|
|
904
|
-
|
|
905
|
-
|
|
900
|
+
}), /* @__PURE__ */ jsx(Box, {
|
|
901
|
+
flexDirection: "column",
|
|
902
|
+
width: detailColumnWidth,
|
|
903
|
+
borderStyle: "single",
|
|
904
|
+
borderColor: "gray",
|
|
905
|
+
borderTop: false,
|
|
906
|
+
borderRight: false,
|
|
907
|
+
borderBottom: false,
|
|
908
|
+
paddingLeft: 1,
|
|
909
|
+
height: detailHeight,
|
|
910
|
+
overflowY: "hidden",
|
|
911
|
+
children: detailContent
|
|
912
|
+
})]
|
|
913
|
+
}), statusBar]
|
|
914
|
+
});
|
|
915
|
+
if (isCompact) return /* @__PURE__ */ jsxs(Box, {
|
|
916
|
+
flexDirection: "column",
|
|
917
|
+
width,
|
|
918
|
+
children: [
|
|
919
|
+
header,
|
|
920
|
+
listColumn,
|
|
921
|
+
statusBar
|
|
906
922
|
]
|
|
907
923
|
});
|
|
908
924
|
return /* @__PURE__ */ jsxs(Box, {
|
|
909
925
|
flexDirection: "column",
|
|
910
926
|
width,
|
|
911
|
-
position: "relative",
|
|
912
927
|
children: [
|
|
913
928
|
header,
|
|
914
929
|
/* @__PURE__ */ jsx(Box, {
|
|
@@ -925,8 +940,7 @@ const DiagnosticList = ({ header, rows, width, listColumnWidth, detailColumnWidt
|
|
|
925
940
|
overflowY: "hidden",
|
|
926
941
|
children: detailContent
|
|
927
942
|
}),
|
|
928
|
-
statusBar
|
|
929
|
-
overlay
|
|
943
|
+
statusBar
|
|
930
944
|
]
|
|
931
945
|
});
|
|
932
946
|
};
|
|
@@ -991,7 +1005,7 @@ const scoreColorName = (score) => {
|
|
|
991
1005
|
//#endregion
|
|
992
1006
|
//#region src/cli/ink/components/score-header.tsx
|
|
993
1007
|
const BRANDING = "https://react.doctor";
|
|
994
|
-
const ScoreHeader = ({ score, projectedScore, projectName, issueCount, noScoreMessage, width }) => {
|
|
1008
|
+
const ScoreHeader = ({ score, projectedScore, projectName, issueCount, noScoreMessage, width, compact = false }) => {
|
|
995
1009
|
const { columns } = useStdoutDimensions();
|
|
996
1010
|
const availableWidth = width ?? columns;
|
|
997
1011
|
const { stdout } = useStdout();
|
|
@@ -1001,6 +1015,42 @@ const ScoreHeader = ({ score, projectedScore, projectName, issueCount, noScoreMe
|
|
|
1001
1015
|
projectedScore,
|
|
1002
1016
|
animate: animate && score !== null
|
|
1003
1017
|
});
|
|
1018
|
+
if (compact) return score ? /* @__PURE__ */ jsxs(Text, {
|
|
1019
|
+
wrap: "truncate-end",
|
|
1020
|
+
children: [
|
|
1021
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1022
|
+
color: scoreColorName(score.score),
|
|
1023
|
+
bold: true,
|
|
1024
|
+
children: displayScore
|
|
1025
|
+
}),
|
|
1026
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
1027
|
+
dimColor: true,
|
|
1028
|
+
children: [
|
|
1029
|
+
" / ",
|
|
1030
|
+
100,
|
|
1031
|
+
" "
|
|
1032
|
+
]
|
|
1033
|
+
}),
|
|
1034
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1035
|
+
color: scoreColorName(score.score),
|
|
1036
|
+
children: score.label
|
|
1037
|
+
}),
|
|
1038
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
1039
|
+
dimColor: true,
|
|
1040
|
+
children: [" · ", projectName]
|
|
1041
|
+
})
|
|
1042
|
+
]
|
|
1043
|
+
}) : /* @__PURE__ */ jsxs(Text, {
|
|
1044
|
+
wrap: "truncate-end",
|
|
1045
|
+
children: [
|
|
1046
|
+
"React Doctor",
|
|
1047
|
+
" ",
|
|
1048
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
1049
|
+
dimColor: true,
|
|
1050
|
+
children: ["· ", noScoreMessage ?? `${issueCount} issues · ${projectName}`]
|
|
1051
|
+
})
|
|
1052
|
+
]
|
|
1053
|
+
});
|
|
1004
1054
|
if (!score) return /* @__PURE__ */ jsxs(Box, {
|
|
1005
1055
|
flexDirection: "column",
|
|
1006
1056
|
paddingLeft: 2,
|
|
@@ -1136,8 +1186,8 @@ const ScoreHeader = ({ score, projectedScore, projectName, issueCount, noScoreMe
|
|
|
1136
1186
|
};
|
|
1137
1187
|
//#endregion
|
|
1138
1188
|
//#region src/cli/ink/components/report.tsx
|
|
1139
|
-
const STACKED_FIXED_ROWS =
|
|
1140
|
-
const SPLIT_CHROME_ROWS =
|
|
1189
|
+
const STACKED_FIXED_ROWS = 11;
|
|
1190
|
+
const SPLIT_CHROME_ROWS = 10;
|
|
1141
1191
|
const EMPTY_LAUNCHABLE_AGENTS = [];
|
|
1142
1192
|
const Report = ({ report, onExit, launchableAgents = EMPTY_LAUNCHABLE_AGENTS, onHandoff, canAddToCi, onAddToCi, projectCount, priorityScores, exitHint = "q to quit" }) => {
|
|
1143
1193
|
const { rows: terminalRows, columns } = useStdoutDimensions();
|
|
@@ -1151,17 +1201,38 @@ const Report = ({ report, onExit, launchableAgents = EMPTY_LAUNCHABLE_AGENTS, on
|
|
|
1151
1201
|
}, { isActive: diagnosticRows.length === 0 });
|
|
1152
1202
|
const width = Math.max(24, columns - 2);
|
|
1153
1203
|
const isWide = columns >= 120 && terminalRows >= 22;
|
|
1154
|
-
const
|
|
1155
|
-
const
|
|
1204
|
+
const isCompact = !isWide && terminalRows <= TUI_REPORT_COMPACT_MAX_ROWS;
|
|
1205
|
+
const didRecordCompactReport = useRef(false);
|
|
1206
|
+
const didRecordStackedReportCap = useRef(false);
|
|
1207
|
+
useEffect(() => {
|
|
1208
|
+
if (!isCompact || didRecordCompactReport.current) return;
|
|
1209
|
+
didRecordCompactReport.current = true;
|
|
1210
|
+
recordCount(METRIC.tuiCompactReportShown);
|
|
1211
|
+
}, [isCompact]);
|
|
1212
|
+
const detailHeight = isWide ? Math.max(0, terminalRows - 3) : Math.max(0, Math.min(15, terminalRows - STACKED_FIXED_ROWS - 3));
|
|
1213
|
+
const availableListHeight = Math.max(3, terminalRows - (isWide ? SPLIT_CHROME_ROWS : STACKED_FIXED_ROWS + detailHeight));
|
|
1214
|
+
const isStackedReportCapped = !isCompact && !isWide && availableListHeight > 16;
|
|
1215
|
+
useEffect(() => {
|
|
1216
|
+
if (!isStackedReportCapped || didRecordStackedReportCap.current) return;
|
|
1217
|
+
didRecordStackedReportCap.current = true;
|
|
1218
|
+
recordCount(METRIC.tuiStackedReportCapped);
|
|
1219
|
+
}, [isStackedReportCapped]);
|
|
1220
|
+
let listHeight = availableListHeight;
|
|
1221
|
+
if (isCompact) listHeight = Math.max(3, terminalRows - 1 - 1);
|
|
1222
|
+
else if (!isWide) listHeight = Math.min(16, availableListHeight);
|
|
1156
1223
|
const detailColumnWidth = Math.max(20, Math.floor(width * TUI_REPORT_DETAIL_WIDTH_FRACTION));
|
|
1157
1224
|
const listColumnWidth = Math.max(20, width - detailColumnWidth - 3);
|
|
1225
|
+
let layout = "stacked";
|
|
1226
|
+
if (isCompact) layout = "compact";
|
|
1227
|
+
else if (isWide) layout = "split";
|
|
1158
1228
|
const scoreHeader = /* @__PURE__ */ jsx(ScoreHeader, {
|
|
1159
1229
|
score: report.score,
|
|
1160
1230
|
projectedScore: report.projectedScore,
|
|
1161
1231
|
projectName: report.projectName,
|
|
1162
1232
|
issueCount: report.diagnostics.length,
|
|
1163
1233
|
noScoreMessage: report.noScoreMessage,
|
|
1164
|
-
width: isWide ? listColumnWidth : width
|
|
1234
|
+
width: isWide ? listColumnWidth : width,
|
|
1235
|
+
compact: isCompact
|
|
1165
1236
|
});
|
|
1166
1237
|
if (diagnosticRows.length === 0) {
|
|
1167
1238
|
const lintFailureReason = report.lintFailureReason;
|
|
@@ -1194,7 +1265,7 @@ const Report = ({ report, onExit, launchableAgents = EMPTY_LAUNCHABLE_AGENTS, on
|
|
|
1194
1265
|
detailColumnWidth,
|
|
1195
1266
|
listHeight,
|
|
1196
1267
|
detailHeight,
|
|
1197
|
-
layout
|
|
1268
|
+
layout,
|
|
1198
1269
|
rootDirectory: report.rootDirectory,
|
|
1199
1270
|
projectName: report.projectName,
|
|
1200
1271
|
launchableAgents,
|
|
@@ -1228,7 +1299,7 @@ const Scanning = ({ progressText, liveCount, recent }) => {
|
|
|
1228
1299
|
]
|
|
1229
1300
|
}) : null
|
|
1230
1301
|
]
|
|
1231
|
-
}), recent.map((diagnostic) => {
|
|
1302
|
+
}), recent.map((diagnostic, diagnosticIndex) => {
|
|
1232
1303
|
const variant = severityVariant(diagnostic.severity === "error" ? "error" : "warning");
|
|
1233
1304
|
const location = formatDiagnosticSite(diagnostic);
|
|
1234
1305
|
return /* @__PURE__ */ jsxs(Text, {
|
|
@@ -1245,7 +1316,7 @@ const Scanning = ({ progressText, liveCount, recent }) => {
|
|
|
1245
1316
|
children: [" ", location]
|
|
1246
1317
|
})
|
|
1247
1318
|
]
|
|
1248
|
-
}, `${diagnostic.filePath}:${diagnostic.line}:${diagnostic.column}:${diagnostic.plugin}:${diagnostic.rule}`);
|
|
1319
|
+
}, `${diagnostic.filePath}:${diagnostic.line}:${diagnostic.column}:${diagnostic.plugin}:${diagnostic.rule}:${diagnosticIndex}`);
|
|
1249
1320
|
})]
|
|
1250
1321
|
});
|
|
1251
1322
|
};
|
|
@@ -1657,5 +1728,5 @@ const runScanApp = async (input) => {
|
|
|
1657
1728
|
//#endregion
|
|
1658
1729
|
export { runScanApp };
|
|
1659
1730
|
|
|
1660
|
-
//# sourceMappingURL=run-scan-app-
|
|
1661
|
-
//# debugId=
|
|
1731
|
+
//# sourceMappingURL=run-scan-app-C9MJnVwv.js.map
|
|
1732
|
+
//# debugId=90f58187-6a1d-56d1-a411-800f7bc51d28
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-doctor",
|
|
3
|
-
"version": "0.9.2-dev.
|
|
3
|
+
"version": "0.9.2-dev.b31fd85",
|
|
4
4
|
"description": "Your agent writes bad React. This catches it",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"accessibility",
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"vscode-uri": "^3.1.0",
|
|
72
72
|
"yaml": "^2.9.0",
|
|
73
73
|
"deslop-js": "0.9.2",
|
|
74
|
-
"oxlint-plugin-react-doctor": "0.9.2-dev.
|
|
74
|
+
"oxlint-plugin-react-doctor": "0.9.2-dev.b31fd85"
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|
|
77
77
|
"@types/babel__code-frame": "^7.27.0",
|
|
@@ -81,8 +81,8 @@
|
|
|
81
81
|
"commander": "^14.0.3",
|
|
82
82
|
"ink-testing-library": "^4.0.0",
|
|
83
83
|
"ora": "^9.4.0",
|
|
84
|
-
"@react-doctor/api": "0.9.2",
|
|
85
84
|
"@react-doctor/core": "0.9.2",
|
|
85
|
+
"@react-doctor/api": "0.9.2",
|
|
86
86
|
"@react-doctor/language-server": "0.9.2"
|
|
87
87
|
},
|
|
88
88
|
"engines": {
|