From 41742c86b0de00c625a6d66d2f933b0b92da41c0 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Thu, 15 Nov 2012 08:47:12 -0800 Subject: [PATCH 01/67] refactor --- index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 0cbcda9..7a7cb06 100644 --- a/index.js +++ b/index.js @@ -167,12 +167,12 @@ Compiler.prototype.declaration = function(node){ /** * Increase, decrease or return current indentation. */ + Compiler.prototype.indent = function(level) { this.level = this.level || 1; - if (level !== undefined) { + if (null != level) { this.level += level; - return ''; } From fbb9ceaf3b78af2da56983209fb256237bb7bc38 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Thu, 15 Nov 2012 08:48:02 -0800 Subject: [PATCH 02/67] Release 1.0.4 --- History.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index c6f8cb5..27e175b 100644 --- a/History.md +++ b/History.md @@ -1,4 +1,9 @@ +1.0.4 / 2012-11-15 +================== + + * fix indentation + 1.0.3 / 2012-09-04 ================== diff --git a/package.json b/package.json index 8c7c23b..7168997 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "css-stringify", - "version": "1.0.3", + "version": "1.0.4", "description": "CSS compiler", "keywords": ["css", "stringify", "stylesheet"], "author": "TJ Holowaychuk ", From 52ae2a4dee9af1d325a36fcde21acd9523fed382 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Wed, 21 Nov 2012 17:43:00 -0800 Subject: [PATCH 03/67] fix .repo prop --- component.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/component.json b/component.json index 939e778..74449c1 100644 --- a/component.json +++ b/component.json @@ -1,6 +1,6 @@ { "name": "css-stringify", - "repo": "visionmedia/node-css-stringify", + "repo": "visionmedia/css-stringify", "version": "1.0.2", "description": "CSS compiler", "keywords": ["css", "stringify", "stylesheet"], From f00967a0ff81dd79f1f3998976279daad1411bf9 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Wed, 21 Nov 2012 17:43:18 -0800 Subject: [PATCH 04/67] fix component.json .version --- component.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/component.json b/component.json index 74449c1..dcd417e 100644 --- a/component.json +++ b/component.json @@ -1,7 +1,7 @@ { "name": "css-stringify", "repo": "visionmedia/css-stringify", - "version": "1.0.2", + "version": "1.0.4", "description": "CSS compiler", "keywords": ["css", "stringify", "stylesheet"], "scripts": ["index.js"] From 19719595693bc0788eb51957750694b27cf13bc1 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Mon, 7 Jan 2013 08:57:06 -0800 Subject: [PATCH 05/67] fix link. Closes #8 --- Readme.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Readme.md b/Readme.md index 745ae92..a36e780 100644 --- a/Readme.md +++ b/Readme.md @@ -1,13 +1,13 @@ # css-stringify - CSS compiler using the AST provided by [css-parse](https://github.com/visionmedia/node-css-parse). + CSS compiler using the AST provided by [css-parse](https://github.com/visionmedia/css-parse). ## Performance Formats 15,000 lines of CSS (2mb) in 23ms on my macbook air. -## License +## License (The MIT License) @@ -30,4 +30,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. From 2a3bad5bc740b0c61f47cfcb6cae45118b9159b8 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Fri, 15 Mar 2013 08:31:37 -0700 Subject: [PATCH 06/67] fix indentation of multiple selectors in @media. Closes #11 --- examples/media.css | 5 +++-- index.js | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/media.css b/examples/media.css index a9e6128..927ab78 100644 --- a/examples/media.css +++ b/examples/media.css @@ -16,8 +16,9 @@ color: #000; } - body { + body, + #content { padding: 1in; border: 0.5pt solid #666; } -} \ No newline at end of file +} diff --git a/index.js b/index.js index 7a7cb06..f528e41 100644 --- a/index.js +++ b/index.js @@ -137,6 +137,8 @@ Compiler.prototype.keyframe = function(node){ */ Compiler.prototype.rule = function(node){ + var indent = this.indent(); + if (this.compress) { return node.selectors.join(',') + '{' @@ -144,7 +146,7 @@ Compiler.prototype.rule = function(node){ + '}'; } - return this.indent() + node.selectors.join(',\n') + return node.selectors.map(function(s){ return indent + s }).join(',\n') + ' {\n' + this.indent(1) + node.declarations.map(this.declaration, this).join(';\n') From a1f0b0d28eae10d8049f22307787495d70259748 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Fri, 15 Mar 2013 08:32:02 -0700 Subject: [PATCH 07/67] Release 1.0.5 --- History.md | 5 +++++ component.json | 4 ++-- package.json | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/History.md b/History.md index 27e175b..a6ff960 100644 --- a/History.md +++ b/History.md @@ -1,4 +1,9 @@ +1.0.5 / 2013-03-15 +================== + + * fix indentation of multiple selectors in @media. Closes #11 + 1.0.4 / 2012-11-15 ================== diff --git a/component.json b/component.json index dcd417e..259baef 100644 --- a/component.json +++ b/component.json @@ -1,8 +1,8 @@ { "name": "css-stringify", "repo": "visionmedia/css-stringify", - "version": "1.0.4", + "version": "1.0.5", "description": "CSS compiler", "keywords": ["css", "stringify", "stylesheet"], "scripts": ["index.js"] -} \ No newline at end of file +} diff --git a/package.json b/package.json index 7168997..e8c38e6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "css-stringify", - "version": "1.0.4", + "version": "1.0.5", "description": "CSS compiler", "keywords": ["css", "stringify", "stylesheet"], "author": "TJ Holowaychuk ", @@ -10,4 +10,4 @@ "css-parse": "1.0.3" }, "main": "index" -} \ No newline at end of file +} From abf45d3a3e5533000d562102cd210e703dd19d61 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Mon, 18 Mar 2013 09:13:13 -0700 Subject: [PATCH 08/67] add comment support --- index.js | 9 +++++++++ package.json | 2 +- test/cases/comments.css | 5 +++++ test/css-stringify.js | 4 ++-- 4 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 test/cases/comments.css diff --git a/index.js b/index.js index f528e41..9630d8e 100644 --- a/index.js +++ b/index.js @@ -36,6 +36,7 @@ Compiler.prototype.compile = function(node){ */ Compiler.prototype.visit = function(node){ + if (node.comment) return this.comment(node); if (node.charset) return this.charset(node); if (node.keyframes) return this.keyframes(node); if (node.media) return this.media(node); @@ -43,6 +44,14 @@ Compiler.prototype.visit = function(node){ return this.rule(node); }; +/** + * Visit comment node. + */ + +Compiler.prototype.comment = function(node){ + return '/*' + node.comment + '*/'; +}; + /** * Visit import node. */ diff --git a/package.json b/package.json index e8c38e6..81c95dd 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "devDependencies": { "mocha": "*", "should": "*", - "css-parse": "1.0.3" + "css-parse": "1.1.0" }, "main": "index" } diff --git a/test/cases/comments.css b/test/cases/comments.css new file mode 100644 index 0000000..866abfd --- /dev/null +++ b/test/cases/comments.css @@ -0,0 +1,5 @@ +/* comment */ + +body { + color: #eee +} diff --git a/test/css-stringify.js b/test/css-stringify.js index 30e6a0b..ad2ba19 100644 --- a/test/css-stringify.js +++ b/test/css-stringify.js @@ -18,7 +18,7 @@ describe('stringify(obj)', function(){ var css = read(path.join('test', 'cases', file + '.css'), 'utf8'); if (compress) file = file.replace('.compress', ''); var ret = stringify(parse(css), { compress: compress }); - ret.should.equal(css); + ret.trim().should.equal(css.trim()); }); }); -}); \ No newline at end of file +}); From 6774c413c71081514ea68b4f968162f4e5046215 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Tue, 19 Mar 2013 08:15:52 -0700 Subject: [PATCH 09/67] add omission of comments when compressed --- examples/media.css | 3 +++ index.js | 1 + 2 files changed, 4 insertions(+) diff --git a/examples/media.css b/examples/media.css index 927ab78..d50e65b 100644 --- a/examples/media.css +++ b/examples/media.css @@ -1,3 +1,6 @@ + +/* some comment */ + @media screen, projection { html { background: #fffef0; diff --git a/index.js b/index.js index 9630d8e..f2e9ec5 100644 --- a/index.js +++ b/index.js @@ -49,6 +49,7 @@ Compiler.prototype.visit = function(node){ */ Compiler.prototype.comment = function(node){ + if (this.compress) return ''; return '/*' + node.comment + '*/'; }; From 2e239867e78f247bbf9a26a83525570d0519f052 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Tue, 19 Mar 2013 08:16:37 -0700 Subject: [PATCH 10/67] Release 1.1.0 --- History.md | 6 ++++++ component.json | 2 +- package.json | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index a6ff960..4decbc3 100644 --- a/History.md +++ b/History.md @@ -1,4 +1,10 @@ +1.1.0 / 2013-03-19 +================== + + * add omission of comments when compressed + * add comment support + 1.0.5 / 2013-03-15 ================== diff --git a/component.json b/component.json index 259baef..ddb1013 100644 --- a/component.json +++ b/component.json @@ -1,7 +1,7 @@ { "name": "css-stringify", "repo": "visionmedia/css-stringify", - "version": "1.0.5", + "version": "1.1.0", "description": "CSS compiler", "keywords": ["css", "stringify", "stylesheet"], "scripts": ["index.js"] diff --git a/package.json b/package.json index 81c95dd..15edc6d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "css-stringify", - "version": "1.0.5", + "version": "1.1.0", "description": "CSS compiler", "keywords": ["css", "stringify", "stylesheet"], "author": "TJ Holowaychuk ", From f27442462ccd6fb7727793bf909dc3b444eda9a6 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Tue, 21 May 2013 09:51:32 -0700 Subject: [PATCH 11/67] update deps --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 15edc6d..77c0b8b 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "devDependencies": { "mocha": "*", "should": "*", - "css-parse": "1.1.0" + "css-parse": "1.3.0" }, "main": "index" } From e02df7f0a09728e69eda77cdc2812ab0cad1f437 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Tue, 21 May 2013 10:01:24 -0700 Subject: [PATCH 12/67] add @document compilation. Closes #82 --- examples/document.css | 17 +++++++++++++++++ examples/document.js | 12 ++++++++++++ index.js | 23 +++++++++++++++++++++++ test/cases/document.css | 17 +++++++++++++++++ 4 files changed, 69 insertions(+) create mode 100644 examples/document.css create mode 100644 examples/document.js create mode 100644 test/cases/document.css diff --git a/examples/document.css b/examples/document.css new file mode 100644 index 0000000..7ddf3d6 --- /dev/null +++ b/examples/document.css @@ -0,0 +1,17 @@ +@-moz-document url-prefix() { + .icon-spin { + height: .9em + } + + .btn .icon-spin { + height: auto + } + + .icon-spin.icon-large { + height: 1.25em + } + + .btn .icon-spin.icon-large { + height: .75em + } +} diff --git a/examples/document.js b/examples/document.js new file mode 100644 index 0000000..3fc8793 --- /dev/null +++ b/examples/document.js @@ -0,0 +1,12 @@ + +/** + * Module dependencies. + */ + +var parse = require('css-parse') + , stringify = require('..') + , fs = require('fs') + , read = fs.readFileSync + , css = read('examples/document.css', 'utf8'); + +console.log(stringify(parse(css), { compress: false })); diff --git a/index.js b/index.js index f2e9ec5..36f4c34 100644 --- a/index.js +++ b/index.js @@ -36,6 +36,7 @@ Compiler.prototype.compile = function(node){ */ Compiler.prototype.visit = function(node){ + if (node.document) return this.document(node); if (node.comment) return this.comment(node); if (node.charset) return this.charset(node); if (node.keyframes) return this.keyframes(node); @@ -83,6 +84,28 @@ Compiler.prototype.media = function(node){ + '\n}'; }; +/** + * Visit document node. + */ + +Compiler.prototype.document = function(node){ + var doc = '@' + (node.vendor || '') + 'document ' + node.document; + + if (this.compress) { + return doc + + '{' + + node.rules.map(this.visit, this).join('') + + '}'; + } + + return doc + ' ' + + ' {\n' + + this.indent(1) + + node.rules.map(this.visit, this).join('\n\n') + + this.indent(-1) + + '\n}'; +}; + /** * Visit charset node. */ diff --git a/test/cases/document.css b/test/cases/document.css new file mode 100644 index 0000000..1445e37 --- /dev/null +++ b/test/cases/document.css @@ -0,0 +1,17 @@ +@-moz-document url-prefix() { + .icon-spin { + height: .9em + } + + .btn .icon-spin { + height: auto + } + + .icon-spin.icon-large { + height: 1.25em + } + + .btn .icon-spin.icon-large { + height: .75em + } +} From cf146b442e478ddc456f8468c718bf14aa6caf15 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Tue, 21 May 2013 10:03:06 -0700 Subject: [PATCH 13/67] Release 1.2.0 --- History.md | 5 +++++ component.json | 2 +- package.json | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index 4decbc3..b818df7 100644 --- a/History.md +++ b/History.md @@ -1,4 +1,9 @@ +1.2.0 / 2013-05-21 +================== + + * add @document compilation. Closes #82 + 1.1.0 / 2013-03-19 ================== diff --git a/component.json b/component.json index ddb1013..4f59b33 100644 --- a/component.json +++ b/component.json @@ -1,7 +1,7 @@ { "name": "css-stringify", "repo": "visionmedia/css-stringify", - "version": "1.1.0", + "version": "1.2.0", "description": "CSS compiler", "keywords": ["css", "stringify", "stylesheet"], "scripts": ["index.js"] diff --git a/package.json b/package.json index 77c0b8b..03f2067 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "css-stringify", - "version": "1.1.0", + "version": "1.2.0", "description": "CSS compiler", "keywords": ["css", "stringify", "stylesheet"], "author": "TJ Holowaychuk ", From 3c00f86ed23f15fa646e08e1df096f8d22bc7217 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Tue, 21 May 2013 10:11:58 -0700 Subject: [PATCH 14/67] add @page compilation support --- examples/page.css | 8 ++++++++ examples/page.js | 12 ++++++++++++ index.js | 14 ++++++++++++++ test/cases/page.css | 0 4 files changed, 34 insertions(+) create mode 100644 examples/page.css create mode 100644 examples/page.js create mode 100644 test/cases/page.css diff --git a/examples/page.css b/examples/page.css new file mode 100644 index 0000000..a413d84 --- /dev/null +++ b/examples/page.css @@ -0,0 +1,8 @@ +@page { + size: auto; + margin: 10% +} + +@page foo, bar { + bar: baz +} diff --git a/examples/page.js b/examples/page.js new file mode 100644 index 0000000..1d402aa --- /dev/null +++ b/examples/page.js @@ -0,0 +1,12 @@ + +/** + * Module dependencies. + */ + +var parse = require('css-parse') + , stringify = require('..') + , fs = require('fs') + , read = fs.readFileSync + , css = read('examples/page.css', 'utf8'); + +console.log(stringify(parse(css), { compress: false })); diff --git a/index.js b/index.js index 36f4c34..0643002 100644 --- a/index.js +++ b/index.js @@ -36,6 +36,7 @@ Compiler.prototype.compile = function(node){ */ Compiler.prototype.visit = function(node){ + if ('page' == node.type) return this.page(node); if (node.document) return this.document(node); if (node.comment) return this.comment(node); if (node.charset) return this.charset(node); @@ -165,6 +166,19 @@ Compiler.prototype.keyframe = function(node){ + '\n' + this.indent() + '}\n'; }; +/** + * Visit page node. + */ + +Compiler.prototype.page = function(node){ + return '@page ' + node.selectors.join(', ') + + ' {\n' + + this.indent(1) + + node.declarations.map(this.declaration, this).join(';\n') + + this.indent(-1) + + '\n}'; +}; + /** * Visit rule node. */ diff --git a/test/cases/page.css b/test/cases/page.css new file mode 100644 index 0000000..e69de29 From b9865cc85941fc9031fb91162eb82fe166047b89 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Wed, 22 May 2013 19:57:34 -0700 Subject: [PATCH 15/67] refactor visitor with .type --- index.js | 9 +-------- package.json | 2 +- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/index.js b/index.js index 0643002..41790c8 100644 --- a/index.js +++ b/index.js @@ -36,14 +36,7 @@ Compiler.prototype.compile = function(node){ */ Compiler.prototype.visit = function(node){ - if ('page' == node.type) return this.page(node); - if (node.document) return this.document(node); - if (node.comment) return this.comment(node); - if (node.charset) return this.charset(node); - if (node.keyframes) return this.keyframes(node); - if (node.media) return this.media(node); - if (node.import) return this.import(node); - return this.rule(node); + return this[node.type](node); }; /** diff --git a/package.json b/package.json index 03f2067..3bc7342 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "devDependencies": { "mocha": "*", "should": "*", - "css-parse": "1.3.0" + "css-parse": "1.4.0" }, "main": "index" } From 4df1e0e22265d7c1e51048c6caaf06830a6e2e5b Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Wed, 22 May 2013 20:02:54 -0700 Subject: [PATCH 16/67] add ignoring of empty rulesets. Closes #7 --- examples/empty.css | 4 ++++ examples/empty.js | 12 ++++++++++++ index.js | 7 +++++-- 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 examples/empty.css create mode 100644 examples/empty.js diff --git a/examples/empty.css b/examples/empty.css new file mode 100644 index 0000000..c14f1e9 --- /dev/null +++ b/examples/empty.css @@ -0,0 +1,4 @@ + +body { + +} diff --git a/examples/empty.js b/examples/empty.js new file mode 100644 index 0000000..3c32c33 --- /dev/null +++ b/examples/empty.js @@ -0,0 +1,12 @@ + +/** + * Module dependencies. + */ + +var parse = require('css-parse') + , stringify = require('..') + , fs = require('fs') + , read = fs.readFileSync + , css = read('examples/empty.css', 'utf8'); + +console.log(stringify(parse(css), { compress: true })); diff --git a/index.js b/index.js index 41790c8..94f3353 100644 --- a/index.js +++ b/index.js @@ -178,18 +178,21 @@ Compiler.prototype.page = function(node){ Compiler.prototype.rule = function(node){ var indent = this.indent(); + var decls = node.declarations; if (this.compress) { + if (!decls.length) return ''; + return node.selectors.join(',') + '{' - + node.declarations.map(this.declaration, this).join(';') + + decls.map(this.declaration, this).join(';') + '}'; } return node.selectors.map(function(s){ return indent + s }).join(',\n') + ' {\n' + this.indent(1) - + node.declarations.map(this.declaration, this).join(';\n') + + decls.map(this.declaration, this).join(';\n') + this.indent(-1) + '\n' + this.indent() + '}'; }; From 39dca32804044ff7f642524c7cd3184fc913adb5 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Wed, 22 May 2013 20:03:07 -0700 Subject: [PATCH 17/67] refactor --- index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 94f3353..fb568d1 100644 --- a/index.js +++ b/index.js @@ -27,7 +27,8 @@ function Compiler(options) { */ Compiler.prototype.compile = function(node){ - return node.stylesheet.rules.map(this.visit, this) + return node.stylesheet + .rules.map(this.visit, this) .join(this.compress ? '' : '\n\n'); }; From 39d46c72c45418f40546e6f19deecfccbad9a81e Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Tue, 28 May 2013 16:18:13 -0700 Subject: [PATCH 18/67] add failing test case --- test/cases/comments.css | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/cases/comments.css b/test/cases/comments.css index 866abfd..87e95a3 100644 --- a/test/cases/comments.css +++ b/test/cases/comments.css @@ -1,5 +1,8 @@ /* comment */ body { - color: #eee + /* foo */ + /* bar */ + color: #eee; + /* baz */ } From 1e19ec2416fe156d5dfa7acfe09f6ab3a7ab4d19 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Tue, 28 May 2013 16:18:49 -0700 Subject: [PATCH 19/67] add comments example --- examples/comments.css | 8 ++++++++ examples/comments.js | 12 ++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 examples/comments.css create mode 100644 examples/comments.js diff --git a/examples/comments.css b/examples/comments.css new file mode 100644 index 0000000..87e95a3 --- /dev/null +++ b/examples/comments.css @@ -0,0 +1,8 @@ +/* comment */ + +body { + /* foo */ + /* bar */ + color: #eee; + /* baz */ +} diff --git a/examples/comments.js b/examples/comments.js new file mode 100644 index 0000000..c255105 --- /dev/null +++ b/examples/comments.js @@ -0,0 +1,12 @@ + +/** + * Module dependencies. + */ + +var parse = require('css-parse') + , stringify = require('..') + , fs = require('fs') + , read = fs.readFileSync + , css = read('examples/comments.css', 'utf8'); + +console.log(stringify(parse(css))); From d644ef2c773ec507fa8d0ba382e414ae7e01f51b Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Tue, 28 May 2013 16:20:47 -0700 Subject: [PATCH 20/67] fix comment output. Closes #16 --- index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index fb568d1..3858a17 100644 --- a/index.js +++ b/index.js @@ -186,14 +186,14 @@ Compiler.prototype.rule = function(node){ return node.selectors.join(',') + '{' - + decls.map(this.declaration, this).join(';') + + decls.map(this.visit, this).join(';') + '}'; } return node.selectors.map(function(s){ return indent + s }).join(',\n') + ' {\n' + this.indent(1) - + decls.map(this.declaration, this).join(';\n') + + decls.map(this.visit, this).join(';\n') + this.indent(-1) + '\n' + this.indent() + '}'; }; From bb2d6a38ee763e3e91513d22a89a5e960ce4bc75 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Tue, 28 May 2013 16:21:47 -0700 Subject: [PATCH 21/67] fix comment indentation --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 3858a17..e2a1e5e 100644 --- a/index.js +++ b/index.js @@ -46,7 +46,7 @@ Compiler.prototype.visit = function(node){ Compiler.prototype.comment = function(node){ if (this.compress) return ''; - return '/*' + node.comment + '*/'; + return this.indent() + '/*' + node.comment + '*/'; }; /** From ee68d4b476813896309886ba579e32e090ca6b02 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Tue, 28 May 2013 16:24:34 -0700 Subject: [PATCH 22/67] fix trailing ; with comments within rules --- index.js | 16 +++++++++------- test/cases/document.css | 8 ++++---- test/cases/keyframes.css | 6 +++--- test/cases/media.css | 10 +++++----- test/cases/rules.css | 6 +++--- test/cases/selectors.css | 4 ++-- 6 files changed, 26 insertions(+), 24 deletions(-) diff --git a/index.js b/index.js index e2a1e5e..77f6c3f 100644 --- a/index.js +++ b/index.js @@ -144,10 +144,12 @@ Compiler.prototype.keyframes = function(node){ */ Compiler.prototype.keyframe = function(node){ + var decls = node.declarations; + if (this.compress) { return node.values.join(',') + '{' - + node.declarations.map(this.declaration, this).join(';') + + decls.map(this.visit, this).join('') + '}'; } @@ -155,7 +157,7 @@ Compiler.prototype.keyframe = function(node){ + node.values.join(', ') + ' {\n' + this.indent(1) - + node.declarations.map(this.declaration, this).join(';\n') + + decls.map(this.visit, this).join('\n') + this.indent(-1) + '\n' + this.indent() + '}\n'; }; @@ -168,7 +170,7 @@ Compiler.prototype.page = function(node){ return '@page ' + node.selectors.join(', ') + ' {\n' + this.indent(1) - + node.declarations.map(this.declaration, this).join(';\n') + + node.declarations.map(this.visit, this).join('\n') + this.indent(-1) + '\n}'; }; @@ -186,14 +188,14 @@ Compiler.prototype.rule = function(node){ return node.selectors.join(',') + '{' - + decls.map(this.visit, this).join(';') + + decls.map(this.visit, this).join('') + '}'; } return node.selectors.map(function(s){ return indent + s }).join(',\n') + ' {\n' + this.indent(1) - + decls.map(this.visit, this).join(';\n') + + decls.map(this.visit, this).join('\n') + this.indent(-1) + '\n' + this.indent() + '}'; }; @@ -204,10 +206,10 @@ Compiler.prototype.rule = function(node){ Compiler.prototype.declaration = function(node){ if (this.compress) { - return node.property + ':' + node.value; + return node.property + ':' + node.value + ';'; } - return this.indent() + node.property + ': ' + node.value; + return this.indent() + node.property + ': ' + node.value + ';'; }; /** diff --git a/test/cases/document.css b/test/cases/document.css index 1445e37..e6302e7 100644 --- a/test/cases/document.css +++ b/test/cases/document.css @@ -1,17 +1,17 @@ @-moz-document url-prefix() { .icon-spin { - height: .9em + height: .9em; } .btn .icon-spin { - height: auto + height: auto; } .icon-spin.icon-large { - height: 1.25em + height: 1.25em; } .btn .icon-spin.icon-large { - height: .75em + height: .75em; } } diff --git a/test/cases/keyframes.css b/test/cases/keyframes.css index a50d14a..e8ed694 100644 --- a/test/cases/keyframes.css +++ b/test/cases/keyframes.css @@ -1,10 +1,10 @@ @keyframes fade { from { opacity: 0; - opacity: 1 + opacity: 1; } to { - opacity: 1 + opacity: 1; } -} \ No newline at end of file +} diff --git a/test/cases/media.css b/test/cases/media.css index 69ef305..c234e7d 100644 --- a/test/cases/media.css +++ b/test/cases/media.css @@ -1,23 +1,23 @@ @media screen, projection { html { background: #fffef0; - color: #300 + color: #300; } body { max-width: 35em; - margin: 0 auto + margin: 0 auto; } } @media print { html { background: #fff; - color: #000 + color: #000; } body { padding: 1in; - border: 0.5pt solid #666 + border: 0.5pt solid #666; } -} \ No newline at end of file +} diff --git a/test/cases/rules.css b/test/cases/rules.css index 96f2504..5b98d01 100644 --- a/test/cases/rules.css +++ b/test/cases/rules.css @@ -1,9 +1,9 @@ tobi { name: 'tobi'; - age: 2 + age: 2; } loki { name: 'loki'; - age: 1 -} \ No newline at end of file + age: 1; +} diff --git a/test/cases/selectors.css b/test/cases/selectors.css index 5920f9e..9f214f1 100644 --- a/test/cases/selectors.css +++ b/test/cases/selectors.css @@ -1,5 +1,5 @@ foo, bar, baz { - color: 'black' -} \ No newline at end of file + color: 'black'; +} From 39e89a4161c4ae56794789e5cba6fe8618e36670 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Tue, 28 May 2013 16:30:41 -0700 Subject: [PATCH 23/67] add @page tests --- Makefile | 5 +++-- index.js | 8 ++++++-- test/cases/page.css | 15 +++++++++++++++ 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 4e9c8d3..d78a055 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ test: @./node_modules/.bin/mocha \ --require should \ - --reporter spec + --reporter spec \ + --bail -.PHONY: test \ No newline at end of file +.PHONY: test diff --git a/index.js b/index.js index 77f6c3f..2319dc9 100644 --- a/index.js +++ b/index.js @@ -167,8 +167,12 @@ Compiler.prototype.keyframe = function(node){ */ Compiler.prototype.page = function(node){ - return '@page ' + node.selectors.join(', ') - + ' {\n' + var sel = node.selectors.length + ? node.selectors.join(', ') + ' ' + : ''; + + return '@page ' + sel + + '{\n' + this.indent(1) + node.declarations.map(this.visit, this).join('\n') + this.indent(-1) diff --git a/test/cases/page.css b/test/cases/page.css index e69de29..34f2a09 100644 --- a/test/cases/page.css +++ b/test/cases/page.css @@ -0,0 +1,15 @@ +@page { + margin: 2.5cm; +} + +@page :left { + margin-left: 5cm; +} + +@page :right { + margin-right: 5cm; +} + +@page :first { + margin-top: 8cm; +} From 5e8b4c97dcc123a90ec652c3563c3a02529fa414 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Tue, 28 May 2013 16:45:22 -0700 Subject: [PATCH 24/67] add @supports support --- index.js | 14 ++++++++++++++ test/cases/supports.css | 10 ++++++++++ 2 files changed, 24 insertions(+) create mode 100644 test/cases/supports.css diff --git a/index.js b/index.js index 2319dc9..55fddb9 100644 --- a/index.js +++ b/index.js @@ -113,6 +113,20 @@ Compiler.prototype.charset = function(node){ return '@charset ' + node.charset + ';\n'; }; +/** + * Visit supports node. + */ + +Compiler.prototype.supports = function(node){ + return '@supports ' + + node.supports + + ' {\n' + + this.indent(1) + + node.rules.map(this.visit, this).join('\n\n') + + this.indent(-1) + + '\n}'; +}; + /** * Visit keyframes node. */ diff --git a/test/cases/supports.css b/test/cases/supports.css new file mode 100644 index 0000000..05ca478 --- /dev/null +++ b/test/cases/supports.css @@ -0,0 +1,10 @@ + +@supports (display: flex) { + div { + display: flex; + } + + div { + something: else; + } +} From d6abda10ca72e4bfcae586604523b4f1e03f7512 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Tue, 28 May 2013 16:48:25 -0700 Subject: [PATCH 25/67] .visit everything --- index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 55fddb9..f462425 100644 --- a/index.js +++ b/index.js @@ -138,7 +138,7 @@ Compiler.prototype.keyframes = function(node){ + 'keyframes ' + node.name + '{' - + node.keyframes.map(this.keyframe, this).join('') + + node.keyframes.map(this.visit, this).join('') + '}'; } @@ -148,7 +148,7 @@ Compiler.prototype.keyframes = function(node){ + node.name + ' {\n' + this.indent(1) - + node.keyframes.map(this.keyframe, this).join('\n') + + node.keyframes.map(this.visit, this).join('\n') + this.indent(-1) + '}'; }; From a9a40869daa10fde0807d63fc70f36b423933749 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Tue, 28 May 2013 16:52:06 -0700 Subject: [PATCH 26/67] add separate compilers --- component.json | 6 +- index.js | 241 ++---------------------------------------------- lib/compress.js | 239 +++++++++++++++++++++++++++++++++++++++++++++++ lib/identity.js | 239 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 493 insertions(+), 232 deletions(-) create mode 100644 lib/compress.js create mode 100644 lib/identity.js diff --git a/component.json b/component.json index 4f59b33..8c79e79 100644 --- a/component.json +++ b/component.json @@ -4,5 +4,9 @@ "version": "1.2.0", "description": "CSS compiler", "keywords": ["css", "stringify", "stylesheet"], - "scripts": ["index.js"] + "scripts": [ + "index.js", + "lib/compress.js", + "lib/identity.js" + ] } diff --git a/index.js b/index.js index f462425..6598da3 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,11 @@ +/** + * Module dependencies. + */ + +var Compressed = require('./lib/compress'); +var Identity = require('./lib/identity'); + /** * Stringfy the given AST `node`. * @@ -9,238 +16,10 @@ */ module.exports = function(node, options){ - return new Compiler(options).compile(node); -}; - -/** - * Initialize a new `Compiler`. - */ - -function Compiler(options) { - options = options || {}; - this.compress = options.compress; - this.indentation = options.indent; -} - -/** - * Compile `node`. - */ - -Compiler.prototype.compile = function(node){ - return node.stylesheet - .rules.map(this.visit, this) - .join(this.compress ? '' : '\n\n'); -}; - -/** - * Visit `node`. - */ - -Compiler.prototype.visit = function(node){ - return this[node.type](node); -}; - -/** - * Visit comment node. - */ - -Compiler.prototype.comment = function(node){ - if (this.compress) return ''; - return this.indent() + '/*' + node.comment + '*/'; -}; - -/** - * Visit import node. - */ - -Compiler.prototype.import = function(node){ - return '@import ' + node.import + ';'; -}; - -/** - * Visit media node. - */ - -Compiler.prototype.media = function(node){ - if (this.compress) { - return '@media ' - + node.media - + '{' - + node.rules.map(this.visit, this).join('') - + '}'; - } - - return '@media ' - + node.media - + ' {\n' - + this.indent(1) - + node.rules.map(this.visit, this).join('\n\n') - + this.indent(-1) - + '\n}'; -}; - -/** - * Visit document node. - */ - -Compiler.prototype.document = function(node){ - var doc = '@' + (node.vendor || '') + 'document ' + node.document; - - if (this.compress) { - return doc - + '{' - + node.rules.map(this.visit, this).join('') - + '}'; - } - - return doc + ' ' - + ' {\n' - + this.indent(1) - + node.rules.map(this.visit, this).join('\n\n') - + this.indent(-1) - + '\n}'; -}; - -/** - * Visit charset node. - */ - -Compiler.prototype.charset = function(node){ - if (this.compress) { - return '@charset ' + node.charset + ';'; + if (options.compress) { + return new Compressed(options).compile(node); } - return '@charset ' + node.charset + ';\n'; + return new Identity(options).compile(node); }; -/** - * Visit supports node. - */ - -Compiler.prototype.supports = function(node){ - return '@supports ' - + node.supports - + ' {\n' - + this.indent(1) - + node.rules.map(this.visit, this).join('\n\n') - + this.indent(-1) - + '\n}'; -}; - -/** - * Visit keyframes node. - */ - -Compiler.prototype.keyframes = function(node){ - if (this.compress) { - return '@' - + (node.vendor || '') - + 'keyframes ' - + node.name - + '{' - + node.keyframes.map(this.visit, this).join('') - + '}'; - } - - return '@' - + (node.vendor || '') - + 'keyframes ' - + node.name - + ' {\n' - + this.indent(1) - + node.keyframes.map(this.visit, this).join('\n') - + this.indent(-1) - + '}'; -}; - -/** - * Visit keyframe node. - */ - -Compiler.prototype.keyframe = function(node){ - var decls = node.declarations; - - if (this.compress) { - return node.values.join(',') - + '{' - + decls.map(this.visit, this).join('') - + '}'; - } - - return this.indent() - + node.values.join(', ') - + ' {\n' - + this.indent(1) - + decls.map(this.visit, this).join('\n') - + this.indent(-1) - + '\n' + this.indent() + '}\n'; -}; - -/** - * Visit page node. - */ - -Compiler.prototype.page = function(node){ - var sel = node.selectors.length - ? node.selectors.join(', ') + ' ' - : ''; - - return '@page ' + sel - + '{\n' - + this.indent(1) - + node.declarations.map(this.visit, this).join('\n') - + this.indent(-1) - + '\n}'; -}; - -/** - * Visit rule node. - */ - -Compiler.prototype.rule = function(node){ - var indent = this.indent(); - var decls = node.declarations; - - if (this.compress) { - if (!decls.length) return ''; - - return node.selectors.join(',') - + '{' - + decls.map(this.visit, this).join('') - + '}'; - } - - return node.selectors.map(function(s){ return indent + s }).join(',\n') - + ' {\n' - + this.indent(1) - + decls.map(this.visit, this).join('\n') - + this.indent(-1) - + '\n' + this.indent() + '}'; -}; - -/** - * Visit declaration node. - */ - -Compiler.prototype.declaration = function(node){ - if (this.compress) { - return node.property + ':' + node.value + ';'; - } - - return this.indent() + node.property + ': ' + node.value + ';'; -}; - -/** - * Increase, decrease or return current indentation. - */ - -Compiler.prototype.indent = function(level) { - this.level = this.level || 1; - - if (null != level) { - this.level += level; - return ''; - } - - return Array(this.level).join(this.indentation || ' '); -}; diff --git a/lib/compress.js b/lib/compress.js new file mode 100644 index 0000000..0cfdfaf --- /dev/null +++ b/lib/compress.js @@ -0,0 +1,239 @@ + +/** + * Expose compiler. + */ + +module.exports = Compiler; + +/** + * Initialize a new `Compiler`. + */ + +function Compiler(options) { + options = options || {}; + this.compress = options.compress; + this.indentation = options.indent; +} + +/** + * Compile `node`. + */ + +Compiler.prototype.compile = function(node){ + return node.stylesheet + .rules.map(this.visit, this) + .join(this.compress ? '' : '\n\n'); +}; + +/** + * Visit `node`. + */ + +Compiler.prototype.visit = function(node){ + return this[node.type](node); +}; + +/** + * Visit comment node. + */ + +Compiler.prototype.comment = function(node){ + if (this.compress) return ''; + return this.indent() + '/*' + node.comment + '*/'; +}; + +/** + * Visit import node. + */ + +Compiler.prototype.import = function(node){ + return '@import ' + node.import + ';'; +}; + +/** + * Visit media node. + */ + +Compiler.prototype.media = function(node){ + if (this.compress) { + return '@media ' + + node.media + + '{' + + node.rules.map(this.visit, this).join('') + + '}'; + } + + return '@media ' + + node.media + + ' {\n' + + this.indent(1) + + node.rules.map(this.visit, this).join('\n\n') + + this.indent(-1) + + '\n}'; +}; + +/** + * Visit document node. + */ + +Compiler.prototype.document = function(node){ + var doc = '@' + (node.vendor || '') + 'document ' + node.document; + + if (this.compress) { + return doc + + '{' + + node.rules.map(this.visit, this).join('') + + '}'; + } + + return doc + ' ' + + ' {\n' + + this.indent(1) + + node.rules.map(this.visit, this).join('\n\n') + + this.indent(-1) + + '\n}'; +}; + +/** + * Visit charset node. + */ + +Compiler.prototype.charset = function(node){ + if (this.compress) { + return '@charset ' + node.charset + ';'; + } + + return '@charset ' + node.charset + ';\n'; +}; + +/** + * Visit supports node. + */ + +Compiler.prototype.supports = function(node){ + return '@supports ' + + node.supports + + ' {\n' + + this.indent(1) + + node.rules.map(this.visit, this).join('\n\n') + + this.indent(-1) + + '\n}'; +}; + +/** + * Visit keyframes node. + */ + +Compiler.prototype.keyframes = function(node){ + if (this.compress) { + return '@' + + (node.vendor || '') + + 'keyframes ' + + node.name + + '{' + + node.keyframes.map(this.visit, this).join('') + + '}'; + } + + return '@' + + (node.vendor || '') + + 'keyframes ' + + node.name + + ' {\n' + + this.indent(1) + + node.keyframes.map(this.visit, this).join('\n') + + this.indent(-1) + + '}'; +}; + +/** + * Visit keyframe node. + */ + +Compiler.prototype.keyframe = function(node){ + var decls = node.declarations; + + if (this.compress) { + return node.values.join(',') + + '{' + + decls.map(this.visit, this).join('') + + '}'; + } + + return this.indent() + + node.values.join(', ') + + ' {\n' + + this.indent(1) + + decls.map(this.visit, this).join('\n') + + this.indent(-1) + + '\n' + this.indent() + '}\n'; +}; + +/** + * Visit page node. + */ + +Compiler.prototype.page = function(node){ + var sel = node.selectors.length + ? node.selectors.join(', ') + ' ' + : ''; + + return '@page ' + sel + + '{\n' + + this.indent(1) + + node.declarations.map(this.visit, this).join('\n') + + this.indent(-1) + + '\n}'; +}; + +/** + * Visit rule node. + */ + +Compiler.prototype.rule = function(node){ + var indent = this.indent(); + var decls = node.declarations; + + if (this.compress) { + if (!decls.length) return ''; + + return node.selectors.join(',') + + '{' + + decls.map(this.visit, this).join('') + + '}'; + } + + return node.selectors.map(function(s){ return indent + s }).join(',\n') + + ' {\n' + + this.indent(1) + + decls.map(this.visit, this).join('\n') + + this.indent(-1) + + '\n' + this.indent() + '}'; +}; + +/** + * Visit declaration node. + */ + +Compiler.prototype.declaration = function(node){ + if (this.compress) { + return node.property + ':' + node.value + ';'; + } + + return this.indent() + node.property + ': ' + node.value + ';'; +}; + +/** + * Increase, decrease or return current indentation. + */ + +Compiler.prototype.indent = function(level) { + this.level = this.level || 1; + + if (null != level) { + this.level += level; + return ''; + } + + return Array(this.level).join(this.indentation || ' '); +}; diff --git a/lib/identity.js b/lib/identity.js new file mode 100644 index 0000000..0cfdfaf --- /dev/null +++ b/lib/identity.js @@ -0,0 +1,239 @@ + +/** + * Expose compiler. + */ + +module.exports = Compiler; + +/** + * Initialize a new `Compiler`. + */ + +function Compiler(options) { + options = options || {}; + this.compress = options.compress; + this.indentation = options.indent; +} + +/** + * Compile `node`. + */ + +Compiler.prototype.compile = function(node){ + return node.stylesheet + .rules.map(this.visit, this) + .join(this.compress ? '' : '\n\n'); +}; + +/** + * Visit `node`. + */ + +Compiler.prototype.visit = function(node){ + return this[node.type](node); +}; + +/** + * Visit comment node. + */ + +Compiler.prototype.comment = function(node){ + if (this.compress) return ''; + return this.indent() + '/*' + node.comment + '*/'; +}; + +/** + * Visit import node. + */ + +Compiler.prototype.import = function(node){ + return '@import ' + node.import + ';'; +}; + +/** + * Visit media node. + */ + +Compiler.prototype.media = function(node){ + if (this.compress) { + return '@media ' + + node.media + + '{' + + node.rules.map(this.visit, this).join('') + + '}'; + } + + return '@media ' + + node.media + + ' {\n' + + this.indent(1) + + node.rules.map(this.visit, this).join('\n\n') + + this.indent(-1) + + '\n}'; +}; + +/** + * Visit document node. + */ + +Compiler.prototype.document = function(node){ + var doc = '@' + (node.vendor || '') + 'document ' + node.document; + + if (this.compress) { + return doc + + '{' + + node.rules.map(this.visit, this).join('') + + '}'; + } + + return doc + ' ' + + ' {\n' + + this.indent(1) + + node.rules.map(this.visit, this).join('\n\n') + + this.indent(-1) + + '\n}'; +}; + +/** + * Visit charset node. + */ + +Compiler.prototype.charset = function(node){ + if (this.compress) { + return '@charset ' + node.charset + ';'; + } + + return '@charset ' + node.charset + ';\n'; +}; + +/** + * Visit supports node. + */ + +Compiler.prototype.supports = function(node){ + return '@supports ' + + node.supports + + ' {\n' + + this.indent(1) + + node.rules.map(this.visit, this).join('\n\n') + + this.indent(-1) + + '\n}'; +}; + +/** + * Visit keyframes node. + */ + +Compiler.prototype.keyframes = function(node){ + if (this.compress) { + return '@' + + (node.vendor || '') + + 'keyframes ' + + node.name + + '{' + + node.keyframes.map(this.visit, this).join('') + + '}'; + } + + return '@' + + (node.vendor || '') + + 'keyframes ' + + node.name + + ' {\n' + + this.indent(1) + + node.keyframes.map(this.visit, this).join('\n') + + this.indent(-1) + + '}'; +}; + +/** + * Visit keyframe node. + */ + +Compiler.prototype.keyframe = function(node){ + var decls = node.declarations; + + if (this.compress) { + return node.values.join(',') + + '{' + + decls.map(this.visit, this).join('') + + '}'; + } + + return this.indent() + + node.values.join(', ') + + ' {\n' + + this.indent(1) + + decls.map(this.visit, this).join('\n') + + this.indent(-1) + + '\n' + this.indent() + '}\n'; +}; + +/** + * Visit page node. + */ + +Compiler.prototype.page = function(node){ + var sel = node.selectors.length + ? node.selectors.join(', ') + ' ' + : ''; + + return '@page ' + sel + + '{\n' + + this.indent(1) + + node.declarations.map(this.visit, this).join('\n') + + this.indent(-1) + + '\n}'; +}; + +/** + * Visit rule node. + */ + +Compiler.prototype.rule = function(node){ + var indent = this.indent(); + var decls = node.declarations; + + if (this.compress) { + if (!decls.length) return ''; + + return node.selectors.join(',') + + '{' + + decls.map(this.visit, this).join('') + + '}'; + } + + return node.selectors.map(function(s){ return indent + s }).join(',\n') + + ' {\n' + + this.indent(1) + + decls.map(this.visit, this).join('\n') + + this.indent(-1) + + '\n' + this.indent() + '}'; +}; + +/** + * Visit declaration node. + */ + +Compiler.prototype.declaration = function(node){ + if (this.compress) { + return node.property + ':' + node.value + ';'; + } + + return this.indent() + node.property + ': ' + node.value + ';'; +}; + +/** + * Increase, decrease or return current indentation. + */ + +Compiler.prototype.indent = function(level) { + this.level = this.level || 1; + + if (null != level) { + this.level += level; + return ''; + } + + return Array(this.level).join(this.indentation || ' '); +}; From 6ffde6c81245ed40abec7c3b8c55ef358c3e8350 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Tue, 28 May 2013 16:53:19 -0700 Subject: [PATCH 27/67] remove .compressed usage from Identity compiler --- lib/identity.js | 53 +------------------------------------------------ 1 file changed, 1 insertion(+), 52 deletions(-) diff --git a/lib/identity.js b/lib/identity.js index 0cfdfaf..3a681e3 100644 --- a/lib/identity.js +++ b/lib/identity.js @@ -11,7 +11,6 @@ module.exports = Compiler; function Compiler(options) { options = options || {}; - this.compress = options.compress; this.indentation = options.indent; } @@ -22,7 +21,7 @@ function Compiler(options) { Compiler.prototype.compile = function(node){ return node.stylesheet .rules.map(this.visit, this) - .join(this.compress ? '' : '\n\n'); + .join('\n\n'); }; /** @@ -38,7 +37,6 @@ Compiler.prototype.visit = function(node){ */ Compiler.prototype.comment = function(node){ - if (this.compress) return ''; return this.indent() + '/*' + node.comment + '*/'; }; @@ -55,14 +53,6 @@ Compiler.prototype.import = function(node){ */ Compiler.prototype.media = function(node){ - if (this.compress) { - return '@media ' - + node.media - + '{' - + node.rules.map(this.visit, this).join('') - + '}'; - } - return '@media ' + node.media + ' {\n' @@ -79,13 +69,6 @@ Compiler.prototype.media = function(node){ Compiler.prototype.document = function(node){ var doc = '@' + (node.vendor || '') + 'document ' + node.document; - if (this.compress) { - return doc - + '{' - + node.rules.map(this.visit, this).join('') - + '}'; - } - return doc + ' ' + ' {\n' + this.indent(1) @@ -99,10 +82,6 @@ Compiler.prototype.document = function(node){ */ Compiler.prototype.charset = function(node){ - if (this.compress) { - return '@charset ' + node.charset + ';'; - } - return '@charset ' + node.charset + ';\n'; }; @@ -125,16 +104,6 @@ Compiler.prototype.supports = function(node){ */ Compiler.prototype.keyframes = function(node){ - if (this.compress) { - return '@' - + (node.vendor || '') - + 'keyframes ' - + node.name - + '{' - + node.keyframes.map(this.visit, this).join('') - + '}'; - } - return '@' + (node.vendor || '') + 'keyframes ' @@ -153,13 +122,6 @@ Compiler.prototype.keyframes = function(node){ Compiler.prototype.keyframe = function(node){ var decls = node.declarations; - if (this.compress) { - return node.values.join(',') - + '{' - + decls.map(this.visit, this).join('') - + '}'; - } - return this.indent() + node.values.join(', ') + ' {\n' @@ -194,15 +156,6 @@ Compiler.prototype.rule = function(node){ var indent = this.indent(); var decls = node.declarations; - if (this.compress) { - if (!decls.length) return ''; - - return node.selectors.join(',') - + '{' - + decls.map(this.visit, this).join('') - + '}'; - } - return node.selectors.map(function(s){ return indent + s }).join(',\n') + ' {\n' + this.indent(1) @@ -216,10 +169,6 @@ Compiler.prototype.rule = function(node){ */ Compiler.prototype.declaration = function(node){ - if (this.compress) { - return node.property + ':' + node.value + ';'; - } - return this.indent() + node.property + ': ' + node.value + ';'; }; From b0bf887655ebd6ad4dfb106c6a43546bac76dd67 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Tue, 28 May 2013 16:55:09 -0700 Subject: [PATCH 28/67] remove identity checks from compressed compiler --- lib/compress.js | 119 +++++++++--------------------------------------- 1 file changed, 21 insertions(+), 98 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index 0cfdfaf..db4fa54 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -11,8 +11,6 @@ module.exports = Compiler; function Compiler(options) { options = options || {}; - this.compress = options.compress; - this.indentation = options.indent; } /** @@ -22,7 +20,7 @@ function Compiler(options) { Compiler.prototype.compile = function(node){ return node.stylesheet .rules.map(this.visit, this) - .join(this.compress ? '' : '\n\n'); + .join(''); }; /** @@ -39,7 +37,6 @@ Compiler.prototype.visit = function(node){ Compiler.prototype.comment = function(node){ if (this.compress) return ''; - return this.indent() + '/*' + node.comment + '*/'; }; /** @@ -55,21 +52,11 @@ Compiler.prototype.import = function(node){ */ Compiler.prototype.media = function(node){ - if (this.compress) { - return '@media ' - + node.media - + '{' - + node.rules.map(this.visit, this).join('') - + '}'; - } - return '@media ' + node.media - + ' {\n' - + this.indent(1) - + node.rules.map(this.visit, this).join('\n\n') - + this.indent(-1) - + '\n}'; + + '{' + + node.rules.map(this.visit, this).join('') + + '}'; }; /** @@ -79,19 +66,10 @@ Compiler.prototype.media = function(node){ Compiler.prototype.document = function(node){ var doc = '@' + (node.vendor || '') + 'document ' + node.document; - if (this.compress) { - return doc - + '{' - + node.rules.map(this.visit, this).join('') - + '}'; - } - - return doc + ' ' - + ' {\n' - + this.indent(1) - + node.rules.map(this.visit, this).join('\n\n') - + this.indent(-1) - + '\n}'; + return doc + + '{' + + node.rules.map(this.visit, this).join('') + + '}'; }; /** @@ -99,11 +77,7 @@ Compiler.prototype.document = function(node){ */ Compiler.prototype.charset = function(node){ - if (this.compress) { - return '@charset ' + node.charset + ';'; - } - - return '@charset ' + node.charset + ';\n'; + return '@charset ' + node.charset + ';'; }; /** @@ -125,24 +99,12 @@ Compiler.prototype.supports = function(node){ */ Compiler.prototype.keyframes = function(node){ - if (this.compress) { - return '@' - + (node.vendor || '') - + 'keyframes ' - + node.name - + '{' - + node.keyframes.map(this.visit, this).join('') - + '}'; - } - return '@' + (node.vendor || '') + 'keyframes ' + node.name - + ' {\n' - + this.indent(1) - + node.keyframes.map(this.visit, this).join('\n') - + this.indent(-1) + + '{' + + node.keyframes.map(this.visit, this).join('') + '}'; }; @@ -153,20 +115,10 @@ Compiler.prototype.keyframes = function(node){ Compiler.prototype.keyframe = function(node){ var decls = node.declarations; - if (this.compress) { - return node.values.join(',') - + '{' - + decls.map(this.visit, this).join('') - + '}'; - } - - return this.indent() - + node.values.join(', ') - + ' {\n' - + this.indent(1) - + decls.map(this.visit, this).join('\n') - + this.indent(-1) - + '\n' + this.indent() + '}\n'; + return node.values.join(',') + + '{' + + decls.map(this.visit, this).join('') + + '}'; }; /** @@ -191,24 +143,13 @@ Compiler.prototype.page = function(node){ */ Compiler.prototype.rule = function(node){ - var indent = this.indent(); var decls = node.declarations; + if (!decls.length) return ''; - if (this.compress) { - if (!decls.length) return ''; - - return node.selectors.join(',') - + '{' - + decls.map(this.visit, this).join('') - + '}'; - } - - return node.selectors.map(function(s){ return indent + s }).join(',\n') - + ' {\n' - + this.indent(1) - + decls.map(this.visit, this).join('\n') - + this.indent(-1) - + '\n' + this.indent() + '}'; + return node.selectors.join(',') + + '{' + + decls.map(this.visit, this).join('') + + '}'; }; /** @@ -216,24 +157,6 @@ Compiler.prototype.rule = function(node){ */ Compiler.prototype.declaration = function(node){ - if (this.compress) { - return node.property + ':' + node.value + ';'; - } - - return this.indent() + node.property + ': ' + node.value + ';'; + return node.property + ':' + node.value + ';'; }; -/** - * Increase, decrease or return current indentation. - */ - -Compiler.prototype.indent = function(level) { - this.level = this.level || 1; - - if (null != level) { - this.level += level; - return ''; - } - - return Array(this.level).join(this.indentation || ' '); -}; From d44782da4e0a1afd8de7453958c3109cae6d7a8e Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Tue, 28 May 2013 16:56:33 -0700 Subject: [PATCH 29/67] add comment compression test --- test/cases/comments.compressed.css | 1 + 1 file changed, 1 insertion(+) create mode 100644 test/cases/comments.compressed.css diff --git a/test/cases/comments.compressed.css b/test/cases/comments.compressed.css new file mode 100644 index 0000000..7ca44b1 --- /dev/null +++ b/test/cases/comments.compressed.css @@ -0,0 +1 @@ +body{color:#eee;} From 695bd4386af3fe5bf28d8e9d92adc6d4d0e86106 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Tue, 28 May 2013 16:58:43 -0700 Subject: [PATCH 30/67] add keyframes compression test --- test/cases/keyframes.compressed.css | 1 + 1 file changed, 1 insertion(+) create mode 100644 test/cases/keyframes.compressed.css diff --git a/test/cases/keyframes.compressed.css b/test/cases/keyframes.compressed.css new file mode 100644 index 0000000..75a9dbb --- /dev/null +++ b/test/cases/keyframes.compressed.css @@ -0,0 +1 @@ +@keyframes fade{from{opacity:0;opacity:1;}to{opacity:1;}} From 3ed7147892fff34f32a0067b171cbf8cc8376e41 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Tue, 28 May 2013 17:00:50 -0700 Subject: [PATCH 31/67] Release 1.3.0 --- History.md | 11 +++++++++++ component.json | 2 +- package.json | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index b818df7..3946f56 100644 --- a/History.md +++ b/History.md @@ -1,4 +1,15 @@ +1.3.0 / 2013-05-28 +================== + + * add ignoring of empty rulesets. Closes #7 + * add separate compilers + * add @supports support + * add @page compilation support + * fix comment output. Closes #16 + * fix trailing ; with comments within rules + * fix comment indentation + 1.2.0 / 2013-05-21 ================== diff --git a/component.json b/component.json index 8c79e79..4474e2a 100644 --- a/component.json +++ b/component.json @@ -1,7 +1,7 @@ { "name": "css-stringify", "repo": "visionmedia/css-stringify", - "version": "1.2.0", + "version": "1.3.0", "description": "CSS compiler", "keywords": ["css", "stringify", "stylesheet"], "scripts": [ diff --git a/package.json b/package.json index 3bc7342..70c9214 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "css-stringify", - "version": "1.2.0", + "version": "1.3.0", "description": "CSS compiler", "keywords": ["css", "stringify", "stylesheet"], "author": "TJ Holowaychuk ", From 693b45e6e0efa3e4410583bfbda4ab78ef336515 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Tue, 28 May 2013 17:03:23 -0700 Subject: [PATCH 32/67] fix defaulting of options --- index.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/index.js b/index.js index 6598da3..193b75e 100644 --- a/index.js +++ b/index.js @@ -10,16 +10,18 @@ var Identity = require('./lib/identity'); * Stringfy the given AST `node`. * * @param {Object} node - * @param {Object} options + * @param {Object} [options] * @return {String} * @api public */ module.exports = function(node, options){ - if (options.compress) { - return new Compressed(options).compile(node); - } + options = options || {}; - return new Identity(options).compile(node); + var compiler = options.compress + ? new Compressed(options) + : new Identity(options); + + return compiler.compile(node); }; From ae20c65a2e5a422b01f4b44d4b0647d0014b378b Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Sun, 2 Jun 2013 14:20:14 -0700 Subject: [PATCH 33/67] fix output of rules with no declarations for Identity compiler --- lib/identity.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/identity.js b/lib/identity.js index 3a681e3..4534c66 100644 --- a/lib/identity.js +++ b/lib/identity.js @@ -155,6 +155,7 @@ Compiler.prototype.page = function(node){ Compiler.prototype.rule = function(node){ var indent = this.indent(); var decls = node.declarations; + if (!decls.length) return ''; return node.selectors.map(function(s){ return indent + s }).join(',\n') + ' {\n' From 700f9d4bf5965190b4a2435458237fcdaf60d057 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Sun, 2 Jun 2013 14:20:29 -0700 Subject: [PATCH 34/67] Release 1.3.1 --- History.md | 6 ++++++ component.json | 2 +- package.json | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index 3946f56..e96ad3b 100644 --- a/History.md +++ b/History.md @@ -1,4 +1,10 @@ +1.3.1 / 2013-06-02 +================== + + * fix output of rules with no declarations for Identity compiler + * fix defaulting of options + 1.3.0 / 2013-05-28 ================== diff --git a/component.json b/component.json index 4474e2a..6110e97 100644 --- a/component.json +++ b/component.json @@ -1,7 +1,7 @@ { "name": "css-stringify", "repo": "visionmedia/css-stringify", - "version": "1.3.0", + "version": "1.3.1", "description": "CSS compiler", "keywords": ["css", "stringify", "stylesheet"], "scripts": [ diff --git a/package.json b/package.json index 70c9214..0be8b47 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "css-stringify", - "version": "1.3.0", + "version": "1.3.1", "description": "CSS compiler", "keywords": ["css", "stringify", "stylesheet"], "author": "TJ Holowaychuk ", From 67ddc839e46c75c6c3f91abd2770bd0b1fd729f0 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Fri, 14 Jun 2013 13:37:35 -0700 Subject: [PATCH 35/67] add .stylesheet(node) --- lib/identity.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/identity.js b/lib/identity.js index 4534c66..00bdce7 100644 --- a/lib/identity.js +++ b/lib/identity.js @@ -19,9 +19,7 @@ function Compiler(options) { */ Compiler.prototype.compile = function(node){ - return node.stylesheet - .rules.map(this.visit, this) - .join('\n\n'); + return this.stylesheet(node); }; /** @@ -32,6 +30,16 @@ Compiler.prototype.visit = function(node){ return this[node.type](node); }; +/** + * Visit stylesheet node. + */ + +Compiler.prototype.stylesheet = function(node){ + return node.stylesheet + .rules.map(this.visit, this) + .join('\n\n'); +}; + /** * Visit comment node. */ From ef85829d8cda27bd50b979bf4f2183721f0fec4f Mon Sep 17 00:00:00 2001 From: "Alexey Ten (Lynn)" Date: Mon, 19 Aug 2013 17:12:04 +0400 Subject: [PATCH 36/67] Add @namespace support --- lib/compress.js | 8 ++++++++ lib/identity.js | 8 ++++++++ test/cases/at_namespace.css | 1 + 3 files changed, 17 insertions(+) create mode 100644 test/cases/at_namespace.css diff --git a/lib/compress.js b/lib/compress.js index db4fa54..da1504f 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -80,6 +80,14 @@ Compiler.prototype.charset = function(node){ return '@charset ' + node.charset + ';'; }; +/** + * Visit namespace node. + */ + +Compiler.prototype.namespace = function(node){ + return '@namespace ' + node.namespace + ';'; +}; + /** * Visit supports node. */ diff --git a/lib/identity.js b/lib/identity.js index 00bdce7..abf97f4 100644 --- a/lib/identity.js +++ b/lib/identity.js @@ -93,6 +93,14 @@ Compiler.prototype.charset = function(node){ return '@charset ' + node.charset + ';\n'; }; +/** + * Visit namespace node. + */ + +Compiler.prototype.namespace = function(node){ + return '@namespace ' + node.namespace + ';\n'; +}; + /** * Visit supports node. */ diff --git a/test/cases/at_namespace.css b/test/cases/at_namespace.css new file mode 100644 index 0000000..edc75cf --- /dev/null +++ b/test/cases/at_namespace.css @@ -0,0 +1 @@ +@namespace svg "http://www.w3.org/2000/svg"; From b5b26a3b36ad1c9d360f849859c7297601e91644 Mon Sep 17 00:00:00 2001 From: Forbes Lindesay Date: Wed, 21 Aug 2013 09:40:11 -0700 Subject: [PATCH 37/67] add repository field to readme --- package.json | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 0be8b47..d3db9e8 100644 --- a/package.json +++ b/package.json @@ -2,12 +2,20 @@ "name": "css-stringify", "version": "1.3.1", "description": "CSS compiler", - "keywords": ["css", "stringify", "stylesheet"], + "keywords": [ + "css", + "stringify", + "stylesheet" + ], "author": "TJ Holowaychuk ", "devDependencies": { "mocha": "*", "should": "*", "css-parse": "1.4.0" }, - "main": "index" + "main": "index", + "repository": { + "type": "git", + "url": "https://github.com/visionmedia/css-stringify.git" + } } From 6ab04b50c87050f1352faec248b31c47354582c9 Mon Sep 17 00:00:00 2001 From: Jonathan Ong Date: Wed, 9 Oct 2013 16:56:51 -0700 Subject: [PATCH 38/67] Create LICENSE --- LICENSE | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0239d9c --- /dev/null +++ b/LICENSE @@ -0,0 +1,9 @@ +(The MIT License) + +Copyright (c) 2012 TJ Holowaychuk + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. From ab392ead2b4f62f42cc19699a55727977e4499c0 Mon Sep 17 00:00:00 2001 From: Jonathan Ong Date: Wed, 9 Oct 2013 18:10:22 -0700 Subject: [PATCH 39/67] Create .travis.yml --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..6e5919d --- /dev/null +++ b/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - "0.10" From f90d60b55e4b377cb70aa8b09b4ab1770763591e Mon Sep 17 00:00:00 2001 From: Jonathan Ong Date: Thu, 10 Oct 2013 11:04:27 -0700 Subject: [PATCH 40/67] Update package.json --- package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/package.json b/package.json index d3db9e8..af67f6f 100644 --- a/package.json +++ b/package.json @@ -17,5 +17,8 @@ "repository": { "type": "git", "url": "https://github.com/visionmedia/css-stringify.git" + }, + "scripts": { + "test": "make test" } } From 5097e318667c93bf9d0685c957b8906076cdf34c Mon Sep 17 00:00:00 2001 From: Jonathan Ong Date: Thu, 17 Oct 2013 05:09:30 -0700 Subject: [PATCH 41/67] travis badge --- Readme.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Readme.md b/Readme.md index a36e780..2755c94 100644 --- a/Readme.md +++ b/Readme.md @@ -1,5 +1,4 @@ - -# css-stringify +# css-stringify [![Build Status](https://travis-ci.org/visionmedia/css-stringify.png)](https://travis-ci.org/visionmedia/css-stringify) CSS compiler using the AST provided by [css-parse](https://github.com/visionmedia/css-parse). From 7347b8b4c3facf5127d1d3a783b08ca314f210e9 Mon Sep 17 00:00:00 2001 From: Brett Stimmerman Date: Fri, 18 Oct 2013 11:55:24 -0700 Subject: [PATCH 42/67] Fix whitespace and indentation in the Compressed compiler. Before this change the Compressed compiler errored when processing @page and @supports blocks, and the tests did not cover this. This change fixes @page and @supports compression in the Compressed compiler, fixes the tests to fully flex the Compressed compiler, and adds missing fixtures to flesh out the test suite. --- lib/compress.js | 20 ++++++++------------ test/cases/document.compressed.css | 1 + test/cases/media.compressed.css | 1 + test/cases/page.compressed.css | 1 + test/cases/rules.compressed.css | 1 + test/cases/selectors.compressed.css | 1 + test/cases/supports.compressed.css | 1 + test/cases/supports.css | 1 - test/css-stringify.js | 15 +++++++++------ 9 files changed, 23 insertions(+), 19 deletions(-) create mode 100644 test/cases/document.compressed.css create mode 100644 test/cases/media.compressed.css create mode 100644 test/cases/page.compressed.css create mode 100644 test/cases/rules.compressed.css create mode 100644 test/cases/selectors.compressed.css create mode 100644 test/cases/supports.compressed.css diff --git a/lib/compress.js b/lib/compress.js index da1504f..0a9b98b 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -36,7 +36,7 @@ Compiler.prototype.visit = function(node){ */ Compiler.prototype.comment = function(node){ - if (this.compress) return ''; + return ''; }; /** @@ -95,11 +95,9 @@ Compiler.prototype.namespace = function(node){ Compiler.prototype.supports = function(node){ return '@supports ' + node.supports - + ' {\n' - + this.indent(1) - + node.rules.map(this.visit, this).join('\n\n') - + this.indent(-1) - + '\n}'; + + '{' + + node.rules.map(this.visit, this).join('') + + '}'; }; /** @@ -135,15 +133,13 @@ Compiler.prototype.keyframe = function(node){ Compiler.prototype.page = function(node){ var sel = node.selectors.length - ? node.selectors.join(', ') + ' ' + ? node.selectors.join(', ') : ''; return '@page ' + sel - + '{\n' - + this.indent(1) - + node.declarations.map(this.visit, this).join('\n') - + this.indent(-1) - + '\n}'; + + '{' + + node.declarations.map(this.visit, this).join('') + + '}'; }; /** diff --git a/test/cases/document.compressed.css b/test/cases/document.compressed.css new file mode 100644 index 0000000..d56d0a5 --- /dev/null +++ b/test/cases/document.compressed.css @@ -0,0 +1 @@ +@-moz-document url-prefix(){.icon-spin{height:.9em;}.btn .icon-spin{height:auto;}.icon-spin.icon-large{height:1.25em;}.btn .icon-spin.icon-large{height:.75em;}} diff --git a/test/cases/media.compressed.css b/test/cases/media.compressed.css new file mode 100644 index 0000000..a34785a --- /dev/null +++ b/test/cases/media.compressed.css @@ -0,0 +1 @@ +@media screen, projection{html{background:#fffef0;color:#300;}body{max-width:35em;margin:0 auto;}}@media print{html{background:#fff;color:#000;}body{padding:1in;border:0.5pt solid #666;}} diff --git a/test/cases/page.compressed.css b/test/cases/page.compressed.css new file mode 100644 index 0000000..84595d2 --- /dev/null +++ b/test/cases/page.compressed.css @@ -0,0 +1 @@ +@page {margin:2.5cm;}@page :left{margin-left:5cm;}@page :right{margin-right:5cm;}@page :first{margin-top:8cm;} \ No newline at end of file diff --git a/test/cases/rules.compressed.css b/test/cases/rules.compressed.css new file mode 100644 index 0000000..3a4188c --- /dev/null +++ b/test/cases/rules.compressed.css @@ -0,0 +1 @@ +tobi{name:'tobi';age:2;}loki{name:'loki';age:1;} diff --git a/test/cases/selectors.compressed.css b/test/cases/selectors.compressed.css new file mode 100644 index 0000000..ee0faf9 --- /dev/null +++ b/test/cases/selectors.compressed.css @@ -0,0 +1 @@ +foo,bar,baz{color:'black';} diff --git a/test/cases/supports.compressed.css b/test/cases/supports.compressed.css new file mode 100644 index 0000000..61d4ee2 --- /dev/null +++ b/test/cases/supports.compressed.css @@ -0,0 +1 @@ +@supports (display: flex){div{display:flex;}div{something:else;}} diff --git a/test/cases/supports.css b/test/cases/supports.css index 05ca478..37952f1 100644 --- a/test/cases/supports.css +++ b/test/cases/supports.css @@ -1,4 +1,3 @@ - @supports (display: flex) { div { display: flex; diff --git a/test/css-stringify.js b/test/css-stringify.js index ad2ba19..8f55ef7 100644 --- a/test/css-stringify.js +++ b/test/css-stringify.js @@ -12,13 +12,16 @@ var stringify = require('..') describe('stringify(obj)', function(){ readdir('test/cases').forEach(function(file){ - var compress = ~file.indexOf('compress'); - file = path.basename(file, '.css'); - it('should stringify ' + file, function(){ - var css = read(path.join('test', 'cases', file + '.css'), 'utf8'); - if (compress) file = file.replace('.compress', ''); + var compress = ~file.indexOf('.compressed'); + it('should stringify ' + path.basename(file), function(){ + var expect; + if (compress) { + expect = read(path.join('test', 'cases', file), 'utf8'); + file = file.replace('.compressed', ''); + } + var css = read(path.join('test', 'cases', file), 'utf8'); var ret = stringify(parse(css), { compress: compress }); - ret.trim().should.equal(css.trim()); + ret.trim().should.equal((expect || css).trim()); }); }); }); From 08c07d60074d861840c0634ee142532bffd571e9 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Fri, 18 Oct 2013 13:02:29 -0700 Subject: [PATCH 43/67] Release 1.3.2 --- History.md | 7 +++++++ component.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index e96ad3b..c9accae 100644 --- a/History.md +++ b/History.md @@ -1,4 +1,11 @@ +1.3.2 / 2013-10-18 +================== + + * fix whitespace and indentation in the Compressed compiler. + * add @namespace support + * add .stylesheet(node) + 1.3.1 / 2013-06-02 ================== diff --git a/component.json b/component.json index 6110e97..c4f438a 100644 --- a/component.json +++ b/component.json @@ -1,7 +1,7 @@ { "name": "css-stringify", "repo": "visionmedia/css-stringify", - "version": "1.3.1", + "version": "1.3.2", "description": "CSS compiler", "keywords": ["css", "stringify", "stylesheet"], "scripts": [ diff --git a/package.json b/package.json index af67f6f..305f585 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "css-stringify", - "version": "1.3.1", + "version": "1.3.2", "description": "CSS compiler", "keywords": [ "css", From 9e2e590b9fd4b6d0244c225a72464ab71fd09a32 Mon Sep 17 00:00:00 2001 From: Andrey Popp <8mayday@gmail.com> Date: Wed, 27 Nov 2013 09:49:46 -0800 Subject: [PATCH 44/67] add sourcemap support --- examples/sourcemaps.js | 12 ++++ index.js | 12 +++- lib/compiler.js | 50 ++++++++++++++ lib/compress.js | 92 ++++++++++++------------- lib/identity.js | 138 +++++++++++++++++++++----------------- lib/source-map-support.js | 84 +++++++++++++++++++++++ package.json | 5 +- test/css-stringify.js | 45 ++++++++++++- test/source-map-case.css | 17 +++++ 9 files changed, 344 insertions(+), 111 deletions(-) create mode 100644 examples/sourcemaps.js create mode 100644 lib/compiler.js create mode 100644 lib/source-map-support.js create mode 100644 test/source-map-case.css diff --git a/examples/sourcemaps.js b/examples/sourcemaps.js new file mode 100644 index 0000000..ef1fe4b --- /dev/null +++ b/examples/sourcemaps.js @@ -0,0 +1,12 @@ + +/** + * Module dependencies. + */ + +var parse = require('css-parse') + , stringify = require('..') + , fs = require('fs') + , read = fs.readFileSync + , css = read('examples/media.css', 'utf8'); + +console.log(stringify(parse(css), { compress: false, sourcemap: true })); diff --git a/index.js b/index.js index 193b75e..103a849 100644 --- a/index.js +++ b/index.js @@ -22,6 +22,16 @@ module.exports = function(node, options){ ? new Compressed(options) : new Identity(options); - return compiler.compile(node); + // source maps + if (options.sourcemap) { + var sourcemaps = require('./lib/source-map-support'); + sourcemaps(compiler); + + var code = compiler.compile(node); + return { code: code, map: compiler.map.toJSON() }; + } + + var code = compiler.compile(node); + return code; }; diff --git a/lib/compiler.js b/lib/compiler.js new file mode 100644 index 0000000..6d01a14 --- /dev/null +++ b/lib/compiler.js @@ -0,0 +1,50 @@ + +/** + * Expose `Compiler`. + */ + +module.exports = Compiler; + +/** + * Initialize a compiler. + * + * @param {Type} name + * @return {Type} + * @api public + */ + +function Compiler(opts) { + this.options = opts || {}; +} + +/** + * Emit `str` + */ + +Compiler.prototype.emit = function(str) { + return str; +}; + +/** + * Visit `node`. + */ + +Compiler.prototype.visit = function(node){ + return this[node.type](node); +}; + +/** + * Map visit over array of `nodes`, optionally using a `delim` + */ + +Compiler.prototype.mapVisit = function(nodes, delim){ + var buf = ''; + delim = delim || ''; + + for (var i = 0, length = nodes.length; i < length; i++) { + buf += this.visit(nodes[i]); + if (delim && i < length - 1) buf += this.emit(delim); + } + + return buf; +}; diff --git a/lib/compress.js b/lib/compress.js index 0a9b98b..601bd73 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -1,4 +1,10 @@ +/** + * Module dependencies. + */ + +var Base = require('./compiler'); + /** * Expose compiler. */ @@ -10,9 +16,15 @@ module.exports = Compiler; */ function Compiler(options) { - options = options || {}; + Base.call(this, options); } +/** + * Inherit from `Base.prototype`. + */ + +Compiler.prototype.__proto__ = Base.prototype; + /** * Compile `node`. */ @@ -23,20 +35,12 @@ Compiler.prototype.compile = function(node){ .join(''); }; -/** - * Visit `node`. - */ - -Compiler.prototype.visit = function(node){ - return this[node.type](node); -}; - /** * Visit comment node. */ Compiler.prototype.comment = function(node){ - return ''; + return this.emit('', node.position); }; /** @@ -44,7 +48,7 @@ Compiler.prototype.comment = function(node){ */ Compiler.prototype.import = function(node){ - return '@import ' + node.import + ';'; + return this.emit('@import ' + node.import + ';', node.position); }; /** @@ -52,11 +56,10 @@ Compiler.prototype.import = function(node){ */ Compiler.prototype.media = function(node){ - return '@media ' - + node.media - + '{' - + node.rules.map(this.visit, this).join('') - + '}'; + return this.emit('@media ' + node.media, node.position, true) + + this.emit('{') + + this.mapVisit(node.rules) + + this.emit('}'); }; /** @@ -66,10 +69,10 @@ Compiler.prototype.media = function(node){ Compiler.prototype.document = function(node){ var doc = '@' + (node.vendor || '') + 'document ' + node.document; - return doc - + '{' - + node.rules.map(this.visit, this).join('') - + '}'; + return this.emit(doc, node.position, true) + + this.emit('{') + + this.mapVisit(node.rules) + + this.emit('}'); }; /** @@ -77,7 +80,7 @@ Compiler.prototype.document = function(node){ */ Compiler.prototype.charset = function(node){ - return '@charset ' + node.charset + ';'; + return this.emit('@charset ' + node.charset + ';', node.position); }; /** @@ -85,7 +88,7 @@ Compiler.prototype.charset = function(node){ */ Compiler.prototype.namespace = function(node){ - return '@namespace ' + node.namespace + ';'; + return this.emit('@namespace ' + node.namespace + ';', node.position); }; /** @@ -93,11 +96,10 @@ Compiler.prototype.namespace = function(node){ */ Compiler.prototype.supports = function(node){ - return '@supports ' - + node.supports - + '{' - + node.rules.map(this.visit, this).join('') - + '}'; + return this.emit('@supports ' + node.supports, node.position, true) + + this.emit('{') + + this.mapVisit(node.rules) + + this.emit('}'); }; /** @@ -105,13 +107,13 @@ Compiler.prototype.supports = function(node){ */ Compiler.prototype.keyframes = function(node){ - return '@' + return this.emit('@' + (node.vendor || '') + 'keyframes ' - + node.name - + '{' - + node.keyframes.map(this.visit, this).join('') - + '}'; + + node.name, node.position, true) + + this.emit('{') + + this.mapVisit(node.keyframes) + + this.emit('}'); }; /** @@ -121,10 +123,10 @@ Compiler.prototype.keyframes = function(node){ Compiler.prototype.keyframe = function(node){ var decls = node.declarations; - return node.values.join(',') - + '{' - + decls.map(this.visit, this).join('') - + '}'; + return this.emit(node.values.join(','), node.position, true) + + this.emit('{') + + this.mapVisit(decls) + + this.emit('}'); }; /** @@ -136,10 +138,10 @@ Compiler.prototype.page = function(node){ ? node.selectors.join(', ') : ''; - return '@page ' + sel - + '{' - + node.declarations.map(this.visit, this).join('') - + '}'; + return this.emit('@page ' + sel, node.position, true) + + this.emit('{') + + this.mapVisit(node.declarations) + + this.emit('}'); }; /** @@ -150,10 +152,10 @@ Compiler.prototype.rule = function(node){ var decls = node.declarations; if (!decls.length) return ''; - return node.selectors.join(',') - + '{' - + decls.map(this.visit, this).join('') - + '}'; + return this.emit(node.selectors.join(','), node.position, true) + + this.emit('{') + + this.mapVisit(decls) + + this.emit('}'); }; /** @@ -161,6 +163,6 @@ Compiler.prototype.rule = function(node){ */ Compiler.prototype.declaration = function(node){ - return node.property + ':' + node.value + ';'; + return this.emit(node.property + ':' + node.value, node.position) + this.emit(';'); }; diff --git a/lib/identity.js b/lib/identity.js index abf97f4..cc9fd5c 100644 --- a/lib/identity.js +++ b/lib/identity.js @@ -1,4 +1,10 @@ +/** + * Module dependencies. + */ + +var Base = require('./compiler'); + /** * Expose compiler. */ @@ -11,23 +17,22 @@ module.exports = Compiler; function Compiler(options) { options = options || {}; + Base.call(this, options); this.indentation = options.indent; } /** - * Compile `node`. + * Inherit from `Base.prototype`. */ -Compiler.prototype.compile = function(node){ - return this.stylesheet(node); -}; +Compiler.prototype.__proto__ = Base.prototype; /** - * Visit `node`. + * Compile `node`. */ -Compiler.prototype.visit = function(node){ - return this[node.type](node); +Compiler.prototype.compile = function(node){ + return this.stylesheet(node); }; /** @@ -35,9 +40,7 @@ Compiler.prototype.visit = function(node){ */ Compiler.prototype.stylesheet = function(node){ - return node.stylesheet - .rules.map(this.visit, this) - .join('\n\n'); + return this.mapVisit(node.stylesheet.rules, '\n\n'); }; /** @@ -45,7 +48,7 @@ Compiler.prototype.stylesheet = function(node){ */ Compiler.prototype.comment = function(node){ - return this.indent() + '/*' + node.comment + '*/'; + return this.emit(this.indent() + '/*' + node.comment + '*/', node.position); }; /** @@ -53,7 +56,7 @@ Compiler.prototype.comment = function(node){ */ Compiler.prototype.import = function(node){ - return '@import ' + node.import + ';'; + return this.emit('@import ' + node.import + ';', node.position); }; /** @@ -61,13 +64,14 @@ Compiler.prototype.import = function(node){ */ Compiler.prototype.media = function(node){ - return '@media ' - + node.media - + ' {\n' - + this.indent(1) - + node.rules.map(this.visit, this).join('\n\n') - + this.indent(-1) - + '\n}'; + return this.emit('@media ' + node.media, node.position, true) + + this.emit( + ' {\n' + + this.indent(1)) + + this.mapVisit(node.rules, '\n\n') + + this.emit( + this.indent(-1) + + '\n}'); }; /** @@ -77,12 +81,15 @@ Compiler.prototype.media = function(node){ Compiler.prototype.document = function(node){ var doc = '@' + (node.vendor || '') + 'document ' + node.document; - return doc + ' ' - + ' {\n' - + this.indent(1) - + node.rules.map(this.visit, this).join('\n\n') - + this.indent(-1) - + '\n}'; + return this.emit(doc, node.position, true) + + this.emit( + ' ' + + ' {\n' + + this.indent(1)) + + this.mapVisit(node.rules, '\n\n') + + this.emit( + this.indent(-1) + + '\n}'); }; /** @@ -90,7 +97,7 @@ Compiler.prototype.document = function(node){ */ Compiler.prototype.charset = function(node){ - return '@charset ' + node.charset + ';\n'; + return this.emit('@charset ' + node.charset + ';', node.position); }; /** @@ -98,7 +105,7 @@ Compiler.prototype.charset = function(node){ */ Compiler.prototype.namespace = function(node){ - return '@namespace ' + node.namespace + ';\n'; + return this.emit('@namespace ' + node.namespace + ';', node.position); }; /** @@ -106,13 +113,14 @@ Compiler.prototype.namespace = function(node){ */ Compiler.prototype.supports = function(node){ - return '@supports ' - + node.supports - + ' {\n' - + this.indent(1) - + node.rules.map(this.visit, this).join('\n\n') - + this.indent(-1) - + '\n}'; + return this.emit('@supports ' + node.supports, node.position, true) + + this.emit( + ' {\n' + + this.indent(1)) + + this.mapVisit(node.rules, '\n\n') + + this.emit( + this.indent(-1) + + '\n}'); }; /** @@ -120,15 +128,14 @@ Compiler.prototype.supports = function(node){ */ Compiler.prototype.keyframes = function(node){ - return '@' - + (node.vendor || '') - + 'keyframes ' - + node.name - + ' {\n' - + this.indent(1) - + node.keyframes.map(this.visit, this).join('\n') - + this.indent(-1) - + '}'; + return this.emit('@' + (node.vendor || '') + 'keyframes ' + node.name, node.position, true) + + this.emit( + ' {\n' + + this.indent(1)) + + this.mapVisit(node.keyframes, '\n') + + this.emit( + this.indent(-1) + + '}'); }; /** @@ -138,13 +145,16 @@ Compiler.prototype.keyframes = function(node){ Compiler.prototype.keyframe = function(node){ var decls = node.declarations; - return this.indent() - + node.values.join(', ') - + ' {\n' - + this.indent(1) - + decls.map(this.visit, this).join('\n') - + this.indent(-1) - + '\n' + this.indent() + '}\n'; + return this.emit(this.indent()) + + this.emit(node.values.join(', '), node.position, true) + + this.emit( + ' {\n' + + this.indent(1)) + + this.mapVisit(decls, '\n') + + this.emit( + this.indent(-1) + + '\n' + + this.indent() + '}\n'); }; /** @@ -156,12 +166,12 @@ Compiler.prototype.page = function(node){ ? node.selectors.join(', ') + ' ' : ''; - return '@page ' + sel - + '{\n' - + this.indent(1) - + node.declarations.map(this.visit, this).join('\n') - + this.indent(-1) - + '\n}'; + return this.emit('@page ' + sel, node.position, true) + + this.emit('{\n') + + this.emit(this.indent(1)) + + this.mapVisit(node.declarations, '\n') + + this.emit(this.indent(-1)) + + this.emit('\n}'); }; /** @@ -173,12 +183,12 @@ Compiler.prototype.rule = function(node){ var decls = node.declarations; if (!decls.length) return ''; - return node.selectors.map(function(s){ return indent + s }).join(',\n') - + ' {\n' - + this.indent(1) - + decls.map(this.visit, this).join('\n') - + this.indent(-1) - + '\n' + this.indent() + '}'; + return this.emit(node.selectors.map(function(s){ return indent + s }).join(',\n'), node.position, true) + + this.emit(' {\n') + + this.emit(this.indent(1)) + + this.mapVisit(decls, '\n') + + this.emit(this.indent(-1)) + + this.emit('\n' + this.indent() + '}'); }; /** @@ -186,7 +196,9 @@ Compiler.prototype.rule = function(node){ */ Compiler.prototype.declaration = function(node){ - return this.indent() + node.property + ': ' + node.value + ';'; + return this.emit(this.indent()) + + this.emit(node.property + ': ' + node.value, node.position) + + this.emit(';'); }; /** diff --git a/lib/source-map-support.js b/lib/source-map-support.js new file mode 100644 index 0000000..1e60513 --- /dev/null +++ b/lib/source-map-support.js @@ -0,0 +1,84 @@ + +/** + * Module dependencies. + */ + +var SourceMap = require('source-map').SourceMapGenerator; + +/** + * Expose `mixin()`. + */ + +module.exports = mixin; + +/** + * Mixin source map support into `compiler`. + * + * @param {Compiler} compiler + * @api public + */ + +function mixin(compiler) { + var file = compiler.options.filename || 'generated.css'; + compiler.map = new SourceMap({ file: file }); + compiler.position = { line: 1, column: 1 }; + for (var k in exports) compiler[k] = exports[k]; +} + +/** + * Update position. + * + * @param {String} str + * @api private + */ + +exports.updatePosition = function(str) { + var lines = str.match(/\n/g); + if (lines) this.position.line += lines.length; + var i = str.lastIndexOf('\n'); + this.position.column = ~i ? str.length - i : this.position.column + str.length; +}; + +/** + * Emit `str`. + * + * @param {String} str + * @param {Number} [pos] + * @param {Boolean} [startOnly] + * @return {String} + * @api private + */ + +exports.emit = function(str, pos, startOnly) { + if (pos && pos.start) { + this.map.addMapping({ + source: pos.source || 'source.css', + generated: { + line: this.position.line, + column: Math.max(this.position.column - 1, 0) + }, + original: { + line: pos.start.line, + column: pos.start.column - 1 + } + }); + } + + this.updatePosition(str); + + if (!startOnly && pos && pos.end) { + this.map.addMapping({ + source: pos.source || 'source.css', + generated: { + line: this.position.line, + column: Math.max(this.position.column - 1, 0) + }, + original: { + line: pos.end.line, + column: pos.end.column - 1 + } + }); + } + + return str; +}; diff --git a/package.json b/package.json index 305f585..1dfe90c 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "devDependencies": { "mocha": "*", "should": "*", - "css-parse": "1.4.0" + "css-parse": "1.6.0" }, "main": "index", "repository": { @@ -20,5 +20,8 @@ }, "scripts": { "test": "make test" + }, + "dependencies": { + "source-map": "~0.1.31" } } diff --git a/test/css-stringify.js b/test/css-stringify.js index 8f55ef7..b37ee7f 100644 --- a/test/css-stringify.js +++ b/test/css-stringify.js @@ -8,7 +8,8 @@ var stringify = require('..') , fs = require('fs') , path = require('path') , read = fs.readFileSync - , readdir = fs.readdirSync; + , readdir = fs.readdirSync + , SourceMapConsumer = require('source-map').SourceMapConsumer; describe('stringify(obj)', function(){ readdir('test/cases').forEach(function(file){ @@ -25,3 +26,45 @@ describe('stringify(obj)', function(){ }); }); }); + +describe('stringify(obj, {sourcemap: true})', function(){ + var src = read('test/source-map-case.css', 'utf8'); + var stylesheet = parse(src, { source: 'rules.css', position: true }); + function loc(line, column) { + return { line: line, column: column, source: 'rules.css', name: null } + }; + + var locs = { + tobiSelector: loc(1, 0), + tobiNameName: loc(2, 2), + tobiNameValue: loc(2, 2), + mediaBlock: loc(11, 0), + mediaOnly: loc(12, 2), + comment: loc(17, 0), + }; + + it('should generate source maps alongside when using identity compiler', function(){ + var result = stringify(stylesheet, { sourcemap: true }); + result.should.have.property('code'); + result.should.have.property('map'); + var map = new SourceMapConsumer(result.map); + map.originalPositionFor({ line: 1, column: 0 }).should.eql(locs.tobiSelector); + map.originalPositionFor({ line: 2, column: 2 }).should.eql(locs.tobiNameName); + map.originalPositionFor({ line: 2, column: 8 }).should.eql(locs.tobiNameValue); + map.originalPositionFor({ line: 11, column: 0 }).should.eql(locs.mediaBlock); + map.originalPositionFor({ line: 12, column: 2 }).should.eql(locs.mediaOnly); + map.originalPositionFor({ line: 17, column: 0 }).should.eql(locs.comment); + }); + + it('should generate source maps alongside when using compress compiler', function(){ + var result = stringify(stylesheet, { compress: true, sourcemap: true }); + result.should.have.property('code'); + result.should.have.property('map'); + var map = new SourceMapConsumer(result.map); + map.originalPositionFor({ line: 1, column: 0 }).should.eql(locs.tobiSelector); + map.originalPositionFor({ line: 1, column: 5 }).should.eql(locs.tobiNameName); + map.originalPositionFor({ line: 1, column: 10 }).should.eql(locs.tobiNameValue); + map.originalPositionFor({ line: 1, column: 50 }).should.eql(locs.mediaBlock); + map.originalPositionFor({ line: 1, column: 64 }).should.eql(locs.mediaOnly); + }); +}); diff --git a/test/source-map-case.css b/test/source-map-case.css new file mode 100644 index 0000000..47598d7 --- /dev/null +++ b/test/source-map-case.css @@ -0,0 +1,17 @@ +tobi { + name: 'tobi'; + age: 2; +} + +loki { + name: 'loki'; + age: 1; +} + +@media screen { + screen-only { + display: block; + } +} + +/* comment */ From 336f27ee70764e6dac011118b51d4cee8b262917 Mon Sep 17 00:00:00 2001 From: Andrey Popp <8mayday@gmail.com> Date: Wed, 27 Nov 2013 22:18:13 +0400 Subject: [PATCH 45/67] Add docs --- History.md | 4 ++++ Readme.md | 22 ++++++++++++++++++++++ index.js | 8 ++++++++ 3 files changed, 34 insertions(+) diff --git a/History.md b/History.md index c9accae..80a2a9a 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,7 @@ +1.4.0 / 2013-XX-XX +================== + + * source map generation 1.3.2 / 2013-10-18 ================== diff --git a/Readme.md b/Readme.md index 2755c94..7fa7bb9 100644 --- a/Readme.md +++ b/Readme.md @@ -2,6 +2,28 @@ CSS compiler using the AST provided by [css-parse](https://github.com/visionmedia/css-parse). +## Usage + +`css-stringify` exports a single function which dumps CSS AST: + + var stringify = require('css-stringify'); + var parse = require('css-parse'); + + var ast = parse('body { font-size: 12px; }'); + + var str = stringify(ast); + +To get compressed output: + + var compressed = stringify(ast, {compress: true}); + +To get a source map: + + var result = stringify(ast, {sourcemap: true}); + + result.code // string with CSS + result.map // source map + ## Performance Formats 15,000 lines of CSS (2mb) in 23ms on my macbook air. diff --git a/index.js b/index.js index 103a849..85394fe 100644 --- a/index.js +++ b/index.js @@ -11,6 +11,14 @@ var Identity = require('./lib/identity'); * * @param {Object} node * @param {Object} [options] + * @param {Boolean} [options.sourcemap] generate source map, + * if set to true this will change return value to + * `{code: '...', map: {...}}`, `node` argument should contain + * position information (e.g. parsed by css-parse with + * `position` option set to `true`) + * @param {Boolean} [options.compress] compress output (ignores indent option) + * @param {String} [options.indent] a string used for indents (defaults to 2 spaces) + * * @return {String} * @api public */ From 311c5751b396c0a5332d8a45d373bd46969a3379 Mon Sep 17 00:00:00 2001 From: Andrey Popp <8mayday@gmail.com> Date: Wed, 27 Nov 2013 22:20:59 +0400 Subject: [PATCH 46/67] Docs: Mention `position` option for source map generation --- Readme.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Readme.md b/Readme.md index 7fa7bb9..bfc4947 100644 --- a/Readme.md +++ b/Readme.md @@ -19,11 +19,15 @@ To get compressed output: To get a source map: + var ast = parse('body { font-size: 12px; }', {position: true}); var result = stringify(ast, {sourcemap: true}); result.code // string with CSS result.map // source map +Note that the AST should contain position information (`position` option set to +`true`). + ## Performance Formats 15,000 lines of CSS (2mb) in 23ms on my macbook air. From b069217e766624ce5d82d437f76cbe68e97758a5 Mon Sep 17 00:00:00 2001 From: Andrey Popp <8mayday@gmail.com> Date: Wed, 27 Nov 2013 22:23:22 +0400 Subject: [PATCH 47/67] History: add "add" --- History.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/History.md b/History.md index 80a2a9a..b867c81 100644 --- a/History.md +++ b/History.md @@ -1,7 +1,7 @@ 1.4.0 / 2013-XX-XX ================== - * source map generation + * add source map generation 1.3.2 / 2013-10-18 ================== From 611c1c9e5f20e086f39086e9a20ed3721e62fe23 Mon Sep 17 00:00:00 2001 From: Andrey Popp <8mayday@gmail.com> Date: Wed, 27 Nov 2013 22:25:08 +0400 Subject: [PATCH 48/67] Readme: wording --- Readme.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Readme.md b/Readme.md index bfc4947..f14a81b 100644 --- a/Readme.md +++ b/Readme.md @@ -13,11 +13,11 @@ var str = stringify(ast); -To get compressed output: +To get compressed output pass `compress` option: var compressed = stringify(ast, {compress: true}); -To get a source map: +To get a source map pass `sourcemap` option: var ast = parse('body { font-size: 12px; }', {position: true}); var result = stringify(ast, {sourcemap: true}); @@ -25,8 +25,8 @@ To get a source map: result.code // string with CSS result.map // source map -Note that the AST should contain position information (`position` option set to -`true`). +Note that the AST should contain position information (`position` option of +`css-parse` set to `true`). ## Performance From facc12e063e0036b20b9bb497bc44da5eeb0333e Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Wed, 27 Nov 2013 10:31:06 -0800 Subject: [PATCH 49/67] tweak docs a bit --- Readme.md | 37 +++++++++++++++++++++---------------- index.js | 13 +++++-------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/Readme.md b/Readme.md index f14a81b..809201b 100644 --- a/Readme.md +++ b/Readme.md @@ -2,31 +2,36 @@ CSS compiler using the AST provided by [css-parse](https://github.com/visionmedia/css-parse). -## Usage +## API -`css-stringify` exports a single function which dumps CSS AST: +### stringify(object, [options]) - var stringify = require('css-stringify'); - var parse = require('css-parse'); + Accepts an AST `object` from css-parse and returns a CSS string. - var ast = parse('body { font-size: 12px; }'); +```js +var stringify = require('css-stringify'); +var parse = require('css-parse'); - var str = stringify(ast); +var ast = parse('body { font-size: 12px; }'); +var css = stringify(ast); +``` -To get compressed output pass `compress` option: + Optionally you may `compress` the output: - var compressed = stringify(ast, {compress: true}); +```js +var css = stringify(ast, { compress: true }); +``` -To get a source map pass `sourcemap` option: + Or return a `sourcemap` along with the CSS output, + which requires the use of the css-parse `position` option. - var ast = parse('body { font-size: 12px; }', {position: true}); - var result = stringify(ast, {sourcemap: true}); +```js +var ast = parse('body { font-size: 12px; }', { position: true }); +var result = stringify(ast, { sourcemap: true }); - result.code // string with CSS - result.map // source map - -Note that the AST should contain position information (`position` option of -`css-parse` set to `true`). +result.code // string with CSS +result.map // source map +``` ## Performance diff --git a/index.js b/index.js index 85394fe..7c3dbc4 100644 --- a/index.js +++ b/index.js @@ -9,16 +9,13 @@ var Identity = require('./lib/identity'); /** * Stringfy the given AST `node`. * + * Options: + * + * - `compress` space-optimized output + * - `sourcemap` return an object with `.code` and `.map` + * * @param {Object} node * @param {Object} [options] - * @param {Boolean} [options.sourcemap] generate source map, - * if set to true this will change return value to - * `{code: '...', map: {...}}`, `node` argument should contain - * position information (e.g. parsed by css-parse with - * `position` option set to `true`) - * @param {Boolean} [options.compress] compress output (ignores indent option) - * @param {String} [options.indent] a string used for indents (defaults to 2 spaces) - * * @return {String} * @api public */ From 3d6cc47625f5c5fe6b6a93049ed75c92a5fefbcf Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Wed, 27 Nov 2013 10:31:29 -0800 Subject: [PATCH 50/67] Release 1.4.0 --- component.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/component.json b/component.json index c4f438a..6bc2bbe 100644 --- a/component.json +++ b/component.json @@ -1,7 +1,7 @@ { "name": "css-stringify", "repo": "visionmedia/css-stringify", - "version": "1.3.2", + "version": "1.4.0", "description": "CSS compiler", "keywords": ["css", "stringify", "stylesheet"], "scripts": [ diff --git a/package.json b/package.json index 1dfe90c..fc1724e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "css-stringify", - "version": "1.3.2", + "version": "1.4.0", "description": "CSS compiler", "keywords": [ "css", From 9669f8f85f7925bec08d54924647a7413c4ec922 Mon Sep 17 00:00:00 2001 From: "Andrey A.I. Sitnik" Date: Mon, 9 Dec 2013 09:59:20 +0100 Subject: [PATCH 51/67] Add missing files to component.json --- component.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/component.json b/component.json index 6bc2bbe..00aebda 100644 --- a/component.json +++ b/component.json @@ -7,6 +7,8 @@ "scripts": [ "index.js", "lib/compress.js", - "lib/identity.js" + "lib/identity.js", + "lib/compiler.js", + "lib/source-map-support.js" ] } From 74a42f06087891273274acf2e30065ee9454bd66 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Mon, 9 Dec 2013 09:07:42 -0800 Subject: [PATCH 52/67] Release 1.4.1 --- History.md | 6 ++++++ component.json | 2 +- package.json | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index b867c81..6a916b8 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,9 @@ + +1.4.1 / 2013-12-09 +================== + + * add missing files to component.json + 1.4.0 / 2013-XX-XX ================== diff --git a/component.json b/component.json index 00aebda..ca5cb38 100644 --- a/component.json +++ b/component.json @@ -1,7 +1,7 @@ { "name": "css-stringify", "repo": "visionmedia/css-stringify", - "version": "1.4.0", + "version": "1.4.1", "description": "CSS compiler", "keywords": ["css", "stringify", "stylesheet"], "scripts": [ diff --git a/package.json b/package.json index fc1724e..3e34ece 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "css-stringify", - "version": "1.4.0", + "version": "1.4.1", "description": "CSS compiler", "keywords": [ "css", From 324da12bc004e0ee9b2470d401637b0873f262cc Mon Sep 17 00:00:00 2001 From: Jonathan Ong Date: Thu, 2 Jan 2014 14:26:38 -0800 Subject: [PATCH 53/67] Update component.json --- component.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/component.json b/component.json index ca5cb38..816685f 100644 --- a/component.json +++ b/component.json @@ -1,6 +1,6 @@ { "name": "css-stringify", - "repo": "visionmedia/css-stringify", + "repo": "reworkcss/css-stringify", "version": "1.4.1", "description": "CSS compiler", "keywords": ["css", "stringify", "stylesheet"], From 84a56af9ea915b997e70c4c2af0fd1dd4e08dda8 Mon Sep 17 00:00:00 2001 From: shinnn Date: Mon, 10 Feb 2014 10:03:26 +0900 Subject: [PATCH 54/67] Fix repository URL --- Readme.md | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Readme.md b/Readme.md index 809201b..8b691c9 100644 --- a/Readme.md +++ b/Readme.md @@ -1,4 +1,4 @@ -# css-stringify [![Build Status](https://travis-ci.org/visionmedia/css-stringify.png)](https://travis-ci.org/visionmedia/css-stringify) +# css-stringify [![Build Status](https://travis-ci.org/reworkcss/css-stringify.png)](https://travis-ci.org/reworkcss/css-stringify) CSS compiler using the AST provided by [css-parse](https://github.com/visionmedia/css-parse). diff --git a/package.json b/package.json index 3e34ece..d1771a7 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "main": "index", "repository": { "type": "git", - "url": "https://github.com/visionmedia/css-stringify.git" + "url": "https://github.com/reworkcss/css-stringify.git" }, "scripts": { "test": "make test" From 89c7ca84a9870f71f3794eaf292a5bde0d33f795 Mon Sep 17 00:00:00 2001 From: Eric Ferraiuolo Date: Wed, 12 Mar 2014 13:09:52 -0400 Subject: [PATCH 55/67] Add support for @font-face, which should not be considered a selector This change stringifies `@font-face` at-rules, instead of treating them as a standard rule with `@font-face` being the selector. Relates reworkcss/css-parse#75 --- lib/compress.js | 11 +++++++++++ lib/identity.js | 13 +++++++++++++ test/cases/font-face.compressed.css | 1 + test/cases/font-face.css | 8 ++++++++ 4 files changed, 33 insertions(+) create mode 100644 test/cases/font-face.compressed.css create mode 100644 test/cases/font-face.css diff --git a/lib/compress.js b/lib/compress.js index 601bd73..c1309f0 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -144,6 +144,17 @@ Compiler.prototype.page = function(node){ + this.emit('}'); }; +/** + * Visit font-face node. + */ + +Compiler.prototype['font-face'] = function(node){ + return this.emit('@font-face', node.position, true) + + this.emit('{') + + this.mapVisit(node.declarations) + + this.emit('}'); +}; + /** * Visit rule node. */ diff --git a/lib/identity.js b/lib/identity.js index cc9fd5c..f20c4b9 100644 --- a/lib/identity.js +++ b/lib/identity.js @@ -174,6 +174,19 @@ Compiler.prototype.page = function(node){ + this.emit('\n}'); }; +/** + * Visit font-face node. + */ + +Compiler.prototype['font-face'] = function(node){ + return this.emit('@font-face ', node.position, true) + + this.emit('{\n') + + this.emit(this.indent(1)) + + this.mapVisit(node.declarations, '\n') + + this.emit(this.indent(-1)) + + this.emit('\n}'); +}; + /** * Visit rule node. */ diff --git a/test/cases/font-face.compressed.css b/test/cases/font-face.compressed.css new file mode 100644 index 0000000..b08d099 --- /dev/null +++ b/test/cases/font-face.compressed.css @@ -0,0 +1 @@ +@font-face{font-family:"Bitstream Vera Serif Bold";src:url("http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf");}body{font-family:"Bitstream Vera Serif Bold", serif;} diff --git a/test/cases/font-face.css b/test/cases/font-face.css new file mode 100644 index 0000000..09945e6 --- /dev/null +++ b/test/cases/font-face.css @@ -0,0 +1,8 @@ +@font-face { + font-family: "Bitstream Vera Serif Bold"; + src: url("http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf"); +} + +body { + font-family: "Bitstream Vera Serif Bold", serif; +} From f73fd3ab813ff8c53f4086b411fd28e7da1caf25 Mon Sep 17 00:00:00 2001 From: Conrad Zimmerman Date: Fri, 23 May 2014 17:09:16 -0400 Subject: [PATCH 56/67] Embed source file content in source map Depends on latest css-stringify git master --- lib/source-map-support.js | 10 ++++++++-- test/css-stringify.js | 2 ++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/source-map-support.js b/lib/source-map-support.js index 1e60513..863690a 100644 --- a/lib/source-map-support.js +++ b/lib/source-map-support.js @@ -50,9 +50,11 @@ exports.updatePosition = function(str) { */ exports.emit = function(str, pos, startOnly) { + var sourceFile = pos && pos.source || 'source.css'; + if (pos && pos.start) { this.map.addMapping({ - source: pos.source || 'source.css', + source: sourceFile, generated: { line: this.position.line, column: Math.max(this.position.column - 1, 0) @@ -62,13 +64,15 @@ exports.emit = function(str, pos, startOnly) { column: pos.start.column - 1 } }); + + this.map.setSourceContent(sourceFile, pos.content || ''); } this.updatePosition(str); if (!startOnly && pos && pos.end) { this.map.addMapping({ - source: pos.source || 'source.css', + source: sourceFile, generated: { line: this.position.line, column: Math.max(this.position.column - 1, 0) @@ -78,6 +82,8 @@ exports.emit = function(str, pos, startOnly) { column: pos.end.column - 1 } }); + + this.map.setSourceContent(sourceFile, pos.content || ''); } return str; diff --git a/test/css-stringify.js b/test/css-stringify.js index b37ee7f..7eda331 100644 --- a/test/css-stringify.js +++ b/test/css-stringify.js @@ -54,6 +54,7 @@ describe('stringify(obj, {sourcemap: true})', function(){ map.originalPositionFor({ line: 11, column: 0 }).should.eql(locs.mediaBlock); map.originalPositionFor({ line: 12, column: 2 }).should.eql(locs.mediaOnly); map.originalPositionFor({ line: 17, column: 0 }).should.eql(locs.comment); + map.sourceContentFor('rules.css').should.eql(src); }); it('should generate source maps alongside when using compress compiler', function(){ @@ -66,5 +67,6 @@ describe('stringify(obj, {sourcemap: true})', function(){ map.originalPositionFor({ line: 1, column: 10 }).should.eql(locs.tobiNameValue); map.originalPositionFor({ line: 1, column: 50 }).should.eql(locs.mediaBlock); map.originalPositionFor({ line: 1, column: 64 }).should.eql(locs.mediaOnly); + map.sourceContentFor('rules.css').should.eql(src); }); }); From 72ced9d236cfde75611607fba35e9ab2e9c4ab9b Mon Sep 17 00:00:00 2001 From: Nicolas Gallagher Date: Wed, 28 May 2014 10:47:20 -0700 Subject: [PATCH 57/67] Fix path to css-parse in Readme --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 8b691c9..8d297fd 100644 --- a/Readme.md +++ b/Readme.md @@ -1,6 +1,6 @@ # css-stringify [![Build Status](https://travis-ci.org/reworkcss/css-stringify.png)](https://travis-ci.org/reworkcss/css-stringify) - CSS compiler using the AST provided by [css-parse](https://github.com/visionmedia/css-parse). + CSS compiler using the AST provided by [css-parse](https://github.com/reworkcss/css-parse). ## API From 8c63bd14eadba5dc3e62418fac93739040e6ad03 Mon Sep 17 00:00:00 2001 From: Conrad Zimmerman Date: Sat, 24 May 2014 11:33:23 -0400 Subject: [PATCH 58/67] Apply original source maps from source files --- index.js | 2 +- lib/source-map-support.js | 47 +++++++++++++++++++++++++++++++++++++-- package.json | 3 ++- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/index.js b/index.js index 7c3dbc4..ccd4204 100644 --- a/index.js +++ b/index.js @@ -33,10 +33,10 @@ module.exports = function(node, options){ sourcemaps(compiler); var code = compiler.compile(node); + compiler.applySourceMaps(); return { code: code, map: compiler.map.toJSON() }; } var code = compiler.compile(node); return code; }; - diff --git a/lib/source-map-support.js b/lib/source-map-support.js index 863690a..0295818 100644 --- a/lib/source-map-support.js +++ b/lib/source-map-support.js @@ -4,6 +4,9 @@ */ var SourceMap = require('source-map').SourceMapGenerator; +var SourceMapConsumer = require('source-map').SourceMapConsumer; +var sourceMapResolve = require('source-map-resolve'); +var fs = require('fs'); /** * Expose `mixin()`. @@ -20,8 +23,10 @@ module.exports = mixin; function mixin(compiler) { var file = compiler.options.filename || 'generated.css'; + compiler._comment = compiler.comment; compiler.map = new SourceMap({ file: file }); compiler.position = { line: 1, column: 1 }; + compiler.files = {}; for (var k in exports) compiler[k] = exports[k]; } @@ -65,7 +70,7 @@ exports.emit = function(str, pos, startOnly) { } }); - this.map.setSourceContent(sourceFile, pos.content || ''); + this.addFile(pos); } this.updatePosition(str); @@ -83,8 +88,46 @@ exports.emit = function(str, pos, startOnly) { } }); - this.map.setSourceContent(sourceFile, pos.content || ''); + this.addFile(pos); } return str; }; + +/** + * Adds a file to the source map output if it has not already been added + * @param {Object} pos + */ + +exports.addFile = function(pos) { + var file = pos.source || 'source.css'; + if (this.files.hasOwnProperty(file)) return; + this.files[file] = pos.content; +}; + +/** + * Applies any original source maps to the output. + */ + +exports.applySourceMaps = function() { + for (var file in this.files) { + var originalMap = sourceMapResolve.resolveSync( + this.files[file], file, fs.readFileSync); + if (originalMap) { + originalMap = new SourceMapConsumer(originalMap.map); + this.map.applySourceMap(originalMap, file); + } + } +}; + +/** + * Process comments, drops sourceMap comments. + * @param {Object} node + */ + +exports.comment = function(node) { + if (/^# sourceMappingURL=/.test(node.comment)) + return this.emit('', node.position); + else + return this._comment(node); +}; diff --git a/package.json b/package.json index d1771a7..8803ce7 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "test": "make test" }, "dependencies": { - "source-map": "~0.1.31" + "source-map": "~0.1.31", + "source-map-resolve": "^0.1.3" } } From be22c403e45e855196a504dacd37d6f54cc4cf31 Mon Sep 17 00:00:00 2001 From: Conrad Zimmerman Date: Sat, 24 May 2014 13:13:06 -0400 Subject: [PATCH 59/67] Add tests for applying source maps and refactor --- lib/source-map-support.js | 7 ++++--- test/cases/source-map-apply.scss | 0 test/css-stringify.js | 24 ++++++++++++++++++++++++ test/source-map-apply.css | 4 ++++ test/source-map-apply.css.map | 7 +++++++ test/source-map-apply.scss | 1 + 6 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 test/cases/source-map-apply.scss create mode 100644 test/source-map-apply.css create mode 100644 test/source-map-apply.css.map create mode 100644 test/source-map-apply.scss diff --git a/lib/source-map-support.js b/lib/source-map-support.js index 0295818..8ae8c53 100644 --- a/lib/source-map-support.js +++ b/lib/source-map-support.js @@ -101,7 +101,8 @@ exports.emit = function(str, pos, startOnly) { exports.addFile = function(pos) { var file = pos.source || 'source.css'; - if (this.files.hasOwnProperty(file)) return; + if (Object.prototype.hasOwnProperty.call(this.files, file)) return; + if (typeof pos.content !== 'string') return; this.files[file] = pos.content; }; @@ -110,14 +111,14 @@ exports.addFile = function(pos) { */ exports.applySourceMaps = function() { - for (var file in this.files) { + Object.keys(this.files).forEach(function(file) { var originalMap = sourceMapResolve.resolveSync( this.files[file], file, fs.readFileSync); if (originalMap) { originalMap = new SourceMapConsumer(originalMap.map); this.map.applySourceMap(originalMap, file); } - } + }, this); }; /** diff --git a/test/cases/source-map-apply.scss b/test/cases/source-map-apply.scss new file mode 100644 index 0000000..e69de29 diff --git a/test/css-stringify.js b/test/css-stringify.js index 7eda331..4c58826 100644 --- a/test/css-stringify.js +++ b/test/css-stringify.js @@ -69,4 +69,28 @@ describe('stringify(obj, {sourcemap: true})', function(){ map.originalPositionFor({ line: 1, column: 64 }).should.eql(locs.mediaOnly); map.sourceContentFor('rules.css').should.eql(src); }); + + it('should apply included source maps', function(){ + var file = 'test/source-map-apply.css'; + var src = read(file, 'utf8'); + var stylesheet = parse(src, { source: file, position: true }); + var result = stringify(stylesheet, { sourcemap: true }); + result.should.have.property('code'); + result.should.have.property('map'); + + var map = new SourceMapConsumer(result.map); + map.originalPositionFor({ line: 1, column: 0 }).should.eql({ + column: 0, + line: 1, + name: null, + source: 'source-map-apply.scss' + }); + + map.originalPositionFor({ line: 2, column: 2 }).should.eql({ + column: 7, + line: 1, + name: null, + source: 'source-map-apply.scss' + }); + }); }); diff --git a/test/source-map-apply.css b/test/source-map-apply.css new file mode 100644 index 0000000..5f11212 --- /dev/null +++ b/test/source-map-apply.css @@ -0,0 +1,4 @@ +tobi { + name: 'tobi'; } + +/*# sourceMappingURL=source-map-apply.css.map */ \ No newline at end of file diff --git a/test/source-map-apply.css.map b/test/source-map-apply.css.map new file mode 100644 index 0000000..066c1f5 --- /dev/null +++ b/test/source-map-apply.css.map @@ -0,0 +1,7 @@ +{ + "version": 3, + "file": "", + "sources": ["source-map-apply.scss"], + "names": [], + "mappings": "AAAA;EAAO,MAAM" +} \ No newline at end of file diff --git a/test/source-map-apply.scss b/test/source-map-apply.scss new file mode 100644 index 0000000..7ad3ef5 --- /dev/null +++ b/test/source-map-apply.scss @@ -0,0 +1 @@ +tobi { name: 'tobi'; } From b7bf89ae097fb4dbde83f02efaec14775c56d83e Mon Sep 17 00:00:00 2001 From: Nicolas Gallagher Date: Wed, 28 May 2014 11:42:19 -0700 Subject: [PATCH 60/67] Remove leftover assertions --- test/css-stringify.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/css-stringify.js b/test/css-stringify.js index 4c58826..32e2474 100644 --- a/test/css-stringify.js +++ b/test/css-stringify.js @@ -54,7 +54,6 @@ describe('stringify(obj, {sourcemap: true})', function(){ map.originalPositionFor({ line: 11, column: 0 }).should.eql(locs.mediaBlock); map.originalPositionFor({ line: 12, column: 2 }).should.eql(locs.mediaOnly); map.originalPositionFor({ line: 17, column: 0 }).should.eql(locs.comment); - map.sourceContentFor('rules.css').should.eql(src); }); it('should generate source maps alongside when using compress compiler', function(){ @@ -67,7 +66,6 @@ describe('stringify(obj, {sourcemap: true})', function(){ map.originalPositionFor({ line: 1, column: 10 }).should.eql(locs.tobiNameValue); map.originalPositionFor({ line: 1, column: 50 }).should.eql(locs.mediaBlock); map.originalPositionFor({ line: 1, column: 64 }).should.eql(locs.mediaOnly); - map.sourceContentFor('rules.css').should.eql(src); }); it('should apply included source maps', function(){ From e809b04eacdeea702709cfd40fc419f848b924ab Mon Sep 17 00:00:00 2001 From: Nicolas Gallagher Date: Wed, 28 May 2014 11:00:19 -0700 Subject: [PATCH 61/67] Add support for @host --- History.md | 20 ++++++++++---------- lib/compress.js | 11 +++++++++++ lib/identity.js | 15 +++++++++++++++ test/cases/host.compressed.css | 1 + test/cases/host.css | 5 +++++ 5 files changed, 42 insertions(+), 10 deletions(-) create mode 100644 test/cases/host.compressed.css create mode 100644 test/cases/host.css diff --git a/History.md b/History.md index 6a916b8..a35765a 100644 --- a/History.md +++ b/History.md @@ -9,20 +9,20 @@ * add source map generation -1.3.2 / 2013-10-18 +1.3.2 / 2013-10-18 ================== * fix whitespace and indentation in the Compressed compiler. * add @namespace support * add .stylesheet(node) -1.3.1 / 2013-06-02 +1.3.1 / 2013-06-02 ================== * fix output of rules with no declarations for Identity compiler * fix defaulting of options -1.3.0 / 2013-05-28 +1.3.0 / 2013-05-28 ================== * add ignoring of empty rulesets. Closes #7 @@ -33,38 +33,38 @@ * fix trailing ; with comments within rules * fix comment indentation -1.2.0 / 2013-05-21 +1.2.0 / 2013-05-21 ================== * add @document compilation. Closes #82 -1.1.0 / 2013-03-19 +1.1.0 / 2013-03-19 ================== * add omission of comments when compressed * add comment support -1.0.5 / 2013-03-15 +1.0.5 / 2013-03-15 ================== * fix indentation of multiple selectors in @media. Closes #11 -1.0.4 / 2012-11-15 +1.0.4 / 2012-11-15 ================== * fix indentation -1.0.3 / 2012-09-04 +1.0.3 / 2012-09-04 ================== * add __@charset__ support [rstacruz] -1.0.2 / 2012-09-01 +1.0.2 / 2012-09-01 ================== * add component support -1.0.1 / 2012-07-26 +1.0.1 / 2012-07-26 ================== * add "selectors" array support diff --git a/lib/compress.js b/lib/compress.js index c1309f0..98c105a 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -155,6 +155,17 @@ Compiler.prototype['font-face'] = function(node){ + this.emit('}'); }; +/** + * Visit host node. + */ + +Compiler.prototype.host = function(node){ + return this.emit('@host', node.position, true) + + this.emit('{') + + this.mapVisit(node.rules) + + this.emit('}'); +}; + /** * Visit rule node. */ diff --git a/lib/identity.js b/lib/identity.js index f20c4b9..2dc891b 100644 --- a/lib/identity.js +++ b/lib/identity.js @@ -187,6 +187,21 @@ Compiler.prototype['font-face'] = function(node){ + this.emit('\n}'); }; +/** + * Visit host node. + */ + +Compiler.prototype.host = function(node){ + return this.emit('@host', node.position, true) + + this.emit( + ' {\n' + + this.indent(1)) + + this.mapVisit(node.rules, '\n\n') + + this.emit( + this.indent(-1) + + '\n}'); +}; + /** * Visit rule node. */ diff --git a/test/cases/host.compressed.css b/test/cases/host.compressed.css new file mode 100644 index 0000000..509667c --- /dev/null +++ b/test/cases/host.compressed.css @@ -0,0 +1 @@ +@host{:scope{display:block;}} diff --git a/test/cases/host.css b/test/cases/host.css new file mode 100644 index 0000000..0ec989c --- /dev/null +++ b/test/cases/host.css @@ -0,0 +1,5 @@ +@host { + :scope { + display: block; + } +} From f38a30fd9bb1f873ae12a124c6cd94fc5fdd9dba Mon Sep 17 00:00:00 2001 From: Nicolas Gallagher Date: Wed, 28 May 2014 11:15:17 -0700 Subject: [PATCH 62/67] Add support for @custom-media Fix #34 --- lib/compress.js | 8 ++++++++ lib/identity.js | 8 ++++++++ package.json | 2 +- test/cases/custom-media.css | 1 + 4 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 test/cases/custom-media.css diff --git a/lib/compress.js b/lib/compress.js index 98c105a..bdd5f1f 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -166,6 +166,14 @@ Compiler.prototype.host = function(node){ + this.emit('}'); }; +/** + * Visit custom-media node. + */ + +Compiler.prototype['custom-media'] = function(node){ + return this.emit('@custom-media ' + node.name + ' ' + node.media + ';', node.position); +}; + /** * Visit rule node. */ diff --git a/lib/identity.js b/lib/identity.js index 2dc891b..9c8d3c9 100644 --- a/lib/identity.js +++ b/lib/identity.js @@ -202,6 +202,14 @@ Compiler.prototype.host = function(node){ + '\n}'); }; +/** + * Visit custom-media node. + */ + +Compiler.prototype['custom-media'] = function(node){ + return this.emit('@custom-media ' + node.name + ' ' + node.media + ';', node.position); +}; + /** * Visit rule node. */ diff --git a/package.json b/package.json index 8803ce7..a3139a3 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "devDependencies": { "mocha": "*", "should": "*", - "css-parse": "1.6.0" + "css-parse": "git://github.com/reworkcss/css-parse.git#7cef3658d0bba872cde05a85339034b187cb3397" }, "main": "index", "repository": { diff --git a/test/cases/custom-media.css b/test/cases/custom-media.css new file mode 100644 index 0000000..035deba --- /dev/null +++ b/test/cases/custom-media.css @@ -0,0 +1 @@ +@custom-media --wide-window screen and (min-width: 40em); From 3cfdda9cbae4a2a0049d941103b1d7fbd0c3e032 Mon Sep 17 00:00:00 2001 From: Nicolas Gallagher Date: Wed, 28 May 2014 11:49:14 -0700 Subject: [PATCH 63/67] Remove Component(1) support Source maps support required the removal of client-side support. Not very useful on the client-side anyway. --- component.json | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 component.json diff --git a/component.json b/component.json deleted file mode 100644 index 816685f..0000000 --- a/component.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "css-stringify", - "repo": "reworkcss/css-stringify", - "version": "1.4.1", - "description": "CSS compiler", - "keywords": ["css", "stringify", "stylesheet"], - "scripts": [ - "index.js", - "lib/compress.js", - "lib/identity.js", - "lib/compiler.js", - "lib/source-map-support.js" - ] -} From 87d69941b6ba685ddb01bae71302bf03e4a9dcdd Mon Sep 17 00:00:00 2001 From: Conrad Zimmerman Date: Mon, 2 Jun 2014 16:33:20 -0400 Subject: [PATCH 64/67] Fix embedding source file contents in source maps and add tests Somehow these had been added in #33 but lost in a later merge. --- lib/source-map-support.js | 19 ++++++++++++------- test/css-stringify.js | 9 ++++++--- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/lib/source-map-support.js b/lib/source-map-support.js index 8ae8c53..528f426 100644 --- a/lib/source-map-support.js +++ b/lib/source-map-support.js @@ -70,7 +70,7 @@ exports.emit = function(str, pos, startOnly) { } }); - this.addFile(pos); + this.addFile(sourceFile, pos); } this.updatePosition(str); @@ -88,7 +88,7 @@ exports.emit = function(str, pos, startOnly) { } }); - this.addFile(pos); + this.addFile(sourceFile, pos); } return str; @@ -96,24 +96,29 @@ exports.emit = function(str, pos, startOnly) { /** * Adds a file to the source map output if it has not already been added + * @param {String} file * @param {Object} pos */ -exports.addFile = function(pos) { - var file = pos.source || 'source.css'; - if (Object.prototype.hasOwnProperty.call(this.files, file)) return; +exports.addFile = function(file, pos) { if (typeof pos.content !== 'string') return; + if (Object.prototype.hasOwnProperty.call(this.files, file)) return; + this.files[file] = pos.content; }; /** - * Applies any original source maps to the output. + * Applies any original source maps to the output and embeds the source file + * contents in the source map. */ exports.applySourceMaps = function() { Object.keys(this.files).forEach(function(file) { + var content = this.files[file]; + this.map.setSourceContent(file, content); + var originalMap = sourceMapResolve.resolveSync( - this.files[file], file, fs.readFileSync); + content, file, fs.readFileSync); if (originalMap) { originalMap = new SourceMapConsumer(originalMap.map); this.map.applySourceMap(originalMap, file); diff --git a/test/css-stringify.js b/test/css-stringify.js index 32e2474..d917005 100644 --- a/test/css-stringify.js +++ b/test/css-stringify.js @@ -28,10 +28,11 @@ describe('stringify(obj)', function(){ }); describe('stringify(obj, {sourcemap: true})', function(){ - var src = read('test/source-map-case.css', 'utf8'); - var stylesheet = parse(src, { source: 'rules.css', position: true }); + var file = 'test/source-map-case.css'; + var src = read(file, 'utf8'); + var stylesheet = parse(src, { source: file, position: true }); function loc(line, column) { - return { line: line, column: column, source: 'rules.css', name: null } + return { line: line, column: column, source: file, name: null } }; var locs = { @@ -54,6 +55,7 @@ describe('stringify(obj, {sourcemap: true})', function(){ map.originalPositionFor({ line: 11, column: 0 }).should.eql(locs.mediaBlock); map.originalPositionFor({ line: 12, column: 2 }).should.eql(locs.mediaOnly); map.originalPositionFor({ line: 17, column: 0 }).should.eql(locs.comment); + map.sourceContentFor(file).should.eql(src); }); it('should generate source maps alongside when using compress compiler', function(){ @@ -66,6 +68,7 @@ describe('stringify(obj, {sourcemap: true})', function(){ map.originalPositionFor({ line: 1, column: 10 }).should.eql(locs.tobiNameValue); map.originalPositionFor({ line: 1, column: 50 }).should.eql(locs.mediaBlock); map.originalPositionFor({ line: 1, column: 64 }).should.eql(locs.mediaOnly); + map.sourceContentFor(file).should.eql(src); }); it('should apply included source maps', function(){ From 2180c2e17ab5a23a844a534473afd3bbf0dff809 Mon Sep 17 00:00:00 2001 From: Nicolas Gallagher Date: Wed, 4 Jun 2014 14:41:34 -0700 Subject: [PATCH 65/67] Depend on 'css' and remove migrated code All the stringify code and tests are now part of the 'css' package. From now on, 'css-stringify' will merely export the `stringify` method of 'css'. Recommended that you depend on 'css' directly. --- .gitignore | 2 - .npmignore | 6 - .travis.yml | 3 - History.md | 4 + Makefile | 8 - Readme.md | 62 +------ examples/comments.css | 8 - examples/comments.js | 12 -- examples/dialog.css | 92 ---------- examples/dialog.js | 12 -- examples/document.css | 17 -- examples/document.js | 12 -- examples/empty.css | 4 - examples/empty.js | 12 -- examples/keyframes.css | 10 -- examples/keyframes.js | 12 -- examples/media.css | 27 --- examples/media.js | 12 -- examples/page.css | 8 - examples/page.js | 12 -- examples/sourcemaps.js | 12 -- index.js | 43 +---- lib/compiler.js | 50 ------ lib/compress.js | 198 ---------------------- lib/identity.js | 253 ---------------------------- lib/source-map-support.js | 139 --------------- package.json | 29 ++-- test/cases/at_charset.css | 1 - test/cases/at_namespace.css | 1 - test/cases/comments.compressed.css | 1 - test/cases/comments.css | 8 - test/cases/custom-media.css | 1 - test/cases/document.compressed.css | 1 - test/cases/document.css | 17 -- test/cases/font-face.compressed.css | 1 - test/cases/font-face.css | 8 - test/cases/host.compressed.css | 1 - test/cases/host.css | 5 - test/cases/import.css | 1 - test/cases/keyframes.compressed.css | 1 - test/cases/keyframes.css | 10 -- test/cases/media.compressed.css | 1 - test/cases/media.css | 23 --- test/cases/page.compressed.css | 1 - test/cases/page.css | 15 -- test/cases/rules.compressed.css | 1 - test/cases/rules.css | 9 - test/cases/selectors.compressed.css | 1 - test/cases/selectors.css | 5 - test/cases/source-map-apply.scss | 0 test/cases/supports.compressed.css | 1 - test/cases/supports.css | 9 - test/css-stringify.js | 97 ----------- test/source-map-apply.css | 4 - test/source-map-apply.css.map | 7 - test/source-map-apply.scss | 1 - test/source-map-case.css | 17 -- 57 files changed, 24 insertions(+), 1284 deletions(-) delete mode 100644 .npmignore delete mode 100644 .travis.yml delete mode 100644 Makefile delete mode 100644 examples/comments.css delete mode 100644 examples/comments.js delete mode 100644 examples/dialog.css delete mode 100644 examples/dialog.js delete mode 100644 examples/document.css delete mode 100644 examples/document.js delete mode 100644 examples/empty.css delete mode 100644 examples/empty.js delete mode 100644 examples/keyframes.css delete mode 100644 examples/keyframes.js delete mode 100644 examples/media.css delete mode 100644 examples/media.js delete mode 100644 examples/page.css delete mode 100644 examples/page.js delete mode 100644 examples/sourcemaps.js delete mode 100644 lib/compiler.js delete mode 100644 lib/compress.js delete mode 100644 lib/identity.js delete mode 100644 lib/source-map-support.js delete mode 100644 test/cases/at_charset.css delete mode 100644 test/cases/at_namespace.css delete mode 100644 test/cases/comments.compressed.css delete mode 100644 test/cases/comments.css delete mode 100644 test/cases/custom-media.css delete mode 100644 test/cases/document.compressed.css delete mode 100644 test/cases/document.css delete mode 100644 test/cases/font-face.compressed.css delete mode 100644 test/cases/font-face.css delete mode 100644 test/cases/host.compressed.css delete mode 100644 test/cases/host.css delete mode 100644 test/cases/import.css delete mode 100644 test/cases/keyframes.compressed.css delete mode 100644 test/cases/keyframes.css delete mode 100644 test/cases/media.compressed.css delete mode 100644 test/cases/media.css delete mode 100644 test/cases/page.compressed.css delete mode 100644 test/cases/page.css delete mode 100644 test/cases/rules.compressed.css delete mode 100644 test/cases/rules.css delete mode 100644 test/cases/selectors.compressed.css delete mode 100644 test/cases/selectors.css delete mode 100644 test/cases/source-map-apply.scss delete mode 100644 test/cases/supports.compressed.css delete mode 100644 test/cases/supports.css delete mode 100644 test/css-stringify.js delete mode 100644 test/source-map-apply.css delete mode 100644 test/source-map-apply.css.map delete mode 100644 test/source-map-apply.scss delete mode 100644 test/source-map-case.css diff --git a/.gitignore b/.gitignore index 2e7b3f5..3c3629e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1 @@ node_modules -test.css -test.js diff --git a/.npmignore b/.npmignore deleted file mode 100644 index 4a3c398..0000000 --- a/.npmignore +++ /dev/null @@ -1,6 +0,0 @@ -support -test -examples -*.sock -test.css -test.js diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 6e5919d..0000000 --- a/.travis.yml +++ /dev/null @@ -1,3 +0,0 @@ -language: node_js -node_js: - - "0.10" diff --git a/History.md b/History.md index a35765a..934d616 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,7 @@ +HEAD +================== + + * depend on the 'css' package, which now contains the stringifier 1.4.1 / 2013-12-09 ================== diff --git a/Makefile b/Makefile deleted file mode 100644 index d78a055..0000000 --- a/Makefile +++ /dev/null @@ -1,8 +0,0 @@ - -test: - @./node_modules/.bin/mocha \ - --require should \ - --reporter spec \ - --bail - -.PHONY: test diff --git a/Readme.md b/Readme.md index 8d297fd..954623d 100644 --- a/Readme.md +++ b/Readme.md @@ -1,63 +1,15 @@ -# css-stringify [![Build Status](https://travis-ci.org/reworkcss/css-stringify.png)](https://travis-ci.org/reworkcss/css-stringify) +# css-stringify - CSS compiler using the AST provided by [css-parse](https://github.com/reworkcss/css-parse). + JavaScript CSS stringifier for Node.js (exports the `stringify` method of [css](https://github.com/reworkcss/css)) -## API +## Installation -### stringify(object, [options]) + $ npm install css-stringify - Accepts an AST `object` from css-parse and returns a CSS string. +## Usage -```js -var stringify = require('css-stringify'); -var parse = require('css-parse'); - -var ast = parse('body { font-size: 12px; }'); -var css = stringify(ast); -``` - - Optionally you may `compress` the output: - -```js -var css = stringify(ast, { compress: true }); -``` - - Or return a `sourcemap` along with the CSS output, - which requires the use of the css-parse `position` option. - -```js -var ast = parse('body { font-size: 12px; }', { position: true }); -var result = stringify(ast, { sourcemap: true }); - -result.code // string with CSS -result.map // source map -``` - -## Performance - - Formats 15,000 lines of CSS (2mb) in 23ms on my macbook air. + Please see the [css](https://github.com/reworkcss/css) module documentation. ## License -(The MIT License) - -Copyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca> - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + MIT diff --git a/examples/comments.css b/examples/comments.css deleted file mode 100644 index 87e95a3..0000000 --- a/examples/comments.css +++ /dev/null @@ -1,8 +0,0 @@ -/* comment */ - -body { - /* foo */ - /* bar */ - color: #eee; - /* baz */ -} diff --git a/examples/comments.js b/examples/comments.js deleted file mode 100644 index c255105..0000000 --- a/examples/comments.js +++ /dev/null @@ -1,12 +0,0 @@ - -/** - * Module dependencies. - */ - -var parse = require('css-parse') - , stringify = require('..') - , fs = require('fs') - , read = fs.readFileSync - , css = read('examples/comments.css', 'utf8'); - -console.log(stringify(parse(css))); diff --git a/examples/dialog.css b/examples/dialog.css deleted file mode 100644 index df74183..0000000 --- a/examples/dialog.css +++ /dev/null @@ -1,92 +0,0 @@ -#dialog { - position: fixed; - left: 50%; - top: 150px; - max-width: 600px; - min-width: 250px; - border: 1px solid #eee; - background: white; - z-index: 1000; -} - -#dialog .content { - padding: 15px 20px; -} - -#dialog h1 { - margin: 0 0 5px 0; - font-size: 16px; - font-weight: normal; -} - -#dialog p { - margin: 0; - padding: 0; - font-size: .9em; -} - -#dialog.modal { - box-shadow: 0 1px 8px 0 black; -} - -/* close */ - -#dialog .close { - position: absolute; - top: 3px; - right: 10px; - text-decoration: none; - color: #888; - font-size: 16px; - font-weight: bold; - display: none; -} - -#dialog.closable .close { - display: block; -} - -#dialog .close:hover { - color: black; -} - -#dialog .close:active { - margin-top: 1px; -} - -/* slide */ - -#dialog.slide { - -webkit-transition: opacity 300ms, top 300ms; - -moz-transition: opacity 300ms, top 300ms; -} - -#dialog.slide.hide { - opacity: 0; - top: -500px; -} - -/* fade */ - -#dialog.fade { - -webkit-transition: opacity 300ms; - -moz-transition: opacity 300ms; -} - -#dialog.fade.hide { - opacity: 0; -} - -/* scale */ - -#dialog.scale { - -webkit-transition: -webkit-transform 300ms; - -moz-transition: -moz-transform 300ms; - -webkit-transform: scale(1); - -moz-transform: scale(1); -} - -#dialog.scale.hide { - -webkit-transform: scale(0); - -moz-transform: scale(0); -} \ No newline at end of file diff --git a/examples/dialog.js b/examples/dialog.js deleted file mode 100644 index 69cb6fe..0000000 --- a/examples/dialog.js +++ /dev/null @@ -1,12 +0,0 @@ - -/** - * Module dependencies. - */ - -var parse = require('css-parse') - , stringify = require('..') - , fs = require('fs') - , read = fs.readFileSync - , css = read('examples/dialog.css', 'utf8'); - -console.log(stringify(parse(css), { compress: true })); diff --git a/examples/document.css b/examples/document.css deleted file mode 100644 index 7ddf3d6..0000000 --- a/examples/document.css +++ /dev/null @@ -1,17 +0,0 @@ -@-moz-document url-prefix() { - .icon-spin { - height: .9em - } - - .btn .icon-spin { - height: auto - } - - .icon-spin.icon-large { - height: 1.25em - } - - .btn .icon-spin.icon-large { - height: .75em - } -} diff --git a/examples/document.js b/examples/document.js deleted file mode 100644 index 3fc8793..0000000 --- a/examples/document.js +++ /dev/null @@ -1,12 +0,0 @@ - -/** - * Module dependencies. - */ - -var parse = require('css-parse') - , stringify = require('..') - , fs = require('fs') - , read = fs.readFileSync - , css = read('examples/document.css', 'utf8'); - -console.log(stringify(parse(css), { compress: false })); diff --git a/examples/empty.css b/examples/empty.css deleted file mode 100644 index c14f1e9..0000000 --- a/examples/empty.css +++ /dev/null @@ -1,4 +0,0 @@ - -body { - -} diff --git a/examples/empty.js b/examples/empty.js deleted file mode 100644 index 3c32c33..0000000 --- a/examples/empty.js +++ /dev/null @@ -1,12 +0,0 @@ - -/** - * Module dependencies. - */ - -var parse = require('css-parse') - , stringify = require('..') - , fs = require('fs') - , read = fs.readFileSync - , css = read('examples/empty.css', 'utf8'); - -console.log(stringify(parse(css), { compress: true })); diff --git a/examples/keyframes.css b/examples/keyframes.css deleted file mode 100644 index a50d14a..0000000 --- a/examples/keyframes.css +++ /dev/null @@ -1,10 +0,0 @@ -@keyframes fade { - from { - opacity: 0; - opacity: 1 - } - - to { - opacity: 1 - } -} \ No newline at end of file diff --git a/examples/keyframes.js b/examples/keyframes.js deleted file mode 100644 index 7454ff9..0000000 --- a/examples/keyframes.js +++ /dev/null @@ -1,12 +0,0 @@ - -/** - * Module dependencies. - */ - -var parse = require('css-parse') - , stringify = require('..') - , fs = require('fs') - , read = fs.readFileSync - , css = read('examples/keyframes.css', 'utf8'); - -console.log(stringify(parse(css), { compress: true })); diff --git a/examples/media.css b/examples/media.css deleted file mode 100644 index d50e65b..0000000 --- a/examples/media.css +++ /dev/null @@ -1,27 +0,0 @@ - -/* some comment */ - -@media screen, projection { - html { - background: #fffef0; - color: #300; - } - - body { - max-width: 35em; - margin: 0 auto; - } -} - -@media print { - html { - background: #fff; - color: #000; - } - - body, - #content { - padding: 1in; - border: 0.5pt solid #666; - } -} diff --git a/examples/media.js b/examples/media.js deleted file mode 100644 index ec5bcf5..0000000 --- a/examples/media.js +++ /dev/null @@ -1,12 +0,0 @@ - -/** - * Module dependencies. - */ - -var parse = require('css-parse') - , stringify = require('..') - , fs = require('fs') - , read = fs.readFileSync - , css = read('examples/media.css', 'utf8'); - -console.log(stringify(parse(css), { compress: false })); diff --git a/examples/page.css b/examples/page.css deleted file mode 100644 index a413d84..0000000 --- a/examples/page.css +++ /dev/null @@ -1,8 +0,0 @@ -@page { - size: auto; - margin: 10% -} - -@page foo, bar { - bar: baz -} diff --git a/examples/page.js b/examples/page.js deleted file mode 100644 index 1d402aa..0000000 --- a/examples/page.js +++ /dev/null @@ -1,12 +0,0 @@ - -/** - * Module dependencies. - */ - -var parse = require('css-parse') - , stringify = require('..') - , fs = require('fs') - , read = fs.readFileSync - , css = read('examples/page.css', 'utf8'); - -console.log(stringify(parse(css), { compress: false })); diff --git a/examples/sourcemaps.js b/examples/sourcemaps.js deleted file mode 100644 index ef1fe4b..0000000 --- a/examples/sourcemaps.js +++ /dev/null @@ -1,12 +0,0 @@ - -/** - * Module dependencies. - */ - -var parse = require('css-parse') - , stringify = require('..') - , fs = require('fs') - , read = fs.readFileSync - , css = read('examples/media.css', 'utf8'); - -console.log(stringify(parse(css), { compress: false, sourcemap: true })); diff --git a/index.js b/index.js index ccd4204..b4c1752 100644 --- a/index.js +++ b/index.js @@ -1,42 +1 @@ - -/** - * Module dependencies. - */ - -var Compressed = require('./lib/compress'); -var Identity = require('./lib/identity'); - -/** - * Stringfy the given AST `node`. - * - * Options: - * - * - `compress` space-optimized output - * - `sourcemap` return an object with `.code` and `.map` - * - * @param {Object} node - * @param {Object} [options] - * @return {String} - * @api public - */ - -module.exports = function(node, options){ - options = options || {}; - - var compiler = options.compress - ? new Compressed(options) - : new Identity(options); - - // source maps - if (options.sourcemap) { - var sourcemaps = require('./lib/source-map-support'); - sourcemaps(compiler); - - var code = compiler.compile(node); - compiler.applySourceMaps(); - return { code: code, map: compiler.map.toJSON() }; - } - - var code = compiler.compile(node); - return code; -}; +module.exports = require('css').stringify; diff --git a/lib/compiler.js b/lib/compiler.js deleted file mode 100644 index 6d01a14..0000000 --- a/lib/compiler.js +++ /dev/null @@ -1,50 +0,0 @@ - -/** - * Expose `Compiler`. - */ - -module.exports = Compiler; - -/** - * Initialize a compiler. - * - * @param {Type} name - * @return {Type} - * @api public - */ - -function Compiler(opts) { - this.options = opts || {}; -} - -/** - * Emit `str` - */ - -Compiler.prototype.emit = function(str) { - return str; -}; - -/** - * Visit `node`. - */ - -Compiler.prototype.visit = function(node){ - return this[node.type](node); -}; - -/** - * Map visit over array of `nodes`, optionally using a `delim` - */ - -Compiler.prototype.mapVisit = function(nodes, delim){ - var buf = ''; - delim = delim || ''; - - for (var i = 0, length = nodes.length; i < length; i++) { - buf += this.visit(nodes[i]); - if (delim && i < length - 1) buf += this.emit(delim); - } - - return buf; -}; diff --git a/lib/compress.js b/lib/compress.js deleted file mode 100644 index bdd5f1f..0000000 --- a/lib/compress.js +++ /dev/null @@ -1,198 +0,0 @@ - -/** - * Module dependencies. - */ - -var Base = require('./compiler'); - -/** - * Expose compiler. - */ - -module.exports = Compiler; - -/** - * Initialize a new `Compiler`. - */ - -function Compiler(options) { - Base.call(this, options); -} - -/** - * Inherit from `Base.prototype`. - */ - -Compiler.prototype.__proto__ = Base.prototype; - -/** - * Compile `node`. - */ - -Compiler.prototype.compile = function(node){ - return node.stylesheet - .rules.map(this.visit, this) - .join(''); -}; - -/** - * Visit comment node. - */ - -Compiler.prototype.comment = function(node){ - return this.emit('', node.position); -}; - -/** - * Visit import node. - */ - -Compiler.prototype.import = function(node){ - return this.emit('@import ' + node.import + ';', node.position); -}; - -/** - * Visit media node. - */ - -Compiler.prototype.media = function(node){ - return this.emit('@media ' + node.media, node.position, true) - + this.emit('{') - + this.mapVisit(node.rules) - + this.emit('}'); -}; - -/** - * Visit document node. - */ - -Compiler.prototype.document = function(node){ - var doc = '@' + (node.vendor || '') + 'document ' + node.document; - - return this.emit(doc, node.position, true) - + this.emit('{') - + this.mapVisit(node.rules) - + this.emit('}'); -}; - -/** - * Visit charset node. - */ - -Compiler.prototype.charset = function(node){ - return this.emit('@charset ' + node.charset + ';', node.position); -}; - -/** - * Visit namespace node. - */ - -Compiler.prototype.namespace = function(node){ - return this.emit('@namespace ' + node.namespace + ';', node.position); -}; - -/** - * Visit supports node. - */ - -Compiler.prototype.supports = function(node){ - return this.emit('@supports ' + node.supports, node.position, true) - + this.emit('{') - + this.mapVisit(node.rules) - + this.emit('}'); -}; - -/** - * Visit keyframes node. - */ - -Compiler.prototype.keyframes = function(node){ - return this.emit('@' - + (node.vendor || '') - + 'keyframes ' - + node.name, node.position, true) - + this.emit('{') - + this.mapVisit(node.keyframes) - + this.emit('}'); -}; - -/** - * Visit keyframe node. - */ - -Compiler.prototype.keyframe = function(node){ - var decls = node.declarations; - - return this.emit(node.values.join(','), node.position, true) - + this.emit('{') - + this.mapVisit(decls) - + this.emit('}'); -}; - -/** - * Visit page node. - */ - -Compiler.prototype.page = function(node){ - var sel = node.selectors.length - ? node.selectors.join(', ') - : ''; - - return this.emit('@page ' + sel, node.position, true) - + this.emit('{') - + this.mapVisit(node.declarations) - + this.emit('}'); -}; - -/** - * Visit font-face node. - */ - -Compiler.prototype['font-face'] = function(node){ - return this.emit('@font-face', node.position, true) - + this.emit('{') - + this.mapVisit(node.declarations) - + this.emit('}'); -}; - -/** - * Visit host node. - */ - -Compiler.prototype.host = function(node){ - return this.emit('@host', node.position, true) - + this.emit('{') - + this.mapVisit(node.rules) - + this.emit('}'); -}; - -/** - * Visit custom-media node. - */ - -Compiler.prototype['custom-media'] = function(node){ - return this.emit('@custom-media ' + node.name + ' ' + node.media + ';', node.position); -}; - -/** - * Visit rule node. - */ - -Compiler.prototype.rule = function(node){ - var decls = node.declarations; - if (!decls.length) return ''; - - return this.emit(node.selectors.join(','), node.position, true) - + this.emit('{') - + this.mapVisit(decls) - + this.emit('}'); -}; - -/** - * Visit declaration node. - */ - -Compiler.prototype.declaration = function(node){ - return this.emit(node.property + ':' + node.value, node.position) + this.emit(';'); -}; - diff --git a/lib/identity.js b/lib/identity.js deleted file mode 100644 index 9c8d3c9..0000000 --- a/lib/identity.js +++ /dev/null @@ -1,253 +0,0 @@ - -/** - * Module dependencies. - */ - -var Base = require('./compiler'); - -/** - * Expose compiler. - */ - -module.exports = Compiler; - -/** - * Initialize a new `Compiler`. - */ - -function Compiler(options) { - options = options || {}; - Base.call(this, options); - this.indentation = options.indent; -} - -/** - * Inherit from `Base.prototype`. - */ - -Compiler.prototype.__proto__ = Base.prototype; - -/** - * Compile `node`. - */ - -Compiler.prototype.compile = function(node){ - return this.stylesheet(node); -}; - -/** - * Visit stylesheet node. - */ - -Compiler.prototype.stylesheet = function(node){ - return this.mapVisit(node.stylesheet.rules, '\n\n'); -}; - -/** - * Visit comment node. - */ - -Compiler.prototype.comment = function(node){ - return this.emit(this.indent() + '/*' + node.comment + '*/', node.position); -}; - -/** - * Visit import node. - */ - -Compiler.prototype.import = function(node){ - return this.emit('@import ' + node.import + ';', node.position); -}; - -/** - * Visit media node. - */ - -Compiler.prototype.media = function(node){ - return this.emit('@media ' + node.media, node.position, true) - + this.emit( - ' {\n' - + this.indent(1)) - + this.mapVisit(node.rules, '\n\n') - + this.emit( - this.indent(-1) - + '\n}'); -}; - -/** - * Visit document node. - */ - -Compiler.prototype.document = function(node){ - var doc = '@' + (node.vendor || '') + 'document ' + node.document; - - return this.emit(doc, node.position, true) - + this.emit( - ' ' - + ' {\n' - + this.indent(1)) - + this.mapVisit(node.rules, '\n\n') - + this.emit( - this.indent(-1) - + '\n}'); -}; - -/** - * Visit charset node. - */ - -Compiler.prototype.charset = function(node){ - return this.emit('@charset ' + node.charset + ';', node.position); -}; - -/** - * Visit namespace node. - */ - -Compiler.prototype.namespace = function(node){ - return this.emit('@namespace ' + node.namespace + ';', node.position); -}; - -/** - * Visit supports node. - */ - -Compiler.prototype.supports = function(node){ - return this.emit('@supports ' + node.supports, node.position, true) - + this.emit( - ' {\n' - + this.indent(1)) - + this.mapVisit(node.rules, '\n\n') - + this.emit( - this.indent(-1) - + '\n}'); -}; - -/** - * Visit keyframes node. - */ - -Compiler.prototype.keyframes = function(node){ - return this.emit('@' + (node.vendor || '') + 'keyframes ' + node.name, node.position, true) - + this.emit( - ' {\n' - + this.indent(1)) - + this.mapVisit(node.keyframes, '\n') - + this.emit( - this.indent(-1) - + '}'); -}; - -/** - * Visit keyframe node. - */ - -Compiler.prototype.keyframe = function(node){ - var decls = node.declarations; - - return this.emit(this.indent()) - + this.emit(node.values.join(', '), node.position, true) - + this.emit( - ' {\n' - + this.indent(1)) - + this.mapVisit(decls, '\n') - + this.emit( - this.indent(-1) - + '\n' - + this.indent() + '}\n'); -}; - -/** - * Visit page node. - */ - -Compiler.prototype.page = function(node){ - var sel = node.selectors.length - ? node.selectors.join(', ') + ' ' - : ''; - - return this.emit('@page ' + sel, node.position, true) - + this.emit('{\n') - + this.emit(this.indent(1)) - + this.mapVisit(node.declarations, '\n') - + this.emit(this.indent(-1)) - + this.emit('\n}'); -}; - -/** - * Visit font-face node. - */ - -Compiler.prototype['font-face'] = function(node){ - return this.emit('@font-face ', node.position, true) - + this.emit('{\n') - + this.emit(this.indent(1)) - + this.mapVisit(node.declarations, '\n') - + this.emit(this.indent(-1)) - + this.emit('\n}'); -}; - -/** - * Visit host node. - */ - -Compiler.prototype.host = function(node){ - return this.emit('@host', node.position, true) - + this.emit( - ' {\n' - + this.indent(1)) - + this.mapVisit(node.rules, '\n\n') - + this.emit( - this.indent(-1) - + '\n}'); -}; - -/** - * Visit custom-media node. - */ - -Compiler.prototype['custom-media'] = function(node){ - return this.emit('@custom-media ' + node.name + ' ' + node.media + ';', node.position); -}; - -/** - * Visit rule node. - */ - -Compiler.prototype.rule = function(node){ - var indent = this.indent(); - var decls = node.declarations; - if (!decls.length) return ''; - - return this.emit(node.selectors.map(function(s){ return indent + s }).join(',\n'), node.position, true) - + this.emit(' {\n') - + this.emit(this.indent(1)) - + this.mapVisit(decls, '\n') - + this.emit(this.indent(-1)) - + this.emit('\n' + this.indent() + '}'); -}; - -/** - * Visit declaration node. - */ - -Compiler.prototype.declaration = function(node){ - return this.emit(this.indent()) - + this.emit(node.property + ': ' + node.value, node.position) - + this.emit(';'); -}; - -/** - * Increase, decrease or return current indentation. - */ - -Compiler.prototype.indent = function(level) { - this.level = this.level || 1; - - if (null != level) { - this.level += level; - return ''; - } - - return Array(this.level).join(this.indentation || ' '); -}; diff --git a/lib/source-map-support.js b/lib/source-map-support.js deleted file mode 100644 index 528f426..0000000 --- a/lib/source-map-support.js +++ /dev/null @@ -1,139 +0,0 @@ - -/** - * Module dependencies. - */ - -var SourceMap = require('source-map').SourceMapGenerator; -var SourceMapConsumer = require('source-map').SourceMapConsumer; -var sourceMapResolve = require('source-map-resolve'); -var fs = require('fs'); - -/** - * Expose `mixin()`. - */ - -module.exports = mixin; - -/** - * Mixin source map support into `compiler`. - * - * @param {Compiler} compiler - * @api public - */ - -function mixin(compiler) { - var file = compiler.options.filename || 'generated.css'; - compiler._comment = compiler.comment; - compiler.map = new SourceMap({ file: file }); - compiler.position = { line: 1, column: 1 }; - compiler.files = {}; - for (var k in exports) compiler[k] = exports[k]; -} - -/** - * Update position. - * - * @param {String} str - * @api private - */ - -exports.updatePosition = function(str) { - var lines = str.match(/\n/g); - if (lines) this.position.line += lines.length; - var i = str.lastIndexOf('\n'); - this.position.column = ~i ? str.length - i : this.position.column + str.length; -}; - -/** - * Emit `str`. - * - * @param {String} str - * @param {Number} [pos] - * @param {Boolean} [startOnly] - * @return {String} - * @api private - */ - -exports.emit = function(str, pos, startOnly) { - var sourceFile = pos && pos.source || 'source.css'; - - if (pos && pos.start) { - this.map.addMapping({ - source: sourceFile, - generated: { - line: this.position.line, - column: Math.max(this.position.column - 1, 0) - }, - original: { - line: pos.start.line, - column: pos.start.column - 1 - } - }); - - this.addFile(sourceFile, pos); - } - - this.updatePosition(str); - - if (!startOnly && pos && pos.end) { - this.map.addMapping({ - source: sourceFile, - generated: { - line: this.position.line, - column: Math.max(this.position.column - 1, 0) - }, - original: { - line: pos.end.line, - column: pos.end.column - 1 - } - }); - - this.addFile(sourceFile, pos); - } - - return str; -}; - -/** - * Adds a file to the source map output if it has not already been added - * @param {String} file - * @param {Object} pos - */ - -exports.addFile = function(file, pos) { - if (typeof pos.content !== 'string') return; - if (Object.prototype.hasOwnProperty.call(this.files, file)) return; - - this.files[file] = pos.content; -}; - -/** - * Applies any original source maps to the output and embeds the source file - * contents in the source map. - */ - -exports.applySourceMaps = function() { - Object.keys(this.files).forEach(function(file) { - var content = this.files[file]; - this.map.setSourceContent(file, content); - - var originalMap = sourceMapResolve.resolveSync( - content, file, fs.readFileSync); - if (originalMap) { - originalMap = new SourceMapConsumer(originalMap.map); - this.map.applySourceMap(originalMap, file); - } - }, this); -}; - -/** - * Process comments, drops sourceMap comments. - * @param {Object} node - */ - -exports.comment = function(node) { - if (/^# sourceMappingURL=/.test(node.comment)) - return this.emit('', node.position); - else - return this._comment(node); -}; diff --git a/package.json b/package.json index a3139a3..1077a49 100644 --- a/package.json +++ b/package.json @@ -2,27 +2,22 @@ "name": "css-stringify", "version": "1.4.1", "description": "CSS compiler", - "keywords": [ - "css", - "stringify", - "stylesheet" + "main": "index", + "files": [ + "index.js" ], - "author": "TJ Holowaychuk ", - "devDependencies": { - "mocha": "*", - "should": "*", - "css-parse": "git://github.com/reworkcss/css-parse.git#7cef3658d0bba872cde05a85339034b187cb3397" + "dependencies": { + "css": "^1.6.0" }, - "main": "index", + "author": "TJ Holowaychuk ", + "license": "MIT", "repository": { "type": "git", "url": "https://github.com/reworkcss/css-stringify.git" }, - "scripts": { - "test": "make test" - }, - "dependencies": { - "source-map": "~0.1.31", - "source-map-resolve": "^0.1.3" - } + "keywords": [ + "css", + "stringify", + "stylesheet" + ] } diff --git a/test/cases/at_charset.css b/test/cases/at_charset.css deleted file mode 100644 index e63c05c..0000000 --- a/test/cases/at_charset.css +++ /dev/null @@ -1 +0,0 @@ -@charset "utf-8"; diff --git a/test/cases/at_namespace.css b/test/cases/at_namespace.css deleted file mode 100644 index edc75cf..0000000 --- a/test/cases/at_namespace.css +++ /dev/null @@ -1 +0,0 @@ -@namespace svg "http://www.w3.org/2000/svg"; diff --git a/test/cases/comments.compressed.css b/test/cases/comments.compressed.css deleted file mode 100644 index 7ca44b1..0000000 --- a/test/cases/comments.compressed.css +++ /dev/null @@ -1 +0,0 @@ -body{color:#eee;} diff --git a/test/cases/comments.css b/test/cases/comments.css deleted file mode 100644 index 87e95a3..0000000 --- a/test/cases/comments.css +++ /dev/null @@ -1,8 +0,0 @@ -/* comment */ - -body { - /* foo */ - /* bar */ - color: #eee; - /* baz */ -} diff --git a/test/cases/custom-media.css b/test/cases/custom-media.css deleted file mode 100644 index 035deba..0000000 --- a/test/cases/custom-media.css +++ /dev/null @@ -1 +0,0 @@ -@custom-media --wide-window screen and (min-width: 40em); diff --git a/test/cases/document.compressed.css b/test/cases/document.compressed.css deleted file mode 100644 index d56d0a5..0000000 --- a/test/cases/document.compressed.css +++ /dev/null @@ -1 +0,0 @@ -@-moz-document url-prefix(){.icon-spin{height:.9em;}.btn .icon-spin{height:auto;}.icon-spin.icon-large{height:1.25em;}.btn .icon-spin.icon-large{height:.75em;}} diff --git a/test/cases/document.css b/test/cases/document.css deleted file mode 100644 index e6302e7..0000000 --- a/test/cases/document.css +++ /dev/null @@ -1,17 +0,0 @@ -@-moz-document url-prefix() { - .icon-spin { - height: .9em; - } - - .btn .icon-spin { - height: auto; - } - - .icon-spin.icon-large { - height: 1.25em; - } - - .btn .icon-spin.icon-large { - height: .75em; - } -} diff --git a/test/cases/font-face.compressed.css b/test/cases/font-face.compressed.css deleted file mode 100644 index b08d099..0000000 --- a/test/cases/font-face.compressed.css +++ /dev/null @@ -1 +0,0 @@ -@font-face{font-family:"Bitstream Vera Serif Bold";src:url("http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf");}body{font-family:"Bitstream Vera Serif Bold", serif;} diff --git a/test/cases/font-face.css b/test/cases/font-face.css deleted file mode 100644 index 09945e6..0000000 --- a/test/cases/font-face.css +++ /dev/null @@ -1,8 +0,0 @@ -@font-face { - font-family: "Bitstream Vera Serif Bold"; - src: url("http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf"); -} - -body { - font-family: "Bitstream Vera Serif Bold", serif; -} diff --git a/test/cases/host.compressed.css b/test/cases/host.compressed.css deleted file mode 100644 index 509667c..0000000 --- a/test/cases/host.compressed.css +++ /dev/null @@ -1 +0,0 @@ -@host{:scope{display:block;}} diff --git a/test/cases/host.css b/test/cases/host.css deleted file mode 100644 index 0ec989c..0000000 --- a/test/cases/host.css +++ /dev/null @@ -1,5 +0,0 @@ -@host { - :scope { - display: block; - } -} diff --git a/test/cases/import.css b/test/cases/import.css deleted file mode 100644 index ebeed7b..0000000 --- a/test/cases/import.css +++ /dev/null @@ -1 +0,0 @@ -@import 'foo.css'; \ No newline at end of file diff --git a/test/cases/keyframes.compressed.css b/test/cases/keyframes.compressed.css deleted file mode 100644 index 75a9dbb..0000000 --- a/test/cases/keyframes.compressed.css +++ /dev/null @@ -1 +0,0 @@ -@keyframes fade{from{opacity:0;opacity:1;}to{opacity:1;}} diff --git a/test/cases/keyframes.css b/test/cases/keyframes.css deleted file mode 100644 index e8ed694..0000000 --- a/test/cases/keyframes.css +++ /dev/null @@ -1,10 +0,0 @@ -@keyframes fade { - from { - opacity: 0; - opacity: 1; - } - - to { - opacity: 1; - } -} diff --git a/test/cases/media.compressed.css b/test/cases/media.compressed.css deleted file mode 100644 index a34785a..0000000 --- a/test/cases/media.compressed.css +++ /dev/null @@ -1 +0,0 @@ -@media screen, projection{html{background:#fffef0;color:#300;}body{max-width:35em;margin:0 auto;}}@media print{html{background:#fff;color:#000;}body{padding:1in;border:0.5pt solid #666;}} diff --git a/test/cases/media.css b/test/cases/media.css deleted file mode 100644 index c234e7d..0000000 --- a/test/cases/media.css +++ /dev/null @@ -1,23 +0,0 @@ -@media screen, projection { - html { - background: #fffef0; - color: #300; - } - - body { - max-width: 35em; - margin: 0 auto; - } -} - -@media print { - html { - background: #fff; - color: #000; - } - - body { - padding: 1in; - border: 0.5pt solid #666; - } -} diff --git a/test/cases/page.compressed.css b/test/cases/page.compressed.css deleted file mode 100644 index 84595d2..0000000 --- a/test/cases/page.compressed.css +++ /dev/null @@ -1 +0,0 @@ -@page {margin:2.5cm;}@page :left{margin-left:5cm;}@page :right{margin-right:5cm;}@page :first{margin-top:8cm;} \ No newline at end of file diff --git a/test/cases/page.css b/test/cases/page.css deleted file mode 100644 index 34f2a09..0000000 --- a/test/cases/page.css +++ /dev/null @@ -1,15 +0,0 @@ -@page { - margin: 2.5cm; -} - -@page :left { - margin-left: 5cm; -} - -@page :right { - margin-right: 5cm; -} - -@page :first { - margin-top: 8cm; -} diff --git a/test/cases/rules.compressed.css b/test/cases/rules.compressed.css deleted file mode 100644 index 3a4188c..0000000 --- a/test/cases/rules.compressed.css +++ /dev/null @@ -1 +0,0 @@ -tobi{name:'tobi';age:2;}loki{name:'loki';age:1;} diff --git a/test/cases/rules.css b/test/cases/rules.css deleted file mode 100644 index 5b98d01..0000000 --- a/test/cases/rules.css +++ /dev/null @@ -1,9 +0,0 @@ -tobi { - name: 'tobi'; - age: 2; -} - -loki { - name: 'loki'; - age: 1; -} diff --git a/test/cases/selectors.compressed.css b/test/cases/selectors.compressed.css deleted file mode 100644 index ee0faf9..0000000 --- a/test/cases/selectors.compressed.css +++ /dev/null @@ -1 +0,0 @@ -foo,bar,baz{color:'black';} diff --git a/test/cases/selectors.css b/test/cases/selectors.css deleted file mode 100644 index 9f214f1..0000000 --- a/test/cases/selectors.css +++ /dev/null @@ -1,5 +0,0 @@ -foo, -bar, -baz { - color: 'black'; -} diff --git a/test/cases/source-map-apply.scss b/test/cases/source-map-apply.scss deleted file mode 100644 index e69de29..0000000 diff --git a/test/cases/supports.compressed.css b/test/cases/supports.compressed.css deleted file mode 100644 index 61d4ee2..0000000 --- a/test/cases/supports.compressed.css +++ /dev/null @@ -1 +0,0 @@ -@supports (display: flex){div{display:flex;}div{something:else;}} diff --git a/test/cases/supports.css b/test/cases/supports.css deleted file mode 100644 index 37952f1..0000000 --- a/test/cases/supports.css +++ /dev/null @@ -1,9 +0,0 @@ -@supports (display: flex) { - div { - display: flex; - } - - div { - something: else; - } -} diff --git a/test/css-stringify.js b/test/css-stringify.js deleted file mode 100644 index d917005..0000000 --- a/test/css-stringify.js +++ /dev/null @@ -1,97 +0,0 @@ - -/** - * Module dependencies. - */ - -var stringify = require('..') - , parse = require('css-parse') - , fs = require('fs') - , path = require('path') - , read = fs.readFileSync - , readdir = fs.readdirSync - , SourceMapConsumer = require('source-map').SourceMapConsumer; - -describe('stringify(obj)', function(){ - readdir('test/cases').forEach(function(file){ - var compress = ~file.indexOf('.compressed'); - it('should stringify ' + path.basename(file), function(){ - var expect; - if (compress) { - expect = read(path.join('test', 'cases', file), 'utf8'); - file = file.replace('.compressed', ''); - } - var css = read(path.join('test', 'cases', file), 'utf8'); - var ret = stringify(parse(css), { compress: compress }); - ret.trim().should.equal((expect || css).trim()); - }); - }); -}); - -describe('stringify(obj, {sourcemap: true})', function(){ - var file = 'test/source-map-case.css'; - var src = read(file, 'utf8'); - var stylesheet = parse(src, { source: file, position: true }); - function loc(line, column) { - return { line: line, column: column, source: file, name: null } - }; - - var locs = { - tobiSelector: loc(1, 0), - tobiNameName: loc(2, 2), - tobiNameValue: loc(2, 2), - mediaBlock: loc(11, 0), - mediaOnly: loc(12, 2), - comment: loc(17, 0), - }; - - it('should generate source maps alongside when using identity compiler', function(){ - var result = stringify(stylesheet, { sourcemap: true }); - result.should.have.property('code'); - result.should.have.property('map'); - var map = new SourceMapConsumer(result.map); - map.originalPositionFor({ line: 1, column: 0 }).should.eql(locs.tobiSelector); - map.originalPositionFor({ line: 2, column: 2 }).should.eql(locs.tobiNameName); - map.originalPositionFor({ line: 2, column: 8 }).should.eql(locs.tobiNameValue); - map.originalPositionFor({ line: 11, column: 0 }).should.eql(locs.mediaBlock); - map.originalPositionFor({ line: 12, column: 2 }).should.eql(locs.mediaOnly); - map.originalPositionFor({ line: 17, column: 0 }).should.eql(locs.comment); - map.sourceContentFor(file).should.eql(src); - }); - - it('should generate source maps alongside when using compress compiler', function(){ - var result = stringify(stylesheet, { compress: true, sourcemap: true }); - result.should.have.property('code'); - result.should.have.property('map'); - var map = new SourceMapConsumer(result.map); - map.originalPositionFor({ line: 1, column: 0 }).should.eql(locs.tobiSelector); - map.originalPositionFor({ line: 1, column: 5 }).should.eql(locs.tobiNameName); - map.originalPositionFor({ line: 1, column: 10 }).should.eql(locs.tobiNameValue); - map.originalPositionFor({ line: 1, column: 50 }).should.eql(locs.mediaBlock); - map.originalPositionFor({ line: 1, column: 64 }).should.eql(locs.mediaOnly); - map.sourceContentFor(file).should.eql(src); - }); - - it('should apply included source maps', function(){ - var file = 'test/source-map-apply.css'; - var src = read(file, 'utf8'); - var stylesheet = parse(src, { source: file, position: true }); - var result = stringify(stylesheet, { sourcemap: true }); - result.should.have.property('code'); - result.should.have.property('map'); - - var map = new SourceMapConsumer(result.map); - map.originalPositionFor({ line: 1, column: 0 }).should.eql({ - column: 0, - line: 1, - name: null, - source: 'source-map-apply.scss' - }); - - map.originalPositionFor({ line: 2, column: 2 }).should.eql({ - column: 7, - line: 1, - name: null, - source: 'source-map-apply.scss' - }); - }); -}); diff --git a/test/source-map-apply.css b/test/source-map-apply.css deleted file mode 100644 index 5f11212..0000000 --- a/test/source-map-apply.css +++ /dev/null @@ -1,4 +0,0 @@ -tobi { - name: 'tobi'; } - -/*# sourceMappingURL=source-map-apply.css.map */ \ No newline at end of file diff --git a/test/source-map-apply.css.map b/test/source-map-apply.css.map deleted file mode 100644 index 066c1f5..0000000 --- a/test/source-map-apply.css.map +++ /dev/null @@ -1,7 +0,0 @@ -{ - "version": 3, - "file": "", - "sources": ["source-map-apply.scss"], - "names": [], - "mappings": "AAAA;EAAO,MAAM" -} \ No newline at end of file diff --git a/test/source-map-apply.scss b/test/source-map-apply.scss deleted file mode 100644 index 7ad3ef5..0000000 --- a/test/source-map-apply.scss +++ /dev/null @@ -1 +0,0 @@ -tobi { name: 'tobi'; } diff --git a/test/source-map-case.css b/test/source-map-case.css deleted file mode 100644 index 47598d7..0000000 --- a/test/source-map-case.css +++ /dev/null @@ -1,17 +0,0 @@ -tobi { - name: 'tobi'; - age: 2; -} - -loki { - name: 'loki'; - age: 1; -} - -@media screen { - screen-only { - display: block; - } -} - -/* comment */ From 58d4e82f7f80595cd07e66cb298bfedc515d61c0 Mon Sep 17 00:00:00 2001 From: Nicolas Gallagher Date: Wed, 18 Jun 2014 10:45:16 -0700 Subject: [PATCH 66/67] Update 'css' to 2.0.0 --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 934d616..fc0a6a3 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,7 @@ HEAD ================== + * update 'css' to 2.0.0 * depend on the 'css' package, which now contains the stringifier 1.4.1 / 2013-12-09 diff --git a/package.json b/package.json index 1077a49..2d7434b 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "index.js" ], "dependencies": { - "css": "^1.6.0" + "css": "^2.0.0" }, "author": "TJ Holowaychuk ", "license": "MIT", From b78e3743096da0e8de4f6ee204f11fbdab353fd5 Mon Sep 17 00:00:00 2001 From: Nicolas Gallagher Date: Wed, 18 Jun 2014 10:45:51 -0700 Subject: [PATCH 67/67] 2.0.0 --- History.md | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index fc0a6a3..dbc401c 100644 --- a/History.md +++ b/History.md @@ -1,4 +1,4 @@ -HEAD +2.0.0 / 2014-06-18 ================== * update 'css' to 2.0.0 diff --git a/package.json b/package.json index 2d7434b..3f55a24 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "css-stringify", - "version": "1.4.1", + "version": "2.0.0", "description": "CSS compiler", "main": "index", "files": [