mirror of
https://github.com/DavidAnson/markdownlint.git
synced 2025-12-17 06:20:12 +01:00
Update applyFix/es to preserve the dominant line ending for each input.
This commit is contained in:
parent
220a1d78a9
commit
b77a56255f
2 changed files with 112 additions and 6 deletions
|
|
@ -2,9 +2,11 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
const os = require("os");
|
||||||
|
|
||||||
// Regular expression for matching common newline characters
|
// Regular expression for matching common newline characters
|
||||||
// See NEWLINES_RE in markdown-it/lib/rules_core/normalize.js
|
// See NEWLINES_RE in markdown-it/lib/rules_core/normalize.js
|
||||||
const newLineRe = /\r\n?|\n/;
|
const newLineRe = /\r\n?|\n/g;
|
||||||
module.exports.newLineRe = newLineRe;
|
module.exports.newLineRe = newLineRe;
|
||||||
|
|
||||||
// Regular expression for matching common front matter (YAML and TOML)
|
// Regular expression for matching common front matter (YAML and TOML)
|
||||||
|
|
@ -404,6 +406,40 @@ module.exports.frontMatterHasTitle =
|
||||||
frontMatterLines.some((line) => frontMatterTitleRe.test(line));
|
frontMatterLines.some((line) => frontMatterTitleRe.test(line));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Gets the most common line ending, falling back to platform default
|
||||||
|
function getPreferredLineEnding(input) {
|
||||||
|
let cr = 0;
|
||||||
|
let lf = 0;
|
||||||
|
let crlf = 0;
|
||||||
|
const endings = input.match(newLineRe) || [];
|
||||||
|
endings.forEach((ending) => {
|
||||||
|
// eslint-disable-next-line default-case
|
||||||
|
switch (ending) {
|
||||||
|
case "\r":
|
||||||
|
cr++;
|
||||||
|
break;
|
||||||
|
case "\n":
|
||||||
|
lf++;
|
||||||
|
break;
|
||||||
|
case "\r\n":
|
||||||
|
crlf++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let preferredLineEnding = null;
|
||||||
|
if (!cr && !lf && !crlf) {
|
||||||
|
preferredLineEnding = os.EOL;
|
||||||
|
} else if ((lf >= crlf) && (lf >= cr)) {
|
||||||
|
preferredLineEnding = "\n";
|
||||||
|
} else if (crlf >= cr) {
|
||||||
|
preferredLineEnding = "\r\n";
|
||||||
|
} else {
|
||||||
|
preferredLineEnding = "\r";
|
||||||
|
}
|
||||||
|
return preferredLineEnding;
|
||||||
|
}
|
||||||
|
module.exports.getPreferredLineEnding = getPreferredLineEnding;
|
||||||
|
|
||||||
// Normalizes the fields of a fixInfo object
|
// Normalizes the fields of a fixInfo object
|
||||||
function normalizeFixInfo(fixInfo, lineNumber) {
|
function normalizeFixInfo(fixInfo, lineNumber) {
|
||||||
return {
|
return {
|
||||||
|
|
@ -415,19 +451,20 @@ function normalizeFixInfo(fixInfo, lineNumber) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fixes the specifide error on a line
|
// Fixes the specifide error on a line
|
||||||
function applyFix(line, fixInfo) {
|
function applyFix(line, fixInfo, lineEnding) {
|
||||||
const { editColumn, deleteCount, insertText } = normalizeFixInfo(fixInfo);
|
const { editColumn, deleteCount, insertText } = normalizeFixInfo(fixInfo);
|
||||||
const editIndex = editColumn - 1;
|
const editIndex = editColumn - 1;
|
||||||
return (deleteCount === -1) ?
|
return (deleteCount === -1) ?
|
||||||
null :
|
null :
|
||||||
line.slice(0, editIndex) +
|
line.slice(0, editIndex) +
|
||||||
insertText +
|
insertText.replace("\n", lineEnding) +
|
||||||
line.slice(editIndex + deleteCount);
|
line.slice(editIndex + deleteCount);
|
||||||
}
|
}
|
||||||
module.exports.applyFix = applyFix;
|
module.exports.applyFix = applyFix;
|
||||||
|
|
||||||
// Applies as many fixes as possible to the input lines
|
// Applies as many fixes as possible to the input lines
|
||||||
module.exports.applyFixes = function applyFixes(input, errors) {
|
module.exports.applyFixes = function applyFixes(input, errors) {
|
||||||
|
const lineEnding = getPreferredLineEnding(input);
|
||||||
const lines = input.split(newLineRe);
|
const lines = input.split(newLineRe);
|
||||||
// Normalize fixInfo objects
|
// Normalize fixInfo objects
|
||||||
let fixInfos = errors
|
let fixInfos = errors
|
||||||
|
|
@ -484,11 +521,11 @@ module.exports.applyFixes = function applyFixes(input, errors) {
|
||||||
((editIndex + deleteCount) < lastEditIndex) ||
|
((editIndex + deleteCount) < lastEditIndex) ||
|
||||||
(deleteCount === -1)
|
(deleteCount === -1)
|
||||||
) {
|
) {
|
||||||
lines[lineIndex] = applyFix(lines[lineIndex], fixInfo);
|
lines[lineIndex] = applyFix(lines[lineIndex], fixInfo, lineEnding);
|
||||||
}
|
}
|
||||||
lastLineIndex = lineIndex;
|
lastLineIndex = lineIndex;
|
||||||
lastEditIndex = editIndex;
|
lastEditIndex = editIndex;
|
||||||
});
|
});
|
||||||
// Return corrected input
|
// Return corrected input
|
||||||
return lines.filter((line) => line !== null).join("\n");
|
return lines.filter((line) => line !== null).join(lineEnding);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
|
const os = require("os");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const { URL } = require("url");
|
const { URL } = require("url");
|
||||||
const md = require("markdown-it")();
|
const md = require("markdown-it")();
|
||||||
|
|
@ -1889,8 +1890,37 @@ module.exports.forEachInlineCodeSpan = function forEachInlineCodeSpan(test) {
|
||||||
test.done();
|
test.done();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module.exports.getPreferredLineEnding = function getPreferredLineEnding(test) {
|
||||||
|
test.expect(17);
|
||||||
|
const testCases = [
|
||||||
|
[ "", os.EOL ],
|
||||||
|
[ "\r", "\r" ],
|
||||||
|
[ "\n", "\n" ],
|
||||||
|
[ "\r\n", "\r\n" ],
|
||||||
|
[ "t\rt\nt", "\n" ],
|
||||||
|
[ "t\nt\rt", "\n" ],
|
||||||
|
[ "t\r\nt\nt", "\n" ],
|
||||||
|
[ "t\nt\r\nt", "\n" ],
|
||||||
|
[ "t\r\nt\rt", "\r\n" ],
|
||||||
|
[ "t\rt\r\nt", "\r\n" ],
|
||||||
|
[ "t\r\nt\rt\nt", "\n" ],
|
||||||
|
[ "t\r\nt\r\nt\r\nt", "\r\n" ],
|
||||||
|
[ "t\nt\nt\nt", "\n" ],
|
||||||
|
[ "t\rt\rt\rt", "\r" ],
|
||||||
|
[ "t\r\nt\nt\r\nt", "\r\n" ],
|
||||||
|
[ "t\nt\r\nt\nt", "\n" ],
|
||||||
|
[ "t\rt\t\rt", "\r" ]
|
||||||
|
];
|
||||||
|
testCases.forEach((testCase) => {
|
||||||
|
const [ input, expected ] = testCase;
|
||||||
|
const actual = helpers.getPreferredLineEnding(input);
|
||||||
|
test.equal(actual, expected, "Incorrect line ending returned.");
|
||||||
|
});
|
||||||
|
test.done();
|
||||||
|
};
|
||||||
|
|
||||||
module.exports.applyFixes = function applyFixes(test) {
|
module.exports.applyFixes = function applyFixes(test) {
|
||||||
test.expect(24);
|
test.expect(27);
|
||||||
const testCases = [
|
const testCases = [
|
||||||
[
|
[
|
||||||
"Hello world.",
|
"Hello world.",
|
||||||
|
|
@ -2266,6 +2296,45 @@ module.exports.applyFixes = function applyFixes(test) {
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"Hello zorld"
|
"Hello zorld"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Hello\nworld\nhello\rworld",
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"fixInfo": {
|
||||||
|
"lineNumber": 4,
|
||||||
|
"editColumn": 6,
|
||||||
|
"insertText": "\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Hello\nworld\nhello\nworld\n"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Hello\r\nworld\r\nhello\nworld",
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"fixInfo": {
|
||||||
|
"lineNumber": 4,
|
||||||
|
"editColumn": 6,
|
||||||
|
"insertText": "\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Hello\r\nworld\r\nhello\r\nworld\r\n"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Hello\rworld\rhello\nworld",
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"fixInfo": {
|
||||||
|
"lineNumber": 4,
|
||||||
|
"editColumn": 6,
|
||||||
|
"insertText": "\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Hello\rworld\rhello\rworld\r"
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
testCases.forEach((testCase) => {
|
testCases.forEach((testCase) => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue