UNPKG

4.94 kBJavaScriptView Raw
1/**
2 * @fileoverview Disallows multiple blank lines.
3 * implementation adapted from the no-trailing-spaces rule.
4 * @author Greg Cochard
5 * @copyright 2014 Greg Cochard. All rights reserved.
6 */
7"use strict";
8
9//------------------------------------------------------------------------------
10// Rule Definition
11//------------------------------------------------------------------------------
12
13module.exports = function(context) {
14
15 // Use options.max or 2 as default
16 var max = 2,
17 maxEOF,
18 maxBOF;
19
20 // store lines that appear empty but really aren't
21 var notEmpty = [];
22
23 if (context.options.length) {
24 max = context.options[0].max;
25 maxEOF = context.options[0].maxEOF;
26 maxBOF = context.options[0].maxBOF;
27 }
28
29 //--------------------------------------------------------------------------
30 // Public
31 //--------------------------------------------------------------------------
32
33 return {
34
35 "TemplateLiteral": function(node) {
36 var start = node.loc.start.line;
37 var end = node.loc.end.line;
38 while (start <= end) {
39 notEmpty.push(start);
40 start++;
41 }
42 },
43
44 "Program:exit": function checkBlankLines(node) {
45 var lines = context.getSourceLines(),
46 currentLocation = -1,
47 lastLocation,
48 blankCounter = 0,
49 location,
50 firstOfEndingBlankLines,
51 firstNonBlankLine = -1,
52 trimmedLines = [];
53
54 lines.forEach(function(str, i) {
55 var trimmed = str.trim();
56 if ((firstNonBlankLine === -1) && (trimmed !== "")) {
57 firstNonBlankLine = i;
58 }
59
60 trimmedLines.push(trimmed);
61 });
62
63 // add the notEmpty lines in there with a placeholder
64 notEmpty.forEach(function(x, i) {
65 trimmedLines[i] = x;
66 });
67
68 if (typeof maxEOF === "undefined") {
69 // swallow the final newline, as some editors add it
70 // automatically and we don't want it to cause an issue
71 if (trimmedLines[trimmedLines.length - 1] === "") {
72 trimmedLines = trimmedLines.slice(0, -1);
73 }
74 firstOfEndingBlankLines = trimmedLines.length;
75 } else {
76 // save the number of the first of the last blank lines
77 firstOfEndingBlankLines = trimmedLines.length;
78 while (trimmedLines[firstOfEndingBlankLines - 1] === ""
79 && firstOfEndingBlankLines > 0) {
80 firstOfEndingBlankLines--;
81 }
82 }
83
84 // Aggregate and count blank lines
85 if (firstNonBlankLine > maxBOF) {
86 context.report(node, 0,
87 "Too many blank lines at the beginning of file. Max of " + maxBOF + " allowed.");
88 }
89
90 lastLocation = currentLocation;
91 currentLocation = trimmedLines.indexOf("", currentLocation + 1);
92 while (currentLocation !== -1) {
93 lastLocation = currentLocation;
94 currentLocation = trimmedLines.indexOf("", currentLocation + 1);
95 if (lastLocation === currentLocation - 1) {
96 blankCounter++;
97 } else {
98 location = {
99 line: lastLocation + 1,
100 column: 1
101 };
102 if (lastLocation < firstOfEndingBlankLines) {
103 // within the file, not at the end
104 if (blankCounter >= max) {
105 context.report(node, location,
106 "More than " + max + " blank " + (max === 1 ? "line" : "lines") + " not allowed.");
107 }
108 } else {
109 // inside the last blank lines
110 if (blankCounter > maxEOF) {
111 context.report(node, location,
112 "Too many blank lines at the end of file. Max of " + maxEOF + " allowed.");
113 }
114 }
115
116 // Finally, reset the blank counter
117 blankCounter = 0;
118 }
119 }
120 }
121 };
122
123};
124
125module.exports.schema = [
126 {
127 "type": "object",
128 "properties": {
129 "max": {
130 "type": "integer",
131 "minimum": 0
132 },
133 "maxEOF": {
134 "type": "integer",
135 "minimum": 0
136 },
137 "maxBOF": {
138 "type": "integer",
139 "minimum": 0
140 }
141 },
142 "required": ["max"],
143 "additionalProperties": false
144 }
145];