58 lines
1.8 KiB
JavaScript
58 lines
1.8 KiB
JavaScript
// Markdownlint custom rules
|
|
|
|
const { trimBlankLinesFromArray } = require('../_util');
|
|
|
|
module.exports = {
|
|
names: ['trim-code-block-and-unindent'],
|
|
description:
|
|
'Code block: avoid leading/trailing empty lines and excess indentation',
|
|
// What is considered excess indentation? If the code-block code lines can be
|
|
// trimmed of some leading whitespace while preserving the relative
|
|
// indentation of non-whitespace characters, then an issue is reported.
|
|
tags: ['custom'],
|
|
function: (params, onError) => {
|
|
params.tokens.forEach(processToken.bind({ onError: onError }));
|
|
},
|
|
};
|
|
|
|
function processToken(token) {
|
|
if (token.type !== 'fence') return;
|
|
|
|
const lines = token.content.split('\n');
|
|
const originalNumLines = lines.length;
|
|
|
|
let minIndent = Infinity;
|
|
for (const line of lines) {
|
|
if (!line.trim().length) continue;
|
|
const currentIndent = line.length - line.trimStart().length;
|
|
minIndent = Math.min(minIndent, currentIndent);
|
|
}
|
|
|
|
let fixedLines = lines.map(
|
|
(line) =>
|
|
line.trim().length === 0
|
|
? '' // Blank-only lines
|
|
: line.substring(minIndent), // Unindent
|
|
);
|
|
fixedLines = trimBlankLinesFromArray(fixedLines);
|
|
const fixedContent = fixedLines.join('\n');
|
|
|
|
if (token.content === fixedContent + '\n') return;
|
|
|
|
const offset = 1; // 1-based
|
|
const codeFenceLineCount = 1;
|
|
const args = {
|
|
lineNumber: token.map[0] + offset + codeFenceLineCount,
|
|
detail: 'Trim empty lines and/or unindent',
|
|
context: token.line,
|
|
fixInfo: {
|
|
// Using the following as an endLineNumber
|
|
lineNumber: token.map[0] + originalNumLines + offset - codeFenceLineCount,
|
|
insertText: fixedContent,
|
|
},
|
|
};
|
|
// console.log(JSON.stringify(args, null, 2));
|
|
// console.log(`${token.lineNumber} - Line ${token.map[0]} to ${token.map[1]}:`, token.content);
|
|
this.onError(args);
|
|
}
|