Skip to content

Commit d058801

Browse files
author
Lennart Melzer
committed
Initial Commit
0 parents  commit d058801

File tree

10 files changed

+758
-0
lines changed

10 files changed

+758
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
tmp

Cakefile

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
fs = require 'fs'
2+
spawn = require('child_process').spawn
3+
4+
# Run a CoffeeScript through our node/coffee interpreter.
5+
run = (args, cb) ->
6+
proc = spawn 'coffee', args
7+
proc.stderr.on 'data', (buffer) -> console.log buffer.toString()
8+
proc.on 'exit', (status) ->
9+
process.exit(1) if status != 0
10+
cb() if typeof cb is 'function'
11+
12+
task 'build', 'build the CoffeeScript language from source', build = (cb) ->
13+
files = fs.readdirSync 'src'
14+
files = ('src/' + file for file in files when file.match(/\.coffee$/))
15+
run ['-c', '-o', 'lib/style-less'].concat(files), cb

README.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# styleLess
2+
3+
Parses LESS, beautifies LESS then writes LESS all using LESS.js
4+
5+
## Synopsis
6+
7+
__Warning__ this is opionionated formatting, as it compresses lines that take up
8+
less than 81 chars into one line to be more concise.
9+
10+
```less
11+
12+
/* Comments before rule */
13+
.navbar {
14+
background-color: black;
15+
color: #fff;
16+
height: 23px;
17+
-moz-transition-duration: 1337ms;
18+
width: ~`@{document.body.clientWidth}`;
19+
@desired-menu-width: 950px;
20+
21+
a:link, a:visited { color: #dadada; }
22+
23+
.nav-main {
24+
/* calls to mixins */
25+
.grid(24, 14);
26+
27+
/* Inline mixin declarations */
28+
.right-separator() { border-right: 1px solid #949494; }
29+
30+
/* Literal escaped values */
31+
filter: ~"progid:DXImageTransform.Microsoft.Alpha(Opacity=89)";
32+
33+
/* Literal quoted values */
34+
font-family: "Trebuchet MS";
35+
36+
li { &:first-child { margin: 0; } }
37+
38+
> li.submenu > a:link, > li.submenu > a:visited {
39+
background: url('icons/arrow-down.png') 23px 23px no-repeat transparent;
40+
.right-separator;
41+
}
42+
43+
// Keep Me
44+
.preview-label { width: 100px; display: block; font-size: small; }
45+
46+
li a:hover, li a:active, li.current a:link,
47+
li.current a:visited, li.submenu a:link, li.submenu a:visited {
48+
.menublock {
49+
opacity: 1;
50+
padding: 10px ((@desired-menu-width - 100px) / 2);
51+
}
52+
}
53+
}
54+
55+
/*
56+
* Comments after rule
57+
*/
58+
}
59+
60+
/* Comments between root rules */
61+
#main { .link { color: white; font-weight: bold; text-decoration: underline; } }
62+
63+
```
64+
65+
## Installation
66+
67+
npm install style-less
68+
69+
## Usage
70+
71+
style-less ugly.less > pretty.less
72+
73+
74+
75+

