cspell 9.3.2 → 9.6.0
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/README.md +13 -7
- package/dist/cjs/commonJsApi.cjs +8 -0
- package/dist/cjs/commonJsApi.d.cts +2 -0
- package/dist/esm/app.d.ts +1 -1
- package/dist/esm/app.js +39 -335
- package/dist/esm/{application-CGIx5L0D.js → application-BJHh60xM.js} +886 -239
- package/dist/esm/{application-B84gvlDU.d.ts → application-Ce_s5c1d.d.ts} +2 -2
- package/dist/esm/application.d.ts +2 -2
- package/dist/esm/application.js +1 -1
- package/dist/esm/index.d.ts +3 -3
- package/dist/esm/index.js +1 -1
- package/dist/esm/{options-BeJCICDB.d.ts → options-D_PtlSKK.d.ts} +12 -1
- package/package.json +20 -17
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
|
-
import chalk, { Chalk } from "chalk";
|
|
3
2
|
import { isAsyncIterable, opFilter, opMap, opTap, operators, pipeAsync, pipeAsync as asyncPipe, toAsyncIterable, toAsyncIterable as mergeAsyncIterables } from "@cspell/cspell-pipe";
|
|
4
3
|
import * as cspell from "cspell-lib";
|
|
5
|
-
import { ENV_CSPELL_GLOB_ROOT, IncludeExcludeFlag, SuggestionError, Text, checkTextDocument, combineTextAndLanguageSettings, createPerfTimer, extractDependencies, extractImportErrors, fileToDocument, getDefaultSettings, getDictionary, getGlobalSettingsAsync, getSystemFeatureFlags, isBinaryFile, isSpellingDictionaryLoadError, mergeSettings, setLogger, shouldCheckDocument, spellCheckDocument, suggestionsForWords, traceWordsAsync } from "cspell-lib";
|
|
4
|
+
import { ENV_CSPELL_GLOB_ROOT, IncludeExcludeFlag, MessageTypes, SuggestionError, Text, checkTextDocument, combineTextAndLanguageSettings, createPerfTimer, extractDependencies, extractImportErrors, fileToDocument, getDefaultSettings, getDictionary, getGlobalSettingsAsync, getSystemFeatureFlags, isBinaryFile, isSpellingDictionaryLoadError, mergeSettings, setLogger, shouldCheckDocument, spellCheckDocument, suggestionsForWords, traceWordsAsync } from "cspell-lib";
|
|
6
5
|
import assert from "node:assert";
|
|
7
|
-
import { format, formatWithOptions } from "node:util";
|
|
6
|
+
import { format, formatWithOptions, stripVTControlCharacters } from "node:util";
|
|
8
7
|
import { isUrlLike, toFileDirURL, toFilePathOrHref, toFileURL, urlRelative } from "@cspell/url";
|
|
8
|
+
import chalk, { Chalk } from "chalk";
|
|
9
9
|
import { makeTemplate } from "chalk-template";
|
|
10
|
+
import ansiRegex from "ansi-regex";
|
|
10
11
|
import fs, { stat } from "node:fs/promises";
|
|
11
12
|
import { MutableCSpellConfigFile, createReaderWriter, cspellConfigFileSchema, isCfgArrayNode } from "cspell-config-lib";
|
|
12
13
|
import { promises } from "node:fs";
|
|
@@ -14,13 +15,13 @@ import { fileURLToPath } from "node:url";
|
|
|
14
15
|
import * as path$1 from "node:path";
|
|
15
16
|
import path, { isAbsolute, posix, relative, resolve, sep } from "node:path";
|
|
16
17
|
import { opMap as opMap$1, pipe } from "@cspell/cspell-pipe/sync";
|
|
17
|
-
import { IssueType, MessageTypes, unknownWordsChoices } from "@cspell/cspell-types";
|
|
18
|
-
import {
|
|
18
|
+
import { IssueType, MessageTypes as MessageTypes$1, unknownWordsChoices } from "@cspell/cspell-types";
|
|
19
|
+
import { dictionaryCacheEnableLogging, dictionaryCacheGetLog } from "cspell-dictionary";
|
|
19
20
|
import { GitIgnore, findRepoRoot } from "cspell-gitignore";
|
|
20
21
|
import { GlobMatcher, fileOrGlobToGlob, workaroundPicomatchBug } from "cspell-glob";
|
|
21
22
|
import crypto from "node:crypto";
|
|
22
23
|
import streamConsumers from "node:stream/consumers";
|
|
23
|
-
import { readFileText, toURL } from "cspell-io";
|
|
24
|
+
import { getStat, readFileText, toURL } from "cspell-io";
|
|
24
25
|
import { glob } from "tinyglobby";
|
|
25
26
|
import * as readline from "node:readline";
|
|
26
27
|
import { parse, stringify } from "flatted";
|
|
@@ -88,7 +89,7 @@ var IOError = class extends ApplicationError {
|
|
|
88
89
|
return this.cause.code === "ENOENT";
|
|
89
90
|
}
|
|
90
91
|
};
|
|
91
|
-
function toError(e) {
|
|
92
|
+
function toError$1(e) {
|
|
92
93
|
if (isError(e)) return e;
|
|
93
94
|
if (isErrorLike(e)) {
|
|
94
95
|
const ex = new Error(e.message, { cause: e });
|
|
@@ -108,10 +109,349 @@ function isErrorLike(e) {
|
|
|
108
109
|
}
|
|
109
110
|
function toApplicationError(e, message) {
|
|
110
111
|
if (e instanceof ApplicationError && !message) return e;
|
|
111
|
-
const err = toError(e);
|
|
112
|
+
const err = toError$1(e);
|
|
112
113
|
return new ApplicationError(message ?? err.message, void 0, err);
|
|
113
114
|
}
|
|
114
115
|
|
|
116
|
+
//#endregion
|
|
117
|
+
//#region src/util/perfMeasurements.ts
|
|
118
|
+
function getPerfMeasurements() {
|
|
119
|
+
const measurements = performance.getEntriesByType("measure");
|
|
120
|
+
const root = {
|
|
121
|
+
depth: -1,
|
|
122
|
+
totalTimeMs: 0,
|
|
123
|
+
nestedTimeMs: 0,
|
|
124
|
+
children: /* @__PURE__ */ new Map()
|
|
125
|
+
};
|
|
126
|
+
if (!measurements.length) return [];
|
|
127
|
+
const stack = [];
|
|
128
|
+
let depth = 0;
|
|
129
|
+
for (let i = 0; i < measurements.length; i++) {
|
|
130
|
+
const m = measurements[i];
|
|
131
|
+
rollUpStack(m.startTime);
|
|
132
|
+
const s = {
|
|
133
|
+
m,
|
|
134
|
+
p: addToParent(depth === 0 ? root : stack[depth - 1].p, m)
|
|
135
|
+
};
|
|
136
|
+
stack[depth++] = s;
|
|
137
|
+
}
|
|
138
|
+
sortChildren(root);
|
|
139
|
+
return [...root.children.values()].flatMap((r) => [...flattenChildren(r)]);
|
|
140
|
+
function contains(m, t) {
|
|
141
|
+
const stop = m.startTime + m.duration;
|
|
142
|
+
return t >= m.startTime && t < stop;
|
|
143
|
+
}
|
|
144
|
+
function rollUpStack(t) {
|
|
145
|
+
for (; depth > 0 && !contains(stack[depth - 1].m, t); --depth);
|
|
146
|
+
}
|
|
147
|
+
function addToParent(p, m) {
|
|
148
|
+
p.children ??= /* @__PURE__ */ new Map();
|
|
149
|
+
p.nestedTimeMs += m.duration;
|
|
150
|
+
return updateChild(p.children, m, p.depth + 1);
|
|
151
|
+
}
|
|
152
|
+
function updateChild(children, m, depth$1) {
|
|
153
|
+
const p = children.get(m.name);
|
|
154
|
+
if (p) {
|
|
155
|
+
p.totalTimeMs += m.duration;
|
|
156
|
+
p.count += 1;
|
|
157
|
+
p.minTimeMs = Math.min(p.minTimeMs, m.duration);
|
|
158
|
+
p.maxTimeMs = Math.max(p.maxTimeMs, m.duration);
|
|
159
|
+
return p;
|
|
160
|
+
}
|
|
161
|
+
const n = {
|
|
162
|
+
name: m.name,
|
|
163
|
+
depth: depth$1,
|
|
164
|
+
totalTimeMs: m.duration,
|
|
165
|
+
nestedTimeMs: 0,
|
|
166
|
+
count: 1,
|
|
167
|
+
minTimeMs: m.duration,
|
|
168
|
+
maxTimeMs: m.duration
|
|
169
|
+
};
|
|
170
|
+
children.set(m.name, n);
|
|
171
|
+
return n;
|
|
172
|
+
}
|
|
173
|
+
function* flattenChildren(m) {
|
|
174
|
+
yield m;
|
|
175
|
+
if (!m.children) return;
|
|
176
|
+
for (const child of m.children.values()) yield* flattenChildren(child);
|
|
177
|
+
}
|
|
178
|
+
function sortChildren(m) {
|
|
179
|
+
if (!m.children) return;
|
|
180
|
+
m.children = new Map([...m.children.entries()].sort((a, b) => b[1].totalTimeMs - a[1].totalTimeMs));
|
|
181
|
+
m.children.forEach(sortChildren);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
//#endregion
|
|
186
|
+
//#region src/util/ansi.ts
|
|
187
|
+
function isAnsiString(s) {
|
|
188
|
+
return s.includes("\x1B") || s.includes("");
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
*
|
|
192
|
+
* @param s - the string to measure - should NOT contains ANSI codes
|
|
193
|
+
* @param tabWidth -
|
|
194
|
+
* @returns
|
|
195
|
+
*/
|
|
196
|
+
function width(s, tabWidth = 1) {
|
|
197
|
+
return s.replaceAll("…", ".").replaceAll(" ", " ".repeat(tabWidth)).replaceAll(/\p{M}/gu, "").replaceAll(/\p{L}/gu, ".").replaceAll(/[\u0000-\u001F\u0300-\u036F]/g, "").replaceAll(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, ".").length;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Measure the width of a string containing ANSI control characters.
|
|
201
|
+
* @param s - string to measure with width in characters.
|
|
202
|
+
* @returns the approximate number of screen characters.
|
|
203
|
+
*/
|
|
204
|
+
function ansiWidth(s) {
|
|
205
|
+
return width(stripVTControlCharacters(s));
|
|
206
|
+
}
|
|
207
|
+
function fragmentString(str, splitOnRegex, sType) {
|
|
208
|
+
const fragments = [];
|
|
209
|
+
let lastIndex = 0;
|
|
210
|
+
for (const match of str.matchAll(new RegExp(splitOnRegex))) {
|
|
211
|
+
if (match.index > lastIndex) fragments.push({
|
|
212
|
+
type: "text",
|
|
213
|
+
text: str.slice(lastIndex, match.index)
|
|
214
|
+
});
|
|
215
|
+
fragments.push({
|
|
216
|
+
type: sType,
|
|
217
|
+
text: match[0]
|
|
218
|
+
});
|
|
219
|
+
lastIndex = match.index + match[0].length;
|
|
220
|
+
}
|
|
221
|
+
if (lastIndex < str.length) fragments.push({
|
|
222
|
+
type: "text",
|
|
223
|
+
text: str.slice(lastIndex)
|
|
224
|
+
});
|
|
225
|
+
return fragments;
|
|
226
|
+
}
|
|
227
|
+
const ansi = ansiRegex();
|
|
228
|
+
function parseAnsiStr(str) {
|
|
229
|
+
return fragmentString(str, ansi, "ansi");
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Prune the end of a string to fit within a specified width, adding an ellipsis if necessary.
|
|
233
|
+
* @param str - the text to prune - ANSI is supported
|
|
234
|
+
* @param maxWidth - the maximum width of the text
|
|
235
|
+
* @param pad - the string to use for padding, default is '…'
|
|
236
|
+
* @returns the pruned text
|
|
237
|
+
*/
|
|
238
|
+
function pruneAnsiTextEnd(str, maxWidth, pad$1 = "…") {
|
|
239
|
+
if (!maxWidth || maxWidth <= 0) return str;
|
|
240
|
+
if (str.length <= maxWidth) return str;
|
|
241
|
+
if (ansiWidth(str) <= maxWidth) return str;
|
|
242
|
+
const padWidth$1 = ansiWidth(pad$1);
|
|
243
|
+
const fragments = parseAnsiStr(str);
|
|
244
|
+
let remaining = maxWidth - padWidth$1;
|
|
245
|
+
for (const frag of fragments) {
|
|
246
|
+
if (frag.type !== "text") continue;
|
|
247
|
+
if (remaining <= 0) {
|
|
248
|
+
frag.text = "";
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
const pruned = pruneTextEnd(frag.text, remaining, pad$1);
|
|
252
|
+
if (pruned !== frag.text) {
|
|
253
|
+
frag.text = pruned;
|
|
254
|
+
remaining = 0;
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
remaining -= width(frag.text);
|
|
258
|
+
}
|
|
259
|
+
return fragments.map((frag) => frag.text).join("");
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Prune the start of a string to fit within a specified width, adding an ellipsis if necessary.
|
|
263
|
+
* @param str - the text to prune - ANSI is supported
|
|
264
|
+
* @param maxWidth - the maximum width of the text
|
|
265
|
+
* @param pad - the string to use for padding, default is '…'
|
|
266
|
+
* @returns the pruned text
|
|
267
|
+
*/
|
|
268
|
+
function pruneAnsiTextStart(str, maxWidth, pad$1 = "…") {
|
|
269
|
+
if (!maxWidth || maxWidth <= 0) return str;
|
|
270
|
+
if (str.length <= maxWidth) return str;
|
|
271
|
+
if (ansiWidth(str) <= maxWidth) return str;
|
|
272
|
+
const padWidth$1 = ansiWidth(pad$1);
|
|
273
|
+
const fragments = parseAnsiStr(str);
|
|
274
|
+
let remaining = maxWidth - padWidth$1;
|
|
275
|
+
for (const frag of fragments.reverse()) {
|
|
276
|
+
if (frag.type !== "text") continue;
|
|
277
|
+
if (remaining <= 0) {
|
|
278
|
+
frag.text = "";
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
const pruned = pruneTextStart(frag.text, remaining, pad$1);
|
|
282
|
+
if (pruned !== frag.text) {
|
|
283
|
+
frag.text = pruned;
|
|
284
|
+
remaining = 0;
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
remaining -= width(frag.text);
|
|
288
|
+
}
|
|
289
|
+
return fragments.reverse().map((frag) => frag.text).join("");
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Prune the end of a string to fit within a specified width, adding an ellipsis if necessary.
|
|
293
|
+
* @param str - the text to prune - ANSI is not supported
|
|
294
|
+
* @param maxWidth - the maximum width of the text
|
|
295
|
+
* @param pad - the string to use for padding, default is '…'
|
|
296
|
+
* @returns the pruned text
|
|
297
|
+
*/
|
|
298
|
+
function pruneTextEnd(str, maxWidth, pad$1 = "…") {
|
|
299
|
+
if (!maxWidth || maxWidth <= 0) return str;
|
|
300
|
+
if (str.length <= maxWidth) return str;
|
|
301
|
+
if (isAnsiString(str)) return pruneAnsiTextEnd(str, maxWidth, pad$1);
|
|
302
|
+
const maxWidthWithPad = maxWidth - width(pad$1);
|
|
303
|
+
const letters = [...str];
|
|
304
|
+
let len = 0;
|
|
305
|
+
for (let i = 0; i < letters.length; i++) {
|
|
306
|
+
const c = letters[i];
|
|
307
|
+
len += width(c);
|
|
308
|
+
if (len > maxWidthWithPad) {
|
|
309
|
+
let j = i + 1;
|
|
310
|
+
while (j < letters.length && width(letters[j]) === 0) ++j;
|
|
311
|
+
return j === letters.length ? str : letters.slice(0, i).join("") + pad$1;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return str;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Prune the start of a string to fit within a specified width, adding an ellipsis if necessary.
|
|
318
|
+
* @param str - the text to prune - ANSI is not supported
|
|
319
|
+
* @param maxWidth - the maximum width of the text
|
|
320
|
+
* @param pad - the string to use for padding, default is '…'
|
|
321
|
+
* @returns the pruned text
|
|
322
|
+
*/
|
|
323
|
+
function pruneTextStart(str, maxWidth, pad$1 = "…") {
|
|
324
|
+
if (!maxWidth || maxWidth <= 0) return str;
|
|
325
|
+
if (str.length <= maxWidth) return str;
|
|
326
|
+
const maxWidthWithPad = maxWidth - width(pad$1);
|
|
327
|
+
const letters = [...str];
|
|
328
|
+
let len = 0;
|
|
329
|
+
for (let i = letters.length - 1; i >= 1; i--) {
|
|
330
|
+
const c = letters[i];
|
|
331
|
+
len += width(c);
|
|
332
|
+
if (len > maxWidthWithPad) {
|
|
333
|
+
i += 1;
|
|
334
|
+
while (i < letters.length && width(letters[i]) === 0) ++i;
|
|
335
|
+
return pad$1 + letters.slice(i).join("");
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
return str;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
//#endregion
|
|
342
|
+
//#region src/util/pad.ts
|
|
343
|
+
function pad(s, w) {
|
|
344
|
+
const p = padWidth(s, w);
|
|
345
|
+
if (!p) return s;
|
|
346
|
+
return s.padEnd(p + s.length);
|
|
347
|
+
}
|
|
348
|
+
function padWidth(s, target) {
|
|
349
|
+
const sWidth = ansiWidth(s);
|
|
350
|
+
return Math.max(target - sWidth, 0);
|
|
351
|
+
}
|
|
352
|
+
function padLeft(s, w) {
|
|
353
|
+
const p = padWidth(s, w);
|
|
354
|
+
if (!p) return s;
|
|
355
|
+
return s.padStart(p + s.length);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
//#endregion
|
|
359
|
+
//#region src/util/table.ts
|
|
360
|
+
function tableToLines(table, deliminator) {
|
|
361
|
+
const del = deliminator || table.deliminator || " | ";
|
|
362
|
+
const columnWidths = [];
|
|
363
|
+
const columnAlignments = table.columnAlignments || [];
|
|
364
|
+
const maxColumnWidthsMap = table.maxColumnWidths || {};
|
|
365
|
+
const tableIndent = table.indent ? typeof table.indent === "number" ? " ".repeat(table.indent) : table.indent : "";
|
|
366
|
+
const { header, rows } = table;
|
|
367
|
+
const simpleHeader = header.map((col) => Array.isArray(col) ? col[1] : col);
|
|
368
|
+
const columnFieldNames = header.map((col) => Array.isArray(col) ? col[0] : col);
|
|
369
|
+
const maxColumnWidths = columnFieldNames.map((field, idx) => maxColumnWidthsMap[field] ?? maxColumnWidthsMap[idx]);
|
|
370
|
+
function getCell(row, col) {
|
|
371
|
+
return getCellFromRow(rows[row], col);
|
|
372
|
+
}
|
|
373
|
+
function getCellFromRow(row, col) {
|
|
374
|
+
if (!row) return void 0;
|
|
375
|
+
if (Array.isArray(row)) return row[col];
|
|
376
|
+
return row[columnFieldNames[col]];
|
|
377
|
+
}
|
|
378
|
+
function rowToCells(row) {
|
|
379
|
+
if (Array.isArray(row)) return row;
|
|
380
|
+
return columnFieldNames.map((fieldName) => row[fieldName]);
|
|
381
|
+
}
|
|
382
|
+
function getText(col, maxWidth) {
|
|
383
|
+
return !col ? "" : typeof col === "string" ? pruneTextEnd(col, maxWidth) : col(maxWidth);
|
|
384
|
+
}
|
|
385
|
+
function getRCText(row, col, maxWidth) {
|
|
386
|
+
return getText(getCell(row, col), maxWidth);
|
|
387
|
+
}
|
|
388
|
+
function recordHeaderWidths(header$1) {
|
|
389
|
+
header$1.forEach((col, idx) => {
|
|
390
|
+
columnWidths[idx] = Math.max(ansiWidth(col), columnWidths[idx] || 0);
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
function recordColWidths() {
|
|
394
|
+
for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) for (let colIndex = 0; colIndex < columnFieldNames.length; colIndex++) columnWidths[colIndex] = Math.max(ansiWidth(getRCText(rowIndex, colIndex, void 0)), columnWidths[colIndex] || 0);
|
|
395
|
+
}
|
|
396
|
+
function justifyRow(c, i) {
|
|
397
|
+
return columnAlignments[i] === "R" ? padLeft(c, columnWidths[i]) : pad(c, columnWidths[i]);
|
|
398
|
+
}
|
|
399
|
+
function toHeaderLine(header$1) {
|
|
400
|
+
return tableIndent + decorateRowWith(header$1.map((c, i) => getText(c, columnWidths[i])), justifyRow, headerDecorator).join(del);
|
|
401
|
+
}
|
|
402
|
+
function toLine(row) {
|
|
403
|
+
return tableIndent + decorateRowWith(rowToCells(row).map((c, i) => getText(c, columnWidths[i])), justifyRow).join(del);
|
|
404
|
+
}
|
|
405
|
+
function* process$1() {
|
|
406
|
+
if (table.title) yield table.title;
|
|
407
|
+
yield toHeaderLine(simpleHeader);
|
|
408
|
+
yield* rows.map(toLine);
|
|
409
|
+
}
|
|
410
|
+
function sumColumnWidths() {
|
|
411
|
+
return columnWidths.reduce((sum, width$1) => sum + width$1, 0);
|
|
412
|
+
}
|
|
413
|
+
function adjustColWidths() {
|
|
414
|
+
for (let i = 0; i < columnWidths.length; i++) {
|
|
415
|
+
const mw = maxColumnWidths[i];
|
|
416
|
+
if (!mw) continue;
|
|
417
|
+
columnWidths[i] = Math.min(columnWidths[i], mw);
|
|
418
|
+
}
|
|
419
|
+
if (!table.terminalWidth) return;
|
|
420
|
+
const dWidth = (columnWidths.length - 1) * ansiWidth(del);
|
|
421
|
+
const lineWidth = table.terminalWidth - dWidth;
|
|
422
|
+
if (lineWidth <= columnWidths.length * 2) {
|
|
423
|
+
const fixedWidth = Math.max(Math.min(...columnWidths), 5);
|
|
424
|
+
for (let i = 0; i < columnWidths.length; i++) columnWidths[i] = fixedWidth;
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
if (columnWidths.length === 1) {
|
|
428
|
+
columnWidths[0] = lineWidth;
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
function trimWidestColumn(neededToTrim) {
|
|
432
|
+
let first = 0;
|
|
433
|
+
let second = 0;
|
|
434
|
+
for (let i = 0; i < columnWidths.length; i++) if (columnWidths[i] > columnWidths[first]) {
|
|
435
|
+
second = first;
|
|
436
|
+
first = i;
|
|
437
|
+
} else if (columnWidths[i] > columnWidths[second]) second = i;
|
|
438
|
+
const diff = Math.max(columnWidths[first] - columnWidths[second], 1);
|
|
439
|
+
columnWidths[first] -= Math.min(diff, neededToTrim);
|
|
440
|
+
}
|
|
441
|
+
for (let sum = sumColumnWidths(); sum > lineWidth; sum = sumColumnWidths()) trimWidestColumn(sum - lineWidth);
|
|
442
|
+
}
|
|
443
|
+
recordHeaderWidths(simpleHeader);
|
|
444
|
+
recordColWidths();
|
|
445
|
+
adjustColWidths();
|
|
446
|
+
return [...process$1()];
|
|
447
|
+
}
|
|
448
|
+
function headerDecorator(t) {
|
|
449
|
+
return chalk.bold(chalk.underline(t));
|
|
450
|
+
}
|
|
451
|
+
function decorateRowWith(row, ...decorators) {
|
|
452
|
+
return decorators.reduce((row$1, decorator) => row$1.map(decorator), row);
|
|
453
|
+
}
|
|
454
|
+
|
|
115
455
|
//#endregion
|
|
116
456
|
//#region src/util/util.ts
|
|
117
457
|
const uniqueFn = uniqueFilterFnGenerator;
|
|
@@ -199,9 +539,10 @@ function reportProgressFileComplete(io, p, cwd, options) {
|
|
|
199
539
|
const { idx, filename } = determineFilename(io, p, cwd);
|
|
200
540
|
const { verbose, debug } = options;
|
|
201
541
|
const time = reportTime(io, p.elapsedTimeMs, !!p.cached);
|
|
202
|
-
const
|
|
542
|
+
const skippedReason = p.skippedReason ? ` (${p.skippedReason})` : "";
|
|
543
|
+
const skipped = p.processed === false ? ` skipped${skippedReason}` : "";
|
|
203
544
|
const hasErrors = p.numErrors ? io.chalk.red` X` : "";
|
|
204
|
-
const msg = `${idx} ${filename} ${time}${skipped}${hasErrors}${(
|
|
545
|
+
const msg = `${idx} ${filename} ${time}${skipped}${hasErrors}${(verbose || debug || hasErrors || isSlow(p.elapsedTimeMs) || io.getColorLevel() < 1 ? "\n" : "") || "\r"}`;
|
|
205
546
|
io.write(msg);
|
|
206
547
|
}
|
|
207
548
|
function reportTime(io, elapsedTimeMs, cached) {
|
|
@@ -275,8 +616,9 @@ function getReporter(options, config) {
|
|
|
275
616
|
}
|
|
276
617
|
const resultEmitter = (result) => {
|
|
277
618
|
if (!fileGlobs.length && !result.files) return;
|
|
278
|
-
const { files, issues: issues$1, cachedFiles, filesWithIssues, errors } = result;
|
|
619
|
+
const { files, issues: issues$1, cachedFiles, filesWithIssues, errors, skippedFiles } = result;
|
|
279
620
|
const numFilesWithIssues = filesWithIssues.size;
|
|
621
|
+
const chalk$1 = stderr.chalk;
|
|
280
622
|
if (stderr.getColorLevel() > 0) {
|
|
281
623
|
stderr.write("\r");
|
|
282
624
|
stderr.clearLine(0);
|
|
@@ -286,9 +628,11 @@ function getReporter(options, config) {
|
|
|
286
628
|
consoleError("Issues found:");
|
|
287
629
|
issuesCollection.forEach((issue) => consoleError(issue));
|
|
288
630
|
}
|
|
631
|
+
const filesChecked = files - (skippedFiles || 0);
|
|
289
632
|
const cachedFilesText = cachedFiles ? ` (${cachedFiles} from cache)` : "";
|
|
633
|
+
const skippedFilesText = skippedFiles ? `, skipped: ${skippedFiles}` : "";
|
|
290
634
|
const withErrorsText = errors ? ` with ${errors} error${errors === 1 ? "" : "s"}` : "";
|
|
291
|
-
consoleError(`CSpell\u003A Files checked: ${
|
|
635
|
+
consoleError(`CSpell\u003A Files checked: ${filesChecked}${cachedFilesText}${skippedFilesText}, Issues found: ${issues$1} in ${numFilesWithIssues === 1 ? "1 file" : `${numFilesWithIssues} files`}${withErrorsText}.`);
|
|
292
636
|
if (errorCollection?.length && issues$1 > 5) {
|
|
293
637
|
consoleError("-------------------------------------------");
|
|
294
638
|
consoleError("Errors:");
|
|
@@ -301,14 +645,80 @@ function getReporter(options, config) {
|
|
|
301
645
|
consoleError(` Files Skipped : ${perfStats.filesSkipped.toString().padStart(6)}`);
|
|
302
646
|
consoleError(` Files Cached : ${perfStats.filesCached.toString().padStart(6)}`);
|
|
303
647
|
consoleError(` Processing Time: ${perfStats.elapsedTimeMs.toFixed(2).padStart(9)}ms`);
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
648
|
+
const tableStats = {
|
|
649
|
+
title: chalk$1.bold("Perf Stats:"),
|
|
650
|
+
header: ["Name", "Time (ms)"],
|
|
651
|
+
columnAlignments: ["L", "R"],
|
|
652
|
+
indent: 2,
|
|
653
|
+
rows: Object.entries(perfStats.perf).filter((p) => !!p[1]).map(([key, value]) => [key, value.toFixed(2)])
|
|
654
|
+
};
|
|
655
|
+
consoleError("");
|
|
656
|
+
for (const line of tableToLines(tableStats)) consoleError(line);
|
|
657
|
+
if (options.verboseLevel) verbosePerfReport();
|
|
310
658
|
}
|
|
311
659
|
};
|
|
660
|
+
function verbosePerfReport() {
|
|
661
|
+
const perfMeasurements = getPerfMeasurements();
|
|
662
|
+
if (!perfMeasurements.length) return;
|
|
663
|
+
const notable = extractNotableBySelfTimeInGroup(perfMeasurements);
|
|
664
|
+
const chalk$1 = stderr.chalk;
|
|
665
|
+
const maxDepth = Math.max(...perfMeasurements.map((m) => m.depth));
|
|
666
|
+
const depthIndicator = (d) => "⋅".repeat(d) + " ".repeat(maxDepth - d);
|
|
667
|
+
const rows = perfMeasurements.map((m) => {
|
|
668
|
+
const cbd = (text) => colorByDepth(chalk$1, m.depth, text);
|
|
669
|
+
const cNotable = (text) => notable.has(m) ? chalk$1.yellow(text) : text;
|
|
670
|
+
return [
|
|
671
|
+
chalk$1.dim("⋅".repeat(m.depth)) + colorByDepthGrayscale(stderr.chalk, m.depth, m.name),
|
|
672
|
+
cbd(m.totalTimeMs.toFixed(2) + chalk$1.dim(depthIndicator(m.depth))),
|
|
673
|
+
cbd(cNotable((m.totalTimeMs - m.nestedTimeMs).toFixed(2))),
|
|
674
|
+
cbd(m.count.toString()),
|
|
675
|
+
cbd(m.minTimeMs.toFixed(2)),
|
|
676
|
+
cbd(m.maxTimeMs.toFixed(2)),
|
|
677
|
+
cbd((m.totalTimeMs / m.count).toFixed(2))
|
|
678
|
+
];
|
|
679
|
+
});
|
|
680
|
+
const table = tableToLines({
|
|
681
|
+
title: chalk$1.bold("Detailed Measurements:"),
|
|
682
|
+
header: [
|
|
683
|
+
"Name",
|
|
684
|
+
"Total Time (ms)",
|
|
685
|
+
"Self (ms)",
|
|
686
|
+
"Count",
|
|
687
|
+
"Min (ms)",
|
|
688
|
+
"Max (ms)",
|
|
689
|
+
"Avg (ms)"
|
|
690
|
+
],
|
|
691
|
+
rows,
|
|
692
|
+
columnAlignments: [
|
|
693
|
+
"L",
|
|
694
|
+
"R",
|
|
695
|
+
"R",
|
|
696
|
+
"R",
|
|
697
|
+
"R",
|
|
698
|
+
"R",
|
|
699
|
+
"R"
|
|
700
|
+
],
|
|
701
|
+
indent: 2
|
|
702
|
+
});
|
|
703
|
+
consoleError("\n-------------------------------------------\n");
|
|
704
|
+
for (const line of table) consoleError(line);
|
|
705
|
+
}
|
|
706
|
+
function colorByDepth(chalk$1, depth, text) {
|
|
707
|
+
const colors = [
|
|
708
|
+
chalk$1.green,
|
|
709
|
+
chalk$1.cyan,
|
|
710
|
+
chalk$1.blue,
|
|
711
|
+
chalk$1.magenta,
|
|
712
|
+
chalk$1.red
|
|
713
|
+
];
|
|
714
|
+
const color = colors[depth % colors.length];
|
|
715
|
+
if (depth / colors.length >= 1) return chalk$1.dim(color(text));
|
|
716
|
+
return color(text);
|
|
717
|
+
}
|
|
718
|
+
function colorByDepthGrayscale(chalk$1, depth, text) {
|
|
719
|
+
const grayLevel = Math.max(32, 255 - depth * 20);
|
|
720
|
+
return chalk$1.rgb(grayLevel, grayLevel, grayLevel)(text);
|
|
721
|
+
}
|
|
312
722
|
function collectPerfStats(p) {
|
|
313
723
|
if (p.cached) {
|
|
314
724
|
perfStats.filesCached++;
|
|
@@ -334,6 +744,27 @@ function getReporter(options, config) {
|
|
|
334
744
|
features: void 0
|
|
335
745
|
};
|
|
336
746
|
}
|
|
747
|
+
function extractNotableBySelfTimeInGroup(measurements) {
|
|
748
|
+
const notable = /* @__PURE__ */ new Set();
|
|
749
|
+
if (!measurements.length) return notable;
|
|
750
|
+
let highest;
|
|
751
|
+
let highestSelfTime = 0;
|
|
752
|
+
for (const m of measurements) {
|
|
753
|
+
if (m.depth === 0 || !highest) {
|
|
754
|
+
if (highest) notable.add(highest);
|
|
755
|
+
highest = m;
|
|
756
|
+
highestSelfTime = m.totalTimeMs - m.nestedTimeMs;
|
|
757
|
+
continue;
|
|
758
|
+
}
|
|
759
|
+
const selfTime = m.totalTimeMs - m.nestedTimeMs;
|
|
760
|
+
if (selfTime > highestSelfTime) {
|
|
761
|
+
highest = m;
|
|
762
|
+
highestSelfTime = selfTime;
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
if (highest) notable.add(highest);
|
|
766
|
+
return notable;
|
|
767
|
+
}
|
|
337
768
|
function formatIssue(io, templateStr, issue, maxIssueTextWidth) {
|
|
338
769
|
function clean$1(t$1) {
|
|
339
770
|
return t$1.replace(/\s+/, " ");
|
|
@@ -443,7 +874,7 @@ async function fileExists(url) {
|
|
|
443
874
|
try {
|
|
444
875
|
return (await promises.stat(url)).isFile();
|
|
445
876
|
} catch (e) {
|
|
446
|
-
if (toError(e).code === "ENOENT") return false;
|
|
877
|
+
if (toError$1(e).code === "ENOENT") return false;
|
|
447
878
|
throw e;
|
|
448
879
|
}
|
|
449
880
|
}
|
|
@@ -766,7 +1197,7 @@ const pkgDir = _dirname;
|
|
|
766
1197
|
//#endregion
|
|
767
1198
|
//#region src/pkgInfo.ts
|
|
768
1199
|
const name = "cspell";
|
|
769
|
-
const version$1 = "9.
|
|
1200
|
+
const version$1 = "9.6.0";
|
|
770
1201
|
const engines = { node: ">=20" };
|
|
771
1202
|
const npmPackage = {
|
|
772
1203
|
name,
|
|
@@ -987,7 +1418,7 @@ function readFileInfo(filename, encoding = UTF8, handleNotFound = false) {
|
|
|
987
1418
|
text,
|
|
988
1419
|
filename
|
|
989
1420
|
}), (e) => {
|
|
990
|
-
const error = toError(e);
|
|
1421
|
+
const error = toError$1(e);
|
|
991
1422
|
return handleNotFound && error.code === "EISDIR" ? Promise.resolve({
|
|
992
1423
|
text: "",
|
|
993
1424
|
filename,
|
|
@@ -999,6 +1430,11 @@ function readFileInfo(filename, encoding = UTF8, handleNotFound = false) {
|
|
|
999
1430
|
}) : Promise.reject(new IOError(`Error reading file: "${filename}"`, error));
|
|
1000
1431
|
});
|
|
1001
1432
|
}
|
|
1433
|
+
async function getFileSize(filename) {
|
|
1434
|
+
const s = await getStat(filename);
|
|
1435
|
+
if (!(s instanceof Error)) return s.size;
|
|
1436
|
+
throw s;
|
|
1437
|
+
}
|
|
1002
1438
|
function readFile(filename, encoding = UTF8) {
|
|
1003
1439
|
return readFileInfo(filename, encoding).then((info) => info.text);
|
|
1004
1440
|
}
|
|
@@ -1172,7 +1608,7 @@ var ImplFileEntryCache = class {
|
|
|
1172
1608
|
return {
|
|
1173
1609
|
key: file,
|
|
1174
1610
|
notFound: true,
|
|
1175
|
-
err: toError
|
|
1611
|
+
err: toError(error)
|
|
1176
1612
|
};
|
|
1177
1613
|
}
|
|
1178
1614
|
if (this.useChecksum) return this.#getFileDescriptorUsingChecksum(file);
|
|
@@ -1287,7 +1723,7 @@ var ImplFileEntryCache = class {
|
|
|
1287
1723
|
function isNodeError(error) {
|
|
1288
1724
|
return typeof error === "object" && error !== null && "code" in error;
|
|
1289
1725
|
}
|
|
1290
|
-
function toError
|
|
1726
|
+
function toError(error) {
|
|
1291
1727
|
if (error instanceof Error) return error;
|
|
1292
1728
|
if (typeof error === "string") return new Error(error);
|
|
1293
1729
|
return new Error("Unknown error", { cause: error });
|
|
@@ -1376,7 +1812,7 @@ var DiskCache = class {
|
|
|
1376
1812
|
cached
|
|
1377
1813
|
};
|
|
1378
1814
|
}
|
|
1379
|
-
async setCachedLintResults({ fileInfo, elapsedTimeMs: _, cached: __
|
|
1815
|
+
async setCachedLintResults({ fileInfo, elapsedTimeMs: _, cached: __, ...result }, dependsUponFiles) {
|
|
1380
1816
|
const fileDescriptor = await this.fileEntryCache.getFileDescriptor(fileInfo.filename);
|
|
1381
1817
|
const meta = fileDescriptor.meta;
|
|
1382
1818
|
if (fileDescriptor.notFound || !meta) return;
|
|
@@ -1397,7 +1833,7 @@ var DiskCache = class {
|
|
|
1397
1833
|
this.ocCacheFileResult = new ShallowObjectCollection();
|
|
1398
1834
|
}
|
|
1399
1835
|
normalizeResult(result) {
|
|
1400
|
-
const { issues, processed, errors, configErrors, reportIssueOptions
|
|
1836
|
+
const { issues, processed, errors, configErrors, reportIssueOptions, ...rest } = result;
|
|
1401
1837
|
if (!Object.keys(rest).length) return this.ocCacheFileResult.get(result);
|
|
1402
1838
|
return this.ocCacheFileResult.get({
|
|
1403
1839
|
issues,
|
|
@@ -1638,61 +2074,6 @@ async function readConfigHandleError(filename) {
|
|
|
1638
2074
|
}
|
|
1639
2075
|
}
|
|
1640
2076
|
|
|
1641
|
-
//#endregion
|
|
1642
|
-
//#region src/util/extractContext.ts
|
|
1643
|
-
function prefCharIndex(text, offset, count = 1) {
|
|
1644
|
-
if (offset - count < 0) return 0;
|
|
1645
|
-
for (; count > 0 && offset > 0; count--) {
|
|
1646
|
-
let code = text.charCodeAt(--offset) || 0;
|
|
1647
|
-
if (code === 65039) code = text.charCodeAt(--offset) || 0;
|
|
1648
|
-
offset -= (code & 64512) === 56320 ? 1 : 0;
|
|
1649
|
-
}
|
|
1650
|
-
return offset < 0 ? 0 : offset;
|
|
1651
|
-
}
|
|
1652
|
-
function nextCharIndex(text, offset, count = 1) {
|
|
1653
|
-
if (offset + count >= text.length) return text.length;
|
|
1654
|
-
for (; count > 0 && offset < text.length; count--) {
|
|
1655
|
-
const code = text.charCodeAt(offset++) || 0;
|
|
1656
|
-
offset += (code & 64512) === 55296 ? 1 : 0;
|
|
1657
|
-
if (text.charCodeAt(offset) === 65039) offset++;
|
|
1658
|
-
}
|
|
1659
|
-
return offset > text.length ? text.length : offset;
|
|
1660
|
-
}
|
|
1661
|
-
function lineContext(lineText, start, end, contextRange) {
|
|
1662
|
-
let left = prefCharIndex(lineText, start, contextRange);
|
|
1663
|
-
let right = nextCharIndex(lineText, end, contextRange);
|
|
1664
|
-
const isLetter = /^\p{L}$/u;
|
|
1665
|
-
const isMark = /^\p{M}$/u;
|
|
1666
|
-
for (let n = contextRange / 2; n > 0 && left > 0; n--, left--) {
|
|
1667
|
-
const c = lineText[left - 1];
|
|
1668
|
-
if (isMark.test(c)) {
|
|
1669
|
-
if (!isLetter.test(lineText[left - 2])) break;
|
|
1670
|
-
left--;
|
|
1671
|
-
continue;
|
|
1672
|
-
}
|
|
1673
|
-
if (!isLetter.test(lineText[left - 1])) break;
|
|
1674
|
-
}
|
|
1675
|
-
for (let n = contextRange / 2; n > 0 && right < lineText.length; n--, right++) {
|
|
1676
|
-
if (!isLetter.test(lineText[right])) break;
|
|
1677
|
-
if (isMark.test(lineText[right + 1])) right++;
|
|
1678
|
-
}
|
|
1679
|
-
left = left < 0 ? 0 : left;
|
|
1680
|
-
const t0 = lineText.slice(left, right);
|
|
1681
|
-
const tLeft = t0.trimStart();
|
|
1682
|
-
left = Math.min(left + t0.length - tLeft.length, start);
|
|
1683
|
-
return {
|
|
1684
|
-
text: tLeft.trimEnd(),
|
|
1685
|
-
offset: left
|
|
1686
|
-
};
|
|
1687
|
-
}
|
|
1688
|
-
function extractContext(tdo, contextRange) {
|
|
1689
|
-
const { line, offset, text } = tdo;
|
|
1690
|
-
const start = offset - line.offset;
|
|
1691
|
-
const context = lineContext(line.text, start, start + text.length, contextRange);
|
|
1692
|
-
context.offset += line.offset;
|
|
1693
|
-
return context;
|
|
1694
|
-
}
|
|
1695
|
-
|
|
1696
2077
|
//#endregion
|
|
1697
2078
|
//#region src/util/prefetch.ts
|
|
1698
2079
|
function* prefetchIterable(iterable, size) {
|
|
@@ -1741,7 +2122,7 @@ async function loadReporters(reporters, defaultReporter, config) {
|
|
|
1741
2122
|
const { getReporter: getReporter$1 } = await dynamicImport(moduleName, [process.cwd(), pkgDir]);
|
|
1742
2123
|
return getReporter$1(settings, config);
|
|
1743
2124
|
} catch (e) {
|
|
1744
|
-
throw new ApplicationError(`Failed to load reporter ${moduleName}: ${toError(e).message}`);
|
|
2125
|
+
throw new ApplicationError(`Failed to load reporter ${moduleName}: ${toError$1(e).message}`);
|
|
1745
2126
|
}
|
|
1746
2127
|
}
|
|
1747
2128
|
reporters = !reporters || !reporters.length ? ["default"] : [...reporters];
|
|
@@ -1852,6 +2233,7 @@ var LintReporter = class {
|
|
|
1852
2233
|
filename,
|
|
1853
2234
|
elapsedTimeMs: result.elapsedTimeMs,
|
|
1854
2235
|
processed: result.processed,
|
|
2236
|
+
skippedReason: result.skippedReason,
|
|
1855
2237
|
numErrors: numIssues || result.errors,
|
|
1856
2238
|
cached: result.cached,
|
|
1857
2239
|
perf: result.perf,
|
|
@@ -1872,6 +2254,144 @@ function getTimeMeasurer() {
|
|
|
1872
2254
|
return () => timer.elapsed;
|
|
1873
2255
|
}
|
|
1874
2256
|
|
|
2257
|
+
//#endregion
|
|
2258
|
+
//#region src/util/unindent.ts
|
|
2259
|
+
/**
|
|
2260
|
+
* Indent each line of a multi-line string.
|
|
2261
|
+
* @param str - multi-line string to left pad
|
|
2262
|
+
* @param padding - the padding to use for all lines except the first.
|
|
2263
|
+
* @param firstLinePadding - optional padding of first line.
|
|
2264
|
+
* @returns
|
|
2265
|
+
*/
|
|
2266
|
+
function indent(str, padding, firstLinePadding = "") {
|
|
2267
|
+
let pad$1 = firstLinePadding;
|
|
2268
|
+
const lines = [];
|
|
2269
|
+
for (const line of str.split("\n")) {
|
|
2270
|
+
lines.push(pad$1 + line);
|
|
2271
|
+
pad$1 = padding;
|
|
2272
|
+
}
|
|
2273
|
+
return lines.join("\n");
|
|
2274
|
+
}
|
|
2275
|
+
/**
|
|
2276
|
+
* Inject values into a template string while keeping indentation of multi-line values.
|
|
2277
|
+
* @param template - template string
|
|
2278
|
+
* @param values- values to inject
|
|
2279
|
+
* @returns the injected string
|
|
2280
|
+
*/
|
|
2281
|
+
function keepIndent(template, ...values) {
|
|
2282
|
+
const strings = template;
|
|
2283
|
+
const adjValues = [];
|
|
2284
|
+
for (let i = 0; i < values.length; ++i) {
|
|
2285
|
+
const prevLines = strings[i].split("\n");
|
|
2286
|
+
const currLine = prevLines[prevLines.length - 1];
|
|
2287
|
+
const padLen = padLength(currLine);
|
|
2288
|
+
const padding = " ".repeat(padLen);
|
|
2289
|
+
adjValues.push(indent(`${values[i]}`, padding));
|
|
2290
|
+
}
|
|
2291
|
+
return String.raw({ raw: strings }, ...adjValues);
|
|
2292
|
+
}
|
|
2293
|
+
/**
|
|
2294
|
+
* Calculate the padding at the start of the string.
|
|
2295
|
+
* @param s - string to evaluate
|
|
2296
|
+
* @returns number of padding characters
|
|
2297
|
+
*/
|
|
2298
|
+
function padLength(s) {
|
|
2299
|
+
return s.length - s.trimStart().length;
|
|
2300
|
+
}
|
|
2301
|
+
function unindent(templateOrString, ...values) {
|
|
2302
|
+
return unindentString(typeof templateOrString === "string" ? templateOrString : keepIndent(templateOrString, ...values));
|
|
2303
|
+
}
|
|
2304
|
+
function unindentString(str) {
|
|
2305
|
+
const lines = str.split("\n");
|
|
2306
|
+
let curPad = str.length;
|
|
2307
|
+
for (const line of lines) {
|
|
2308
|
+
if (!line.trim()) continue;
|
|
2309
|
+
curPad = Math.min(curPad, padLength(line));
|
|
2310
|
+
}
|
|
2311
|
+
return lines.map((line) => line.slice(curPad)).join("\n");
|
|
2312
|
+
}
|
|
2313
|
+
|
|
2314
|
+
//#endregion
|
|
2315
|
+
//#region src/util/unitNumbers.ts
|
|
2316
|
+
const regexUnitNumber = /^((?:\d+(?:\.\d*)?)|(?:\.\d+))([a-z]*)$/i;
|
|
2317
|
+
const unitSizes = {
|
|
2318
|
+
"": 1,
|
|
2319
|
+
b: 1,
|
|
2320
|
+
k: 1024,
|
|
2321
|
+
kb: 1024,
|
|
2322
|
+
m: 1 << 20,
|
|
2323
|
+
mb: 1 << 20,
|
|
2324
|
+
g: 1 << 30,
|
|
2325
|
+
gb: 1 << 30
|
|
2326
|
+
};
|
|
2327
|
+
function parseUnitSize(size) {
|
|
2328
|
+
const match = size.match(regexUnitNumber);
|
|
2329
|
+
const digits = match?.[1] || "";
|
|
2330
|
+
const units = (match?.[2] || "").toLowerCase();
|
|
2331
|
+
if (!match) return {
|
|
2332
|
+
size,
|
|
2333
|
+
digits,
|
|
2334
|
+
units,
|
|
2335
|
+
error: "Invalid size."
|
|
2336
|
+
};
|
|
2337
|
+
if (!units || units in unitSizes) return {
|
|
2338
|
+
size,
|
|
2339
|
+
digits,
|
|
2340
|
+
units
|
|
2341
|
+
};
|
|
2342
|
+
return {
|
|
2343
|
+
size,
|
|
2344
|
+
digits,
|
|
2345
|
+
units,
|
|
2346
|
+
error: `Unknown units. Valid units are: ${Object.keys(unitSizes).filter(Boolean).join(", ").toUpperCase()}.`
|
|
2347
|
+
};
|
|
2348
|
+
}
|
|
2349
|
+
function validateUnitSize(size) {
|
|
2350
|
+
return parseUnitSize(size).error;
|
|
2351
|
+
}
|
|
2352
|
+
function sizeToNumber(size) {
|
|
2353
|
+
const p = parseUnitSize(size);
|
|
2354
|
+
if (p.error) return NaN;
|
|
2355
|
+
return Number.parseFloat(p.digits) * (unitSizes[p.units] || 1);
|
|
2356
|
+
}
|
|
2357
|
+
|
|
2358
|
+
//#endregion
|
|
2359
|
+
//#region src/util/wrap.ts
|
|
2360
|
+
const wrapSep = /\s+|(?<=,)|\.(?=\w)/g;
|
|
2361
|
+
function wordWrapAnsiText(str, maxWidth, indent$1 = "", sep$1 = wrapSep) {
|
|
2362
|
+
if (!maxWidth || maxWidth <= 0) return str;
|
|
2363
|
+
if (str.length <= maxWidth) return str;
|
|
2364
|
+
if (str.includes("\n")) return str.split("\n").map((line$1) => wordWrapAnsiText(line$1, maxWidth, indent$1)).join("\n");
|
|
2365
|
+
const fragments = fragmentString(str, sep$1, "sep");
|
|
2366
|
+
const lines = [];
|
|
2367
|
+
let line = "";
|
|
2368
|
+
for (const text of joinFragments(fragments)) {
|
|
2369
|
+
const lineWidth = ansiWidth(line);
|
|
2370
|
+
const textWidth = ansiWidth(text);
|
|
2371
|
+
if (line && lineWidth + textWidth > maxWidth) {
|
|
2372
|
+
if (line) lines.push(line);
|
|
2373
|
+
line = indent$1 + text.trimStart();
|
|
2374
|
+
continue;
|
|
2375
|
+
}
|
|
2376
|
+
line += text;
|
|
2377
|
+
}
|
|
2378
|
+
if (line) lines.push(line);
|
|
2379
|
+
return lines.join("\n");
|
|
2380
|
+
}
|
|
2381
|
+
function* joinFragments(fragments) {
|
|
2382
|
+
let last;
|
|
2383
|
+
for (const frag of fragments) {
|
|
2384
|
+
if (frag.type === "sep") {
|
|
2385
|
+
if (last) yield last.text;
|
|
2386
|
+
last = frag;
|
|
2387
|
+
continue;
|
|
2388
|
+
}
|
|
2389
|
+
yield last ? last.text + frag.text : frag.text;
|
|
2390
|
+
last = void 0;
|
|
2391
|
+
}
|
|
2392
|
+
if (last) yield last.text;
|
|
2393
|
+
}
|
|
2394
|
+
|
|
1875
2395
|
//#endregion
|
|
1876
2396
|
//#region src/util/writeFile.ts
|
|
1877
2397
|
async function writeFileOrStream(filename, data) {
|
|
@@ -1895,6 +2415,206 @@ function writeStream(stream, data) {
|
|
|
1895
2415
|
});
|
|
1896
2416
|
}
|
|
1897
2417
|
|
|
2418
|
+
//#endregion
|
|
2419
|
+
//#region src/util/extractContext.ts
|
|
2420
|
+
function prefCharIndex(text, offset, count = 1) {
|
|
2421
|
+
if (offset - count < 0) return 0;
|
|
2422
|
+
for (; count > 0 && offset > 0; count--) {
|
|
2423
|
+
let code = text.charCodeAt(--offset) || 0;
|
|
2424
|
+
if (code === 65039) code = text.charCodeAt(--offset) || 0;
|
|
2425
|
+
offset -= (code & 64512) === 56320 ? 1 : 0;
|
|
2426
|
+
}
|
|
2427
|
+
return offset < 0 ? 0 : offset;
|
|
2428
|
+
}
|
|
2429
|
+
function nextCharIndex(text, offset, count = 1) {
|
|
2430
|
+
if (offset + count >= text.length) return text.length;
|
|
2431
|
+
for (; count > 0 && offset < text.length; count--) {
|
|
2432
|
+
const code = text.charCodeAt(offset++) || 0;
|
|
2433
|
+
offset += (code & 64512) === 55296 ? 1 : 0;
|
|
2434
|
+
if (text.charCodeAt(offset) === 65039) offset++;
|
|
2435
|
+
}
|
|
2436
|
+
return offset > text.length ? text.length : offset;
|
|
2437
|
+
}
|
|
2438
|
+
function lineContext(lineText, start, end, contextRange) {
|
|
2439
|
+
let left = prefCharIndex(lineText, start, contextRange);
|
|
2440
|
+
let right = nextCharIndex(lineText, end, contextRange);
|
|
2441
|
+
const isLetter = /^\p{L}$/u;
|
|
2442
|
+
const isMark = /^\p{M}$/u;
|
|
2443
|
+
for (let n = contextRange / 2; n > 0 && left > 0; n--, left--) {
|
|
2444
|
+
const c = lineText[left - 1];
|
|
2445
|
+
if (isMark.test(c)) {
|
|
2446
|
+
if (!isLetter.test(lineText[left - 2])) break;
|
|
2447
|
+
left--;
|
|
2448
|
+
continue;
|
|
2449
|
+
}
|
|
2450
|
+
if (!isLetter.test(lineText[left - 1])) break;
|
|
2451
|
+
}
|
|
2452
|
+
for (let n = contextRange / 2; n > 0 && right < lineText.length; n--, right++) {
|
|
2453
|
+
if (!isLetter.test(lineText[right])) break;
|
|
2454
|
+
if (isMark.test(lineText[right + 1])) right++;
|
|
2455
|
+
}
|
|
2456
|
+
left = left < 0 ? 0 : left;
|
|
2457
|
+
const t0 = lineText.slice(left, right);
|
|
2458
|
+
const tLeft = t0.trimStart();
|
|
2459
|
+
left = Math.min(left + t0.length - tLeft.length, start);
|
|
2460
|
+
return {
|
|
2461
|
+
text: tLeft.trimEnd(),
|
|
2462
|
+
offset: left
|
|
2463
|
+
};
|
|
2464
|
+
}
|
|
2465
|
+
function extractContext(tdo, contextRange) {
|
|
2466
|
+
const { line, offset, text } = tdo;
|
|
2467
|
+
const start = offset - line.offset;
|
|
2468
|
+
const context = lineContext(line.text, start, start + text.length, contextRange);
|
|
2469
|
+
context.offset += line.offset;
|
|
2470
|
+
return context;
|
|
2471
|
+
}
|
|
2472
|
+
|
|
2473
|
+
//#endregion
|
|
2474
|
+
//#region src/lint/LinterError.ts
|
|
2475
|
+
var LinterError = class extends Error {
|
|
2476
|
+
constructor(message) {
|
|
2477
|
+
super(message);
|
|
2478
|
+
}
|
|
2479
|
+
toString() {
|
|
2480
|
+
return this.message;
|
|
2481
|
+
}
|
|
2482
|
+
};
|
|
2483
|
+
|
|
2484
|
+
//#endregion
|
|
2485
|
+
//#region src/lint/processFile.ts
|
|
2486
|
+
async function processFile(filename, cache, prefetch, processFileOptions) {
|
|
2487
|
+
if (prefetch?.fileResult) return prefetch.fileResult;
|
|
2488
|
+
const { reporter, cfg, configInfo } = processFileOptions;
|
|
2489
|
+
const getElapsedTimeMs = getTimeMeasurer();
|
|
2490
|
+
const reportIssueOptions = prefetch?.reportIssueOptions;
|
|
2491
|
+
const cachedResult = await cache.getCachedLintResults(filename);
|
|
2492
|
+
if (cachedResult) {
|
|
2493
|
+
reporter.debug(`Filename: ${filename}, using cache`);
|
|
2494
|
+
return {
|
|
2495
|
+
...cachedResult,
|
|
2496
|
+
elapsedTimeMs: getElapsedTimeMs(),
|
|
2497
|
+
reportIssueOptions: {
|
|
2498
|
+
...cachedResult.reportIssueOptions,
|
|
2499
|
+
...reportIssueOptions
|
|
2500
|
+
}
|
|
2501
|
+
};
|
|
2502
|
+
}
|
|
2503
|
+
const result = {
|
|
2504
|
+
fileInfo: { filename },
|
|
2505
|
+
issues: [],
|
|
2506
|
+
processed: false,
|
|
2507
|
+
errors: 0,
|
|
2508
|
+
configErrors: 0,
|
|
2509
|
+
elapsedTimeMs: 0,
|
|
2510
|
+
reportIssueOptions
|
|
2511
|
+
};
|
|
2512
|
+
const fileInfo = prefetch?.fileInfo || await readFileInfo(filename, void 0, true);
|
|
2513
|
+
if (fileInfo.errorCode) {
|
|
2514
|
+
if (fileInfo.errorCode !== "EISDIR" && cfg.options.mustFindFiles) {
|
|
2515
|
+
const err = new LinterError(`File not found: "${filename}"`);
|
|
2516
|
+
reporter.error("Linter:", err);
|
|
2517
|
+
result.errors += 1;
|
|
2518
|
+
}
|
|
2519
|
+
return result;
|
|
2520
|
+
}
|
|
2521
|
+
const doc = fileInfoToDocument(fileInfo, cfg.options.languageId, cfg.locale);
|
|
2522
|
+
const { text } = fileInfo;
|
|
2523
|
+
result.fileInfo = fileInfo;
|
|
2524
|
+
let spellResult = {};
|
|
2525
|
+
try {
|
|
2526
|
+
const { showSuggestions: generateSuggestions, validateDirectives, skipValidation } = cfg.options;
|
|
2527
|
+
const numSuggestions = configInfo.config.numSuggestions ?? 5;
|
|
2528
|
+
const r = await spellCheckDocument(doc, clean({
|
|
2529
|
+
generateSuggestions,
|
|
2530
|
+
numSuggestions,
|
|
2531
|
+
validateDirectives,
|
|
2532
|
+
skipValidation
|
|
2533
|
+
}), configInfo.config);
|
|
2534
|
+
spellResult = r;
|
|
2535
|
+
result.processed = r.checked;
|
|
2536
|
+
result.perf = r.perf ? { ...r.perf } : void 0;
|
|
2537
|
+
result.issues = Text.calculateTextDocumentOffsets(doc.uri, text, r.issues).map(mapIssue);
|
|
2538
|
+
} catch (e) {
|
|
2539
|
+
reporter.error(`Failed to process "${filename}"`, toError$1(e));
|
|
2540
|
+
result.errors += 1;
|
|
2541
|
+
}
|
|
2542
|
+
result.elapsedTimeMs = getElapsedTimeMs();
|
|
2543
|
+
const config = spellResult.settingsUsed ?? {};
|
|
2544
|
+
result.reportIssueOptions = mergeReportIssueOptions(spellResult.settingsUsed || configInfo.config, reportIssueOptions);
|
|
2545
|
+
result.configErrors += await reportConfigurationErrors(config, processFileOptions);
|
|
2546
|
+
reportCheckResult(result, doc, spellResult, config, processFileOptions);
|
|
2547
|
+
const dep = calcDependencies(config);
|
|
2548
|
+
await cache.setCachedLintResults(result, dep.files);
|
|
2549
|
+
return result;
|
|
2550
|
+
function mapIssue({ doc: _, ...tdo }) {
|
|
2551
|
+
const context = cfg.showContext ? extractContext(tdo, cfg.showContext) : void 0;
|
|
2552
|
+
return clean({
|
|
2553
|
+
...tdo,
|
|
2554
|
+
context
|
|
2555
|
+
});
|
|
2556
|
+
}
|
|
2557
|
+
}
|
|
2558
|
+
function reportCheckResult(result, _doc, spellResult, config, processFileOptions) {
|
|
2559
|
+
const { configInfo, reporter, verboseLevel, useColor, cfg, chalk: chalk$1 } = processFileOptions;
|
|
2560
|
+
const elapsed = result.elapsedTimeMs || 0;
|
|
2561
|
+
const dictionaries = config.dictionaries || [];
|
|
2562
|
+
if (verboseLevel > 1) {
|
|
2563
|
+
const dictsUsed = [...dictionaries].sort().map((name$1) => chalk$1.green(name$1)).join(", ");
|
|
2564
|
+
const msg = unindent`
|
|
2565
|
+
File type: ${config.languageId}, Language: ${config.language}, Issues: ${result.issues.length} ${elapsed.toFixed(2)}ms
|
|
2566
|
+
Config file Used: ${relativeToCwd(spellResult.localConfigFilepath || configInfo.source, cfg.root)}
|
|
2567
|
+
Dictionaries Used:
|
|
2568
|
+
${wordWrapAnsiText(dictsUsed, 70)}`;
|
|
2569
|
+
reporter.info(indent(msg, " "), MessageTypes.Info);
|
|
2570
|
+
}
|
|
2571
|
+
if (cfg.options.debug) {
|
|
2572
|
+
const { enabled, language, languageId, dictionaries: dictionaries$1 } = config;
|
|
2573
|
+
const msg = unindent`\
|
|
2574
|
+
Debug Config: ${formatWithOptions({
|
|
2575
|
+
depth: 2,
|
|
2576
|
+
colors: useColor
|
|
2577
|
+
}, {
|
|
2578
|
+
languageId,
|
|
2579
|
+
enabled,
|
|
2580
|
+
language,
|
|
2581
|
+
dictionaries: dictionaries$1
|
|
2582
|
+
})}`;
|
|
2583
|
+
reporter.debug(msg);
|
|
2584
|
+
}
|
|
2585
|
+
}
|
|
2586
|
+
function calcDependencies(config) {
|
|
2587
|
+
const { configFiles, dictionaryFiles } = extractDependencies(config);
|
|
2588
|
+
return { files: [...configFiles, ...dictionaryFiles] };
|
|
2589
|
+
}
|
|
2590
|
+
async function reportConfigurationErrors(config, processFileOptions) {
|
|
2591
|
+
const { reporter, configErrors } = processFileOptions;
|
|
2592
|
+
const errors = extractImportErrors(config);
|
|
2593
|
+
let count = 0;
|
|
2594
|
+
errors.forEach((ref) => {
|
|
2595
|
+
const key = ref.error.toString();
|
|
2596
|
+
if (configErrors.has(key)) return;
|
|
2597
|
+
configErrors.add(key);
|
|
2598
|
+
count += 1;
|
|
2599
|
+
reporter.error("Configuration", ref.error);
|
|
2600
|
+
});
|
|
2601
|
+
(await getDictionary(config)).dictionaries.forEach((dict) => {
|
|
2602
|
+
const dictErrors = dict.getErrors?.() || [];
|
|
2603
|
+
const msg = `Dictionary Error with (${dict.name})`;
|
|
2604
|
+
dictErrors.forEach((error) => {
|
|
2605
|
+
const key = msg + error.toString();
|
|
2606
|
+
if (configErrors.has(key)) return;
|
|
2607
|
+
configErrors.add(key);
|
|
2608
|
+
count += 1;
|
|
2609
|
+
reporter.error(msg, error);
|
|
2610
|
+
});
|
|
2611
|
+
});
|
|
2612
|
+
return count;
|
|
2613
|
+
}
|
|
2614
|
+
function countConfigErrors(configInfo, processFileOptions) {
|
|
2615
|
+
return reportConfigurationErrors(configInfo.config, processFileOptions);
|
|
2616
|
+
}
|
|
2617
|
+
|
|
1898
2618
|
//#endregion
|
|
1899
2619
|
//#region src/lint/lint.ts
|
|
1900
2620
|
const version = npmPackage.version;
|
|
@@ -1903,9 +2623,11 @@ const { opFilterAsync } = operators;
|
|
|
1903
2623
|
async function runLint(cfg) {
|
|
1904
2624
|
const reporter = new LintReporter(cfg.reporter, cfg.options);
|
|
1905
2625
|
const configErrors = /* @__PURE__ */ new Set();
|
|
2626
|
+
const verboseLevel = calcVerboseLevel(cfg.options);
|
|
2627
|
+
const useColor = cfg.options.color ?? true;
|
|
1906
2628
|
const timer = getTimeMeasurer();
|
|
1907
2629
|
const logDictRequests = truthy(getEnvironmentVariable("CSPELL_ENABLE_DICTIONARY_LOGGING"));
|
|
1908
|
-
if (logDictRequests)
|
|
2630
|
+
if (logDictRequests) dictionaryCacheEnableLogging(true);
|
|
1909
2631
|
const lintResult = await run();
|
|
1910
2632
|
if (logDictRequests) await writeDictionaryLog();
|
|
1911
2633
|
await reporter.result(lintResult);
|
|
@@ -1915,7 +2637,10 @@ async function runLint(cfg) {
|
|
|
1915
2637
|
function prefetch(filename, configInfo, cache) {
|
|
1916
2638
|
if (isBinaryFile$1(filename, cfg.root)) return {
|
|
1917
2639
|
filename,
|
|
1918
|
-
result: Promise.resolve({
|
|
2640
|
+
result: Promise.resolve({
|
|
2641
|
+
skip: true,
|
|
2642
|
+
skipReason: "Binary file."
|
|
2643
|
+
})
|
|
1919
2644
|
};
|
|
1920
2645
|
const reportIssueOptions = extractReporterIssueOptions(configInfo.config);
|
|
1921
2646
|
async function fetch$1() {
|
|
@@ -1929,7 +2654,18 @@ async function runLint(cfg) {
|
|
|
1929
2654
|
} };
|
|
1930
2655
|
}
|
|
1931
2656
|
const uri = filenameToUri(filename, cfg.root).href;
|
|
1932
|
-
|
|
2657
|
+
const checkResult = await shouldCheckDocument({ uri }, {}, configInfo.config);
|
|
2658
|
+
if (!checkResult.shouldCheck) return {
|
|
2659
|
+
skip: true,
|
|
2660
|
+
skipReason: checkResult.reason || "Ignored by configuration."
|
|
2661
|
+
};
|
|
2662
|
+
const maxFileSize = processMaxFileSize(cfg.maxFileSize ?? checkResult.settings.maxFileSize);
|
|
2663
|
+
if (maxFileSize) {
|
|
2664
|
+
if (await getFileSize(filename) > maxFileSize) return {
|
|
2665
|
+
skip: true,
|
|
2666
|
+
skipReason: `File exceeded max file size of ${maxFileSize.toLocaleString()}`
|
|
2667
|
+
};
|
|
2668
|
+
}
|
|
1933
2669
|
return {
|
|
1934
2670
|
fileInfo: await readFileInfo(filename, void 0, true),
|
|
1935
2671
|
reportIssueOptions
|
|
@@ -1937,97 +2673,8 @@ async function runLint(cfg) {
|
|
|
1937
2673
|
}
|
|
1938
2674
|
return {
|
|
1939
2675
|
filename,
|
|
1940
|
-
result: fetch$1()
|
|
1941
|
-
};
|
|
1942
|
-
}
|
|
1943
|
-
async function processFile(filename, configInfo, cache, prefetch$1) {
|
|
1944
|
-
if (prefetch$1?.fileResult) return prefetch$1.fileResult;
|
|
1945
|
-
const getElapsedTimeMs = getTimeMeasurer();
|
|
1946
|
-
const reportIssueOptions = prefetch$1?.reportIssueOptions;
|
|
1947
|
-
const cachedResult = await cache.getCachedLintResults(filename);
|
|
1948
|
-
if (cachedResult) {
|
|
1949
|
-
reporter.debug(`Filename: ${filename}, using cache`);
|
|
1950
|
-
return {
|
|
1951
|
-
...cachedResult,
|
|
1952
|
-
elapsedTimeMs: getElapsedTimeMs(),
|
|
1953
|
-
reportIssueOptions: {
|
|
1954
|
-
...cachedResult.reportIssueOptions,
|
|
1955
|
-
...reportIssueOptions
|
|
1956
|
-
}
|
|
1957
|
-
};
|
|
1958
|
-
}
|
|
1959
|
-
const result = {
|
|
1960
|
-
fileInfo: { filename },
|
|
1961
|
-
issues: [],
|
|
1962
|
-
processed: false,
|
|
1963
|
-
errors: 0,
|
|
1964
|
-
configErrors: 0,
|
|
1965
|
-
elapsedTimeMs: 0,
|
|
1966
|
-
reportIssueOptions
|
|
2676
|
+
result: fetch$1().catch((e) => toApplicationError(e))
|
|
1967
2677
|
};
|
|
1968
|
-
const fileInfo = prefetch$1?.fileInfo || await readFileInfo(filename, void 0, true);
|
|
1969
|
-
if (fileInfo.errorCode) {
|
|
1970
|
-
if (fileInfo.errorCode !== "EISDIR" && cfg.options.mustFindFiles) {
|
|
1971
|
-
const err = new LinterError(`File not found: "${filename}"`);
|
|
1972
|
-
reporter.error("Linter:", err);
|
|
1973
|
-
result.errors += 1;
|
|
1974
|
-
}
|
|
1975
|
-
return result;
|
|
1976
|
-
}
|
|
1977
|
-
const doc = fileInfoToDocument(fileInfo, cfg.options.languageId, cfg.locale);
|
|
1978
|
-
const { text } = fileInfo;
|
|
1979
|
-
result.fileInfo = fileInfo;
|
|
1980
|
-
let spellResult = {};
|
|
1981
|
-
reporter.info(`Checking: ${filename}, File type: ${doc.languageId ?? "auto"}, Language: ${doc.locale ?? "default"}`, MessageTypes.Info);
|
|
1982
|
-
try {
|
|
1983
|
-
const { showSuggestions: generateSuggestions, validateDirectives, skipValidation } = cfg.options;
|
|
1984
|
-
const numSuggestions = configInfo.config.numSuggestions ?? 5;
|
|
1985
|
-
const r = await spellCheckDocument(doc, clean({
|
|
1986
|
-
generateSuggestions,
|
|
1987
|
-
numSuggestions,
|
|
1988
|
-
validateDirectives,
|
|
1989
|
-
skipValidation
|
|
1990
|
-
}), configInfo.config);
|
|
1991
|
-
spellResult = r;
|
|
1992
|
-
result.processed = r.checked;
|
|
1993
|
-
result.perf = r.perf ? { ...r.perf } : void 0;
|
|
1994
|
-
result.issues = Text.calculateTextDocumentOffsets(doc.uri, text, r.issues).map(mapIssue);
|
|
1995
|
-
} catch (e) {
|
|
1996
|
-
reporter.error(`Failed to process "${filename}"`, toError(e));
|
|
1997
|
-
result.errors += 1;
|
|
1998
|
-
}
|
|
1999
|
-
result.elapsedTimeMs = getElapsedTimeMs();
|
|
2000
|
-
const config = spellResult.settingsUsed ?? {};
|
|
2001
|
-
result.reportIssueOptions = mergeReportIssueOptions(spellResult.settingsUsed || configInfo.config, reportIssueOptions);
|
|
2002
|
-
result.configErrors += await reportConfigurationErrors(config);
|
|
2003
|
-
const elapsed$1 = result.elapsedTimeMs;
|
|
2004
|
-
const dictionaries = config.dictionaries || [];
|
|
2005
|
-
reporter.info(`Checked: ${filename}, File type: ${config.languageId}, Language: ${config.language} ... Issues: ${result.issues.length} ${elapsed$1.toFixed(2)}ms`, MessageTypes.Info);
|
|
2006
|
-
reporter.info(`Config file Used: ${spellResult.localConfigFilepath || configInfo.source}`, MessageTypes.Info);
|
|
2007
|
-
reporter.info(`Dictionaries Used: ${dictionaries.join(", ")}`, MessageTypes.Info);
|
|
2008
|
-
if (cfg.options.debug) {
|
|
2009
|
-
const { id: _id, name: _name, __imports, __importRef,...cfg$1 } = config;
|
|
2010
|
-
const debugCfg = {
|
|
2011
|
-
filename,
|
|
2012
|
-
languageId: doc.languageId ?? cfg$1.languageId ?? "default",
|
|
2013
|
-
config: {
|
|
2014
|
-
...cfg$1,
|
|
2015
|
-
source: null
|
|
2016
|
-
},
|
|
2017
|
-
source: spellResult.localConfigFilepath
|
|
2018
|
-
};
|
|
2019
|
-
reporter.debug(JSON.stringify(debugCfg, void 0, 2));
|
|
2020
|
-
}
|
|
2021
|
-
const dep = calcDependencies(config);
|
|
2022
|
-
await cache.setCachedLintResults(result, dep.files);
|
|
2023
|
-
return result;
|
|
2024
|
-
}
|
|
2025
|
-
function mapIssue({ doc: _,...tdo }) {
|
|
2026
|
-
const context = cfg.showContext ? extractContext(tdo, cfg.showContext) : void 0;
|
|
2027
|
-
return clean({
|
|
2028
|
-
...tdo,
|
|
2029
|
-
context
|
|
2030
|
-
});
|
|
2031
2678
|
}
|
|
2032
2679
|
async function processFiles(files, configInfo, cacheSettings) {
|
|
2033
2680
|
const fileCount = Array.isArray(files) ? files.length : void 0;
|
|
@@ -2054,6 +2701,7 @@ async function runLint(cfg) {
|
|
|
2054
2701
|
const { filename, result: pFetchResult } = pf;
|
|
2055
2702
|
const getElapsedTimeMs = getTimeMeasurer();
|
|
2056
2703
|
const fetchResult = await pFetchResult;
|
|
2704
|
+
if (fetchResult instanceof Error) throw fetchResult;
|
|
2057
2705
|
reporter.emitProgressBegin(filename, index, fileCount ?? index);
|
|
2058
2706
|
if (fetchResult?.skip) return {
|
|
2059
2707
|
filename,
|
|
@@ -2061,13 +2709,14 @@ async function runLint(cfg) {
|
|
|
2061
2709
|
result: {
|
|
2062
2710
|
...emptyResult,
|
|
2063
2711
|
fileInfo: { filename },
|
|
2064
|
-
elapsedTimeMs: getElapsedTimeMs()
|
|
2712
|
+
elapsedTimeMs: getElapsedTimeMs(),
|
|
2713
|
+
skippedReason: fetchResult.skipReason
|
|
2065
2714
|
}
|
|
2066
2715
|
};
|
|
2067
2716
|
return {
|
|
2068
2717
|
filename,
|
|
2069
2718
|
fileNum: index,
|
|
2070
|
-
result: await processFile(filename,
|
|
2719
|
+
result: await processFile(filename, cache, fetchResult, getProcessFileOptions(configInfo))
|
|
2071
2720
|
};
|
|
2072
2721
|
}
|
|
2073
2722
|
async function* loadAndProcessFiles() {
|
|
@@ -2082,6 +2731,7 @@ async function runLint(cfg) {
|
|
|
2082
2731
|
const { filename, fileNum, result } = fileP;
|
|
2083
2732
|
status.files += 1;
|
|
2084
2733
|
status.cachedFiles = (status.cachedFiles || 0) + (result.cached ? 1 : 0);
|
|
2734
|
+
status.skippedFiles = (status.skippedFiles || 0) + (result.processed ? 0 : 1);
|
|
2085
2735
|
const numIssues = reporter.emitProgressComplete(filename, fileNum, fileCount ?? fileNum, result);
|
|
2086
2736
|
if (numIssues || result.errors) {
|
|
2087
2737
|
status.filesWithIssues.add(relativeToCwd(filename, cfg.root));
|
|
@@ -2094,39 +2744,10 @@ async function runLint(cfg) {
|
|
|
2094
2744
|
await cache.reconcile();
|
|
2095
2745
|
return status;
|
|
2096
2746
|
}
|
|
2097
|
-
function calcDependencies(config) {
|
|
2098
|
-
const { configFiles, dictionaryFiles } = extractDependencies(config);
|
|
2099
|
-
return { files: [...configFiles, ...dictionaryFiles] };
|
|
2100
|
-
}
|
|
2101
|
-
async function reportConfigurationErrors(config) {
|
|
2102
|
-
const errors = extractImportErrors(config);
|
|
2103
|
-
let count = 0;
|
|
2104
|
-
errors.forEach((ref) => {
|
|
2105
|
-
const key = ref.error.toString();
|
|
2106
|
-
if (configErrors.has(key)) return;
|
|
2107
|
-
configErrors.add(key);
|
|
2108
|
-
count += 1;
|
|
2109
|
-
reporter.error("Configuration", ref.error);
|
|
2110
|
-
});
|
|
2111
|
-
(await getDictionary(config)).dictionaries.forEach((dict) => {
|
|
2112
|
-
const dictErrors = dict.getErrors?.() || [];
|
|
2113
|
-
const msg = `Dictionary Error with (${dict.name})`;
|
|
2114
|
-
dictErrors.forEach((error) => {
|
|
2115
|
-
const key = msg + error.toString();
|
|
2116
|
-
if (configErrors.has(key)) return;
|
|
2117
|
-
configErrors.add(key);
|
|
2118
|
-
count += 1;
|
|
2119
|
-
reporter.error(msg, error);
|
|
2120
|
-
});
|
|
2121
|
-
});
|
|
2122
|
-
return count;
|
|
2123
|
-
}
|
|
2124
|
-
function countConfigErrors(configInfo) {
|
|
2125
|
-
return reportConfigurationErrors(configInfo.config);
|
|
2126
|
-
}
|
|
2127
2747
|
async function run() {
|
|
2128
2748
|
if (cfg.options.root) setEnvironmentVariable(ENV_CSPELL_GLOB_ROOT, cfg.root);
|
|
2129
2749
|
const configInfo = await readConfig(cfg.configFile, cfg.root, cfg.options.stopConfigSearchAt);
|
|
2750
|
+
const processFileOptions = getProcessFileOptions(configInfo);
|
|
2130
2751
|
if (cfg.options.defaultConfiguration !== void 0) configInfo.config.loadDefaultConfiguration = cfg.options.defaultConfiguration;
|
|
2131
2752
|
configInfo.config = mergeSettings(configInfo.config, cfg.cspellSettingsFromCliOptions);
|
|
2132
2753
|
const reporterConfig = clean({
|
|
@@ -2139,15 +2760,15 @@ async function runLint(cfg) {
|
|
|
2139
2760
|
const reporters = cfg.options.reporter ?? configInfo.config.reporters;
|
|
2140
2761
|
reporter.config = reporterConfig;
|
|
2141
2762
|
await reporter.loadReportersAndFinalize(reporters);
|
|
2142
|
-
setLogger(getLoggerFromReporter(reporter));
|
|
2763
|
+
setLogger(getLoggerFromReporter(reporter, useColor));
|
|
2143
2764
|
const globInfo = await determineGlobs(configInfo, cfg);
|
|
2144
2765
|
const { fileGlobs, excludeGlobs } = globInfo;
|
|
2145
2766
|
const hasFileLists = !!cfg.fileLists.length;
|
|
2146
2767
|
if (!fileGlobs.length && !hasFileLists && !cfg.files?.length) return runResult();
|
|
2147
2768
|
header(fileGlobs, excludeGlobs);
|
|
2148
2769
|
checkGlobs(fileGlobs, reporter);
|
|
2149
|
-
reporter.info(`Config Files Found:\n ${configInfo.source}\n`, MessageTypes.Info);
|
|
2150
|
-
const configErrors$1 = await countConfigErrors(configInfo);
|
|
2770
|
+
if (verboseLevel > 1) reporter.info(`Config Files Found:\n ${relativeToCwd(configInfo.source)}\n`, MessageTypes$1.Info);
|
|
2771
|
+
const configErrors$1 = await countConfigErrors(configInfo, processFileOptions);
|
|
2151
2772
|
if (configErrors$1 && cfg.options.exitCode !== false && !cfg.options.continueOnError) return runResult({ errors: configErrors$1 });
|
|
2152
2773
|
const { root } = cfg;
|
|
2153
2774
|
try {
|
|
@@ -2165,18 +2786,30 @@ async function runLint(cfg) {
|
|
|
2165
2786
|
}
|
|
2166
2787
|
}
|
|
2167
2788
|
function header(files, cliExcludes) {
|
|
2789
|
+
if (verboseLevel < 2) return;
|
|
2168
2790
|
const formattedFiles = files.length > 100 ? [...files.slice(0, 100), "..."] : files;
|
|
2169
|
-
reporter.info(`
|
|
2170
|
-
cspell;
|
|
2171
|
-
Date: ${(/* @__PURE__ */ new Date()).toUTCString()}
|
|
2172
|
-
Options:
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
`, MessageTypes.Info);
|
|
2791
|
+
reporter.info(unindent`
|
|
2792
|
+
cspell;
|
|
2793
|
+
Date: ${(/* @__PURE__ */ new Date()).toUTCString()}
|
|
2794
|
+
Options:
|
|
2795
|
+
verbose: ${yesNo(!!cfg.options.verbose)}
|
|
2796
|
+
config: ${cfg.configFile || "default"}
|
|
2797
|
+
exclude: ${wordWrapAnsiText(cliExcludes.join(", "), 60, " ")}
|
|
2798
|
+
files: ${formattedFiles}
|
|
2799
|
+
wordsOnly: ${yesNo(!!cfg.options.wordsOnly)}
|
|
2800
|
+
unique: ${yesNo(!!cfg.options.unique)}
|
|
2801
|
+
`, MessageTypes$1.Info);
|
|
2802
|
+
}
|
|
2803
|
+
function getProcessFileOptions(configInfo) {
|
|
2804
|
+
return {
|
|
2805
|
+
reporter,
|
|
2806
|
+
chalk,
|
|
2807
|
+
configInfo,
|
|
2808
|
+
cfg,
|
|
2809
|
+
verboseLevel,
|
|
2810
|
+
useColor,
|
|
2811
|
+
configErrors
|
|
2812
|
+
};
|
|
2180
2813
|
}
|
|
2181
2814
|
}
|
|
2182
2815
|
function checkGlobs(globs, reporter) {
|
|
@@ -2208,7 +2841,7 @@ async function determineFilesToCheck(configInfo, cfg, reporter, globInfo) {
|
|
|
2208
2841
|
const globsToExclude = globsToExcludeRaw.filter((g) => !globPattern(g).startsWith("!"));
|
|
2209
2842
|
if (globsToExclude.length !== globsToExcludeRaw.length) {
|
|
2210
2843
|
const msg = `Negative glob exclusions are not supported: ${globsToExcludeRaw.map((g) => globPattern(g)).filter((g) => g.startsWith("!")).join(", ")}`;
|
|
2211
|
-
reporter.info(msg, MessageTypes.Warning);
|
|
2844
|
+
reporter.info(msg, MessageTypes$1.Warning);
|
|
2212
2845
|
}
|
|
2213
2846
|
const globMatcher = buildGlobMatcher(globsToExclude, root, true);
|
|
2214
2847
|
const globOptions = {
|
|
@@ -2234,13 +2867,13 @@ async function determineFilesToCheck(configInfo, cfg, reporter, globInfo) {
|
|
|
2234
2867
|
const r = globMatcherExclude.matchEx(absFilename);
|
|
2235
2868
|
if (r.matched) {
|
|
2236
2869
|
const { glob: glob$2, source } = extractGlobSource(r.pattern);
|
|
2237
|
-
reporter.info(`Excluded File: ${path$1.relative(root, absFilename)}; Excluded by ${glob$2} from ${source}`, MessageTypes.Info);
|
|
2870
|
+
if (calcVerboseLevel(cfg.options) > 1) reporter.info(`Excluded File: ${path$1.relative(root, absFilename)}; Excluded by ${glob$2} from ${source}`, MessageTypes$1.Info);
|
|
2238
2871
|
}
|
|
2239
2872
|
return r.matched;
|
|
2240
2873
|
}
|
|
2241
2874
|
function filterOutExcludedFilesFn(globMatcherExclude) {
|
|
2242
2875
|
const excludeInfo = globMatcherExclude.patterns.map(extractGlobSource).map(({ glob: glob$2, source }) => `Glob: ${glob$2} from ${source}`).filter(uniqueFn());
|
|
2243
|
-
reporter.info(`Exclusion Globs: \n ${excludeInfo.join("\n ")}\n`, MessageTypes.Info);
|
|
2876
|
+
if (calcVerboseLevel(cfg.options) > 1) reporter.info(`Exclusion Globs: \n ${excludeInfo.join("\n ")}\n`, MessageTypes$1.Info);
|
|
2244
2877
|
return (filename) => !isExcluded(filename, globMatcherExclude);
|
|
2245
2878
|
}
|
|
2246
2879
|
return _determineFilesToCheck();
|
|
@@ -2265,13 +2898,14 @@ function runResult(init = {}) {
|
|
|
2265
2898
|
function yesNo(value) {
|
|
2266
2899
|
return value ? "Yes" : "No";
|
|
2267
2900
|
}
|
|
2268
|
-
function getLoggerFromReporter(reporter) {
|
|
2901
|
+
function getLoggerFromReporter(reporter, useColor) {
|
|
2902
|
+
const inspectOptions = { colors: useColor };
|
|
2269
2903
|
const log = (...params) => {
|
|
2270
|
-
const msg =
|
|
2904
|
+
const msg = formatWithOptions(inspectOptions, ...params);
|
|
2271
2905
|
reporter.info(msg, "Info");
|
|
2272
2906
|
};
|
|
2273
2907
|
const error = (...params) => {
|
|
2274
|
-
const msg =
|
|
2908
|
+
const msg = formatWithOptions(inspectOptions, ...params);
|
|
2275
2909
|
reporter.error(msg, {
|
|
2276
2910
|
message: "",
|
|
2277
2911
|
name: "error",
|
|
@@ -2279,7 +2913,7 @@ function getLoggerFromReporter(reporter) {
|
|
|
2279
2913
|
});
|
|
2280
2914
|
};
|
|
2281
2915
|
const warn = (...params) => {
|
|
2282
|
-
const msg =
|
|
2916
|
+
const msg = formatWithOptions(inspectOptions, ...params);
|
|
2283
2917
|
reporter.info(msg, "Warning");
|
|
2284
2918
|
};
|
|
2285
2919
|
return {
|
|
@@ -2319,20 +2953,22 @@ async function* concatAsyncIterables(...iterables) {
|
|
|
2319
2953
|
}
|
|
2320
2954
|
async function writeDictionaryLog() {
|
|
2321
2955
|
const fields = (getEnvironmentVariable("CSPELL_ENABLE_DICTIONARY_LOG_FIELDS") || "time, word, value").split(",").map((f) => f.trim());
|
|
2322
|
-
const data = fields.join(", ") + "\n" +
|
|
2956
|
+
const data = fields.join(", ") + "\n" + dictionaryCacheGetLog().filter((d) => d.method === "has").map((d) => fields.map((f) => f in d ? `${d[f]}` : "").join(", ")).join("\n") + "\n";
|
|
2323
2957
|
await writeFileOrStream(getEnvironmentVariable("CSPELL_ENABLE_DICTIONARY_LOG_FILE") || "cspell-dictionary-log.csv", data);
|
|
2324
2958
|
}
|
|
2325
2959
|
function globPattern(g) {
|
|
2326
2960
|
return typeof g === "string" ? g : g.glob;
|
|
2327
2961
|
}
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
};
|
|
2962
|
+
function calcVerboseLevel(options) {
|
|
2963
|
+
return options.verboseLevel ?? (options.verbose ? 1 : 0);
|
|
2964
|
+
}
|
|
2965
|
+
function processMaxFileSize(value) {
|
|
2966
|
+
if (!value) return void 0;
|
|
2967
|
+
if (typeof value === "number") return value;
|
|
2968
|
+
const num = sizeToNumber(value);
|
|
2969
|
+
if (Number.isNaN(num)) throw new ApplicationError(`Invalid max file size: "${value}"`);
|
|
2970
|
+
return num;
|
|
2971
|
+
}
|
|
2336
2972
|
|
|
2337
2973
|
//#endregion
|
|
2338
2974
|
//#region src/lint/LintRequest.ts
|
|
@@ -2347,6 +2983,7 @@ var LintRequest = class {
|
|
|
2347
2983
|
fileLists;
|
|
2348
2984
|
files;
|
|
2349
2985
|
cspellSettingsFromCliOptions;
|
|
2986
|
+
maxFileSize;
|
|
2350
2987
|
constructor(fileGlobs, options, reporter) {
|
|
2351
2988
|
this.fileGlobs = fileGlobs;
|
|
2352
2989
|
this.options = options;
|
|
@@ -2370,6 +3007,7 @@ var LintRequest = class {
|
|
|
2370
3007
|
...extractUnknownWordsConfig(options),
|
|
2371
3008
|
languageSettings
|
|
2372
3009
|
};
|
|
3010
|
+
this.maxFileSize = options.maxFileSize ? sizeToNumber(options.maxFileSize) : void 0;
|
|
2373
3011
|
}
|
|
2374
3012
|
};
|
|
2375
3013
|
function mergeFiles(a, b) {
|
|
@@ -2411,10 +3049,19 @@ const ReportChoicesAll = [
|
|
|
2411
3049
|
"flagged"
|
|
2412
3050
|
];
|
|
2413
3051
|
function fixLegacy(opts) {
|
|
2414
|
-
const { local
|
|
3052
|
+
const { local, ...rest } = opts;
|
|
2415
3053
|
if (local && !rest.locale) rest.locale = local;
|
|
2416
3054
|
return rest;
|
|
2417
3055
|
}
|
|
3056
|
+
function cvtLinterCliCommandOptionsToLinterCliOptions(options) {
|
|
3057
|
+
const { verbose: verboseLevel, ...optionsRest } = options;
|
|
3058
|
+
const cliOptions = { ...optionsRest };
|
|
3059
|
+
if (verboseLevel) {
|
|
3060
|
+
cliOptions.verboseLevel = verboseLevel;
|
|
3061
|
+
cliOptions.verbose = true;
|
|
3062
|
+
}
|
|
3063
|
+
return cliOptions;
|
|
3064
|
+
}
|
|
2418
3065
|
|
|
2419
3066
|
//#endregion
|
|
2420
3067
|
//#region src/repl/index.ts
|
|
@@ -2655,5 +3302,5 @@ function parseApplicationFeatureFlags(flags) {
|
|
|
2655
3302
|
}
|
|
2656
3303
|
|
|
2657
3304
|
//#endregion
|
|
2658
|
-
export { parseApplicationFeatureFlags as a, listDictionaries as c,
|
|
2659
|
-
//# sourceMappingURL=application-
|
|
3305
|
+
export { CheckFailed as C, ApplicationError as S, padLeft as _, parseApplicationFeatureFlags as a, pruneAnsiTextStart as b, listDictionaries as c, validateUnitSize as d, unindent as f, tableToLines as g, getReporter as h, lint as i, ReportChoicesAll as l, npmPackage as m, checkText as n, suggestions as o, DEFAULT_CACHE_LOCATION as p, createInit as r, trace as s, IncludeExcludeFlag as t, cvtLinterCliCommandOptionsToLinterCliOptions as u, padWidth as v, console as w, width as x, pruneAnsiTextEnd as y };
|
|
3306
|
+
//# sourceMappingURL=application-BJHh60xM.js.map
|