// @ts-check "use strict"; const { addError } = require("markdownlint-rule-helpers"); const { indentFor } = require("./helper"); const isAfterIgnoredWord = (ignoredWords, line, i) => { for (const ignoredWord of ignoredWords) { const lastWordInLine = line.substring(i - ignoredWord.length, i); if (ignoredWord === lastWordInLine.toLowerCase()) { return true; } } return false; }; module.exports = { "names": [ "max-one-sentence-per-line" ], "description": "Max 1 sentence should be on a line", "information": new URL( "https://github.com/aepfli/markdownlint-rule-max-one-sentence-per-line" ), "tags": [ "sentences" ], "function": (params, onError) => { const ignoredWords = params.config.ignored_words || [ "ie", "i.e", "eg", "e.g", "etc", "ex" ]; const lineEndings = params.config.line_endings || [ ".", "?", "!" ]; const sentenceStartRegex = params.config.sentence_start || "^\\s+(\\w|[*_'\"])"; const contextSize = Number(params.config.context_length || 14); const indentation = params.config.indentation || " "; const sentenceStart = new RegExp(sentenceStartRegex); const relevantTokens = []; for (let i = 0; i < params.tokens.length; i++) { const token = params.tokens[i]; if (token.type === "paragraph_open" && params.tokens[i + 1].type === "inline") { relevantTokens.push(params.tokens[i + 1]); } } for (const relevantToken of relevantTokens) { for (const token of relevantToken.children) { const lineNumber = token.lineNumber; if (token.type === "text") { const content = token.content; for (let i = 0; i < content.length - 2; i += 1) { if (lineEndings.includes(content[i])) { const sentence = sentenceStart.exec(content.substr(i + 1)); if ( sentence !== null && !isAfterIgnoredWord(ignoredWords, content, i) ) { const spaces = sentence[1]; const pointInLine = token.line.indexOf(content) + i; addError( onError, lineNumber, null, // eslint-disable-next-line max-len content.substr(Math.max(0, i - (contextSize / 2)), contextSize), [ pointInLine, spaces.length ], { "lineNumber": lineNumber, "editColumn": pointInLine + 2, "deleteCount": spaces.length, // eslint-disable-next-line max-len "insertText": "\n" + indentFor(relevantToken.line, indentation) } ); } } } } } } } };