uilint 0.2.33 → 0.2.35
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/{chunk-W6X3RNOE.js → chunk-YS2QQOCB.js} +6 -1
- package/dist/{chunk-W6X3RNOE.js.map → chunk-YS2QQOCB.js.map} +1 -1
- package/dist/index.js +2 -2
- package/dist/{install-ui-ZXMZNRU2.js → install-ui-JV4G2CAC.js} +766 -182
- package/dist/install-ui-JV4G2CAC.js.map +1 -0
- package/dist/{plan-E7ZMQPPE.js → plan-QVR3RBLG.js} +22 -1
- package/dist/{plan-E7ZMQPPE.js.map → plan-QVR3RBLG.js.map} +1 -1
- package/package.json +5 -5
- package/dist/install-ui-ZXMZNRU2.js.map +0 -1
|
@@ -14,8 +14,9 @@ import {
|
|
|
14
14
|
note,
|
|
15
15
|
pc,
|
|
16
16
|
select,
|
|
17
|
+
text,
|
|
17
18
|
uninstallEslintPlugin
|
|
18
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-YS2QQOCB.js";
|
|
19
20
|
import {
|
|
20
21
|
GENSTYLEGUIDE_COMMAND_MD,
|
|
21
22
|
loadSkill,
|
|
@@ -31,8 +32,8 @@ import {
|
|
|
31
32
|
import { render } from "ink";
|
|
32
33
|
|
|
33
34
|
// src/commands/install/components/InstallApp.tsx
|
|
34
|
-
import { useState as
|
|
35
|
-
import { Box as
|
|
35
|
+
import { useState as useState7, useEffect as useEffect2 } from "react";
|
|
36
|
+
import { Box as Box6, Text as Text7, useApp as useApp5, useInput as useInput6 } from "ink";
|
|
36
37
|
|
|
37
38
|
// src/commands/install/components/Spinner.tsx
|
|
38
39
|
import { useState, useEffect } from "react";
|
|
@@ -316,21 +317,274 @@ function ConfigSelector({
|
|
|
316
317
|
}
|
|
317
318
|
|
|
318
319
|
// src/commands/install/components/RuleSelector.tsx
|
|
319
|
-
import { useState as
|
|
320
|
-
import { Box as
|
|
321
|
-
import { getRulesByCategory } from "uilint-eslint";
|
|
320
|
+
import { useState as useState5, useMemo } from "react";
|
|
321
|
+
import { Box as Box4, Text as Text5, useInput as useInput4, useApp as useApp3 } from "ink";
|
|
322
|
+
import { getRulesByCategory, getCategoryMeta } from "uilint-eslint";
|
|
323
|
+
|
|
324
|
+
// src/commands/install/components/OptionField.tsx
|
|
325
|
+
import { useState as useState4 } from "react";
|
|
326
|
+
import { Box as Box3, Text as Text4, useInput as useInput3 } from "ink";
|
|
322
327
|
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
328
|
+
function BooleanField({
|
|
329
|
+
field,
|
|
330
|
+
value,
|
|
331
|
+
onChange,
|
|
332
|
+
isActive
|
|
333
|
+
}) {
|
|
334
|
+
const checked = Boolean(value);
|
|
335
|
+
useInput3(
|
|
336
|
+
(input) => {
|
|
337
|
+
if (isActive && input === " ") {
|
|
338
|
+
onChange(!checked);
|
|
339
|
+
}
|
|
340
|
+
},
|
|
341
|
+
{ isActive }
|
|
342
|
+
);
|
|
343
|
+
return /* @__PURE__ */ jsxs3(Box3, { children: [
|
|
344
|
+
/* @__PURE__ */ jsx4(Text4, { color: isActive ? "cyan" : void 0, children: isActive ? "\u203A " : " " }),
|
|
345
|
+
/* @__PURE__ */ jsx4(Text4, { color: checked ? "green" : "gray", children: checked ? "[\u2713]" : "[ ]" }),
|
|
346
|
+
/* @__PURE__ */ jsxs3(Text4, { children: [
|
|
347
|
+
" ",
|
|
348
|
+
field.label
|
|
349
|
+
] }),
|
|
350
|
+
field.description && /* @__PURE__ */ jsxs3(Text4, { dimColor: true, children: [
|
|
351
|
+
" - ",
|
|
352
|
+
field.description
|
|
353
|
+
] })
|
|
354
|
+
] });
|
|
355
|
+
}
|
|
356
|
+
function NumberField({
|
|
357
|
+
field,
|
|
358
|
+
value,
|
|
359
|
+
onChange,
|
|
360
|
+
isActive
|
|
361
|
+
}) {
|
|
362
|
+
const [inputValue, setInputValue] = useState4(String(value ?? field.defaultValue ?? ""));
|
|
363
|
+
const [error, setError] = useState4(null);
|
|
364
|
+
useInput3(
|
|
365
|
+
(input, key) => {
|
|
366
|
+
if (!isActive) return;
|
|
367
|
+
if (key.backspace || key.delete) {
|
|
368
|
+
const newValue = inputValue.slice(0, -1);
|
|
369
|
+
setInputValue(newValue);
|
|
370
|
+
const num = Number(newValue);
|
|
371
|
+
if (!isNaN(num) && newValue !== "") {
|
|
372
|
+
onChange(num);
|
|
373
|
+
setError(null);
|
|
374
|
+
} else if (newValue === "") {
|
|
375
|
+
setError(null);
|
|
376
|
+
} else {
|
|
377
|
+
setError("Enter a valid number");
|
|
378
|
+
}
|
|
379
|
+
} else if (/^[0-9.-]$/.test(input)) {
|
|
380
|
+
const newValue = inputValue + input;
|
|
381
|
+
setInputValue(newValue);
|
|
382
|
+
const num = Number(newValue);
|
|
383
|
+
if (!isNaN(num)) {
|
|
384
|
+
onChange(num);
|
|
385
|
+
setError(null);
|
|
386
|
+
} else {
|
|
387
|
+
setError("Enter a valid number");
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
},
|
|
391
|
+
{ isActive }
|
|
392
|
+
);
|
|
393
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
|
|
394
|
+
/* @__PURE__ */ jsxs3(Box3, { children: [
|
|
395
|
+
/* @__PURE__ */ jsx4(Text4, { color: isActive ? "cyan" : void 0, children: isActive ? "\u203A " : " " }),
|
|
396
|
+
/* @__PURE__ */ jsxs3(Text4, { children: [
|
|
397
|
+
field.label,
|
|
398
|
+
": "
|
|
399
|
+
] }),
|
|
400
|
+
/* @__PURE__ */ jsx4(Text4, { color: isActive ? "cyan" : void 0, underline: isActive, children: inputValue || field.placeholder || "" }),
|
|
401
|
+
field.description && /* @__PURE__ */ jsxs3(Text4, { dimColor: true, children: [
|
|
402
|
+
" (",
|
|
403
|
+
field.description,
|
|
404
|
+
")"
|
|
405
|
+
] })
|
|
406
|
+
] }),
|
|
407
|
+
error && /* @__PURE__ */ jsx4(Box3, { paddingLeft: 4, children: /* @__PURE__ */ jsx4(Text4, { color: "red", children: error }) })
|
|
408
|
+
] });
|
|
409
|
+
}
|
|
410
|
+
function TextField({
|
|
411
|
+
field,
|
|
412
|
+
value,
|
|
413
|
+
onChange,
|
|
414
|
+
isActive
|
|
415
|
+
}) {
|
|
416
|
+
const displayValue = Array.isArray(value) ? value.join(", ") : String(value ?? field.defaultValue ?? "");
|
|
417
|
+
const [inputValue, setInputValue] = useState4(displayValue);
|
|
418
|
+
useInput3(
|
|
419
|
+
(input, key) => {
|
|
420
|
+
if (!isActive) return;
|
|
421
|
+
if (key.backspace || key.delete) {
|
|
422
|
+
const newValue = inputValue.slice(0, -1);
|
|
423
|
+
setInputValue(newValue);
|
|
424
|
+
onChange(newValue);
|
|
425
|
+
} else if (input && !key.ctrl && !key.meta) {
|
|
426
|
+
const newValue = inputValue + input;
|
|
427
|
+
setInputValue(newValue);
|
|
428
|
+
onChange(newValue);
|
|
429
|
+
}
|
|
430
|
+
},
|
|
431
|
+
{ isActive }
|
|
432
|
+
);
|
|
433
|
+
return /* @__PURE__ */ jsxs3(Box3, { children: [
|
|
434
|
+
/* @__PURE__ */ jsx4(Text4, { color: isActive ? "cyan" : void 0, children: isActive ? "\u203A " : " " }),
|
|
435
|
+
/* @__PURE__ */ jsxs3(Text4, { children: [
|
|
436
|
+
field.label,
|
|
437
|
+
": "
|
|
438
|
+
] }),
|
|
439
|
+
/* @__PURE__ */ jsx4(Text4, { color: isActive ? "cyan" : void 0, underline: isActive, children: inputValue || field.placeholder || "(empty)" }),
|
|
440
|
+
field.description && /* @__PURE__ */ jsxs3(Text4, { dimColor: true, children: [
|
|
441
|
+
" (",
|
|
442
|
+
field.description,
|
|
443
|
+
")"
|
|
444
|
+
] })
|
|
445
|
+
] });
|
|
446
|
+
}
|
|
447
|
+
function SelectField({
|
|
448
|
+
field,
|
|
449
|
+
value,
|
|
450
|
+
onChange,
|
|
451
|
+
isActive
|
|
452
|
+
}) {
|
|
453
|
+
const options = field.options ?? [];
|
|
454
|
+
const currentIndex = options.findIndex(
|
|
455
|
+
(opt) => String(opt.value) === String(value)
|
|
456
|
+
);
|
|
457
|
+
const selectedIndex = currentIndex >= 0 ? currentIndex : 0;
|
|
458
|
+
useInput3(
|
|
459
|
+
(input, key) => {
|
|
460
|
+
if (!isActive || options.length === 0) return;
|
|
461
|
+
if (input === " " || key.rightArrow) {
|
|
462
|
+
const newIndex = selectedIndex < options.length - 1 ? selectedIndex + 1 : 0;
|
|
463
|
+
onChange(options[newIndex].value);
|
|
464
|
+
} else if (key.leftArrow) {
|
|
465
|
+
const newIndex = selectedIndex > 0 ? selectedIndex - 1 : options.length - 1;
|
|
466
|
+
onChange(options[newIndex].value);
|
|
467
|
+
}
|
|
468
|
+
},
|
|
469
|
+
{ isActive }
|
|
470
|
+
);
|
|
471
|
+
const selectedOption = options[selectedIndex];
|
|
472
|
+
return /* @__PURE__ */ jsxs3(Box3, { children: [
|
|
473
|
+
/* @__PURE__ */ jsx4(Text4, { color: isActive ? "cyan" : void 0, children: isActive ? "\u203A " : " " }),
|
|
474
|
+
/* @__PURE__ */ jsxs3(Text4, { children: [
|
|
475
|
+
field.label,
|
|
476
|
+
": "
|
|
477
|
+
] }),
|
|
478
|
+
/* @__PURE__ */ jsxs3(Text4, { color: isActive ? "cyan" : void 0, bold: isActive, children: [
|
|
479
|
+
"\u25C0 ",
|
|
480
|
+
selectedOption?.label ?? "(none)",
|
|
481
|
+
" \u25B6"
|
|
482
|
+
] }),
|
|
483
|
+
field.description && /* @__PURE__ */ jsxs3(Text4, { dimColor: true, children: [
|
|
484
|
+
" (",
|
|
485
|
+
field.description,
|
|
486
|
+
")"
|
|
487
|
+
] })
|
|
488
|
+
] });
|
|
489
|
+
}
|
|
490
|
+
function MultiselectField({
|
|
491
|
+
field,
|
|
492
|
+
value,
|
|
493
|
+
onChange,
|
|
494
|
+
isActive
|
|
495
|
+
}) {
|
|
496
|
+
const options = field.options ?? [];
|
|
497
|
+
const selectedValues = new Set(
|
|
498
|
+
Array.isArray(value) ? value.map(String) : []
|
|
499
|
+
);
|
|
500
|
+
const [cursor, setCursor] = useState4(0);
|
|
501
|
+
useInput3(
|
|
502
|
+
(input, key) => {
|
|
503
|
+
if (!isActive || options.length === 0) return;
|
|
504
|
+
if (key.upArrow) {
|
|
505
|
+
setCursor((prev) => prev > 0 ? prev - 1 : options.length - 1);
|
|
506
|
+
} else if (key.downArrow) {
|
|
507
|
+
setCursor((prev) => prev < options.length - 1 ? prev + 1 : 0);
|
|
508
|
+
} else if (input === " ") {
|
|
509
|
+
const opt = options[cursor];
|
|
510
|
+
const newSelected = new Set(selectedValues);
|
|
511
|
+
if (newSelected.has(String(opt.value))) {
|
|
512
|
+
newSelected.delete(String(opt.value));
|
|
513
|
+
} else {
|
|
514
|
+
newSelected.add(String(opt.value));
|
|
515
|
+
}
|
|
516
|
+
onChange(Array.from(newSelected));
|
|
517
|
+
}
|
|
518
|
+
},
|
|
519
|
+
{ isActive }
|
|
520
|
+
);
|
|
521
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
|
|
522
|
+
/* @__PURE__ */ jsxs3(Box3, { children: [
|
|
523
|
+
/* @__PURE__ */ jsx4(Text4, { color: isActive ? "cyan" : void 0, children: isActive ? "\u203A " : " " }),
|
|
524
|
+
/* @__PURE__ */ jsx4(Text4, { children: field.label }),
|
|
525
|
+
field.description && /* @__PURE__ */ jsxs3(Text4, { dimColor: true, children: [
|
|
526
|
+
" - ",
|
|
527
|
+
field.description
|
|
528
|
+
] })
|
|
529
|
+
] }),
|
|
530
|
+
isActive && /* @__PURE__ */ jsx4(Box3, { flexDirection: "column", paddingLeft: 4, children: options.map((opt, i) => {
|
|
531
|
+
const isSelected = selectedValues.has(String(opt.value));
|
|
532
|
+
const isCursor = i === cursor;
|
|
533
|
+
return /* @__PURE__ */ jsxs3(Box3, { children: [
|
|
534
|
+
/* @__PURE__ */ jsx4(Text4, { color: isCursor ? "cyan" : void 0, children: isCursor ? "\u203A " : " " }),
|
|
535
|
+
/* @__PURE__ */ jsx4(Text4, { color: isSelected ? "green" : void 0, children: isSelected ? "[\u2713]" : "[ ]" }),
|
|
536
|
+
/* @__PURE__ */ jsxs3(Text4, { color: isCursor ? "cyan" : void 0, children: [
|
|
537
|
+
" ",
|
|
538
|
+
opt.label
|
|
539
|
+
] })
|
|
540
|
+
] }, String(opt.value));
|
|
541
|
+
}) }),
|
|
542
|
+
!isActive && /* @__PURE__ */ jsx4(Box3, { paddingLeft: 4, children: /* @__PURE__ */ jsxs3(Text4, { dimColor: true, children: [
|
|
543
|
+
"Selected: ",
|
|
544
|
+
Array.from(selectedValues).length > 0 ? Array.from(selectedValues).join(", ") : "(none)"
|
|
545
|
+
] }) })
|
|
546
|
+
] });
|
|
547
|
+
}
|
|
548
|
+
function OptionField(props) {
|
|
549
|
+
const { field } = props;
|
|
550
|
+
switch (field.type) {
|
|
551
|
+
case "boolean":
|
|
552
|
+
return /* @__PURE__ */ jsx4(BooleanField, { ...props });
|
|
553
|
+
case "number":
|
|
554
|
+
return /* @__PURE__ */ jsx4(NumberField, { ...props });
|
|
555
|
+
case "text":
|
|
556
|
+
return /* @__PURE__ */ jsx4(TextField, { ...props });
|
|
557
|
+
case "select":
|
|
558
|
+
return /* @__PURE__ */ jsx4(SelectField, { ...props });
|
|
559
|
+
case "multiselect":
|
|
560
|
+
return /* @__PURE__ */ jsx4(MultiselectField, { ...props });
|
|
561
|
+
default:
|
|
562
|
+
return /* @__PURE__ */ jsx4(Box3, { children: /* @__PURE__ */ jsxs3(Text4, { dimColor: true, children: [
|
|
563
|
+
"Unknown field type: ",
|
|
564
|
+
field.type
|
|
565
|
+
] }) });
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
function convertFieldValue(value, field, defaultValue) {
|
|
569
|
+
if (Array.isArray(defaultValue) && field.type === "text" && typeof value === "string") {
|
|
570
|
+
return value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
571
|
+
}
|
|
572
|
+
return value;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
// src/commands/install/components/RuleSelector.tsx
|
|
576
|
+
import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
323
577
|
function SeverityBadge({ severity }) {
|
|
324
578
|
if (severity === "error") {
|
|
325
|
-
return /* @__PURE__ */
|
|
579
|
+
return /* @__PURE__ */ jsx5(Text5, { color: "red", children: "error" });
|
|
326
580
|
}
|
|
327
581
|
if (severity === "warn") {
|
|
328
|
-
return /* @__PURE__ */
|
|
582
|
+
return /* @__PURE__ */ jsx5(Text5, { color: "yellow", children: "warn" });
|
|
329
583
|
}
|
|
330
|
-
return /* @__PURE__ */
|
|
584
|
+
return /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "off" });
|
|
331
585
|
}
|
|
332
586
|
function CategoryHeader({ name, icon }) {
|
|
333
|
-
return /* @__PURE__ */
|
|
587
|
+
return /* @__PURE__ */ jsx5(Box4, { marginTop: 1, marginBottom: 0, children: /* @__PURE__ */ jsxs4(Text5, { bold: true, color: "white", children: [
|
|
334
588
|
icon,
|
|
335
589
|
" ",
|
|
336
590
|
name
|
|
@@ -345,28 +599,35 @@ function RuleSelector({
|
|
|
345
599
|
const staticRules = useMemo(() => getRulesByCategory("static"), []);
|
|
346
600
|
const semanticRules = useMemo(() => getRulesByCategory("semantic"), []);
|
|
347
601
|
const allRules = useMemo(() => [...staticRules, ...semanticRules], [staticRules, semanticRules]);
|
|
348
|
-
const [cursor, setCursor] =
|
|
349
|
-
const [viewMode, setViewMode] =
|
|
350
|
-
const [ruleStates, setRuleStates] =
|
|
602
|
+
const [cursor, setCursor] = useState5(0);
|
|
603
|
+
const [viewMode, setViewMode] = useState5("list");
|
|
604
|
+
const [ruleStates, setRuleStates] = useState5(
|
|
351
605
|
() => {
|
|
352
606
|
const map = /* @__PURE__ */ new Map();
|
|
353
|
-
for (const rule of
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
severity: rule.defaultSeverity === "off" ? "warn" : rule.defaultSeverity
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
for (const rule of semanticRules) {
|
|
607
|
+
for (const rule of allRules) {
|
|
608
|
+
const categoryMeta = getCategoryMeta(rule.category);
|
|
609
|
+
const enabled = rule.defaultEnabled ?? categoryMeta?.defaultEnabled ?? false;
|
|
360
610
|
map.set(rule.id, {
|
|
361
|
-
enabled
|
|
611
|
+
enabled,
|
|
362
612
|
severity: rule.defaultSeverity === "off" ? "warn" : rule.defaultSeverity
|
|
363
613
|
});
|
|
364
614
|
}
|
|
365
615
|
return map;
|
|
366
616
|
}
|
|
367
617
|
);
|
|
618
|
+
const [customOptions, setCustomOptions] = useState5(/* @__PURE__ */ new Map());
|
|
619
|
+
const [editingRuleIndex, setEditingRuleIndex] = useState5(0);
|
|
620
|
+
const [editingFieldCursor, setEditingFieldCursor] = useState5(0);
|
|
621
|
+
const [confirmCursor, setConfirmCursor] = useState5(1);
|
|
368
622
|
const currentRule = allRules[cursor];
|
|
369
|
-
const
|
|
623
|
+
const enabledRulesWithOptions = useMemo(() => {
|
|
624
|
+
return allRules.filter((rule) => {
|
|
625
|
+
const state = ruleStates.get(rule.id);
|
|
626
|
+
return state?.enabled && rule.optionSchema && rule.optionSchema.fields.length > 0;
|
|
627
|
+
});
|
|
628
|
+
}, [allRules, ruleStates]);
|
|
629
|
+
const currentEditingRule = enabledRulesWithOptions[editingRuleIndex];
|
|
630
|
+
const currentEditingFields = currentEditingRule?.optionSchema?.fields ?? [];
|
|
370
631
|
const toggleRule = () => {
|
|
371
632
|
if (!currentRule) return;
|
|
372
633
|
setRuleStates((prev) => {
|
|
@@ -386,27 +647,122 @@ function RuleSelector({
|
|
|
386
647
|
return next;
|
|
387
648
|
});
|
|
388
649
|
};
|
|
389
|
-
const
|
|
650
|
+
const finalSubmit = () => {
|
|
390
651
|
const configuredRules = [];
|
|
391
652
|
for (const rule of allRules) {
|
|
392
653
|
const state = ruleStates.get(rule.id);
|
|
393
654
|
if (state?.enabled) {
|
|
655
|
+
const custom = customOptions.get(rule.id);
|
|
656
|
+
const baseOptions = rule.defaultOptions?.[0] ?? {};
|
|
394
657
|
configuredRules.push({
|
|
395
658
|
rule,
|
|
396
659
|
severity: state.severity,
|
|
397
|
-
options: rule.defaultOptions
|
|
660
|
+
options: custom ? [{ ...baseOptions, ...custom }] : rule.defaultOptions
|
|
398
661
|
});
|
|
399
662
|
}
|
|
400
663
|
}
|
|
401
664
|
onSubmit(configuredRules);
|
|
402
665
|
};
|
|
403
|
-
|
|
666
|
+
const handleListSubmit = () => {
|
|
667
|
+
if (enabledRulesWithOptions.length > 0) {
|
|
668
|
+
setViewMode("confirm-options");
|
|
669
|
+
setConfirmCursor(1);
|
|
670
|
+
} else {
|
|
671
|
+
finalSubmit();
|
|
672
|
+
}
|
|
673
|
+
};
|
|
674
|
+
const handleConfirmSelection = () => {
|
|
675
|
+
if (confirmCursor === 0) {
|
|
676
|
+
setEditingRuleIndex(0);
|
|
677
|
+
setEditingFieldCursor(0);
|
|
678
|
+
if (enabledRulesWithOptions[0]) {
|
|
679
|
+
initializeRuleOptions(enabledRulesWithOptions[0]);
|
|
680
|
+
}
|
|
681
|
+
setViewMode("edit-options");
|
|
682
|
+
} else {
|
|
683
|
+
finalSubmit();
|
|
684
|
+
}
|
|
685
|
+
};
|
|
686
|
+
const initializeRuleOptions = (rule) => {
|
|
687
|
+
if (!customOptions.has(rule.id) && rule.optionSchema) {
|
|
688
|
+
const baseOptions = rule.defaultOptions?.[0] ?? {};
|
|
689
|
+
const initial = {};
|
|
690
|
+
for (const field of rule.optionSchema.fields) {
|
|
691
|
+
initial[field.key] = baseOptions[field.key] ?? field.defaultValue;
|
|
692
|
+
}
|
|
693
|
+
setCustomOptions((prev) => {
|
|
694
|
+
const next = new Map(prev);
|
|
695
|
+
next.set(rule.id, initial);
|
|
696
|
+
return next;
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
};
|
|
700
|
+
const updateFieldValue = (fieldKey, value) => {
|
|
701
|
+
if (!currentEditingRule) return;
|
|
702
|
+
setCustomOptions((prev) => {
|
|
703
|
+
const next = new Map(prev);
|
|
704
|
+
const current = next.get(currentEditingRule.id) ?? {};
|
|
705
|
+
next.set(currentEditingRule.id, { ...current, [fieldKey]: value });
|
|
706
|
+
return next;
|
|
707
|
+
});
|
|
708
|
+
};
|
|
709
|
+
const nextEditingRule = () => {
|
|
710
|
+
if (editingRuleIndex < enabledRulesWithOptions.length - 1) {
|
|
711
|
+
const nextIndex = editingRuleIndex + 1;
|
|
712
|
+
setEditingRuleIndex(nextIndex);
|
|
713
|
+
setEditingFieldCursor(0);
|
|
714
|
+
if (enabledRulesWithOptions[nextIndex]) {
|
|
715
|
+
initializeRuleOptions(enabledRulesWithOptions[nextIndex]);
|
|
716
|
+
}
|
|
717
|
+
} else {
|
|
718
|
+
finalSubmit();
|
|
719
|
+
}
|
|
720
|
+
};
|
|
721
|
+
const skipCurrentRule = () => {
|
|
722
|
+
if (currentEditingRule) {
|
|
723
|
+
setCustomOptions((prev) => {
|
|
724
|
+
const next = new Map(prev);
|
|
725
|
+
next.delete(currentEditingRule.id);
|
|
726
|
+
return next;
|
|
727
|
+
});
|
|
728
|
+
}
|
|
729
|
+
nextEditingRule();
|
|
730
|
+
};
|
|
731
|
+
useInput4((input, key) => {
|
|
404
732
|
if (viewMode === "docs") {
|
|
405
733
|
if (key.escape || key.return || input === "d" || input === "q") {
|
|
406
734
|
setViewMode("list");
|
|
407
735
|
}
|
|
408
736
|
return;
|
|
409
737
|
}
|
|
738
|
+
if (viewMode === "confirm-options") {
|
|
739
|
+
if (key.upArrow || key.downArrow) {
|
|
740
|
+
setConfirmCursor((prev) => prev === 0 ? 1 : 0);
|
|
741
|
+
} else if (key.return || input === " ") {
|
|
742
|
+
handleConfirmSelection();
|
|
743
|
+
} else if (key.escape || input === "q") {
|
|
744
|
+
setViewMode("list");
|
|
745
|
+
}
|
|
746
|
+
return;
|
|
747
|
+
}
|
|
748
|
+
if (viewMode === "edit-options") {
|
|
749
|
+
if (key.upArrow) {
|
|
750
|
+
setEditingFieldCursor(
|
|
751
|
+
(prev) => prev > 0 ? prev - 1 : currentEditingFields.length - 1
|
|
752
|
+
);
|
|
753
|
+
} else if (key.downArrow) {
|
|
754
|
+
setEditingFieldCursor(
|
|
755
|
+
(prev) => prev < currentEditingFields.length - 1 ? prev + 1 : 0
|
|
756
|
+
);
|
|
757
|
+
} else if (key.return) {
|
|
758
|
+
nextEditingRule();
|
|
759
|
+
} else if (key.escape) {
|
|
760
|
+
skipCurrentRule();
|
|
761
|
+
} else if (input === "q") {
|
|
762
|
+
setViewMode("list");
|
|
763
|
+
}
|
|
764
|
+
return;
|
|
765
|
+
}
|
|
410
766
|
if (key.upArrow) {
|
|
411
767
|
setCursor((prev) => prev > 0 ? prev - 1 : allRules.length - 1);
|
|
412
768
|
} else if (key.downArrow) {
|
|
@@ -418,7 +774,7 @@ function RuleSelector({
|
|
|
418
774
|
} else if (input === "d") {
|
|
419
775
|
setViewMode("docs");
|
|
420
776
|
} else if (key.return) {
|
|
421
|
-
|
|
777
|
+
handleListSubmit();
|
|
422
778
|
} else if (key.escape || input === "q") {
|
|
423
779
|
onCancel?.();
|
|
424
780
|
exit();
|
|
@@ -446,40 +802,136 @@ function RuleSelector({
|
|
|
446
802
|
});
|
|
447
803
|
if (viewMode === "docs" && currentRule) {
|
|
448
804
|
const docLines = currentRule.docs.trim().split("\n").slice(0, 20);
|
|
449
|
-
return /* @__PURE__ */
|
|
450
|
-
/* @__PURE__ */
|
|
451
|
-
/* @__PURE__ */
|
|
452
|
-
/* @__PURE__ */
|
|
805
|
+
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
806
|
+
/* @__PURE__ */ jsxs4(Box4, { marginBottom: 1, children: [
|
|
807
|
+
/* @__PURE__ */ jsx5(Text5, { bold: true, color: "cyan", children: currentRule.name }),
|
|
808
|
+
/* @__PURE__ */ jsxs4(Text5, { dimColor: true, children: [
|
|
453
809
|
" - ",
|
|
454
810
|
currentRule.description
|
|
455
811
|
] })
|
|
456
812
|
] }),
|
|
457
|
-
/* @__PURE__ */
|
|
458
|
-
docLines.map((line, i) => /* @__PURE__ */
|
|
459
|
-
currentRule.docs.split("\n").length > 20 && /* @__PURE__ */
|
|
813
|
+
/* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", borderStyle: "single", borderColor: "gray", paddingX: 1, children: [
|
|
814
|
+
docLines.map((line, i) => /* @__PURE__ */ jsx5(Text5, { dimColor: line.startsWith("#"), children: line }, i)),
|
|
815
|
+
currentRule.docs.split("\n").length > 20 && /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "... (truncated)" })
|
|
816
|
+
] }),
|
|
817
|
+
/* @__PURE__ */ jsx5(Box4, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "Press any key to return to list" }) })
|
|
818
|
+
] });
|
|
819
|
+
}
|
|
820
|
+
if (viewMode === "confirm-options") {
|
|
821
|
+
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
822
|
+
/* @__PURE__ */ jsx5(Box4, { marginBottom: 1, children: /* @__PURE__ */ jsx5(Text5, { bold: true, children: "Configure Rule Options" }) }),
|
|
823
|
+
/* @__PURE__ */ jsx5(Box4, { marginBottom: 1, children: /* @__PURE__ */ jsxs4(Text5, { children: [
|
|
824
|
+
/* @__PURE__ */ jsx5(Text5, { color: "cyan", children: enabledRulesWithOptions.length }),
|
|
825
|
+
/* @__PURE__ */ jsx5(Text5, { children: " selected rules have configurable options. Would you like to customize them?" })
|
|
826
|
+
] }) }),
|
|
827
|
+
/* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", paddingLeft: 2, children: [
|
|
828
|
+
/* @__PURE__ */ jsxs4(Box4, { children: [
|
|
829
|
+
/* @__PURE__ */ jsx5(Text5, { color: confirmCursor === 0 ? "cyan" : void 0, children: confirmCursor === 0 ? "\u203A " : " " }),
|
|
830
|
+
/* @__PURE__ */ jsx5(Text5, { color: confirmCursor === 0 ? "cyan" : void 0, bold: confirmCursor === 0, children: "Yes" }),
|
|
831
|
+
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: " - Configure each rule's options" })
|
|
832
|
+
] }),
|
|
833
|
+
/* @__PURE__ */ jsxs4(Box4, { children: [
|
|
834
|
+
/* @__PURE__ */ jsx5(Text5, { color: confirmCursor === 1 ? "cyan" : void 0, children: confirmCursor === 1 ? "\u203A " : " " }),
|
|
835
|
+
/* @__PURE__ */ jsx5(Text5, { color: confirmCursor === 1 ? "cyan" : void 0, bold: confirmCursor === 1, children: "No" }),
|
|
836
|
+
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: " - Use defaults for all rules" })
|
|
837
|
+
] })
|
|
838
|
+
] }),
|
|
839
|
+
/* @__PURE__ */ jsx5(Box4, { marginTop: 1, children: /* @__PURE__ */ jsxs4(Text5, { dimColor: true, children: [
|
|
840
|
+
"Rules with options:",
|
|
841
|
+
" ",
|
|
842
|
+
enabledRulesWithOptions.map((r) => r.name).join(", ")
|
|
843
|
+
] }) }),
|
|
844
|
+
/* @__PURE__ */ jsx5(Box4, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 1, children: /* @__PURE__ */ jsxs4(Text5, { dimColor: true, children: [
|
|
845
|
+
/* @__PURE__ */ jsx5(Text5, { color: "cyan", children: "\u2191\u2193" }),
|
|
846
|
+
" select",
|
|
847
|
+
" ",
|
|
848
|
+
/* @__PURE__ */ jsx5(Text5, { color: "cyan", children: "enter" }),
|
|
849
|
+
" confirm",
|
|
850
|
+
" ",
|
|
851
|
+
/* @__PURE__ */ jsx5(Text5, { color: "cyan", children: "esc" }),
|
|
852
|
+
" back"
|
|
853
|
+
] }) })
|
|
854
|
+
] });
|
|
855
|
+
}
|
|
856
|
+
if (viewMode === "edit-options" && currentEditingRule) {
|
|
857
|
+
const ruleOptions = customOptions.get(currentEditingRule.id) ?? {};
|
|
858
|
+
const baseOptions = currentEditingRule.defaultOptions?.[0] ?? {};
|
|
859
|
+
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
860
|
+
/* @__PURE__ */ jsxs4(Box4, { marginBottom: 1, children: [
|
|
861
|
+
/* @__PURE__ */ jsxs4(Text5, { bold: true, color: "cyan", children: [
|
|
862
|
+
currentEditingRule.icon ?? "\u2699\uFE0F",
|
|
863
|
+
" ",
|
|
864
|
+
currentEditingRule.name
|
|
865
|
+
] }),
|
|
866
|
+
/* @__PURE__ */ jsxs4(Text5, { dimColor: true, children: [
|
|
867
|
+
" (",
|
|
868
|
+
editingRuleIndex + 1,
|
|
869
|
+
"/",
|
|
870
|
+
enabledRulesWithOptions.length,
|
|
871
|
+
")"
|
|
872
|
+
] })
|
|
460
873
|
] }),
|
|
461
|
-
/* @__PURE__ */
|
|
874
|
+
/* @__PURE__ */ jsx5(Box4, { marginBottom: 1, children: /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: currentEditingRule.description }) }),
|
|
875
|
+
/* @__PURE__ */ jsx5(Box4, { flexDirection: "column", children: currentEditingFields.map((field, i) => {
|
|
876
|
+
const currentValue = ruleOptions[field.key] ?? baseOptions[field.key] ?? field.defaultValue;
|
|
877
|
+
const defaultValue = baseOptions[field.key] ?? field.defaultValue;
|
|
878
|
+
return /* @__PURE__ */ jsx5(
|
|
879
|
+
OptionField,
|
|
880
|
+
{
|
|
881
|
+
field,
|
|
882
|
+
value: currentValue,
|
|
883
|
+
onChange: (newValue) => {
|
|
884
|
+
const converted = convertFieldValue(newValue, field, defaultValue);
|
|
885
|
+
updateFieldValue(field.key, converted);
|
|
886
|
+
},
|
|
887
|
+
isActive: i === editingFieldCursor
|
|
888
|
+
},
|
|
889
|
+
field.key
|
|
890
|
+
);
|
|
891
|
+
}) }),
|
|
892
|
+
/* @__PURE__ */ jsx5(Box4, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 1, children: /* @__PURE__ */ jsxs4(Text5, { dimColor: true, children: [
|
|
893
|
+
/* @__PURE__ */ jsx5(Text5, { color: "cyan", children: "\u2191\u2193" }),
|
|
894
|
+
" navigate",
|
|
895
|
+
" ",
|
|
896
|
+
/* @__PURE__ */ jsx5(Text5, { color: "cyan", children: "space" }),
|
|
897
|
+
" toggle",
|
|
898
|
+
" ",
|
|
899
|
+
/* @__PURE__ */ jsx5(Text5, { color: "cyan", children: "enter" }),
|
|
900
|
+
" next rule",
|
|
901
|
+
" ",
|
|
902
|
+
/* @__PURE__ */ jsx5(Text5, { color: "cyan", children: "esc" }),
|
|
903
|
+
" skip (use defaults)"
|
|
904
|
+
] }) })
|
|
462
905
|
] });
|
|
463
906
|
}
|
|
464
907
|
const enabledCount = Array.from(ruleStates.values()).filter((s) => s.enabled).length;
|
|
465
908
|
const errorCount = Array.from(ruleStates.entries()).filter(
|
|
466
|
-
([
|
|
909
|
+
([, s]) => s.enabled && s.severity === "error"
|
|
467
910
|
).length;
|
|
468
911
|
const warnCount = enabledCount - errorCount;
|
|
469
912
|
let globalIndex = 0;
|
|
470
|
-
return /* @__PURE__ */
|
|
471
|
-
/* @__PURE__ */
|
|
472
|
-
|
|
473
|
-
|
|
913
|
+
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
914
|
+
/* @__PURE__ */ jsx5(Box4, { marginBottom: 1, children: /* @__PURE__ */ jsx5(Text5, { bold: true, children: "Configure ESLint Rules" }) }),
|
|
915
|
+
(() => {
|
|
916
|
+
const cat = getCategoryMeta("static");
|
|
917
|
+
return cat ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
918
|
+
/* @__PURE__ */ jsx5(CategoryHeader, { name: cat.name, icon: cat.icon }),
|
|
919
|
+
/* @__PURE__ */ jsxs4(Text5, { dimColor: true, children: [
|
|
920
|
+
" ",
|
|
921
|
+
cat.description
|
|
922
|
+
] })
|
|
923
|
+
] }) : null;
|
|
924
|
+
})(),
|
|
474
925
|
staticRules.map((rule) => {
|
|
475
926
|
const itemIndex = globalIndex++;
|
|
476
927
|
const isCursor = itemIndex === cursor;
|
|
477
928
|
const state = ruleStates.get(rule.id);
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
/* @__PURE__ */
|
|
481
|
-
/* @__PURE__ */
|
|
482
|
-
|
|
929
|
+
const hasOptions = rule.optionSchema && rule.optionSchema.fields.length > 0;
|
|
930
|
+
return /* @__PURE__ */ jsxs4(Box4, { paddingLeft: 2, children: [
|
|
931
|
+
/* @__PURE__ */ jsx5(Text5, { color: isCursor ? "cyan" : void 0, children: isCursor ? "\u203A " : " " }),
|
|
932
|
+
/* @__PURE__ */ jsx5(Box4, { width: 3, children: /* @__PURE__ */ jsx5(Text5, { color: state.enabled ? "green" : void 0, dimColor: !state.enabled, children: state.enabled ? "\u2713" : "\u25CB" }) }),
|
|
933
|
+
/* @__PURE__ */ jsx5(Box4, { width: 30, children: /* @__PURE__ */ jsx5(
|
|
934
|
+
Text5,
|
|
483
935
|
{
|
|
484
936
|
color: isCursor ? "cyan" : void 0,
|
|
485
937
|
dimColor: !state.enabled,
|
|
@@ -487,20 +939,30 @@ function RuleSelector({
|
|
|
487
939
|
children: rule.name
|
|
488
940
|
}
|
|
489
941
|
) }),
|
|
490
|
-
/* @__PURE__ */
|
|
942
|
+
/* @__PURE__ */ jsx5(Box4, { width: 8, children: state.enabled ? /* @__PURE__ */ jsx5(SeverityBadge, { severity: state.severity }) : /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "-" }) }),
|
|
943
|
+
hasOptions && state.enabled && /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: " \u2699" })
|
|
491
944
|
] }, rule.id);
|
|
492
945
|
}),
|
|
493
|
-
|
|
494
|
-
|
|
946
|
+
(() => {
|
|
947
|
+
const cat = getCategoryMeta("semantic");
|
|
948
|
+
return cat ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
949
|
+
/* @__PURE__ */ jsx5(CategoryHeader, { name: cat.name, icon: cat.icon }),
|
|
950
|
+
/* @__PURE__ */ jsxs4(Text5, { dimColor: true, children: [
|
|
951
|
+
" ",
|
|
952
|
+
cat.description
|
|
953
|
+
] })
|
|
954
|
+
] }) : null;
|
|
955
|
+
})(),
|
|
495
956
|
semanticRules.map((rule) => {
|
|
496
957
|
const itemIndex = globalIndex++;
|
|
497
958
|
const isCursor = itemIndex === cursor;
|
|
498
959
|
const state = ruleStates.get(rule.id);
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
/* @__PURE__ */
|
|
502
|
-
/* @__PURE__ */
|
|
503
|
-
|
|
960
|
+
const hasOptions = rule.optionSchema && rule.optionSchema.fields.length > 0;
|
|
961
|
+
return /* @__PURE__ */ jsxs4(Box4, { paddingLeft: 2, children: [
|
|
962
|
+
/* @__PURE__ */ jsx5(Text5, { color: isCursor ? "cyan" : void 0, children: isCursor ? "\u203A " : " " }),
|
|
963
|
+
/* @__PURE__ */ jsx5(Box4, { width: 3, children: /* @__PURE__ */ jsx5(Text5, { color: state.enabled ? "green" : void 0, dimColor: !state.enabled, children: state.enabled ? "\u2713" : "\u25CB" }) }),
|
|
964
|
+
/* @__PURE__ */ jsx5(Box4, { width: 30, children: /* @__PURE__ */ jsx5(
|
|
965
|
+
Text5,
|
|
504
966
|
{
|
|
505
967
|
color: isCursor ? "cyan" : void 0,
|
|
506
968
|
dimColor: !state.enabled,
|
|
@@ -508,47 +970,53 @@ function RuleSelector({
|
|
|
508
970
|
children: rule.name
|
|
509
971
|
}
|
|
510
972
|
) }),
|
|
511
|
-
/* @__PURE__ */
|
|
973
|
+
/* @__PURE__ */ jsx5(Box4, { width: 8, children: state.enabled ? /* @__PURE__ */ jsx5(SeverityBadge, { severity: state.severity }) : /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "-" }) }),
|
|
974
|
+
hasOptions && state.enabled && /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: " \u2699" })
|
|
512
975
|
] }, rule.id);
|
|
513
976
|
}),
|
|
514
|
-
currentRule && /* @__PURE__ */
|
|
515
|
-
/* @__PURE__ */
|
|
516
|
-
/* @__PURE__ */
|
|
977
|
+
currentRule && /* @__PURE__ */ jsx5(Box4, { marginTop: 1, paddingX: 2, children: /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: currentRule.description }) }),
|
|
978
|
+
/* @__PURE__ */ jsx5(Box4, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 1, children: /* @__PURE__ */ jsxs4(Text5, { dimColor: true, children: [
|
|
979
|
+
/* @__PURE__ */ jsx5(Text5, { color: "cyan", children: "\u2191\u2193" }),
|
|
517
980
|
" navigate",
|
|
518
981
|
" ",
|
|
519
|
-
/* @__PURE__ */
|
|
982
|
+
/* @__PURE__ */ jsx5(Text5, { color: "cyan", children: "space" }),
|
|
520
983
|
" toggle",
|
|
521
984
|
" ",
|
|
522
|
-
/* @__PURE__ */
|
|
985
|
+
/* @__PURE__ */ jsx5(Text5, { color: "cyan", children: "s" }),
|
|
523
986
|
" severity",
|
|
524
987
|
" ",
|
|
525
|
-
/* @__PURE__ */
|
|
988
|
+
/* @__PURE__ */ jsx5(Text5, { color: "cyan", children: "d" }),
|
|
526
989
|
" docs",
|
|
527
990
|
" ",
|
|
528
|
-
/* @__PURE__ */
|
|
991
|
+
/* @__PURE__ */ jsx5(Text5, { color: "cyan", children: "a" }),
|
|
529
992
|
" all",
|
|
530
993
|
" ",
|
|
531
|
-
/* @__PURE__ */
|
|
994
|
+
/* @__PURE__ */ jsx5(Text5, { color: "cyan", children: "n" }),
|
|
532
995
|
" none",
|
|
533
996
|
" ",
|
|
534
|
-
/* @__PURE__ */
|
|
997
|
+
/* @__PURE__ */ jsx5(Text5, { color: "cyan", children: "enter" }),
|
|
535
998
|
" confirm"
|
|
536
999
|
] }) }),
|
|
537
|
-
/* @__PURE__ */
|
|
538
|
-
/* @__PURE__ */
|
|
539
|
-
/* @__PURE__ */
|
|
540
|
-
/* @__PURE__ */
|
|
541
|
-
/* @__PURE__ */
|
|
542
|
-
/* @__PURE__ */
|
|
543
|
-
/* @__PURE__ */
|
|
1000
|
+
/* @__PURE__ */ jsx5(Box4, { marginTop: 1, children: /* @__PURE__ */ jsxs4(Text5, { children: [
|
|
1001
|
+
/* @__PURE__ */ jsx5(Text5, { color: "cyan", children: enabledCount }),
|
|
1002
|
+
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: " rules enabled (" }),
|
|
1003
|
+
/* @__PURE__ */ jsx5(Text5, { color: "red", children: errorCount }),
|
|
1004
|
+
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: " errors, " }),
|
|
1005
|
+
/* @__PURE__ */ jsx5(Text5, { color: "yellow", children: warnCount }),
|
|
1006
|
+
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: " warnings)" }),
|
|
1007
|
+
enabledRulesWithOptions.length > 0 && /* @__PURE__ */ jsxs4(Text5, { dimColor: true, children: [
|
|
1008
|
+
", ",
|
|
1009
|
+
enabledRulesWithOptions.length,
|
|
1010
|
+
" with options \u2699"
|
|
1011
|
+
] })
|
|
544
1012
|
] }) })
|
|
545
1013
|
] });
|
|
546
1014
|
}
|
|
547
1015
|
|
|
548
1016
|
// src/commands/install/components/InjectionPointSelector.tsx
|
|
549
|
-
import { useState as
|
|
550
|
-
import { Box as
|
|
551
|
-
import { jsx as
|
|
1017
|
+
import { useState as useState6 } from "react";
|
|
1018
|
+
import { Box as Box5, Text as Text6, useInput as useInput5, useApp as useApp4 } from "ink";
|
|
1019
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
552
1020
|
function InjectionPointSelector({
|
|
553
1021
|
points,
|
|
554
1022
|
onSubmit,
|
|
@@ -557,8 +1025,8 @@ function InjectionPointSelector({
|
|
|
557
1025
|
}) {
|
|
558
1026
|
const { exit } = useApp4();
|
|
559
1027
|
const recommendedIndex = points.findIndex((p) => p.recommended);
|
|
560
|
-
const [cursor, setCursor] =
|
|
561
|
-
|
|
1028
|
+
const [cursor, setCursor] = useState6(recommendedIndex >= 0 ? recommendedIndex : 0);
|
|
1029
|
+
useInput5((input, key) => {
|
|
562
1030
|
if (key.upArrow) {
|
|
563
1031
|
setCursor((prev) => prev > 0 ? prev - 1 : points.length - 1);
|
|
564
1032
|
} else if (key.downArrow) {
|
|
@@ -575,16 +1043,16 @@ function InjectionPointSelector({
|
|
|
575
1043
|
exit();
|
|
576
1044
|
}
|
|
577
1045
|
});
|
|
578
|
-
return /* @__PURE__ */
|
|
579
|
-
/* @__PURE__ */
|
|
1046
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
1047
|
+
/* @__PURE__ */ jsx6(Box5, { marginBottom: 1, children: /* @__PURE__ */ jsx6(Text6, { bold: true, children: "Where should the devtools component be injected?" }) }),
|
|
580
1048
|
points.map((point, index) => {
|
|
581
1049
|
const isCursor = index === cursor;
|
|
582
|
-
return /* @__PURE__ */
|
|
583
|
-
/* @__PURE__ */
|
|
584
|
-
/* @__PURE__ */
|
|
585
|
-
/* @__PURE__ */
|
|
586
|
-
/* @__PURE__ */
|
|
587
|
-
point.hint && /* @__PURE__ */
|
|
1050
|
+
return /* @__PURE__ */ jsxs5(Box5, { paddingLeft: 1, children: [
|
|
1051
|
+
/* @__PURE__ */ jsx6(Text6, { color: isCursor ? "cyan" : void 0, children: isCursor ? "\u203A " : " " }),
|
|
1052
|
+
/* @__PURE__ */ jsx6(Box5, { width: 2, children: /* @__PURE__ */ jsx6(Text6, { color: isCursor ? "cyan" : void 0, children: isCursor ? "\u25C9" : "\u25CB" }) }),
|
|
1053
|
+
/* @__PURE__ */ jsxs5(Box5, { children: [
|
|
1054
|
+
/* @__PURE__ */ jsx6(Text6, { color: isCursor ? "cyan" : void 0, children: point.label }),
|
|
1055
|
+
point.hint && /* @__PURE__ */ jsxs5(Text6, { dimColor: true, children: [
|
|
588
1056
|
" (",
|
|
589
1057
|
point.hint,
|
|
590
1058
|
")"
|
|
@@ -592,17 +1060,17 @@ function InjectionPointSelector({
|
|
|
592
1060
|
] })
|
|
593
1061
|
] }, point.id);
|
|
594
1062
|
}),
|
|
595
|
-
/* @__PURE__ */
|
|
596
|
-
/* @__PURE__ */
|
|
1063
|
+
/* @__PURE__ */ jsx6(Box5, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 1, children: /* @__PURE__ */ jsxs5(Text6, { dimColor: true, children: [
|
|
1064
|
+
/* @__PURE__ */ jsx6(Text6, { color: "cyan", children: "\u2191\u2193" }),
|
|
597
1065
|
" navigate",
|
|
598
1066
|
" ",
|
|
599
|
-
/* @__PURE__ */
|
|
1067
|
+
/* @__PURE__ */ jsx6(Text6, { color: "cyan", children: "enter" }),
|
|
600
1068
|
" select",
|
|
601
1069
|
" ",
|
|
602
|
-
/* @__PURE__ */
|
|
1070
|
+
/* @__PURE__ */ jsx6(Text6, { color: "cyan", children: "b" }),
|
|
603
1071
|
" back",
|
|
604
1072
|
" ",
|
|
605
|
-
/* @__PURE__ */
|
|
1073
|
+
/* @__PURE__ */ jsx6(Text6, { color: "cyan", children: "q" }),
|
|
606
1074
|
" quit"
|
|
607
1075
|
] }) })
|
|
608
1076
|
] });
|
|
@@ -967,7 +1435,7 @@ var nextOverlayInstaller = {
|
|
|
967
1435
|
};
|
|
968
1436
|
|
|
969
1437
|
// src/commands/install/components/InstallApp.tsx
|
|
970
|
-
import { jsx as
|
|
1438
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
971
1439
|
function getTargetStatus(target) {
|
|
972
1440
|
if (!target.isInstalled) {
|
|
973
1441
|
return "not_installed";
|
|
@@ -1052,10 +1520,10 @@ function checkNodeVersion() {
|
|
|
1052
1520
|
};
|
|
1053
1521
|
}
|
|
1054
1522
|
function Header({ subtitle }) {
|
|
1055
|
-
return /* @__PURE__ */
|
|
1056
|
-
/* @__PURE__ */
|
|
1057
|
-
/* @__PURE__ */
|
|
1058
|
-
subtitle && /* @__PURE__ */
|
|
1523
|
+
return /* @__PURE__ */ jsx7(Box6, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs6(Box6, { children: [
|
|
1524
|
+
/* @__PURE__ */ jsx7(Text7, { bold: true, color: "cyan", children: "\u25C6 UILint" }),
|
|
1525
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: " v0.5.0" }),
|
|
1526
|
+
subtitle && /* @__PURE__ */ jsxs6(Text7, { dimColor: true, children: [
|
|
1059
1527
|
" \xB7 ",
|
|
1060
1528
|
subtitle
|
|
1061
1529
|
] })
|
|
@@ -1069,22 +1537,22 @@ function FeatureConfig({
|
|
|
1069
1537
|
onBack,
|
|
1070
1538
|
onCancel
|
|
1071
1539
|
}) {
|
|
1072
|
-
|
|
1540
|
+
useInput6((input, key) => {
|
|
1073
1541
|
if ((input === "b" || key.leftArrow) && canGoBack) {
|
|
1074
1542
|
onBack();
|
|
1075
1543
|
}
|
|
1076
1544
|
});
|
|
1077
|
-
return /* @__PURE__ */
|
|
1078
|
-
selectedProject && /* @__PURE__ */
|
|
1079
|
-
/* @__PURE__ */
|
|
1080
|
-
/* @__PURE__ */
|
|
1081
|
-
/* @__PURE__ */
|
|
1545
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
1546
|
+
selectedProject && /* @__PURE__ */ jsxs6(Box6, { marginBottom: 1, children: [
|
|
1547
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Project: " }),
|
|
1548
|
+
/* @__PURE__ */ jsx7(Text7, { bold: true, color: "cyan", children: selectedProject.name }),
|
|
1549
|
+
/* @__PURE__ */ jsxs6(Text7, { dimColor: true, children: [
|
|
1082
1550
|
" (",
|
|
1083
1551
|
selectedProject.hint,
|
|
1084
1552
|
")"
|
|
1085
1553
|
] })
|
|
1086
1554
|
] }),
|
|
1087
|
-
/* @__PURE__ */
|
|
1555
|
+
/* @__PURE__ */ jsx7(
|
|
1088
1556
|
ConfigSelector,
|
|
1089
1557
|
{
|
|
1090
1558
|
items: configItems,
|
|
@@ -1092,11 +1560,11 @@ function FeatureConfig({
|
|
|
1092
1560
|
onCancel
|
|
1093
1561
|
}
|
|
1094
1562
|
),
|
|
1095
|
-
canGoBack && /* @__PURE__ */
|
|
1563
|
+
canGoBack && /* @__PURE__ */ jsx7(Box6, { marginTop: 1, children: /* @__PURE__ */ jsxs6(Text7, { dimColor: true, children: [
|
|
1096
1564
|
"Press ",
|
|
1097
|
-
/* @__PURE__ */
|
|
1565
|
+
/* @__PURE__ */ jsx7(Text7, { color: "cyan", children: "b" }),
|
|
1098
1566
|
" or ",
|
|
1099
|
-
/* @__PURE__ */
|
|
1567
|
+
/* @__PURE__ */ jsx7(Text7, { color: "cyan", children: "\u2190" }),
|
|
1100
1568
|
" to select a different project"
|
|
1101
1569
|
] }) })
|
|
1102
1570
|
] });
|
|
@@ -1107,18 +1575,18 @@ function InstallApp({
|
|
|
1107
1575
|
onError
|
|
1108
1576
|
}) {
|
|
1109
1577
|
const { exit } = useApp5();
|
|
1110
|
-
const [phase, setPhase] =
|
|
1111
|
-
const [nodeVersionCheck, setNodeVersionCheck] =
|
|
1112
|
-
const [project, setProject] =
|
|
1113
|
-
const [detectedProjects, setDetectedProjects] =
|
|
1114
|
-
const [selectedProject, setSelectedProject] =
|
|
1115
|
-
const [selections, setSelections] =
|
|
1116
|
-
const [configItems, setConfigItems] =
|
|
1117
|
-
const [selectedFeatureIds, setSelectedFeatureIds] =
|
|
1118
|
-
const [uninstallFeatureIds, setUninstallFeatureIds] =
|
|
1119
|
-
const [error, setError] =
|
|
1120
|
-
const [injectionPoints, setInjectionPoints] =
|
|
1121
|
-
const [selectedInjectionPoint, setSelectedInjectionPoint] =
|
|
1578
|
+
const [phase, setPhase] = useState7("checking-requirements");
|
|
1579
|
+
const [nodeVersionCheck, setNodeVersionCheck] = useState7(null);
|
|
1580
|
+
const [project, setProject] = useState7(null);
|
|
1581
|
+
const [detectedProjects, setDetectedProjects] = useState7([]);
|
|
1582
|
+
const [selectedProject, setSelectedProject] = useState7(null);
|
|
1583
|
+
const [selections, setSelections] = useState7([]);
|
|
1584
|
+
const [configItems, setConfigItems] = useState7([]);
|
|
1585
|
+
const [selectedFeatureIds, setSelectedFeatureIds] = useState7([]);
|
|
1586
|
+
const [uninstallFeatureIds, setUninstallFeatureIds] = useState7([]);
|
|
1587
|
+
const [error, setError] = useState7(null);
|
|
1588
|
+
const [injectionPoints, setInjectionPoints] = useState7([]);
|
|
1589
|
+
const [selectedInjectionPoint, setSelectedInjectionPoint] = useState7(void 0);
|
|
1122
1590
|
const isEslintSelected = selectedFeatureIds.some((id) => id.startsWith("eslint:"));
|
|
1123
1591
|
const isNextSelected = selectedFeatureIds.some((id) => id.startsWith("next:"));
|
|
1124
1592
|
useEffect2(() => {
|
|
@@ -1277,36 +1745,36 @@ function InstallApp({
|
|
|
1277
1745
|
exit();
|
|
1278
1746
|
};
|
|
1279
1747
|
if (phase === "checking-requirements") {
|
|
1280
|
-
return /* @__PURE__ */
|
|
1281
|
-
/* @__PURE__ */
|
|
1282
|
-
/* @__PURE__ */
|
|
1283
|
-
/* @__PURE__ */
|
|
1284
|
-
/* @__PURE__ */
|
|
1748
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
1749
|
+
/* @__PURE__ */ jsx7(Header, { subtitle: "Install" }),
|
|
1750
|
+
/* @__PURE__ */ jsxs6(Box6, { children: [
|
|
1751
|
+
/* @__PURE__ */ jsx7(Spinner, {}),
|
|
1752
|
+
/* @__PURE__ */ jsx7(Text7, { children: " Checking requirements..." })
|
|
1285
1753
|
] })
|
|
1286
1754
|
] });
|
|
1287
1755
|
}
|
|
1288
1756
|
if (phase === "scanning") {
|
|
1289
|
-
return /* @__PURE__ */
|
|
1290
|
-
/* @__PURE__ */
|
|
1291
|
-
/* @__PURE__ */
|
|
1292
|
-
/* @__PURE__ */
|
|
1293
|
-
/* @__PURE__ */
|
|
1757
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
1758
|
+
/* @__PURE__ */ jsx7(Header, { subtitle: "Install" }),
|
|
1759
|
+
/* @__PURE__ */ jsxs6(Box6, { children: [
|
|
1760
|
+
/* @__PURE__ */ jsx7(Spinner, {}),
|
|
1761
|
+
/* @__PURE__ */ jsx7(Text7, { children: " Scanning project..." })
|
|
1294
1762
|
] })
|
|
1295
1763
|
] });
|
|
1296
1764
|
}
|
|
1297
1765
|
if (phase === "error") {
|
|
1298
|
-
return /* @__PURE__ */
|
|
1299
|
-
/* @__PURE__ */
|
|
1300
|
-
/* @__PURE__ */
|
|
1301
|
-
/* @__PURE__ */
|
|
1302
|
-
/* @__PURE__ */
|
|
1766
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
1767
|
+
/* @__PURE__ */ jsx7(Header, {}),
|
|
1768
|
+
/* @__PURE__ */ jsxs6(Box6, { children: [
|
|
1769
|
+
/* @__PURE__ */ jsx7(Text7, { color: "red", children: "\u2717 " }),
|
|
1770
|
+
/* @__PURE__ */ jsx7(Text7, { color: "red", children: error?.message || "An unknown error occurred" })
|
|
1303
1771
|
] })
|
|
1304
1772
|
] });
|
|
1305
1773
|
}
|
|
1306
1774
|
if (phase === "select-project") {
|
|
1307
|
-
return /* @__PURE__ */
|
|
1308
|
-
/* @__PURE__ */
|
|
1309
|
-
/* @__PURE__ */
|
|
1775
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
1776
|
+
/* @__PURE__ */ jsx7(Header, { subtitle: "Install" }),
|
|
1777
|
+
/* @__PURE__ */ jsx7(
|
|
1310
1778
|
ProjectSelector,
|
|
1311
1779
|
{
|
|
1312
1780
|
projects: detectedProjects,
|
|
@@ -1317,9 +1785,9 @@ function InstallApp({
|
|
|
1317
1785
|
] });
|
|
1318
1786
|
}
|
|
1319
1787
|
if (phase === "configure-features" && project && configItems.length > 0) {
|
|
1320
|
-
return /* @__PURE__ */
|
|
1321
|
-
/* @__PURE__ */
|
|
1322
|
-
/* @__PURE__ */
|
|
1788
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
1789
|
+
/* @__PURE__ */ jsx7(Header, { subtitle: "Features" }),
|
|
1790
|
+
/* @__PURE__ */ jsx7(
|
|
1323
1791
|
FeatureConfig,
|
|
1324
1792
|
{
|
|
1325
1793
|
selectedProject,
|
|
@@ -1333,13 +1801,13 @@ function InstallApp({
|
|
|
1333
1801
|
] });
|
|
1334
1802
|
}
|
|
1335
1803
|
if (phase === "configure-injection-point" && injectionPoints.length > 0) {
|
|
1336
|
-
return /* @__PURE__ */
|
|
1337
|
-
/* @__PURE__ */
|
|
1338
|
-
selectedProject && /* @__PURE__ */
|
|
1339
|
-
/* @__PURE__ */
|
|
1340
|
-
/* @__PURE__ */
|
|
1804
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
1805
|
+
/* @__PURE__ */ jsx7(Header, { subtitle: "Injection Point" }),
|
|
1806
|
+
selectedProject && /* @__PURE__ */ jsxs6(Box6, { marginBottom: 1, children: [
|
|
1807
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Project: " }),
|
|
1808
|
+
/* @__PURE__ */ jsx7(Text7, { bold: true, color: "cyan", children: selectedProject.name })
|
|
1341
1809
|
] }),
|
|
1342
|
-
/* @__PURE__ */
|
|
1810
|
+
/* @__PURE__ */ jsx7(
|
|
1343
1811
|
InjectionPointSelector,
|
|
1344
1812
|
{
|
|
1345
1813
|
points: injectionPoints,
|
|
@@ -1351,13 +1819,13 @@ function InstallApp({
|
|
|
1351
1819
|
] });
|
|
1352
1820
|
}
|
|
1353
1821
|
if (phase === "configure-eslint") {
|
|
1354
|
-
return /* @__PURE__ */
|
|
1355
|
-
/* @__PURE__ */
|
|
1356
|
-
selectedProject && /* @__PURE__ */
|
|
1357
|
-
/* @__PURE__ */
|
|
1358
|
-
/* @__PURE__ */
|
|
1822
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
1823
|
+
/* @__PURE__ */ jsx7(Header, { subtitle: "ESLint Rules" }),
|
|
1824
|
+
selectedProject && /* @__PURE__ */ jsxs6(Box6, { marginBottom: 1, children: [
|
|
1825
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Project: " }),
|
|
1826
|
+
/* @__PURE__ */ jsx7(Text7, { bold: true, color: "cyan", children: selectedProject.name })
|
|
1359
1827
|
] }),
|
|
1360
|
-
/* @__PURE__ */
|
|
1828
|
+
/* @__PURE__ */ jsx7(
|
|
1361
1829
|
RuleSelector,
|
|
1362
1830
|
{
|
|
1363
1831
|
onSubmit: handleRuleSubmit,
|
|
@@ -1367,9 +1835,9 @@ function InstallApp({
|
|
|
1367
1835
|
)
|
|
1368
1836
|
] });
|
|
1369
1837
|
}
|
|
1370
|
-
return /* @__PURE__ */
|
|
1371
|
-
/* @__PURE__ */
|
|
1372
|
-
/* @__PURE__ */
|
|
1838
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
1839
|
+
/* @__PURE__ */ jsx7(Header, {}),
|
|
1840
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Loading..." })
|
|
1373
1841
|
] });
|
|
1374
1842
|
}
|
|
1375
1843
|
|
|
@@ -3996,7 +4464,7 @@ async function execute(plan, options = {}) {
|
|
|
3996
4464
|
}
|
|
3997
4465
|
|
|
3998
4466
|
// src/commands/install-ui.tsx
|
|
3999
|
-
import { ruleRegistry as
|
|
4467
|
+
import { ruleRegistry as ruleRegistry2 } from "uilint-eslint";
|
|
4000
4468
|
|
|
4001
4469
|
// src/commands/install/installers/genstyleguide.ts
|
|
4002
4470
|
import { join as join12 } from "path";
|
|
@@ -4187,10 +4655,92 @@ var skillInstaller = {
|
|
|
4187
4655
|
|
|
4188
4656
|
// src/commands/install/installers/eslint.ts
|
|
4189
4657
|
import { join as join14 } from "path";
|
|
4190
|
-
import { ruleRegistry as
|
|
4658
|
+
import { ruleRegistry, getRulesByCategory as getRulesByCategory2, getCategoryMeta as getCategoryMeta2 } from "uilint-eslint";
|
|
4659
|
+
async function promptForField(field, currentValue) {
|
|
4660
|
+
const hint = field.description ? pc.dim(` ${field.description}`) : "";
|
|
4661
|
+
switch (field.type) {
|
|
4662
|
+
case "boolean":
|
|
4663
|
+
return confirm({
|
|
4664
|
+
message: field.label,
|
|
4665
|
+
initialValue: currentValue ?? field.defaultValue ?? false
|
|
4666
|
+
});
|
|
4667
|
+
case "number": {
|
|
4668
|
+
const numResult = await text({
|
|
4669
|
+
message: field.label + hint,
|
|
4670
|
+
placeholder: field.placeholder || String(currentValue ?? field.defaultValue ?? ""),
|
|
4671
|
+
defaultValue: String(currentValue ?? field.defaultValue ?? ""),
|
|
4672
|
+
validate: (value) => {
|
|
4673
|
+
const num = Number(value);
|
|
4674
|
+
if (isNaN(num)) return "Please enter a valid number";
|
|
4675
|
+
return void 0;
|
|
4676
|
+
}
|
|
4677
|
+
});
|
|
4678
|
+
return Number(numResult);
|
|
4679
|
+
}
|
|
4680
|
+
case "text": {
|
|
4681
|
+
const defaultVal = currentValue ?? field.defaultValue ?? "";
|
|
4682
|
+
const displayDefault = Array.isArray(defaultVal) ? defaultVal.join(", ") : String(defaultVal);
|
|
4683
|
+
return text({
|
|
4684
|
+
message: field.label + hint,
|
|
4685
|
+
placeholder: field.placeholder || displayDefault,
|
|
4686
|
+
defaultValue: displayDefault
|
|
4687
|
+
});
|
|
4688
|
+
}
|
|
4689
|
+
case "select":
|
|
4690
|
+
if (!field.options?.length) {
|
|
4691
|
+
return currentValue ?? field.defaultValue;
|
|
4692
|
+
}
|
|
4693
|
+
return select({
|
|
4694
|
+
message: field.label + hint,
|
|
4695
|
+
options: field.options.map((opt) => ({
|
|
4696
|
+
value: String(opt.value),
|
|
4697
|
+
label: opt.label
|
|
4698
|
+
})),
|
|
4699
|
+
initialValue: String(currentValue ?? field.defaultValue)
|
|
4700
|
+
});
|
|
4701
|
+
case "multiselect":
|
|
4702
|
+
if (!field.options?.length) {
|
|
4703
|
+
return currentValue ?? field.defaultValue;
|
|
4704
|
+
}
|
|
4705
|
+
return multiselect({
|
|
4706
|
+
message: field.label + hint,
|
|
4707
|
+
options: field.options.map((opt) => ({
|
|
4708
|
+
value: String(opt.value),
|
|
4709
|
+
label: opt.label
|
|
4710
|
+
})),
|
|
4711
|
+
initialValues: Array.isArray(currentValue) ? currentValue.map(String) : Array.isArray(field.defaultValue) ? field.defaultValue.map(String) : []
|
|
4712
|
+
});
|
|
4713
|
+
default:
|
|
4714
|
+
return currentValue ?? field.defaultValue;
|
|
4715
|
+
}
|
|
4716
|
+
}
|
|
4717
|
+
function convertFieldValue2(value, field, defaultValue) {
|
|
4718
|
+
if (Array.isArray(defaultValue) && field.type === "text" && typeof value === "string") {
|
|
4719
|
+
return value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
4720
|
+
}
|
|
4721
|
+
return value;
|
|
4722
|
+
}
|
|
4723
|
+
async function configureRuleOptions(rule) {
|
|
4724
|
+
if (!rule.optionSchema?.fields?.length) {
|
|
4725
|
+
return void 0;
|
|
4726
|
+
}
|
|
4727
|
+
log("");
|
|
4728
|
+
log(
|
|
4729
|
+
pc.bold(pc.cyan(`${rule.icon ?? "\u2699\uFE0F"} ${rule.name}`)) + pc.dim(` - ${rule.description}`)
|
|
4730
|
+
);
|
|
4731
|
+
const baseOptions = rule.defaultOptions?.[0] ?? {};
|
|
4732
|
+
const options = {};
|
|
4733
|
+
for (const field of rule.optionSchema.fields) {
|
|
4734
|
+
const currentValue = baseOptions[field.key];
|
|
4735
|
+
const defaultValue = currentValue ?? field.defaultValue;
|
|
4736
|
+
const value = await promptForField(field, currentValue);
|
|
4737
|
+
options[field.key] = convertFieldValue2(value, field, defaultValue);
|
|
4738
|
+
}
|
|
4739
|
+
return options;
|
|
4740
|
+
}
|
|
4191
4741
|
function getUpgradeInfo(configuredRuleIds) {
|
|
4192
4742
|
const configuredSet = new Set(configuredRuleIds);
|
|
4193
|
-
const allRuleIds =
|
|
4743
|
+
const allRuleIds = ruleRegistry.map((r) => r.id);
|
|
4194
4744
|
const missingRules = allRuleIds.filter((id) => !configuredSet.has(id));
|
|
4195
4745
|
if (missingRules.length === 0) {
|
|
4196
4746
|
return void 0;
|
|
@@ -4205,8 +4755,8 @@ function formatRuleOption(rule) {
|
|
|
4205
4755
|
const severityBadge = rule.defaultSeverity === "error" ? pc.red("error") : pc.yellow("warn");
|
|
4206
4756
|
return {
|
|
4207
4757
|
value: rule.id,
|
|
4208
|
-
label: `${rule.name}
|
|
4209
|
-
hint: `${rule.description} [${severityBadge}]`
|
|
4758
|
+
label: `${rule.icon ?? ""} ${rule.name}`.trim(),
|
|
4759
|
+
hint: `${rule.hint ?? rule.description} [${severityBadge}]`
|
|
4210
4760
|
};
|
|
4211
4761
|
}
|
|
4212
4762
|
var eslintInstaller = {
|
|
@@ -4267,33 +4817,37 @@ var eslintInstaller = {
|
|
|
4267
4817
|
options: rule.defaultOptions
|
|
4268
4818
|
}));
|
|
4269
4819
|
} else if (installMode === "strict") {
|
|
4270
|
-
configuredRules =
|
|
4820
|
+
configuredRules = ruleRegistry.map((rule) => ({
|
|
4271
4821
|
rule,
|
|
4272
4822
|
severity: rule.defaultSeverity,
|
|
4273
4823
|
options: rule.defaultOptions
|
|
4274
4824
|
}));
|
|
4275
4825
|
} else {
|
|
4276
|
-
|
|
4826
|
+
const staticCat = getCategoryMeta2("static");
|
|
4827
|
+
const semanticCat = getCategoryMeta2("semantic");
|
|
4828
|
+
log(pc.dim(`
|
|
4829
|
+
${staticCat?.icon ?? "\u{1F4CB}"} ${staticCat?.name ?? "Static rules"} (${staticCat?.description ?? "pattern-based, fast"}):`));
|
|
4277
4830
|
const selectedStaticIds = await multiselect({
|
|
4278
4831
|
message: "Select static rules to enable:",
|
|
4279
4832
|
options: staticRules.map(formatRuleOption),
|
|
4280
|
-
initialValues: staticRules.map((r) => r.id)
|
|
4833
|
+
initialValues: staticRules.filter((r) => r.defaultEnabled ?? staticCat?.defaultEnabled ?? true).map((r) => r.id)
|
|
4281
4834
|
});
|
|
4282
4835
|
const includeSemanticRules = await confirm({
|
|
4283
4836
|
message: `Include semantic rules? ${pc.dim(
|
|
4284
|
-
|
|
4837
|
+
`(${semanticCat?.description ?? "LLM-powered analysis"})`
|
|
4285
4838
|
)}`,
|
|
4286
4839
|
initialValue: false
|
|
4287
4840
|
});
|
|
4288
4841
|
let selectedSemanticIds = [];
|
|
4289
4842
|
if (includeSemanticRules) {
|
|
4290
4843
|
log(
|
|
4291
|
-
pc.dim(
|
|
4844
|
+
pc.dim(`
|
|
4845
|
+
${semanticCat?.icon ?? "\u{1F9E0}"} ${semanticCat?.name ?? "Semantic rules"} (${semanticCat?.description ?? "LLM-powered, slower"}):`)
|
|
4292
4846
|
);
|
|
4293
4847
|
selectedSemanticIds = await multiselect({
|
|
4294
4848
|
message: "Select semantic rules:",
|
|
4295
4849
|
options: semanticRules.map(formatRuleOption),
|
|
4296
|
-
initialValues: semanticRules.map((r) => r.id)
|
|
4850
|
+
initialValues: semanticRules.filter((r) => r.defaultEnabled ?? semanticCat?.defaultEnabled ?? false).map((r) => r.id)
|
|
4297
4851
|
});
|
|
4298
4852
|
}
|
|
4299
4853
|
selectedRuleIds = [...selectedStaticIds, ...selectedSemanticIds];
|
|
@@ -4303,7 +4857,7 @@ var eslintInstaller = {
|
|
|
4303
4857
|
});
|
|
4304
4858
|
configuredRules = [];
|
|
4305
4859
|
for (const ruleId of selectedRuleIds) {
|
|
4306
|
-
const rule =
|
|
4860
|
+
const rule = ruleRegistry.find((r) => r.id === ruleId);
|
|
4307
4861
|
if (configureSeverity) {
|
|
4308
4862
|
const severity = await select({
|
|
4309
4863
|
message: `${rule.name} - severity:`,
|
|
@@ -4331,34 +4885,64 @@ var eslintInstaller = {
|
|
|
4331
4885
|
}
|
|
4332
4886
|
}
|
|
4333
4887
|
}
|
|
4888
|
+
const rulesWithOptions = configuredRules.filter(
|
|
4889
|
+
(cr) => cr.rule.optionSchema && cr.rule.optionSchema.fields.length > 0
|
|
4890
|
+
);
|
|
4891
|
+
if (rulesWithOptions.length > 0) {
|
|
4892
|
+
const customizeOptions = await confirm({
|
|
4893
|
+
message: `Customize rule options? ${pc.dim(
|
|
4894
|
+
`(${rulesWithOptions.length} rules have configurable options)`
|
|
4895
|
+
)}`,
|
|
4896
|
+
initialValue: false
|
|
4897
|
+
});
|
|
4898
|
+
if (customizeOptions) {
|
|
4899
|
+
for (const cr of configuredRules) {
|
|
4900
|
+
if (cr.rule.optionSchema && cr.rule.optionSchema.fields.length > 0) {
|
|
4901
|
+
const options = await configureRuleOptions(cr.rule);
|
|
4902
|
+
if (options) {
|
|
4903
|
+
const existingOptions = cr.options && cr.options.length > 0 ? cr.options[0] : {};
|
|
4904
|
+
cr.options = [{ ...existingOptions, ...options }];
|
|
4905
|
+
}
|
|
4906
|
+
}
|
|
4907
|
+
}
|
|
4908
|
+
}
|
|
4909
|
+
}
|
|
4334
4910
|
const errorCount = configuredRules.filter(
|
|
4335
4911
|
(r) => r.severity === "error"
|
|
4336
4912
|
).length;
|
|
4337
4913
|
const warnCount = configuredRules.filter(
|
|
4338
4914
|
(r) => r.severity === "warn"
|
|
4339
4915
|
).length;
|
|
4340
|
-
const hasSemanticDuplicates = configuredRules.some(
|
|
4341
|
-
(cr) => cr.rule.id === "no-semantic-duplicates"
|
|
4342
|
-
);
|
|
4343
4916
|
log("");
|
|
4344
4917
|
note(
|
|
4345
4918
|
configuredRules.map(
|
|
4346
|
-
(cr) => `${cr.severity === "error" ? "\u{1F534}" : "\u{1F7E1}"} ${cr.rule.name} (${cr.severity})`
|
|
4919
|
+
(cr) => `${cr.severity === "error" ? "\u{1F534}" : "\u{1F7E1}"} ${cr.rule.icon ?? ""} ${cr.rule.name} (${cr.severity})`
|
|
4347
4920
|
).join("\n"),
|
|
4348
4921
|
`Selected ${configuredRules.length} rules (${errorCount} errors, ${warnCount} warnings)`
|
|
4349
4922
|
);
|
|
4350
|
-
|
|
4923
|
+
const rulesWithInstructions = configuredRules.filter(
|
|
4924
|
+
(cr) => cr.rule.postInstallInstructions || (cr.rule.requirements?.length ?? 0) > 0
|
|
4925
|
+
);
|
|
4926
|
+
if (rulesWithInstructions.length > 0) {
|
|
4351
4927
|
log("");
|
|
4352
|
-
log(
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4928
|
+
log(pc.bold("\u{1F4CB} Setup Requirements:"));
|
|
4929
|
+
for (const cr of rulesWithInstructions) {
|
|
4930
|
+
if (cr.rule.requirements?.length) {
|
|
4931
|
+
for (const req of cr.rule.requirements) {
|
|
4932
|
+
log(
|
|
4933
|
+
pc.yellow(` \u26A0\uFE0F ${cr.rule.name}: ${req.description}`)
|
|
4934
|
+
);
|
|
4935
|
+
if (req.setupHint) {
|
|
4936
|
+
log(pc.dim(` \u2192 ${req.setupHint}`));
|
|
4937
|
+
}
|
|
4938
|
+
}
|
|
4939
|
+
}
|
|
4940
|
+
if (cr.rule.postInstallInstructions) {
|
|
4941
|
+
log(
|
|
4942
|
+
pc.cyan(` \u2139\uFE0F ${cr.rule.name}: ${cr.rule.postInstallInstructions}`)
|
|
4943
|
+
);
|
|
4944
|
+
}
|
|
4945
|
+
}
|
|
4362
4946
|
}
|
|
4363
4947
|
return { configuredRules };
|
|
4364
4948
|
},
|
|
@@ -4572,7 +5156,7 @@ registerInstaller(nextOverlayInstaller);
|
|
|
4572
5156
|
registerInstaller(viteOverlayInstaller);
|
|
4573
5157
|
|
|
4574
5158
|
// src/commands/install-ui.tsx
|
|
4575
|
-
import { jsx as
|
|
5159
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
4576
5160
|
function limitList(items, max) {
|
|
4577
5161
|
if (items.length <= max) return items;
|
|
4578
5162
|
return [...items.slice(0, max), pc.dim(`\u2026and ${items.length - max} more`)];
|
|
@@ -4692,7 +5276,7 @@ function selectionsToUserChoices(selections, project, eslintRules, injectionPoin
|
|
|
4692
5276
|
// Override severity with user's selection
|
|
4693
5277
|
defaultSeverity: cr.severity,
|
|
4694
5278
|
defaultOptions: cr.options
|
|
4695
|
-
})) :
|
|
5279
|
+
})) : ruleRegistry2
|
|
4696
5280
|
};
|
|
4697
5281
|
} else if (installer.id === "next") {
|
|
4698
5282
|
items.push("next");
|
|
@@ -4737,7 +5321,7 @@ async function installUI(options = {}, executeOptions = {}) {
|
|
|
4737
5321
|
}
|
|
4738
5322
|
const projectPromise = analyze(projectPath);
|
|
4739
5323
|
const { waitUntilExit } = render(
|
|
4740
|
-
/* @__PURE__ */
|
|
5324
|
+
/* @__PURE__ */ jsx8(
|
|
4741
5325
|
InstallApp,
|
|
4742
5326
|
{
|
|
4743
5327
|
projectPromise,
|
|
@@ -4750,7 +5334,7 @@ async function installUI(options = {}, executeOptions = {}) {
|
|
|
4750
5334
|
console.log("\nNo changes selected");
|
|
4751
5335
|
process.exit(0);
|
|
4752
5336
|
}
|
|
4753
|
-
const { createPlan } = await import("./plan-
|
|
5337
|
+
const { createPlan } = await import("./plan-QVR3RBLG.js");
|
|
4754
5338
|
const plan = createPlan(project, choices, { force: options.force });
|
|
4755
5339
|
if (hasUninstalls && uninstallSelections) {
|
|
4756
5340
|
for (const selection of uninstallSelections) {
|
|
@@ -4802,4 +5386,4 @@ ${pc.blue("Running tests with coverage...")}`);
|
|
|
4802
5386
|
export {
|
|
4803
5387
|
installUI
|
|
4804
5388
|
};
|
|
4805
|
-
//# sourceMappingURL=install-ui-
|
|
5389
|
+
//# sourceMappingURL=install-ui-JV4G2CAC.js.map
|