lib/style-less/beautifier.js

Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
2+
module.exports = function(tree) {
3+
var _compact, _filter, _isLogicalSection, _multi, _selectors, _shortened, _single;
4+
tree.Import.prototype.toLess = function() {
5+
if (this.css) {
6+
return this.toCSS();
7+
} else {
8+
return "@import " + this._path.toCSS() + ";";
9+
}
10+
};
11+
tree.mixin.Definition.prototype.toLess = function(ctx, env) {
12+
var merged, params, rules, sel;
13+
params = this.params.map(function(p) {
14+
if (p.value != null) {
15+
return p.name + ": " + p.value.toLess(env);
16+
} else {
17+
return p.name;
18+
}
19+
}).join(", ").trim();
20+
sel = this.selectors[0].toLess(env).trim() + "(" + (params || "") + ")";
21+
rules = this.rules.reduce(function(_css, r) {
22+
_css += ctx + " " + r.toLess(ctx + " ", env).trim();
23+
return _css;
24+
}, "");
25+
merged = _multi(sel, ctx, env, rules);
26+
if (merged.length > 80) {
27+
return ctx + merged;
28+
} else {
29+
return ctx + _single(sel, ctx, {
30+
compress: true
31+
}, rules);
32+
}
33+
};
34+
tree.Selector.prototype.toLess = function(env) {
35+
if (this._css) {
36+
console.log(this._css);
37+
this._css;
38+
}
39+
return this.elements.map(function(e) {
40+
if (typeof e === 'string') {
41+
return ' ' + e.trim();
42+
} else {
43+
return e.toLess(env);
44+
}
45+
}).join("");
46+
};
47+
tree.Color.prototype.toLess = function() {
48+
return this.toCSS();
49+
};
50+
tree.Call.prototype.toLess = function(env) {
51+
var args, _ref;
52+
args = (_ref = this.args) != null ? _ref.map(function(a) {
53+
return a.toLess(env);
54+
}).join(", ").trim() : void 0;
55+
return this.name + (args != null ? "(" + args + ")" : "");
56+
};
57+
tree.mixin.Call.prototype.toLess = function(env) {
58+
var args, _ref;
59+
args = (_ref = this.arguments) != null ? _ref.map(function(a) {
60+
return a.toLess(env);
61+
}).join(", ").trim() : void 0;
62+
return this.selector.toLess(env).trim() + (args != null ? "(" + args + ");" : ";");
63+
};
64+
tree.Directive.prototype.toLess = function(ctx, env) {
65+
var merged, params, rules, sel;
66+
params = this.params.map(function(p) {
67+
return p.toLess(env);
68+
}).join(", ").trim();
69+
sel = this.selectors[0].toLess(env).trim() + "(" + (params || "") + ")";
70+
rules = this.rules.map(function(r) {
71+
return r.toLess(env).trim();
72+
});
73+
merged = _multi(sel, ctx, env, rules);
74+
if (merged.length > 80) {
75+
return merged;
76+
} else {
77+
return _single(sel, ctx, {
78+
compress: true
79+
}, rules);
80+
}
81+
};
82+
tree.Dimension.prototype.toLess = function() {
83+
return this.toCSS();
84+
};
85+
tree.Anonymous.prototype.toLess = function() {
86+
return this.toCSS();
87+
};
88+
tree.Alpha.prototype.toLess = function() {
89+
return this.toCSS();
90+
};
91+
tree.Element.prototype.toLess = function(env) {
92+
return this.combinator.toLess(env || {}) + this.value;
93+
};
94+
tree.Combinator.prototype.toLess = function(env) {
95+
return {
96+
'': '',
97+
' ': ' ',
98+
'&': '&',
99+
'& ': '& ',
100+
':': ' :',
101+
'::': '::',
102+
'+': ' + ',
103+
'~': ' ~ ',
104+
'>': ' > '
105+
}[this.value];
106+
};
107+
tree.Expression.prototype.toLess = function(env) {
108+
return this.value.map(function(e) {
109+
return e.toLess(env);
110+
}).join(' ');
111+
};
112+
tree.JavaScript.prototype.toLess = function() {
113+
return "" + (this.escaped && "~" || "") + "`" + this.expression + "`";
114+
};
115+
tree.Keyword.prototype.toLess = function() {
116+
return this.toCSS();
117+
};
118+
tree.Quoted.prototype.toLess = function() {
119+
return (this.escaped && "~" || "") + this.quote + this.value + this.quote;
120+
};
121+
tree.URL.prototype.toLess = function(env) {
122+
return "url(" + this.value.toLess(env) + ")";
123+
};
124+
tree.Variable.prototype.toLess = function() {
125+
return this.name;
126+
};
127+
tree.Value.prototype.toLess = function(env) {
128+
return this.value.map(function(e) {
129+
return e.toLess(env);
130+
}).join(env.compress ? ',' : ', ');
131+
};
132+
tree.Shorthand.prototype.toLess = function(env) {
133+
return this.a.toLess(env) + "/" + this.b.toLess(env);
134+
};
135+
tree.Comment.prototype.toLess = function(env) {
136+
return this.toCSS(env);
137+
};
138+
tree.Rule.prototype.toLess = function(env) {
139+
return this.name + (env.compress ? ':' : ': ') + this.value.toLess(env) + this.important + ";";
140+
};
141+
tree.Operation.prototype.toLess = function(env) {
142+
return "(" + [this.operands[0].toLess(env), this.op, this.operands[1].toLess(env)].join(" ") + ")";
143+
};
144+
_multi = function(selector, context, env, rules) {
145+
return "" + selector + " {\n" + rules + "\n" + context + "}";
146+
};
147+
_single = function(selector, context, env, rules) {
148+
return selector + ' { ' + rules.trim() + ' }';
149+
};
150+
_selectors = function(paths, env, padding) {
151+
var i, mapped, part, results;
152+
mapped = paths.map(function(p) {
153+
return p.map(function(s) {
154+
return s.toLess(env);
155+
}).join('').trim();
156+
});
157+
results = [padding + mapped.shift()];
158+
if (mapped.length !== 0) {
159+
for (i in mapped) {
160+
part = mapped[i];
161+
if (env.compress) {
162+
results.push(',' + part);
163+
} else {
164+
if (paths.length > 3 && i % 3 === 2) {
165+
results.push(',\n' + padding + part);
166+
} else {
167+
results.push(', ' + part);
168+
}
169+
}
170+
}
171+
}
172+
return results.join("");
173+
};
174+
_filter = function(obj, iterator, context) {
175+
var results;
176+
results = [];
177+
if (obj === null) return results;
178+
return obj.filter(iterator, context);
179+
};
180+
_compact = function(array) {
181+
return _filter(array, function(value) {
182+
return !!value;
183+
});
184+
};
185+
_isLogicalSection = function(content) {
186+
var lastChar;
187+
lastChar = content.charAt(content.length - 2);
188+
return lastChar === ";" || lastChar === "}";
189+
};
190+
_shortened = function(content) {
191+
return content.replace(/\s+/g, " ").trim();
192+
};
193+
tree.Ruleset.prototype.toLess = function(context, env) {
194+
var css, merged, padding, paths, rules, rulesets, sel;
195+
var _this = this;
196+
css = "";
197+
paths = [];
198+
rulesets = [];
199+
if (!this.root) {
200+
paths = this.selectors.map(function(s) {
201+
return [s];
202+
});
203+
}
204+
padding = this.root ? "" : context + " ";
205+
rules = this.rules.reduce(function(_css, rule, r, list) {
206+
var comment, content, sel;
207+
if (rule.rules || (rule instanceof tree.Directive)) {
208+
sel = rule.selectors.map(function(s) {
209+
return s.toLess(env);
210+
}).join(", ").trim();
211+
if (_isLogicalSection(_css)) _css += "\n";
212+
content = rule.toLess(padding, env);
213+
if (_shortened(content).length < 90) {
214+
content = padding + _shortened(content);
215+
}
216+
_css += content;
217+
} else {
218+
if (rule instanceof tree.Comment) {
219+
if (_isLogicalSection(_css)) _css += "\n";
220+
if (_this.root) {
221+
_css += rule.toLess(env).trim();
222+
} else {
223+
comment = rule.value.toString().trim();
224+
_css += padding + comment;
225+
}
226+
} else {
227+
if (rule.toLess && !rule.variable) {
228+
_css += padding + rule.toLess(env);
229+
} else if (rule.value) {
230+
if (rule.variable) {
231+
_css += context + padding + rule.name + ": " + rule.value.toLess(env) + ";";
232+
} else {
233+
_css += context + rule.value.toString();
234+
}
235+
}
236+
}
237+
}
238+
if (list.length !== r + 1) _css += '\n';
239+
return _css;
240+
}, "");
241+
if (this.root) {
242+
css += rules;
243+
} else {
244+
sel = _selectors(paths, env, context);
245+
merged = _multi(sel, context, env, rules);
246+
if (merged.length > 80) {
247+
css += merged;
248+
} else {
249+
sel = _selectors(paths, {
250+
compress: false
251+
}, context);
252+
css += _single(sel, context, env, rules);
253+
}
254+
}
255+
return css;
256+
};
257+
};

lib/style-less/style-less.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
(function() {
2+
var Beautifier, fs, less, munge, parse, parser;
3+
4+
fs = require("fs");
5+
6+
less = require("less");
7+
8+
Beautifier = require(__dirname + '/beautifier');
9+
10+
less.tree = Beautifier(require(require('path').dirname(require.resolve('less')) + "/tree"));
11+
12+
parser = function(options) {
13+
return new less.Parser({
14+
paths: options.paths || []
15+
});
16+
};
17+
18+
parse = function(lessSrc, parser, cb) {
19+
return parser.parse(lessSrc, function(e, root) {
20+
return cb(e, root);
21+
});
22+
};
23+
24+
munge = function(lessSrc, parser, cb) {
25+
return parse(lessSrc, parser, function(e, root) {
26+
if (e) {
27+
return cb(e);
28+
} else {
29+
return cb(null, root.toLess("", "production"));
30+
}
31+
});
32+
};
33+
34+
module.exports = {
35+
parse: parse,
36+
munge: munge
37+
};
38+
39+
}).call(this);

0 commit comments

Comments
 (0)