Skip to content

Instantly share code, notes, and snippets.

@bebraw

bebraw/mixin.css

Created Dec 27, 2011
Embed
What would you like to do?
more.js blog post examples part 2
#header {
border-radius: 5px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
}
#footer {
border-radius: 10px;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
}
#content {
border-radius: 20px;
-webkit-border-radius: 20px;
-moz-border-radius: 20px;
}
var replaceVariables = function(line, vars) {
for(var k in vars) {
var v = vars[k];
line = line.replace(k, v);
}
return line;
};
var findMixins = function(tree) {
var ret = {};
var parseParams = function(line) {
var ret = {};
var parts;
line = line.trim();
line = line.substr(1, line.length - 2);
parts = line.split(',');
parts.forEach(function(k) {
var segments = k.split(':');
ret[segments[0]] = segments[1];
});
return ret;
};
tree.forEach(function(child) {
if (child.name.search('mixin ') == 0) {
var parts = child.name.split(' ');
var name = parts[1];
var params = parseParams(parts.slice(2).join(''));
ret[child.name.split(' ')[1].trim()] = {
children: child.children,
params: params
};
// mark as deleted so we can avoid this later
child.deleted = true;
}
});
return ret;
};
mixins = findMixins(tree);
var setParams = function(params, values) {
values = values || [];
var ret = {};
var i = 0;
for(var k in params) {
ret[k] = values[i] || params[k];
i++;
};
return ret;
};
var recursion = function(tree, i, vars) {
return tree.map(function(child) {
if (child.deleted) {
return '';
}
var ret = '';
var parts = child.name.split(':');
var begin = parts[0];
if (begin in mixins) {
var values = parts[1] || '';
values = values.trim().split(' ');
var mixin = mixins[begin];
var mixinParams = setParams(mixin.params, values);
ret += recursion(mixin.children, i, mixinParams).join('\n');
return ret;
}
var prefix = chars(' ', i * 4);
var name = replaceVariables(replaceVariables(child.name, vars), variables);
ret = prefix + name;
...
mixin roundedCorners (@radius: 5px)
border-radius: @radius
-webkit-border-radius: @radius
-moz-border-radius: @radius
#header
roundedCorners
#footer
roundedCorners: 10px
@a: 20px
#content
roundedCorners: @a
#!/usr/bin/env node
var fs = require('fs');
var source = process.argv.splice(2)[0];
var target = source.substring(0, source.lastIndexOf('.')) + '.css';
fs.readFile(source, 'utf-8', function(err, data) {
if (err) throw err;
var analyze = function(input) {
return input.map(function(line) {
var rPart = line.trimLeft();
return {l: line.replace(rPart, ''), r: rPart};
});
};
var treeify = function(input) {
var parents = [];
return input.filter(function(elem) {return elem.l || elem.r;}).
map(function(line) {
elem = {name: line.r, children: [], ind: line.l.length};
parent = parents[parents.length - 1] || {ind: 0};
if (parent.ind == elem.ind) {
parents.pop();
parent = parents[parents.length -1] || {ind: 0};
}
elem.parent = parent;
if (elem.ind == 0) {
parents = [elem];
elem.parent = null;
return elem;
}
else if (parent.ind < elem.ind) {
parents.push(elem);
parent.children.push(elem);
}
}).filter(function(elem) {return elem;});
};
var printTree = function(tree, i) {
i = i || 0;
tree.forEach(function(k) {
console.log('depth: ' + i);
console.log('name: ' + k.name);
console.log('parent: ' + k.parent);
printTree(k.children, i + 1);
});
};
var chars = function(c, n) {
var ret = '';
for(var i = 0; i < n; i++) {
ret += c;
}
return ret;
};
var transform = function(tree) {
var variables;
var mixins;
var nested = [];
var findVariables = function(tree) {
var ret = {};
tree.forEach(function(child) {
if (child.name[0] == '@') {
var parts = child.name.split(':');
ret[parts[0]] = parts[1].trim();
}
});
return ret;
};
variables = findVariables(tree);
var replaceVariables = function(line, vars) {
for(var k in vars) {
var v = vars[k];
line = line.replace(k, v);
}
return line;
};
var findMixins = function(tree) {
var ret = {};
var parseParams = function(line) {
var ret = {};
var parts;
line = line.trim();
line = line.substr(1, line.length - 2);
parts = line.split(',');
parts.forEach(function(k) {
var segments = k.split(':');
ret[segments[0]] = segments[1];
});
return ret;
};
tree.forEach(function(child) {
if (child.name.search('mixin ') == 0) {
var parts = child.name.split(' ');
var name = parts[1];
var params = parseParams(parts.slice(2).join(''));
ret[child.name.split(' ')[1].trim()] = {
children: child.children,
params: params
};
// mark as deleted so we can avoid this later
child.deleted = true;
}
});
return ret;
};
mixins = findMixins(tree);
var setParams = function(params, values) {
values = values || [];
var ret = {};
var i = 0;
for(var k in params) {
ret[k] = values[i] || params[k];
i++;
};
return ret;
};
var recursion = function(tree, i, vars) {
return tree.map(function(child) {
if (child.deleted) {
return '';
}
var ret = '';
var parts = child.name.split(':');
var begin = parts[0];
if (begin in mixins) {
var values = parts[1] || '';
values = values.trim().split(' ');
var mixin = mixins[begin];
var mixinParams = setParams(mixin.params, values);
ret += recursion(mixin.children, i, mixinParams).join('\n');
return ret;
}
var prefix = chars(' ', i * 4);
var name = replaceVariables(replaceVariables(child.name, vars), variables);
ret = prefix + name;
if (child.children.length) {
if (child.parent) {
// going to handle these later separately
// we'll lose positional data but it's
// a bit easier this way
// alternatively could try to sort attributes
// within blocks and then render nesting here
nested.push(child);
ret = '';
}
else {
ret += ' {\n' + recursion(child.children, i + 1).join('\n') + '\n}\n';
}
}
else {
ret += ';';
}
return ret;
});
};
var ret = recursion(tree, 0);
var getFullName = function(child) {
return child.parent? getFullName(child.parent) + ' ' + child.name: child.name;
};
if (nested.length) {
nested = nested.map(function(child) {
child.name = getFullName(child);
child.parent = null;
return child;
});
ret.push(transform(nested));
}
return ret.filter(function(o) {return o;});
};
var parts = analyze(data.split('\n'));
var tree = treeify(parts);
var output = transform(tree).join('\n');
console.log(output);
fs.writeFile(target, output, function(err) {
if (err) throw err;
console.log('Wrote ' + target + '!');
});
});
#header {
color: #4D926F;
}
h2 {
color: #4D926F;
}
var transform = function(tree) {
var variables;
var nested = [];
var findVariables = function(tree) {
var ret = {};
tree.forEach(function(child) {
if (child.name[0] == '@') {
var parts = child.name.split(':');
ret[parts[0]] = parts[1].trim();
}
});
return ret;
};
variables = findVariables(tree);
var replaceVariables = function(line) {
for(var k in variables) {
var v = variables[k];
line = line.replace(k, v);
}
return line;
};
var recursion = function(tree, i) {
return tree.map(function(child) {
var prefix = chars(' ', i * 4);
var ret = prefix + replaceVariables(child.name);
...
/* idea borrowed from LESS http://lesscss.org/ */
@color: #4D926F
#header
color: @color
h2
color: @color
@lukewatts

This comment has been minimized.

Copy link

@lukewatts lukewatts commented May 31, 2017

Add the following after the first if (err) throw err in more.js to account for Windows OS \r\n and Mac \r newlines:

data = data.replace(/\r\n|\r/gm, '\n');

Otherwise you end up with this:

div
 {
    color: white
;
    border: 1px solid black
;

}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment