diff --git a/index.js b/index.js index 5c98029..426ab89 100644 --- a/index.js +++ b/index.js @@ -31,11 +31,11 @@ function substr(node, css) { function print_rule(node, indent_level, css) { let buffer = '' - if (node.prelude && node.prelude.type === 'SelectorList') { + if (node.prelude !== null && node.prelude.type === 'SelectorList') { buffer += print_selectorlist(node.prelude, indent_level, css) } - if (node.block && node.block.type === 'Block') { + if (node.block !== null && node.block.type === 'Block') { buffer += print_block(node.block, indent_level, css) } @@ -89,20 +89,28 @@ function print_selector(node, indent_level, css) { function print_block(node, indent_level, css) { let children = node.children - if (children.size === 0) { - return ' {}\n' + if (children.isEmpty) { + return ' {}' } let buffer = ' {\n' indent_level++ + let prev_type + for (let child of children) { if (child.type === 'Declaration') { buffer += print_declaration(child, indent_level, css) } else if (child.type === 'Rule') { + if (prev_type !== undefined && prev_type === 'Declaration') { + buffer += '\n' + } buffer += print_rule(child, indent_level, css) } else if (child.type === 'Atrule') { + if (prev_type !== undefined && prev_type === 'Declaration') { + buffer += '\n' + } buffer += print_atrule(child, indent_level, css) } else { buffer += print_unknown(child, indent_level, css) @@ -115,6 +123,8 @@ function print_block(node, indent_level, css) { buffer += '\n\n' } } + + prev_type = child.type } indent_level-- diff --git a/test.js b/test.js index 7cd17d3..4df3b15 100644 --- a/test.js +++ b/test.js @@ -64,8 +64,7 @@ test('Atrule blocks are surrounded by {} with correct spacing and indentation', test('Does not do AtRule prelude formatting', () => { let actual = format(`@media (min-width:1000px){}`) - let expected = `@media (min-width:1000px) {} -` + let expected = `@media (min-width:1000px) {}` assert.equal(actual, expected) }) @@ -86,8 +85,7 @@ selector1a, selector1b, selector1aa, selector2, -selector3 {} -` +selector3 {}` assert.equal(actual, expected) }) @@ -125,6 +123,7 @@ test('Declarations end with a semicolon (;)', () => { css { property1: value2; property2: value2; + & .nested { property1: value2; property2: value2; @@ -313,11 +312,9 @@ no-layer-2 { @layer test {} - @supports (min-width: 1px) { @layer deep { layer-deep {} - } } } @@ -329,7 +326,6 @@ test { @layer components { @layer alert {} - @layer table { @layer tbody, thead; @@ -358,7 +354,6 @@ test { @layer components.breadcrumb { layer-components-breadcrumb {} - } @font-face { @@ -370,4 +365,67 @@ test { assert.equal(actual, expected); }); +test('newline between last declaration and nested ruleset', () => { + let actual = format(` + test { + property1: value1; + & > item { + property2: value2; + & + another { + property3: value3; + } + } + } + `) + let expected = `test { + property1: value1; + + & > item { + property2: value2; + + & + another { + property3: value3; + } + } +}` + assert.equal(actual, expected) +}) + +test('newline between last declaration and nested atrule', () => { + let actual = format(` + test { + property1: value1; + @media all { + property2: value2; + } + } + `) + let expected = `test { + property1: value1; + + @media all { + property2: value2; + } +}` + assert.equal(actual, expected) +}) + +test('no trailing newline on empty nested rule', () => { + let actual = format(` + @layer test { + empty {} + } + `) + let expected = `@layer test { + empty {} +}` + assert.equal(actual, expected) +}) + +test('empty input', () => { + let actual = format(` `) + let expected = `` + assert.equal(actual, expected) +}) + test.run(); \ No newline at end of file