UNPKG

3.85 kBJavaScriptView Raw
1/**
2 * Requires all lines to end on a non-whitespace character
3 *
4 * Types: `Boolean` or `String`
5 *
6 * Values:
7 * - `true`
8 * - `"ignoreEmptyLines"`: (default: `false`) allow whitespace on empty lines
9 *
10 * JSHint: [`trailing`](http://jshint.com/docs/options/#trailing)
11 *
12 * #### Example
13 *
14 * ```js
15 * "disallowTrailingWhitespace": true
16 * ```
17 *
18 * ##### Valid
19 *
20 * ```js
21 * var foo = "blah blah";
22 * ```
23 *
24 * ##### Invalid
25 *
26 * ```js
27 * var foo = "blah blah"; //<-- whitespace character here
28 * ```
29 *
30 * ##### Valid for `true`
31 *
32 * ```js
33 * foo = 'bar';
34 *
35 * foo = 'baz';
36 * ```
37 *
38 * ##### Invalid for `true` but Valid for `ignoreEmptyLines`
39 *
40 * ```js
41 * foo = 'bar';
42 * \t
43 * foo = 'baz';
44 * ```
45 */
46
47var assert = require('assert');
48var Token = require('cst').Token;
49
50module.exports = function() {};
51
52module.exports.prototype = {
53
54 configure: function(options) {
55 assert(
56 options === true || options === 'ignoreEmptyLines',
57 this.getOptionName() + ' option requires a true value or "ignoreEmptyLines"'
58 );
59 this._ignoreEmptyLines = options === 'ignoreEmptyLines';
60 },
61
62 getOptionName: function() {
63 return 'disallowTrailingWhitespace';
64 },
65
66 check: function(file, errors) {
67 var program = file.getProgram();
68
69 if (!program) {
70 return;
71 }
72
73 var lastToken = program.getLastToken();
74 if (lastToken && lastToken.type === 'EOF') {
75 lastToken = lastToken.getPreviousToken();
76 }
77 program.selectTokensByType('Whitespace').forEach(function(whitespace) {
78 whitespace.getValueLineInfo().some(function(line, i) {
79 if (this._ignoreEmptyLines && i > 0) {
80 return true;
81 }
82 if (line.text && (line.lineBreak || whitespace === lastToken)) {
83 errors.cast({
84 message: 'Illegal trailing whitespace',
85 element: whitespace,
86 offset: line.offset,
87 additional: {
88 lineNumber: i
89 }
90 });
91 }
92 }, this);
93 }, this);
94 program.selectTokensByType('CommentBlock').concat(program.selectTokensByType('CommentLine'))
95 .forEach(function(comment) {
96 var lines = comment.getValueLineInfo();
97 lines.forEach(function(line, i) {
98 if (i > 0 && this._ignoreEmptyLines && line.text.trim() === '') {
99 return;
100 }
101 if (comment.type === 'CommentBlock' && i === lines.length - 1) {
102 return;
103 }
104 if (line.text.match(/\s$/)) {
105 errors.cast({
106 message: 'Illegal trailing comment',
107 element: comment,
108 offset: line.offset,
109 additional: {
110 lineNumber: i
111 }
112 });
113 }
114 }, this);
115 }, this);
116 },
117
118 _fix: function(file, error) {
119 var element = error.element;
120 var newValue;
121 var lines = element.getValueLineInfo();
122 var line = lines[error.additional.lineNumber];
123 if (element.isWhitespace) {
124 line.text = '';
125 }
126 if (element.isComment) {
127 line.text = line.text.replace(/\s+$/, '');
128 }
129
130 newValue = lines.map(function(line) {
131 return line.text + (line.lineBreak || '');
132 }).join('');
133
134 var newElement = new Token(element.type, newValue);
135 element.parentElement.replaceChild(newElement, element);
136 }
137};