diff --git a/README.md b/README.md index 168a1bae..5c05447f 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,7 @@ Please also see the [example configs](./docs/examples/) for special cases. - [`dollar-variable-colon-space-after`](./src/rules/dollar-variable-colon-space-after/README.md): Require or disallow whitespace after the colon in `$`-variable declarations (Autofixable). - [`dollar-variable-colon-space-before`](./src/rules/dollar-variable-colon-space-before/README.md): Require a single space or disallow whitespace before the colon in `$`-variable declarations (Autofixable). - [`dollar-variable-default`](./src/rules/dollar-variable-default/README.md): Require `!default` flag for `$`-variable declarations. +- [`dollar-variable-empty-line-after`](./src/rules/dollar-variable-empty-line-after/README.md): Require a single empty line or disallow empty lines after `$`-variable declarations (Autofixable). - [`dollar-variable-empty-line-before`](./src/rules/dollar-variable-empty-line-before/README.md): Require a single empty line or disallow empty lines before `$`-variable declarations (Autofixable). - [`dollar-variable-no-missing-interpolation`](./src/rules/dollar-variable-no-missing-interpolation/README.md): Disallow Sass variables that are used without interpolation with CSS features that use custom identifiers. - [`dollar-variable-pattern`](./src/rules/dollar-variable-pattern/README.md): Specify a pattern for Sass-like variables. diff --git a/src/rules/dollar-variable-empty-line-after/README.md b/src/rules/dollar-variable-empty-line-after/README.md new file mode 100644 index 00000000..ffe3520c --- /dev/null +++ b/src/rules/dollar-variable-empty-line-after/README.md @@ -0,0 +1,185 @@ +# dollar-variable-empty-line-after + +Require an empty line or disallow empty lines after `$`-variable declarations. + +If the `$`-variable declaration is the last declaration in a file, it's ignored. + +The `--fix` option on the [command line](https://github.com/stylelint/stylelint/blob/master/docs/user-guide/cli.md#autofixing-errors) can automatically fix all of the problems reported by this rule. + +## Options + +`string`: `"always"|"never"` + +### `"always"` + +There *must always* be one empty line after a `$`-variable declaration. + +The following patterns are considered warnings: + +```scss +$var: 200px; +@import '1.css'; +``` + +```scss +a { + $var: 1; +} +``` + +The following patterns are *not* considered warnings: + +```scss +$var: 100px; // The last declaration in a stylesheet +``` + +```scss +$var: 1; + +a { color: red; } +``` + +### `"never"` + +There *must never* be an empty line after a `$`-variable declaration. + +The following patterns are considered warnings: + +```scss +$var: 1; + +a { color: red; } +``` + +The following patterns are *not* considered warnings: + +```scss +$var: 100px; +$var2: 200px; +``` + +```scss +$var: 1; +a { + width: auto; +} +``` + +## Optional secondary options + +### `except: ["last-nested", "before-comment", "before-dollar-variable"]` + +### `"last-nested"` + +Reverse the primary option for a `$`-variable declaration if it's the last child of its parent. + +For example, with `"always"`: + +The following patterns are considered warnings: + +```scss +a { + $var: 1; + color: red; +} + +b { + $var: 1; + +} +``` + +The following patterns are *not* considered warnings: + +```scss +a { + color: red; + $var: 1; +} + +b { + $var: 1; + + color: red; +} +``` + +### `"before-comment"` + +Reverse the primary option for `$`-variable declarations that go before comments. + +For example, with `"always"`: + +The following patterns are *not* considered warnings: + +```scss +a { + $var: 1; + // comment +} +``` + +### `"before-dollar-variable"` + +Reverse the primary option for `$`-variable declarations that go right after another `$`-variable declaration. + +For example, with `"always"`: + +The following patterns are considered warnings: + +```scss +a { + $var: 1; // this one is ok + $var1: 2; // and this one shouldn't have a preceding empty line + b { + width: 100px; + } +} +``` + +The following patterns are *not* considered warnings: + +```scss +a { + $var: 1; + $var1: 2; + + b { + width: 100%; + } +} +``` + +### `ignore: ["before-comment", "inside-single-line-block"]` + +### `"before-comment"` + +Ignore `$`-variables that go before a comment. + +For example, with `"always"`: + +The following patterns are *not* considered warnings: + +```scss +$var: 1 +// comment + +$var2: 1; +/* comment */ +``` + +### `"inside-single-line-block"` + +Ignore `$`-variables that are inside single-line blocks. + +For example, with `"always"`: + +The following patterns are *not* considered warnings: + +```scss +a { $var: 10; } +``` + +### `disableFix: true` + +Disables autofixing for this rule. diff --git a/src/rules/dollar-variable-empty-line-after/__tests__/index.js b/src/rules/dollar-variable-empty-line-after/__tests__/index.js new file mode 100644 index 00000000..084f6339 --- /dev/null +++ b/src/rules/dollar-variable-empty-line-after/__tests__/index.js @@ -0,0 +1,812 @@ +import rule, { ruleName, messages } from ".."; + +// always +// -------------------------------------------------------------------------- + +testRule(rule, { + ruleName, + config: ["always"], + syntax: "scss", + fix: true, + + accept: [ + { + code: `a { + $var1: 100px; + + }`, + description: "always. $var inside a rule, emptyline after." + }, + { + code: `a { + $var1: 100px; + + $var1: 100px; + + }`, + description: "always. Two $var-s inside a rule, emptyline after both." + }, + { + code: "$var1: 100px;", + description: "always. $var in root, no emptyline after." + }, + { + code: ` + $var1: 100px; + + + @import '1.css'; + `, + description: "always. $var in root, not the last, multiple newlines." + }, + { + code: "a { $var1: 100px;\n\n}", + description: "always. Unix newline" + }, + { + code: "a { $var1: 100px;\r\n\r\n}", + description: "always. Windows newline" + }, + { + code: "a { $var1: 100px;\n\r\n}", + description: "always. Mixed newline" + }, + { + code: "a { width: 100px; }", + description: "always. Not a $-variable" + } + ], + + reject: [ + { + code: `a { + $var1: 100px; + }`, + fixed: `a { + $var1: 100px; + + }`, + description: "always. $var inside a rule, no emptyline after.", + message: messages.expected, + line: 2 + }, + { + code: ` + $var1: 100px; + $var1: 100px; + + `, + fixed: ` + $var1: 100px; + + $var1: 100px; + + `, + description: + "always. Two $var-s at the root start, no empty line between them.", + message: messages.expected, + line: 2 + } + ] +}); + +// never +// -------------------------------------------------------------------------- + +testRule(rule, { + ruleName, + config: ["never"], + syntax: "scss", + fix: true, + + accept: [ + { + code: `a { + $var1: 100px; + }`, + description: "never. $var inside a rule, no emptyline after." + }, + { + code: ` + $var1: 100px; + + `, + description: "never. $var in root, the last, has newline." + }, + { + code: `a { + width: 100px; + + }`, + description: "never. Not a $-variable" + } + ], + + reject: [ + { + code: `a { + $var1: 100px; + + }`, + fixed: `a { + $var1: 100px; + }`, + description: "never. $var inside a rule, emptyline after.", + message: messages.rejected, + line: 2 + }, + { + code: ` + $var1: 100px; + + // comment + `, + fixed: ` + $var1: 100px; + // comment + `, + description: "never. $var in root, before comment, has empty line.", + message: messages.rejected, + line: 2 + }, + { + code: "a { $var1: 100px;\n\n}", + fixed: "a { $var1: 100px;\n}", + description: "never. Unix newline", + message: messages.rejected, + line: 1 + }, + { + code: "a { $var1: 100px;\r\n\r\n}", + fixed: "a { $var1: 100px;\r\n}", + description: "never. Windows newline", + message: messages.rejected, + line: 1 + }, + { + code: "a { $var1: 100px;\n\r\n}", + fixed: "a { $var1: 100px;\r\n}", + description: "never. Mixed newline", + message: messages.rejected, + line: 1 + } + ] +}); + +// Ignore: after-comment +// -------------------------------------------------------------------------- + +testRule(rule, { + ruleName, + config: ["always", { ignore: "before-comment" }], + syntax: "scss", + fix: true, + + accept: [ + { + code: ` + $var1: 100px; + // comment + `, + description: + "always, { ignore: before-comment }. $var before //-comment, no empty line." + }, + { + code: ` + $var1: 100px; + + // comment + `, + description: + "always, { ignore: before-comment }. $var before //-comment, has empty line." + }, + { + code: ` + $var1: 100px; + /* comment */ + `, + description: + "always, { ignore: before-comment }. $var before CSS-comment, no empty line." + }, + { + code: ` + $var1: 100px; + /* comment */ + `, + description: + "always, { ignore: before-comment }. $var before CSS-comment, has empty line." + } + ], + + reject: [ + { + code: ` + $var2: 2; + width: 1; + `, + fixed: ` + $var2: 2; + + width: 1; + `, + description: + "always, { ignore: before-comment }. No comment directly after $var, no empty line.", + message: messages.expected, + line: 2 + } + ] +}); + +testRule(rule, { + ruleName, + config: ["never", { ignore: "before-comment" }], + syntax: "scss", + fix: true, + + accept: [ + { + code: ` + $var1: 100px; + // comment + `, + description: + "never, { ignore: before-comment }. $var before //-comment, no empty line." + }, + { + code: ` + $var1: 100px; + + // comment + `, + description: + "never, { ignore: before-comment }. $var before //-comment, has empty line." + }, + { + code: ` + $var1: 100px; + /* comment */ + `, + description: + "never, { ignore: before-comment }. $var before CSS-comment, no empty line." + }, + { + code: ` + $var1: 100px; + /* comment */ + `, + description: + "never, { ignore: before-comment }. $var before CSS-comment, has empty line." + } + ], + + reject: [ + { + code: ` + $var2: 2; + + width: 1; + `, + fixed: ` + $var2: 2; + width: 1; + `, + description: + "never, { ignore: before-comment }. No comment directly before $var, has empty line.", + message: messages.rejected, + line: 2 + } + ] +}); + +// Ignore: single-line-block +// -------------------------------------------------------------------------- + +testRule(rule, { + ruleName, + config: ["always", { ignore: "inside-single-line-block" }], + syntax: "scss", + + accept: [ + { + code: "a { $var1: 100px; }", + description: + "always, { ignore: inside-single-line-block }. $var inside single-line ruleset, alone." + }, + { + code: ` + a { $var1: 100px; } + `, + description: + "always, { ignore: inside-single-line-block }. $var inside single-line ruleset with newlines around, alone." + }, + { + code: "a { width: 10px; $var1: 100px; color: red; }", + description: + "always, { ignore: inside-single-line-block }. $var inside single-line ruleset, has neighbours." + } + ], + + reject: [ + { + code: `a { + width: 1; $var2: 2; + }`, + description: + "always, { ignore: inside-single-line-block }. Not a single line ruleset, $var and other decl on the same line.", + message: messages.expected, + line: 2 + } + ] +}); + +// Except: first-nested +// -------------------------------------------------------------------------- + +testRule(rule, { + ruleName, + config: ["always", { except: "last-nested" }], + syntax: "scss", + fix: true, + + accept: [ + { + code: `a { + color: red; + $var1: 100px; + }`, + description: + "always, { except: last-nested }. $var is the last inside ruleset, no empty line." + }, + { + code: `@mixin name { + color: red; + $var1: 100px; + }`, + description: + "always, { except: last-nested }. $var is the last inside mixin, no empty line." + } + ], + + reject: [ + { + code: `a { + $var2: 234; width: 1; + }`, + fixed: `a { + $var2: 234; + +width: 1; + }`, + description: + "always, { except: last-nested }. $var is not the last in a ruleset, no empty line.", + message: messages.expected, + line: 2 + }, + { + code: `a { + $var2: 2; + + }`, + fixed: `a { + $var2: 2; + }`, + description: + "always, { except: last-nested }. $var is the last in a ruleset, has empty line.", + message: messages.expected, + line: 2 + } + ] +}); + +testRule(rule, { + ruleName, + config: ["never", { except: "last-nested" }], + syntax: "scss", + fix: true, + + accept: [ + { + code: `a { + color: red; + $var1: 100px; + + }`, + description: + "never, { except: last-nested }. $var is the last inside ruleset, has empty line." + }, + { + code: `a { + $var1: 100px; + color: red; + }`, + description: + "never, { except: last-nested }. $var isn't the last inside ruleset, no empty line." + } + ], + + reject: [ + { + code: `a { + $var2: 2; + }`, + fixed: `a { + $var2: 2; + + }`, + description: + "never, { except: last-nested }. $var is the last in a ruleset, no empty line.", + message: messages.rejected, + line: 2 + }, + { + code: `a { + $var2: 2; + + color: red; + }`, + fixed: `a { + $var2: 2; + color: red; + }`, + description: + "never, { except: last-nested }. $var isn't the last in a ruleset, has empty line.", + message: messages.rejected, + line: 2 + } + ] +}); + +// Except: first-nested with `disableFix: true` +// -------------------------------------------------------------------------- + +testRule(rule, { + ruleName, + config: [ + "always", + { + except: "last-nested", + disableFix: true + } + ], + syntax: "scss", + fix: true, + + accept: [ + { + code: `a { + color: red; + $var1: 100px; + }`, + description: + "always, { except: last-nested }. $var is the last inside ruleset, no empty line." + }, + { + code: `@mixin name { + color: red; + $var1: 100px; + }`, + description: + "always, { except: last-nested }. $var is the last inside mixin, no empty line." + } + ], + + reject: [ + { + code: `a { + $var2: 2; width: 1; + }`, + fixed: `a { + $var2: 2; width: 1; + }`, + description: + "always, { except: last-nested }. $var is not the last in a ruleset, no empty line.", + message: messages.expected, + line: 2 + }, + { + code: `a { + $var2: 2; + + }`, + fixed: `a { + $var2: 2; + + }`, + description: + "always, { except: last-nested }. $var is the last in a ruleset, has empty line.", + message: messages.expected, + line: 2 + } + ] +}); + +// Except: after-comment +// -------------------------------------------------------------------------- + +testRule(rule, { + ruleName, + config: ["always", { except: "before-comment" }], + syntax: "scss", + fix: true, + + accept: [ + { + code: ` + $var1: 100px; + // comment + `, + description: + "always, { except: before-comment }. $var before //-comment, no empty line." + }, + { + code: "$var1: 100px; /* comment */", + description: + "always, { except: before-comment }. $var before CSS-comment, no empty line." + }, + { + code: ` + $var1: 100px; + + @import 'a.css'; + `, + description: + "always, { except: before-comment }. $var is not before CSS-comment, has empty line." + } + ], + + reject: [ + { + code: ` + $var1: 100px; + + // comment + `, + fixed: ` + $var1: 100px; + // comment + `, + description: + "always, { except: before-comment }. $var before //-comment, has empty line.", + message: messages.expected, + line: 2 + }, + { + code: ` + $var1: 100px; + + /* comment */ + `, + fixed: ` + $var1: 100px; + /* comment */ + `, + description: + "always, { except: before-comment }. $var before CSS-comment, has empty line.", + message: messages.expected, + line: 2 + }, + { + code: `a { + $var1: 100px; + color: red; + }`, + fixed: `a { + $var1: 100px; + + color: red; + }`, + description: + "always, { except: before-comment }. No comment after $var, has empty line.", + message: messages.expected, + line: 2 + } + ] +}); + +testRule(rule, { + ruleName, + config: ["never", { except: "before-comment" }], + syntax: "scss", + fix: true, + + accept: [ + { + code: ` + $var1: 100px; + + // comment + `, + description: + "never, { except: before-comment }. $var before //-comment, has empty line." + }, + { + code: ` + $var1: 100px; + + /* comment */ + `, + description: + "never, { except: before-comment }. $var before CSS-comment, has empty line." + }, + { + code: ` + $var1: 100px; + @import 'a.css'; + `, + description: + "never, { except: before-comment }. $var is not before CSS-comment, no empty line." + } + ], + + reject: [ + { + code: ` + $var1: 100px; + // comment + `, + fixed: ` + $var1: 100px; + + // comment + `, + description: + "never, { except: before-comment }. $var before //-comment, no empty line.", + message: messages.rejected, + line: 2 + }, + { + code: ` + $var1: 100px; + /* comment */ + `, + fixed: ` + $var1: 100px; + + /* comment */ + `, + description: + "never, { except: before-comment }. $var before CSS-comment, no empty line.", + message: messages.rejected, + line: 2 + }, + { + code: `a { + $var1: 100px; + + color: red; + }`, + fixed: `a { + $var1: 100px; + color: red; + }`, + description: + "never, { except: before-comment }. No comment before $var, has empty line.", + message: messages.rejected, + line: 2 + } + ] +}); + +// Except: after-dollar-variable +// -------------------------------------------------------------------------- + +testRule(rule, { + ruleName, + config: ["always", { except: "before-dollar-variable" }], + syntax: "scss", + fix: true, + + accept: [ + { + code: `a { + $var1: 1; + + }`, + description: + "always, { except: before-dollar-variable }. Just a single var with empty line." + }, + { + code: ` + $var1: 1; + $var2: 1; + + `, + description: + "always, { except: before-dollar-variable }. $var2 has empty line, $var1 before it doesn't." + }, + { + code: ` + $var1: 1; + $var2: 1; + $var3: 1; + + `, + description: + "always, { except: before-dollar-variable }. Three $var-s, last with empty line, others without." + } + ] +}); + +testRule(rule, { + ruleName, + config: ["never", { except: "before-dollar-variable" }], + syntax: "scss", + fix: true, + + accept: [ + { + code: `$var1: 1; + + $var2: 1; + `, + description: + "never, { except: before-dollar-variable }. $var2 doesn't have empty line, $var2 before it does." + }, + { + code: `$var1: 1; + + $var2: 1; + + $var3: 1; + `, + description: + "never, { except: before-dollar-variable }. Three $var-s, last w/o empty line, others with." + } + ], + + reject: [ + { + code: `a { + $var1: 1; + $var2: 1; + }`, + fixed: `a { + $var1: 1; + + $var2: 1; + }`, + description: + "never, { except: before-dollar-variable }. $var1 and $var2 have no empty lines.", + message: messages.rejected, + line: 2 + } + ] +}); + +// Combining secondary options +// -------------------------------------------------------------------------- + +testRule(rule, { + ruleName, + config: [ + "always", + { except: ["last-nested", "before-comment", "before-dollar-variable"] } + ], + syntax: "scss", + + accept: [ + { + code: ` + a { + $var1: value; + $var2: value; + + $var3: value; + /* comment */ + + @extends "x"; + + $var4: value; + + & b { + prop: value; + } + + $var5: value; + } + `, + description: + "always, { except: [last-nested, before-comment, before-dollar-variable] }." + } + ] +}); diff --git a/src/rules/dollar-variable-empty-line-after/index.js b/src/rules/dollar-variable-empty-line-after/index.js new file mode 100644 index 00000000..875891f9 --- /dev/null +++ b/src/rules/dollar-variable-empty-line-after/index.js @@ -0,0 +1,240 @@ +import { + hasEmptyLine, + isSingleLineString, + namespace, + optionsHaveException, + optionsHaveIgnored, + blockString +} from "../../utils"; +import { utils } from "stylelint"; +import { isBoolean } from "lodash"; + +export const ruleName = namespace("dollar-variable-empty-line-after"); + +export const messages = utils.ruleMessages(ruleName, { + expected: "Expected an empty line after $-variable", + rejected: "Unexpected empty line after $-variable" +}); + +export default function(expectation, options, context) { + return (root, result) => { + const validOptions = utils.validateOptions( + result, + ruleName, + { + actual: expectation, + possible: ["always", "never"] + }, + { + actual: options, + possible: { + except: ["last-nested", "before-comment", "before-dollar-variable"], + ignore: ["before-comment", "inside-single-line-block"], + disableFix: isBoolean + }, + optional: true + } + ); + + if (!validOptions) { + return; + } + + const fixNext = (decl, match, replace) => { + decl.raws.before = decl.raws.before.replace( + new RegExp(`^${match}`), + replace + ); + }; + + const fixParent = (decl, match, replace) => { + decl.parent.raws.after = decl.parent.raws.after.replace( + new RegExp(`^${match}`), + replace + ); + }; + + const hasNewline = str => str.indexOf(context.newline) > -1; + const isDollarVar = node => node.prop && node.prop[0] === "$"; + + root.walkDecls(decl => { + let expectEmptyLineAfter = expectation === "always"; + const exceptLastNested = optionsHaveException(options, "last-nested"); + const exceptBeforeComment = optionsHaveException( + options, + "before-comment" + ); + const exceptBeforeVariable = optionsHaveException( + options, + "before-dollar-variable" + ); + const ignoreInsideSingleLineBlock = optionsHaveIgnored( + options, + "inside-single-line-block" + ); + const ignoreBeforeComment = optionsHaveIgnored(options, "before-comment"); + + const isSingleLineDeclaration = isSingleLineString( + blockString(decl.parent) + ); + + // Ignore declarations that aren't variables. + // ------------------------------------------ + if (!isDollarVar(decl)) { + return; + } + + // Ignore declaration if it's the last line in a file. + // --------------------------------------------------- + if (decl === root.last) { + return; + } + + // Ignore single line blocks (if chosen as an option). + // --------------------------------------------------- + if ( + ignoreInsideSingleLineBlock && + decl.parent.type !== "root" && + isSingleLineDeclaration + ) { + return; + } + + const next = decl.next(); + + // The declaration is the last in a block. + // --------------------------------------- + if (!next) { + const hasEmptyLineAfter = hasEmptyLine(decl.parent.raws.after); + + if ( + (expectEmptyLineAfter && hasEmptyLineAfter && !exceptLastNested) || + (!expectEmptyLineAfter && !hasEmptyLineAfter && !exceptLastNested) || + (expectEmptyLineAfter && !hasEmptyLineAfter && exceptLastNested) || + (!expectEmptyLineAfter && hasEmptyLineAfter && exceptLastNested) + ) { + return; + } + } + + // The declaration is NOT the last in a block. + // ------------------------------------------- + else { + const hasEmptyLineAfter = hasEmptyLine(next.raws.before); + const nextIsComment = next.type === "comment"; + const nextIsVariable = isDollarVar(next); + + if (nextIsComment) { + if ( + ignoreBeforeComment || + (expectEmptyLineAfter && + hasEmptyLineAfter && + !exceptBeforeComment) || + (!expectEmptyLineAfter && + !hasEmptyLineAfter && + !exceptBeforeComment) || + (expectEmptyLineAfter && + !hasEmptyLineAfter && + exceptBeforeComment) || + (!expectEmptyLineAfter && hasEmptyLineAfter && exceptBeforeComment) + ) { + return; + } + } else if (nextIsVariable) { + if ( + (expectEmptyLineAfter && + hasEmptyLineAfter && + !exceptBeforeVariable) || + (!expectEmptyLineAfter && + !hasEmptyLineAfter && + !exceptBeforeVariable) || + (expectEmptyLineAfter && + !hasEmptyLineAfter && + exceptBeforeVariable) || + (!expectEmptyLineAfter && + hasEmptyLineAfter && + exceptBeforeVariable) || + (expectEmptyLineAfter && hasEmptyLineAfter && exceptBeforeVariable) + ) { + return; + } + } else if (expectEmptyLineAfter === hasEmptyLineAfter) { + return; + } + } + + const isFixDisabled = options && options.disableFix === true; + + if (context.fix && !isFixDisabled) { + if (next) { + const nextBefore = next.raws.before; + const hasEmptyLineAfter = hasEmptyLine(nextBefore); + const nextIsComment = next.type === "comment"; + const nextIsVariable = isDollarVar(next); + + if (expectEmptyLineAfter && !hasEmptyLineAfter) { + fixNext(next, context.newline, context.newline + context.newline); + + if (exceptLastNested && !hasNewline(nextBefore)) { + fixNext(next, "\\s+", context.newline + context.newline); + } + + return; + } else if ( + (expectEmptyLineAfter && + exceptBeforeComment && + nextIsComment && + hasEmptyLineAfter) || + (expectEmptyLineAfter && + exceptBeforeVariable && + nextIsVariable && + hasEmptyLineAfter) || + (!expectEmptyLineAfter && hasEmptyLineAfter) + ) { + fixNext(decl, "\\n\\r\\n", "\r\n"); + fixNext(next, context.newline + context.newline, context.newline); + + return; + } else if ( + (!expectEmptyLineAfter && + exceptBeforeComment && + nextIsComment && + !hasEmptyLineAfter) || + (!expectEmptyLineAfter && + exceptBeforeVariable && + nextIsVariable && + !hasEmptyLineAfter) + ) { + fixNext(next, context.newline, context.newline + context.newline); + + return; + } + } else { + const hasEmptyLineAfter = hasEmptyLine(decl.parent.raws.after); + + expectEmptyLineAfter = exceptLastNested + ? !expectEmptyLineAfter + : expectEmptyLineAfter; + + if (expectEmptyLineAfter && !hasEmptyLineAfter) { + fixParent(decl, context.newline, context.newline + context.newline); + + return; + } else if (!expectEmptyLineAfter && hasEmptyLineAfter) { + fixParent(decl, "\\n\\r\\n", "\r\n"); + fixParent(decl, context.newline + context.newline, context.newline); + + return; + } + } + } + + utils.report({ + message: expectEmptyLineAfter ? messages.expected : messages.rejected, + node: decl, + result, + ruleName + }); + }); + }; +} diff --git a/src/rules/index.js b/src/rules/index.js index a24dc219..61c110f2 100644 --- a/src/rules/index.js +++ b/src/rules/index.js @@ -28,6 +28,7 @@ import dollarVariableColonNewlineAfter from "./dollar-variable-colon-newline-aft import dollarVariableColonSpaceAfter from "./dollar-variable-colon-space-after"; import dollarVariableColonSpaceBefore from "./dollar-variable-colon-space-before"; import dollarVariableDefault from "./dollar-variable-default"; +import dollarVariableEmptyLineAfter from "./dollar-variable-empty-line-after"; import dollarVariableEmptyLineBefore from "./dollar-variable-empty-line-before"; import dollarVariableNoMissingInterpolation from "./dollar-variable-no-missing-interpolation"; import dollarVariablePattern from "./dollar-variable-pattern"; @@ -81,6 +82,7 @@ export default { "dollar-variable-colon-space-after": dollarVariableColonSpaceAfter, "dollar-variable-colon-space-before": dollarVariableColonSpaceBefore, "dollar-variable-default": dollarVariableDefault, + "dollar-variable-empty-line-after": dollarVariableEmptyLineAfter, "dollar-variable-empty-line-before": dollarVariableEmptyLineBefore, "dollar-variable-no-missing-interpolation": dollarVariableNoMissingInterpolation, "dollar-variable-pattern": dollarVariablePattern,