diff --git a/lib/rules/disallow-trailing-whitespace.js b/lib/rules/disallow-trailing-whitespace.js index d8f2eeba0..c2a0bb6a8 100644 --- a/lib/rules/disallow-trailing-whitespace.js +++ b/lib/rules/disallow-trailing-whitespace.js @@ -64,13 +64,84 @@ module.exports.prototype = { check: function(file, errors) { var ignoreEmptyLines = this._ignoreEmptyLines; + var lineTokens = file._tokensByLineIndex; + var lastLine = 1; - var lines = file.getLines(); - for (var i = 0, l = lines.length; i < l; i++) { - if (lines[i].match(/\s$/) && !(ignoreEmptyLines && lines[i].match(/^\s*$/))) { - errors.add('Illegal trailing whitespace', i + 1, lines[i].length); + function checkTokenWhiteSpace(token) { + var whitespace = token.whitespaceBefore; + var sublines = whitespace.split(file.getLineBreakStyle()); + + for (var l = 0; l < sublines.length; l++) { + var subline = sublines[l]; + + if (l === sublines.length - 1 && token.type !== 'EOF') { + // skip check if it is a last whitespace line and not eof + break; + } + + var isEmptyLine = + l || // not first sub line (since there's prev tokens on line) + token._tokenIndex === 0 && l === 0 // first token exception + ; + + if (subline.length && !(ignoreEmptyLines && isEmptyLine)) { + errors.assert.emit('error', { + message: 'Illegal trailing whitespace', + line: lastLine + l, + column: subline.length, + fixed: true + }); + sublines[l] = ''; + } } + + token.whitespaceBefore = sublines.join(file.getLineBreakStyle()); } - } + for (var i in lineTokens) { + var line = lineTokens[i]; + + // check first line token + var token = line[0]; + checkTokenWhiteSpace(token); + + // check last line token + token = line[line.length - 1]; + if (token.isComment && token.type === 'Line') { + // line comment + if (token.value.match(/\s+$/)) { + errors.assert.emit('error', { + message: 'Illegal trailing whitespace', + line: +i, + column: token.loc.end.column, + fixed: true + }); + + token.value = token.value.replace(/\s+$/, ''); + } + } else if (token.isComment && token.type === 'Block') { + // block comment + var sublines = token.value.split(file.getLineBreakStyle()); + for (var l = 0; l < sublines.length - 1; l++) { + var subline = sublines[l]; + + if (subline.match(/\s$/) && !(ignoreEmptyLines && l && subline.match(/^\s*$/))) { + errors.assert.emit('error', { + message: 'Illegal trailing whitespace', + line: +i + l, + column: subline.length, + fixed: true + }); + } + sublines[l] = subline.replace(/\s+$/, ''); + } + token.value = sublines.join(file.getLineBreakStyle()); + } else if (token.type === 'EOF') { + // non new line eof + checkTokenWhiteSpace(token); + } + + lastLine = +i; + } + } }; diff --git a/presets/mdcs.json b/presets/mdcs.json index e8c419bef..7f9b00082 100644 --- a/presets/mdcs.json +++ b/presets/mdcs.json @@ -28,5 +28,6 @@ "beforeConsequent": true, "afterConsequent": true, "beforeAlternate": true - } + }, + "disallowTrailingWhitespace": true }