@yawlabs/ctxlint 0.9.6 → 0.9.7
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 +247 -77
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -34322,29 +34322,24 @@ async function scanForContextFiles(projectRoot, options = {}) {
|
|
|
34322
34322
|
}
|
|
34323
34323
|
}
|
|
34324
34324
|
collectDirs(projectRoot, 0);
|
|
34325
|
-
|
|
34326
|
-
|
|
34327
|
-
|
|
34328
|
-
|
|
34329
|
-
|
|
34330
|
-
|
|
34331
|
-
|
|
34325
|
+
const perDirMatches = await Promise.all(
|
|
34326
|
+
dirsToScan.map((dir) => Ze(patterns, { cwd: dir, absolute: true, nodir: true, dot: true }))
|
|
34327
|
+
);
|
|
34328
|
+
for (const matches of perDirMatches) {
|
|
34329
|
+
for (const match of matches) {
|
|
34330
|
+
const normalized = path2.normalize(match);
|
|
34331
|
+
if (seen.has(normalized)) continue;
|
|
34332
|
+
seen.add(normalized);
|
|
34333
|
+
const relativePath = path2.relative(projectRoot, normalized);
|
|
34334
|
+
const symlink = isSymlink(normalized);
|
|
34335
|
+
const target = symlink ? readSymlinkTarget(normalized) : void 0;
|
|
34336
|
+
found.push({
|
|
34337
|
+
absolutePath: normalized,
|
|
34338
|
+
relativePath: relativePath.replace(/\\/g, "/"),
|
|
34339
|
+
isSymlink: symlink,
|
|
34340
|
+
symlinkTarget: target,
|
|
34341
|
+
type: "context"
|
|
34332
34342
|
});
|
|
34333
|
-
for (const match of matches) {
|
|
34334
|
-
const normalized = path2.normalize(match);
|
|
34335
|
-
if (seen.has(normalized)) continue;
|
|
34336
|
-
seen.add(normalized);
|
|
34337
|
-
const relativePath = path2.relative(projectRoot, normalized);
|
|
34338
|
-
const symlink = isSymlink(normalized);
|
|
34339
|
-
const target = symlink ? readSymlinkTarget(normalized) : void 0;
|
|
34340
|
-
found.push({
|
|
34341
|
-
absolutePath: normalized,
|
|
34342
|
-
relativePath: relativePath.replace(/\\/g, "/"),
|
|
34343
|
-
isSymlink: symlink,
|
|
34344
|
-
symlinkTarget: target,
|
|
34345
|
-
type: "context"
|
|
34346
|
-
});
|
|
34347
|
-
}
|
|
34348
34343
|
}
|
|
34349
34344
|
}
|
|
34350
34345
|
return found.sort((a, b2) => a.relativePath.localeCompare(b2.relativePath));
|
|
@@ -40501,17 +40496,54 @@ async function getFileLastModified(projectRoot, filePath) {
|
|
|
40501
40496
|
return null;
|
|
40502
40497
|
}
|
|
40503
40498
|
}
|
|
40504
|
-
async function
|
|
40499
|
+
async function getCommitsSinceBatch(projectRoot, paths, since) {
|
|
40500
|
+
const counts = /* @__PURE__ */ new Map();
|
|
40501
|
+
for (const p2 of paths) counts.set(p2, 0);
|
|
40502
|
+
if (paths.length === 0) return counts;
|
|
40505
40503
|
try {
|
|
40506
40504
|
const git = getGit(projectRoot);
|
|
40507
|
-
const
|
|
40508
|
-
|
|
40509
|
-
"
|
|
40510
|
-
|
|
40511
|
-
|
|
40505
|
+
const SENTINEL = "___CTXLINT_COMMIT___";
|
|
40506
|
+
const raw = await git.raw([
|
|
40507
|
+
"log",
|
|
40508
|
+
`--since=${since.toISOString()}`,
|
|
40509
|
+
"--name-only",
|
|
40510
|
+
`--format=${SENTINEL}`
|
|
40511
|
+
]);
|
|
40512
|
+
const normalize3 = (p2) => p2.replace(/\\/g, "/");
|
|
40513
|
+
const requested = new Set(paths.map(normalize3));
|
|
40514
|
+
const lines = raw.split("\n");
|
|
40515
|
+
let inCommit = false;
|
|
40516
|
+
const seenThisCommit = /* @__PURE__ */ new Set();
|
|
40517
|
+
const flush = () => {
|
|
40518
|
+
for (const p2 of seenThisCommit) {
|
|
40519
|
+
counts.set(p2, (counts.get(p2) ?? 0) + 1);
|
|
40520
|
+
}
|
|
40521
|
+
seenThisCommit.clear();
|
|
40522
|
+
};
|
|
40523
|
+
for (const line of lines) {
|
|
40524
|
+
if (line === SENTINEL) {
|
|
40525
|
+
if (inCommit) flush();
|
|
40526
|
+
inCommit = true;
|
|
40527
|
+
continue;
|
|
40528
|
+
}
|
|
40529
|
+
if (!inCommit) continue;
|
|
40530
|
+
const trimmed2 = line.trim();
|
|
40531
|
+
if (!trimmed2) continue;
|
|
40532
|
+
const changed = normalize3(trimmed2);
|
|
40533
|
+
for (const req of requested) {
|
|
40534
|
+
if (changed === req || changed.startsWith(req.endsWith("/") ? req : req + "/")) {
|
|
40535
|
+
seenThisCommit.add(req);
|
|
40536
|
+
}
|
|
40537
|
+
}
|
|
40538
|
+
}
|
|
40539
|
+
if (inCommit) flush();
|
|
40512
40540
|
} catch {
|
|
40513
|
-
return 0;
|
|
40514
40541
|
}
|
|
40542
|
+
const out = /* @__PURE__ */ new Map();
|
|
40543
|
+
for (const p2 of paths) {
|
|
40544
|
+
out.set(p2, counts.get(p2.replace(/\\/g, "/")) ?? 0);
|
|
40545
|
+
}
|
|
40546
|
+
return out;
|
|
40515
40547
|
}
|
|
40516
40548
|
async function findRenames(projectRoot, filePath) {
|
|
40517
40549
|
try {
|
|
@@ -40853,7 +40885,7 @@ var require_levenshtein = __commonJS({
|
|
|
40853
40885
|
} catch (err) {
|
|
40854
40886
|
console.log("Collator could not be initialized and wouldn't be used");
|
|
40855
40887
|
}
|
|
40856
|
-
var
|
|
40888
|
+
var levenshtein3 = require_mod();
|
|
40857
40889
|
var prevRow = [], str2Char = [];
|
|
40858
40890
|
var Levenshtein = {
|
|
40859
40891
|
/**
|
|
@@ -40898,7 +40930,7 @@ var require_levenshtein = __commonJS({
|
|
|
40898
40930
|
}
|
|
40899
40931
|
return nextCol;
|
|
40900
40932
|
}
|
|
40901
|
-
return
|
|
40933
|
+
return levenshtein3.distance(str1, str2);
|
|
40902
40934
|
}
|
|
40903
40935
|
};
|
|
40904
40936
|
if (typeof define !== "undefined" && define !== null && define.amd) {
|
|
@@ -41193,11 +41225,14 @@ async function checkStaleness(file2, projectRoot) {
|
|
|
41193
41225
|
for (const ref of file2.references.paths) {
|
|
41194
41226
|
referencedPaths.add(ref.value);
|
|
41195
41227
|
}
|
|
41228
|
+
if (referencedPaths.size === 0) {
|
|
41229
|
+
return issues;
|
|
41230
|
+
}
|
|
41231
|
+
const counts = await getCommitsSinceBatch(projectRoot, [...referencedPaths], lastModified);
|
|
41196
41232
|
let totalCommits = 0;
|
|
41197
41233
|
let mostActiveRef = "";
|
|
41198
41234
|
let mostActiveCommits = 0;
|
|
41199
|
-
for (const refPath of
|
|
41200
|
-
const commits = await getCommitsSince(projectRoot, refPath, lastModified);
|
|
41235
|
+
for (const [refPath, commits] of counts) {
|
|
41201
41236
|
totalCommits += commits;
|
|
41202
41237
|
if (commits > mostActiveCommits) {
|
|
41203
41238
|
mostActiveCommits = commits;
|
|
@@ -41688,54 +41723,88 @@ function detectDirectives(file2) {
|
|
|
41688
41723
|
function checkContradictions(files) {
|
|
41689
41724
|
if (files.length < 2) return [];
|
|
41690
41725
|
const issues = [];
|
|
41691
|
-
const allDirectives = [];
|
|
41692
|
-
for (const file2 of files) {
|
|
41693
|
-
allDirectives.push(...detectDirectives(file2));
|
|
41694
|
-
}
|
|
41695
41726
|
const byCategory = /* @__PURE__ */ new Map();
|
|
41696
|
-
|
|
41697
|
-
|
|
41698
|
-
|
|
41699
|
-
|
|
41727
|
+
const directiveIndex = /* @__PURE__ */ new Map();
|
|
41728
|
+
for (const file2 of files) {
|
|
41729
|
+
for (const d of detectDirectives(file2)) {
|
|
41730
|
+
let list = byCategory.get(d.category);
|
|
41731
|
+
if (!list) {
|
|
41732
|
+
list = [];
|
|
41733
|
+
byCategory.set(d.category, list);
|
|
41734
|
+
}
|
|
41735
|
+
list.push(d);
|
|
41736
|
+
let idx = directiveIndex.get(d.category);
|
|
41737
|
+
if (!idx) {
|
|
41738
|
+
idx = /* @__PURE__ */ new Map();
|
|
41739
|
+
directiveIndex.set(d.category, idx);
|
|
41740
|
+
}
|
|
41741
|
+
const key = `${d.file}::${d.label}`;
|
|
41742
|
+
if (!idx.has(key)) idx.set(key, d);
|
|
41743
|
+
}
|
|
41700
41744
|
}
|
|
41701
41745
|
for (const [category, directives] of byCategory) {
|
|
41702
|
-
const byFile = /* @__PURE__ */ new Map();
|
|
41703
|
-
for (const d of directives) {
|
|
41704
|
-
const existing = byFile.get(d.file) || [];
|
|
41705
|
-
existing.push(d);
|
|
41706
|
-
byFile.set(d.file, existing);
|
|
41707
|
-
}
|
|
41708
41746
|
const labels = new Set(directives.map((d) => d.label));
|
|
41709
41747
|
if (labels.size <= 1) continue;
|
|
41710
41748
|
const fileLabels = /* @__PURE__ */ new Map();
|
|
41711
41749
|
for (const d of directives) {
|
|
41712
|
-
|
|
41750
|
+
let existing = fileLabels.get(d.file);
|
|
41751
|
+
if (!existing) {
|
|
41752
|
+
existing = /* @__PURE__ */ new Set();
|
|
41753
|
+
fileLabels.set(d.file, existing);
|
|
41754
|
+
}
|
|
41713
41755
|
existing.add(d.label);
|
|
41714
|
-
|
|
41715
|
-
|
|
41716
|
-
|
|
41717
|
-
|
|
41718
|
-
|
|
41719
|
-
const
|
|
41720
|
-
|
|
41721
|
-
|
|
41722
|
-
|
|
41723
|
-
|
|
41724
|
-
|
|
41725
|
-
|
|
41726
|
-
|
|
41727
|
-
|
|
41728
|
-
|
|
41729
|
-
|
|
41730
|
-
|
|
41731
|
-
|
|
41732
|
-
|
|
41733
|
-
|
|
41734
|
-
|
|
41735
|
-
|
|
41736
|
-
|
|
41756
|
+
}
|
|
41757
|
+
const conflictingFiles = [...fileLabels.keys()].filter((f) => {
|
|
41758
|
+
const myLabels = fileLabels.get(f);
|
|
41759
|
+
for (const [otherFile, otherLabels] of fileLabels) {
|
|
41760
|
+
if (otherFile === f) continue;
|
|
41761
|
+
for (const l of myLabels) {
|
|
41762
|
+
if (!otherLabels.has(l)) return true;
|
|
41763
|
+
}
|
|
41764
|
+
}
|
|
41765
|
+
return false;
|
|
41766
|
+
});
|
|
41767
|
+
if (conflictingFiles.length < 2) continue;
|
|
41768
|
+
const idx = directiveIndex.get(category);
|
|
41769
|
+
if (conflictingFiles.length === 2) {
|
|
41770
|
+
const [fileA, fileB] = conflictingFiles;
|
|
41771
|
+
const labelsA = fileLabels.get(fileA);
|
|
41772
|
+
const labelsB = fileLabels.get(fileB);
|
|
41773
|
+
for (const labelA of labelsA) {
|
|
41774
|
+
for (const labelB of labelsB) {
|
|
41775
|
+
if (labelA === labelB) continue;
|
|
41776
|
+
const directiveA = idx.get(`${fileA}::${labelA}`);
|
|
41777
|
+
const directiveB = idx.get(`${fileB}::${labelB}`);
|
|
41778
|
+
issues.push({
|
|
41779
|
+
severity: "warning",
|
|
41780
|
+
check: "contradictions",
|
|
41781
|
+
ruleId: "contradictions/conflict",
|
|
41782
|
+
line: directiveA.line,
|
|
41783
|
+
message: `${category} conflict: "${directiveA.label}" in ${fileA} vs "${directiveB.label}" in ${fileB}`,
|
|
41784
|
+
suggestion: `Align on one ${category} across all context files`,
|
|
41785
|
+
detail: `${fileA}:${directiveA.line} says "${directiveA.text}" but ${fileB}:${directiveB.line} says "${directiveB.text}"`
|
|
41786
|
+
});
|
|
41737
41787
|
}
|
|
41738
41788
|
}
|
|
41789
|
+
} else {
|
|
41790
|
+
const entries = [];
|
|
41791
|
+
for (const f of conflictingFiles) {
|
|
41792
|
+
for (const l of fileLabels.get(f)) {
|
|
41793
|
+
entries.push(idx.get(`${f}::${l}`));
|
|
41794
|
+
}
|
|
41795
|
+
}
|
|
41796
|
+
const firstEntry = entries[0];
|
|
41797
|
+
const summary = entries.map((e) => `"${e.label}" in ${e.file}`).join(", ");
|
|
41798
|
+
const detail = entries.map((e) => `${e.file}:${e.line} says "${e.text}"`).join("\n");
|
|
41799
|
+
issues.push({
|
|
41800
|
+
severity: "warning",
|
|
41801
|
+
check: "contradictions",
|
|
41802
|
+
ruleId: "contradictions/conflict",
|
|
41803
|
+
line: firstEntry.line,
|
|
41804
|
+
message: `${category} conflict across ${conflictingFiles.length} files: ${summary}`,
|
|
41805
|
+
suggestion: `Align on one ${category} across all context files`,
|
|
41806
|
+
detail
|
|
41807
|
+
});
|
|
41739
41808
|
}
|
|
41740
41809
|
}
|
|
41741
41810
|
return issues;
|
|
@@ -42413,6 +42482,7 @@ async function checkMcpCommands(config2, projectRoot) {
|
|
|
42413
42482
|
}
|
|
42414
42483
|
if (server2.args) {
|
|
42415
42484
|
for (const arg of server2.args) {
|
|
42485
|
+
if (URL_PREFIX.test(arg)) continue;
|
|
42416
42486
|
if (LOCAL_PATH_PATTERN.test(arg) || FILE_PATH_PATTERN.test(arg)) {
|
|
42417
42487
|
const resolved = path8.resolve(projectRoot, arg);
|
|
42418
42488
|
if (!fileExistsSafe(resolved)) {
|
|
@@ -42438,12 +42508,13 @@ function fileExistsSafe(filePath) {
|
|
|
42438
42508
|
return false;
|
|
42439
42509
|
}
|
|
42440
42510
|
}
|
|
42441
|
-
var LOCAL_PATH_PATTERN, FILE_PATH_PATTERN;
|
|
42511
|
+
var LOCAL_PATH_PATTERN, FILE_PATH_PATTERN, URL_PREFIX;
|
|
42442
42512
|
var init_commands2 = __esm({
|
|
42443
42513
|
"src/core/checks/mcp/commands.ts"() {
|
|
42444
42514
|
"use strict";
|
|
42445
42515
|
LOCAL_PATH_PATTERN = /^\.\.?\//;
|
|
42446
42516
|
FILE_PATH_PATTERN = /^[^-].*\/.*\.\w+$/;
|
|
42517
|
+
URL_PREFIX = /^(https?|file|s3|gs|ssh|git):\/\//i;
|
|
42447
42518
|
}
|
|
42448
42519
|
});
|
|
42449
42520
|
|
|
@@ -43766,7 +43837,7 @@ import { readFileSync as readFileSync4 } from "node:fs";
|
|
|
43766
43837
|
import { resolve as resolve8, dirname as dirname3 } from "node:path";
|
|
43767
43838
|
import { fileURLToPath } from "node:url";
|
|
43768
43839
|
function loadVersion() {
|
|
43769
|
-
if (true) return "0.9.
|
|
43840
|
+
if (true) return "0.9.7";
|
|
43770
43841
|
const __dir = dirname3(fileURLToPath(import.meta.url));
|
|
43771
43842
|
const pkgPath = resolve8(__dir, "../package.json");
|
|
43772
43843
|
const pkg = JSON.parse(readFileSync4(pkgPath, "utf-8"));
|
|
@@ -44597,6 +44668,7 @@ function applyFixes(result, options = {}) {
|
|
|
44597
44668
|
}
|
|
44598
44669
|
}
|
|
44599
44670
|
const fixesByFile = /* @__PURE__ */ new Map();
|
|
44671
|
+
const dedupeKeys = /* @__PURE__ */ new Map();
|
|
44600
44672
|
const skippedSymlinks = /* @__PURE__ */ new Set();
|
|
44601
44673
|
for (const file2 of result.files) {
|
|
44602
44674
|
for (const issue2 of file2.issues) {
|
|
@@ -44605,6 +44677,14 @@ function applyFixes(result, options = {}) {
|
|
|
44605
44677
|
skippedSymlinks.add(file2.path);
|
|
44606
44678
|
continue;
|
|
44607
44679
|
}
|
|
44680
|
+
const key = `${issue2.fix.line}:${issue2.fix.oldText}:${issue2.fix.newText}`;
|
|
44681
|
+
let seenInFile = dedupeKeys.get(issue2.fix.file);
|
|
44682
|
+
if (!seenInFile) {
|
|
44683
|
+
seenInFile = /* @__PURE__ */ new Set();
|
|
44684
|
+
dedupeKeys.set(issue2.fix.file, seenInFile);
|
|
44685
|
+
}
|
|
44686
|
+
if (seenInFile.has(key)) continue;
|
|
44687
|
+
seenInFile.add(key);
|
|
44608
44688
|
const existing = fixesByFile.get(issue2.fix.file) || [];
|
|
44609
44689
|
existing.push(issue2.fix);
|
|
44610
44690
|
fixesByFile.set(issue2.fix.file, existing);
|
|
@@ -51751,6 +51831,76 @@ var init_reporter = __esm({
|
|
|
51751
51831
|
// src/core/config.ts
|
|
51752
51832
|
import * as fs8 from "node:fs";
|
|
51753
51833
|
import * as path10 from "node:path";
|
|
51834
|
+
function formatJsonError(content, err) {
|
|
51835
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
51836
|
+
const posMatch = msg.match(/position (\d+)/);
|
|
51837
|
+
if (posMatch) {
|
|
51838
|
+
return `${msg} (${posToLineCol(content, Number(posMatch[1]))})`;
|
|
51839
|
+
}
|
|
51840
|
+
if (/line \d+/.test(msg)) return msg;
|
|
51841
|
+
const pos = findFirstErrorPos(content, msg);
|
|
51842
|
+
if (pos !== null) {
|
|
51843
|
+
return `${msg} (${posToLineCol(content, pos)})`;
|
|
51844
|
+
}
|
|
51845
|
+
return msg;
|
|
51846
|
+
}
|
|
51847
|
+
function posToLineCol(content, pos) {
|
|
51848
|
+
let line = 1;
|
|
51849
|
+
let col = 1;
|
|
51850
|
+
for (let i2 = 0; i2 < pos && i2 < content.length; i2++) {
|
|
51851
|
+
if (content[i2] === "\n") {
|
|
51852
|
+
line++;
|
|
51853
|
+
col = 1;
|
|
51854
|
+
} else {
|
|
51855
|
+
col++;
|
|
51856
|
+
}
|
|
51857
|
+
}
|
|
51858
|
+
return `line ${line}, column ${col}`;
|
|
51859
|
+
}
|
|
51860
|
+
function findFirstErrorPos(content, errMsg) {
|
|
51861
|
+
const snippetMatch = errMsg.match(/\.\.\."([^"]+(?:"[^"]*)*?)"\s+is not valid JSON/);
|
|
51862
|
+
if (snippetMatch) {
|
|
51863
|
+
const snippet = snippetMatch[1];
|
|
51864
|
+
const needle = snippet.split(/\s/).find((s) => s.length > 1);
|
|
51865
|
+
if (needle) {
|
|
51866
|
+
const idx = content.indexOf(needle);
|
|
51867
|
+
if (idx !== -1) return idx;
|
|
51868
|
+
}
|
|
51869
|
+
}
|
|
51870
|
+
const tokenMatch = errMsg.match(/Unexpected token\s+['"]?([^'",]+?)['"]?,/);
|
|
51871
|
+
if (tokenMatch) {
|
|
51872
|
+
const tok = tokenMatch[1];
|
|
51873
|
+
const idx = content.indexOf(tok);
|
|
51874
|
+
if (idx !== -1) return idx;
|
|
51875
|
+
}
|
|
51876
|
+
return null;
|
|
51877
|
+
}
|
|
51878
|
+
function suggestKey(unknown2) {
|
|
51879
|
+
let best = null;
|
|
51880
|
+
let bestDist = Infinity;
|
|
51881
|
+
for (const known of KNOWN_CONFIG_KEYS) {
|
|
51882
|
+
const d = levenshtein2(unknown2, known);
|
|
51883
|
+
if (d < bestDist) {
|
|
51884
|
+
bestDist = d;
|
|
51885
|
+
best = known;
|
|
51886
|
+
}
|
|
51887
|
+
}
|
|
51888
|
+
if (best && bestDist <= Math.max(2, Math.floor(unknown2.length / 3))) {
|
|
51889
|
+
return best;
|
|
51890
|
+
}
|
|
51891
|
+
return null;
|
|
51892
|
+
}
|
|
51893
|
+
function warnUnknownKeys(config2, source) {
|
|
51894
|
+
if (!config2 || typeof config2 !== "object" || Array.isArray(config2)) return;
|
|
51895
|
+
const keys = Object.keys(config2);
|
|
51896
|
+
const known = new Set(KNOWN_CONFIG_KEYS);
|
|
51897
|
+
for (const k3 of keys) {
|
|
51898
|
+
if (known.has(k3)) continue;
|
|
51899
|
+
const hint = suggestKey(k3);
|
|
51900
|
+
const suggestion = hint ? ` \u2014 did you mean "${hint}"?` : "";
|
|
51901
|
+
console.error(`Warning: unknown config key "${k3}" in ${source}${suggestion}`);
|
|
51902
|
+
}
|
|
51903
|
+
}
|
|
51754
51904
|
function loadConfig(projectRoot) {
|
|
51755
51905
|
for (const filename of CONFIG_FILENAMES) {
|
|
51756
51906
|
const filePath = path10.join(projectRoot, filename);
|
|
@@ -51760,19 +51910,39 @@ function loadConfig(projectRoot) {
|
|
|
51760
51910
|
} catch {
|
|
51761
51911
|
continue;
|
|
51762
51912
|
}
|
|
51913
|
+
let parsed;
|
|
51763
51914
|
try {
|
|
51764
|
-
|
|
51915
|
+
parsed = JSON.parse(content);
|
|
51765
51916
|
} catch (err) {
|
|
51766
|
-
|
|
51767
|
-
|
|
51917
|
+
throw new Error(`Invalid JSON in ${filePath}: ${formatJsonError(content, err)}`, {
|
|
51918
|
+
cause: err
|
|
51919
|
+
});
|
|
51768
51920
|
}
|
|
51921
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
51922
|
+
throw new Error(
|
|
51923
|
+
`Invalid config in ${filePath}: expected a JSON object at the root, got ${Array.isArray(parsed) ? "an array" : typeof parsed}`
|
|
51924
|
+
);
|
|
51925
|
+
}
|
|
51926
|
+
warnUnknownKeys(parsed, filePath);
|
|
51927
|
+
return parsed;
|
|
51769
51928
|
}
|
|
51770
51929
|
return null;
|
|
51771
51930
|
}
|
|
51772
|
-
var CONFIG_FILENAMES;
|
|
51931
|
+
var import_fast_levenshtein2, levenshtein2, KNOWN_CONFIG_KEYS, CONFIG_FILENAMES;
|
|
51773
51932
|
var init_config2 = __esm({
|
|
51774
51933
|
"src/core/config.ts"() {
|
|
51775
51934
|
"use strict";
|
|
51935
|
+
import_fast_levenshtein2 = __toESM(require_levenshtein(), 1);
|
|
51936
|
+
levenshtein2 = import_fast_levenshtein2.default.get;
|
|
51937
|
+
KNOWN_CONFIG_KEYS = [
|
|
51938
|
+
"checks",
|
|
51939
|
+
"ignore",
|
|
51940
|
+
"strict",
|
|
51941
|
+
"tokenThresholds",
|
|
51942
|
+
"contextFiles",
|
|
51943
|
+
"mcp",
|
|
51944
|
+
"mcpGlobal"
|
|
51945
|
+
];
|
|
51776
51946
|
CONFIG_FILENAMES = [".ctxlintrc", ".ctxlintrc.json"];
|
|
51777
51947
|
}
|
|
51778
51948
|
});
|