remark-lint-sentence-newline
Version:
Enforce a newline after an end of sentence in Markdown.
78 lines (69 loc) • 2.34 kB
JavaScript
var visit = require('unist-util-visit');
function sentenceNewline(ast, file, preferred, done) {
var blacklist = [];
if (typeof preferred === 'object' && !('length' in preferred)) {
blacklist = preferred.blacklist;
}
visit(ast, 'text', function (node) {
var sentenceStops = [
'!', '.', '?'
];
function getNextSentenceStop(value, startIndex) {
var result = {index: -1, sentenceStop: ''};
if (startIndex >= value.length) {
return result;
}
// search for all sentence stop types
// return the one with the lowest index
for (var i = 0; i < sentenceStops.length; ++i) {
var index = value.indexOf(sentenceStops[i], startIndex);
if (index === -1) {
continue;
}
if (result.index === -1 || index < result.index) {
result.index = index;
result.sentenceStop = sentenceStops[i];
}
}
return result;
}
var lastCandidate = {index: 0, sentenceStop: ''};
while (true) {
lastCandidate = getNextSentenceStop(
node.value, lastCandidate.index + lastCandidate.sentenceStop.length);
// abort if no more sentence stops are found
if (lastCandidate.index === -1) {
break;
}
// ignore if the sentence stop is the last character
if (lastCandidate.index >= node.value.length - 1) {
continue;
}
// ignore if the next character is not a space
if (node.value.charAt(lastCandidate.index + lastCandidate.sentenceStop.length) !== ' ') {
continue;
}
// ignore if the sentence stop (and its preceeding characters match a blacklisted string
var isBlacklisted = false;
for (var i = 0; i < blacklist.length; ++i) {
var needle = blacklist[i];
var startIndex = lastCandidate.index + lastCandidate.sentenceStop.length - needle.length;
if (node.value.substr(startIndex, needle.length) == needle) {
isBlacklisted = true;
break;
}
}
if (isBlacklisted) {
continue;
}
file.warn(
'Newline should follow end of sentence',
file.offsetToPosition(file.positionToOffset(node.position.start) + lastCandidate.index)
);
}
});
done();
}
module.exports = {
'sentence-newline': sentenceNewline
};