cspell
Version:
A Spelling Checker for Code!
149 lines • 5.38 kB
JavaScript
import * as iPath from 'node:path';
import chalk from 'chalk';
import { console } from '../console.js';
import { tableToLines } from '../util/table.js';
const maxWidth = 120;
const colWidthDictionaryName = 20;
export function emitTraceResults(word, found, results, options) {
const report = calcTraceResultsReport(word, found, results, options);
console.log(report.table);
if (report.errors) {
console.error('Errors:');
console.error(report.errors);
}
}
export function calcTraceResultsReport(word, found, results, options) {
const col = new Intl.Collator();
results.sort((a, b) => col.compare(a.dictName, b.dictName));
options.showWordFound && console.log(`${options.prefix || ''}${word}: ${found ? 'Found' : 'Not Found'}`);
const header = emitHeader(options.dictionaryPathFormat !== 'hide');
const rows = results.map((r) => emitTraceResult(r, options));
const t = tableToLines({
header,
rows,
terminalWidth: options.lineWidth || process.stdout.columns || maxWidth,
deliminator: ' ',
});
return {
table: t.map((line) => line.trimEnd()).join('\n'),
errors: emitErrors(results).join('\n'),
};
}
function emitHeader(location) {
const headers = ['Word', 'F', 'Dictionary'];
location && headers.push('Dictionary Location');
return headers;
}
function emitTraceResult(r, options) {
const errors = !!r.errors?.length;
const word = r.foundWord || r.word;
const cWord = word.replaceAll('+', chalk.yellow('+'));
const sug = r.preferredSuggestions?.map((s) => chalk.yellowBright(s)).join(', ') || '';
const w = (r.forbidden ? chalk.red(cWord) : chalk.green(cWord)) + (sug ? `->(${sug})` : '');
const f = calcFoundChar(r);
const a = r.dictActive ? '*' : ' ';
const dictName = r.dictName.slice(0, colWidthDictionaryName - 1) + a;
const dictColor = r.dictActive ? chalk.yellowBright : chalk.rgb(200, 128, 50);
const n = dictColor(dictName);
const c = colorize(errors ? chalk.red : chalk.white);
return [
w,
f,
n,
(widthSrc) => c(formatDictionaryLocation(r.dictSource, widthSrc ?? maxWidth, { iPath, ...options })),
];
}
function emitErrors(results) {
const errorResults = results.filter((r) => r.errors?.length);
return errorResults.map((r) => {
const errors = r.errors?.map((e) => e.message)?.join('\n\t') || '';
return chalk.bold(r.dictName) + '\n\t' + chalk.red(errors);
});
}
function trimMid(s, w) {
s = s.trim();
if (s.length <= w) {
return s;
}
const l = Math.floor((w - 3) / 2);
const r = Math.ceil((w - 3) / 2);
return s.slice(0, l) + '...' + s.slice(-r);
}
function calcFoundChar(r) {
const errors = r.errors?.map((e) => e.message)?.join('\n\t') || '';
let color = chalk.dim;
color = r.found ? chalk.whiteBright : color;
color = r.forbidden ? chalk.red : color;
color = r.noSuggest ? chalk.yellowBright : color;
color = errors ? chalk.red : color;
let char = '-';
char = r.found ? '*' : char;
char = r.forbidden ? '!' : char;
char = r.noSuggest ? 'I' : char;
char = errors ? 'X' : char;
return color(char);
}
function formatDictionaryLocation(dictSource, maxWidth, { cwd, dictionaryPathFormat: format, iPath, }) {
let relPath = cwd ? iPath.relative(cwd, dictSource) : dictSource;
const idxNodeModule = relPath.lastIndexOf('node_modules');
const isNodeModule = idxNodeModule >= 0;
if (format === 'hide')
return '';
if (format === 'short') {
const prefix = isNodeModule
? '[node_modules]/'
: relPath.startsWith('..' + iPath.sep + '..')
? '.../'
: relPath.startsWith('..' + iPath.sep)
? '../'
: '';
return prefix + iPath.basename(dictSource);
}
if (format === 'full')
return dictSource;
relPath = isNodeModule ? relPath.slice(idxNodeModule) : relPath;
const usePath = relPath.length < dictSource.length ? relPath : dictSource;
return trimMidPath(usePath, maxWidth, iPath.sep);
}
function colorize(fn) {
return (s) => (s ? fn(s) : '');
}
function trimMidPath(s, w, sep) {
if (s.length <= w)
return s;
const parts = s.split(sep);
if (parts[parts.length - 1].length > w)
return trimMid(s, w);
function join(left, right) {
// if (left === right) return parts.join(sep);
return [...parts.slice(0, left), '...', ...parts.slice(right)].join(sep);
}
let left = 0, right = parts.length, last = '';
for (let i = 0; i < parts.length; ++i) {
const incLeft = i & 1 ? 1 : 0;
const incRight = incLeft ? 0 : -1;
const next = join(left + incLeft, right + incRight);
if (next.length > w)
break;
left += incLeft;
right += incRight;
last = next;
}
for (let i = left + 1; i < right; ++i) {
const next = join(i, right);
if (next.length > w)
break;
last = next;
}
for (let i = right - 1; i > left; --i) {
const next = join(left, i);
if (next.length > w)
break;
last = next;
}
return last || trimMid(s, w);
}
export const __testing__ = {
trimMidPath,
};
//# sourceMappingURL=traceEmitter.js.map