From 89c7ca84a9870f71f3794eaf292a5bde0d33f795 Mon Sep 17 00:00:00 2001 From: Eric Ferraiuolo Date: Wed, 12 Mar 2014 13:09:52 -0400 Subject: [PATCH 01/13] 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 02/13] 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 03/13] 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 04/13] 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 05/13] 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 06/13] 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 07/13] 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 08/13] 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 09/13] 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 10/13] 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 11/13] 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 12/13] 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 13/13] 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": [