Skip to content

Commit

Permalink
Added support for functions and conditions
Browse files Browse the repository at this point in the history
  • Loading branch information
ThisIsManta committed Apr 3, 2017
1 parent c8de9e7 commit b8e0bd8
Show file tree
Hide file tree
Showing 21 changed files with 423 additions and 21 deletions.
141 changes: 123 additions & 18 deletions edge/format.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@ const defaultFormattingOptions = {
insertBraces: true,
insertNewLineBetweenGroups: 1,
insertNewLineBetweenSelectors: false,
insertNewLineBetweenElseIf: false,
insertSpaceBeforeComments: true,
insertSpaceAfterComments: true,
insertParenthesisAroundConditions: true,
// TODO: insertLeadingZeroInFrontOfNumbers: true,
indentChar: '\t',
newLineChar: os.EOL,
stringQuoteChar: false, // Specify falsy for not chaning the original quote
Expand Down Expand Up @@ -290,36 +293,72 @@ function format(content, options) {
outputBuffer.append(indent)
}

outputBuffer.append(inputNode.name)

if (_.isObject(inputNode.val)) {
inputNode.val.parent = inputNode
const currentIsAnonymousFunc = inputNode.name === 'anonymous' && inputNode.val instanceof stylus.nodes.Function && inputNode.val.name === 'anonymous'
if (currentIsAnonymousFunc === false) {
outputBuffer.append(inputNode.name)
} else {
outputBuffer.append('@')
}

if (inputNode.val instanceof stylus.nodes.Function) {
inputNode.val.params.parent = inputNode.val
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'

outputBuffer.append('(' + inputNode.val.params.nodes.map(node => travel(inputNode.val.params, node, indentLevel, true)).join(', ') + ')')
outputBuffer.append(travel(inputNode.val, inputNode.val.block, indentLevel, false, { potentialCommentNodeInsideTheBlock: _.last(inputNode.val.params.nodes) }))
outputBuffer.remove(options.newLineChar)
if (inputNode.val instanceof stylus.nodes.Function) {
outputBuffer.append(travel(inputNode, inputNode.val, indentLevel, false))

} else if (inputNode.val instanceof stylus.nodes.Expression) {
outputBuffer.append(' = ')
outputBuffer.append(inputNode.val.nodes.map(node => travel(inputNode.val, node, indentLevel, true)).join(' '))
}
} else if (inputNode.val instanceof stylus.nodes.Expression) {
outputBuffer.append(' = ')
outputBuffer.append(travel(inputNode, inputNode.val, indentLevel, true))
}

if (insideExpression === false) {
if (options.insertSemicolons && !(inputNode.val instanceof stylus.nodes.Function)) {
if (options.insertSemicolons && !(inputNode.val instanceof stylus.nodes.Function) && currentHasChildOfAnonymousFunc === false) {
outputBuffer.append(';')
}
outputBuffer.append(options.newLineChar)
}

} else if (inputNode instanceof stylus.nodes.Function) {
outputBuffer.append('(' + travel(inputNode, inputNode.params, indentLevel, true) + ')')

outputBuffer.append(travel(inputNode, inputNode.block, indentLevel, false, { potentialCommentNodeInsideTheBlock: _.last(inputNode.params.nodes) }))
outputBuffer.remove(options.newLineChar)

} else if (inputNode instanceof stylus.nodes.Params) {
outputBuffer.append(inputNode.nodes.map(node => travel(inputNode, node, indentLevel, true) + (node.rest ? '...' : '')).join(', '))

} else if (inputNode instanceof stylus.nodes.Call) {
inputNode.args.parent = inputNode
if (inputNode.block) {
outputBuffer.append('+')
}

outputBuffer.append(inputNode.name)
outputBuffer.append('(' + inputNode.args.nodes.map(node => travel(inputNode.args, node, indentLevel, true)).join(', ') + ')')
outputBuffer.append(travel(inputNode, inputNode.args, indentLevel, true))

if (inputNode.block) {
outputBuffer.append(travel(inputNode, inputNode.block, indentLevel))
}

} else if (inputNode instanceof stylus.nodes.Return) {
outputBuffer.append('return ' + travel(inputNode, inputNode.expr, indentLevel, true))

if (insideExpression === false) {
if (options.insertSemicolons) {
outputBuffer.append(';')
}
outputBuffer.append(options.newLineChar)
}

} else if (inputNode instanceof stylus.nodes.Arguments) {
outputBuffer.append('(')
if (_.isEmpty(inputNode.map)) {
outputBuffer.append(inputNode.nodes.map(node => travel(inputNode, node, indentLevel, true)).join(', '))

} else {
outputBuffer.append(_.toPairs(inputNode.map).map(pair =>
pair[0] + ': ' + travel(inputNode, pair[1], indentLevel, true)
).join(', '))
}
outputBuffer.append(')')

} else if (inputNode instanceof stylus.nodes.Expression) {
if (insideExpression === false) {
Expand Down Expand Up @@ -404,6 +443,72 @@ function format(content, options) {
} else if (inputNode instanceof stylus.nodes.RGBA) {
outputBuffer.append(inputNode.raw.trim())

} else if (inputNode instanceof stylus.nodes.If) {
if (insideExpression === false) {
outputBuffer.append(indent)
}

const operation = inputNode.negate ? 'unless' : 'if'

if (inputNode.postfix) {
// Insert the `if` body
outputBuffer.append(travel(inputNode, inputNode.block, indentLevel, true))
outputBuffer.append(' ' + operation + ' ')

// Insert the `if` condition
if (options.insertParenthesisAroundConditions) {
outputBuffer.append('(')
}
outputBuffer.append(travel(inputNode, inputNode.cond, indentLevel, true))
if (options.insertParenthesisAroundConditions) {
outputBuffer.append(')')
}

if (options.insertSemicolons) {
outputBuffer.append(';')
}
outputBuffer.append(options.newLineChar)

} else {
if (insideExpression) {
outputBuffer.append(' ')
}

// Insert the `if` condition
outputBuffer.append(operation + ' ')
if (options.insertParenthesisAroundConditions) {
outputBuffer.append('(')
}
outputBuffer.append(travel(inputNode, inputNode.cond, indentLevel, true))
if (options.insertParenthesisAroundConditions) {
outputBuffer.append(')')
}

// Insert the `if` body
outputBuffer.append(travel(inputNode, inputNode.block, indentLevel, false))

// Insert `else` block(s)
if (inputNode.elses.length > 0) {
if (options.insertNewLineBetweenElseIf === false) {
outputBuffer.remove(options.newLineChar)
}

inputNode.elses.forEach((node, rank, list) => {
if (options.insertNewLineBetweenElseIf === true) {
outputBuffer.append(indent)
} else {
outputBuffer.append(' ')
}

outputBuffer.append('else' + travel(inputNode, node, indentLevel, true))

if (rank < list.length - 1 && options.insertNewLineBetweenElseIf === false) {
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)
Expand All @@ -423,7 +528,7 @@ function format(content, options) {
// Add a white-space between /* and */
commentLines[0] = '/*' + spaceAfterComment + commentLines[0].substring(2, commentLines[0].length - 2).trim() + spaceAfterComment + '*/'

} else { // In case of more than one line
} else { // In case of multiple lines
const documenting = _.first(commentLines).startsWith('/**')

// Add a white-space after /*
Expand Down Expand Up @@ -521,7 +626,7 @@ function format(content, options) {
}

function tryGetSingleLineCommentNodeOnTheRightOf(inputNode) {
if (!inputNode || lines[inputNode.lineno - 1].substring(inputNode.column - 1).includes('//') === false) {
if (!inputNode || lines[inputNode.lineno - 1] !== undefined && lines[inputNode.lineno - 1].substring(inputNode.column - 1).includes('//') === false) {
return null
}

Expand Down
15 changes: 15 additions & 0 deletions spec/condition-new-line/formattingOptions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"insertColons": true,
"insertSemicolons": true,
"insertBraces": true,
"insertNewLineBetweenGroups": 1,
"insertNewLineBetweenSelectors": false,
"insertNewLineBetweenElseIf": true,
"insertSpaceBeforeComments": true,
"insertSpaceAfterComments": true,
"insertParenthesisAroundConditions": true,
"indentChar": "\t",
"newLineChar": "\r\n",
"sortProperties": false,
"alwaysUseImport": false
}
13 changes: 13 additions & 0 deletions spec/condition-new-line/input.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
body
if x == y
margin 1

if x > y
padding x
else if x < y
padding x
else
padding 0

unless x == y
display none
17 changes: 17 additions & 0 deletions spec/condition-new-line/output.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
body {
if (x == y) {
margin: 1;
}
if (x > y) {
padding: x;
}
else if (x < y) {
padding: x;
}
else {
padding: 0;
}
unless (x == y) {
display: none;
}
}
15 changes: 15 additions & 0 deletions spec/condition-no-braces/formattingOptions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"insertColons": true,
"insertSemicolons": true,
"insertBraces": false,
"insertNewLineBetweenGroups": 1,
"insertNewLineBetweenSelectors": false,
"insertNewLineBetweenElseIf": true,
"insertSpaceBeforeComments": true,
"insertSpaceAfterComments": true,
"insertParenthesisAroundConditions": true,
"indentChar": "\t",
"newLineChar": "\r\n",
"sortProperties": false,
"alwaysUseImport": false
}
13 changes: 13 additions & 0 deletions spec/condition-no-braces/input.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
body
if x == y
margin 1

if x > y
padding x
else if x < y
padding x
else
padding 0

unless x == y
display none
11 changes: 11 additions & 0 deletions spec/condition-no-braces/output.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
body
if (x == y)
margin: 1;
if (x > y)
padding: x;
else if (x < y)
padding: x;
else
padding: 0;
unless (x == y)
display: none;
15 changes: 15 additions & 0 deletions spec/condition/formattingOptions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"insertColons": true,
"insertSemicolons": true,
"insertBraces": true,
"insertNewLineBetweenGroups": 1,
"insertNewLineBetweenSelectors": false,
"insertNewLineBetweenElseIf": false,
"insertSpaceBeforeComments": true,
"insertSpaceAfterComments": true,
"insertParenthesisAroundConditions": true,
"indentChar": "\t",
"newLineChar": "\r\n",
"sortProperties": false,
"alwaysUseImport": false
}
18 changes: 18 additions & 0 deletions spec/condition/input.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
body
if x == y
margin 1

if x > y
padding x
else if x < y
padding x
else
padding 0

unless x == y
display none

negative(n)
error('invalid number') unless n is a 'unit'
return yes if n < 0
no
22 changes: 22 additions & 0 deletions spec/condition/output.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
body {
if (x == y) {
margin: 1;
}
if (x > y) {
padding: x;
} else if (x < y) {
padding: x;
} else {
padding: 0;
}
unless (x == y) {
display: none;
}
}

negative(n) {
error('invalid number') unless (n is a 'unit');
return yes if (n < 0);

no;
}
13 changes: 13 additions & 0 deletions spec/function/formattingOptions.json
Original file line number Diff line number Diff line change
@@ -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
}
29 changes: 29 additions & 0 deletions spec/function/input.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
add(a,b)
a=unit(a,px)
b=unit(b,px)
a+b
body
padding add(10px,5)

func(x,y=unit(a,px))
x**y
func(x:10,y:25)
alias=func

multi-returned-value-func()
10px 25px

anonymous-func=@(a,b) {
a > b
}

body
color mix(#000,#fff,30%)

+prefix-classes('foo-')
.bar
width 10px

box-shadow(a,args...)
box-shadow args
border-radius arguments
Loading

0 comments on commit b8e0bd8

Please sign in to comment.