[Pkg-javascript-commits] [node-css-stringify] 01/01: Imported Upstream version 1.4.1
Leo Iannacone
l3on-guest at moszumanska.debian.org
Tue May 6 14:04:39 UTC 2014
This is an automated email from the git hooks/post-receive script.
l3on-guest pushed a commit to branch master
in repository node-css-stringify.
commit 794cb7148744f7734d145042ea3292cc49a8950e
Author: Leo Iannacone <l3on at ubuntu.com>
Date: Tue May 6 15:52:15 2014 +0200
Imported Upstream version 1.4.1
---
.npmignore | 6 +
.travis.yml | 3 +
History.md | 75 +++++++++++++
LICENSE | 9 ++
Makefile | 8 ++
Readme.md | 63 +++++++++++
component.json | 14 +++
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 | 42 +++++++
lib/compiler.js | 50 +++++++++
lib/compress.js | 168 ++++++++++++++++++++++++++++
lib/identity.js | 217 ++++++++++++++++++++++++++++++++++++
lib/source-map-support.js | 84 ++++++++++++++
package.json | 27 +++++
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/document.compressed.css | 1 +
test/cases/document.css | 17 +++
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/supports.compressed.css | 1 +
test/cases/supports.css | 9 ++
test/css-stringify.js | 70 ++++++++++++
test/source-map-case.css | 17 +++
49 files changed, 1222 insertions(+)
diff --git a/.npmignore b/.npmignore
new file mode 100644
index 0000000..4a3c398
--- /dev/null
+++ b/.npmignore
@@ -0,0 +1,6 @@
+support
+test
+examples
+*.sock
+test.css
+test.js
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"
diff --git a/History.md b/History.md
new file mode 100644
index 0000000..6a916b8
--- /dev/null
+++ b/History.md
@@ -0,0 +1,75 @@
+
+1.4.1 / 2013-12-09
+==================
+
+ * add missing files to component.json
+
+1.4.0 / 2013-XX-XX
+==================
+
+ * add source map generation
+
+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
+==================
+
+ * fix output of rules with no declarations for Identity compiler
+ * fix defaulting of options
+
+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
+==================
+
+ * add @document compilation. Closes #82
+
+1.1.0 / 2013-03-19
+==================
+
+ * add omission of comments when compressed
+ * add comment support
+
+1.0.5 / 2013-03-15
+==================
+
+ * fix indentation of multiple selectors in @media. Closes #11
+
+1.0.4 / 2012-11-15
+==================
+
+ * fix indentation
+
+1.0.3 / 2012-09-04
+==================
+
+ * add __ at charset__ support [rstacruz]
+
+1.0.2 / 2012-09-01
+==================
+
+ * add component support
+
+1.0.1 / 2012-07-26
+==================
+
+ * add "selectors" array support
+
+0.0.1 / 2010-01-03
+==================
+
+ * Initial release
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 <tj at 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.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..d78a055
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,8 @@
+
+test:
+ @./node_modules/.bin/mocha \
+ --require should \
+ --reporter spec \
+ --bail
+
+.PHONY: test
diff --git a/Readme.md b/Readme.md
new file mode 100644
index 0000000..809201b
--- /dev/null
+++ b/Readme.md
@@ -0,0 +1,63 @@
+# 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).
+
+## API
+
+### stringify(object, [options])
+
+ Accepts an AST `object` from css-parse and returns a CSS string.
+
+```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.
+
+## License
+
+(The MIT License)
+
+Copyright (c) 2012 TJ Holowaychuk <tj at 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.
diff --git a/component.json b/component.json
new file mode 100644
index 0000000..ca5cb38
--- /dev/null
+++ b/component.json
@@ -0,0 +1,14 @@
+{
+ "name": "css-stringify",
+ "repo": "visionmedia/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"
+ ]
+}
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)));
diff --git a/examples/dialog.css b/examples/dialog.css
new file mode 100644
index 0000000..df74183
--- /dev/null
+++ b/examples/dialog.css
@@ -0,0 +1,92 @@
+#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
new file mode 100644
index 0000000..69cb6fe
--- /dev/null
+++ b/examples/dialog.js
@@ -0,0 +1,12 @@
+
+/**
+ * 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
new file mode 100644
index 0000000..7ddf3d6
--- /dev/null
+++ b/examples/document.css
@@ -0,0 +1,17 @@
+ at -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/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/examples/keyframes.css b/examples/keyframes.css
new file mode 100644
index 0000000..a50d14a
--- /dev/null
+++ b/examples/keyframes.css
@@ -0,0 +1,10 @@
+ at 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
new file mode 100644
index 0000000..7454ff9
--- /dev/null
+++ b/examples/keyframes.js
@@ -0,0 +1,12 @@
+
+/**
+ * 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
new file mode 100644
index 0000000..d50e65b
--- /dev/null
+++ b/examples/media.css
@@ -0,0 +1,27 @@
+
+/* some comment */
+
+ at media screen, projection {
+ html {
+ background: #fffef0;
+ color: #300;
+ }
+
+ body {
+ max-width: 35em;
+ margin: 0 auto;
+ }
+}
+
+ at 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
new file mode 100644
index 0000000..ec5bcf5
--- /dev/null
+++ b/examples/media.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 }));
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 @@
+ at page {
+ size: auto;
+ margin: 10%
+}
+
+ at 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/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
new file mode 100644
index 0000000..7c3dbc4
--- /dev/null
+++ b/index.js
@@ -0,0 +1,42 @@
+
+/**
+ * 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);
+ 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
new file mode 100644
index 0000000..601bd73
--- /dev/null
+++ b/lib/compress.js
@@ -0,0 +1,168 @@
+
+/**
+ * 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 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
new file mode 100644
index 0000000..cc9fd5c
--- /dev/null
+++ b/lib/identity.js
@@ -0,0 +1,217 @@
+
+/**
+ * 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 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
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
new file mode 100644
index 0000000..3e34ece
--- /dev/null
+++ b/package.json
@@ -0,0 +1,27 @@
+{
+ "name": "css-stringify",
+ "version": "1.4.1",
+ "description": "CSS compiler",
+ "keywords": [
+ "css",
+ "stringify",
+ "stylesheet"
+ ],
+ "author": "TJ Holowaychuk <tj at vision-media.ca>",
+ "devDependencies": {
+ "mocha": "*",
+ "should": "*",
+ "css-parse": "1.6.0"
+ },
+ "main": "index",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/visionmedia/css-stringify.git"
+ },
+ "scripts": {
+ "test": "make test"
+ },
+ "dependencies": {
+ "source-map": "~0.1.31"
+ }
+}
diff --git a/test/cases/at_charset.css b/test/cases/at_charset.css
new file mode 100644
index 0000000..e63c05c
--- /dev/null
+++ b/test/cases/at_charset.css
@@ -0,0 +1 @@
+ at charset "utf-8";
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 @@
+ at namespace svg "http://www.w3.org/2000/svg";
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;}
diff --git a/test/cases/comments.css b/test/cases/comments.css
new file mode 100644
index 0000000..87e95a3
--- /dev/null
+++ b/test/cases/comments.css
@@ -0,0 +1,8 @@
+/* comment */
+
+body {
+ /* foo */
+ /* bar */
+ color: #eee;
+ /* baz */
+}
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 @@
+ at -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
new file mode 100644
index 0000000..e6302e7
--- /dev/null
+++ b/test/cases/document.css
@@ -0,0 +1,17 @@
+ at -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/import.css b/test/cases/import.css
new file mode 100644
index 0000000..ebeed7b
--- /dev/null
+++ b/test/cases/import.css
@@ -0,0 +1 @@
+ at import 'foo.css';
\ No newline at end of file
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 @@
+ at keyframes fade{from{opacity:0;opacity:1;}to{opacity:1;}}
diff --git a/test/cases/keyframes.css b/test/cases/keyframes.css
new file mode 100644
index 0000000..e8ed694
--- /dev/null
+++ b/test/cases/keyframes.css
@@ -0,0 +1,10 @@
+ at keyframes fade {
+ from {
+ opacity: 0;
+ opacity: 1;
+ }
+
+ to {
+ opacity: 1;
+ }
+}
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 @@
+ at 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
new file mode 100644
index 0000000..c234e7d
--- /dev/null
+++ b/test/cases/media.css
@@ -0,0 +1,23 @@
+ at media screen, projection {
+ html {
+ background: #fffef0;
+ color: #300;
+ }
+
+ body {
+ max-width: 35em;
+ margin: 0 auto;
+ }
+}
+
+ at 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 @@
+ at 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
new file mode 100644
index 0000000..34f2a09
--- /dev/null
+++ b/test/cases/page.css
@@ -0,0 +1,15 @@
+ at page {
+ margin: 2.5cm;
+}
+
+ at page :left {
+ margin-left: 5cm;
+}
+
+ at page :right {
+ margin-right: 5cm;
+}
+
+ at page :first {
+ margin-top: 8cm;
+}
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/rules.css b/test/cases/rules.css
new file mode 100644
index 0000000..5b98d01
--- /dev/null
+++ b/test/cases/rules.css
@@ -0,0 +1,9 @@
+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/selectors.css b/test/cases/selectors.css
new file mode 100644
index 0000000..9f214f1
--- /dev/null
+++ b/test/cases/selectors.css
@@ -0,0 +1,5 @@
+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 @@
+ at supports (display: flex){div{display:flex;}div{something:else;}}
diff --git a/test/cases/supports.css b/test/cases/supports.css
new file mode 100644
index 0000000..37952f1
--- /dev/null
+++ b/test/cases/supports.css
@@ -0,0 +1,9 @@
+ at supports (display: flex) {
+ div {
+ display: flex;
+ }
+
+ div {
+ something: else;
+ }
+}
diff --git a/test/css-stringify.js b/test/css-stringify.js
new file mode 100644
index 0000000..b37ee7f
--- /dev/null
+++ b/test/css-stringify.js
@@ -0,0 +1,70 @@
+
+/**
+ * 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 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;
+}
+
+ at media screen {
+ screen-only {
+ display: block;
+ }
+}
+
+/* comment */
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-css-stringify.git
More information about the Pkg-javascript-commits
mailing list