From 7f20ffc7f584a8b0834ab2a1bc3cca7ef23cb4fe Mon Sep 17 00:00:00 2001 From: Aakansha Doshi Date: Thu, 19 Apr 2018 02:10:01 +0530 Subject: [PATCH] Allow trailing comma in scss list and maps (#4317) * Allow trailing comma in scss list and maps * fix #4076 * triple equalto * newline * linting * review fixes * print trailing comma only when options.tralingComma is not none * Add nested maps and lists * add isSCSS() check * linting * Add utils for isSCSS() in language-css * lint --- src/language-css/parser-postcss.js | 10 +- src/language-css/printer-postcss.js | 7 + src/language-css/utils.js | 13 + .../__snapshots__/jsfmt.spec.js.snap | 272 +++++++++++++++++- tests/css_trailing_comma/jsfmt.spec.js | 1 + tests/css_trailing_comma/list.css | 47 +++ tests/css_trailing_comma/map.css | 3 +- 7 files changed, 337 insertions(+), 16 deletions(-) create mode 100644 src/language-css/utils.js diff --git a/src/language-css/parser-postcss.js b/src/language-css/parser-postcss.js index 8bd34c19..8e189a16 100644 --- a/src/language-css/parser-postcss.js +++ b/src/language-css/parser-postcss.js @@ -3,6 +3,9 @@ const createError = require("../common/parser-create-error"); const grayMatter = require("gray-matter"); +// utils +const utils = require("./utils"); + function parseSelector(selector) { // If there's a comment inside of a selector, the parser tries to parse // the content of the comment as selectors which turns it into complete @@ -478,15 +481,10 @@ function requireParser(isSCSS) { return require("postcss-less"); } -const IS_POSSIBLY_SCSS = /(\w\s*: [^}:]+|#){|@import[^\n]+(url|,)/; - function parse(text, parsers, opts) { const hasExplicitParserChoice = opts.parser === "less" || opts.parser === "scss"; - - const isSCSS = hasExplicitParserChoice - ? opts.parser === "scss" - : IS_POSSIBLY_SCSS.test(text); + const isSCSS = utils.isSCSS(opts.parser, text); const frontMatter = grayMatter(text); const normalizedText = frontMatter.content; diff --git a/src/language-css/printer-postcss.js b/src/language-css/printer-postcss.js index 04f48adf..ce159a24 100644 --- a/src/language-css/printer-postcss.js +++ b/src/language-css/printer-postcss.js @@ -15,7 +15,9 @@ const group = docBuilders.group; const fill = docBuilders.fill; const indent = docBuilders.indent; +// utils const removeLines = doc.utils.removeLines; +const utils = require("./utils"); function genericPrint(path, options, print) { const node = path.getValue(); @@ -679,6 +681,11 @@ function genericPrint(path, options, print) { ) ]) ), + utils.isSCSS(options.parser, options.originalText) && + node.groups.length > 1 && + options.trailingComma !== "none" + ? "," + : "", softline, node.close ? path.call(print, "close") : "" ]) diff --git a/src/language-css/utils.js b/src/language-css/utils.js new file mode 100644 index 00000000..41198e72 --- /dev/null +++ b/src/language-css/utils.js @@ -0,0 +1,13 @@ +"use strict"; + +function isSCSS(parser, text) { + const hasExplicitParserChoice = parser === "less" || parser === "scss"; + const IS_POSSIBLY_SCSS = /(\w\s*: [^}:]+|#){|@import[^\n]+(url|,)/; + return hasExplicitParserChoice + ? parser === "scss" + : IS_POSSIBLY_SCSS.test(text); +} + +module.exports = { + isSCSS +}; diff --git a/tests/css_trailing_comma/__snapshots__/jsfmt.spec.js.snap b/tests/css_trailing_comma/__snapshots__/jsfmt.spec.js.snap index b9a310af..a530487d 100644 --- a/tests/css_trailing_comma/__snapshots__/jsfmt.spec.js.snap +++ b/tests/css_trailing_comma/__snapshots__/jsfmt.spec.js.snap @@ -11,16 +11,207 @@ a { `; +exports[`declaration.css 2`] = ` +a { + margin: $bar,; +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +a { + margin: $bar; +} + +`; + exports[`list.css 1`] = ` $colors: hotpink deepskyblue firebrick,; +$list: (a,); +$list: ('Helvetica', 'Arial', sans-serif,); +$colors: ( + "red", + "blue" +); +$config: ( + themes: ( + mist: ( + header: #dcfac0, + content: #00968b, + footer: #85c79c + ), + $spring: ( + header: #f4fac7, + content: #c2454e, + footer: #ffb158 + ) + ) +); + +$breakpoint-map: ( + small: ( + min-width: null, + max-width: 479px, + base-font: 16px, + vertical-rhythm: 1.3 + ), + medium: ( + min-width: 480px, + max-width: 959px, + base-font: 18px, + vertical-rhythm: 1.414 + ), + large: ( + min-width: 960px, + max-width: 1099px, + base-font: 18px, + vertical-rhythm: 1.5 + ), + xlarge: ( + min-width: 1100px, + max-width: null, + base-font: 21px, + vertical-rhythm: 1.618 + ) +); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $colors: hotpink deepskyblue firebrick; +$list: (a); +$list: ( + "Helvetica", + "Arial", + sans-serif +); +$colors: ( + "red", + "blue" +); +$config: ( + themes: + ( + mist: (header: #dcfac0, content: #00968b, footer: #85c79c), + $spring: (header: #f4fac7, content: #c2454e, footer: #ffb158) + ) +); + +$breakpoint-map: ( + small: + (min-width: null, max-width: 479px, base-font: 16px, vertical-rhythm: 1.3), + medium: + ( + min-width: 480px, + max-width: 959px, + base-font: 18px, + vertical-rhythm: 1.414 + ), + large: + (min-width: 960px, max-width: 1099px, base-font: 18px, vertical-rhythm: 1.5), + xlarge: + ( + min-width: 1100px, + max-width: null, + base-font: 21px, + vertical-rhythm: 1.618 + ) +); + +`; + +exports[`list.css 2`] = ` +$colors: hotpink deepskyblue firebrick,; +$list: (a,); +$list: ('Helvetica', 'Arial', sans-serif,); +$colors: ( + "red", + "blue" +); +$config: ( + themes: ( + mist: ( + header: #dcfac0, + content: #00968b, + footer: #85c79c + ), + $spring: ( + header: #f4fac7, + content: #c2454e, + footer: #ffb158 + ) + ) +); + +$breakpoint-map: ( + small: ( + min-width: null, + max-width: 479px, + base-font: 16px, + vertical-rhythm: 1.3 + ), + medium: ( + min-width: 480px, + max-width: 959px, + base-font: 18px, + vertical-rhythm: 1.414 + ), + large: ( + min-width: 960px, + max-width: 1099px, + base-font: 18px, + vertical-rhythm: 1.5 + ), + xlarge: ( + min-width: 1100px, + max-width: null, + base-font: 21px, + vertical-rhythm: 1.618 + ) +); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +$colors: hotpink deepskyblue firebrick; +$list: (a); +$list: ( + "Helvetica", + "Arial", + sans-serif, +); +$colors: ( + "red", + "blue", +); +$config: ( + themes: + ( + mist: (header: #dcfac0, content: #00968b, footer: #85c79c,), + $spring: (header: #f4fac7, content: #c2454e, footer: #ffb158,), + ) +); + +$breakpoint-map: ( + small: + (min-width: null, max-width: 479px, base-font: 16px, vertical-rhythm: 1.3,), + medium: + ( + min-width: 480px, + max-width: 959px, + base-font: 18px, + vertical-rhythm: 1.414, + ), + large: + ( + min-width: 960px, + max-width: 1099px, + base-font: 18px, + vertical-rhythm: 1.5, + ), + xlarge: + ( + min-width: 1100px, + max-width: null, + base-font: 21px, + vertical-rhythm: 1.618, + ), +); `; exports[`map.css 1`] = ` -$map: (a,); -$map: ('Helvetica', 'Arial', sans-serif,); $map: ( small: 767px, medium: 992px, @@ -31,13 +222,8 @@ $map: ( 'large': (min-width: 1000px), 'huge': (min-width: 1200px), ); +$map: ( small: 767px, medium: 992px, large: 1200px ); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -$map: (a); -$map: ( - "Helvetica", - "Arial", - sans-serif -); $map: ( small: 767px, medium: 992px, @@ -48,6 +234,42 @@ $map: ( "large": (min-width: 1000px), "huge": (min-width: 1200px) ); +$map: ( + small: 767px, + medium: 992px, + large: 1200px +); + +`; + +exports[`map.css 2`] = ` +$map: ( + small: 767px, + medium: 992px, + large: 1200px, +); +$map: ( + 'medium': (min-width: 800px), + 'large': (min-width: 1000px), + 'huge': (min-width: 1200px), +); +$map: ( small: 767px, medium: 992px, large: 1200px ); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +$map: ( + small: 767px, + medium: 992px, + large: 1200px, +); +$map: ( + "medium": (min-width: 800px), + "large": (min-width: 1000px), + "huge": (min-width: 1200px), +); +$map: ( + small: 767px, + medium: 992px, + large: 1200px, +); `; @@ -75,6 +297,30 @@ asdasldaskdhjkashdahsdkjahskdjhakjsdkjahsdhkasdhkajsdhakjsdhkajsdhjkahskjdkjahsj `; +exports[`selector_list.css 2`] = ` +asdasldaskdhjkashdahsdkjahskdjhakjsdkjahsdhkasdhkajsdhakjsdhkajsdhjkahskjdkjahsjkdjkakjsdm, +asdasldaskdhjkashdahsdkjahskdjhakjsdkjahsdhkasdhkajsdhakjsdhkajsdhjkahskjdkjahsjkdjkakjsdm, { + +} + +.some-class, { +&.another-class, { + color: red; + } +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +asdasldaskdhjkashdahsdkjahskdjhakjsdkjahsdhkasdhkajsdhakjsdhkajsdhjkahskjdkjahsjkdjkakjsdm, +asdasldaskdhjkashdahsdkjahskdjhakjsdkjahsdhkasdhkajsdhakjsdhkajsdhjkahskjdkjahsjkdjkakjsdm { +} + +.some-class { + &.another-class { + color: red; + } +} + +`; + exports[`variable.css 1`] = ` $test: 1,; $margin: 0, 2em, 0, 1.5em,; @@ -84,3 +330,13 @@ $test: 1; $margin: 0, 2em, 0, 1.5em; `; + +exports[`variable.css 2`] = ` +$test: 1,; +$margin: 0, 2em, 0, 1.5em,; + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +$test: 1; +$margin: 0, 2em, 0, 1.5em; + +`; diff --git a/tests/css_trailing_comma/jsfmt.spec.js b/tests/css_trailing_comma/jsfmt.spec.js index 7d3726c8..ddf82c2c 100644 --- a/tests/css_trailing_comma/jsfmt.spec.js +++ b/tests/css_trailing_comma/jsfmt.spec.js @@ -1 +1,2 @@ run_spec(__dirname, ["css"]); +run_spec(__dirname, ["scss"], { trailingComma: "es5" }); diff --git a/tests/css_trailing_comma/list.css b/tests/css_trailing_comma/list.css index d8d5aa5a..9783f0a9 100644 --- a/tests/css_trailing_comma/list.css +++ b/tests/css_trailing_comma/list.css @@ -1 +1,48 @@ $colors: hotpink deepskyblue firebrick,; +$list: (a,); +$list: ('Helvetica', 'Arial', sans-serif,); +$colors: ( + "red", + "blue" +); +$config: ( + themes: ( + mist: ( + header: #dcfac0, + content: #00968b, + footer: #85c79c + ), + $spring: ( + header: #f4fac7, + content: #c2454e, + footer: #ffb158 + ) + ) +); + +$breakpoint-map: ( + small: ( + min-width: null, + max-width: 479px, + base-font: 16px, + vertical-rhythm: 1.3 + ), + medium: ( + min-width: 480px, + max-width: 959px, + base-font: 18px, + vertical-rhythm: 1.414 + ), + large: ( + min-width: 960px, + max-width: 1099px, + base-font: 18px, + vertical-rhythm: 1.5 + ), + xlarge: ( + min-width: 1100px, + max-width: null, + base-font: 21px, + vertical-rhythm: 1.618 + ) +); diff --git a/tests/css_trailing_comma/map.css b/tests/css_trailing_comma/map.css index ca883a7a..17af0c8c 100644 --- a/tests/css_trailing_comma/map.css +++ b/tests/css_trailing_comma/map.css @@ -1,5 +1,3 @@ -$map: (a,); -$map: ('Helvetica', 'Arial', sans-serif,); $map: ( small: 767px, medium: 992px, @@ -10,3 +8,4 @@ $map: ( 'large': (min-width: 1000px), 'huge': (min-width: 1200px), ); +$map: ( small: 767px, medium: 992px, large: 1200px );