diff --git a/test/cases.js b/test/cases.js index 1812a2cf..2dd3a04c 100644 --- a/test/cases.js +++ b/test/cases.js @@ -1,44 +1,47 @@ -var fs = require('fs'); -var path = require('path'); -var parse = require('../').parse; -var stringify = require('../').stringify; +const fs = require('fs'); +const path = require('path'); +const parse = require('../').parse; +const stringify = require('../').stringify; -var cases = fs.readdirSync(path.join(__dirname, 'cases')); +const cases = fs.readdirSync(path.join(__dirname, 'cases')); cases.forEach(function(name) { describe('cases/' + name, function() { - var dir = path.join(__dirname, 'cases', name); - var inputFile = path.join(dir, 'input.css'); - var astFile = path.join(dir, 'ast.json'); - var outputFile = path.join(dir, 'output.css'); - var compressedFile = path.join(dir, 'compressed.css'); + const dir = path.join(__dirname, 'cases', name); + const inputFile = readFile(path.join(dir, 'input.css')); + const astFile = readFile(path.join(dir, 'ast.json')); + const outputFile = readFile(path.join(dir, 'output.css')); + const compressedFile = readFile(path.join(dir, 'compressed.css')); + + const parsedFile = parseFile(inputFile); it('should match ast.json', function() { - var ast = parseInput(); - ast.should.containDeep(JSON.parse(readFile(astFile))); + parsedFile.should.containDeep(JSON.parse(astFile)); }); it('should match output.css', function() { - var output = stringify(parseInput()); - output.should.equal(readFile(outputFile).trim()); + const stringOutput = stringify(parsedFile) + stringOutput.should.equal(outputFile.trim()); }); it('should match compressed.css', function() { - var compressed = stringify(parseInput(), { compress: true }); - compressed.should.equal(readFile(compressedFile)); + const compressedOutput = stringify(parsedFile,{ compress: true }) + compressedOutput.should.equal(compressedFile); }); - function parseInput() { - return parse(readFile(inputFile), { source: 'input.css' }); - } }); }); -function readFile(file) { - var src = fs.readFileSync(file, 'utf8'); - // normalize line endings - src = src.replace(/\r\n/, '\n'); - // remove trailing newline - src = src.replace(/\n$/, ''); +function parseFile(file){ + try { + return parse(file, {source: 'input.css'}); + } catch (e){ + console.error("Error in Parsing",e); + return {}; + } +} - return src; +function readFile(file) { + return fs.readFileSync(file, 'utf8') + .replace(/\r\n/g, '\n')// normalize line endings + .replace(/\n$/g, '');// remove trailing newline } diff --git a/test/cases/background-url/ast.json b/test/cases/background-url/ast.json new file mode 100644 index 00000000..ba6a3003 --- /dev/null +++ b/test/cases/background-url/ast.json @@ -0,0 +1,30 @@ +{ + "type": "stylesheet", + "stylesheet": { + "source": "input.css", + "rules": [ + { + "type": "rule", + "selectors": [ "#val" ], + "declarations": [ + { + "type": "declaration", + "property": "background", + "value": "url(\"data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%2236%22%20height%3D%2212%22%20viewBox%3D%220%200%2036%2012%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%3Ccircle%20cx%3D%226%22%20cy%3D%226%22%20r%3D%223%22%20fill%3D%22rgba(0%2C%200%2C%200%2C%20.2)%22%3E%0A%20%20%20%20%3Canimate%20attributeName%3D%22r%22%20values%3D%223%3B5%3B3%22%20calcMode%3D%22linear%22%20dur%3D%221s%22%20repeatCount%3D%22indefinite%22%20%2F%3E%0A%20%20%3C%2Fcircle%3E%0A%20%20%3Ccircle%20cx%3D%2218%22%20cy%3D%226%22%20r%3D%223%22%20fill%3D%22rgba(0%2C%200%2C%200%2C%20.2)%22%3E%0A%20%20%20%20%3Canimate%20attributeName%3D%22r%22%20values%3D%223%3B5%3B3%22%20calcMode%3D%22linear%22%20begin%3D%22.33s%22%20dur%3D%221s%22%20repeatCount%3D%22indefinite%22%20%2F%3E%0A%20%20%3C%2Fcircle%3E%0A%20%20%3Ccircle%20cx%3D%2230%22%20cy%3D%226%22%20r%3D%223%22%20fill%3D%22rgba(0%2C%200%2C%200%2C%20.2)%22%3E%0A%20%20%20%20%3Canimate%20attributeName%3D%22r%22%20values%3D%223%3B5%3B3%22%20calcMode%3D%22linear%22%20begin%3D%22.66s%22%20dur%3D%221s%22%20repeatCount%3D%22indefinite%22%20%2F%3E%0A%20%20%3C%2Fcircle%3E%0A%3C%2Fsvg%3E%0A\")", + "position": { + "start": { "line": 2, "column": 5 }, + "end": { "line": 2, "column": 1144 }, + "source": "input.css" + } + } + ], + "position": { + "start": { "line": 1, "column": 1 }, + "end": { "line": 3, "column": 2 }, + "source": "input.css" + } + } + ], + "parsingErrors": [] + } +} diff --git a/test/cases/background-url/compressed.css b/test/cases/background-url/compressed.css new file mode 100644 index 00000000..f805a1f7 --- /dev/null +++ b/test/cases/background-url/compressed.css @@ -0,0 +1 @@ +#val{background:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%2236%22%20height%3D%2212%22%20viewBox%3D%220%200%2036%2012%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%3Ccircle%20cx%3D%226%22%20cy%3D%226%22%20r%3D%223%22%20fill%3D%22rgba(0%2C%200%2C%200%2C%20.2)%22%3E%0A%20%20%20%20%3Canimate%20attributeName%3D%22r%22%20values%3D%223%3B5%3B3%22%20calcMode%3D%22linear%22%20dur%3D%221s%22%20repeatCount%3D%22indefinite%22%20%2F%3E%0A%20%20%3C%2Fcircle%3E%0A%20%20%3Ccircle%20cx%3D%2218%22%20cy%3D%226%22%20r%3D%223%22%20fill%3D%22rgba(0%2C%200%2C%200%2C%20.2)%22%3E%0A%20%20%20%20%3Canimate%20attributeName%3D%22r%22%20values%3D%223%3B5%3B3%22%20calcMode%3D%22linear%22%20begin%3D%22.33s%22%20dur%3D%221s%22%20repeatCount%3D%22indefinite%22%20%2F%3E%0A%20%20%3C%2Fcircle%3E%0A%20%20%3Ccircle%20cx%3D%2230%22%20cy%3D%226%22%20r%3D%223%22%20fill%3D%22rgba(0%2C%200%2C%200%2C%20.2)%22%3E%0A%20%20%20%20%3Canimate%20attributeName%3D%22r%22%20values%3D%223%3B5%3B3%22%20calcMode%3D%22linear%22%20begin%3D%22.66s%22%20dur%3D%221s%22%20repeatCount%3D%22indefinite%22%20%2F%3E%0A%20%20%3C%2Fcircle%3E%0A%3C%2Fsvg%3E%0A");} diff --git a/test/cases/background-url/input.css b/test/cases/background-url/input.css new file mode 100644 index 00000000..b883c82b --- /dev/null +++ b/test/cases/background-url/input.css @@ -0,0 +1,4 @@ +#val{ + background:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%2236%22%20height%3D%2212%22%20viewBox%3D%220%200%2036%2012%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%3Ccircle%20cx%3D%226%22%20cy%3D%226%22%20r%3D%223%22%20fill%3D%22rgba(0%2C%200%2C%200%2C%20.2)%22%3E%0A%20%20%20%20%3Canimate%20attributeName%3D%22r%22%20values%3D%223%3B5%3B3%22%20calcMode%3D%22linear%22%20dur%3D%221s%22%20repeatCount%3D%22indefinite%22%20%2F%3E%0A%20%20%3C%2Fcircle%3E%0A%20%20%3Ccircle%20cx%3D%2218%22%20cy%3D%226%22%20r%3D%223%22%20fill%3D%22rgba(0%2C%200%2C%200%2C%20.2)%22%3E%0A%20%20%20%20%3Canimate%20attributeName%3D%22r%22%20values%3D%223%3B5%3B3%22%20calcMode%3D%22linear%22%20begin%3D%22.33s%22%20dur%3D%221s%22%20repeatCount%3D%22indefinite%22%20%2F%3E%0A%20%20%3C%2Fcircle%3E%0A%20%20%3Ccircle%20cx%3D%2230%22%20cy%3D%226%22%20r%3D%223%22%20fill%3D%22rgba(0%2C%200%2C%200%2C%20.2)%22%3E%0A%20%20%20%20%3Canimate%20attributeName%3D%22r%22%20values%3D%223%3B5%3B3%22%20calcMode%3D%22linear%22%20begin%3D%22.66s%22%20dur%3D%221s%22%20repeatCount%3D%22indefinite%22%20%2F%3E%0A%20%20%3C%2Fcircle%3E%0A%3C%2Fsvg%3E%0A"); +} + diff --git a/test/cases/background-url/output.css b/test/cases/background-url/output.css new file mode 100644 index 00000000..ba7081df --- /dev/null +++ b/test/cases/background-url/output.css @@ -0,0 +1,3 @@ +#val { + background: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%2236%22%20height%3D%2212%22%20viewBox%3D%220%200%2036%2012%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%3Ccircle%20cx%3D%226%22%20cy%3D%226%22%20r%3D%223%22%20fill%3D%22rgba(0%2C%200%2C%200%2C%20.2)%22%3E%0A%20%20%20%20%3Canimate%20attributeName%3D%22r%22%20values%3D%223%3B5%3B3%22%20calcMode%3D%22linear%22%20dur%3D%221s%22%20repeatCount%3D%22indefinite%22%20%2F%3E%0A%20%20%3C%2Fcircle%3E%0A%20%20%3Ccircle%20cx%3D%2218%22%20cy%3D%226%22%20r%3D%223%22%20fill%3D%22rgba(0%2C%200%2C%200%2C%20.2)%22%3E%0A%20%20%20%20%3Canimate%20attributeName%3D%22r%22%20values%3D%223%3B5%3B3%22%20calcMode%3D%22linear%22%20begin%3D%22.33s%22%20dur%3D%221s%22%20repeatCount%3D%22indefinite%22%20%2F%3E%0A%20%20%3C%2Fcircle%3E%0A%20%20%3Ccircle%20cx%3D%2230%22%20cy%3D%226%22%20r%3D%223%22%20fill%3D%22rgba(0%2C%200%2C%200%2C%20.2)%22%3E%0A%20%20%20%20%3Canimate%20attributeName%3D%22r%22%20values%3D%223%3B5%3B3%22%20calcMode%3D%22linear%22%20begin%3D%22.66s%22%20dur%3D%221s%22%20repeatCount%3D%22indefinite%22%20%2F%3E%0A%20%20%3C%2Fcircle%3E%0A%3C%2Fsvg%3E%0A"); +} diff --git a/test/cases/import-messed/ast.json b/test/cases/import-messed/ast.json index a3d04d3e..8f234ccd 100644 --- a/test/cases/import-messed/ast.json +++ b/test/cases/import-messed/ast.json @@ -76,6 +76,21 @@ }, "source": "input.css" } + }, + { + "type": "import", + "import": "url('https://fonts.googleapis.com/css2?family=Rubik:wght@300;400;500;600;700')", + "position": { + "start": { + "line": 10, + "column": 29 + }, + "end": { + "line": 10, + "column": 116 + }, + "source": "input.css" + } } ] } diff --git a/test/cases/import-messed/compressed.css b/test/cases/import-messed/compressed.css index 9d888ac7..ba2950d2 100644 --- a/test/cases/import-messed/compressed.css +++ b/test/cases/import-messed/compressed.css @@ -1 +1 @@ -@import url("fineprint.css") print;@import url("bluish.css") projection, tv;@import 'custom.css';@import "common.css" screen, projection;@import url('landscape.css') screen and (orientation:landscape); +@import url("fineprint.css") print;@import url("bluish.css") projection, tv;@import 'custom.css';@import "common.css" screen, projection;@import url('landscape.css') screen and (orientation:landscape);@import url('https://fonts.googleapis.com/css2?family=Rubik:wght@300;400;500;600;700'); diff --git a/test/cases/import-messed/input.css b/test/cases/import-messed/input.css index 6184cf6f..3378d0c5 100644 --- a/test/cases/import-messed/input.css +++ b/test/cases/import-messed/input.css @@ -5,3 +5,6 @@ @import "common.css" screen, projection ; @import url('landscape.css') screen and (orientation:landscape); + + + @import url('https://fonts.googleapis.com/css2?family=Rubik:wght@300;400;500;600;700'); diff --git a/test/cases/import-messed/output.css b/test/cases/import-messed/output.css index 522ea877..32de14cb 100644 --- a/test/cases/import-messed/output.css +++ b/test/cases/import-messed/output.css @@ -7,3 +7,5 @@ @import "common.css" screen, projection; @import url('landscape.css') screen and (orientation:landscape); + +@import url('https://fonts.googleapis.com/css2?family=Rubik:wght@300;400;500;600;700'); diff --git a/test/cases/import/ast.json b/test/cases/import/ast.json index 3b25bc10..f091c9e5 100644 --- a/test/cases/import/ast.json +++ b/test/cases/import/ast.json @@ -76,6 +76,21 @@ }, "source": "input.css" } + }, + { + "type": "import", + "import": "url('https://fonts.googleapis.com/css2?family=Rubik:wght@300;400;500;600;700')", + "position": { + "start": { + "line": 6, + "column": 1 + }, + "end": { + "line": 6, + "column": 88 + }, + "source": "input.css" + } } ] } diff --git a/test/cases/import/compressed.css b/test/cases/import/compressed.css index 9d888ac7..ba2950d2 100644 --- a/test/cases/import/compressed.css +++ b/test/cases/import/compressed.css @@ -1 +1 @@ -@import url("fineprint.css") print;@import url("bluish.css") projection, tv;@import 'custom.css';@import "common.css" screen, projection;@import url('landscape.css') screen and (orientation:landscape); +@import url("fineprint.css") print;@import url("bluish.css") projection, tv;@import 'custom.css';@import "common.css" screen, projection;@import url('landscape.css') screen and (orientation:landscape);@import url('https://fonts.googleapis.com/css2?family=Rubik:wght@300;400;500;600;700'); diff --git a/test/cases/import/input.css b/test/cases/import/input.css index f00b9aad..b407716a 100644 --- a/test/cases/import/input.css +++ b/test/cases/import/input.css @@ -3,3 +3,4 @@ @import 'custom.css'; @import "common.css" screen, projection; @import url('landscape.css') screen and (orientation:landscape); +@import url('https://fonts.googleapis.com/css2?family=Rubik:wght@300;400;500;600;700'); diff --git a/test/cases/import/output.css b/test/cases/import/output.css index 522ea877..32de14cb 100644 --- a/test/cases/import/output.css +++ b/test/cases/import/output.css @@ -7,3 +7,5 @@ @import "common.css" screen, projection; @import url('landscape.css') screen and (orientation:landscape); + +@import url('https://fonts.googleapis.com/css2?family=Rubik:wght@300;400;500;600;700'); diff --git a/test/parse.js b/test/parse.js index b39b6ee2..fcdcf96e 100644 --- a/test/parse.js +++ b/test/parse.js @@ -1,16 +1,16 @@ -var parse = require('../').parse; -var should = require('should'); +const parse = require('../').parse; +const should = require('should'); describe('parse(str)', function() { it('should save the filename and source', function() { - var css = 'booty {\n size: large;\n}\n'; - var ast = parse(css, { + const css = 'booty {\n size: large;\n}\n'; + const ast = parse(css, { source: 'booty.css' }); ast.stylesheet.source.should.equal('booty.css'); - var position = ast.stylesheet.rules[0].position; + const position = ast.stylesheet.rules[0].position; position.start.should.be.ok; position.end.should.be.ok; position.source.should.equal('booty.css'); @@ -55,15 +55,15 @@ describe('parse(str)', function() { }); it('should list the parsing errors and continue parsing', function() { - var result = parse('foo { color= red; } bar { color: blue; } baz {}} boo { display: none}', { + const result = parse('foo { color= red; } bar { color: blue; } baz {}} boo { display: none}', { silent: true, source: 'foo.css' }); - var rules = result.stylesheet.rules; + const rules = result.stylesheet.rules; rules.length.should.be.above(2); - var errors = result.stylesheet.parsingErrors; + const errors = result.stylesheet.parsingErrors; errors.length.should.equal(2); errors[0].should.have.a.property('message'); @@ -77,23 +77,23 @@ describe('parse(str)', function() { }); it('should set parent property', function() { - var result = parse( - 'thing { test: value; }\n' + - '@media (min-width: 100px) { thing { test: value; } }'); + const result = parse( + 'thing { test: value; }\n' + + '@media (min-width: 100px) { thing { test: value; } }'); should(result.parent).equal(null); - var rules = result.stylesheet.rules; + const rules = result.stylesheet.rules; rules.length.should.equal(2); - var rule = rules[0]; + let rule = rules[0]; rule.parent.should.equal(result); rule.declarations.length.should.equal(1); - var decl = rule.declarations[0]; + let decl = rule.declarations[0]; decl.parent.should.equal(rule); - var media = rules[1]; + const media = rules[1]; media.parent.should.equal(result); media.rules.length.should.equal(1); diff --git a/test/stringify.js b/test/stringify.js index a31e5f23..57bbe079 100644 --- a/test/stringify.js +++ b/test/stringify.js @@ -1,19 +1,20 @@ -var stringify = require('../').stringify; -var parse = require('../').parse; -var path = require('path'); -var read = require('fs').readFileSync; -var SourceMapConsumer = require('source-map').SourceMapConsumer; -var SourceMapGenerator = require('source-map').SourceMapGenerator; +const stringify = require('../').stringify; +const parse = require('../').parse; +const path = require('path'); +const read = require('fs').readFileSync; +const SourceMapConsumer = require('source-map').SourceMapConsumer; +const SourceMapGenerator = require('source-map').SourceMapGenerator; describe('stringify(obj, {sourcemap: true})', function() { - var file = 'test/source-map/test.css'; - var src = read(file, 'utf8'); - var stylesheet = parse(src, { source: file }); + const file = 'test/source-map/test.css'; + const src = read(file, 'utf8'); + const stylesheet = parse(src, {source: file}); + function loc(line, column) { return { line: line, column: column, source: file, name: null }; } - var locs = { + const locs = { tobiSelector: loc(1, 0), tobiNameName: loc(2, 2), tobiNameValue: loc(2, 2), @@ -23,10 +24,10 @@ describe('stringify(obj, {sourcemap: true})', function() { }; it('should generate source maps alongside when using identity compiler', function() { - var result = stringify(stylesheet, { sourcemap: true }); + const result = stringify(stylesheet, {sourcemap: true}); result.should.have.property('code'); result.should.have.property('map'); - var map = new SourceMapConsumer(result.map); + const 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); @@ -37,10 +38,10 @@ describe('stringify(obj, {sourcemap: true})', function() { }); it('should generate source maps alongside when using compress compiler', function() { - var result = stringify(stylesheet, { compress: true, sourcemap: true }); + const result = stringify(stylesheet, {compress: true, sourcemap: true}); result.should.have.property('code'); result.should.have.property('map'); - var map = new SourceMapConsumer(result.map); + const 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); @@ -50,14 +51,14 @@ describe('stringify(obj, {sourcemap: true})', function() { }); it('should apply included source maps, with paths adjusted to CWD', function() { - var file = 'test/source-map/apply.css'; - var src = read(file, 'utf8'); - var stylesheet = parse(src, { source: file }); - var result = stringify(stylesheet, { sourcemap: true }); + const file = 'test/source-map/apply.css'; + const src = read(file, 'utf8'); + const stylesheet = parse(src, {source: file}); + const result = stringify(stylesheet, {sourcemap: true}); result.should.have.property('code'); result.should.have.property('map'); - var map = new SourceMapConsumer(result.map); + const map = new SourceMapConsumer(result.map); map.originalPositionFor({ line: 1, column: 0 }).should.eql({ column: 0, line: 1, @@ -74,12 +75,12 @@ describe('stringify(obj, {sourcemap: true})', function() { }); it('should not apply included source maps when inputSourcemap is false', function() { - var file = 'test/source-map/apply.css'; - var src = read(file, 'utf8'); - var stylesheet = parse(src, { source: file }); - var result = stringify(stylesheet, { sourcemap: true, inputSourcemaps: false }); + const file = 'test/source-map/apply.css'; + const src = read(file, 'utf8'); + const stylesheet = parse(src, {source: file}); + const result = stringify(stylesheet, {sourcemap: true, inputSourcemaps: false}); - var map = new SourceMapConsumer(result.map); + const map = new SourceMapConsumer(result.map); map.originalPositionFor({ line: 1, column: 0 }).should.eql({ column: 0, line: 1, @@ -89,13 +90,13 @@ describe('stringify(obj, {sourcemap: true})', function() { }); it('should convert Windows-style paths to URLs', function() { - var originalSep = path.sep; + const originalSep = path.sep; path.sep = '\\'; // Pretend we’re on Windows (if we aren’t already). - var src = 'C:\\test\\source.css'; - var css = 'a { color: black; }' - var stylesheet = parse(css, { source: src }); - var result = stringify(stylesheet, { sourcemap: true }); + const src = 'C:\\test\\source.css'; + const css = 'a { color: black; }'; + const stylesheet = parse(css, {source: src}); + const result = stringify(stylesheet, {sourcemap: true}); result.map.sources.should.eql(['/test/source.css']); @@ -103,35 +104,35 @@ describe('stringify(obj, {sourcemap: true})', function() { }); it('should return source map generator when sourcemap: "generator"', function(){ - var css = 'a { color: black; }'; - var stylesheet = parse(css); - var result = stringify(stylesheet, { sourcemap: 'generator' }); + const css = 'a { color: black; }'; + const stylesheet = parse(css); + const result = stringify(stylesheet, {sourcemap: 'generator'}); result.map.should.be.an.instanceOf(SourceMapGenerator); }); }); describe('stringify(obj, {indent: *})', function() { - var css = - '@media print {\n' + - '\tbody {\n' + - '\t\tbackground: #fff;\n' + - '\t}\n' + - '}'; - var stylesheet = parse(css); + const css = + '@media print {\n' + + '\tbody {\n' + + '\t\tbackground: #fff;\n' + + '\t}\n' + + '}'; + const stylesheet = parse(css); it('should default to two-space indent', function(){ - var result = stringify(stylesheet); + const result = stringify(stylesheet); result.should.eql(css.replace(/\t/g, ' ')); }); it('should indent according to the indent string', function(){ - var result = stringify(stylesheet, { indent: '\t' }); + const result = stringify(stylesheet, {indent: '\t'}); result.should.eql(css); }); it('should accept empty string for indent', function(){ - var result = stringify(stylesheet, { indent: '' }); + const result = stringify(stylesheet, {indent: ''}); result.should.eql(css.replace(/\t/g, '')); }); });