From bbce3c19ce081550a9597c1c1673d8d482ca7a9c Mon Sep 17 00:00:00 2001 From: "Anantachai Saothong (Manta)" Date: Tue, 4 Apr 2017 12:50:24 +0700 Subject: [PATCH] Added support for @rules, @extends and @block --- edge/format.js | 50 ++++++++++++++++++++++++------ spec/block/formattingOptions.json | 13 ++++++++ spec/block/input.styl | 10 ++++++ spec/block/output.styl | 11 +++++++ spec/extend/formattingOptions.json | 13 ++++++++ spec/extend/input.styl | 8 +++++ spec/extend/output.styl | 11 +++++++ spec/rule/formattingOptions.json | 13 ++++++++ spec/rule/input.styl | 14 +++++++++ spec/rule/output.styl | 21 +++++++++++++ test/runner.js | 2 ++ 11 files changed, 157 insertions(+), 9 deletions(-) create mode 100644 spec/block/formattingOptions.json create mode 100644 spec/block/input.styl create mode 100644 spec/block/output.styl create mode 100644 spec/extend/formattingOptions.json create mode 100644 spec/extend/input.styl create mode 100644 spec/extend/output.styl create mode 100644 spec/rule/formattingOptions.json create mode 100644 spec/rule/input.styl create mode 100644 spec/rule/output.styl diff --git a/edge/format.js b/edge/format.js index 106c8ce..ac10c78 100644 --- a/edge/format.js +++ b/edge/format.js @@ -148,7 +148,7 @@ function format(content, options) { const groups = [] _.difference(inputNode.nodes, commentNodes).forEach((node, rank, list) => { - if (rank > 0 && node.toJSON().__type === list[rank - 1].toJSON().__type && (node instanceof stylus.nodes.Group) === false) { + if (rank > 0 && node.toJSON().__type === list[rank - 1].toJSON().__type && node.block === undefined) { _.last(groups).push(node) } else { groups.push([node]) @@ -240,6 +240,9 @@ function format(content, options) { } else if (inputNode instanceof stylus.nodes.Selector) { outputBuffer.append(inputNode.segments.map(segment => travel(inputNode, segment, indentLevel, true))) + if (inputNode.optional) { + outputBuffer.append('!optional') + } } else if (inputNode instanceof stylus.nodes.Property) { // Insert the property name @@ -305,8 +308,6 @@ function format(content, options) { outputBuffer.append('@') } - const currentHasChildOfAnonymousFunc = inputNode.val instanceof stylus.nodes.Expression && inputNode.val.nodes.length === 1 && inputNode.val.nodes[0] instanceof stylus.nodes.Ident && inputNode.val.nodes[0].val instanceof stylus.nodes.Function && inputNode.val.nodes[0].val.name === 'anonymous' - if (inputNode.val instanceof stylus.nodes.Function) { outputBuffer.append(travel(inputNode, inputNode.val, indentLevel, false)) @@ -318,8 +319,12 @@ function format(content, options) { outputBuffer.append(' ' + inputNode.val.op + '= ' + travel(inputNode.val, inputNode.val.right, indentLevel, true)) } + const currentHasChildOfAnonymousFunc = inputNode.val instanceof stylus.nodes.Expression && inputNode.val.nodes.length === 1 && inputNode.val.nodes[0] instanceof stylus.nodes.Ident && inputNode.val.nodes[0].val instanceof stylus.nodes.Function && inputNode.val.nodes[0].val.name === 'anonymous' + + const currentHasChildOfAtblock = inputNode.val instanceof stylus.nodes.Expression && inputNode.val.nodes.length === 1 && inputNode.val.nodes[0] instanceof stylus.nodes.Atblock + if (insideExpression === false) { - if (options.insertSemicolons && !(inputNode.val instanceof stylus.nodes.Function) && currentHasChildOfAnonymousFunc === false) { + if (options.insertSemicolons && !(inputNode.val instanceof stylus.nodes.Function || currentHasChildOfAnonymousFunc || currentHasChildOfAtblock)) { outputBuffer.append(';') } outputBuffer.append(options.newLineChar) @@ -576,7 +581,7 @@ function format(content, options) { } } else if (inputNode instanceof stylus.nodes.Media) { - outputBuffer.append('@media ' + travel(inputNode, inputNode.val, indentLevel)) + outputBuffer.append(indent + '@media ' + travel(inputNode, inputNode.val, indentLevel)) outputBuffer.append(travel(inputNode, inputNode.block, indentLevel)) } else if (inputNode instanceof stylus.nodes.QueryList) { @@ -596,10 +601,34 @@ function format(content, options) { outputBuffer.append(travel(inputNode, inputNode.expr, indentLevel, true)) outputBuffer.append(')') + } else if (inputNode instanceof stylus.nodes.Supports) { + outputBuffer.append(indent + '@supports ') + outputBuffer.append(travel(inputNode, inputNode.condition, indentLevel, true)) + outputBuffer.append(travel(inputNode, inputNode.block, indentLevel, false)) + } else if (inputNode instanceof stylus.nodes.Atrule) { - outputBuffer.append('@' + inputNode.type) + outputBuffer.append(indent + '@' + inputNode.type) + if (_.some(inputNode.segments)) { + outputBuffer.append(' ' + inputNode.segments.map(segment => travel(inputNode, segment, indentLevel, true)).join('')) + } + outputBuffer.append(travel(inputNode, inputNode.block, indentLevel)) + + } else if (inputNode instanceof stylus.nodes.Extend) { + outputBuffer.append(indent + '@extends ' + inputNode.selectors.map(node => travel(inputNode, node, indentLevel, true)).join(', ')) + outputBuffer.append(options.newLineChar) + + } else if (inputNode instanceof stylus.nodes.Atblock) { + if (options.insertBraces) { + outputBuffer.append('@block') + } else { + outputBuffer.remove(' ') + } + outputBuffer.append(travel(inputNode, inputNode.block, indentLevel)) + // Remove the extra new-line because of `Ident` and `Block` + outputBuffer.remove(options.newLineChar) + } else if (inputNode instanceof stylus.nodes.Comment && inputNode.str.startsWith('//')) { // In case of single-line comment if (insideExpression === false) { outputBuffer.append(indent) @@ -691,7 +720,7 @@ function format(content, options) { const commentNodes = [] let zeroBasedLineIndex = inputNode.lineno - 1 - while (--zeroBasedLineIndex >= 0 && lines[zeroBasedLineIndex].trim().startsWith('//')) { + while (--zeroBasedLineIndex >= 0 && lines[zeroBasedLineIndex] !== undefined && lines[zeroBasedLineIndex].trim().startsWith('//')) { commentNodes.unshift(new stylus.nodes.Comment(lines[zeroBasedLineIndex].trim(), false, false)) } return commentNodes @@ -726,8 +755,11 @@ function format(content, options) { return null } - let zeroBasedLineIndex = inputNode.lineno - 1 - let sideCommentText = lines[zeroBasedLineIndex] + let sideCommentText = lines[inputNode.lineno - 1] + if (sideCommentText === undefined) { + return null + } + sideCommentText = sideCommentText.substring(sideCommentText.indexOf('//', inputNode.column)).trim() return new stylus.nodes.Comment(sideCommentText, false, false) } diff --git a/spec/block/formattingOptions.json b/spec/block/formattingOptions.json new file mode 100644 index 0000000..3ac7dea --- /dev/null +++ b/spec/block/formattingOptions.json @@ -0,0 +1,13 @@ +{ + "insertColons": true, + "insertSemicolons": true, + "insertBraces": true, + "insertNewLineBetweenGroups": 1, + "insertNewLineBetweenSelectors": false, + "insertSpaceBeforeComments": true, + "insertSpaceAfterComments": true, + "indentChar": "\t", + "newLineChar": "\r\n", + "sortProperties": false, + "alwaysUseImport": false +} \ No newline at end of file diff --git a/spec/block/input.styl b/spec/block/input.styl new file mode 100644 index 0000000..855a290 --- /dev/null +++ b/spec/block/input.styl @@ -0,0 +1,10 @@ +foo = + width 20px + +bar = @block { + height 30px +} + +.class1 + {foo} + {bar} \ No newline at end of file diff --git a/spec/block/output.styl b/spec/block/output.styl new file mode 100644 index 0000000..afd4704 --- /dev/null +++ b/spec/block/output.styl @@ -0,0 +1,11 @@ +foo = @block { + width: 20px; +} +bar = @block { + height: 30px; +} + +.class1 { + {foo}; + {bar}; +} \ No newline at end of file diff --git a/spec/extend/formattingOptions.json b/spec/extend/formattingOptions.json new file mode 100644 index 0000000..3ac7dea --- /dev/null +++ b/spec/extend/formattingOptions.json @@ -0,0 +1,13 @@ +{ + "insertColons": true, + "insertSemicolons": true, + "insertBraces": true, + "insertNewLineBetweenGroups": 1, + "insertNewLineBetweenSelectors": false, + "insertSpaceBeforeComments": true, + "insertSpaceAfterComments": true, + "indentChar": "\t", + "newLineChar": "\r\n", + "sortProperties": false, + "alwaysUseImport": false +} \ No newline at end of file diff --git a/spec/extend/input.styl b/spec/extend/input.styl new file mode 100644 index 0000000..54144c9 --- /dev/null +++ b/spec/extend/input.styl @@ -0,0 +1,8 @@ +$boo + color black + +.foo + @extend .class1 + @extend .class2, .class3, .class4 !optional + @extend $boo + color white \ No newline at end of file diff --git a/spec/extend/output.styl b/spec/extend/output.styl new file mode 100644 index 0000000..d4497b5 --- /dev/null +++ b/spec/extend/output.styl @@ -0,0 +1,11 @@ +$boo { + color: black; +} + +.foo { + @extends .class1 + @extends .class2, .class3, .class4 !optional + @extends $boo + + color: white; +} \ No newline at end of file diff --git a/spec/rule/formattingOptions.json b/spec/rule/formattingOptions.json new file mode 100644 index 0000000..3ac7dea --- /dev/null +++ b/spec/rule/formattingOptions.json @@ -0,0 +1,13 @@ +{ + "insertColons": true, + "insertSemicolons": true, + "insertBraces": true, + "insertNewLineBetweenGroups": 1, + "insertNewLineBetweenSelectors": false, + "insertSpaceBeforeComments": true, + "insertSpaceAfterComments": true, + "indentChar": "\t", + "newLineChar": "\r\n", + "sortProperties": false, + "alwaysUseImport": false +} \ No newline at end of file diff --git a/spec/rule/input.styl b/spec/rule/input.styl new file mode 100644 index 0000000..4cc5567 --- /dev/null +++ b/spec/rule/input.styl @@ -0,0 +1,14 @@ +@viewport + color: #00f + +@supports (display: flex) + div + display: flex + +@page :blank + @top-center + content: none + +@foo + @bar + width: 10px \ No newline at end of file diff --git a/spec/rule/output.styl b/spec/rule/output.styl new file mode 100644 index 0000000..59a1755 --- /dev/null +++ b/spec/rule/output.styl @@ -0,0 +1,21 @@ +@viewport { + color: #00f; +} + +@supports (display: flex) { + div { + display: flex; + } +} + +@page :blank { + @top-center { + content: none; + } +} + +@foo { + @bar { + width: 10px; + } +} \ No newline at end of file diff --git a/test/runner.js b/test/runner.js index 66e4b47..f3fd1c6 100644 --- a/test/runner.js +++ b/test/runner.js @@ -93,6 +93,8 @@ glob.sync('spec/' + (filteredSpecName || '*')) stack }) } + + expect(actual.warnings.length).toBe(0) }) }) })