uilint 0.2.22 → 0.2.23
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-PB5DLLVC.js +1000 -0
- package/dist/chunk-PB5DLLVC.js.map +1 -0
- package/dist/index.js +216 -16
- package/dist/index.js.map +1 -1
- package/dist/{install-ui-HTVB5HDB.js → install-ui-TXV7A34M.js} +212 -789
- package/dist/install-ui-TXV7A34M.js.map +1 -0
- package/package.json +3 -3
- package/dist/chunk-FRNXXIEM.js +0 -197
- package/dist/chunk-FRNXXIEM.js.map +0 -1
- package/dist/install-ui-HTVB5HDB.js.map +0 -1
|
@@ -2,13 +2,18 @@
|
|
|
2
2
|
import {
|
|
3
3
|
confirm,
|
|
4
4
|
detectNextAppRouter,
|
|
5
|
+
findEslintConfigFile,
|
|
5
6
|
findNextAppRouterProjects,
|
|
7
|
+
getEslintConfigFilename,
|
|
8
|
+
getUilintEslintConfigInfoFromSource,
|
|
9
|
+
installEslintPlugin,
|
|
6
10
|
log,
|
|
7
11
|
multiselect,
|
|
8
12
|
note,
|
|
9
13
|
pc,
|
|
10
|
-
select
|
|
11
|
-
|
|
14
|
+
select,
|
|
15
|
+
uninstallEslintPlugin
|
|
16
|
+
} from "./chunk-PB5DLLVC.js";
|
|
12
17
|
import {
|
|
13
18
|
GENSTYLEGUIDE_COMMAND_MD,
|
|
14
19
|
detectPackageManager,
|
|
@@ -841,7 +846,7 @@ var nextOverlayInstaller = {
|
|
|
841
846
|
label: app.projectPath.split("/").pop() || app.projectPath,
|
|
842
847
|
path: app.projectPath,
|
|
843
848
|
hint: "App Router",
|
|
844
|
-
isInstalled:
|
|
849
|
+
isInstalled: app.hasUilintOverlay
|
|
845
850
|
}));
|
|
846
851
|
},
|
|
847
852
|
plan(targets, config, project) {
|
|
@@ -1309,9 +1314,9 @@ function InstallApp({
|
|
|
1309
1314
|
}
|
|
1310
1315
|
|
|
1311
1316
|
// src/commands/install/analyze.ts
|
|
1312
|
-
import { existsSync as
|
|
1313
|
-
import { join as
|
|
1314
|
-
import { findWorkspaceRoot
|
|
1317
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
|
|
1318
|
+
import { join as join4 } from "path";
|
|
1319
|
+
import { findWorkspaceRoot } from "uilint-core/node";
|
|
1315
1320
|
|
|
1316
1321
|
// src/utils/vite-detect.ts
|
|
1317
1322
|
import { existsSync as existsSync2, readdirSync, readFileSync as readFileSync2 } from "fs";
|
|
@@ -1554,644 +1559,63 @@ function findPackages(rootDir, options) {
|
|
|
1554
1559
|
});
|
|
1555
1560
|
}
|
|
1556
1561
|
|
|
1557
|
-
// src/
|
|
1558
|
-
|
|
1559
|
-
import { join as join4, relative as relative3, dirname as dirname2 } from "path";
|
|
1560
|
-
import { parseExpression, parseModule as parseModule2, generateCode } from "magicast";
|
|
1561
|
-
import { findWorkspaceRoot } from "uilint-core/node";
|
|
1562
|
-
var CONFIG_EXTENSIONS = [".ts", ".mjs", ".js", ".cjs"];
|
|
1563
|
-
function findEslintConfigFile(projectPath) {
|
|
1564
|
-
for (const ext of CONFIG_EXTENSIONS) {
|
|
1565
|
-
const configPath = join4(projectPath, `eslint.config${ext}`);
|
|
1566
|
-
if (existsSync4(configPath)) {
|
|
1567
|
-
return configPath;
|
|
1568
|
-
}
|
|
1569
|
-
}
|
|
1570
|
-
return null;
|
|
1571
|
-
}
|
|
1572
|
-
function getEslintConfigFilename(configPath) {
|
|
1573
|
-
const parts = configPath.split("/");
|
|
1574
|
-
return parts[parts.length - 1] || "eslint.config.mjs";
|
|
1575
|
-
}
|
|
1576
|
-
function isIdentifier(node, name) {
|
|
1577
|
-
return !!node && node.type === "Identifier" && (name ? node.name === name : typeof node.name === "string");
|
|
1578
|
-
}
|
|
1579
|
-
function isStringLiteral(node) {
|
|
1580
|
-
return !!node && (node.type === "StringLiteral" || node.type === "Literal") && typeof node.value === "string";
|
|
1581
|
-
}
|
|
1582
|
-
function getObjectPropertyValue(obj, keyName) {
|
|
1583
|
-
if (!obj || obj.type !== "ObjectExpression") return null;
|
|
1584
|
-
for (const prop of obj.properties ?? []) {
|
|
1585
|
-
if (!prop) continue;
|
|
1586
|
-
if (prop.type === "ObjectProperty" || prop.type === "Property") {
|
|
1587
|
-
const key = prop.key;
|
|
1588
|
-
const keyMatch = key?.type === "Identifier" && key.name === keyName || isStringLiteral(key) && key.value === keyName;
|
|
1589
|
-
if (keyMatch) return prop.value;
|
|
1590
|
-
}
|
|
1591
|
-
}
|
|
1592
|
-
return null;
|
|
1593
|
-
}
|
|
1594
|
-
function hasSpreadProperties(obj) {
|
|
1595
|
-
if (!obj || obj.type !== "ObjectExpression") return false;
|
|
1596
|
-
return (obj.properties ?? []).some(
|
|
1597
|
-
(p) => p && (p.type === "SpreadElement" || p.type === "SpreadProperty")
|
|
1598
|
-
);
|
|
1599
|
-
}
|
|
1600
|
-
var IGNORED_AST_KEYS = /* @__PURE__ */ new Set([
|
|
1601
|
-
"loc",
|
|
1602
|
-
"start",
|
|
1603
|
-
"end",
|
|
1604
|
-
"extra",
|
|
1605
|
-
"leadingComments",
|
|
1606
|
-
"trailingComments",
|
|
1607
|
-
"innerComments"
|
|
1608
|
-
]);
|
|
1609
|
-
function normalizeAstForCompare(node) {
|
|
1610
|
-
if (node === null) return null;
|
|
1611
|
-
if (node === void 0) return void 0;
|
|
1612
|
-
if (typeof node !== "object") return node;
|
|
1613
|
-
if (Array.isArray(node)) return node.map(normalizeAstForCompare);
|
|
1614
|
-
const out = {};
|
|
1615
|
-
const keys = Object.keys(node).filter((k) => !IGNORED_AST_KEYS.has(k)).sort();
|
|
1616
|
-
for (const k of keys) {
|
|
1617
|
-
if (k.startsWith("$")) continue;
|
|
1618
|
-
out[k] = normalizeAstForCompare(node[k]);
|
|
1619
|
-
}
|
|
1620
|
-
return out;
|
|
1621
|
-
}
|
|
1622
|
-
function astEquivalent(a, b) {
|
|
1623
|
-
try {
|
|
1624
|
-
return JSON.stringify(normalizeAstForCompare(a)) === JSON.stringify(normalizeAstForCompare(b));
|
|
1625
|
-
} catch {
|
|
1626
|
-
return false;
|
|
1627
|
-
}
|
|
1628
|
-
}
|
|
1629
|
-
function collectUilintRuleIdsFromRulesObject(rulesObj) {
|
|
1630
|
-
const ids = /* @__PURE__ */ new Set();
|
|
1631
|
-
if (!rulesObj || rulesObj.type !== "ObjectExpression") return ids;
|
|
1632
|
-
for (const prop of rulesObj.properties ?? []) {
|
|
1633
|
-
if (!prop) continue;
|
|
1634
|
-
if (prop.type !== "ObjectProperty" && prop.type !== "Property") continue;
|
|
1635
|
-
const key = prop.key;
|
|
1636
|
-
if (!isStringLiteral(key)) continue;
|
|
1637
|
-
const val = key.value;
|
|
1638
|
-
if (typeof val !== "string") continue;
|
|
1639
|
-
if (val.startsWith("uilint/")) {
|
|
1640
|
-
ids.add(val.slice("uilint/".length));
|
|
1641
|
-
}
|
|
1642
|
-
}
|
|
1643
|
-
return ids;
|
|
1644
|
-
}
|
|
1645
|
-
function findExportedConfigArrayExpression(mod) {
|
|
1646
|
-
function unwrapExpression2(expr) {
|
|
1647
|
-
let e = expr;
|
|
1648
|
-
while (e) {
|
|
1649
|
-
if (e.type === "TSAsExpression" || e.type === "TSNonNullExpression") {
|
|
1650
|
-
e = e.expression;
|
|
1651
|
-
continue;
|
|
1652
|
-
}
|
|
1653
|
-
if (e.type === "TSSatisfiesExpression") {
|
|
1654
|
-
e = e.expression;
|
|
1655
|
-
continue;
|
|
1656
|
-
}
|
|
1657
|
-
if (e.type === "ParenthesizedExpression") {
|
|
1658
|
-
e = e.expression;
|
|
1659
|
-
continue;
|
|
1660
|
-
}
|
|
1661
|
-
break;
|
|
1662
|
-
}
|
|
1663
|
-
return e;
|
|
1664
|
-
}
|
|
1665
|
-
function resolveTopLevelIdentifierToArrayExpr(program2, name) {
|
|
1666
|
-
if (!program2 || program2.type !== "Program") return null;
|
|
1667
|
-
for (const stmt of program2.body ?? []) {
|
|
1668
|
-
if (stmt?.type !== "VariableDeclaration") continue;
|
|
1669
|
-
for (const decl of stmt.declarations ?? []) {
|
|
1670
|
-
const id = decl?.id;
|
|
1671
|
-
if (!isIdentifier(id, name)) continue;
|
|
1672
|
-
const init = unwrapExpression2(decl?.init);
|
|
1673
|
-
if (!init) return null;
|
|
1674
|
-
if (init.type === "ArrayExpression") return init;
|
|
1675
|
-
if (init.type === "CallExpression" && isIdentifier(init.callee, "defineConfig") && unwrapExpression2(init.arguments?.[0])?.type === "ArrayExpression") {
|
|
1676
|
-
return unwrapExpression2(init.arguments?.[0]);
|
|
1677
|
-
}
|
|
1678
|
-
return null;
|
|
1679
|
-
}
|
|
1680
|
-
}
|
|
1681
|
-
return null;
|
|
1682
|
-
}
|
|
1683
|
-
const program = mod?.$ast;
|
|
1684
|
-
if (program && program.type === "Program") {
|
|
1685
|
-
for (const stmt of program.body ?? []) {
|
|
1686
|
-
if (!stmt || stmt.type !== "ExportDefaultDeclaration") continue;
|
|
1687
|
-
const decl = unwrapExpression2(stmt.declaration);
|
|
1688
|
-
if (!decl) break;
|
|
1689
|
-
if (decl.type === "ArrayExpression") {
|
|
1690
|
-
return { kind: "esm", arrayExpr: decl, program };
|
|
1691
|
-
}
|
|
1692
|
-
if (decl.type === "CallExpression" && isIdentifier(decl.callee, "defineConfig") && unwrapExpression2(decl.arguments?.[0])?.type === "ArrayExpression") {
|
|
1693
|
-
return {
|
|
1694
|
-
kind: "esm",
|
|
1695
|
-
arrayExpr: unwrapExpression2(decl.arguments?.[0]),
|
|
1696
|
-
program
|
|
1697
|
-
};
|
|
1698
|
-
}
|
|
1699
|
-
if (decl.type === "Identifier" && typeof decl.name === "string") {
|
|
1700
|
-
const resolved = resolveTopLevelIdentifierToArrayExpr(
|
|
1701
|
-
program,
|
|
1702
|
-
decl.name
|
|
1703
|
-
);
|
|
1704
|
-
if (resolved) return { kind: "esm", arrayExpr: resolved, program };
|
|
1705
|
-
}
|
|
1706
|
-
break;
|
|
1707
|
-
}
|
|
1708
|
-
}
|
|
1709
|
-
if (!program || program.type !== "Program") return null;
|
|
1710
|
-
for (const stmt of program.body ?? []) {
|
|
1711
|
-
if (!stmt || stmt.type !== "ExpressionStatement") continue;
|
|
1712
|
-
const expr = stmt.expression;
|
|
1713
|
-
if (!expr || expr.type !== "AssignmentExpression") continue;
|
|
1714
|
-
const left = expr.left;
|
|
1715
|
-
const right = expr.right;
|
|
1716
|
-
const isModuleExports = left?.type === "MemberExpression" && isIdentifier(left.object, "module") && isIdentifier(left.property, "exports");
|
|
1717
|
-
if (!isModuleExports) continue;
|
|
1718
|
-
if (right?.type === "ArrayExpression") {
|
|
1719
|
-
return { kind: "cjs", arrayExpr: right, program };
|
|
1720
|
-
}
|
|
1721
|
-
if (right?.type === "CallExpression" && isIdentifier(right.callee, "defineConfig") && right.arguments?.[0]?.type === "ArrayExpression") {
|
|
1722
|
-
return { kind: "cjs", arrayExpr: right.arguments[0], program };
|
|
1723
|
-
}
|
|
1724
|
-
if (right?.type === "Identifier" && typeof right.name === "string") {
|
|
1725
|
-
const resolved = resolveTopLevelIdentifierToArrayExpr(
|
|
1726
|
-
program,
|
|
1727
|
-
right.name
|
|
1728
|
-
);
|
|
1729
|
-
if (resolved) return { kind: "cjs", arrayExpr: resolved, program };
|
|
1730
|
-
}
|
|
1731
|
-
}
|
|
1732
|
-
return null;
|
|
1733
|
-
}
|
|
1734
|
-
function collectConfiguredUilintRuleIdsFromConfigArray(arrayExpr) {
|
|
1735
|
-
const ids = /* @__PURE__ */ new Set();
|
|
1736
|
-
if (!arrayExpr || arrayExpr.type !== "ArrayExpression") return ids;
|
|
1737
|
-
for (const el of arrayExpr.elements ?? []) {
|
|
1738
|
-
if (!el || el.type !== "ObjectExpression") continue;
|
|
1739
|
-
const rules = getObjectPropertyValue(el, "rules");
|
|
1740
|
-
for (const id of collectUilintRuleIdsFromRulesObject(rules)) ids.add(id);
|
|
1741
|
-
}
|
|
1742
|
-
return ids;
|
|
1743
|
-
}
|
|
1744
|
-
function findExistingUilintRulesObject(arrayExpr) {
|
|
1745
|
-
if (!arrayExpr || arrayExpr.type !== "ArrayExpression") {
|
|
1746
|
-
return { configObj: null, rulesObj: null, safeToMutate: false };
|
|
1747
|
-
}
|
|
1748
|
-
for (const el of arrayExpr.elements ?? []) {
|
|
1749
|
-
if (!el || el.type !== "ObjectExpression") continue;
|
|
1750
|
-
const plugins = getObjectPropertyValue(el, "plugins");
|
|
1751
|
-
const rules = getObjectPropertyValue(el, "rules");
|
|
1752
|
-
const hasUilintPlugin = plugins?.type === "ObjectExpression" && getObjectPropertyValue(plugins, "uilint") !== null;
|
|
1753
|
-
const uilintIds = collectUilintRuleIdsFromRulesObject(rules);
|
|
1754
|
-
const hasUilintRules = uilintIds.size > 0;
|
|
1755
|
-
if (!hasUilintPlugin && !hasUilintRules) continue;
|
|
1756
|
-
const safe = rules?.type === "ObjectExpression" && !hasSpreadProperties(rules);
|
|
1757
|
-
return { configObj: el, rulesObj: rules, safeToMutate: safe };
|
|
1758
|
-
}
|
|
1759
|
-
return { configObj: null, rulesObj: null, safeToMutate: false };
|
|
1760
|
-
}
|
|
1761
|
-
function collectTopLevelBindings(program) {
|
|
1762
|
-
const names = /* @__PURE__ */ new Set();
|
|
1763
|
-
if (!program || program.type !== "Program") return names;
|
|
1764
|
-
for (const stmt of program.body ?? []) {
|
|
1765
|
-
if (stmt?.type === "VariableDeclaration") {
|
|
1766
|
-
for (const decl of stmt.declarations ?? []) {
|
|
1767
|
-
const id = decl?.id;
|
|
1768
|
-
if (id?.type === "Identifier" && typeof id.name === "string") {
|
|
1769
|
-
names.add(id.name);
|
|
1770
|
-
}
|
|
1771
|
-
}
|
|
1772
|
-
} else if (stmt?.type === "FunctionDeclaration") {
|
|
1773
|
-
if (stmt.id?.type === "Identifier" && typeof stmt.id.name === "string") {
|
|
1774
|
-
names.add(stmt.id.name);
|
|
1775
|
-
}
|
|
1776
|
-
}
|
|
1777
|
-
}
|
|
1778
|
-
return names;
|
|
1779
|
-
}
|
|
1780
|
-
function chooseUniqueIdentifier(base, used) {
|
|
1781
|
-
if (!used.has(base)) return base;
|
|
1782
|
-
let i = 2;
|
|
1783
|
-
while (used.has(`${base}${i}`)) i++;
|
|
1784
|
-
return `${base}${i}`;
|
|
1785
|
-
}
|
|
1786
|
-
function addLocalRuleImportsAst(mod, selectedRules, configPath, rulesRoot, fileExtension = ".js") {
|
|
1787
|
-
const importNames = /* @__PURE__ */ new Map();
|
|
1788
|
-
let changed = false;
|
|
1789
|
-
const configDir = dirname2(configPath);
|
|
1790
|
-
const rulesDir = join4(rulesRoot, ".uilint", "rules");
|
|
1791
|
-
const relativeRulesPath = relative3(configDir, rulesDir).replace(/\\/g, "/");
|
|
1792
|
-
const normalizedRulesPath = relativeRulesPath.startsWith("./") || relativeRulesPath.startsWith("../") ? relativeRulesPath : `./${relativeRulesPath}`;
|
|
1793
|
-
const used = collectTopLevelBindings(mod.$ast);
|
|
1794
|
-
for (const rule of selectedRules) {
|
|
1795
|
-
const importName = chooseUniqueIdentifier(
|
|
1796
|
-
`${rule.id.replace(/-([a-z])/g, (_, c) => c.toUpperCase()).replace(/^./, (c) => c.toUpperCase())}Rule`,
|
|
1797
|
-
used
|
|
1798
|
-
);
|
|
1799
|
-
importNames.set(rule.id, importName);
|
|
1800
|
-
used.add(importName);
|
|
1801
|
-
const rulePath = `${normalizedRulesPath}/${rule.id}${fileExtension}`;
|
|
1802
|
-
mod.imports.$add({
|
|
1803
|
-
imported: "default",
|
|
1804
|
-
local: importName,
|
|
1805
|
-
from: rulePath
|
|
1806
|
-
});
|
|
1807
|
-
changed = true;
|
|
1808
|
-
}
|
|
1809
|
-
return { importNames, changed };
|
|
1810
|
-
}
|
|
1811
|
-
function addLocalRuleRequiresAst(program, selectedRules, configPath, rulesRoot, fileExtension = ".js") {
|
|
1812
|
-
const importNames = /* @__PURE__ */ new Map();
|
|
1813
|
-
let changed = false;
|
|
1814
|
-
if (!program || program.type !== "Program") {
|
|
1815
|
-
return { importNames, changed };
|
|
1816
|
-
}
|
|
1817
|
-
const configDir = dirname2(configPath);
|
|
1818
|
-
const rulesDir = join4(rulesRoot, ".uilint", "rules");
|
|
1819
|
-
const relativeRulesPath = relative3(configDir, rulesDir).replace(/\\/g, "/");
|
|
1820
|
-
const normalizedRulesPath = relativeRulesPath.startsWith("./") || relativeRulesPath.startsWith("../") ? relativeRulesPath : `./${relativeRulesPath}`;
|
|
1821
|
-
const used = collectTopLevelBindings(program);
|
|
1822
|
-
for (const rule of selectedRules) {
|
|
1823
|
-
const importName = chooseUniqueIdentifier(
|
|
1824
|
-
`${rule.id.replace(/-([a-z])/g, (_, c) => c.toUpperCase()).replace(/^./, (c) => c.toUpperCase())}Rule`,
|
|
1825
|
-
used
|
|
1826
|
-
);
|
|
1827
|
-
importNames.set(rule.id, importName);
|
|
1828
|
-
used.add(importName);
|
|
1829
|
-
const rulePath = `${normalizedRulesPath}/${rule.id}${fileExtension}`;
|
|
1830
|
-
const stmtMod = parseModule2(
|
|
1831
|
-
`const ${importName} = require("${rulePath}");`
|
|
1832
|
-
);
|
|
1833
|
-
const stmt = stmtMod.$ast.body?.[0];
|
|
1834
|
-
if (stmt) {
|
|
1835
|
-
let insertAt = 0;
|
|
1836
|
-
const first = program.body?.[0];
|
|
1837
|
-
if (first?.type === "ExpressionStatement" && first.expression?.type === "StringLiteral" && first.expression.value === "use strict") {
|
|
1838
|
-
insertAt = 1;
|
|
1839
|
-
}
|
|
1840
|
-
program.body.splice(insertAt, 0, stmt);
|
|
1841
|
-
changed = true;
|
|
1842
|
-
}
|
|
1843
|
-
}
|
|
1844
|
-
return { importNames, changed };
|
|
1845
|
-
}
|
|
1846
|
-
function appendUilintConfigBlockToArray(arrayExpr, selectedRules, ruleImportNames) {
|
|
1847
|
-
const pluginRulesCode = Array.from(ruleImportNames.entries()).map(([ruleId, importName]) => ` "${ruleId}": ${importName},`).join("\n");
|
|
1848
|
-
const rulesPropsCode = selectedRules.map((r) => {
|
|
1849
|
-
const ruleKey = `uilint/${r.id}`;
|
|
1850
|
-
const valueCode = r.defaultOptions && r.defaultOptions.length > 0 ? `["${r.defaultSeverity}", ...${JSON.stringify(
|
|
1851
|
-
r.defaultOptions,
|
|
1852
|
-
null,
|
|
1853
|
-
2
|
|
1854
|
-
)}]` : `"${r.defaultSeverity}"`;
|
|
1855
|
-
return ` "${ruleKey}": ${valueCode},`;
|
|
1856
|
-
}).join("\n");
|
|
1857
|
-
const blockCode = `{
|
|
1858
|
-
files: [
|
|
1859
|
-
"src/**/*.{js,jsx,ts,tsx}",
|
|
1860
|
-
"app/**/*.{js,jsx,ts,tsx}",
|
|
1861
|
-
"pages/**/*.{js,jsx,ts,tsx}",
|
|
1862
|
-
],
|
|
1863
|
-
plugins: {
|
|
1864
|
-
uilint: {
|
|
1865
|
-
rules: {
|
|
1866
|
-
${pluginRulesCode}
|
|
1867
|
-
},
|
|
1868
|
-
},
|
|
1869
|
-
},
|
|
1870
|
-
rules: {
|
|
1871
|
-
${rulesPropsCode}
|
|
1872
|
-
},
|
|
1873
|
-
}`;
|
|
1874
|
-
const objExpr = parseExpression(blockCode).$ast;
|
|
1875
|
-
arrayExpr.elements.push(objExpr);
|
|
1876
|
-
}
|
|
1877
|
-
function getUilintEslintConfigInfoFromSourceAst(source) {
|
|
1562
|
+
// src/commands/install/analyze.ts
|
|
1563
|
+
function safeParseJson(filePath) {
|
|
1878
1564
|
try {
|
|
1879
|
-
const
|
|
1880
|
-
|
|
1881
|
-
if (!found) {
|
|
1882
|
-
return {
|
|
1883
|
-
error: "Could not locate an exported ESLint flat config array (expected `export default [...]`, `export default defineConfig([...])`, `module.exports = [...]`, or `module.exports = defineConfig([...])`)."
|
|
1884
|
-
};
|
|
1885
|
-
}
|
|
1886
|
-
const configuredRuleIds = collectConfiguredUilintRuleIdsFromConfigArray(
|
|
1887
|
-
found.arrayExpr
|
|
1888
|
-
);
|
|
1889
|
-
const existingUilint = findExistingUilintRulesObject(found.arrayExpr);
|
|
1890
|
-
const configured = configuredRuleIds.size > 0 || existingUilint.configObj !== null;
|
|
1891
|
-
return {
|
|
1892
|
-
info: { configuredRuleIds, configured },
|
|
1893
|
-
mod,
|
|
1894
|
-
arrayExpr: found.arrayExpr,
|
|
1895
|
-
kind: found.kind
|
|
1896
|
-
};
|
|
1565
|
+
const content = readFileSync4(filePath, "utf-8");
|
|
1566
|
+
return JSON.parse(content);
|
|
1897
1567
|
} catch {
|
|
1898
|
-
return
|
|
1899
|
-
error: "Unable to parse ESLint config as JavaScript. Please update it manually or simplify the config so it can be safely auto-modified."
|
|
1900
|
-
};
|
|
1901
|
-
}
|
|
1902
|
-
}
|
|
1903
|
-
function getUilintEslintConfigInfoFromSource(source) {
|
|
1904
|
-
const ast = getUilintEslintConfigInfoFromSourceAst(source);
|
|
1905
|
-
if ("error" in ast) {
|
|
1906
|
-
const configuredRuleIds = extractConfiguredUilintRuleIds(source);
|
|
1907
|
-
return {
|
|
1908
|
-
configuredRuleIds,
|
|
1909
|
-
configured: configuredRuleIds.size > 0
|
|
1910
|
-
};
|
|
1911
|
-
}
|
|
1912
|
-
return ast.info;
|
|
1913
|
-
}
|
|
1914
|
-
function extractConfiguredUilintRuleIds(source) {
|
|
1915
|
-
const ids = /* @__PURE__ */ new Set();
|
|
1916
|
-
const re = /["']uilint\/([^"']+)["']\s*:/g;
|
|
1917
|
-
for (const m of source.matchAll(re)) {
|
|
1918
|
-
if (m[1]) ids.add(m[1]);
|
|
1919
|
-
}
|
|
1920
|
-
return ids;
|
|
1921
|
-
}
|
|
1922
|
-
function getMissingSelectedRules(selectedRules, configuredIds) {
|
|
1923
|
-
return selectedRules.filter((r) => !configuredIds.has(r.id));
|
|
1924
|
-
}
|
|
1925
|
-
function buildDesiredRuleValueExpression(rule) {
|
|
1926
|
-
if (rule.defaultOptions && rule.defaultOptions.length > 0) {
|
|
1927
|
-
return `["${rule.defaultSeverity}", ...${JSON.stringify(
|
|
1928
|
-
rule.defaultOptions,
|
|
1929
|
-
null,
|
|
1930
|
-
2
|
|
1931
|
-
)}]`;
|
|
1932
|
-
}
|
|
1933
|
-
return `"${rule.defaultSeverity}"`;
|
|
1934
|
-
}
|
|
1935
|
-
function collectUilintRuleValueNodesFromConfigArray(arrayExpr) {
|
|
1936
|
-
const out = /* @__PURE__ */ new Map();
|
|
1937
|
-
if (!arrayExpr || arrayExpr.type !== "ArrayExpression") return out;
|
|
1938
|
-
for (const el of arrayExpr.elements ?? []) {
|
|
1939
|
-
if (!el || el.type !== "ObjectExpression") continue;
|
|
1940
|
-
const rules = getObjectPropertyValue(el, "rules");
|
|
1941
|
-
if (!rules || rules.type !== "ObjectExpression") continue;
|
|
1942
|
-
for (const prop of rules.properties ?? []) {
|
|
1943
|
-
if (!prop) continue;
|
|
1944
|
-
if (prop.type !== "ObjectProperty" && prop.type !== "Property") continue;
|
|
1945
|
-
const key = prop.key;
|
|
1946
|
-
if (!isStringLiteral(key)) continue;
|
|
1947
|
-
const k = key.value;
|
|
1948
|
-
if (typeof k !== "string" || !k.startsWith("uilint/")) continue;
|
|
1949
|
-
const id = k.slice("uilint/".length);
|
|
1950
|
-
if (!out.has(id)) out.set(id, prop.value);
|
|
1951
|
-
}
|
|
1952
|
-
}
|
|
1953
|
-
return out;
|
|
1954
|
-
}
|
|
1955
|
-
function getRulesNeedingUpdate(selectedRules, configuredIds, arrayExpr) {
|
|
1956
|
-
const existingVals = collectUilintRuleValueNodesFromConfigArray(arrayExpr);
|
|
1957
|
-
return selectedRules.filter((r) => {
|
|
1958
|
-
if (!configuredIds.has(r.id)) return false;
|
|
1959
|
-
const existing = existingVals.get(r.id);
|
|
1960
|
-
if (!existing) return true;
|
|
1961
|
-
const desiredExpr = buildDesiredRuleValueExpression(r);
|
|
1962
|
-
const desiredAst = parseExpression(desiredExpr).$ast;
|
|
1963
|
-
return !astEquivalent(existing, desiredAst);
|
|
1964
|
-
});
|
|
1965
|
-
}
|
|
1966
|
-
async function installEslintPlugin(opts) {
|
|
1967
|
-
const configPath = findEslintConfigFile(opts.projectPath);
|
|
1968
|
-
if (!configPath) {
|
|
1969
|
-
return {
|
|
1970
|
-
configFile: null,
|
|
1971
|
-
modified: false,
|
|
1972
|
-
missingRuleIds: [],
|
|
1973
|
-
configured: false
|
|
1974
|
-
};
|
|
1975
|
-
}
|
|
1976
|
-
const configFilename = getEslintConfigFilename(configPath);
|
|
1977
|
-
const original = readFileSync4(configPath, "utf-8");
|
|
1978
|
-
const isCommonJS = configPath.endsWith(".cjs");
|
|
1979
|
-
const ast = getUilintEslintConfigInfoFromSourceAst(original);
|
|
1980
|
-
if ("error" in ast) {
|
|
1981
|
-
return {
|
|
1982
|
-
configFile: configFilename,
|
|
1983
|
-
modified: false,
|
|
1984
|
-
missingRuleIds: [],
|
|
1985
|
-
configured: false,
|
|
1986
|
-
error: ast.error
|
|
1987
|
-
};
|
|
1988
|
-
}
|
|
1989
|
-
const { info, mod, arrayExpr, kind } = ast;
|
|
1990
|
-
const configuredIds = info.configuredRuleIds;
|
|
1991
|
-
const missingRules = getMissingSelectedRules(
|
|
1992
|
-
opts.selectedRules,
|
|
1993
|
-
configuredIds
|
|
1994
|
-
);
|
|
1995
|
-
const rulesToUpdate = getRulesNeedingUpdate(
|
|
1996
|
-
opts.selectedRules,
|
|
1997
|
-
configuredIds,
|
|
1998
|
-
arrayExpr
|
|
1999
|
-
);
|
|
2000
|
-
let rulesToApply = [];
|
|
2001
|
-
if (!info.configured) {
|
|
2002
|
-
rulesToApply = opts.selectedRules;
|
|
2003
|
-
} else {
|
|
2004
|
-
rulesToApply = [...missingRules, ...rulesToUpdate];
|
|
2005
|
-
if (missingRules.length > 0 && !opts.force) {
|
|
2006
|
-
const ok = await opts.confirmAddMissingRules?.(
|
|
2007
|
-
configFilename,
|
|
2008
|
-
missingRules
|
|
2009
|
-
);
|
|
2010
|
-
if (!ok) {
|
|
2011
|
-
return {
|
|
2012
|
-
configFile: configFilename,
|
|
2013
|
-
modified: false,
|
|
2014
|
-
missingRuleIds: missingRules.map((r) => r.id),
|
|
2015
|
-
configured: true
|
|
2016
|
-
};
|
|
2017
|
-
}
|
|
2018
|
-
}
|
|
2019
|
-
}
|
|
2020
|
-
if (rulesToApply.length === 0) {
|
|
2021
|
-
return {
|
|
2022
|
-
configFile: configFilename,
|
|
2023
|
-
modified: false,
|
|
2024
|
-
missingRuleIds: missingRules.map((r) => r.id),
|
|
2025
|
-
configured: info.configured
|
|
2026
|
-
};
|
|
2027
|
-
}
|
|
2028
|
-
let modifiedAst = false;
|
|
2029
|
-
const localRulesDir = join4(opts.projectPath, ".uilint", "rules");
|
|
2030
|
-
const workspaceRoot = findWorkspaceRoot(opts.projectPath);
|
|
2031
|
-
const workspaceRulesDir = join4(workspaceRoot, ".uilint", "rules");
|
|
2032
|
-
const rulesRoot = existsSync4(localRulesDir) ? opts.projectPath : workspaceRoot;
|
|
2033
|
-
const isTypeScriptConfig = configPath.endsWith(".ts");
|
|
2034
|
-
let fileExtension = isTypeScriptConfig ? "" : ".js";
|
|
2035
|
-
let ruleImportNames;
|
|
2036
|
-
if (kind === "esm") {
|
|
2037
|
-
const result = addLocalRuleImportsAst(
|
|
2038
|
-
mod,
|
|
2039
|
-
rulesToApply,
|
|
2040
|
-
configPath,
|
|
2041
|
-
rulesRoot,
|
|
2042
|
-
fileExtension
|
|
2043
|
-
);
|
|
2044
|
-
ruleImportNames = result.importNames;
|
|
2045
|
-
if (result.changed) modifiedAst = true;
|
|
2046
|
-
} else {
|
|
2047
|
-
const result = addLocalRuleRequiresAst(
|
|
2048
|
-
mod.$ast,
|
|
2049
|
-
rulesToApply,
|
|
2050
|
-
configPath,
|
|
2051
|
-
rulesRoot,
|
|
2052
|
-
fileExtension
|
|
2053
|
-
);
|
|
2054
|
-
ruleImportNames = result.importNames;
|
|
2055
|
-
if (result.changed) modifiedAst = true;
|
|
2056
|
-
}
|
|
2057
|
-
if (ruleImportNames && ruleImportNames.size > 0) {
|
|
2058
|
-
appendUilintConfigBlockToArray(arrayExpr, rulesToApply, ruleImportNames);
|
|
2059
|
-
modifiedAst = true;
|
|
2060
|
-
}
|
|
2061
|
-
if (!info.configured) {
|
|
2062
|
-
if (kind === "esm") {
|
|
2063
|
-
mod.imports.$add({
|
|
2064
|
-
imported: "createRule",
|
|
2065
|
-
local: "createRule",
|
|
2066
|
-
from: "uilint-eslint"
|
|
2067
|
-
});
|
|
2068
|
-
modifiedAst = true;
|
|
2069
|
-
} else {
|
|
2070
|
-
const stmtMod = parseModule2(
|
|
2071
|
-
`const { createRule } = require("uilint-eslint");`
|
|
2072
|
-
);
|
|
2073
|
-
const stmt = stmtMod.$ast.body?.[0];
|
|
2074
|
-
if (stmt) {
|
|
2075
|
-
let insertAt = 0;
|
|
2076
|
-
const first = mod.$ast.body?.[0];
|
|
2077
|
-
if (first?.type === "ExpressionStatement" && first.expression?.type === "StringLiteral" && first.expression.value === "use strict") {
|
|
2078
|
-
insertAt = 1;
|
|
2079
|
-
}
|
|
2080
|
-
mod.$ast.body.splice(insertAt, 0, stmt);
|
|
2081
|
-
modifiedAst = true;
|
|
2082
|
-
}
|
|
2083
|
-
}
|
|
2084
|
-
}
|
|
2085
|
-
const updated = modifiedAst ? generateCode(mod).code : original;
|
|
2086
|
-
if (updated !== original) {
|
|
2087
|
-
writeFileSync(configPath, updated, "utf-8");
|
|
2088
|
-
return {
|
|
2089
|
-
configFile: configFilename,
|
|
2090
|
-
modified: true,
|
|
2091
|
-
missingRuleIds: missingRules.map((r) => r.id),
|
|
2092
|
-
configured: getUilintEslintConfigInfoFromSource(updated).configured
|
|
2093
|
-
};
|
|
1568
|
+
return void 0;
|
|
2094
1569
|
}
|
|
2095
|
-
return {
|
|
2096
|
-
configFile: configFilename,
|
|
2097
|
-
modified: false,
|
|
2098
|
-
missingRuleIds: missingRules.map((r) => r.id),
|
|
2099
|
-
configured: getUilintEslintConfigInfoFromSource(updated).configured
|
|
2100
|
-
};
|
|
2101
1570
|
}
|
|
2102
|
-
|
|
2103
|
-
const
|
|
2104
|
-
const
|
|
2105
|
-
if (!
|
|
2106
|
-
|
|
2107
|
-
success: true,
|
|
2108
|
-
// Nothing to uninstall
|
|
2109
|
-
modifiedFiles: []
|
|
2110
|
-
};
|
|
2111
|
-
}
|
|
2112
|
-
try {
|
|
2113
|
-
const original = readFileSync4(configPath, "utf-8");
|
|
2114
|
-
let updated = original.replace(
|
|
2115
|
-
/^import\s+\{[^}]*\}\s+from\s+["'][^"']*\.uilint\/rules[^"']*["'];?\s*$/gm,
|
|
2116
|
-
""
|
|
2117
|
-
);
|
|
2118
|
-
updated = updated.replace(
|
|
2119
|
-
/^import\s+\w+\s+from\s+["'][^"']*\.uilint\/rules[^"']*["'];?\s*$/gm,
|
|
2120
|
-
""
|
|
2121
|
-
);
|
|
2122
|
-
updated = updated.replace(
|
|
2123
|
-
/^import\s+\{[^}]*\}\s+from\s+["']uilint-eslint["'];?\s*$/gm,
|
|
2124
|
-
""
|
|
2125
|
-
);
|
|
2126
|
-
updated = updated.replace(
|
|
2127
|
-
/^const\s+\{[^}]*createRule[^}]*\}\s*=\s*require\s*\(\s*["']uilint-eslint["']\s*\)\s*;?\s*$/gm,
|
|
2128
|
-
""
|
|
2129
|
-
);
|
|
2130
|
-
updated = updated.replace(
|
|
2131
|
-
/["']uilint\/[^"']+["']\s*:\s*["'][^"']+["']\s*,?\s*/g,
|
|
2132
|
-
""
|
|
2133
|
-
);
|
|
2134
|
-
updated = updated.replace(
|
|
2135
|
-
/["']uilint\/[^"']+["']\s*:\s*\[[^\]]*\]\s*,?\s*/g,
|
|
2136
|
-
""
|
|
2137
|
-
);
|
|
2138
|
-
updated = updated.replace(
|
|
2139
|
-
/\{\s*plugins:\s*\{\s*uilint:\s*\{[^}]*\}[^}]*\}[^}]*rules:\s*\{[^}]*\}[^}]*\}\s*,?\s*/gs,
|
|
2140
|
-
""
|
|
2141
|
-
);
|
|
2142
|
-
updated = updated.replace(/\n{3,}/g, "\n\n");
|
|
2143
|
-
if (updated !== original) {
|
|
2144
|
-
writeFileSync(configPath, updated, "utf-8");
|
|
2145
|
-
return {
|
|
2146
|
-
success: true,
|
|
2147
|
-
modifiedFiles: [configPath]
|
|
2148
|
-
};
|
|
2149
|
-
}
|
|
2150
|
-
return {
|
|
2151
|
-
success: true,
|
|
2152
|
-
modifiedFiles: []
|
|
2153
|
-
};
|
|
2154
|
-
} catch (error) {
|
|
2155
|
-
return {
|
|
2156
|
-
success: false,
|
|
2157
|
-
error: error instanceof Error ? error.message : String(error)
|
|
2158
|
-
};
|
|
2159
|
-
}
|
|
1571
|
+
function hasUilintOverlayInstalled(projectPath) {
|
|
1572
|
+
const pkgPath = join4(projectPath, "package.json");
|
|
1573
|
+
const pkg = safeParseJson(pkgPath);
|
|
1574
|
+
if (!pkg) return false;
|
|
1575
|
+
return !!(pkg.dependencies?.["uilint-react"] || pkg.devDependencies?.["uilint-react"]);
|
|
2160
1576
|
}
|
|
2161
|
-
|
|
2162
|
-
// src/commands/install/analyze.ts
|
|
2163
1577
|
async function analyze(projectPath = process.cwd()) {
|
|
2164
|
-
const workspaceRoot =
|
|
1578
|
+
const workspaceRoot = findWorkspaceRoot(projectPath);
|
|
2165
1579
|
const packageManager = detectPackageManager(projectPath);
|
|
2166
|
-
const cursorDir =
|
|
2167
|
-
const cursorDirExists =
|
|
2168
|
-
const styleguidePath =
|
|
2169
|
-
const styleguideExists =
|
|
2170
|
-
const commandsDir =
|
|
2171
|
-
const genstyleguideExists =
|
|
1580
|
+
const cursorDir = join4(projectPath, ".cursor");
|
|
1581
|
+
const cursorDirExists = existsSync4(cursorDir);
|
|
1582
|
+
const styleguidePath = join4(projectPath, ".uilint", "styleguide.md");
|
|
1583
|
+
const styleguideExists = existsSync4(styleguidePath);
|
|
1584
|
+
const commandsDir = join4(cursorDir, "commands");
|
|
1585
|
+
const genstyleguideExists = existsSync4(join4(commandsDir, "genstyleguide.md"));
|
|
2172
1586
|
const nextApps = [];
|
|
2173
1587
|
const directDetection = detectNextAppRouter(projectPath);
|
|
2174
1588
|
if (directDetection) {
|
|
2175
|
-
nextApps.push({
|
|
1589
|
+
nextApps.push({
|
|
1590
|
+
projectPath,
|
|
1591
|
+
detection: directDetection,
|
|
1592
|
+
hasUilintOverlay: hasUilintOverlayInstalled(projectPath)
|
|
1593
|
+
});
|
|
2176
1594
|
} else {
|
|
2177
1595
|
const matches = findNextAppRouterProjects(workspaceRoot, { maxDepth: 5 });
|
|
2178
1596
|
for (const match of matches) {
|
|
2179
1597
|
nextApps.push({
|
|
2180
1598
|
projectPath: match.projectPath,
|
|
2181
|
-
detection: match.detection
|
|
1599
|
+
detection: match.detection,
|
|
1600
|
+
hasUilintOverlay: hasUilintOverlayInstalled(match.projectPath)
|
|
2182
1601
|
});
|
|
2183
1602
|
}
|
|
2184
1603
|
}
|
|
2185
1604
|
const viteApps = [];
|
|
2186
1605
|
const directVite = detectViteReact(projectPath);
|
|
2187
1606
|
if (directVite) {
|
|
2188
|
-
viteApps.push({
|
|
1607
|
+
viteApps.push({
|
|
1608
|
+
projectPath,
|
|
1609
|
+
detection: directVite,
|
|
1610
|
+
hasUilintOverlay: hasUilintOverlayInstalled(projectPath)
|
|
1611
|
+
});
|
|
2189
1612
|
} else {
|
|
2190
1613
|
const matches = findViteReactProjects(workspaceRoot, { maxDepth: 5 });
|
|
2191
1614
|
for (const match of matches) {
|
|
2192
1615
|
viteApps.push({
|
|
2193
1616
|
projectPath: match.projectPath,
|
|
2194
|
-
detection: match.detection
|
|
1617
|
+
detection: match.detection,
|
|
1618
|
+
hasUilintOverlay: hasUilintOverlayInstalled(match.projectPath)
|
|
2195
1619
|
});
|
|
2196
1620
|
}
|
|
2197
1621
|
}
|
|
@@ -2204,7 +1628,7 @@ async function analyze(projectPath = process.cwd()) {
|
|
|
2204
1628
|
if (eslintConfigPath) {
|
|
2205
1629
|
eslintConfigFilename = getEslintConfigFilename(eslintConfigPath);
|
|
2206
1630
|
try {
|
|
2207
|
-
const source =
|
|
1631
|
+
const source = readFileSync4(eslintConfigPath, "utf-8");
|
|
2208
1632
|
const info = getUilintEslintConfigInfoFromSource(source);
|
|
2209
1633
|
hasRules = info.configuredRuleIds.size > 0;
|
|
2210
1634
|
configuredRuleIds = Array.from(info.configuredRuleIds);
|
|
@@ -2242,50 +1666,50 @@ async function analyze(projectPath = process.cwd()) {
|
|
|
2242
1666
|
|
|
2243
1667
|
// src/commands/install/execute.ts
|
|
2244
1668
|
import {
|
|
2245
|
-
existsSync as
|
|
1669
|
+
existsSync as existsSync10,
|
|
2246
1670
|
mkdirSync,
|
|
2247
|
-
writeFileSync as
|
|
2248
|
-
readFileSync as
|
|
1671
|
+
writeFileSync as writeFileSync4,
|
|
1672
|
+
readFileSync as readFileSync8,
|
|
2249
1673
|
unlinkSync,
|
|
2250
1674
|
chmodSync,
|
|
2251
1675
|
rmSync
|
|
2252
1676
|
} from "fs";
|
|
2253
|
-
import { dirname as
|
|
1677
|
+
import { dirname as dirname4 } from "path";
|
|
2254
1678
|
|
|
2255
1679
|
// src/utils/react-inject.ts
|
|
2256
|
-
import { existsSync as
|
|
2257
|
-
import { join as
|
|
2258
|
-
import { parseModule as
|
|
1680
|
+
import { existsSync as existsSync5, readFileSync as readFileSync5, writeFileSync } from "fs";
|
|
1681
|
+
import { join as join5, relative as relative3 } from "path";
|
|
1682
|
+
import { parseModule as parseModule2, generateCode } from "magicast";
|
|
2259
1683
|
function getDefaultCandidates(projectPath, appRoot) {
|
|
2260
1684
|
const viteMainCandidates = [
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
1685
|
+
join5(appRoot, "main.tsx"),
|
|
1686
|
+
join5(appRoot, "main.jsx"),
|
|
1687
|
+
join5(appRoot, "main.ts"),
|
|
1688
|
+
join5(appRoot, "main.js")
|
|
2265
1689
|
];
|
|
2266
1690
|
const existingViteMain = viteMainCandidates.filter(
|
|
2267
|
-
(rel) =>
|
|
1691
|
+
(rel) => existsSync5(join5(projectPath, rel))
|
|
2268
1692
|
);
|
|
2269
1693
|
if (existingViteMain.length > 0) return existingViteMain;
|
|
2270
|
-
const viteAppCandidates = [
|
|
1694
|
+
const viteAppCandidates = [join5(appRoot, "App.tsx"), join5(appRoot, "App.jsx")];
|
|
2271
1695
|
const existingViteApp = viteAppCandidates.filter(
|
|
2272
|
-
(rel) =>
|
|
1696
|
+
(rel) => existsSync5(join5(projectPath, rel))
|
|
2273
1697
|
);
|
|
2274
1698
|
if (existingViteApp.length > 0) return existingViteApp;
|
|
2275
1699
|
const layoutCandidates = [
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
1700
|
+
join5(appRoot, "layout.tsx"),
|
|
1701
|
+
join5(appRoot, "layout.jsx"),
|
|
1702
|
+
join5(appRoot, "layout.ts"),
|
|
1703
|
+
join5(appRoot, "layout.js")
|
|
2280
1704
|
];
|
|
2281
1705
|
const existingLayouts = layoutCandidates.filter(
|
|
2282
|
-
(rel) =>
|
|
1706
|
+
(rel) => existsSync5(join5(projectPath, rel))
|
|
2283
1707
|
);
|
|
2284
1708
|
if (existingLayouts.length > 0) {
|
|
2285
1709
|
return existingLayouts;
|
|
2286
1710
|
}
|
|
2287
|
-
const pageCandidates = [
|
|
2288
|
-
return pageCandidates.filter((rel) =>
|
|
1711
|
+
const pageCandidates = [join5(appRoot, "page.tsx"), join5(appRoot, "page.jsx")];
|
|
1712
|
+
return pageCandidates.filter((rel) => existsSync5(join5(projectPath, rel)));
|
|
2289
1713
|
}
|
|
2290
1714
|
function isUseClientDirective(stmt) {
|
|
2291
1715
|
return stmt?.type === "ExpressionStatement" && stmt.expression?.type === "StringLiteral" && stmt.expression.value === "use client";
|
|
@@ -2319,12 +1743,12 @@ function ensureNamedImport(program, from, name) {
|
|
|
2319
1743
|
(s) => s?.type === "ImportSpecifier" && (s.imported?.name === name || s.imported?.value === name)
|
|
2320
1744
|
);
|
|
2321
1745
|
if (has) return { changed: false };
|
|
2322
|
-
const spec =
|
|
1746
|
+
const spec = parseModule2(`import { ${name} } from "${from}";`).$ast.body?.[0]?.specifiers?.[0];
|
|
2323
1747
|
if (!spec) return { changed: false };
|
|
2324
1748
|
existing.specifiers = [...existing.specifiers ?? [], spec];
|
|
2325
1749
|
return { changed: true };
|
|
2326
1750
|
}
|
|
2327
|
-
const importDecl =
|
|
1751
|
+
const importDecl = parseModule2(`import { ${name} } from "${from}";`).$ast.body?.[0];
|
|
2328
1752
|
if (!importDecl) return { changed: false };
|
|
2329
1753
|
const body = program.body ?? [];
|
|
2330
1754
|
let insertAt = 0;
|
|
@@ -2354,7 +1778,7 @@ function hasUILintDevtoolsJsx(program) {
|
|
|
2354
1778
|
function addDevtoolsElementNextJs(program) {
|
|
2355
1779
|
if (!program || program.type !== "Program") return { changed: false };
|
|
2356
1780
|
if (hasUILintDevtoolsJsx(program)) return { changed: false };
|
|
2357
|
-
const devtoolsMod =
|
|
1781
|
+
const devtoolsMod = parseModule2(
|
|
2358
1782
|
"const __uilint_devtools = <uilint-devtools />;"
|
|
2359
1783
|
);
|
|
2360
1784
|
const devtoolsJsx = devtoolsMod.$ast.body?.[0]?.declarations?.[0]?.init ?? null;
|
|
@@ -2392,12 +1816,12 @@ function addDevtoolsElementVite(program) {
|
|
|
2392
1816
|
const arg0 = node.arguments?.[0];
|
|
2393
1817
|
if (!arg0) return;
|
|
2394
1818
|
if (arg0.type !== "JSXElement" && arg0.type !== "JSXFragment") return;
|
|
2395
|
-
const devtoolsMod =
|
|
1819
|
+
const devtoolsMod = parseModule2(
|
|
2396
1820
|
"const __uilint_devtools = <uilint-devtools />;"
|
|
2397
1821
|
);
|
|
2398
1822
|
const devtoolsJsx = devtoolsMod.$ast.body?.[0]?.declarations?.[0]?.init ?? null;
|
|
2399
1823
|
if (!devtoolsJsx) return;
|
|
2400
|
-
const fragmentMod =
|
|
1824
|
+
const fragmentMod = parseModule2(
|
|
2401
1825
|
"const __fragment = <></>;"
|
|
2402
1826
|
);
|
|
2403
1827
|
const fragmentJsx = fragmentMod.$ast.body?.[0]?.declarations?.[0]?.init ?? null;
|
|
@@ -2417,7 +1841,7 @@ function ensureSideEffectImport(program, from) {
|
|
|
2417
1841
|
if (!program || program.type !== "Program") return { changed: false };
|
|
2418
1842
|
const existing = findImportDeclaration(program, from);
|
|
2419
1843
|
if (existing) return { changed: false };
|
|
2420
|
-
const importDecl =
|
|
1844
|
+
const importDecl = parseModule2(`import "${from}";`).$ast.body?.[0];
|
|
2421
1845
|
if (!importDecl) return { changed: false };
|
|
2422
1846
|
const body = program.body ?? [];
|
|
2423
1847
|
let insertAt = 0;
|
|
@@ -2433,7 +1857,7 @@ function ensureSideEffectImport(program, from) {
|
|
|
2433
1857
|
function addDevtoolsToClientComponent(program) {
|
|
2434
1858
|
if (!program || program.type !== "Program") return { changed: false };
|
|
2435
1859
|
if (hasUILintDevtoolsJsx(program)) return { changed: false };
|
|
2436
|
-
const devtoolsMod =
|
|
1860
|
+
const devtoolsMod = parseModule2(
|
|
2437
1861
|
"const __uilint_devtools = <uilint-devtools />;"
|
|
2438
1862
|
);
|
|
2439
1863
|
const devtoolsJsx = devtoolsMod.$ast.body?.[0]?.declarations?.[0]?.init ?? null;
|
|
@@ -2459,7 +1883,7 @@ function addDevtoolsToClientComponent(program) {
|
|
|
2459
1883
|
const arg = node.argument;
|
|
2460
1884
|
if (!arg) return;
|
|
2461
1885
|
if (arg.type !== "JSXElement" && arg.type !== "JSXFragment") return;
|
|
2462
|
-
const fragmentMod =
|
|
1886
|
+
const fragmentMod = parseModule2("const __fragment = <></>;");
|
|
2463
1887
|
const fragmentJsx = fragmentMod.$ast.body?.[0]?.declarations?.[0]?.init ?? null;
|
|
2464
1888
|
if (!fragmentJsx) return;
|
|
2465
1889
|
fragmentJsx.children = [arg, devtoolsJsx];
|
|
@@ -2514,7 +1938,7 @@ function wrapChildrenWithProviders(program, providersImportPath) {
|
|
|
2514
1938
|
(child) => child?.type === "JSXExpressionContainer" && child.expression?.type === "Identifier" && child.expression.name === "children"
|
|
2515
1939
|
);
|
|
2516
1940
|
if (childrenIndex === -1) return;
|
|
2517
|
-
const providersMod =
|
|
1941
|
+
const providersMod = parseModule2(
|
|
2518
1942
|
"const __providers = <Providers>{children}</Providers>;"
|
|
2519
1943
|
);
|
|
2520
1944
|
const providersJsx = providersMod.$ast.body?.[0]?.declarations?.[0]?.init ?? null;
|
|
@@ -2532,8 +1956,8 @@ function wrapChildrenWithProviders(program, providersImportPath) {
|
|
|
2532
1956
|
function findLayoutFile2(projectPath, appRoot) {
|
|
2533
1957
|
const extensions = [".tsx", ".jsx", ".ts", ".js"];
|
|
2534
1958
|
for (const ext of extensions) {
|
|
2535
|
-
const layoutPath =
|
|
2536
|
-
if (
|
|
1959
|
+
const layoutPath = join5(projectPath, appRoot, `layout${ext}`);
|
|
1960
|
+
if (existsSync5(layoutPath)) return layoutPath;
|
|
2537
1961
|
}
|
|
2538
1962
|
return null;
|
|
2539
1963
|
}
|
|
@@ -2544,32 +1968,32 @@ async function createProvidersAndModifyLayout(projectPath, appRoot) {
|
|
|
2544
1968
|
}
|
|
2545
1969
|
const isTypeScript = layoutPath.endsWith(".tsx") || layoutPath.endsWith(".ts");
|
|
2546
1970
|
const providersExt = isTypeScript ? ".tsx" : ".jsx";
|
|
2547
|
-
const providersPath =
|
|
2548
|
-
if (
|
|
1971
|
+
const providersPath = join5(projectPath, appRoot, `providers${providersExt}`);
|
|
1972
|
+
if (existsSync5(providersPath)) {
|
|
2549
1973
|
throw new Error(
|
|
2550
1974
|
`providers${providersExt} already exists. Please select it from the list instead.`
|
|
2551
1975
|
);
|
|
2552
1976
|
}
|
|
2553
1977
|
const providersContent = generateProvidersContent(isTypeScript);
|
|
2554
|
-
|
|
2555
|
-
const layoutContent =
|
|
1978
|
+
writeFileSync(providersPath, providersContent, "utf-8");
|
|
1979
|
+
const layoutContent = readFileSync5(layoutPath, "utf-8");
|
|
2556
1980
|
let layoutMod;
|
|
2557
1981
|
try {
|
|
2558
|
-
layoutMod =
|
|
1982
|
+
layoutMod = parseModule2(layoutContent);
|
|
2559
1983
|
} catch {
|
|
2560
1984
|
throw new Error(
|
|
2561
|
-
`Unable to parse ${
|
|
1985
|
+
`Unable to parse ${relative3(projectPath, layoutPath)} as JavaScript/TypeScript.`
|
|
2562
1986
|
);
|
|
2563
1987
|
}
|
|
2564
1988
|
const layoutProgram = layoutMod.$ast;
|
|
2565
1989
|
const wrapRes = wrapChildrenWithProviders(layoutProgram, "./providers");
|
|
2566
1990
|
if (wrapRes.changed) {
|
|
2567
|
-
const updatedLayout =
|
|
2568
|
-
|
|
1991
|
+
const updatedLayout = generateCode(layoutMod).code;
|
|
1992
|
+
writeFileSync(layoutPath, updatedLayout, "utf-8");
|
|
2569
1993
|
}
|
|
2570
1994
|
return {
|
|
2571
|
-
providersFile:
|
|
2572
|
-
layoutFile:
|
|
1995
|
+
providersFile: relative3(projectPath, providersPath),
|
|
1996
|
+
layoutFile: relative3(projectPath, layoutPath),
|
|
2573
1997
|
modified: true
|
|
2574
1998
|
};
|
|
2575
1999
|
}
|
|
@@ -2581,8 +2005,8 @@ async function installReactUILintOverlay(opts) {
|
|
|
2581
2005
|
);
|
|
2582
2006
|
const modifiedFiles = [];
|
|
2583
2007
|
if (result.modified) {
|
|
2584
|
-
modifiedFiles.push(
|
|
2585
|
-
modifiedFiles.push(
|
|
2008
|
+
modifiedFiles.push(join5(opts.projectPath, result.providersFile));
|
|
2009
|
+
modifiedFiles.push(join5(opts.projectPath, result.layoutFile));
|
|
2586
2010
|
}
|
|
2587
2011
|
return {
|
|
2588
2012
|
targetFile: result.providersFile,
|
|
@@ -2594,14 +2018,14 @@ async function installReactUILintOverlay(opts) {
|
|
|
2594
2018
|
}
|
|
2595
2019
|
if (opts.targetFile) {
|
|
2596
2020
|
const absTarget2 = opts.targetFile;
|
|
2597
|
-
const relTarget =
|
|
2598
|
-
if (!
|
|
2021
|
+
const relTarget = relative3(opts.projectPath, absTarget2);
|
|
2022
|
+
if (!existsSync5(absTarget2)) {
|
|
2599
2023
|
throw new Error(`Target file not found: ${relTarget}`);
|
|
2600
2024
|
}
|
|
2601
|
-
const original2 =
|
|
2025
|
+
const original2 = readFileSync5(absTarget2, "utf-8");
|
|
2602
2026
|
let mod2;
|
|
2603
2027
|
try {
|
|
2604
|
-
mod2 =
|
|
2028
|
+
mod2 = parseModule2(original2);
|
|
2605
2029
|
} catch {
|
|
2606
2030
|
throw new Error(
|
|
2607
2031
|
`Unable to parse ${relTarget} as JavaScript/TypeScript. Please update it manually.`
|
|
@@ -2624,10 +2048,10 @@ async function installReactUILintOverlay(opts) {
|
|
|
2624
2048
|
if (importRes2.changed) changed2 = true;
|
|
2625
2049
|
const addRes2 = addDevtoolsToClientComponent(program2);
|
|
2626
2050
|
if (addRes2.changed) changed2 = true;
|
|
2627
|
-
const updated2 = changed2 ?
|
|
2051
|
+
const updated2 = changed2 ? generateCode(mod2).code : original2;
|
|
2628
2052
|
const modified2 = updated2 !== original2;
|
|
2629
2053
|
if (modified2) {
|
|
2630
|
-
|
|
2054
|
+
writeFileSync(absTarget2, updated2, "utf-8");
|
|
2631
2055
|
}
|
|
2632
2056
|
return {
|
|
2633
2057
|
targetFile: relTarget,
|
|
@@ -2648,11 +2072,11 @@ async function installReactUILintOverlay(opts) {
|
|
|
2648
2072
|
} else {
|
|
2649
2073
|
chosen = candidates[0];
|
|
2650
2074
|
}
|
|
2651
|
-
const absTarget =
|
|
2652
|
-
const original =
|
|
2075
|
+
const absTarget = join5(opts.projectPath, chosen);
|
|
2076
|
+
const original = readFileSync5(absTarget, "utf-8");
|
|
2653
2077
|
let mod;
|
|
2654
2078
|
try {
|
|
2655
|
-
mod =
|
|
2079
|
+
mod = parseModule2(original);
|
|
2656
2080
|
} catch {
|
|
2657
2081
|
throw new Error(
|
|
2658
2082
|
`Unable to parse ${chosen} as JavaScript/TypeScript. Please update it manually.`
|
|
@@ -2668,10 +2092,10 @@ async function installReactUILintOverlay(opts) {
|
|
|
2668
2092
|
const mode = opts.mode ?? "next";
|
|
2669
2093
|
const addRes = mode === "vite" ? addDevtoolsElementVite(program) : addDevtoolsElementNextJs(program);
|
|
2670
2094
|
if (addRes.changed) changed = true;
|
|
2671
|
-
const updated = changed ?
|
|
2095
|
+
const updated = changed ? generateCode(mod).code : original;
|
|
2672
2096
|
const modified = updated !== original;
|
|
2673
2097
|
if (modified) {
|
|
2674
|
-
|
|
2098
|
+
writeFileSync(absTarget, updated, "utf-8");
|
|
2675
2099
|
}
|
|
2676
2100
|
return {
|
|
2677
2101
|
targetFile: chosen,
|
|
@@ -2685,10 +2109,10 @@ async function uninstallReactUILintOverlay(options) {
|
|
|
2685
2109
|
const candidates = getDefaultCandidates(projectPath, appRoot);
|
|
2686
2110
|
const modifiedFiles = [];
|
|
2687
2111
|
for (const candidate of candidates) {
|
|
2688
|
-
const absPath =
|
|
2689
|
-
if (!
|
|
2112
|
+
const absPath = join5(projectPath, candidate);
|
|
2113
|
+
if (!existsSync5(absPath)) continue;
|
|
2690
2114
|
try {
|
|
2691
|
-
const original =
|
|
2115
|
+
const original = readFileSync5(absPath, "utf-8");
|
|
2692
2116
|
let updated = original.replace(
|
|
2693
2117
|
/^import\s+["']uilint-react\/devtools["'];?\s*$/gm,
|
|
2694
2118
|
""
|
|
@@ -2706,7 +2130,7 @@ async function uninstallReactUILintOverlay(options) {
|
|
|
2706
2130
|
);
|
|
2707
2131
|
updated = updated.replace(/\n{3,}/g, "\n\n");
|
|
2708
2132
|
if (updated !== original) {
|
|
2709
|
-
|
|
2133
|
+
writeFileSync(absPath, updated, "utf-8");
|
|
2710
2134
|
modifiedFiles.push(absPath);
|
|
2711
2135
|
}
|
|
2712
2136
|
} catch {
|
|
@@ -2719,14 +2143,14 @@ async function uninstallReactUILintOverlay(options) {
|
|
|
2719
2143
|
}
|
|
2720
2144
|
|
|
2721
2145
|
// src/utils/next-config-inject.ts
|
|
2722
|
-
import { existsSync as
|
|
2723
|
-
import { join as
|
|
2724
|
-
import { parseModule as
|
|
2725
|
-
var
|
|
2146
|
+
import { existsSync as existsSync6, readFileSync as readFileSync6, writeFileSync as writeFileSync2 } from "fs";
|
|
2147
|
+
import { join as join6 } from "path";
|
|
2148
|
+
import { parseModule as parseModule3, generateCode as generateCode2 } from "magicast";
|
|
2149
|
+
var CONFIG_EXTENSIONS = [".ts", ".mjs", ".js", ".cjs"];
|
|
2726
2150
|
function findNextConfigFile(projectPath) {
|
|
2727
|
-
for (const ext of
|
|
2728
|
-
const configPath =
|
|
2729
|
-
if (
|
|
2151
|
+
for (const ext of CONFIG_EXTENSIONS) {
|
|
2152
|
+
const configPath = join6(projectPath, `next.config${ext}`);
|
|
2153
|
+
if (existsSync6(configPath)) {
|
|
2730
2154
|
return configPath;
|
|
2731
2155
|
}
|
|
2732
2156
|
}
|
|
@@ -2736,10 +2160,10 @@ function getNextConfigFilename(configPath) {
|
|
|
2736
2160
|
const parts = configPath.split("/");
|
|
2737
2161
|
return parts[parts.length - 1] || "next.config.ts";
|
|
2738
2162
|
}
|
|
2739
|
-
function
|
|
2163
|
+
function isIdentifier(node, name) {
|
|
2740
2164
|
return !!node && node.type === "Identifier" && (name ? node.name === name : typeof node.name === "string");
|
|
2741
2165
|
}
|
|
2742
|
-
function
|
|
2166
|
+
function isStringLiteral(node) {
|
|
2743
2167
|
return !!node && (node.type === "StringLiteral" || node.type === "Literal") && typeof node.value === "string";
|
|
2744
2168
|
}
|
|
2745
2169
|
function ensureEsmWithJsxLocImport(program) {
|
|
@@ -2752,12 +2176,12 @@ function ensureEsmWithJsxLocImport(program) {
|
|
|
2752
2176
|
(sp) => sp?.type === "ImportSpecifier" && (sp.imported?.name === "withJsxLoc" || sp.imported?.value === "withJsxLoc")
|
|
2753
2177
|
);
|
|
2754
2178
|
if (has) return { changed: false };
|
|
2755
|
-
const spec =
|
|
2179
|
+
const spec = parseModule3('import { withJsxLoc } from "jsx-loc-plugin";').$ast.body?.[0]?.specifiers?.[0];
|
|
2756
2180
|
if (!spec) return { changed: false };
|
|
2757
2181
|
existing.specifiers = [...existing.specifiers ?? [], spec];
|
|
2758
2182
|
return { changed: true };
|
|
2759
2183
|
}
|
|
2760
|
-
const importDecl =
|
|
2184
|
+
const importDecl = parseModule3('import { withJsxLoc } from "jsx-loc-plugin";').$ast.body?.[0];
|
|
2761
2185
|
if (!importDecl) return { changed: false };
|
|
2762
2186
|
const body = program.body ?? [];
|
|
2763
2187
|
let insertAt = 0;
|
|
@@ -2773,14 +2197,14 @@ function ensureCjsWithJsxLocRequire(program) {
|
|
|
2773
2197
|
if (stmt?.type !== "VariableDeclaration") continue;
|
|
2774
2198
|
for (const decl of stmt.declarations ?? []) {
|
|
2775
2199
|
const init = decl?.init;
|
|
2776
|
-
if (init?.type === "CallExpression" &&
|
|
2200
|
+
if (init?.type === "CallExpression" && isIdentifier(init.callee, "require") && isStringLiteral(init.arguments?.[0]) && init.arguments[0].value === "jsx-loc-plugin") {
|
|
2777
2201
|
if (decl.id?.type === "ObjectPattern") {
|
|
2778
2202
|
const has = (decl.id.properties ?? []).some((p) => {
|
|
2779
2203
|
if (p?.type !== "ObjectProperty" && p?.type !== "Property") return false;
|
|
2780
|
-
return
|
|
2204
|
+
return isIdentifier(p.key, "withJsxLoc");
|
|
2781
2205
|
});
|
|
2782
2206
|
if (has) return { changed: false };
|
|
2783
|
-
const prop =
|
|
2207
|
+
const prop = parseModule3('const { withJsxLoc } = require("jsx-loc-plugin");').$ast.body?.[0]?.declarations?.[0]?.id?.properties?.[0];
|
|
2784
2208
|
if (!prop) return { changed: false };
|
|
2785
2209
|
decl.id.properties = [...decl.id.properties ?? [], prop];
|
|
2786
2210
|
return { changed: true };
|
|
@@ -2789,7 +2213,7 @@ function ensureCjsWithJsxLocRequire(program) {
|
|
|
2789
2213
|
}
|
|
2790
2214
|
}
|
|
2791
2215
|
}
|
|
2792
|
-
const reqDecl =
|
|
2216
|
+
const reqDecl = parseModule3('const { withJsxLoc } = require("jsx-loc-plugin");').$ast.body?.[0];
|
|
2793
2217
|
if (!reqDecl) return { changed: false };
|
|
2794
2218
|
program.body.unshift(reqDecl);
|
|
2795
2219
|
return { changed: true };
|
|
@@ -2801,7 +2225,7 @@ function wrapEsmExportDefault(program) {
|
|
|
2801
2225
|
);
|
|
2802
2226
|
if (!exportDecl) return { changed: false };
|
|
2803
2227
|
const decl = exportDecl.declaration;
|
|
2804
|
-
if (decl?.type === "CallExpression" &&
|
|
2228
|
+
if (decl?.type === "CallExpression" && isIdentifier(decl.callee, "withJsxLoc")) {
|
|
2805
2229
|
return { changed: false };
|
|
2806
2230
|
}
|
|
2807
2231
|
exportDecl.declaration = {
|
|
@@ -2819,9 +2243,9 @@ function wrapCjsModuleExports(program) {
|
|
|
2819
2243
|
if (!expr || expr.type !== "AssignmentExpression") continue;
|
|
2820
2244
|
const left = expr.left;
|
|
2821
2245
|
const right = expr.right;
|
|
2822
|
-
const isModuleExports = left?.type === "MemberExpression" &&
|
|
2246
|
+
const isModuleExports = left?.type === "MemberExpression" && isIdentifier(left.object, "module") && isIdentifier(left.property, "exports");
|
|
2823
2247
|
if (!isModuleExports) continue;
|
|
2824
|
-
if (right?.type === "CallExpression" &&
|
|
2248
|
+
if (right?.type === "CallExpression" && isIdentifier(right.callee, "withJsxLoc")) {
|
|
2825
2249
|
return { changed: false };
|
|
2826
2250
|
}
|
|
2827
2251
|
expr.right = {
|
|
@@ -2839,10 +2263,10 @@ async function installJsxLocPlugin(opts) {
|
|
|
2839
2263
|
return { configFile: null, modified: false, modifiedFiles: [] };
|
|
2840
2264
|
}
|
|
2841
2265
|
const configFilename = getNextConfigFilename(configPath);
|
|
2842
|
-
const original =
|
|
2266
|
+
const original = readFileSync6(configPath, "utf-8");
|
|
2843
2267
|
let mod;
|
|
2844
2268
|
try {
|
|
2845
|
-
mod =
|
|
2269
|
+
mod = parseModule3(original);
|
|
2846
2270
|
} catch {
|
|
2847
2271
|
return { configFile: configFilename, modified: false, modifiedFiles: [] };
|
|
2848
2272
|
}
|
|
@@ -2860,9 +2284,9 @@ async function installJsxLocPlugin(opts) {
|
|
|
2860
2284
|
const wrapRes = wrapEsmExportDefault(program);
|
|
2861
2285
|
if (wrapRes.changed) changed = true;
|
|
2862
2286
|
}
|
|
2863
|
-
const updated = changed ?
|
|
2287
|
+
const updated = changed ? generateCode2(mod).code : original;
|
|
2864
2288
|
if (updated !== original) {
|
|
2865
|
-
|
|
2289
|
+
writeFileSync2(configPath, updated, "utf-8");
|
|
2866
2290
|
return { configFile: configFilename, modified: true, modifiedFiles: [configPath] };
|
|
2867
2291
|
}
|
|
2868
2292
|
return { configFile: configFilename, modified: false, modifiedFiles: [] };
|
|
@@ -2877,7 +2301,7 @@ async function uninstallJsxLocPlugin(options) {
|
|
|
2877
2301
|
};
|
|
2878
2302
|
}
|
|
2879
2303
|
try {
|
|
2880
|
-
const original =
|
|
2304
|
+
const original = readFileSync6(configPath, "utf-8");
|
|
2881
2305
|
let updated = original.replace(
|
|
2882
2306
|
/^import\s+\{[^}]*withJsxLoc[^}]*\}\s+from\s+["']jsx-loc-plugin\/next["'];?\s*$/gm,
|
|
2883
2307
|
""
|
|
@@ -2896,7 +2320,7 @@ async function uninstallJsxLocPlugin(options) {
|
|
|
2896
2320
|
);
|
|
2897
2321
|
updated = updated.replace(/\n{3,}/g, "\n\n");
|
|
2898
2322
|
if (updated !== original) {
|
|
2899
|
-
|
|
2323
|
+
writeFileSync2(configPath, updated, "utf-8");
|
|
2900
2324
|
return {
|
|
2901
2325
|
success: true,
|
|
2902
2326
|
modifiedFiles: [configPath]
|
|
@@ -2915,14 +2339,14 @@ async function uninstallJsxLocPlugin(options) {
|
|
|
2915
2339
|
}
|
|
2916
2340
|
|
|
2917
2341
|
// src/utils/vite-config-inject.ts
|
|
2918
|
-
import { existsSync as
|
|
2919
|
-
import { join as
|
|
2920
|
-
import { parseModule as
|
|
2921
|
-
var
|
|
2342
|
+
import { existsSync as existsSync7, readFileSync as readFileSync7, writeFileSync as writeFileSync3 } from "fs";
|
|
2343
|
+
import { join as join7 } from "path";
|
|
2344
|
+
import { parseModule as parseModule4, generateCode as generateCode3 } from "magicast";
|
|
2345
|
+
var CONFIG_EXTENSIONS2 = [".ts", ".mjs", ".js", ".cjs"];
|
|
2922
2346
|
function findViteConfigFile2(projectPath) {
|
|
2923
|
-
for (const ext of
|
|
2924
|
-
const configPath =
|
|
2925
|
-
if (
|
|
2347
|
+
for (const ext of CONFIG_EXTENSIONS2) {
|
|
2348
|
+
const configPath = join7(projectPath, `vite.config${ext}`);
|
|
2349
|
+
if (existsSync7(configPath)) return configPath;
|
|
2926
2350
|
}
|
|
2927
2351
|
return null;
|
|
2928
2352
|
}
|
|
@@ -2930,10 +2354,10 @@ function getViteConfigFilename(configPath) {
|
|
|
2930
2354
|
const parts = configPath.split("/");
|
|
2931
2355
|
return parts[parts.length - 1] || "vite.config.ts";
|
|
2932
2356
|
}
|
|
2933
|
-
function
|
|
2357
|
+
function isIdentifier2(node, name) {
|
|
2934
2358
|
return !!node && node.type === "Identifier" && (name ? node.name === name : typeof node.name === "string");
|
|
2935
2359
|
}
|
|
2936
|
-
function
|
|
2360
|
+
function isStringLiteral2(node) {
|
|
2937
2361
|
return !!node && (node.type === "StringLiteral" || node.type === "Literal") && typeof node.value === "string";
|
|
2938
2362
|
}
|
|
2939
2363
|
function unwrapExpression(expr) {
|
|
@@ -2965,7 +2389,7 @@ function findExportedConfigObjectExpression(mod) {
|
|
|
2965
2389
|
if (decl.type === "ObjectExpression") {
|
|
2966
2390
|
return { kind: "esm", objExpr: decl, program };
|
|
2967
2391
|
}
|
|
2968
|
-
if (decl.type === "CallExpression" &&
|
|
2392
|
+
if (decl.type === "CallExpression" && isIdentifier2(decl.callee, "defineConfig") && unwrapExpression(decl.arguments?.[0])?.type === "ObjectExpression") {
|
|
2969
2393
|
return {
|
|
2970
2394
|
kind: "esm",
|
|
2971
2395
|
objExpr: unwrapExpression(decl.arguments?.[0]),
|
|
@@ -2980,12 +2404,12 @@ function findExportedConfigObjectExpression(mod) {
|
|
|
2980
2404
|
if (!expr || expr.type !== "AssignmentExpression") continue;
|
|
2981
2405
|
const left = expr.left;
|
|
2982
2406
|
const right = unwrapExpression(expr.right);
|
|
2983
|
-
const isModuleExports = left?.type === "MemberExpression" &&
|
|
2407
|
+
const isModuleExports = left?.type === "MemberExpression" && isIdentifier2(left.object, "module") && isIdentifier2(left.property, "exports");
|
|
2984
2408
|
if (!isModuleExports) continue;
|
|
2985
2409
|
if (right?.type === "ObjectExpression") {
|
|
2986
2410
|
return { kind: "cjs", objExpr: right, program };
|
|
2987
2411
|
}
|
|
2988
|
-
if (right?.type === "CallExpression" &&
|
|
2412
|
+
if (right?.type === "CallExpression" && isIdentifier2(right.callee, "defineConfig") && unwrapExpression(right.arguments?.[0])?.type === "ObjectExpression") {
|
|
2989
2413
|
return {
|
|
2990
2414
|
kind: "cjs",
|
|
2991
2415
|
objExpr: unwrapExpression(right.arguments?.[0]),
|
|
@@ -3001,7 +2425,7 @@ function getObjectProperty(obj, keyName) {
|
|
|
3001
2425
|
if (!prop) continue;
|
|
3002
2426
|
if (prop.type !== "ObjectProperty" && prop.type !== "Property") continue;
|
|
3003
2427
|
const key = prop.key;
|
|
3004
|
-
const keyMatch = key?.type === "Identifier" && key.name === keyName ||
|
|
2428
|
+
const keyMatch = key?.type === "Identifier" && key.name === keyName || isStringLiteral2(key) && key.value === keyName;
|
|
3005
2429
|
if (keyMatch) return prop;
|
|
3006
2430
|
}
|
|
3007
2431
|
return null;
|
|
@@ -3016,12 +2440,12 @@ function ensureEsmJsxLocImport(program) {
|
|
|
3016
2440
|
(sp) => sp?.type === "ImportSpecifier" && (sp.imported?.name === "jsxLoc" || sp.imported?.value === "jsxLoc")
|
|
3017
2441
|
);
|
|
3018
2442
|
if (has) return { changed: false };
|
|
3019
|
-
const spec =
|
|
2443
|
+
const spec = parseModule4('import { jsxLoc } from "jsx-loc-plugin/vite";').$ast.body?.[0]?.specifiers?.[0];
|
|
3020
2444
|
if (!spec) return { changed: false };
|
|
3021
2445
|
existing.specifiers = [...existing.specifiers ?? [], spec];
|
|
3022
2446
|
return { changed: true };
|
|
3023
2447
|
}
|
|
3024
|
-
const importDecl =
|
|
2448
|
+
const importDecl = parseModule4('import { jsxLoc } from "jsx-loc-plugin/vite";').$ast.body?.[0];
|
|
3025
2449
|
if (!importDecl) return { changed: false };
|
|
3026
2450
|
const body = program.body ?? [];
|
|
3027
2451
|
let insertAt = 0;
|
|
@@ -3037,14 +2461,14 @@ function ensureCjsJsxLocRequire(program) {
|
|
|
3037
2461
|
if (stmt?.type !== "VariableDeclaration") continue;
|
|
3038
2462
|
for (const decl of stmt.declarations ?? []) {
|
|
3039
2463
|
const init = decl?.init;
|
|
3040
|
-
if (init?.type === "CallExpression" &&
|
|
2464
|
+
if (init?.type === "CallExpression" && isIdentifier2(init.callee, "require") && isStringLiteral2(init.arguments?.[0]) && init.arguments[0].value === "jsx-loc-plugin/vite") {
|
|
3041
2465
|
if (decl.id?.type === "ObjectPattern") {
|
|
3042
2466
|
const has = (decl.id.properties ?? []).some((p) => {
|
|
3043
2467
|
if (p?.type !== "ObjectProperty" && p?.type !== "Property") return false;
|
|
3044
|
-
return
|
|
2468
|
+
return isIdentifier2(p.key, "jsxLoc");
|
|
3045
2469
|
});
|
|
3046
2470
|
if (has) return { changed: false };
|
|
3047
|
-
const prop =
|
|
2471
|
+
const prop = parseModule4('const { jsxLoc } = require("jsx-loc-plugin/vite");').$ast.body?.[0]?.declarations?.[0]?.id?.properties?.[0];
|
|
3048
2472
|
if (!prop) return { changed: false };
|
|
3049
2473
|
decl.id.properties = [...decl.id.properties ?? [], prop];
|
|
3050
2474
|
return { changed: true };
|
|
@@ -3053,7 +2477,7 @@ function ensureCjsJsxLocRequire(program) {
|
|
|
3053
2477
|
}
|
|
3054
2478
|
}
|
|
3055
2479
|
}
|
|
3056
|
-
const reqDecl =
|
|
2480
|
+
const reqDecl = parseModule4('const { jsxLoc } = require("jsx-loc-plugin/vite");').$ast.body?.[0];
|
|
3057
2481
|
if (!reqDecl) return { changed: false };
|
|
3058
2482
|
program.body.unshift(reqDecl);
|
|
3059
2483
|
return { changed: true };
|
|
@@ -3063,16 +2487,16 @@ function pluginsHasJsxLoc(arr) {
|
|
|
3063
2487
|
for (const el of arr.elements ?? []) {
|
|
3064
2488
|
const e = unwrapExpression(el);
|
|
3065
2489
|
if (!e) continue;
|
|
3066
|
-
if (e.type === "CallExpression" &&
|
|
2490
|
+
if (e.type === "CallExpression" && isIdentifier2(e.callee, "jsxLoc")) return true;
|
|
3067
2491
|
}
|
|
3068
2492
|
return false;
|
|
3069
2493
|
}
|
|
3070
2494
|
function ensurePluginsContainsJsxLoc(configObj) {
|
|
3071
2495
|
const pluginsProp = getObjectProperty(configObj, "plugins");
|
|
3072
2496
|
if (!pluginsProp) {
|
|
3073
|
-
const prop =
|
|
2497
|
+
const prop = parseModule4("export default { plugins: [jsxLoc()] };").$ast.body?.find((s) => s.type === "ExportDefaultDeclaration")?.declaration?.properties?.find((p) => {
|
|
3074
2498
|
const k = p?.key;
|
|
3075
|
-
return k?.type === "Identifier" && k.name === "plugins" ||
|
|
2499
|
+
return k?.type === "Identifier" && k.name === "plugins" || isStringLiteral2(k) && k.value === "plugins";
|
|
3076
2500
|
});
|
|
3077
2501
|
if (!prop) return { changed: false };
|
|
3078
2502
|
configObj.properties = [...configObj.properties ?? [], prop];
|
|
@@ -3082,12 +2506,12 @@ function ensurePluginsContainsJsxLoc(configObj) {
|
|
|
3082
2506
|
if (!value) return { changed: false };
|
|
3083
2507
|
if (value.type === "ArrayExpression") {
|
|
3084
2508
|
if (pluginsHasJsxLoc(value)) return { changed: false };
|
|
3085
|
-
const jsxLocCall2 =
|
|
2509
|
+
const jsxLocCall2 = parseModule4("const __x = jsxLoc();").$ast.body?.[0]?.declarations?.[0]?.init;
|
|
3086
2510
|
if (!jsxLocCall2) return { changed: false };
|
|
3087
2511
|
value.elements.push(jsxLocCall2);
|
|
3088
2512
|
return { changed: true };
|
|
3089
2513
|
}
|
|
3090
|
-
const jsxLocCall =
|
|
2514
|
+
const jsxLocCall = parseModule4("const __x = jsxLoc();").$ast.body?.[0]?.declarations?.[0]?.init;
|
|
3091
2515
|
if (!jsxLocCall) return { changed: false };
|
|
3092
2516
|
const spread = { type: "SpreadElement", argument: value };
|
|
3093
2517
|
pluginsProp.value = { type: "ArrayExpression", elements: [spread, jsxLocCall] };
|
|
@@ -3097,11 +2521,11 @@ async function installViteJsxLocPlugin(opts) {
|
|
|
3097
2521
|
const configPath = findViteConfigFile2(opts.projectPath);
|
|
3098
2522
|
if (!configPath) return { configFile: null, modified: false, modifiedFiles: [] };
|
|
3099
2523
|
const configFilename = getViteConfigFilename(configPath);
|
|
3100
|
-
const original =
|
|
2524
|
+
const original = readFileSync7(configPath, "utf-8");
|
|
3101
2525
|
const isCjs = configPath.endsWith(".cjs");
|
|
3102
2526
|
let mod;
|
|
3103
2527
|
try {
|
|
3104
|
-
mod =
|
|
2528
|
+
mod = parseModule4(original);
|
|
3105
2529
|
} catch {
|
|
3106
2530
|
return { configFile: configFilename, modified: false, modifiedFiles: [] };
|
|
3107
2531
|
}
|
|
@@ -3117,9 +2541,9 @@ async function installViteJsxLocPlugin(opts) {
|
|
|
3117
2541
|
}
|
|
3118
2542
|
const pluginsRes = ensurePluginsContainsJsxLoc(found.objExpr);
|
|
3119
2543
|
if (pluginsRes.changed) changed = true;
|
|
3120
|
-
const updated = changed ?
|
|
2544
|
+
const updated = changed ? generateCode3(mod).code : original;
|
|
3121
2545
|
if (updated !== original) {
|
|
3122
|
-
|
|
2546
|
+
writeFileSync3(configPath, updated, "utf-8");
|
|
3123
2547
|
return { configFile: configFilename, modified: true, modifiedFiles: [configPath] };
|
|
3124
2548
|
}
|
|
3125
2549
|
return { configFile: configFilename, modified: false, modifiedFiles: [] };
|
|
@@ -3134,7 +2558,7 @@ async function uninstallViteJsxLocPlugin(options) {
|
|
|
3134
2558
|
};
|
|
3135
2559
|
}
|
|
3136
2560
|
try {
|
|
3137
|
-
const original =
|
|
2561
|
+
const original = readFileSync7(configPath, "utf-8");
|
|
3138
2562
|
let updated = original.replace(
|
|
3139
2563
|
/^import\s+\{[^}]*jsxLoc[^}]*\}\s+from\s+["']jsx-loc-plugin\/vite["'];?\s*$/gm,
|
|
3140
2564
|
""
|
|
@@ -3150,7 +2574,7 @@ async function uninstallViteJsxLocPlugin(options) {
|
|
|
3150
2574
|
updated = updated.replace(/jsxLoc\s*\(\s*\)\s*,?\s*/g, "");
|
|
3151
2575
|
updated = updated.replace(/\n{3,}/g, "\n\n");
|
|
3152
2576
|
if (updated !== original) {
|
|
3153
|
-
|
|
2577
|
+
writeFileSync3(configPath, updated, "utf-8");
|
|
3154
2578
|
return {
|
|
3155
2579
|
success: true,
|
|
3156
2580
|
modifiedFiles: [configPath]
|
|
@@ -3169,9 +2593,9 @@ async function uninstallViteJsxLocPlugin(options) {
|
|
|
3169
2593
|
}
|
|
3170
2594
|
|
|
3171
2595
|
// src/utils/next-routes.ts
|
|
3172
|
-
import { existsSync as
|
|
2596
|
+
import { existsSync as existsSync8 } from "fs";
|
|
3173
2597
|
import { mkdir, writeFile } from "fs/promises";
|
|
3174
|
-
import { join as
|
|
2598
|
+
import { join as join8 } from "path";
|
|
3175
2599
|
var DEV_SOURCE_ROUTE_TS = `/**
|
|
3176
2600
|
* Dev-only API route for fetching source files
|
|
3177
2601
|
*
|
|
@@ -3627,23 +3051,23 @@ export async function GET(request: NextRequest) {
|
|
|
3627
3051
|
}
|
|
3628
3052
|
`;
|
|
3629
3053
|
async function writeRouteFile(absPath, relPath, content, opts) {
|
|
3630
|
-
if (
|
|
3054
|
+
if (existsSync8(absPath) && !opts.force) return;
|
|
3631
3055
|
await writeFile(absPath, content, "utf-8");
|
|
3632
3056
|
}
|
|
3633
3057
|
async function installNextUILintRoutes(opts) {
|
|
3634
|
-
const baseRel =
|
|
3635
|
-
const baseAbs =
|
|
3636
|
-
await mkdir(
|
|
3058
|
+
const baseRel = join8(opts.appRoot, "api", ".uilint");
|
|
3059
|
+
const baseAbs = join8(opts.projectPath, baseRel);
|
|
3060
|
+
await mkdir(join8(baseAbs, "source"), { recursive: true });
|
|
3637
3061
|
await writeRouteFile(
|
|
3638
|
-
|
|
3639
|
-
|
|
3062
|
+
join8(baseAbs, "source", "route.ts"),
|
|
3063
|
+
join8(baseRel, "source", "route.ts"),
|
|
3640
3064
|
DEV_SOURCE_ROUTE_TS,
|
|
3641
3065
|
opts
|
|
3642
3066
|
);
|
|
3643
|
-
await mkdir(
|
|
3067
|
+
await mkdir(join8(baseAbs, "screenshots"), { recursive: true });
|
|
3644
3068
|
await writeRouteFile(
|
|
3645
|
-
|
|
3646
|
-
|
|
3069
|
+
join8(baseAbs, "screenshots", "route.ts"),
|
|
3070
|
+
join8(baseRel, "screenshots", "route.ts"),
|
|
3647
3071
|
SCREENSHOT_ROUTE_TS,
|
|
3648
3072
|
opts
|
|
3649
3073
|
);
|
|
@@ -3651,9 +3075,9 @@ async function installNextUILintRoutes(opts) {
|
|
|
3651
3075
|
async function uninstallNextUILintRoutes(options) {
|
|
3652
3076
|
const { projectPath, appRoot } = options;
|
|
3653
3077
|
const { rm } = await import("fs/promises");
|
|
3654
|
-
const baseAbs =
|
|
3078
|
+
const baseAbs = join8(projectPath, appRoot, "api", ".uilint");
|
|
3655
3079
|
try {
|
|
3656
|
-
if (
|
|
3080
|
+
if (existsSync8(baseAbs)) {
|
|
3657
3081
|
await rm(baseAbs, { recursive: true, force: true });
|
|
3658
3082
|
}
|
|
3659
3083
|
return { success: true };
|
|
@@ -3666,17 +3090,17 @@ async function uninstallNextUILintRoutes(options) {
|
|
|
3666
3090
|
}
|
|
3667
3091
|
|
|
3668
3092
|
// src/utils/prettier.ts
|
|
3669
|
-
import { existsSync as
|
|
3093
|
+
import { existsSync as existsSync9, utimesSync } from "fs";
|
|
3670
3094
|
import { spawn } from "child_process";
|
|
3671
|
-
import { join as
|
|
3095
|
+
import { join as join9, dirname as dirname3 } from "path";
|
|
3672
3096
|
function getPrettierPath(projectPath) {
|
|
3673
|
-
const localPath =
|
|
3674
|
-
if (
|
|
3097
|
+
const localPath = join9(projectPath, "node_modules", ".bin", "prettier");
|
|
3098
|
+
if (existsSync9(localPath)) return localPath;
|
|
3675
3099
|
let dir = projectPath;
|
|
3676
3100
|
for (let i = 0; i < 10; i++) {
|
|
3677
|
-
const binPath =
|
|
3678
|
-
if (
|
|
3679
|
-
const parent =
|
|
3101
|
+
const binPath = join9(dir, "node_modules", ".bin", "prettier");
|
|
3102
|
+
if (existsSync9(binPath)) return binPath;
|
|
3103
|
+
const parent = dirname3(dir);
|
|
3680
3104
|
if (parent === dir) break;
|
|
3681
3105
|
dir = parent;
|
|
3682
3106
|
}
|
|
@@ -3807,7 +3231,7 @@ function touchFiles(filePaths) {
|
|
|
3807
3231
|
const now = /* @__PURE__ */ new Date();
|
|
3808
3232
|
for (const filePath of filePaths) {
|
|
3809
3233
|
try {
|
|
3810
|
-
if (
|
|
3234
|
+
if (existsSync9(filePath)) {
|
|
3811
3235
|
utimesSync(filePath, now, now);
|
|
3812
3236
|
}
|
|
3813
3237
|
} catch {
|
|
@@ -3828,7 +3252,7 @@ async function executeAction(action, options) {
|
|
|
3828
3252
|
wouldDo: `Create directory: ${action.path}`
|
|
3829
3253
|
};
|
|
3830
3254
|
}
|
|
3831
|
-
if (!
|
|
3255
|
+
if (!existsSync10(action.path)) {
|
|
3832
3256
|
mkdirSync(action.path, { recursive: true });
|
|
3833
3257
|
}
|
|
3834
3258
|
return { action, success: true };
|
|
@@ -3841,11 +3265,11 @@ async function executeAction(action, options) {
|
|
|
3841
3265
|
wouldDo: `Create file: ${action.path}${action.permissions ? ` (mode: ${action.permissions.toString(8)})` : ""}`
|
|
3842
3266
|
};
|
|
3843
3267
|
}
|
|
3844
|
-
const dir =
|
|
3845
|
-
if (!
|
|
3268
|
+
const dir = dirname4(action.path);
|
|
3269
|
+
if (!existsSync10(dir)) {
|
|
3846
3270
|
mkdirSync(dir, { recursive: true });
|
|
3847
3271
|
}
|
|
3848
|
-
|
|
3272
|
+
writeFileSync4(action.path, action.content, "utf-8");
|
|
3849
3273
|
if (action.permissions) {
|
|
3850
3274
|
chmodSync(action.path, action.permissions);
|
|
3851
3275
|
}
|
|
@@ -3860,18 +3284,18 @@ async function executeAction(action, options) {
|
|
|
3860
3284
|
};
|
|
3861
3285
|
}
|
|
3862
3286
|
let existing = {};
|
|
3863
|
-
if (
|
|
3287
|
+
if (existsSync10(action.path)) {
|
|
3864
3288
|
try {
|
|
3865
|
-
existing = JSON.parse(
|
|
3289
|
+
existing = JSON.parse(readFileSync8(action.path, "utf-8"));
|
|
3866
3290
|
} catch {
|
|
3867
3291
|
}
|
|
3868
3292
|
}
|
|
3869
3293
|
const merged = deepMerge(existing, action.merge);
|
|
3870
|
-
const dir =
|
|
3871
|
-
if (!
|
|
3294
|
+
const dir = dirname4(action.path);
|
|
3295
|
+
if (!existsSync10(dir)) {
|
|
3872
3296
|
mkdirSync(dir, { recursive: true });
|
|
3873
3297
|
}
|
|
3874
|
-
|
|
3298
|
+
writeFileSync4(action.path, JSON.stringify(merged, null, 2), "utf-8");
|
|
3875
3299
|
return { action, success: true };
|
|
3876
3300
|
}
|
|
3877
3301
|
case "delete_file": {
|
|
@@ -3882,7 +3306,7 @@ async function executeAction(action, options) {
|
|
|
3882
3306
|
wouldDo: `Delete file: ${action.path}`
|
|
3883
3307
|
};
|
|
3884
3308
|
}
|
|
3885
|
-
if (
|
|
3309
|
+
if (existsSync10(action.path)) {
|
|
3886
3310
|
unlinkSync(action.path);
|
|
3887
3311
|
}
|
|
3888
3312
|
return { action, success: true };
|
|
@@ -3895,12 +3319,12 @@ async function executeAction(action, options) {
|
|
|
3895
3319
|
wouldDo: `Append to file: ${action.path}`
|
|
3896
3320
|
};
|
|
3897
3321
|
}
|
|
3898
|
-
if (
|
|
3899
|
-
const content =
|
|
3322
|
+
if (existsSync10(action.path)) {
|
|
3323
|
+
const content = readFileSync8(action.path, "utf-8");
|
|
3900
3324
|
if (action.ifNotContains && content.includes(action.ifNotContains)) {
|
|
3901
3325
|
return { action, success: true };
|
|
3902
3326
|
}
|
|
3903
|
-
|
|
3327
|
+
writeFileSync4(action.path, content + action.content, "utf-8");
|
|
3904
3328
|
}
|
|
3905
3329
|
return { action, success: true };
|
|
3906
3330
|
}
|
|
@@ -4169,7 +3593,7 @@ async function executeRemoveDirectory(action, options) {
|
|
|
4169
3593
|
wouldDo: `Remove directory: ${action.path}`
|
|
4170
3594
|
};
|
|
4171
3595
|
}
|
|
4172
|
-
if (
|
|
3596
|
+
if (existsSync10(action.path)) {
|
|
4173
3597
|
rmSync(action.path, { recursive: true, force: true });
|
|
4174
3598
|
}
|
|
4175
3599
|
return { action, success: true };
|
|
@@ -4406,7 +3830,7 @@ async function execute(plan, options = {}) {
|
|
|
4406
3830
|
import { ruleRegistry as ruleRegistry3 } from "uilint-eslint";
|
|
4407
3831
|
|
|
4408
3832
|
// src/commands/install/installers/genstyleguide.ts
|
|
4409
|
-
import { join as
|
|
3833
|
+
import { join as join10 } from "path";
|
|
4410
3834
|
var genstyleguideInstaller = {
|
|
4411
3835
|
id: "genstyleguide",
|
|
4412
3836
|
name: "/genstyleguide command",
|
|
@@ -4416,7 +3840,7 @@ var genstyleguideInstaller = {
|
|
|
4416
3840
|
return true;
|
|
4417
3841
|
},
|
|
4418
3842
|
getTargets(project) {
|
|
4419
|
-
const commandPath =
|
|
3843
|
+
const commandPath = join10(project.cursorDir.path, "commands", "genstyleguide.md");
|
|
4420
3844
|
const isInstalled = project.commands.genstyleguide;
|
|
4421
3845
|
return [
|
|
4422
3846
|
{
|
|
@@ -4429,7 +3853,7 @@ var genstyleguideInstaller = {
|
|
|
4429
3853
|
},
|
|
4430
3854
|
plan(targets, config, project) {
|
|
4431
3855
|
const actions = [];
|
|
4432
|
-
const commandsDir =
|
|
3856
|
+
const commandsDir = join10(project.cursorDir.path, "commands");
|
|
4433
3857
|
if (!project.cursorDir.exists) {
|
|
4434
3858
|
actions.push({
|
|
4435
3859
|
type: "create_directory",
|
|
@@ -4442,7 +3866,7 @@ var genstyleguideInstaller = {
|
|
|
4442
3866
|
});
|
|
4443
3867
|
actions.push({
|
|
4444
3868
|
type: "create_file",
|
|
4445
|
-
path:
|
|
3869
|
+
path: join10(commandsDir, "genstyleguide.md"),
|
|
4446
3870
|
content: GENSTYLEGUIDE_COMMAND_MD
|
|
4447
3871
|
});
|
|
4448
3872
|
return {
|
|
@@ -4471,7 +3895,7 @@ var genstyleguideInstaller = {
|
|
|
4471
3895
|
},
|
|
4472
3896
|
planUninstall(targets, project) {
|
|
4473
3897
|
const actions = [];
|
|
4474
|
-
const commandPath =
|
|
3898
|
+
const commandPath = join10(project.cursorDir.path, "commands", "genstyleguide.md");
|
|
4475
3899
|
actions.push({
|
|
4476
3900
|
type: "delete_file",
|
|
4477
3901
|
path: commandPath
|
|
@@ -4481,8 +3905,8 @@ var genstyleguideInstaller = {
|
|
|
4481
3905
|
};
|
|
4482
3906
|
|
|
4483
3907
|
// src/commands/install/installers/skill.ts
|
|
4484
|
-
import { existsSync as
|
|
4485
|
-
import { join as
|
|
3908
|
+
import { existsSync as existsSync11 } from "fs";
|
|
3909
|
+
import { join as join11 } from "path";
|
|
4486
3910
|
var skillInstaller = {
|
|
4487
3911
|
id: "skill",
|
|
4488
3912
|
name: "UI Consistency Agent skill",
|
|
@@ -4492,9 +3916,9 @@ var skillInstaller = {
|
|
|
4492
3916
|
return true;
|
|
4493
3917
|
},
|
|
4494
3918
|
getTargets(project) {
|
|
4495
|
-
const skillsDir =
|
|
4496
|
-
const skillMdPath =
|
|
4497
|
-
const isInstalled =
|
|
3919
|
+
const skillsDir = join11(project.cursorDir.path, "skills", "ui-consistency-enforcer");
|
|
3920
|
+
const skillMdPath = join11(skillsDir, "SKILL.md");
|
|
3921
|
+
const isInstalled = existsSync11(skillMdPath);
|
|
4498
3922
|
return [
|
|
4499
3923
|
{
|
|
4500
3924
|
id: "ui-consistency-skill",
|
|
@@ -4513,21 +3937,21 @@ var skillInstaller = {
|
|
|
4513
3937
|
path: project.cursorDir.path
|
|
4514
3938
|
});
|
|
4515
3939
|
}
|
|
4516
|
-
const skillsDir =
|
|
3940
|
+
const skillsDir = join11(project.cursorDir.path, "skills");
|
|
4517
3941
|
actions.push({
|
|
4518
3942
|
type: "create_directory",
|
|
4519
3943
|
path: skillsDir
|
|
4520
3944
|
});
|
|
4521
3945
|
try {
|
|
4522
3946
|
const skill = loadSkill("ui-consistency-enforcer");
|
|
4523
|
-
const skillDir =
|
|
3947
|
+
const skillDir = join11(skillsDir, skill.name);
|
|
4524
3948
|
actions.push({
|
|
4525
3949
|
type: "create_directory",
|
|
4526
3950
|
path: skillDir
|
|
4527
3951
|
});
|
|
4528
3952
|
for (const file of skill.files) {
|
|
4529
|
-
const filePath =
|
|
4530
|
-
const fileDir =
|
|
3953
|
+
const filePath = join11(skillDir, file.relativePath);
|
|
3954
|
+
const fileDir = join11(
|
|
4531
3955
|
skillDir,
|
|
4532
3956
|
file.relativePath.split("/").slice(0, -1).join("/")
|
|
4533
3957
|
);
|
|
@@ -4583,7 +4007,7 @@ var skillInstaller = {
|
|
|
4583
4007
|
},
|
|
4584
4008
|
planUninstall(targets, project) {
|
|
4585
4009
|
const actions = [];
|
|
4586
|
-
const skillDir =
|
|
4010
|
+
const skillDir = join11(project.cursorDir.path, "skills", "ui-consistency-enforcer");
|
|
4587
4011
|
actions.push({
|
|
4588
4012
|
type: "remove_directory",
|
|
4589
4013
|
path: skillDir
|
|
@@ -4593,7 +4017,7 @@ var skillInstaller = {
|
|
|
4593
4017
|
};
|
|
4594
4018
|
|
|
4595
4019
|
// src/commands/install/installers/eslint.ts
|
|
4596
|
-
import { join as
|
|
4020
|
+
import { join as join12 } from "path";
|
|
4597
4021
|
import { ruleRegistry as ruleRegistry2, getRulesByCategory as getRulesByCategory2 } from "uilint-eslint";
|
|
4598
4022
|
function getUpgradeInfo(configuredRuleIds) {
|
|
4599
4023
|
const configuredSet = new Set(configuredRuleIds);
|
|
@@ -4769,7 +4193,7 @@ var eslintInstaller = {
|
|
|
4769
4193
|
for (const target of targets) {
|
|
4770
4194
|
const pkgInfo = project.packages.find((p) => p.path === target.path);
|
|
4771
4195
|
if (!pkgInfo || !pkgInfo.eslintConfigPath) continue;
|
|
4772
|
-
const rulesDir =
|
|
4196
|
+
const rulesDir = join12(target.path, ".uilint", "rules");
|
|
4773
4197
|
actions.push({
|
|
4774
4198
|
type: "create_directory",
|
|
4775
4199
|
path: rulesDir
|
|
@@ -4787,7 +4211,7 @@ var eslintInstaller = {
|
|
|
4787
4211
|
hasExistingRules: pkgInfo.hasUilintRules
|
|
4788
4212
|
});
|
|
4789
4213
|
}
|
|
4790
|
-
const gitignorePath =
|
|
4214
|
+
const gitignorePath = join12(project.workspaceRoot, ".gitignore");
|
|
4791
4215
|
actions.push({
|
|
4792
4216
|
type: "append_to_file",
|
|
4793
4217
|
path: gitignorePath,
|
|
@@ -4829,7 +4253,7 @@ var eslintInstaller = {
|
|
|
4829
4253
|
packagePath: target.path,
|
|
4830
4254
|
configPath: pkgInfo.eslintConfigPath
|
|
4831
4255
|
});
|
|
4832
|
-
const rulesDir =
|
|
4256
|
+
const rulesDir = join12(target.path, ".uilint", "rules");
|
|
4833
4257
|
actions.push({
|
|
4834
4258
|
type: "remove_directory",
|
|
4835
4259
|
path: rulesDir
|
|
@@ -4854,8 +4278,7 @@ var viteOverlayInstaller = {
|
|
|
4854
4278
|
label: app.projectPath.split("/").pop() || app.projectPath,
|
|
4855
4279
|
path: app.projectPath,
|
|
4856
4280
|
hint: "React + Vite",
|
|
4857
|
-
isInstalled:
|
|
4858
|
-
// TODO: Detect if already installed
|
|
4281
|
+
isInstalled: app.hasUilintOverlay
|
|
4859
4282
|
}));
|
|
4860
4283
|
},
|
|
4861
4284
|
plan(targets, config, project) {
|
|
@@ -5066,4 +4489,4 @@ async function installUI(options = {}, executeOptions = {}) {
|
|
|
5066
4489
|
export {
|
|
5067
4490
|
installUI
|
|
5068
4491
|
};
|
|
5069
|
-
//# sourceMappingURL=install-ui-
|
|
4492
|
+
//# sourceMappingURL=install-ui-TXV7A34M.js.map
|