Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions __tests__/report-unapplied-fixes.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { getUnappliedFixesWarnings } from '../src/utils/report-unapplied-fixes';
import type { BatchLintItem } from '../src/types';

const makeItem = (overrides: Partial<BatchLintItem> = {}): BatchLintItem => ({
path: 'doc.md',
lintResult: [],
...overrides,
});

describe('getUnappliedFixesWarnings', () => {
test('returns no warnings for an empty result', () => {
expect(getUnappliedFixesWarnings([])).toEqual([]);
});

test('returns no warnings when fixedResult is null', () => {
const result: BatchLintItem[] = [makeItem({ fixedResult: null })];
expect(getUnappliedFixesWarnings(result)).toEqual([]);
});

test('returns no warnings when notAppliedFixes is empty', () => {
const result: BatchLintItem[] = [
makeItem({ fixedResult: { result: 'x', notAppliedFixes: [] } }),
];
expect(getUnappliedFixesWarnings(result)).toEqual([]);
});

test('warns once with the correct count for a single unapplied fix', () => {
const result: BatchLintItem[] = [
makeItem({
path: 'a.md',
fixedResult: {
result: 'x',
notAppliedFixes: [{ range: [0, 1], text: 'y' }],
},
}),
];
expect(getUnappliedFixesWarnings(result)).toEqual([
'[lint-md] a.md: 1 fixes were not applied due to conflicts.',
]);
});

test('reports the count for multiple unapplied fixes and preserves the path', () => {
const result: BatchLintItem[] = [
makeItem({
path: 'conflict.md',
fixedResult: {
result: 'x',
notAppliedFixes: [
{ range: [0, 1], text: 'y' },
{ range: [2, 3], text: 'z' },
{ range: [4, 5], text: 'w' },
],
},
}),
];
expect(getUnappliedFixesWarnings(result)).toEqual([
'[lint-md] conflict.md: 3 fixes were not applied due to conflicts.',
]);
});

test('only warns for files that have unapplied fixes', () => {
const result: BatchLintItem[] = [
makeItem({
path: 'ok.md',
fixedResult: { result: 'x', notAppliedFixes: [] },
}),
makeItem({
path: 'bad.md',
fixedResult: {
result: 'x',
notAppliedFixes: [{ range: [0, 1], text: 'y' }],
},
}),
];
expect(getUnappliedFixesWarnings(result)).toEqual([
'[lint-md] bad.md: 1 fixes were not applied due to conflicts.',
]);
});

test('sanitizes file path in warning output', () => {
const result: BatchLintItem[] = [
makeItem({
path: 'bad\u001B[31m.md\nnext-line',
fixedResult: {
result: 'x',
notAppliedFixes: [{ range: [0, 1], text: 'y' }],
},
}),
];

expect(getUnappliedFixesWarnings(result)[0]).not.toContain('\u001B');
expect(getUnappliedFixesWarnings(result)[0]).not.toContain('\n');
});
});
5 changes: 5 additions & 0 deletions src/lint-md.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import type { CLIOptions, ThreadCount } from './types';
import { loadMdFiles } from './utils/load-md-files';
import { getReportData } from './utils/get-report-data';
import { filterFilesByMaxSize } from './utils/filter-by-max-size';
import { getUnappliedFixesWarnings } from './utils/report-unapplied-fixes';

program
.version(
Expand Down Expand Up @@ -178,6 +179,10 @@ program
.map(({ path, fixedResult }) => () => safeWriteFile(path, fixedResult!.result)),
effectiveThreads
);

for (const warning of getUnappliedFixesWarnings(lintResult)) {
console.error(warning);
}
}
}
catch (e) {
Expand Down
22 changes: 22 additions & 0 deletions src/utils/report-unapplied-fixes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { BatchLintItem } from '../types';
import { sanitizeTerminalText } from './sanitize-terminal';

// Returns stderr warning lines for files whose --fix pass left fixes
// unapplied due to conflicts. `fixedResult.notAppliedFixes` (from
// @lint-md/core) contains only the final-round conflicting fixes after
// core stopped dropping them across rounds, so the range coordinates are
// based on the returned result text and safe to report directly.
export const getUnappliedFixesWarnings = (lintResult: BatchLintItem[]): string[] => {
const warnings: string[] = [];

for (const item of lintResult) {
const count = item.fixedResult?.notAppliedFixes?.length ?? 0;
if (count > 0) {
warnings.push(
`[lint-md] ${sanitizeTerminalText(item.path)}: ${count} fixes were not applied due to conflicts.`
);
}
}

return warnings;
};