Skip to content

Commit

Permalink
Added unit testing (cont')
Browse files Browse the repository at this point in the history
  • Loading branch information
ThisIsManta committed Mar 31, 2017
1 parent e36a290 commit 24d7790
Show file tree
Hide file tree
Showing 11 changed files with 218 additions and 32 deletions.
110 changes: 82 additions & 28 deletions edge/format.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ const defaultFormattingOptions = {
insertSpaceAfterComments: true,
indentChar: '\t',
newLineChar: os.EOL,
stringQuoteChar: false, // Specify falsy for not chaning the original quote
// TODO: sortImports: 'alphabetical',
sortProperties: 'alphabetical',
preferImport: false,
alwaysUseImport: false,
}

class StringBuffer {
Expand All @@ -41,7 +43,7 @@ class StringBuffer {
if (_.last(this.buffer) === text) {
this.buffer.pop()
} else if (_.last(this.buffer).endsWith(text)) {
this.buffer[this.buffer.length - 1] = _.last(this.buffer).substring(_.last(this.buffer).length - text.length)
this.buffer[this.buffer.length - 1] = _.last(this.buffer).substring(0, _.last(this.buffer).length - text.length)
}
}
return this
Expand Down Expand Up @@ -85,7 +87,7 @@ function format(content, options, isDebugging = false) {

const outputBuffer = new StringBuffer(options)

function travel(inputNode, levelCount, insideExpression = false) {
function travel(inputNode, levelCount, insideExpression = false, data = {}) {
const outputBuffer = new StringBuffer()
const indent = _.repeat(options.indentChar, levelCount)

Expand All @@ -99,23 +101,23 @@ function format(content, options, isDebugging = false) {
let buffer = travel(node, levelCount)

// Remove new line(s) between groups if the previous node is a sticky comment
if (node instanceof stylus.nodes.Group && rank >= 1 && list[rank - 1] instanceof stylus.nodes.Comment) {
/*if (node instanceof stylus.nodes.Group && rank >= 1 && list[rank - 1] instanceof stylus.nodes.Comment) {
buffer = buffer.substring(newLineBetweenGroups.length)
}
}*/

return buffer
return buffer + getNewLineBetweenGroups(node, rank, list)
}))

} else if (inputNode instanceof stylus.nodes.Import) {
outputBuffer.append(indent + `@${options.preferImport || inputNode.once === false ? 'import' : 'require'} '${inputNode.path.nodes[0].val}'`)
outputBuffer.append(indent + `@${options.alwaysUseImport || inputNode.once === false ? 'import' : 'require'} '${inputNode.path.nodes[0].val}'`)

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

} else if (inputNode instanceof stylus.nodes.Group) {
outputBuffer.append(newLineBetweenGroups)
// outputBuffer.append(newLineBetweenGroups)

// Insert single-line comment(s)
const topCommentNodes = tryGetSingleLineCommentNodesOnTheTopOf(_.first(inputNode.nodes))
Expand All @@ -127,20 +129,26 @@ function format(content, options, isDebugging = false) {
const separator = ',' + (options.insertNewLineBetweenSelectors ? (options.newLineChar + indent) : ' ')
outputBuffer.append(indent + inputNode.nodes.map(node => travel(node, levelCount, true)).join(separator).trim())

outputBuffer.append(travel(inputNode.block, levelCount, false, { potentialCommentNodeInsideTheBlock: _.last(inputNode.nodes) }))

} else if (inputNode instanceof stylus.nodes.Block) {
if (options.insertBraces) {
outputBuffer.append(' {')
}

// Insert a comment on the right of the last selector
const sideCommentNode = tryGetMultiLineCommentNodeOnTheRightOf(_.last(inputNode.nodes)) || tryGetSingleLineCommentNodeOnTheRightOf(_.last(inputNode.nodes))
const sideCommentNode = tryGetMultiLineCommentNodeOnTheRightOf(data.potentialCommentNodeInsideTheBlock) || tryGetSingleLineCommentNodeOnTheRightOf(data.potentialCommentNodeInsideTheBlock)
if (sideCommentNode) {
if (options.insertSpaceBeforeComments) {
outputBuffer.append(' ')
}
outputBuffer.append(travel(sideCommentNode, levelCount, true))
}

outputBuffer.append(options.newLineChar)

// Filter and sort CSS properties
let properties = inputNode.block.nodes.filter(node => node instanceof stylus.nodes.Property)
let properties = inputNode.nodes.filter(node => node instanceof stylus.nodes.Property)
if (options.sortProperties === 'alphabetical') {
properties = _.sortBy(properties, node => node.segments.map(segment => segment.name).join(''))
} else if (options.sortProperties === 'grouped') {
Expand All @@ -156,10 +164,10 @@ function format(content, options, isDebugging = false) {
}

// Filter multi-line comment(s)
const comments = inputNode.block.nodes.filter(node => node instanceof stylus.nodes.Comment)
const comments = inputNode.nodes.filter(node => node instanceof stylus.nodes.Comment)

// Merge and sort everything together
let sortedNodes = properties.concat(_.difference(inputNode.block.nodes, properties, comments))
let sortedNodes = properties.concat(_.difference(inputNode.nodes, properties, comments))

sortedNodes.forEach(node => {
node.commentsOnTop = tryGetSingleLineCommentNodesOnTheTopOf(node)
Expand All @@ -183,12 +191,12 @@ function format(content, options, isDebugging = false) {
sideNode.commentsOnRight.push(comment)

} else {
const index = inputNode.block.nodes.indexOf(comment)
if (index === inputNode.block.nodes.length - 1) {
const index = inputNode.nodes.indexOf(comment)
if (index === inputNode.nodes.length - 1) {
sortedNodes.push(comment)

} else {
let belowNode = inputNode.block.nodes[index + 1]
let belowNode = inputNode.nodes[index + 1]
if (_.includes(sortedNodes, belowNode)) {
if (belowNode.commentsOnTop === undefined) {
belowNode.commentsOnTop = []
Expand All @@ -204,27 +212,24 @@ function format(content, options, isDebugging = false) {
}).value()

// Insert CSS body (all of the nodes above)
outputBuffer.append(sortedNodes.map(node => travel(node, levelCount + 1)))
outputBuffer.append(sortedNodes.map((node, rank, list) => {
return travel(node, levelCount + 1) + getNewLineBetweenGroups(node, rank, list)
}))

// Insert the bottom comment(s)
const bottomCommentNodes = tryGetSingleLineCommentNodesOnTheBottomOf(_.last(sortedNodes))
outputBuffer.append(bottomCommentNodes.map(node => travel(node, levelCount + 1)))
if (bottomCommentNodes.length > 0) {
console.log(bottomCommentNodes)
}

if (options.insertBraces) {
outputBuffer.append(indent + '}').append(options.newLineChar)
}

} else if (inputNode instanceof stylus.nodes.Selector) {
outputBuffer.append(inputNode.segments.map(segment => segment.string))
outputBuffer.append(inputNode.segments.map(segment => travel(segment, levelCount, true)))

} else if (inputNode instanceof stylus.nodes.Property) {
// Insert the property name
outputBuffer.append(indent + inputNode.segments.map(segment => {
return segment.name
}).join(' '))
outputBuffer.append(indent + inputNode.segments.map(segment => travel(segment, levelCount, true)).join(''))

if (options.insertColons) {
outputBuffer.append(':')
Expand Down Expand Up @@ -267,23 +272,49 @@ function format(content, options, isDebugging = false) {

outputBuffer.append(options.newLineChar)

} else if (inputNode instanceof stylus.nodes.Literal) {
outputBuffer.append(inputNode.val)

} else if (inputNode instanceof stylus.nodes.String) {
outputBuffer.append(options.stringQuoteChar || inputNode.quote).append(inputNode.val).append(options.stringQuoteChar || inputNode.quote)

} else if (inputNode instanceof stylus.nodes.Ident) {
outputBuffer.append(inputNode.name)

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

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

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

} else if (inputNode instanceof stylus.nodes.Unit) {
outputBuffer.append(inputNode.val).append(inputNode.type)

} else if (inputNode instanceof stylus.nodes.Call) {
outputBuffer.append(inputNode.name).append('(' + inputNode.args.nodes.map(node => travel(node, levelCount)).join(', ') + ')')

} else if (inputNode instanceof stylus.nodes.Expression) {
outputBuffer.append(inputNode.nodes.map(node => travel(node, levelCount)).join(' '))
outputBuffer.append(inputNode.nodes.map(node => {
if (node instanceof stylus.nodes.Ident) {
return '{' + travel(node, levelCount, true) + '}'
} else {
return travel(node, levelCount, true)
}
}).join(' '))

} else if (inputNode instanceof stylus.nodes.Comment && inputNode.str.startsWith('//')) { // In case of single-line comment
if (insideExpression === false) {
outputBuffer.append(indent)
} else if (options.insertSpaceBeforeComments) {
outputBuffer.append(' ')
}
outputBuffer.append('//' + (options.insertSpaceAfterComments ? ' ' : '') + inputNode.str.substring(2).trim())
if (insideExpression === false) {
Expand Down Expand Up @@ -351,6 +382,9 @@ function format(content, options, isDebugging = false) {

if (inputNode.commentsOnRight) {
outputBuffer.remove(options.newLineChar)
if (options.insertSpaceBeforeComments) {
outputBuffer.append(' ')
}
outputBuffer.append(inputNode.commentsOnRight.map(node => travel(node, levelCount, true)))
outputBuffer.append(options.newLineChar)
}
Expand All @@ -368,6 +402,10 @@ function format(content, options, isDebugging = false) {
}

function tryGetSingleLineCommentNodesOnTheBottomOf(inputNode) {
if (!inputNode) {
return null
}

const commentNodes = []
let zeroBasedLineIndex = inputNode.lineno - 1
const sourceNodeIndent = lines[zeroBasedLineIndex].substring(0, lines[zeroBasedLineIndex].length - _.trimStart(lines[zeroBasedLineIndex]).length)
Expand All @@ -378,7 +416,7 @@ function format(content, options, isDebugging = false) {
}

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

Expand All @@ -389,7 +427,7 @@ function format(content, options, isDebugging = false) {
}

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

Expand All @@ -412,6 +450,22 @@ function format(content, options, isDebugging = false) {
return new stylus.nodes.Comment(sideCommentText, false, false)
}

function getNewLineBetweenGroups(node, rank, list) {
if (!options.insertNewLineBetweenGroups || rank === list.length - 1 || (node instanceof stylus.nodes.Comment)) {
return ''
}

if (options.insertNewLineBetweenGroups && node instanceof stylus.nodes.Group) {
return options.newLineChar
}

if (_.isFunction(node.toJSON) && rank + 1 < list.length && _.isFunction(list[rank + 1].toJSON) && node.toJSON().__type === list[rank + 1].toJSON().__type) {
return ''
}

return options.newLineChar
}

let output = travel(rootNode, 0)
if (output.startsWith(options.newLineChar)) {
output = output.substring(options.newLineChar.length)
Expand Down
2 changes: 1 addition & 1 deletion spec/comment-multi-line/formattingOptions.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
"indentChar": "\t",
"newLineChar": "\r\n",
"sortProperties": false,
"preferImport": false
"alwaysUseImport": false
}
2 changes: 2 additions & 0 deletions spec/comment-multi-line/output.styl
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
.class1 { /* side-comment */
/* another-top-comment */
margin: 8px /* another-middle-comment */ 0; /* another-side-comment */

/* bottom-comment */
}

/* first-line
second-line
*/
Expand Down
2 changes: 1 addition & 1 deletion spec/comment-single-line/formattingOptions.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
"indentChar": "\t",
"newLineChar": "\r\n",
"sortProperties": false,
"preferImport": false
"alwaysUseImport": false
}
13 changes: 13 additions & 0 deletions spec/interpolation/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
}
11 changes: 11 additions & 0 deletions spec/interpolation/input.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
mixin(pos, val)
margin-{pos} val

row=1
row=2
div:nth-child({row})
display none

mySelectors='#foo,#bar,.baz'
{mySelectors}
display none
15 changes: 15 additions & 0 deletions spec/interpolation/output.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
mixin(pos, val) {
margin-{pos}: val;
}
row = 1
row = 2

div:nth-child({row}) {
display: none;
}

mySelectors = '#foo,#bar,.baz'

{mySelectors} {
display: none;
}
13 changes: 13 additions & 0 deletions spec/selector/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
}
33 changes: 33 additions & 0 deletions spec/selector/input.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
body
display none

#id1
display none

.class1
display none

& #id1
display none

&_bem1
display none

^[0]:hover
display none

&^[1..-1]
display none

~/:hover &
display none

/body
display none

.class2
../input
display none

body > a
display none
Loading

0 comments on commit 24d7790

Please sign in to comment.