From 204068cf1985285fd586f26a396a86a247b3e89d Mon Sep 17 00:00:00 2001 From: 1000ch Date: Thu, 27 Mar 2014 12:42:31 +0900 Subject: [PATCH 1/9] support preprocessors --- lib/parser.js | 80 +++++++++++++++++++++++++++- lib/stylestats.js | 6 ++- package.json | 131 ++++++++++++++++++++++++---------------------- 3 files changed, 149 insertions(+), 68 deletions(-) diff --git a/lib/parser.js b/lib/parser.js index e5a6106..21c988c 100644 --- a/lib/parser.js +++ b/lib/parser.js @@ -36,6 +36,31 @@ function Parser(urls, files, styles) { this.urls = urls; this.files = files; this.styles = styles; + + this.cssFiles = []; + this.sassFiles = []; + this.lessFiles = []; + this.stylusFiles = []; + + for (var i = 0, l = this.files.length;i < l;i++) { + var file = this.files[i]; + var extname = path.extname(file); + switch (extname) { + case '.css': + this.cssFiles.push(file); + break; + case '.scss': + case '.sass': + this.sassFiles.push(file); + break; + case '.less': + this.lessFiles.push(file); + break; + case '.stylus': + this.stylusFiles.push(file); + break; + } + } } /** @@ -66,13 +91,64 @@ Parser.prototype.parse = function(callback) { // css string array from arguments // they will be joined into css string - this.files.forEach(function(file) { + this.cssFiles.forEach(function(cssFile) { // push local css data - that.styles.push(fs.readFileSync(file, { + that.styles.push(fs.readFileSync(cssFile, { encoding: 'utf8' })); }); + if (this.sassFiles.length !== 0) { + var sass = require('node-sass'); + this.sassFiles.forEach(function (sassFile) { + var string = fs.readFileSync(__dirname + sassFile, 'utf8'); + var css = sass.renderSync({ + data: string + }); + that.styles.push(css); + }); + } + + if (this.lessFiles.length !== 0) { + var less = require('less'); + this.lessFiles.forEach(function (lessFile) { + var promise = new Promise(function (resolve, reject) { + var string = fs.readFileSync(__dirname + lessFile, 'utf8'); + less.render(string, function (error, css) { + if (error) { + reject(error); + } + resolve(css); + }); + }); + promise.then(function onFulfilled(value) { + that.styles.push(value); + }, function onRejected(error) { + throw error; + }); + }); + } + + if (this.stylusFiles.length !== 0) { + var stylus = require('stylus'); + this.stylusFiles.forEach(function (stylusFile) { + var promise = new Promise(function (resolve, reject) { + var string = fs.readFileSync(__dirname + stylusFile, 'utf8'); + stylus.render(string, function (error, css) { + if (error) { + reject(error); + } + resolve(css); + }); + }); + promise.then(function onFulfilled(value) { + that.styles.push(value); + }, function onRejected(error) { + throw error; + }); + }); + } + // get remote files Promise.all(requestPromises).then(function onFulfilled(responses) { diff --git a/lib/stylestats.js b/lib/stylestats.js index d9e9b3e..c3b012b 100644 --- a/lib/stylestats.js +++ b/lib/stylestats.js @@ -34,13 +34,15 @@ function StyleStats(args, config) { this.files = []; this.styles = []; + var EXTENSIONS = ['.sass', '.scss', '.less', '.styl', '.stylus', '.css']; + // check arguments which is url or file path or other args.forEach(function(arg) { - if (util.isFile(arg) && path.extname(arg) === '.css') { + if (util.isFile(arg) && EXTENSIONS.indexOf(path.extname(arg)) !== -1) { that.files.push(arg); } else if (util.isDirectory(arg)) { fs.readdirSync(arg).filter(function(file) { - return (path.extname(file) === '.css'); + return (EXTENSIONS.indexOf(path.extname(file)) !== -1); }).forEach(function(file) { that.files.push(arg + file); }); diff --git a/package.json b/package.json index 2b0dce6..8d301fe 100644 --- a/package.json +++ b/package.json @@ -1,65 +1,68 @@ { - "name": "stylestats", - "version": "3.0.0", - "main": "lib/stylestats.js", - "bin": { - "stylestats": "bin/cli.js" - }, - "description": "StyleStats is Node.js library to collect CSS statistics!", - "homepage": "https://github.com/t32k/stylestats", - "bugs": "https://github.com/t32k/stylestats/issues", - "author": { - "name": "Koji Ishimoto", - "email": "ijok.ijok@gmail.com", - "web": "http://t32k.me/" - }, - "maintainers": { - "name": "Shogo Sensui", - "email": "shogo.sensui@gmail.com", - "web": "http://1000ch.net/" - }, - "repository": { - "type": "git", - "url": "git@github.com:t32k/stylestats.git" - }, - "license": "MIT", - "keywords": [ - "css", - "stylesheet", - "performance", - "property" - ], - "scripts": { - "test": "mocha --timeout 5000 --reporter=spec" - }, - "engines": { - "node": "0.10.x" - }, - "files": [ - "lib", - "bin", - "assets" - ], - "dependencies": { - "jade": "~1.3.0", - "glob": "~3.2.9", - "numeral": "~1.5.3", - "promise": "~4.0.0", - "cheerio": "~0.13.1", - "request": "~2.34.0", - "json2csv": "~2.2.1", - "css-parse": "~1.7.0", - "commander": "~2.1.0", - "cli-table": "~0.3.0", - "gzip-size": "~0.1.0", - "underscore": "~1.6.0", - "underscore.string": "~2.3.3" - }, - "devDependencies": { - "mocha": "~1.18.2", - "testem": "~0.6.8", - "istanbul": "~0.2.6", - "coveralls": "~2.10.0", - "mocha-lcov-reporter": "0.0.1" - } -} \ No newline at end of file + "name": "stylestats", + "version": "3.0.0", + "main": "lib/stylestats.js", + "bin": { + "stylestats": "bin/cli.js" + }, + "description": "StyleStats is Node.js library to collect CSS statistics!", + "homepage": "https://github.com/t32k/stylestats", + "bugs": "https://github.com/t32k/stylestats/issues", + "author": { + "name": "Koji Ishimoto", + "email": "ijok.ijok@gmail.com", + "web": "http://t32k.me/" + }, + "maintainers": { + "name": "Shogo Sensui", + "email": "shogo.sensui@gmail.com", + "web": "http://1000ch.net/" + }, + "repository": { + "type": "git", + "url": "git@github.com:t32k/stylestats.git" + }, + "license": "MIT", + "keywords": [ + "css", + "stylesheet", + "performance", + "property" + ], + "scripts": { + "test": "mocha --timeout 5000 --reporter=spec" + }, + "engines": { + "node": "0.10.x" + }, + "files": [ + "lib", + "bin", + "assets" + ], + "dependencies": { + "jade": "~1.3.0", + "glob": "~3.2.9", + "numeral": "~1.5.3", + "promise": "~4.0.0", + "cheerio": "~0.13.1", + "request": "~2.34.0", + "json2csv": "~2.2.1", + "css-parse": "~1.7.0", + "commander": "~2.1.0", + "cli-table": "~0.3.0", + "gzip-size": "~0.1.0", + "underscore": "~1.6.0", + "underscore.string": "~2.3.3", + "node-sass": "^0.8.4", + "stylus": "^0.42.3", + "less": "^1.7.0" + }, + "devDependencies": { + "mocha": "~1.18.2", + "testem": "~0.6.8", + "istanbul": "~0.2.6", + "coveralls": "~2.10.0", + "mocha-lcov-reporter": "0.0.1" + } +} From fabd1d2fdb4621d8ec3a634d1e0001a9fe46773b Mon Sep 17 00:00:00 2001 From: 1000ch Date: Thu, 27 Mar 2014 13:36:18 +0900 Subject: [PATCH 2/9] add path --- lib/parser.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/parser.js b/lib/parser.js index 21c988c..b5837b0 100644 --- a/lib/parser.js +++ b/lib/parser.js @@ -1,5 +1,6 @@ var _ = require('underscore'); var fs = require('fs'); +var path = require('path'); var url = require('url'); var Promise = require('promise'); var request = require('request'); From d6db02aebae1e3f84e756f547d3a382a7e0551ac Mon Sep 17 00:00:00 2001 From: t32k Date: Thu, 27 Mar 2014 14:18:57 +0900 Subject: [PATCH 3/9] cosme --- lib/parser.js | 21 ++++---- lib/stylestats.js | 2 +- package.json | 134 +++++++++++++++++++++++----------------------- 3 files changed, 78 insertions(+), 79 deletions(-) diff --git a/lib/parser.js b/lib/parser.js index b5837b0..c9e06ad 100644 --- a/lib/parser.js +++ b/lib/parser.js @@ -1,7 +1,7 @@ var _ = require('underscore'); var fs = require('fs'); -var path = require('path'); var url = require('url'); +var path = require('path'); var Promise = require('promise'); var request = require('request'); var cheerio = require('cheerio'); @@ -43,8 +43,7 @@ function Parser(urls, files, styles) { this.lessFiles = []; this.stylusFiles = []; - for (var i = 0, l = this.files.length;i < l;i++) { - var file = this.files[i]; + this.files.forEach(function(file) { var extname = path.extname(file); switch (extname) { case '.css': @@ -61,7 +60,7 @@ function Parser(urls, files, styles) { this.stylusFiles.push(file); break; } - } + }, this); } /** @@ -101,7 +100,7 @@ Parser.prototype.parse = function(callback) { if (this.sassFiles.length !== 0) { var sass = require('node-sass'); - this.sassFiles.forEach(function (sassFile) { + this.sassFiles.forEach(function(sassFile) { var string = fs.readFileSync(__dirname + sassFile, 'utf8'); var css = sass.renderSync({ data: string @@ -112,10 +111,10 @@ Parser.prototype.parse = function(callback) { if (this.lessFiles.length !== 0) { var less = require('less'); - this.lessFiles.forEach(function (lessFile) { - var promise = new Promise(function (resolve, reject) { + this.lessFiles.forEach(function(lessFile) { + var promise = new Promise(function(resolve, reject) { var string = fs.readFileSync(__dirname + lessFile, 'utf8'); - less.render(string, function (error, css) { + less.render(string, function(error, css) { if (error) { reject(error); } @@ -132,10 +131,10 @@ Parser.prototype.parse = function(callback) { if (this.stylusFiles.length !== 0) { var stylus = require('stylus'); - this.stylusFiles.forEach(function (stylusFile) { - var promise = new Promise(function (resolve, reject) { + this.stylusFiles.forEach(function(stylusFile) { + var promise = new Promise(function(resolve, reject) { var string = fs.readFileSync(__dirname + stylusFile, 'utf8'); - stylus.render(string, function (error, css) { + stylus.render(string, function(error, css) { if (error) { reject(error); } diff --git a/lib/stylestats.js b/lib/stylestats.js index c3b012b..929be4b 100644 --- a/lib/stylestats.js +++ b/lib/stylestats.js @@ -46,7 +46,7 @@ function StyleStats(args, config) { }).forEach(function(file) { that.files.push(arg + file); }); - } else if (URL.test(arg) && path.extname(arg).indexOf('.css') > -1) { + } else if (URL.test(arg) && path.extname(arg).indexOf('.css') !== -1) { that.urls.push(arg); } else if (URL.test(arg)) { that.urls.push(arg); diff --git a/package.json b/package.json index 8d301fe..c3db368 100644 --- a/package.json +++ b/package.json @@ -1,68 +1,68 @@ { - "name": "stylestats", - "version": "3.0.0", - "main": "lib/stylestats.js", - "bin": { - "stylestats": "bin/cli.js" - }, - "description": "StyleStats is Node.js library to collect CSS statistics!", - "homepage": "https://github.com/t32k/stylestats", - "bugs": "https://github.com/t32k/stylestats/issues", - "author": { - "name": "Koji Ishimoto", - "email": "ijok.ijok@gmail.com", - "web": "http://t32k.me/" - }, - "maintainers": { - "name": "Shogo Sensui", - "email": "shogo.sensui@gmail.com", - "web": "http://1000ch.net/" - }, - "repository": { - "type": "git", - "url": "git@github.com:t32k/stylestats.git" - }, - "license": "MIT", - "keywords": [ - "css", - "stylesheet", - "performance", - "property" - ], - "scripts": { - "test": "mocha --timeout 5000 --reporter=spec" - }, - "engines": { - "node": "0.10.x" - }, - "files": [ - "lib", - "bin", - "assets" - ], - "dependencies": { - "jade": "~1.3.0", - "glob": "~3.2.9", - "numeral": "~1.5.3", - "promise": "~4.0.0", - "cheerio": "~0.13.1", - "request": "~2.34.0", - "json2csv": "~2.2.1", - "css-parse": "~1.7.0", - "commander": "~2.1.0", - "cli-table": "~0.3.0", - "gzip-size": "~0.1.0", - "underscore": "~1.6.0", - "underscore.string": "~2.3.3", - "node-sass": "^0.8.4", - "stylus": "^0.42.3", - "less": "^1.7.0" - }, - "devDependencies": { - "mocha": "~1.18.2", - "testem": "~0.6.8", - "istanbul": "~0.2.6", - "coveralls": "~2.10.0", - "mocha-lcov-reporter": "0.0.1" - } -} + "name": "stylestats", + "version": "3.0.1", + "main": "lib/stylestats.js", + "bin": { + "stylestats": "bin/cli.js" + }, + "description": "StyleStats is Node.js library to collect CSS statistics!", + "homepage": "https://github.com/t32k/stylestats", + "bugs": "https://github.com/t32k/stylestats/issues", + "author": { + "name": "Koji Ishimoto", + "email": "ijok.ijok@gmail.com", + "web": "http://t32k.me/" + }, + "maintainers": { + "name": "Shogo Sensui", + "email": "shogo.sensui@gmail.com", + "web": "http://1000ch.net/" + }, + "repository": { + "type": "git", + "url": "git@github.com:t32k/stylestats.git" + }, + "license": "MIT", + "keywords": [ + "css", + "stylesheet", + "performance", + "property" + ], + "scripts": { + "test": "mocha --timeout 5000 --reporter=spec" + }, + "engines": { + "node": "0.10.x" + }, + "files": [ + "lib", + "bin", + "assets" + ], + "dependencies": { + "jade": "~1.3.0", + "glob": "~3.2.9", + "less": "~1.7.0", + "stylus": "~0.42.3", + "numeral": "~1.5.3", + "promise": "~4.0.0", + "cheerio": "~0.13.1", + "request": "~2.34.0", + "json2csv": "~2.2.1", + "css-parse": "~1.7.0", + "node-sass": "~0.8.4", + "commander": "~2.1.0", + "cli-table": "~0.3.0", + "gzip-size": "~0.1.0", + "underscore": "~1.6.0", + "underscore.string": "~2.3.3" + }, + "devDependencies": { + "mocha": "~1.18.2", + "testem": "~0.6.8", + "istanbul": "~0.2.6", + "coveralls": "~2.10.0", + "mocha-lcov-reporter": "0.0.1" + } +} \ No newline at end of file From c7c6353cca19d04a0b3de49631fea5bb7a5dee0b Mon Sep 17 00:00:00 2001 From: t32k Date: Thu, 27 Mar 2014 16:38:12 +0900 Subject: [PATCH 4/9] Add tests --- lib/parser.js | 8 +++-- test/fixture/prepros/foo.less | 40 ++++++++++++++++++++++ test/fixture/prepros/foo.scss | 46 +++++++++++++++++++++++++ test/fixture/prepros/foo.styl | 14 ++++++++ test/fixture/prepros/reset.scss | 2 ++ test/stats-test.js | 60 +++++++++++++++++++++++++-------- 6 files changed, 153 insertions(+), 17 deletions(-) create mode 100644 test/fixture/prepros/foo.less create mode 100644 test/fixture/prepros/foo.scss create mode 100644 test/fixture/prepros/foo.styl create mode 100644 test/fixture/prepros/reset.scss diff --git a/lib/parser.js b/lib/parser.js index c9e06ad..0ef4b5e 100644 --- a/lib/parser.js +++ b/lib/parser.js @@ -101,7 +101,7 @@ Parser.prototype.parse = function(callback) { if (this.sassFiles.length !== 0) { var sass = require('node-sass'); this.sassFiles.forEach(function(sassFile) { - var string = fs.readFileSync(__dirname + sassFile, 'utf8'); + var string = fs.readFileSync(sassFile, 'utf8'); var css = sass.renderSync({ data: string }); @@ -113,7 +113,7 @@ Parser.prototype.parse = function(callback) { var less = require('less'); this.lessFiles.forEach(function(lessFile) { var promise = new Promise(function(resolve, reject) { - var string = fs.readFileSync(__dirname + lessFile, 'utf8'); + var string = fs.readFileSync(lessFile, 'utf8'); less.render(string, function(error, css) { if (error) { reject(error); @@ -133,7 +133,8 @@ Parser.prototype.parse = function(callback) { var stylus = require('stylus'); this.stylusFiles.forEach(function(stylusFile) { var promise = new Promise(function(resolve, reject) { - var string = fs.readFileSync(__dirname + stylusFile, 'utf8'); + var string = fs.readFileSync(stylusFile, 'utf8'); + console.log(string); stylus.render(string, function(error, css) { if (error) { reject(error); @@ -142,6 +143,7 @@ Parser.prototype.parse = function(callback) { }); }); promise.then(function onFulfilled(value) { + console.log('code ' + value); that.styles.push(value); }, function onRejected(error) { throw error; diff --git a/test/fixture/prepros/foo.less b/test/fixture/prepros/foo.less new file mode 100644 index 0000000..f097248 --- /dev/null +++ b/test/fixture/prepros/foo.less @@ -0,0 +1,40 @@ +@nice-blue: #5B83AD; +@light-blue: @nice-blue + #111; + +#header { + color: @light-blue; +} + +.bordered { + border-top: dotted 1px black; + border-bottom: solid 2px black; +} + +#menu a { + color: #111; + .bordered; +} + +.post a { + color: red; + .bordered; +} + +#header { + color: black; + .navigation { + font-size: 12px; + } + .logo { + width: 300px; + } +} + +@base: #f04615; +@width: 0.5; + +.class { + width: percentage(@width); // returns `50%` + color: saturate(@base, 5%); + background-color: spin(lighten(@base, 25%), 8); +} diff --git a/test/fixture/prepros/foo.scss b/test/fixture/prepros/foo.scss new file mode 100644 index 0000000..0f66f32 --- /dev/null +++ b/test/fixture/prepros/foo.scss @@ -0,0 +1,46 @@ +//@import "reset.scss"; + +$font-stack: Helvetica, sans-serif; +$primary-color: #333; + +body { + font: 100% $font-stack; + color: $primary-color; +} + +nav { + ul { + margin: 0; + padding: 0; + list-style: none; + } + + li { display: inline-block; } + + a { + display: block; + padding: 6px 12px; + text-decoration: none; + } +} + +@mixin border-radius($radius) { + -webkit-border-radius: $radius; + -moz-border-radius: $radius; + -ms-border-radius: $radius; + border-radius: $radius; +} + +.box { @include border-radius(10px); } + + +.message { + border: 1px solid #ccc; + padding: 10px; + color: #333; +} + +.success { + @extend .message; + border-color: green; +} \ No newline at end of file diff --git a/test/fixture/prepros/foo.styl b/test/fixture/prepros/foo.styl new file mode 100644 index 0000000..e96ace1 --- /dev/null +++ b/test/fixture/prepros/foo.styl @@ -0,0 +1,14 @@ +border-radius() + -webkit-border-radius: arguments + -moz-border-radius: arguments + border-radius: arguments + +body a + font: 12px/1.4 "Lucida Grande", Arial, sans-serif + background: black + color: #ccc + +form input + padding: 5px + border: 1px solid + border-radius: 5px \ No newline at end of file diff --git a/test/fixture/prepros/reset.scss b/test/fixture/prepros/reset.scss new file mode 100644 index 0000000..b0854aa --- /dev/null +++ b/test/fixture/prepros/reset.scss @@ -0,0 +1,2 @@ +/* Eric Meyer's Reset CSS v2.0 - http://cssreset.com */ +html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{border:0;font-size:100%;font:inherit;vertical-align:baseline;margin:0;padding:0}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:none}table{border-collapse:collapse;border-spacing:0} \ No newline at end of file diff --git a/test/stats-test.js b/test/stats-test.js index eab3441..915af5d 100644 --- a/test/stats-test.js +++ b/test/stats-test.js @@ -95,15 +95,25 @@ describe('Customize with option', function() { }); -describe('Analyze remote css file', function() { - it('should return file size', function(done) { - var requestStats = new StyleStats('http://t32k.me/static/blog/skelton.css?query'); - requestStats.parse(function(requestResult) { - assert.equal(requestResult.size, 15419); - done(); - }); - }); -}); +//describe('Analyze remote css file', function() { +// it('should return file size', function(done) { +// var requestStats = new StyleStats('http://t32k.me/static/blog/skelton.css?query'); +// requestStats.parse(function(requestResult) { +// assert.equal(requestResult.size, 15419); +// done(); +// }); +// }); +//}); +// +//describe('Analyze HTML pages', function() { +// it('should return the number of stylesheets', function(done) { +// var htmlStats = new StyleStats('https://dl.dropboxusercontent.com/u/356242/test/stats/async.html'); +// htmlStats.parse(function(htmlResult) { +// assert.equal(htmlResult.size, 508); +// done(); +// }); +// }); +//}); describe('Analyze files of specified directory', function() { it('should return file size', function(done) { @@ -152,11 +162,33 @@ describe('Analyze raw contents files', function() { }); }); -describe('Analyze HTML pages', function() { - it('should return the number of stylesheets', function(done) { - var htmlStats = new StyleStats('https://dl.dropboxusercontent.com/u/356242/test/stats/async.html'); - htmlStats.parse(function(htmlResult) { - assert.equal(htmlResult.size, 508); + + +describe('Analyze Sass files', function() { + it('should return file size', function(done) { + var sassStats = new StyleStats('test/fixture/prepros/foo.scss'); + sassStats.parse(function(sassResult) { + assert.equal(sassResult.size, 467); + done(); + }); + }); +}); + +describe('Analyze LESS files', function() { + it('should return file size', function(done) { + var lessStats = new StyleStats('test/fixture/prepros/foo.less'); + lessStats.parse(function(lessResult) { + assert.equal(lessResult.size, 472); + done(); + }); + }); +}); + +describe('Analyze Stylus files', function() { + it('should return file size', function(done) { + var stylStats = new StyleStats('test/fixture/prepros/foo.styl'); + stylStats.parse(function(stylResult) { + assert.equal(stylResult.size, 472); done(); }); }); From 96001f71387b337c0be7a6b013552132c38e31ab Mon Sep 17 00:00:00 2001 From: t32k Date: Thu, 27 Mar 2014 17:18:04 +0900 Subject: [PATCH 5/9] Fix test --- lib/parser.js | 12 ++++++------ test/stats-test.js | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/parser.js b/lib/parser.js index 0ef4b5e..d65d5c5 100644 --- a/lib/parser.js +++ b/lib/parser.js @@ -56,6 +56,7 @@ function Parser(urls, files, styles) { case '.less': this.lessFiles.push(file); break; + case '.styl': case '.stylus': this.stylusFiles.push(file); break; @@ -97,7 +98,7 @@ Parser.prototype.parse = function(callback) { encoding: 'utf8' })); }); - + // Sass compile if (this.sassFiles.length !== 0) { var sass = require('node-sass'); this.sassFiles.forEach(function(sassFile) { @@ -108,7 +109,7 @@ Parser.prototype.parse = function(callback) { that.styles.push(css); }); } - + // LESS compile if (this.lessFiles.length !== 0) { var less = require('less'); this.lessFiles.forEach(function(lessFile) { @@ -128,14 +129,14 @@ Parser.prototype.parse = function(callback) { }); }); } - + // Stylus compile if (this.stylusFiles.length !== 0) { var stylus = require('stylus'); this.stylusFiles.forEach(function(stylusFile) { var promise = new Promise(function(resolve, reject) { var string = fs.readFileSync(stylusFile, 'utf8'); - console.log(string); - stylus.render(string, function(error, css) { + + stylus(string).render(function(error, css) { if (error) { reject(error); } @@ -143,7 +144,6 @@ Parser.prototype.parse = function(callback) { }); }); promise.then(function onFulfilled(value) { - console.log('code ' + value); that.styles.push(value); }, function onRejected(error) { throw error; diff --git a/test/stats-test.js b/test/stats-test.js index 915af5d..8958910 100644 --- a/test/stats-test.js +++ b/test/stats-test.js @@ -188,7 +188,7 @@ describe('Analyze Stylus files', function() { it('should return file size', function(done) { var stylStats = new StyleStats('test/fixture/prepros/foo.styl'); stylStats.parse(function(stylResult) { - assert.equal(stylResult.size, 472); + assert.equal(stylResult.size, 230); done(); }); }); From 6e3d11d7113a69b8175579699b522a47f0fd88a1 Mon Sep 17 00:00:00 2001 From: t32k Date: Thu, 27 Mar 2014 18:35:50 +0900 Subject: [PATCH 6/9] Delete Sass support, because of node-sass have many troubles @import-ed files --- lib/parser.js | 16 ------------ lib/stylestats.js | 2 +- test/fixture/prepros/bar.less | 3 +++ test/fixture/prepros/foo.less | 11 +++++--- test/fixture/prepros/foo.scss | 46 --------------------------------- test/fixture/prepros/reset.scss | 2 -- test/stats-test.js | 13 +--------- 7 files changed, 13 insertions(+), 80 deletions(-) create mode 100644 test/fixture/prepros/bar.less delete mode 100644 test/fixture/prepros/foo.scss delete mode 100644 test/fixture/prepros/reset.scss diff --git a/lib/parser.js b/lib/parser.js index d65d5c5..f51019a 100644 --- a/lib/parser.js +++ b/lib/parser.js @@ -49,10 +49,6 @@ function Parser(urls, files, styles) { case '.css': this.cssFiles.push(file); break; - case '.scss': - case '.sass': - this.sassFiles.push(file); - break; case '.less': this.lessFiles.push(file); break; @@ -98,17 +94,6 @@ Parser.prototype.parse = function(callback) { encoding: 'utf8' })); }); - // Sass compile - if (this.sassFiles.length !== 0) { - var sass = require('node-sass'); - this.sassFiles.forEach(function(sassFile) { - var string = fs.readFileSync(sassFile, 'utf8'); - var css = sass.renderSync({ - data: string - }); - that.styles.push(css); - }); - } // LESS compile if (this.lessFiles.length !== 0) { var less = require('less'); @@ -135,7 +120,6 @@ Parser.prototype.parse = function(callback) { this.stylusFiles.forEach(function(stylusFile) { var promise = new Promise(function(resolve, reject) { var string = fs.readFileSync(stylusFile, 'utf8'); - stylus(string).render(function(error, css) { if (error) { reject(error); diff --git a/lib/stylestats.js b/lib/stylestats.js index 929be4b..e6db430 100644 --- a/lib/stylestats.js +++ b/lib/stylestats.js @@ -34,7 +34,7 @@ function StyleStats(args, config) { this.files = []; this.styles = []; - var EXTENSIONS = ['.sass', '.scss', '.less', '.styl', '.stylus', '.css']; + var EXTENSIONS = ['.less', '.styl', '.stylus', '.css']; // check arguments which is url or file path or other args.forEach(function(arg) { diff --git a/test/fixture/prepros/bar.less b/test/fixture/prepros/bar.less new file mode 100644 index 0000000..0292450 --- /dev/null +++ b/test/fixture/prepros/bar.less @@ -0,0 +1,3 @@ +.bar { + color: red +} \ No newline at end of file diff --git a/test/fixture/prepros/foo.less b/test/fixture/prepros/foo.less index f097248..2db4e60 100644 --- a/test/fixture/prepros/foo.less +++ b/test/fixture/prepros/foo.less @@ -1,3 +1,7 @@ +@import "../test.css"; +//@import "bar.less"; + +// Variables @nice-blue: #5B83AD; @light-blue: @nice-blue + #111; @@ -5,21 +9,21 @@ color: @light-blue; } +// Mixins .bordered { border-top: dotted 1px black; border-bottom: solid 2px black; } - #menu a { color: #111; .bordered; } - .post a { color: red; .bordered; } +// Nested rules #header { color: black; .navigation { @@ -30,6 +34,7 @@ } } +// Functions @base: #f04615; @width: 0.5; @@ -37,4 +42,4 @@ width: percentage(@width); // returns `50%` color: saturate(@base, 5%); background-color: spin(lighten(@base, 25%), 8); -} +} \ No newline at end of file diff --git a/test/fixture/prepros/foo.scss b/test/fixture/prepros/foo.scss deleted file mode 100644 index 0f66f32..0000000 --- a/test/fixture/prepros/foo.scss +++ /dev/null @@ -1,46 +0,0 @@ -//@import "reset.scss"; - -$font-stack: Helvetica, sans-serif; -$primary-color: #333; - -body { - font: 100% $font-stack; - color: $primary-color; -} - -nav { - ul { - margin: 0; - padding: 0; - list-style: none; - } - - li { display: inline-block; } - - a { - display: block; - padding: 6px 12px; - text-decoration: none; - } -} - -@mixin border-radius($radius) { - -webkit-border-radius: $radius; - -moz-border-radius: $radius; - -ms-border-radius: $radius; - border-radius: $radius; -} - -.box { @include border-radius(10px); } - - -.message { - border: 1px solid #ccc; - padding: 10px; - color: #333; -} - -.success { - @extend .message; - border-color: green; -} \ No newline at end of file diff --git a/test/fixture/prepros/reset.scss b/test/fixture/prepros/reset.scss deleted file mode 100644 index b0854aa..0000000 --- a/test/fixture/prepros/reset.scss +++ /dev/null @@ -1,2 +0,0 @@ -/* Eric Meyer's Reset CSS v2.0 - http://cssreset.com */ -html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{border:0;font-size:100%;font:inherit;vertical-align:baseline;margin:0;padding:0}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:none}table{border-collapse:collapse;border-spacing:0} \ No newline at end of file diff --git a/test/stats-test.js b/test/stats-test.js index 8958910..6fa6b76 100644 --- a/test/stats-test.js +++ b/test/stats-test.js @@ -163,22 +163,11 @@ describe('Analyze raw contents files', function() { }); - -describe('Analyze Sass files', function() { - it('should return file size', function(done) { - var sassStats = new StyleStats('test/fixture/prepros/foo.scss'); - sassStats.parse(function(sassResult) { - assert.equal(sassResult.size, 467); - done(); - }); - }); -}); - describe('Analyze LESS files', function() { it('should return file size', function(done) { var lessStats = new StyleStats('test/fixture/prepros/foo.less'); lessStats.parse(function(lessResult) { - assert.equal(lessResult.size, 472); + assert.equal(lessResult.size, 495); done(); }); }); From 747e68ca6bb5febd03e374cd1f6c0ad85e6558fb Mon Sep 17 00:00:00 2001 From: t32k Date: Thu, 27 Mar 2014 21:08:15 +0900 Subject: [PATCH 7/9] Support LESS --- lib/parser.js | 79 ++++++++++++++++++----------------- test/fixture/prepros/foo.less | 3 +- test/stats-test.js | 2 +- 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/lib/parser.js b/lib/parser.js index f51019a..50477c3 100644 --- a/lib/parser.js +++ b/lib/parser.js @@ -7,6 +7,8 @@ var request = require('request'); var cheerio = require('cheerio'); var cssParse = require('css-parse'); +var util = require('./util'); + /** * Get promised request * @param {String} url @@ -98,20 +100,19 @@ Parser.prototype.parse = function(callback) { if (this.lessFiles.length !== 0) { var less = require('less'); this.lessFiles.forEach(function(lessFile) { + var parser = new(less.Parser)({ + filename: lessFile + }); var promise = new Promise(function(resolve, reject) { var string = fs.readFileSync(lessFile, 'utf8'); - less.render(string, function(error, css) { + parser.parse(string, function(error, tree) { if (error) { reject(error); } - resolve(css); + resolve(tree.toCSS()); }); }); - promise.then(function onFulfilled(value) { - that.styles.push(value); - }, function onRejected(error) { - throw error; - }); + requestPromises.push(promise); }); } // Stylus compile @@ -136,43 +137,43 @@ Parser.prototype.parse = function(callback) { } // get remote files - Promise.all(requestPromises).then(function onFulfilled(responses) { + Promise.all(requestPromises).then(function onFulfilled(results) { // requests to stylesheet defined in html var requestPromisesInner = []; - // push remote css data - responses.forEach(function(response) { - - // response content type - var contentType = response.headers['content-type']; - - if (contentType.indexOf('html') > -1) { - - // parse response body - var $ = cheerio.load(response.body); - var $link = $('link[rel=stylesheet]'); - var $style = $('style'); - - // add css file count - result.cssFiles += $link.length; - result.styleElements += $style.length; - - // request link[href] - $link.each(function() { - var relPath = $(this).attr('href'); - var absPath = url.resolve(response.request.href, relPath); - requestPromisesInner.push(requestSync(absPath)); - }); - - // add text in style tags - $style.each(function() { - that.styles.push($(this).text()); - }); - } else if (contentType.indexOf('css') > -1) { - that.styles.push(response.body); + results.forEach(function(result) { + if (util.isCSS(result)) { + that.styles.push(result); } else { - throw new Error('Content type is not HTML or CSS!'); + // push remote css data + var type = result.headers['content-type']; + if (type.indexOf('html') > -1) { + // parse result body + var $ = cheerio.load(result.body); + var $link = $('link[rel=stylesheet]'); + var $style = $('style'); + + // add css file count + result.cssFiles += $link.length; + result.styleElements += $style.length; + + // request link[href] + $link.each(function() { + var relPath = $(this).attr('href'); + var absPath = url.resolve(result.request.href, relPath); + requestPromisesInner.push(requestSync(absPath)); + }); + + // add text in style tags + $style.each(function() { + that.styles.push($(this).text()); + }); + } else if (type.indexOf('css') > -1) { + that.styles.push(result.body); + } else { + throw new Error('Content type is not HTML or CSS!'); + } } }); diff --git a/test/fixture/prepros/foo.less b/test/fixture/prepros/foo.less index 2db4e60..309f5af 100644 --- a/test/fixture/prepros/foo.less +++ b/test/fixture/prepros/foo.less @@ -1,5 +1,4 @@ -@import "../test.css"; -//@import "bar.less"; +@import "bar.less"; // Variables @nice-blue: #5B83AD; diff --git a/test/stats-test.js b/test/stats-test.js index 6fa6b76..31d59c5 100644 --- a/test/stats-test.js +++ b/test/stats-test.js @@ -167,7 +167,7 @@ describe('Analyze LESS files', function() { it('should return file size', function(done) { var lessStats = new StyleStats('test/fixture/prepros/foo.less'); lessStats.parse(function(lessResult) { - assert.equal(lessResult.size, 495); + assert.equal(lessResult.size, 499); done(); }); }); From cfaa6167485c0f20750d86a032b8f87dd699a5ec Mon Sep 17 00:00:00 2001 From: t32k Date: Thu, 27 Mar 2014 21:29:55 +0900 Subject: [PATCH 8/9] Support Stylus --- lib/parser.js | 20 ++++++++--------- package.json | 3 +-- test/fixture/prepros/bar.styl | 2 ++ test/fixture/prepros/foo.styl | 42 +++++++++++++++++++++++------------ test/stats-test.js | 40 ++++++++++++++++----------------- 5 files changed, 60 insertions(+), 47 deletions(-) create mode 100644 test/fixture/prepros/bar.styl diff --git a/lib/parser.js b/lib/parser.js index 50477c3..955617d 100644 --- a/lib/parser.js +++ b/lib/parser.js @@ -121,18 +121,16 @@ Parser.prototype.parse = function(callback) { this.stylusFiles.forEach(function(stylusFile) { var promise = new Promise(function(resolve, reject) { var string = fs.readFileSync(stylusFile, 'utf8'); - stylus(string).render(function(error, css) { - if (error) { - reject(error); - } - resolve(css); - }); - }); - promise.then(function onFulfilled(value) { - that.styles.push(value); - }, function onRejected(error) { - throw error; + stylus(string) + .set('filename', stylusFile) + .render(function(error, css) { + if (error) { + reject(error); + } + resolve(css); + }); }); + requestPromises.push(promise); }); } diff --git a/package.json b/package.json index 9e14f95..490d29c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "stylestats", - "version": "3.0.2", + "version": "3.1.0", "main": "lib/stylestats.js", "bin": { "stylestats": "bin/cli.js" @@ -51,7 +51,6 @@ "request": "~2.34.0", "json2csv": "~2.2.1", "css-parse": "~1.7.0", - "node-sass": "~0.8.4", "commander": "~2.1.0", "cli-table": "~0.3.0", "gzip-size": "~0.1.0", diff --git a/test/fixture/prepros/bar.styl b/test/fixture/prepros/bar.styl new file mode 100644 index 0000000..ca7408b --- /dev/null +++ b/test/fixture/prepros/bar.styl @@ -0,0 +1,2 @@ +.bar + font font-size Arial, sans-serif \ No newline at end of file diff --git a/test/fixture/prepros/foo.styl b/test/fixture/prepros/foo.styl index e96ace1..6c87946 100644 --- a/test/fixture/prepros/foo.styl +++ b/test/fixture/prepros/foo.styl @@ -1,14 +1,28 @@ -border-radius() - -webkit-border-radius: arguments - -moz-border-radius: arguments - border-radius: arguments - -body a - font: 12px/1.4 "Lucida Grande", Arial, sans-serif - background: black - color: #ccc - -form input - padding: 5px - border: 1px solid - border-radius: 5px \ No newline at end of file +@import 'bar' + +// Variables +font-size = 14px + +body + font font-size Arial, sans-serif + +// Mixins +border-radius(n) + -webkit-border-radius n + -moz-border-radius n + border-radius n + +form input[type=button] + border-radius(5px) + +// Functions +add(a, b) + a + b + +body + padding add(10px, 5) + +// Iteration +body + for num in 1 2 3 + foo num \ No newline at end of file diff --git a/test/stats-test.js b/test/stats-test.js index 31d59c5..0eee4c9 100644 --- a/test/stats-test.js +++ b/test/stats-test.js @@ -95,25 +95,25 @@ describe('Customize with option', function() { }); -//describe('Analyze remote css file', function() { -// it('should return file size', function(done) { -// var requestStats = new StyleStats('http://t32k.me/static/blog/skelton.css?query'); -// requestStats.parse(function(requestResult) { -// assert.equal(requestResult.size, 15419); -// done(); -// }); -// }); -//}); -// -//describe('Analyze HTML pages', function() { -// it('should return the number of stylesheets', function(done) { -// var htmlStats = new StyleStats('https://dl.dropboxusercontent.com/u/356242/test/stats/async.html'); -// htmlStats.parse(function(htmlResult) { -// assert.equal(htmlResult.size, 508); -// done(); -// }); -// }); -//}); +describe('Analyze remote css file', function() { + it('should return file size', function(done) { + var requestStats = new StyleStats('http://t32k.me/static/blog/skelton.css?query'); + requestStats.parse(function(requestResult) { + assert.equal(requestResult.size, 15419); + done(); + }); + }); +}); + +describe('Analyze HTML pages', function() { + it('should return the number of stylesheets', function(done) { + var htmlStats = new StyleStats('https://dl.dropboxusercontent.com/u/356242/test/stats/async.html'); + htmlStats.parse(function(htmlResult) { + assert.equal(htmlResult.size, 508); + done(); + }); + }); +}); describe('Analyze files of specified directory', function() { it('should return file size', function(done) { @@ -177,7 +177,7 @@ describe('Analyze Stylus files', function() { it('should return file size', function(done) { var stylStats = new StyleStats('test/fixture/prepros/foo.styl'); stylStats.parse(function(stylResult) { - assert.equal(stylResult.size, 230); + assert.equal(stylResult.size, 259); done(); }); }); From 77757e3ae13fb50a844839f9e1be710d914b5dc1 Mon Sep 17 00:00:00 2001 From: t32k Date: Thu, 27 Mar 2014 22:07:03 +0900 Subject: [PATCH 9/9] Fix test --- README.md | 1 + package.json | 2 +- test/stats-test.js | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index de253ab..1c6f564 100644 --- a/README.md +++ b/README.md @@ -317,6 +317,7 @@ _(Coming soon)_ ## Release History ++ v3.1.0: Support compiled Less/Stylus files. + v3.0.0: __API is changed:__ CLI option. Support parse HTML page. + v2.3.0: Support HTML output CLI option. + v2.2.0: Add `dataUriSize`, `ratioOfDataUriSize` metics. diff --git a/package.json b/package.json index 490d29c..027bb68 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "property" ], "scripts": { - "test": "mocha --timeout 5000 --reporter=spec" + "test": "mocha --timeout 10s --reporter=spec" }, "engines": { "node": "0.10.x" diff --git a/test/stats-test.js b/test/stats-test.js index 0eee4c9..d59509e 100644 --- a/test/stats-test.js +++ b/test/stats-test.js @@ -107,9 +107,9 @@ describe('Analyze remote css file', function() { describe('Analyze HTML pages', function() { it('should return the number of stylesheets', function(done) { - var htmlStats = new StyleStats('https://dl.dropboxusercontent.com/u/356242/test/stats/async.html'); + var htmlStats = new StyleStats('http://t32k.me/'); htmlStats.parse(function(htmlResult) { - assert.equal(htmlResult.size, 508); + assert.equal(htmlResult.size, 15419); done(); }); });