uilint 0.2.4 → 0.2.6

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/index.js CHANGED
@@ -1913,6 +1913,35 @@ function hasSpreadProperties(obj) {
1913
1913
  (p2) => p2 && (p2.type === "SpreadElement" || p2.type === "SpreadProperty")
1914
1914
  );
1915
1915
  }
1916
+ var IGNORED_AST_KEYS = /* @__PURE__ */ new Set([
1917
+ "loc",
1918
+ "start",
1919
+ "end",
1920
+ "extra",
1921
+ "leadingComments",
1922
+ "trailingComments",
1923
+ "innerComments"
1924
+ ]);
1925
+ function normalizeAstForCompare(node) {
1926
+ if (node === null) return null;
1927
+ if (node === void 0) return void 0;
1928
+ if (typeof node !== "object") return node;
1929
+ if (Array.isArray(node)) return node.map(normalizeAstForCompare);
1930
+ const out = {};
1931
+ const keys = Object.keys(node).filter((k) => !IGNORED_AST_KEYS.has(k)).sort();
1932
+ for (const k of keys) {
1933
+ if (k.startsWith("$")) continue;
1934
+ out[k] = normalizeAstForCompare(node[k]);
1935
+ }
1936
+ return out;
1937
+ }
1938
+ function astEquivalent(a, b) {
1939
+ try {
1940
+ return JSON.stringify(normalizeAstForCompare(a)) === JSON.stringify(normalizeAstForCompare(b));
1941
+ } catch {
1942
+ return false;
1943
+ }
1944
+ }
1916
1945
  function collectUilintRuleIdsFromRulesObject(rulesObj) {
1917
1946
  const ids = /* @__PURE__ */ new Set();
1918
1947
  if (!rulesObj || rulesObj.type !== "ObjectExpression") return ids;
@@ -2209,8 +2238,46 @@ function extractConfiguredUilintRuleIds(source) {
2209
2238
  function getMissingSelectedRules(selectedRules, configuredIds) {
2210
2239
  return selectedRules.filter((r) => !configuredIds.has(r.id));
2211
2240
  }
2212
- function getRulesNeedingUpdate(selectedRules, configuredIds) {
2213
- return selectedRules.filter((r) => configuredIds.has(r.id));
2241
+ function buildDesiredRuleValueExpression(rule) {
2242
+ if (rule.defaultOptions && rule.defaultOptions.length > 0) {
2243
+ return `["${rule.defaultSeverity}", ...${JSON.stringify(
2244
+ rule.defaultOptions,
2245
+ null,
2246
+ 2
2247
+ )}]`;
2248
+ }
2249
+ return `"${rule.defaultSeverity}"`;
2250
+ }
2251
+ function collectUilintRuleValueNodesFromConfigArray(arrayExpr) {
2252
+ const out = /* @__PURE__ */ new Map();
2253
+ if (!arrayExpr || arrayExpr.type !== "ArrayExpression") return out;
2254
+ for (const el of arrayExpr.elements ?? []) {
2255
+ if (!el || el.type !== "ObjectExpression") continue;
2256
+ const rules = getObjectPropertyValue(el, "rules");
2257
+ if (!rules || rules.type !== "ObjectExpression") continue;
2258
+ for (const prop of rules.properties ?? []) {
2259
+ if (!prop) continue;
2260
+ if (prop.type !== "ObjectProperty" && prop.type !== "Property") continue;
2261
+ const key = prop.key;
2262
+ if (!isStringLiteral(key)) continue;
2263
+ const k = key.value;
2264
+ if (typeof k !== "string" || !k.startsWith("uilint/")) continue;
2265
+ const id = k.slice("uilint/".length);
2266
+ if (!out.has(id)) out.set(id, prop.value);
2267
+ }
2268
+ }
2269
+ return out;
2270
+ }
2271
+ function getRulesNeedingUpdate(selectedRules, configuredIds, arrayExpr) {
2272
+ const existingVals = collectUilintRuleValueNodesFromConfigArray(arrayExpr);
2273
+ return selectedRules.filter((r) => {
2274
+ if (!configuredIds.has(r.id)) return false;
2275
+ const existing = existingVals.get(r.id);
2276
+ if (!existing) return true;
2277
+ const desiredExpr = buildDesiredRuleValueExpression(r);
2278
+ const desiredAst = parseExpression(desiredExpr).$ast;
2279
+ return !astEquivalent(existing, desiredAst);
2280
+ });
2214
2281
  }
2215
2282
  async function installEslintPlugin(opts) {
2216
2283
  const configPath = findEslintConfigFile(opts.projectPath);
@@ -2243,7 +2310,8 @@ async function installEslintPlugin(opts) {
2243
2310
  );
2244
2311
  const rulesToUpdate = getRulesNeedingUpdate(
2245
2312
  opts.selectedRules,
2246
- configuredIds
2313
+ configuredIds,
2314
+ arrayExpr
2247
2315
  );
2248
2316
  let rulesToApply = [];
2249
2317
  if (!info.configured) {
@@ -2923,10 +2991,34 @@ import { createRequire } from "module";
2923
2991
  var __filename2 = fileURLToPath3(import.meta.url);
2924
2992
  var __dirname2 = dirname8(__filename2);
2925
2993
  var require2 = createRequire(import.meta.url);
2994
+ function findNodeModulesPackageRoot(pkgName, startDir) {
2995
+ let dir = startDir;
2996
+ while (true) {
2997
+ const candidate = join10(dir, "node_modules", pkgName);
2998
+ if (existsSync11(join10(candidate, "package.json"))) return candidate;
2999
+ const parent = dirname8(dir);
3000
+ if (parent === dir) break;
3001
+ dir = parent;
3002
+ }
3003
+ return null;
3004
+ }
2926
3005
  function getUilintEslintPackageRoot() {
2927
- const entry = require2.resolve("uilint-eslint");
2928
- const entryDir = dirname8(entry);
2929
- return dirname8(entryDir);
3006
+ const fromCwd = findNodeModulesPackageRoot("uilint-eslint", process.cwd());
3007
+ if (fromCwd) return fromCwd;
3008
+ const fromHere = findNodeModulesPackageRoot("uilint-eslint", __dirname2);
3009
+ if (fromHere) return fromHere;
3010
+ try {
3011
+ const entry = require2.resolve("uilint-eslint");
3012
+ const entryDir = dirname8(entry);
3013
+ return dirname8(entryDir);
3014
+ } catch (e) {
3015
+ const msg = e instanceof Error ? e.message : String(e);
3016
+ throw new Error(
3017
+ `Unable to locate uilint-eslint in node_modules (searched upwards from cwd and uilint's install path).
3018
+ Resolver error: ${msg}
3019
+ Fix: ensure uilint-eslint is installed in the target project (or workspace) and try again.`
3020
+ );
3021
+ }
2930
3022
  }
2931
3023
  function getUilintEslintSrcDir() {
2932
3024
  const devPath = join10(
@@ -3016,7 +3108,7 @@ function loadRule(ruleId, options = { typescript: true }) {
3016
3108
  const implPath = join10(rulesDir, `${ruleId}.js`);
3017
3109
  if (!existsSync11(implPath)) {
3018
3110
  throw new Error(
3019
- `Rule "${ruleId}" not found at ${implPath}. Make sure uilint-eslint has been built.`
3111
+ `Rule "${ruleId}" not found at ${implPath}. For JavaScript-only projects, uilint-eslint must be built to include compiled rule files in dist/rules/. If you're developing uilint-eslint, run 'pnpm build' in packages/uilint-eslint. If you're using a published package, ensure it includes the dist/ directory.`
3020
3112
  );
3021
3113
  }
3022
3114
  const content = readFileSync7(implPath, "utf-8");
@@ -3264,28 +3356,25 @@ function createPlan(state, choices, options = {}) {
3264
3356
  path: rulesDir
3265
3357
  });
3266
3358
  const isTypeScript = pkgInfo?.isTypeScript ?? true;
3267
- try {
3268
- const ruleFiles = loadSelectedRules(
3269
- selectedRules.map((r) => r.id),
3270
- {
3271
- typescript: isTypeScript
3272
- }
3273
- );
3274
- for (const ruleFile of ruleFiles) {
3359
+ const ruleFiles = loadSelectedRules(
3360
+ selectedRules.map((r) => r.id),
3361
+ {
3362
+ typescript: isTypeScript
3363
+ }
3364
+ );
3365
+ for (const ruleFile of ruleFiles) {
3366
+ actions.push({
3367
+ type: "create_file",
3368
+ path: join11(rulesDir, ruleFile.implementation.relativePath),
3369
+ content: ruleFile.implementation.content
3370
+ });
3371
+ if (ruleFile.test && isTypeScript) {
3275
3372
  actions.push({
3276
3373
  type: "create_file",
3277
- path: join11(rulesDir, ruleFile.implementation.relativePath),
3278
- content: ruleFile.implementation.content
3374
+ path: join11(rulesDir, ruleFile.test.relativePath),
3375
+ content: ruleFile.test.content
3279
3376
  });
3280
- if (ruleFile.test && isTypeScript) {
3281
- actions.push({
3282
- type: "create_file",
3283
- path: join11(rulesDir, ruleFile.test.relativePath),
3284
- content: ruleFile.test.content
3285
- });
3286
- }
3287
3377
  }
3288
- } catch {
3289
3378
  }
3290
3379
  dependencies.push({
3291
3380
  packagePath: pkgPath,