Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion lib/io.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
var fs = require('fs'),
path = require('path'),
parser = require('./parser')();

module.exports = function(ioServer, options) {
Expand Down Expand Up @@ -31,8 +32,9 @@ module.exports = function(ioServer, options) {

saveVariables = function(socket) {
return function(variables) {
var syntax = path.extname(options.sassVariables).substring(1);
fs.readFile(options.styleVariables, {encoding: 'utf8'}, function(err, originalData) {
var data = parser.setVariables(originalData, variables);
var data = parser.setVariables(originalData, syntax, variables);
fs.writeFile(options.styleVariables, data, function(err, data) {
if (err) {
return console.error(err);
Expand Down
90 changes: 77 additions & 13 deletions lib/parser.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
module.exports = function() {
var parseVariables,
gonzales = require('gonzales-pe'),
gonzo = require('gonzales-ast');
gonzo = require('gonzales-ast'),
_ = require('lodash');

function astToSrc(ast, syntax) {
return gonzales.astToSrc({
Expand Down Expand Up @@ -67,19 +68,82 @@ module.exports = function() {
}

// Modifies string so that variables passed in object are updated
setVariables = function(string, variables) {
var sorted = [], lines = [];
// TODO: This is temporary solution that just re-generates whole file
for (var variableName in variables) {
if (variables.hasOwnProperty(variableName)) {
sorted.push(variableName);
}
}
sorted.sort();
for (var i = 0; i < sorted.length; i++) {
lines.push('$' + sorted[i] + ': ' + variables[sorted[i]] + ';');
setVariables = function(string, syntax, variables) {
var sorted = [], lines = [],
ast, result, changeVariable;

changeVariable = function(ast, key, value) {
return gonzo.traverse(ast, [
{
test: function(name, nodes) {
return name === 'declaration' && nodes[1][0] === 'variable' && nodes[1][1].indexOf(key) !== -1;
},
process: function(node) {
node[4] = [
'value',
value
]
return node;
}
},
{
test: function(name, nodes) {
return name === 'atrules';
},
process: function(node) {
var varName = node[1][1][1],
savedSpace = false;

/* Processed the variables declared as atrules
* Fix then https://github.com/tonyganch/gonzales-pe/issues/17 is fixed */
node.forEach(function(element, index) {
if (
element == 'atrules' ||
element[0] == 'atkeyword'
) {
return element;
};
if (
element[0] == 'operator' &&
element[1] == ':'
) {
return element;
}
/* Save only first space */
if (
element[0] == 's' &&
savedSpace == false
) {
savedSpace = true;
return;
}
if (varName == key) {
delete node[index]
}
});
if (varName == key) {
node.push(['value', value])
}
return node;
}
}
]);
}
return lines.join('\n');

ast = gonzales.srcToAST({
src: string,
syntax: syntax
});

_.forEach(variables, function(value, key) {
ast = changeVariable(ast, key, value);
});

result = gonzales.astToSrc({
ast: ast,
syntax: syntax
});
return result;
}

return {
Expand Down
179 changes: 165 additions & 14 deletions test/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,20 +129,171 @@ describe('Parser', function() {
});

describe('variable setter', function() {
it('should generate valid SASS file when original file is empty', function() {
var variables = {
mycolor: '#00ff00',
mypadding: '3px',
myfont: '"Helvetica Neue", Helvetica, Arial, sans-serif'
},
result = multiline(function() {
/*
$mycolor: #00ff00;
$myfont: "Helvetica Neue", Helvetica, Arial, sans-serif;
$mypadding: 3px;
*/
});
expect(parser.setVariables('', variables)).eql(result);
describe('SCSS syntax', function() {
it('should change single value variable', function() {
var str = multiline(function() {
/*
$mycolor: #00ff00;
$mypadding: 3px;
$myfont: "Helvetica Neue", Helvetica, Arial, sans-serif;
*/
}),
variables = {
mycolor: '#0000ff',
mypadding: '5px'
},
result = multiline(function() {
/*
$mycolor: #0000ff;
$mypadding: 5px;
$myfont: "Helvetica Neue", Helvetica, Arial, sans-serif;
*/
}),
changed = parser.setVariables(str, 'scss', variables);
expect(changed).eql(result);
});

it('should change complex value variable', function() {
var str = multiline(function() {
/*
$mycolor: #00ff00;
$mypadding: 3px;
$myfont: "Helvetica Neue", Helvetica, Arial, sans-serif;
*/
}),
variables = {
myfont: '"Helvetica Neue", Tahoma'
},
result = multiline(function() {
/*
$mycolor: #00ff00;
$mypadding: 3px;
$myfont: "Helvetica Neue", Tahoma;
*/
}),
changed = parser.setVariables(str, 'scss', variables);
expect(changed).eql(result);
});
it('should preserve indents', function() {
var str = multiline(function() {
/*

$mycolor: #00ff00;
$mypadding: 3px;
*/
}),
variables = {
mypadding: '5px'
},
result = multiline(function() {
/*

$mycolor: #00ff00;
$mypadding: 5px;
*/
}),
changed = parser.setVariables(str, 'scss', variables);
expect(changed).eql(result);
});
it('should preserve comments', function() {
var str = '' +
'$mycolor: #00ff00;\n' +
'/* Comment */\n' +
'$mypadding: 3px;',
variables = {
mypadding: '0'
},
result = '' +
'$mycolor: #00ff00;\n' +
'/* Comment */\n' +
'$mypadding: 0;',
changed = parser.setVariables(str, 'scss', variables);
expect(changed).eql(result);
});
});
describe('LESS syntax', function() {
it('should change single value variable', function() {
var str = multiline(function() {
/*
@mycolor: #00ff00;
@mypadding: 3px;
@myfont: "Helvetica Neue", Helvetica, Arial, sans-serif;
*/
}),
variables = {
mycolor: '#0000ff',
mypadding: '5px'
},
result = multiline(function() {
/*
@mycolor: #0000ff;
@mypadding: 5px;
@myfont: "Helvetica Neue", Helvetica, Arial, sans-serif;
*/
}),
changed = parser.setVariables(str, 'less', variables);
expect(changed).eql(result);
});

it('should change complex value variable', function() {
var str = multiline(function() {
/*
@mycolor: #00ff00;
@mypadding: 3px;
@myfont: "Helvetica Neue", Helvetica, Arial, sans-serif;
*/
}),
variables = {
myfont: '"Helvetica Neue", Tahoma'
},
result = multiline(function() {
/*
@mycolor: #00ff00;
@mypadding: 3px;
@myfont: "Helvetica Neue", Tahoma;
*/
}),
changed = parser.setVariables(str, 'less', variables);
expect(changed).eql(result);
});
it('should preserve indents', function() {
var str = multiline(function() {
/*

@mycolor: #00ff00;

@mypadding: 3px;
*/
}),
variables = {
mypadding: '5px'
},
result = multiline(function() {
/*

@mycolor: #00ff00;

@mypadding: 5px;
*/
}),
changed = parser.setVariables(str, 'less', variables);
expect(changed).eql(result);
});
it('should preserve comments', function() {
var str = '' +
'@mycolor: #00ff00;\n' +
'/* Comment */\n' +
'@mypadding: 3px;',
variables = {
mypadding: '0'
},
result = '' +
'@mycolor: #00ff00;\n' +
'/* Comment */\n' +
'@mypadding: 0;',
changed = parser.setVariables(str, 'less', variables);
expect(changed).eql(result);
});
});
});
});