From d9d6d51020b959533325bfa22f343faa7e94449d Mon Sep 17 00:00:00 2001 From: Cory Simmons Date: Wed, 27 Jan 2016 17:01:33 -0500 Subject: [PATCH 1/5] =?UTF-8?q?Remove=20version=20as=20Bower=20doesn?= =?UTF-8?q?=E2=80=99t=20care=20about=20it?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit You need to make releases https://github.com/saabi/vminpoly/releases --- bower.json | 1 - 1 file changed, 1 deletion(-) diff --git a/bower.json b/bower.json index 7a275a3..61bfae7 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,6 @@ { "name": "vminpoly", "main": "vminpoly.js", - "version": "0.1.0", "homepage": "https://github.com/saabi/vminpoly", "authors": [ "Sebastian Ferreyra " From c44454223e558c48067ab31e0e5f9e0504c91d2a Mon Sep 17 00:00:00 2001 From: Cory Simmons Date: Wed, 27 Jan 2016 17:06:33 -0500 Subject: [PATCH 2/5] Get that paper --- bower.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bower.json b/bower.json index 61bfae7..3ff51e1 100644 --- a/bower.json +++ b/bower.json @@ -3,7 +3,8 @@ "main": "vminpoly.js", "homepage": "https://github.com/saabi/vminpoly", "authors": [ - "Sebastian Ferreyra " + "Sebastian Ferreyra ", + "Cory Simmons" ], "description": "A polyfill for CSS units vw, vh & vmin and now some media queries to boot.", "keywords": [ From 65bcf48aa1c3fd1f3daf17ff2af761fe252a59d5 Mon Sep 17 00:00:00 2001 From: Cory Simmons Date: Wed, 27 Jan 2016 17:08:20 -0500 Subject: [PATCH 3/5] Update LICENSE --- LICENSE | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/LICENSE b/LICENSE index 63e27f8..f475d83 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2010-2014 Sebastian E. Ferreyra Pons +Copyright (c) 2010-2016 Sebastian E. Ferreyra Pons Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -19,4 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - From f8f50637cbd91fa5d40fe7fe95ea878ba9624c28 Mon Sep 17 00:00:00 2001 From: Cory Simmons Date: Wed, 27 Jan 2016 17:24:17 -0500 Subject: [PATCH 4/5] Organize repo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I also condensed all the scripts into one importable script. If someone is using a custom CSS tokenizer/parser and don’t want to use the one bundled with this, they can still access a clean version of vminpoly.js from src folder. --- bower.json | 2 +- demo2.html | 57 - dist/vminpoly.dist.js | 1518 ++++++++++++++++++++++++ dist/vminpoly.dist.min.js | 2 + test2.css => examples/example-2.css | 121 +- examples/example-2.html | 36 + examples/example.css | 11 + examples/example.html | 13 + index.html | 40 - vminpoly.coffee => src/vminpoly.coffee | 0 vminpoly.js => src/vminpoly.js | 0 test.css | 11 - parser.js => vendor/parser.js | 0 tokenizer.js => vendor/tokenizer.js | 0 14 files changed, 1671 insertions(+), 140 deletions(-) delete mode 100644 demo2.html create mode 100644 dist/vminpoly.dist.js create mode 100644 dist/vminpoly.dist.min.js rename test2.css => examples/example-2.css (91%) create mode 100644 examples/example-2.html create mode 100644 examples/example.css create mode 100644 examples/example.html delete mode 100644 index.html rename vminpoly.coffee => src/vminpoly.coffee (100%) rename vminpoly.js => src/vminpoly.js (100%) delete mode 100644 test.css rename parser.js => vendor/parser.js (100%) rename tokenizer.js => vendor/tokenizer.js (100%) diff --git a/bower.json b/bower.json index 3ff51e1..adf4a3d 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "vminpoly", - "main": "vminpoly.js", + "main": "dist/vminpoly.dist.js", "homepage": "https://github.com/saabi/vminpoly", "authors": [ "Sebastian Ferreyra ", diff --git a/demo2.html b/demo2.html deleted file mode 100644 index b948af4..0000000 --- a/demo2.html +++ /dev/null @@ -1,57 +0,0 @@ - - - - Sophisticated vw, vh & vmin example - - - - -
-
Highlights
-
-
News item 1
-
News item 2
-
News item 3
-
-
-
ad 1
-
ad 2
-
ad 3
-
-
- - - - - - - diff --git a/dist/vminpoly.dist.js b/dist/vminpoly.dist.js new file mode 100644 index 0000000..262c454 --- /dev/null +++ b/dist/vminpoly.dist.js @@ -0,0 +1,1518 @@ +// vminpoly - Viewport units for old browsers https://github.com/saabi/vminpoly + +if (!Array.prototype.filter) +{ + Array.prototype.filter = function(fun /*, thisp*/) + { + var len = this.length; + if (typeof fun != "function") + throw new TypeError(); + + var res = new Array(); + var thisp = arguments[1]; + for (var i = 0; i < len; i++) + { + if (i in this) + { + var val = this[i]; // in case fun mutates this + if (fun.call(thisp, val, i, this)) + res.push(val); + } + } + + return res; + }; +} + + +// tokenizer.js +(function (root, factory) { + // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js, + // Rhino, and plain browser loading. + if (typeof define === 'function' && define.amd) { + define(['exports'], factory); + } else if (typeof exports !== 'undefined') { + factory(exports); + } else { + factory(root); + } +}(this, function (exports) { + +var between = function (num, first, last) { return num >= first && num <= last; } +function digit(code) { return between(code, 0x30,0x39); } +function hexdigit(code) { return digit(code) || between(code, 0x41,0x46) || between(code, 0x61,0x66); } +function uppercaseletter(code) { return between(code, 0x41,0x5a); } +function lowercaseletter(code) { return between(code, 0x61,0x7a); } +function letter(code) { return uppercaseletter(code) || lowercaseletter(code); } +function nonascii(code) { return code >= 0xa0; } +function namestartchar(code) { return letter(code) || nonascii(code) || code == 0x5f; } +function namechar(code) { return namestartchar(code) || digit(code) || code == 0x2d; } +function nonprintable(code) { return between(code, 0,8) || between(code, 0xe,0x1f) || between(code, 0x7f,0x9f); } +function newline(code) { return code == 0xa || code == 0xc; } +function whitespace(code) { return newline(code) || code == 9 || code == 0x20; } +function badescape(code) { return newline(code) || isNaN(code); } + +// Note: I'm not yet acting smart enough to actually handle astral characters. +var maximumallowedcodepoint = 0x10ffff; + +function tokenize(str, options) { + if(options == undefined) options = {transformFunctionWhitespace:false, scientificNotation:false}; + var i = -1; + var tokens = []; + var state = "data"; + var code; + var currtoken; + + // Line number information. + var line = 0; + var column = 0; + // The only use of lastLineLength is in reconsume(). + var lastLineLength = 0; + var incrLineno = function() { + line += 1; + lastLineLength = column; + column = 0; + }; + var locStart = {line:line, column:column}; + + var next = function(num) { if(num === undefined) num = 1; return str.charCodeAt(i+num); }; + var consume = function(num) { + if(num === undefined) + num = 1; + i += num; + code = str.charCodeAt(i); + if (newline(code)) incrLineno(); + else column += num; + //console.log('Consume '+i+' '+String.fromCharCode(code) + ' 0x' + code.toString(16)); + return true; + }; + var reconsume = function() { + i -= 1; + if (newline(code)) { + line -= 1; + column = lastLineLength; + } else { + column -= 1; + } + locStart.line = line; + locStart.column = column; + return true; + }; + var eof = function() { return i >= str.length; }; + var donothing = function() {}; + var emit = function(token) { + if(token) { + token.finish(); + } else { + token = currtoken.finish(); + } + if (options.loc === true) { + token.loc = {}; + token.loc.start = {line:locStart.line, column:locStart.column}; + locStart = {line: line, column: column}; + token.loc.end = locStart; + } + tokens.push(token); + //console.log('Emitting ' + token); + currtoken = undefined; + return true; + }; + var create = function(token) { currtoken = token; return true; }; + var parseerror = function() { console.log("Parse error at index " + i + ", processing codepoint 0x" + code.toString(16) + " in state " + state + ".");return true; }; + var catchfire = function(msg) { console.log("MAJOR SPEC ERROR: " + msg); return true;} + var switchto = function(newstate) { + state = newstate; + //console.log('Switching to ' + state); + return true; + }; + var consumeEscape = function() { + // Assume the the current character is the \ + consume(); + if(hexdigit(code)) { + // Consume 1-6 hex digits + var digits = []; + for(var total = 0; total < 6; total++) { + if(hexdigit(code)) { + digits.push(code); + consume(); + } else { break; } + } + if(digits.map != null) { + var value = parseInt(digits.map(String.fromCharCode).join(''), 16); + } else { + d1 = []; + _len = digits.length; + for (_i = 0; _i < _len; _i++) { d1.push(String.fromCharCode(digits[_i])); } + var value = parseInt(d1.join(''), 16); + } + if( value > maximumallowedcodepoint ) value = 0xfffd; + // If the current char is whitespace, cool, we'll just eat it. + // Otherwise, put it back. + if(!whitespace(code)) reconsume(); + return value; + } else { + return code; + } + }; + + for(;;) { + if(i > str.length*2) return "I'm infinite-looping!"; + consume(); + switch(state) { + case "data": + if(whitespace(code)) { + emit(new WhitespaceToken); + while(whitespace(next())) consume(); + } + else if(code == 0x22) switchto("double-quote-string"); + else if(code == 0x23) switchto("hash"); + else if(code == 0x27) switchto("single-quote-string"); + else if(code == 0x28) emit(new OpenParenToken); + else if(code == 0x29) emit(new CloseParenToken); + else if(code == 0x2b) { + if(digit(next()) || (next() == 0x2e && digit(next(2)))) switchto("number") && reconsume(); + else emit(new DelimToken(code)); + } + else if(code == 0x2d) { + if(next(1) == 0x2d && next(2) == 0x3e) consume(2) && emit(new CDCToken); + else if(digit(next()) || (next(1) == 0x2e && digit(next(2)))) switchto("number") && reconsume(); + else switchto('ident') && reconsume(); + } + else if(code == 0x2e) { + if(digit(next())) switchto("number") && reconsume(); + else emit(new DelimToken(code)); + } + else if(code == 0x2f) { + if(next() == 0x2a) consume() && switchto("comment"); + else emit(new DelimToken(code)); + } + else if(code == 0x3a) emit(new ColonToken); + else if(code == 0x3b) emit(new SemicolonToken); + else if(code == 0x3c) { + if(next(1) == 0x21 && next(2) == 0x2d && next(3) == 0x2d) consume(3) && emit(new CDOToken); + else emit(new DelimToken(code)); + } + else if(code == 0x40) switchto("at-keyword"); + else if(code == 0x5b) emit(new OpenSquareToken); + else if(code == 0x5c) { + if(badescape(next())) parseerror() && emit(new DelimToken(code)); + else switchto('ident') && reconsume(); + } + else if(code == 0x5d) emit(new CloseSquareToken); + else if(code == 0x7b) emit(new OpenCurlyToken); + else if(code == 0x7d) emit(new CloseCurlyToken); + else if(digit(code)) switchto("number") && reconsume(); + else if(code == 0x55 || code == 0x75) { + if(next(1) == 0x2b && hexdigit(next(2))) consume() && switchto("unicode-range"); + else switchto('ident') && reconsume(); + } + else if(namestartchar(code)) switchto('ident') && reconsume(); + else if(eof()) { emit(new EOFToken); return tokens; } + else emit(new DelimToken(code)); + break; + + case "double-quote-string": + if(currtoken == undefined) create(new StringToken); + + if(code == 0x22) emit() && switchto("data"); + else if(eof()) parseerror() && emit() && switchto("data") && reconsume(); + else if(newline(code)) parseerror() && emit(new BadStringToken) && switchto("data") && reconsume(); + else if(code == 0x5c) { + if(badescape(next())) parseerror() && emit(new BadStringToken) && switchto("data"); + else if(newline(next())) consume(); + else currtoken.append(consumeEscape()); + } + else currtoken.append(code); + break; + + case "single-quote-string": + if(currtoken == undefined) create(new StringToken); + + if(code == 0x27) emit() && switchto("data"); + else if(eof()) parseerror() && emit() && switchto("data"); + else if(newline(code)) parseerror() && emit(new BadStringToken) && switchto("data") && reconsume(); + else if(code == 0x5c) { + if(badescape(next())) parseerror() && emit(new BadStringToken) && switchto("data"); + else if(newline(next())) consume(); + else currtoken.append(consumeEscape()); + } + else currtoken.append(code); + break; + + case "hash": + if(namechar(code)) create(new HashToken(code)) && switchto("hash-rest"); + else if(code == 0x5c) { + if(badescape(next())) parseerror() && emit(new DelimToken(0x23)) && switchto("data") && reconsume(); + else create(new HashToken(consumeEscape())) && switchto('hash-rest'); + } + else emit(new DelimToken(0x23)) && switchto('data') && reconsume(); + break; + + case "hash-rest": + if(namechar(code)) currtoken.append(code); + else if(code == 0x5c) { + if(badescape(next())) parseerror() && emit() && switchto("data") && reconsume(); + else currtoken.append(consumeEscape()); + } + else emit() && switchto('data') && reconsume(); + break; + + case "comment": + if(code == 0x2a) { + if(next() == 0x2f) consume() && switchto('data'); + else donothing(); + } + else if(eof()) parseerror() && switchto('data') && reconsume(); + else donothing(); + break; + + case "at-keyword": + if(code == 0x2d) { + if(namestartchar(next())) create(new AtKeywordToken(0x2d)) && switchto('at-keyword-rest'); + else if(next(1) == 0x5c && !badescape(next(2))) create(new AtKeywordtoken(0x2d)) && switchto('at-keyword-rest'); + else parseerror() && emit(new DelimToken(0x40)) && switchto('data') && reconsume(); + } + else if(namestartchar(code)) create(new AtKeywordToken(code)) && switchto('at-keyword-rest'); + else if(code == 0x5c) { + if(badescape(next())) parseerror() && emit(new DelimToken(0x23)) && switchto("data") && reconsume(); + else create(new AtKeywordToken(consumeEscape())) && switchto('at-keyword-rest'); + } + else emit(new DelimToken(0x40)) && switchto('data') && reconsume(); + break; + + case "at-keyword-rest": + if(namechar(code)) currtoken.append(code); + else if(code == 0x5c) { + if(badescape(next())) parseerror() && emit() && switchto("data") && reconsume(); + else currtoken.append(consumeEscape()); + } + else emit() && switchto('data') && reconsume(); + break; + + case "ident": + if(code == 0x2d) { + if(namestartchar(next())) create(new IdentifierToken(code)) && switchto('ident-rest'); + else if(next(1) == 0x5c && !badescape(next(2))) create(new IdentifierToken(code)) && switchto('ident-rest'); + else emit(new DelimToken(0x2d)) && switchto('data'); + } + else if(namestartchar(code)) create(new IdentifierToken(code)) && switchto('ident-rest'); + else if(code == 0x5c) { + if(badescape(next())) parseerror() && switchto("data") && reconsume(); + else create(new IdentifierToken(consumeEscape())) && switchto('ident-rest'); + } + else catchfire("Hit the generic 'else' clause in ident state.") && switchto('data') && reconsume(); + break; + + case "ident-rest": + if(namechar(code)) currtoken.append(code); + else if(code == 0x5c) { + if(badescape(next())) parseerror() && emit() && switchto("data") && reconsume(); + else currtoken.append(consumeEscape()); + } + else if(code == 0x28) { + if(currtoken.ASCIImatch('url')) switchto('url'); + else emit(new FunctionToken(currtoken)) && switchto('data'); + } + else if(whitespace(code) && options.transformFunctionWhitespace) switchto('transform-function-whitespace') && reconsume(); + else emit() && switchto('data') && reconsume(); + break; + + case "transform-function-whitespace": + if(whitespace(next())) donothing(); + else if(code == 0x28) emit(new FunctionToken(currtoken)) && switchto('data'); + else emit() && switchto('data') && reconsume(); + break; + + case "number": + create(new NumberToken()); + + if(code == 0x2d) { + if(digit(next())) consume() && currtoken.append([0x2d,code]) && switchto('number-rest'); + else if(next(1) == 0x2e && digit(next(2))) consume(2) && currtoken.append([0x2d,0x2e,code]) && switchto('number-fraction'); + else switchto('data') && reconsume(); + } + else if(code == 0x2b) { + if(digit(next())) consume() && currtoken.append([0x2b,code]) && switchto('number-rest'); + else if(next(1) == 0x2e && digit(next(2))) consume(2) && currtoken.append([0x2b,0x2e,code]) && switchto('number-fraction'); + else switchto('data') && reconsume(); + } + else if(digit(code)) currtoken.append(code) && switchto('number-rest'); + else if(code == 0x2e) { + if(digit(next())) consume() && currtoken.append([0x2e,code]) && switchto('number-fraction'); + else switchto('data') && reconsume(); + } + else switchto('data') && reconsume(); + break; + + case "number-rest": + if(digit(code)) currtoken.append(code); + else if(code == 0x2e) { + if(digit(next())) consume() && currtoken.append([0x2e,code]) && switchto('number-fraction'); + else emit() && switchto('data') && reconsume(); + } + else if(code == 0x25) emit(new PercentageToken(currtoken)) && switchto('data'); + else if(code == 0x45 || code == 0x65) { + if(digit(next())) consume() && currtoken.append([0x25,code]) && switchto('sci-notation'); + else if((next(1) == 0x2b || next(1) == 0x2d) && digit(next(2))) currtoken.append([0x25,next(1),next(2)]) && consume(2) && switchto('sci-notation'); + else create(new DimensionToken(currtoken,code)) && switchto('dimension'); + } + else if(code == 0x2d) { + if(namestartchar(next())) consume() && create(new DimensionToken(currtoken,[0x2d,code])) && switchto('dimension'); + else if(next(1) == 0x5c && badescape(next(2))) parseerror() && emit() && switchto('data') && reconsume(); + else if(next(1) == 0x5c) consume() && create(new DimensionToken(currtoken, [0x2d,consumeEscape()])) && switchto('dimension'); + else emit() && switchto('data') && reconsume(); + } + else if(namestartchar(code)) create(new DimensionToken(currtoken, code)) && switchto('dimension'); + else if(code == 0x5c) { + if(badescape(next)) parseerror() && emit() && switchto('data') && reconsume(); + else create(new DimensionToken(currtoken,consumeEscape)) && switchto('dimension'); + } + else emit() && switchto('data') && reconsume(); + break; + + case "number-fraction": + currtoken.type = "number"; + + if(digit(code)) currtoken.append(code); + else if(code == 0x25) emit(new PercentageToken(currtoken)) && switchto('data'); + else if(code == 0x45 || code == 0x65) { + if(digit(next())) consume() && currtoken.append([0x65,code]) && switchto('sci-notation'); + else if((next(1) == 0x2b || next(1) == 0x2d) && digit(next(2))) currtoken.append([0x65,next(1),next(2)]) && consume(2) && switchto('sci-notation'); + else create(new DimensionToken(currtoken,code)) && switchto('dimension'); + } + else if(code == 0x2d) { + if(namestartchar(next())) consume() && create(new DimensionToken(currtoken,[0x2d,code])) && switchto('dimension'); + else if(next(1) == 0x5c && badescape(next(2))) parseerror() && emit() && switchto('data') && reconsume(); + else if(next(1) == 0x5c) consume() && create(new DimensionToken(currtoken, [0x2d,consumeEscape()])) && switchto('dimension'); + else emit() && switchto('data') && reconsume(); + } + else if(namestartchar(code)) create(new DimensionToken(currtoken, code)) && switchto('dimension'); + else if(code == 0x5c) { + if(badescape(next)) parseerror() && emit() && switchto('data') && reconsume(); + else create(new DimensionToken(currtoken,consumeEscape())) && switchto('dimension'); + } + else emit() && switchto('data') && reconsume(); + break; + + case "dimension": + if(namechar(code)) currtoken.append(code); + else if(code == 0x5c) { + if(badescape(next())) parseerror() && emit() && switchto('data') && reconsume(); + else currtoken.append(consumeEscape()); + } + else emit() && switchto('data') && reconsume(); + break; + + case "sci-notation": + currtoken.type = "number"; + + if(digit(code)) currtoken.append(code); + else emit() && switchto('data') && reconsume(); + break; + + case "url": + if(eof()) parseerror() && emit(new BadURLToken) && switchto('data'); + else if(code == 0x22) switchto('url-double-quote'); + else if(code == 0x27) switchto('url-single-quote'); + else if(code == 0x29) emit(new URLToken) && switchto('data'); + else if(whitespace(code)) donothing(); + else switchto('url-unquoted') && reconsume(); + break; + + case "url-double-quote": + if(! (currtoken instanceof URLToken)) create(new URLToken); + + if(eof()) parseerror() && emit(new BadURLToken) && switchto('data'); + else if(code == 0x22) switchto('url-end'); + else if(newline(code)) parseerror() && switchto('bad-url'); + else if(code == 0x5c) { + if(newline(next())) consume(); + else if(badescape(next())) parseerror() && emit(new BadURLToken) && switchto('data') && reconsume(); + else currtoken.append(consumeEscape()); + } + else currtoken.append(code); + break; + + case "url-single-quote": + if(! (currtoken instanceof URLToken)) create(new URLToken); + + if(eof()) parseerror() && emit(new BadURLToken) && switchto('data'); + else if(code == 0x27) switchto('url-end'); + else if(newline(code)) parseerror() && switchto('bad-url'); + else if(code == 0x5c) { + if(newline(next())) consume(); + else if(badescape(next())) parseerror() && emit(new BadURLToken) && switchto('data') && reconsume(); + else currtoken.append(consumeEscape()); + } + else currtoken.append(code); + break; + + case "url-end": + if(eof()) parseerror() && emit(new BadURLToken) && switchto('data'); + else if(whitespace(code)) donothing(); + else if(code == 0x29) emit() && switchto('data'); + else parseerror() && switchto('bad-url') && reconsume(); + break; + + case "url-unquoted": + if(! (currtoken instanceof URLToken)) create(new URLToken); + + if(eof()) parseerror() && emit(new BadURLToken) && switchto('data'); + else if(whitespace(code)) switchto('url-end'); + else if(code == 0x29) emit() && switchto('data'); + else if(code == 0x22 || code == 0x27 || code == 0x28 || nonprintable(code)) parseerror() && switchto('bad-url'); + else if(code == 0x5c) { + if(badescape(next())) parseerror() && switchto('bad-url'); + else currtoken.append(consumeEscape()); + } + else currtoken.append(code); + break; + + case "bad-url": + if(eof()) parseerror() && emit(new BadURLToken) && switchto('data'); + else if(code == 0x29) emit(new BadURLToken) && switchto('data'); + else if(code == 0x5c) { + if(badescape(next())) donothing(); + else consumeEscape(); + } + else donothing(); + break; + + case "unicode-range": + // We already know that the current code is a hexdigit. + + var start = [code], end = [code]; + + for(var total = 1; total < 6; total++) { + if(hexdigit(next())) { + consume(); + start.push(code); + end.push(code); + } + else break; + } + + if(next() == 0x3f) { + for(;total < 6; total++) { + if(next() == 0x3f) { + consume(); + start.push("0".charCodeAt(0)); + end.push("f".charCodeAt(0)); + } + else break; + } + emit(new UnicodeRangeToken(start,end)) && switchto('data'); + } + else if(next(1) == 0x2d && hexdigit(next(2))) { + consume(); + consume(); + end = [code]; + for(var total = 1; total < 6; total++) { + if(hexdigit(next())) { + consume(); + end.push(code); + } + else break; + } + emit(new UnicodeRangeToken(start,end)) && switchto('data'); + } + else emit(new UnicodeRangeToken(start)) && switchto('data'); + break; + + default: + catchfire("Unknown state '" + state + "'"); + } + } +} + +function stringFromCodeArray(arr) { + return String.fromCharCode.apply(null,arr.filter(function(e){return e;})); +} + +function CSSParserToken(options) { return this; } +CSSParserToken.prototype.finish = function() { return this; } +CSSParserToken.prototype.toString = function() { return this.tokenType; } +CSSParserToken.prototype.toSourceString = CSSParserToken.prototype.toString; +CSSParserToken.prototype.toJSON = function() { return this.toString(); } + +function BadStringToken() { return this; } +BadStringToken.prototype = new CSSParserToken; +BadStringToken.prototype.tokenType = "BADSTRING"; + +function BadURLToken() { return this; } +BadURLToken.prototype = new CSSParserToken; +BadURLToken.prototype.tokenType = "BADURL"; + +function WhitespaceToken() { return this; } +WhitespaceToken.prototype = new CSSParserToken; +WhitespaceToken.prototype.tokenType = "WHITESPACE"; +WhitespaceToken.prototype.toString = function() { return "WS"; } +WhitespaceToken.prototype.toSourceString = function() { return " "; } + +function CDOToken() { return this; } +CDOToken.prototype = new CSSParserToken; +CDOToken.prototype.tokenType = "CDO"; + +function CDCToken() { return this; } +CDCToken.prototype = new CSSParserToken; +CDCToken.prototype.tokenType = "CDC"; + +function ColonToken() { return this; } +ColonToken.prototype = new CSSParserToken; +ColonToken.prototype.tokenType = ":"; + +function SemicolonToken() { return this; } +SemicolonToken.prototype = new CSSParserToken; +SemicolonToken.prototype.tokenType = ";"; + +function OpenCurlyToken() { return this; } +OpenCurlyToken.prototype = new CSSParserToken; +OpenCurlyToken.prototype.tokenType = "{"; + +function CloseCurlyToken() { return this; } +CloseCurlyToken.prototype = new CSSParserToken; +CloseCurlyToken.prototype.tokenType = "}"; + +function OpenSquareToken() { return this; } +OpenSquareToken.prototype = new CSSParserToken; +OpenSquareToken.prototype.tokenType = "["; + +function CloseSquareToken() { return this; } +CloseSquareToken.prototype = new CSSParserToken; +CloseSquareToken.prototype.tokenType = "]"; + +function OpenParenToken() { return this; } +OpenParenToken.prototype = new CSSParserToken; +OpenParenToken.prototype.tokenType = "("; + +function CloseParenToken() { return this; } +CloseParenToken.prototype = new CSSParserToken; +CloseParenToken.prototype.tokenType = ")"; + +function EOFToken() { return this; } +EOFToken.prototype = new CSSParserToken; +EOFToken.prototype.tokenType = "EOF"; + +function DelimToken(code) { + this.value = String.fromCharCode(code); + return this; +} +DelimToken.prototype = new CSSParserToken; +DelimToken.prototype.tokenType = "DELIM"; +DelimToken.prototype.toString = function() { return "DELIM("+this.value+")"; } +DelimToken.prototype.toSourceString = function() { return this.value; } + +function StringValuedToken() { return this; } +StringValuedToken.prototype = new CSSParserToken; +StringValuedToken.prototype.append = function(val) { + if(val instanceof Array) { + for(var i = 0; i < val.length; i++) { + this.value.push(val[i]); + } + } else { + this.value.push(val); + } + return true; +} +StringValuedToken.prototype.finish = function() { + this.value = this.valueAsString(); + return this; +} +StringValuedToken.prototype.ASCIImatch = function(str) { + return this.valueAsString().toLowerCase() == str.toLowerCase(); +} +StringValuedToken.prototype.valueAsString = function() { + if(typeof this.value == 'string') return this.value; + return stringFromCodeArray(this.value); +} +StringValuedToken.prototype.valueAsCodes = function() { + if(typeof this.value == 'string') { + var ret = []; + for(var i = 0; i < this.value.length; i++) + ret.push(this.value.charCodeAt(i)); + return ret; + } + return this.value.filter(function(e){return e;}); +} + +function IdentifierToken(val) { + this.value = []; + this.append(val); +} +IdentifierToken.prototype = new StringValuedToken; +IdentifierToken.prototype.tokenType = "IDENT"; +IdentifierToken.prototype.toString = function() { return "IDENT("+this.value+")"; } +IdentifierToken.prototype.toSourceString = function() { return this.value; } + +function FunctionToken(val) { + // These are always constructed by passing an IdentifierToken + this.value = val.finish().value; +} +FunctionToken.prototype = new StringValuedToken; +FunctionToken.prototype.tokenType = "FUNCTION"; +FunctionToken.prototype.toString = function() { return "FUNCTION("+this.value+")"; } +FunctionToken.prototype.toSourceString = function() { return this.value; } + +function AtKeywordToken(val) { + this.value = []; + this.append(val); +} +AtKeywordToken.prototype = new StringValuedToken; +AtKeywordToken.prototype.tokenType = "AT-KEYWORD"; +AtKeywordToken.prototype.toString = function() { return "AT("+this.value+")"; } +AtKeywordToken.prototype.toSourceString = function() { return "@"+this.value; } + +function HashToken(val) { + this.value = []; + this.append(val); +} +HashToken.prototype = new StringValuedToken; +HashToken.prototype.tokenType = "HASH"; +HashToken.prototype.toString = function() { return "HASH("+this.value+")"; } +HashToken.prototype.toSourceString = function() { return "#"+this.value; } + +function StringToken(val) { + this.value = []; + this.append(val); +} +StringToken.prototype = new StringValuedToken; +StringToken.prototype.tokenType = "STRING"; +StringToken.prototype.toString = function() { return "\""+this.value+"\""; } +StringToken.prototype.toSourceString = StringToken.prototype.toString; + +function URLToken(val) { + this.value = []; + this.append(val); +} +URLToken.prototype = new StringValuedToken; +URLToken.prototype.tokenType = "URL"; +URLToken.prototype.toString = function() { return "URL("+this.value+")"; } +URLToken.prototype.toSourceString = function() { return "url('"+this.value+"')"; } + +function NumberToken(val) { + this.value = []; + this.append(val); + this.type = "integer"; +} +NumberToken.prototype = new StringValuedToken; +NumberToken.prototype.tokenType = "NUMBER"; +NumberToken.prototype.toString = function() { + if(this.type == "integer") + return "INT("+this.value+")"; + return "NUMBER("+this.value+")"; +} +NumberToken.prototype.toSourceString = function() { + if(this.type == "integer") + return this.value; + return this.value; +} +NumberToken.prototype.finish = function() { + this.repr = this.valueAsString(); + this.value = this.repr * 1; + if(Math.abs(this.value) % 1 != 0) this.type = "number"; + return this; +} + +function PercentageToken(val) { + // These are always created by passing a NumberToken as val + val.finish(); + this.value = val.value; + this.repr = val.repr; +} +PercentageToken.prototype = new CSSParserToken; +PercentageToken.prototype.tokenType = "PERCENTAGE"; +PercentageToken.prototype.toString = function() { return "PERCENTAGE("+this.value+")"; } +PercentageToken.prototype.toSourceString = function() { return this.value+'%'; } + +function DimensionToken(val,unit) { + // These are always created by passing a NumberToken as the val + val.finish(); + this.num = val.value; + this.unit = []; + this.repr = val.repr; + this.append(unit); +} +DimensionToken.prototype = new CSSParserToken; +DimensionToken.prototype.tokenType = "DIMENSION"; +DimensionToken.prototype.toString = function() { return "DIM("+this.num+","+this.unit+")"; } +DimensionToken.prototype.toSourceString = function() { return this.num+this.unit; } +DimensionToken.prototype.append = function(val) { + if(val instanceof Array) { + for(var i = 0; i < val.length; i++) { + this.unit.push(val[i]); + } + } else { + this.unit.push(val); + } + return true; +} +DimensionToken.prototype.finish = function() { + this.unit = stringFromCodeArray(this.unit); + this.repr += this.unit; + return this; +} + +function UnicodeRangeToken(start,end) { + // start and end are array of char codes, completely finished + start = parseInt(stringFromCodeArray(start),16); + if(end === undefined) end = start + 1; + else end = parseInt(stringFromCodeArray(end),16); + + if(start > maximumallowedcodepoint) end = start; + if(end < start) end = start; + if(end > maximumallowedcodepoint) end = maximumallowedcodepoint; + + this.start = start; + this.end = end; + return this; +} +UnicodeRangeToken.prototype = new CSSParserToken; +UnicodeRangeToken.prototype.tokenType = "UNICODE-RANGE"; +UnicodeRangeToken.prototype.toString = function() { + if(this.start+1 == this.end) + return "UNICODE-RANGE("+this.start.toString(16).toUpperCase()+")"; + if(this.start < this.end) + return "UNICODE-RANGE("+this.start.toString(16).toUpperCase()+"-"+this.end.toString(16).toUpperCase()+")"; + return "UNICODE-RANGE()"; +} +UnicodeRangeToken.prototype.toSourceString = function() { + if(this.start+1 == this.end) + return "UNICODE-RANGE("+this.start.toString(16).toUpperCase()+")"; + if(this.start < this.end) + return "UNICODE-RANGE("+this.start.toString(16).toUpperCase()+"-"+this.end.toString(16).toUpperCase()+")"; + return "UNICODE-RANGE()"; +} +UnicodeRangeToken.prototype.contains = function(code) { + return code >= this.start && code < this.end; +} + + +// Exportation. +// TODO: also export the various tokens objects? +exports.tokenize = tokenize; + +})); + + +// parser.js +(function (root, factory) { + // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js, + // Rhino, and plain browser loading. + if (typeof define === 'function' && define.amd) { + define(['exports'], factory); + } else if (typeof exports !== 'undefined') { + factory(exports); + } else { + factory(root); + } +}(this, function (exports) { + +function parse(tokens) { + var mode = 'top-level'; + var i = -1; + var token; + + var stylesheet = new Stylesheet; + var stack = [stylesheet]; + var rule = stack[0]; + + var consume = function(advance) { + if(advance === undefined) advance = 1; + i += advance; + if(i < tokens.length) + token = tokens[i]; + else + token = new EOFToken; + return true; + }; + var reprocess = function() { + i--; + return true; + } + var next = function() { + return tokens[i+1]; + }; + var switchto = function(newmode) { + if(newmode === undefined) { + if(rule.fillType !== '') + mode = rule.fillType; + else if(rule.type == 'STYLESHEET') + mode = 'top-level' + else { console.log("Unknown rule-type while switching to current rule's content mode: ",rule); mode = ''; } + } else { + mode = newmode; + } + return true; + } + var push = function(newRule) { + rule = newRule; + stack.push(rule); + return true; + } + var parseerror = function(msg) { + console.log("Parse error at token " + i + ": " + token + ".\n" + msg); + return true; + } + var pop = function() { + var oldrule = stack.pop(); + rule = stack[stack.length - 1]; + rule.append(oldrule); + return true; + } + var discard = function() { + stack.pop(); + rule = stack[stack.length - 1]; + return true; + } + var finish = function() { + while(stack.length > 1) { + pop(); + } + } + + for(;;) { + consume(); + + if (token.tokenType === 'DELIM' && token.value === '\r') + continue; + + switch(mode) { + case "top-level": + switch(token.tokenType) { + case "CDO": + case "CDC": + case "WHITESPACE": break; + case "AT-KEYWORD": push(new AtRule(token.value)) && switchto('at-rule'); break; + case "{": parseerror("Attempt to open a curly-block at top-level.") && consumeAPrimitive(); break; + case "EOF": finish(); return stylesheet; + default: push(new StyleRule) && switchto('selector') && reprocess(); + } + break; + + case "at-rule": + switch(token.tokenType) { + case ";": pop() && switchto(); break; + case "{": + if(rule.fillType !== '') switchto(rule.fillType); + else parseerror("Attempt to open a curly-block in a statement-type at-rule.") && discard() && switchto('next-block') && reprocess(); + break; + case "EOF": finish(); return stylesheet; + default: rule.appendPrelude(consumeAPrimitive()); + } + break; + + case "rule": + switch(token.tokenType) { + case "WHITESPACE": break; + case "}": pop() && switchto(); break; + case "AT-KEYWORD": push(new AtRule(token.value)) && switchto('at-rule'); break; + case "EOF": finish(); return stylesheet; + default: push(new StyleRule) && switchto('selector') && reprocess(); + } + break; + + case "selector": + switch(token.tokenType) { + case "{": switchto('declaration'); break; + case "EOF": discard() && finish(); return stylesheet; + default: rule.appendSelector(consumeAPrimitive()); + } + break; + + case "declaration": + switch(token.tokenType) { + case "WHITESPACE": + case ";": break; + case "}": pop() && switchto(); break; + case "AT-RULE": push(new AtRule(token.value)) && switchto('at-rule'); break; + case "IDENT": push(new Declaration(token.value)) && switchto('after-declaration-name'); break; + case "EOF": finish(); return stylesheet; + default: parseerror() && discard() && switchto('next-declaration'); + } + break; + + case "after-declaration-name": + switch(token.tokenType) { + case "WHITESPACE": break; + case ":": switchto('declaration-value'); break; + case ";": parseerror("Incomplete declaration - semicolon after property name.") && discard() && switchto(); break; + case "EOF": discard() && finish(); return stylesheet; + default: parseerror("Invalid declaration - additional token after property name") && discard() && switchto('next-declaration'); + } + break; + + case "declaration-value": + switch(token.tokenType) { + case "DELIM": + if(token.value == "!" && next().tokenType == 'IDENTIFIER' && next().value.toLowerCase() == "important") { + consume(); + rule.important = true; + switchto('declaration-end'); + } else { + rule.append(token); + } + break; + case ";": pop() && switchto(); break; + case "}": pop() && pop() && switchto(); break; + case "EOF": finish(); return stylesheet; + default: rule.append(consumeAPrimitive()); + } + break; + + case "declaration-end": + switch(token.tokenType) { + case "WHITESPACE": break; + case ";": pop() && switchto(); break; + case "}": pop() && pop() && switchto(); break; + case "EOF": finish(); return stylesheet; + default: parseerror("Invalid declaration - additional token after !important.") && discard() && switchto('next-declaration'); + } + break; + + case "next-block": + switch(token.tokenType) { + case "{": consumeAPrimitive() && switchto(); break; + case "EOF": finish(); return stylesheet; + default: consumeAPrimitive(); break; + } + break; + + case "next-declaration": + switch(token.tokenType) { + case ";": switchto('declaration'); break; + case "}": switchto('declaration') && reprocess(); break; + case "EOF": finish(); return stylesheet; + default: consumeAPrimitive(); break; + } + break; + + default: + // If you hit this, it's because one of the switchto() calls is typo'd. + console.log('Unknown parsing mode: ' + mode); + return; + } + } + + function consumeAPrimitive() { + switch(token.tokenType) { + case "(": + case "[": + case "{": return consumeASimpleBlock(); + case "FUNCTION": return consumeAFunc(); + default: return token; + } + } + + function consumeASimpleBlock() { + var endingTokenType = {"(":")", "[":"]", "{":"}"}[token.tokenType]; + var block = new SimpleBlock(token.tokenType); + + for(;;) { + consume(); + switch(token.tokenType) { + case "EOF": + case endingTokenType: return block; + default: block.append(consumeAPrimitive()); + } + } + } + + function consumeAFunc() { + var func = new Func(token.value); + var arg = new FuncArg(); + + for(;;) { + consume(); + switch(token.tokenType) { + case "EOF": + case ")": func.append(arg); return func; + case "DELIM": + if(token.value == ",") { + func.append(arg); + arg = new FuncArg(); + } else { + arg.append(token); + } + break; + default: arg.append(consumeAPrimitive()); + } + } + } +} + +function CSSParserRule() { return this; } +CSSParserRule.prototype.fillType = ''; +CSSParserRule.prototype.toString = function(indent) { + return JSON.stringify(this.toJSON(),null,indent); +} +CSSParserRule.prototype.append = function(val) { + this.value.push(val); + return this; +} + +function Stylesheet() { + this.value = []; + return this; +} +Stylesheet.prototype = new CSSParserRule; +Stylesheet.prototype.type = "STYLESHEET"; +Stylesheet.prototype.toJSON = function() { + return {type:'stylesheet', value: this.value.map(function(e){return e.toJSON();})}; +} + +function AtRule(name) { + this.name = name; + this.prelude = []; + this.value = []; + if(name in AtRule.registry) + this.fillType = AtRule.registry[name]; + return this; +} +AtRule.prototype = new CSSParserRule; +AtRule.prototype.type = "AT-RULE"; +AtRule.prototype.appendPrelude = function(val) { + this.prelude.push(val); + return this; +} +AtRule.prototype.toJSON = function() { + return {type:'at', name:this.name, prelude:this.prelude.map(function(e){return e.toJSON();}), value:this.value.map(function(e){return e.toJSON();})}; +} +AtRule.registry = { + 'import': '', + 'media': 'rule', + 'font-face': 'declaration', + 'page': 'declaration', + 'keyframes': 'rule', + 'namespace': '', + 'counter-style': 'declaration', + 'supports': 'rule', + 'document': 'rule', + 'font-feature-values': 'declaration', + 'viewport': '', + 'region-style': 'rule' +}; + +function StyleRule() { + this.selector = []; + this.value = []; + return this; +} +StyleRule.prototype = new CSSParserRule; +StyleRule.prototype.type = "STYLE-RULE"; +StyleRule.prototype.fillType = 'declaration'; +StyleRule.prototype.appendSelector = function(val) { + this.selector.push(val); + return this; +} +StyleRule.prototype.toJSON = function() { + return {type:'selector', selector:this.selector.map(function(e){return e.toJSON();}), value:this.value.map(function(e){return e.toJSON();})}; +} + +function Declaration(name) { + this.name = name; + this.value = []; + return this; +} +Declaration.prototype = new CSSParserRule; +Declaration.prototype.type = "DECLARATION"; +Declaration.prototype.toJSON = function() { + return {type:'declaration', name:this.name, value:this.value.map(function(e){return e.toJSON();})}; +} + +function SimpleBlock(type) { + this.name = type; + this.value = []; + return this; +} +SimpleBlock.prototype = new CSSParserRule; +SimpleBlock.prototype.type = "BLOCK"; +SimpleBlock.prototype.toJSON = function() { + return {type:'block', name:this.name, value:this.value.map(function(e){return e.toJSON();})}; +} + +function Func(name) { + this.name = name; + this.value = []; + return this; +} +Func.prototype = new CSSParserRule; +Func.prototype.type = "FUNCTION"; +Func.prototype.toJSON = function() { + return {type:'func', name:this.name, value:this.value.map(function(e){return e.toJSON();})}; +} + +function FuncArg() { + this.value = []; + return this; +} +FuncArg.prototype = new CSSParserRule; +FuncArg.prototype.type = "FUNCTION-ARG"; +FuncArg.prototype.toJSON = function() { + return this.value.map(function(e){return e.toJSON();}); +} + +// Exportation. +// TODO: also export the various rule objects? +exports.parse = parse; + +})); + + +// vminpoly.js +// Generated by CoffeeScript 1.7.1 +(function() { + var XMLHttpFactories, ajax, applyStyleTest, browserSupportsUnitsNatively, clearStyleTests, createXMLHTTPObject, getViewportSize, initLayoutEngine, testElementStyle, testVHSupport, testVMinSupport, testVWSupport; + + XMLHttpFactories = [ + function() { + return new XMLHttpRequest(); + }, function() { + return new ActiveXObject("Msxml2.XMLHTTP"); + }, function() { + return new ActiveXObject("Msxml3.XMLHTTP"); + }, function() { + return new ActiveXObject("Microsoft.XMLHTTP"); + } + ]; + + createXMLHTTPObject = function() { + var e, i, xmlhttp; + xmlhttp = false; + i = 0; + while (i < XMLHttpFactories.length) { + try { + xmlhttp = XMLHttpFactories[i++](); + } catch (_error) { + e = _error; + continue; + } + break; + } + return xmlhttp; + }; + + ajax = function(url, onload) { + var e, xmlhttp; + xmlhttp = createXMLHTTPObject(); + xmlhttp.onreadystatechange = function() { + if (xmlhttp.readyState !== 4) { + return; + } + if (!(xmlhttp.status === 200 || url.match(/^file:\/\/\//))) { + throw "Error!"; + } + console.log("INFO: processing " + url); + onload(xmlhttp.responseText); + }; + try { + xmlhttp.open("GET", url, true); + xmlhttp.send(); + } catch (_error) { + e = _error; + console.log("ERROR: " + e.message + " (" + e.type + ") when accessing " + url); + } + }; + + getViewportSize = function() { + var x, y; + x = 0; + y = 0; + if (window.innerHeight) { + x = window.innerWidth; + y = window.innerHeight; + } else if (document.documentElement && document.documentElement.clientHeight) { + x = document.documentElement.clientWidth; + y = document.documentElement.clientHeight; + } else if (document.body) { + x = document.body.clientWidth; + y = document.body.clientHeight; + } + return { + width: x, + height: y + }; + }; + + browserSupportsUnitsNatively = function() { + var body, head, style_block, test_element, test_results; + test_element = document.createElement('div'); + test_element.id = "vminpolyTests"; + body = document.getElementsByTagName('body')[0]; + body.appendChild(test_element); + style_block = document.createElement('style'); + head = document.getElementsByTagName('head')[0]; + head.appendChild(style_block); + test_results = testVWSupport(test_element, style_block) && testVWSupport(test_element, style_block) && testVMinSupport(test_element, style_block); + body.removeChild(test_element); + head.removeChild(style_block); + return test_results; + }; + + testElementStyle = function(element) { + if (window.getComputedStyle) { + return getComputedStyle(element, null); + } else { + return element.currentStyle; + } + }; + + applyStyleTest = function(style_block, style) { + var new_style, test_style; + new_style = "#vminpolyTests { " + style + "; }"; + if (style_block.styleSheet) { + return style_block.styleSheet.cssText = new_style; + } else { + test_style = document.createTextNode(new_style); + return style_block.appendChild(test_style); + } + }; + + clearStyleTests = function(style_block) { + if (style_block.styleSheet) { + return style_block.styleSheet.cssText = ''; + } else { + return style_block.innerHTML = ''; + } + }; + + testVHSupport = function(element, style_block) { + var comp_style, height; + applyStyleTest(style_block, 'height: 50vh'); + height = parseInt(window.innerHeight / 2, 10); + comp_style = parseInt(testElementStyle(element).height, 10); + clearStyleTests(style_block); + return comp_style === height; + }; + + testVWSupport = function(element, style_block) { + var comp_style, width; + applyStyleTest(style_block, 'width: 50vw'); + width = parseInt(window.innerWidth / 2, 10); + comp_style = parseInt(testElementStyle(element).width, 10); + clearStyleTests(style_block); + return comp_style === width; + }; + + testVMinSupport = function(element, style_block) { + var actual_vmin, comp_width, docElement, one_vh, one_vw; + applyStyleTest(style_block, 'width: 50vmin'); + docElement = document.documentElement; + one_vw = docElement.clientWidth / 100; + one_vh = docElement.clientHeight / 100; + actual_vmin = parseInt(Math.min(one_vw, one_vh) * 50, 10); + comp_width = parseInt(testElementStyle(element).width, 10); + clearStyleTests(style_block); + return actual_vmin === comp_width; + }; + + initLayoutEngine = function() { + var analyzeStyleRule, analyzeStylesheet, head, i, innerSheetCount, links, onresize, outerSheetCount, sheets, styleElement, _i, _len; + analyzeStyleRule = function(rule) { + var declaration, declarations, hasDimension, token, _i, _j, _len, _len1, _ref, _ref1; + declarations = []; + _ref = rule.value; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + declaration = _ref[_i]; + hasDimension = false; + _ref1 = declaration.value; + for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { + token = _ref1[_j]; + if (token.tokenType === 'DIMENSION' && (token.unit === 'vmin' || token.unit === 'vh' || token.unit === 'vw')) { + hasDimension = true; + } + } + if (hasDimension) { + declarations.push(declaration); + } + } + rule.value = declarations; + return declarations; + }; + analyzeStylesheet = function(sheet) { + var atRules, decs, rule, rules, _i, _len, _ref; + rules = []; + _ref = sheet.value; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + rule = _ref[_i]; + switch (rule.type) { + case 'STYLE-RULE': + decs = analyzeStyleRule(rule); + if (decs.length !== 0) { + rules.push(rule); + } + break; + case 'AT-RULE': + atRules = analyzeStylesheet(rule); + if (atRules.length !== 0) { + rules.push(rule); + } + } + } + sheet.value = rules; + return rules; + }; + onresize = function() { + var css, dims, generateRuleCode, generateSheetCode, map, sheet, url, vpAspectRatio, vpDims; + vpDims = getViewportSize(); + dims = { + vh: vpDims.height / 100, + vw: vpDims.width / 100 + }; + dims.vmin = Math.min(dims.vh, dims.vw); + vpAspectRatio = vpDims.width / vpDims.height; + map = function(a, f) { + var a1, e, _i, _len; + if (a.map != null) { + return a.map(f); + } else { + a1 = []; + for (_i = 0, _len = a.length; _i < _len; _i++) { + e = a[_i]; + a1.push(f(e)); + } + return a1; + } + }; + generateRuleCode = function(rule) { + var declaration, declarations, ruleCss, token, _i, _j, _len, _len1, _ref, _ref1; + declarations = []; + ruleCss = (map(rule.selector, function(o) { + if (o.toSourceString != null) { + return o.toSourceString(); + } else { + return ''; + } + })).join(''); + ruleCss += "{"; + _ref = rule.value; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + declaration = _ref[_i]; + ruleCss += declaration.name; + ruleCss += ":"; + _ref1 = declaration.value; + for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { + token = _ref1[_j]; + if (token.tokenType === 'DIMENSION' && (token.unit === 'vmin' || token.unit === 'vh' || token.unit === 'vw')) { + ruleCss += "" + (Math.floor(token.num * dims[token.unit])) + "px"; + } else { + ruleCss += token.toSourceString(); + } + } + ruleCss += ";"; + } + ruleCss += "}\r"; + return ruleCss; + }; + generateSheetCode = function(sheet) { + var mar, nums, prelude, rule, sheetCss, source, t, t1, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3; + sheetCss = ''; + _ref = sheet.value; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + rule = _ref[_i]; + switch (rule.type) { + case 'STYLE-RULE': + sheetCss += generateRuleCode(rule); + break; + case 'AT-RULE': + if (rule.name === 'media') { + prelude = ''; + mar = false; + nums = []; + _ref1 = rule.prelude; + for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { + t = _ref1[_j]; + if (t.name === '(') { + prelude += '('; + _ref2 = t.value; + for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { + t1 = _ref2[_k]; + source = t1.toSourceString != null ? t1.toSourceString() : ''; + if (t1.tokenType === 'IDENT' && source === 'max-aspect-ratio') { + mar = true; + } + if (t1.tokenType === 'NUMBER') { + nums.push(parseInt(source)); + } + prelude += source; + } + prelude += ')'; + } else { + prelude += t.toSourceString(); + } + } + if (vpAspectRatio < nums[0] / nums[1]) { + sheetCss += generateSheetCode(rule); + } + } else { + prelude = ''; + _ref3 = rule.prelude; + for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) { + t = _ref3[_l]; + if (t.name === '(') { + prelude += '('; + prelude += (map(t.value, function(o) { + if (o.toSourceString != null) { + return o.toSourceString(); + } else { + return ''; + } + })).join(''); + prelude += ')'; + } else { + prelude += t.toSourceString(); + } + } + sheetCss += "@" + rule.name + " " + prelude + " {"; + sheetCss += generateSheetCode(rule); + sheetCss += '}\n'; + } + } + } + return sheetCss; + }; + css = ''; + for (url in sheets) { + sheet = sheets[url]; + css += generateSheetCode(sheet); + } + if (styleElement.styleSheet != null) { + return styleElement.styleSheet.cssText = css; + } else { + return styleElement.innerHTML = css; + } + }; + sheets = {}; + styleElement = document.createElement('style'); + head = document.getElementsByTagName('head')[0]; + head.appendChild(styleElement); + links = document.getElementsByTagName('link'); + innerSheetCount = 0; + outerSheetCount = 0; + for (_i = 0, _len = links.length; _i < _len; _i++) { + i = links[_i]; + if (i.rel !== 'stylesheet') { + continue; + } + innerSheetCount++; + ajax(i.href, function(cssText) { + var sheet, tokenlist; + tokenlist = tokenize(cssText); + sheet = parse(tokenlist); + analyzeStylesheet(sheet); + sheets[i.href] = sheet; + outerSheetCount++; + if (outerSheetCount === innerSheetCount) { + window.onresize(); + } + }); + } + window.onresize = onresize; + }; + + console.log('About to do the engine unless...', browserSupportsUnitsNatively()); + + if (!browserSupportsUnitsNatively()) { + initLayoutEngine(); + } + +}).call(this); diff --git a/dist/vminpoly.dist.min.js b/dist/vminpoly.dist.min.js new file mode 100644 index 0000000..4289cb4 --- /dev/null +++ b/dist/vminpoly.dist.min.js @@ -0,0 +1,2 @@ +// vminpoly - Viewport units for old browers https://github.com/saabi/vminpoly +Array.prototype.filter||(Array.prototype.filter=function(e){var t=this.length;if("function"!=typeof e)throw new TypeError;for(var n=new Array,r=arguments[1],o=0;t>o;o++)if(o in this){var i=this[o];e.call(r,i,o,this)&&n.push(i)}return n}),function(e,t){"function"==typeof define&&define.amd?define(["exports"],t):t("undefined"!=typeof exports?exports:e)}(this,function(e){function t(e){return q(e,48,57)}function n(e){return t(e)||q(e,65,70)||q(e,97,102)}function r(e){return q(e,65,90)}function o(e){return q(e,97,122)}function i(e){return r(e)||o(e)}function a(e){return e>=160}function u(e){return i(e)||a(e)||95==e}function p(e){return u(e)||t(e)||45==e}function s(e){return q(e,0,8)||q(e,14,31)||q(e,127,159)}function c(e){return 10==e||12==e}function l(e){return c(e)||9==e||32==e}function d(e){return c(e)||isNaN(e)}function h(e,r){void 0==r&&(r={transformFunctionWhitespace:!1,scientificNotation:!1});for(var o,i,a=-1,h=[],f="data",y=0,U=0,q=0,Y=function(){y+=1,q=U,U=0},j={line:y,column:U},X=function(t){return void 0===t&&(t=1),e.charCodeAt(a+t)},_=function(t){return void 0===t&&(t=1),a+=t,o=e.charCodeAt(a),c(o)?Y():U+=t,!0},K=function(){return a-=1,c(o)?(y-=1,U=q):U-=1,j.line=y,j.column=U,!0},z=function(){return a>=e.length},Q=function(){},V=function(e){return e?e.finish():e=i.finish(),r.loc===!0&&(e.loc={},e.loc.start={line:j.line,column:j.column},j={line:y,column:U},e.loc.end=j),h.push(e),i=void 0,!0},Z=function(e){return i=e,!0},$=function(){return console.log("Parse error at index "+a+", processing codepoint 0x"+o.toString(16)+" in state "+f+"."),!0},ee=function(e){return console.log("MAJOR SPEC ERROR: "+e),!0},te=function(e){return f=e,!0},ne=function(){if(_(),n(o)){for(var e=[],t=0;6>t&&n(o);t++)e.push(o),_();if(null!=e.map)var r=parseInt(e.map(String.fromCharCode).join(""),16);else{for(d1=[],_len=e.length,_i=0;_i<_len;_i++)d1.push(String.fromCharCode(e[_i]));var r=parseInt(d1.join(""),16)}return r>B&&(r=65533),l(o)||K(),r}return o};;){if(a>2*e.length)return"I'm infinite-looping!";switch(_(),f){case"data":if(l(o))for(V(new m);l(X());)_();else if(34==o)te("double-quote-string");else if(35==o)te("hash");else if(39==o)te("single-quote-string");else if(40==o)V(new O);else if(41==o)V(new I);else if(43==o)t(X())||46==X()&&t(X(2))?te("number")&&K():V(new R(o));else if(45==o)45==X(1)&&62==X(2)?_(2)&&V(new k):t(X())||46==X(1)&&t(X(2))?te("number")&&K():te("ident")&&K();else if(46==o)t(X())?te("number")&&K():V(new R(o));else if(47==o)42==X()?_()&&te("comment"):V(new R(o));else if(58==o)V(new S);else if(59==o)V(new T);else if(60==o)33==X(1)&&45==X(2)&&45==X(3)?_(3)&&V(new g):V(new R(o));else if(64==o)te("at-keyword");else if(91==o)V(new N);else if(92==o)d(X())?$()&&V(new R(o)):te("ident")&&K();else if(93==o)V(new C);else if(123==o)V(new b);else if(125==o)V(new E);else if(t(o))te("number")&&K();else if(85==o||117==o)43==X(1)&&n(X(2))?_()&&te("unicode-range"):te("ident")&&K();else if(u(o))te("ident")&&K();else{if(z())return V(new A),h;V(new R(o))}break;case"double-quote-string":void 0==i&&Z(new x),34==o?V()&&te("data"):z()?$()&&V()&&te("data")&&K():c(o)?$()&&V(new w)&&te("data")&&K():92==o?d(X())?$()&&V(new w)&&te("data"):c(X())?_():i.append(ne()):i.append(o);break;case"single-quote-string":void 0==i&&Z(new x),39==o?V()&&te("data"):z()?$()&&V()&&te("data"):c(o)?$()&&V(new w)&&te("data")&&K():92==o?d(X())?$()&&V(new w)&&te("data"):c(X())?_():i.append(ne()):i.append(o);break;case"hash":p(o)?Z(new M(o))&&te("hash-rest"):92==o?d(X())?$()&&V(new R(35))&&te("data")&&K():Z(new M(ne()))&&te("hash-rest"):V(new R(35))&&te("data")&&K();break;case"hash-rest":p(o)?i.append(o):92==o?d(X())?$()&&V()&&te("data")&&K():i.append(ne()):V()&&te("data")&&K();break;case"comment":42==o?47==X()?_()&&te("data"):Q():z()?$()&&te("data")&&K():Q();break;case"at-keyword":45==o?u(X())?Z(new H(45))&&te("at-keyword-rest"):92!=X(1)||d(X(2))?$()&&V(new R(64))&&te("data")&&K():Z(new AtKeywordtoken(45))&&te("at-keyword-rest"):u(o)?Z(new H(o))&&te("at-keyword-rest"):92==o?d(X())?$()&&V(new R(35))&&te("data")&&K():Z(new H(ne()))&&te("at-keyword-rest"):V(new R(64))&&te("data")&&K();break;case"at-keyword-rest":p(o)?i.append(o):92==o?d(X())?$()&&V()&&te("data")&&K():i.append(ne()):V()&&te("data")&&K();break;case"ident":45==o?u(X())?Z(new D(o))&&te("ident-rest"):92!=X(1)||d(X(2))?V(new R(45))&&te("data"):Z(new D(o))&&te("ident-rest"):u(o)?Z(new D(o))&&te("ident-rest"):92==o?d(X())?$()&&te("data")&&K():Z(new D(ne()))&&te("ident-rest"):ee("Hit the generic 'else' clause in ident state.")&&te("data")&&K();break;case"ident-rest":p(o)?i.append(o):92==o?d(X())?$()&&V()&&te("data")&&K():i.append(ne()):40==o?i.ASCIImatch("url")?te("url"):V(new L(i))&&te("data"):l(o)&&r.transformFunctionWhitespace?te("transform-function-whitespace")&&K():V()&&te("data")&&K();break;case"transform-function-whitespace":l(X())?Q():40==o?V(new L(i))&&te("data"):V()&&te("data")&&K();break;case"number":Z(new J),45==o?t(X())?_()&&i.append([45,o])&&te("number-rest"):46==X(1)&&t(X(2))?_(2)&&i.append([45,46,o])&&te("number-fraction"):te("data")&&K():43==o?t(X())?_()&&i.append([43,o])&&te("number-rest"):46==X(1)&&t(X(2))?_(2)&&i.append([43,46,o])&&te("number-fraction"):te("data")&&K():t(o)?i.append(o)&&te("number-rest"):46==o&&t(X())?_()&&i.append([46,o])&&te("number-fraction"):te("data")&&K();break;case"number-rest":t(o)?i.append(o):46==o?t(X())?_()&&i.append([46,o])&&te("number-fraction"):V()&&te("data")&&K():37==o?V(new W(i))&&te("data"):69==o||101==o?t(X())?_()&&i.append([37,o])&&te("sci-notation"):43!=X(1)&&45!=X(1)||!t(X(2))?Z(new P(i,o))&&te("dimension"):i.append([37,X(1),X(2)])&&_(2)&&te("sci-notation"):45==o?u(X())?_()&&Z(new P(i,[45,o]))&&te("dimension"):92==X(1)&&d(X(2))?$()&&V()&&te("data")&&K():92==X(1)?_()&&Z(new P(i,[45,ne()]))&&te("dimension"):V()&&te("data")&&K():u(o)?Z(new P(i,o))&&te("dimension"):92==o?d(X)?$()&&V()&&te("data")&&K():Z(new P(i,ne))&&te("dimension"):V()&&te("data")&&K();break;case"number-fraction":i.type="number",t(o)?i.append(o):37==o?V(new W(i))&&te("data"):69==o||101==o?t(X())?_()&&i.append([101,o])&&te("sci-notation"):43!=X(1)&&45!=X(1)||!t(X(2))?Z(new P(i,o))&&te("dimension"):i.append([101,X(1),X(2)])&&_(2)&&te("sci-notation"):45==o?u(X())?_()&&Z(new P(i,[45,o]))&&te("dimension"):92==X(1)&&d(X(2))?$()&&V()&&te("data")&&K():92==X(1)?_()&&Z(new P(i,[45,ne()]))&&te("dimension"):V()&&te("data")&&K():u(o)?Z(new P(i,o))&&te("dimension"):92==o?d(X)?$()&&V()&&te("data")&&K():Z(new P(i,ne()))&&te("dimension"):V()&&te("data")&&K();break;case"dimension":p(o)?i.append(o):92==o?d(X())?$()&&V()&&te("data")&&K():i.append(ne()):V()&&te("data")&&K();break;case"sci-notation":i.type="number",t(o)?i.append(o):V()&&te("data")&&K();break;case"url":z()?$()&&V(new v)&&te("data"):34==o?te("url-double-quote"):39==o?te("url-single-quote"):41==o?V(new F)&&te("data"):l(o)?Q():te("url-unquoted")&&K();break;case"url-double-quote":i instanceof F||Z(new F),z()?$()&&V(new v)&&te("data"):34==o?te("url-end"):c(o)?$()&&te("bad-url"):92==o?c(X())?_():d(X())?$()&&V(new v)&&te("data")&&K():i.append(ne()):i.append(o);break;case"url-single-quote":i instanceof F||Z(new F),z()?$()&&V(new v)&&te("data"):39==o?te("url-end"):c(o)?$()&&te("bad-url"):92==o?c(X())?_():d(X())?$()&&V(new v)&&te("data")&&K():i.append(ne()):i.append(o);break;case"url-end":z()?$()&&V(new v)&&te("data"):l(o)?Q():41==o?V()&&te("data"):$()&&te("bad-url")&&K();break;case"url-unquoted":i instanceof F||Z(new F),z()?$()&&V(new v)&&te("data"):l(o)?te("url-end"):41==o?V()&&te("data"):34==o||39==o||40==o||s(o)?$()&&te("bad-url"):92==o?d(X())?$()&&te("bad-url"):i.append(ne()):i.append(o);break;case"bad-url":z()?$()&&V(new v)&&te("data"):41==o?V(new v)&&te("data"):92==o?d(X())?Q():ne():Q();break;case"unicode-range":for(var re=[o],oe=[o],ie=1;6>ie&&n(X());ie++)_(),re.push(o),oe.push(o);if(63==X()){for(;6>ie&&63==X();ie++)_(),re.push("0".charCodeAt(0)),oe.push("f".charCodeAt(0));V(new G(re,oe))&&te("data")}else if(45==X(1)&&n(X(2))){_(),_(),oe=[o];for(var ie=1;6>ie&&n(X());ie++)_(),oe.push(o);V(new G(re,oe))&&te("data")}else V(new G(re))&&te("data");break;default:ee("Unknown state '"+f+"'")}}}function f(e){return String.fromCharCode.apply(null,e.filter(function(e){return e}))}function y(e){return this}function w(){return this}function v(){return this}function m(){return this}function g(){return this}function k(){return this}function S(){return this}function T(){return this}function b(){return this}function E(){return this}function N(){return this}function C(){return this}function O(){return this}function I(){return this}function A(){return this}function R(e){return this.value=String.fromCharCode(e),this}function U(){return this}function D(e){this.value=[],this.append(e)}function L(e){this.value=e.finish().value}function H(e){this.value=[],this.append(e)}function M(e){this.value=[],this.append(e)}function x(e){this.value=[],this.append(e)}function F(e){this.value=[],this.append(e)}function J(e){this.value=[],this.append(e),this.type="integer"}function W(e){e.finish(),this.value=e.value,this.repr=e.repr}function P(e,t){e.finish(),this.num=e.value,this.unit=[],this.repr=e.repr,this.append(t)}function G(e,t){return e=parseInt(f(e),16),t=void 0===t?e+1:parseInt(f(t),16),e>B&&(t=e),e>t&&(t=e),t>B&&(t=B),this.start=e,this.end=t,this}var q=function(e,t,n){return e>=t&&n>=e},B=1114111;y.prototype.finish=function(){return this},y.prototype.toString=function(){return this.tokenType},y.prototype.toSourceString=y.prototype.toString,y.prototype.toJSON=function(){return this.toString()},w.prototype=new y,w.prototype.tokenType="BADSTRING",v.prototype=new y,v.prototype.tokenType="BADURL",m.prototype=new y,m.prototype.tokenType="WHITESPACE",m.prototype.toString=function(){return"WS"},m.prototype.toSourceString=function(){return" "},g.prototype=new y,g.prototype.tokenType="CDO",k.prototype=new y,k.prototype.tokenType="CDC",S.prototype=new y,S.prototype.tokenType=":",T.prototype=new y,T.prototype.tokenType=";",b.prototype=new y,b.prototype.tokenType="{",E.prototype=new y,E.prototype.tokenType="}",N.prototype=new y,N.prototype.tokenType="[",C.prototype=new y,C.prototype.tokenType="]",O.prototype=new y,O.prototype.tokenType="(",I.prototype=new y,I.prototype.tokenType=")",A.prototype=new y,A.prototype.tokenType="EOF",R.prototype=new y,R.prototype.tokenType="DELIM",R.prototype.toString=function(){return"DELIM("+this.value+")"},R.prototype.toSourceString=function(){return this.value},U.prototype=new y,U.prototype.append=function(e){if(e instanceof Array)for(var t=0;t=this.start&&e1;)b()};;)if(v(),"DELIM"!==l.tokenType||"\r"!==l.value)switch(d){case"top-level":switch(l.tokenType){case"CDO":case"CDC":case"WHITESPACE":break;case"AT-KEYWORD":S(new o(l.value))&&k("at-rule");break;case"{":T("Attempt to open a curly-block at top-level.")&&t();break;case"EOF":return N(),f;default:S(new i)&&k("selector")&&m()}break;case"at-rule":switch(l.tokenType){case";":b()&&k();break;case"{":""!==w.fillType?k(w.fillType):T("Attempt to open a curly-block in a statement-type at-rule.")&&E()&&k("next-block")&&m();break;case"EOF":return N(),f;default:w.appendPrelude(t())}break;case"rule":switch(l.tokenType){case"WHITESPACE":break;case"}":b()&&k();break;case"AT-KEYWORD":S(new o(l.value))&&k("at-rule");break;case"EOF":return N(),f;default:S(new i)&&k("selector")&&m()}break;case"selector":switch(l.tokenType){case"{":k("declaration");break;case"EOF":return E()&&N(),f;default:w.appendSelector(t())}break;case"declaration":switch(l.tokenType){case"WHITESPACE":case";":break;case"}":b()&&k();break;case"AT-RULE":S(new o(l.value))&&k("at-rule");break;case"IDENT":S(new a(l.value))&&k("after-declaration-name");break;case"EOF":return N(),f;default:T()&&E()&&k("next-declaration")}break;case"after-declaration-name":switch(l.tokenType){case"WHITESPACE":break;case":":k("declaration-value");break;case";":T("Incomplete declaration - semicolon after property name.")&&E()&&k();break;case"EOF":return E()&&N(),f;default:T("Invalid declaration - additional token after property name")&&E()&&k("next-declaration")}break;case"declaration-value":switch(l.tokenType){case"DELIM":"!"==l.value&&"IDENTIFIER"==g().tokenType&&"important"==g().value.toLowerCase()?(v(),w.important=!0,k("declaration-end")):w.append(l);break;case";":b()&&k();break;case"}":b()&&b()&&k();break;case"EOF":return N(),f;default:w.append(t())}break;case"declaration-end":switch(l.tokenType){case"WHITESPACE":break;case";":b()&&k();break;case"}":b()&&b()&&k();break;case"EOF":return N(),f;default:T("Invalid declaration - additional token after !important.")&&E()&&k("next-declaration")}break;case"next-block":switch(l.tokenType){case"{":t()&&k();break;case"EOF":return N(),f;default:t()}break;case"next-declaration":switch(l.tokenType){case";":k("declaration");break;case"}":k("declaration")&&m();break;case"EOF":return N(),f;default:t()}break;default:return void console.log("Unknown parsing mode: "+d)}}function n(){return this}function r(){return this.value=[],this}function o(e){return this.name=e,this.prelude=[],this.value=[],e in o.registry&&(this.fillType=o.registry[e]),this}function i(){return this.selector=[],this.value=[],this}function a(e){return this.name=e,this.value=[],this}function u(e){return this.name=e,this.value=[],this}function p(e){return this.name=e,this.value=[],this}function s(){return this.value=[],this}n.prototype.fillType="",n.prototype.toString=function(e){return JSON.stringify(this.toJSON(),null,e)},n.prototype.append=function(e){return this.value.push(e),this},r.prototype=new n,r.prototype.type="STYLESHEET",r.prototype.toJSON=function(){return{type:"stylesheet",value:this.value.map(function(e){return e.toJSON()})}},o.prototype=new n,o.prototype.type="AT-RULE",o.prototype.appendPrelude=function(e){return this.prelude.push(e),this},o.prototype.toJSON=function(){return{type:"at",name:this.name,prelude:this.prelude.map(function(e){return e.toJSON()}),value:this.value.map(function(e){return e.toJSON()})}},o.registry={"import":"",media:"rule","font-face":"declaration",page:"declaration",keyframes:"rule",namespace:"","counter-style":"declaration",supports:"rule",document:"rule","font-feature-values":"declaration",viewport:"","region-style":"rule"},i.prototype=new n,i.prototype.type="STYLE-RULE",i.prototype.fillType="declaration",i.prototype.appendSelector=function(e){return this.selector.push(e),this},i.prototype.toJSON=function(){return{type:"selector",selector:this.selector.map(function(e){return e.toJSON()}),value:this.value.map(function(e){return e.toJSON()})}},a.prototype=new n,a.prototype.type="DECLARATION",a.prototype.toJSON=function(){return{type:"declaration",name:this.name,value:this.value.map(function(e){return e.toJSON()})}},u.prototype=new n,u.prototype.type="BLOCK",u.prototype.toJSON=function(){return{type:"block",name:this.name,value:this.value.map(function(e){return e.toJSON()})}},p.prototype=new n,p.prototype.type="FUNCTION",p.prototype.toJSON=function(){return{type:"func",name:this.name,value:this.value.map(function(e){return e.toJSON()})}},s.prototype=new n,s.prototype.type="FUNCTION-ARG",s.prototype.toJSON=function(){return this.value.map(function(e){return e.toJSON()})},e.parse=t}),function(){var e,t,n,r,o,i,a,u,p,s,c,l;e=[function(){return new XMLHttpRequest},function(){return new ActiveXObject("Msxml2.XMLHTTP")},function(){return new ActiveXObject("Msxml3.XMLHTTP")},function(){return new ActiveXObject("Microsoft.XMLHTTP")}],i=function(){var t,n,r;for(r=!1,n=0;ni;i++){for(t=s[i],r=!1,c=t.value,a=0,p=c.length;p>a;a++)o=c[a],"DIMENSION"!==o.tokenType||"vmin"!==o.unit&&"vh"!==o.unit&&"vw"!==o.unit||(r=!0);r&&n.push(t)}return e.value=n,n},n=function(t){var r,o,i,a,u,p,s;for(a=[],s=t.value,u=0,p=s.length;p>u;u++)switch(i=s[u],i.type){case"STYLE-RULE":o=e(i),0!==o.length&&a.push(i);break;case"AT-RULE":r=n(i),0!==r.length&&a.push(i)}return t.value=a,a},p=function(){var e,t,n,r,o,i,u,p,s;s=a(),t={vh:s.height/100,vw:s.width/100},t.vmin=Math.min(t.vh,t.vw),p=s.width/s.height,o=function(e,t){var n,r,o,i;if(null!=e.map)return e.map(t);for(n=[],o=0,i=e.length;i>o;o++)r=e[o],n.push(t(r));return n},n=function(e){var n,r,i,a,u,p,s,c,l,d;for(r=[],i=o(e.selector,function(e){return null!=e.toSourceString?e.toSourceString():""}).join(""),i+="{",l=e.value,u=0,s=l.length;s>u;u++){for(n=l[u],i+=n.name,i+=":",d=n.value,p=0,c=d.length;c>p;p++)a=d[p],i+="DIMENSION"!==a.tokenType||"vmin"!==a.unit&&"vh"!==a.unit&&"vw"!==a.unit?a.toSourceString():""+Math.floor(a.num*t[a.unit])+"px";i+=";"}return i+="}\r"},r=function(e){var t,i,a,u,s,c,l,d,h,f,y,w,v,m,g,k,S,T,b,E;for(s="",S=e.value,h=0,v=S.length;v>h;h++)switch(u=S[h],u.type){case"STYLE-RULE":s+=n(u);break;case"AT-RULE":if("media"===u.name){for(a="",t=!1,i=[],T=u.prelude,f=0,m=T.length;m>f;f++)if(l=T[f],"("===l.name){for(a+="(",b=l.value,y=0,g=b.length;g>y;y++)d=b[y],c=null!=d.toSourceString?d.toSourceString():"","IDENT"===d.tokenType&&"max-aspect-ratio"===c&&(t=!0),"NUMBER"===d.tokenType&&i.push(parseInt(c)),a+=c;a+=")"}else a+=l.toSourceString();pw;w++)l=E[w],"("===l.name?(a+="(",a+=o(l.value,function(e){return null!=e.toSourceString?e.toSourceString():""}).join(""),a+=")"):a+=l.toSourceString();s+="@"+u.name+" "+a+" {",s+=r(u),s+="}\n"}}return s},e="";for(u in c)i=c[u],e+=r(i);return null!=l.styleSheet?l.styleSheet.cssText=e:l.innerHTML=e},c={},l=document.createElement("style"),r=document.getElementsByTagName("head")[0],r.appendChild(l),u=document.getElementsByTagName("link"),i=0,s=0,d=0,h=u.length;h>d;d++)o=u[d],"stylesheet"===o.rel&&(i++,t(o.href,function(e){var t,r;r=tokenize(e),t=parse(r),n(t),c[o.href]=t,s++,s===i&&window.onresize()}));window.onresize=p},console.log("About to do the engine unless...",r()),r()||u()}.call(this); diff --git a/test2.css b/examples/example-2.css similarity index 91% rename from test2.css rename to examples/example-2.css index 44b92c9..d76553a 100644 --- a/test2.css +++ b/examples/example-2.css @@ -1,32 +1,25 @@ -body, -#footer { +body, #footer { -webkit-transition: height, width 500ms cubic-bezier(0.115, 0, 0, 1); - -moz-transition: height, width 500ms cubic-bezier(0.115, 0, 0, 1); - -o-transition: height, width 500ms cubic-bezier(0.115, 0, 0, 1); transition: height, width 500ms cubic-bezier(0.115, 0, 0, 1); } -#logo, -#highlights, -#nav, -#news div, -#ads div, -#footer { + +#logo, #highlights, #nav, #news div, #ads div, #footer { -webkit-transition: all 500ms cubic-bezier(0.115, 0, 0, 1); - -moz-transition: all 500ms cubic-bezier(0.115, 0, 0, 1); - -o-transition: all 500ms cubic-bezier(0.115, 0, 0, 1); transition: all 500ms cubic-bezier(0.115, 0, 0, 1); } -html {background: white;} -#logo, -#nav, -#news div, -#footer { +html { + background: white; +} + +#logo, #nav, #news div, #footer { background: silver; } + #ads div { background: gray; } + #highlights { background: darkblue; color: white; @@ -35,9 +28,11 @@ html {background: white;} h1 { font-size: 4vmin; } + div { - font-size: 4vmin; + font-size: 4vmin; } + html { position: absolute; width: 100%; @@ -46,6 +41,7 @@ html { margin: 0; overflow: hidden; } + body { position: relative; margin: 5.4vmin auto; @@ -53,6 +49,7 @@ body { height: 90vmin; overflow: hidden; } + #logo { margin: 0; padding: 0; @@ -63,16 +60,19 @@ body { height: 18.8vmin; overflow: hidden; } + a { text-decoration: none; } + #nav { position: absolute; left: 40.6vmin; top: 0.6vmin; width: 118.8vmin; - height: 18.8vmin; + height: 18.8vmin; } + #highlights { position: absolute; overflow: hidden; @@ -81,51 +81,57 @@ a { top: 20.6vmin; left: 0.6vmin; } -#item1, -#item2, -#item3 { + +#item1, #item2, #item3 { display: block; } -#news div, -#ads div { + +#news div, #ads div { position: absolute; } + #item1 { left: 0.6vmin; top: 60.6vmin; width: 38.8vmin; height: 18.8vmin; } + #item2 { left: 40.6vmin; top: 60.6vmin; width: 38.8vmin; height: 18.8vmin; } + #item3 { left: 80.6vmin; top: 60.6vmin; width: 38.8vmin; height: 18.8vmin; } + #ad1 { top: 20.6vmin; left: 80.6vmin; width: 38.8vmin; height: 18.8vmin; } + #ad2 { top: 40.6vmin; left: 80.6vmin; width: 38.8vmin; height: 18.8vmin; } + #ad3 { top: 20.6vmin; left: 120.6vmin; width: 38.8vmin; height: 18.8vmin; } + #footer { position: absolute; left: 0.6vmin; @@ -134,48 +140,56 @@ a { top: 80.6vmin; } -@media (max-aspect-ratio:80/45) { +@media (max-aspect-ratio: 80/45) { body { width: 140vmin; } + #logo { width: 18.8vmin; } + #nav { position: absolute; left: 20.6vmin; width: 118.8vmin; } + #highlights { left: 0.6vmin; } - #ad1, - #ad2 { + + #ad1, #ad2 { left: 80.6vmin; } + #ad3 { left: 120.6vmin; top: 20.6vmin; width: 18.8vmin; height: 38.8vmin; } + #footer { width: 138.8vmin; } } -@media (max-aspect-ratio:80/55) { + +@media (max-aspect-ratio: 80/55) { body { margin: 4.5vmin auto; width: 116.66666666666667vmin; height: 91.66666666666667vmin; font-size: 1.6666666666666667vmin; } + #logo { left: 0.5vmin; top: 0.5vmin; width: 15.666666666666668vmin; height: 15.666666666666668vmin; } + #nav { position: absolute; left: 17.166666666666668vmin; @@ -183,48 +197,56 @@ a { width: 99vmin; height: 15.666666666666668vmin; } + #highlights { left: 0.5vmin; top: 17.166666666666668vmin; width: 82.33333333333333vmin; height: 49vmin; } + #item1 { left: 0.5vmin; width: 32.333333333333336vmin; height: 15.666666666666668vmin; top: 67.16666666666667vmin; } + #item2 { left: 33.833333333333336vmin; width: 32.333333333333336vmin; height: 15.666666666666668vmin; top: 67.16666666666667vmin; } + #item3 { left: 67.16666666666667vmin; width: 32.333333333333336vmin; height: 15.666666666666668vmin; top: 67.16666666666667vmin; } + #ad1 { top: 17.166666666666668vmin; left: 83.83333333333333vmin; width: 32.333333333333336vmin; height: 15.666666666666668vmin; } + #ad2 { top: 33.833333333333336vmin; left: 83.83333333333333vmin; width: 32.333333333333336vmin; height: 15.666666666666668vmin; } + #ad3 { top: 50.5vmin; left: 83.83333333333333vmin; width: 32.333333333333336vmin; height: 15.666666666666668vmin; } + #footer { left: 0.5vmin; width: 115.66666666666667vmin; @@ -232,98 +254,116 @@ a { top: 83.83333333333333vmin; } } -@media (max-aspect-ratio:70/55) { + +@media (max-aspect-ratio: 70/55) { body { width: 100vmin; } + #nav { width: 83.33333333333333vmin; } + #highlights { left: 17.166666666666668vmin; width: 65.66666666666667vmin; height: 32.333333333333336vmin; } + #ad1 { top: 50.5vmin; width: 32.333333333333336vmin; left: 0.5vmin; } + #ad2 { top: 50.5vmin; width: 32.333333333333336vmin; left: 33.833333333333336vmin; } + #ad3 { top: 50.5vmin; width: 32.333333333333336vmin; left: 67.16666666666667vmin; } + #footer { width: 99vmin; } } -@media (max-aspect-ratio:65/65) { + +@media (max-aspect-ratio: 65/65) { body { margin: 3.857142857142857vmin auto; width: 71.42857142857143vmin; height: 92.85714285714286vmin; font-size: 1.4285714285714286vmin; } + #logo { left: 0.42857142857142855vmin; top: 0.42857142857142855vmin; width: 13.428571428571429vmin; height: 13.428571428571429vmin; } + #nav { left: 14.714285714285715vmin; top: 0.42857142857142855vmin; width: 56.28571428571429vmin; height: 13.428571428571429vmin; } + #highlights { left: 0.42857142857142855vmin; top: 14.714285714285715vmin; width: 70.57142857142857vmin; height: 42vmin; } + #item1 { left: 0.42857142857142855vmin; top: 57.57142857142858vmin; width: 27.714285714285715vmin; height: 13.428571428571429vmin; } + #item2 { left: 0.42857142857142855vmin; top: 71.85714285714286vmin; width: 27.714285714285715vmin; height: 13.428571428571429vmin; } + #item3 { left: 29vmin; top: 71.85714285714286vmin; width: 27.714285714285715vmin; height: 13.428571428571429vmin; } + #ad1 { top: 57.57142857142858vmin; left: 29vmin; width: 13.428571428571429vmin; height: 13.428571428571429vmin; } + #ad2 { top: 57.57142857142858vmin; left: 43.285714285714285vmin; width: 13.428571428571429vmin; height: 13.428571428571429vmin; } + #ad3 { top: 57.57142857142858vmin; height: 27.714285714285715vmin; width: 13.428571428571429vmin; left: 57.57142857142858vmin; } + #footer { top: 86.14285714285714vmin; left: 0.42857142857142855vmin; @@ -331,42 +371,53 @@ a { height: 6.2857142857142865vmin; } } + @media (max-aspect-ratio:65/75) { body { margin: 3.857142857142857vmin auto; height: 107.14285714285714vmin; } + #logo { top: 0.42857142857142855vmin; width: 27.714285714285715vmin; } + #nav { left: 0.42857142857142855vmin; top: 14.714285714285715vmin; width: 70.57142857142857vmin; height: 13.428571428571429vmin; } + #highlights { top: 29vmin; } + #item1 { top: 71.85714285714286vmin; } + #item2 { top: 86.14285714285714vmin; } + #item3 { top: 86.14285714285714vmin; } + #ad1 { top: 71.85714285714286vmin; } + #ad2 { top: 71.85714285714286vmin; } + #ad3 { top: 71.85714285714286vmin; } + #footer { left: 0.42857142857142855vmin; width: 70.57142857142857vmin; @@ -374,30 +425,38 @@ a { top: 100.42857142857143vmin; } } -@media (max-aspect-ratio:65/85) { + +@media (max-aspect-ratio: 65/85) { body { height: 121.42857142857143vmin; } + #item1 { top: 86.14285714285714vmin; } + #item2 { top: 100.42857142857143vmin; } + #item3 { top: 86.14285714285714vmin; } + #ad1 { left: 0.42857142857142855vmin; width: 27.714285714285715vmin; } + #ad2 { left: 29vmin; width: 27.714285714285715vmin; } + #ad3 { top: 71.85714285714286vmin; } + #footer { top: 114.71428571428572vmin; } diff --git a/examples/example-2.html b/examples/example-2.html new file mode 100644 index 0000000..8b5fbce --- /dev/null +++ b/examples/example-2.html @@ -0,0 +1,36 @@ + + + + + Sophisticated vw, vh & vmin example + + + + + + + +
+
Highlights
+
+
News item 1
+
News item 2
+
News item 3
+
+
+
ad 1
+
ad 2
+
ad 3
+
+
+ + + + + + diff --git a/examples/example.css b/examples/example.css new file mode 100644 index 0000000..1af6b5a --- /dev/null +++ b/examples/example.css @@ -0,0 +1,11 @@ +div { + position: absolute; + background: #800; + color: white; + top: 4vh; + left: 4vw; + width: 50vmin; + height: 50vmin; + font-size: 3vmin; + border: 1vw solid black; +} diff --git a/examples/example.html b/examples/example.html new file mode 100644 index 0000000..7ee5ddd --- /dev/null +++ b/examples/example.html @@ -0,0 +1,13 @@ + + + + + + + + +
Hello Viewport Units!
+ + + + diff --git a/index.html b/index.html deleted file mode 100644 index a72dfec..0000000 --- a/index.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - -
Some text
- - - - - - \ No newline at end of file diff --git a/vminpoly.coffee b/src/vminpoly.coffee similarity index 100% rename from vminpoly.coffee rename to src/vminpoly.coffee diff --git a/vminpoly.js b/src/vminpoly.js similarity index 100% rename from vminpoly.js rename to src/vminpoly.js diff --git a/test.css b/test.css deleted file mode 100644 index 454c0f9..0000000 --- a/test.css +++ /dev/null @@ -1,11 +0,0 @@ -#testtarget { - position:absolute; - background:#800; - color:white; - top:4vh; - left:4vw; - width:50vmin; - height:50vmin; - font-size:3vmin; - border:1vw solid black; -} \ No newline at end of file diff --git a/parser.js b/vendor/parser.js similarity index 100% rename from parser.js rename to vendor/parser.js diff --git a/tokenizer.js b/vendor/tokenizer.js similarity index 100% rename from tokenizer.js rename to vendor/tokenizer.js From 60d30fbcc177a7551881352311a7c529824d536b Mon Sep 17 00:00:00 2001 From: Cory Simmons Date: Wed, 27 Jan 2016 17:39:57 -0500 Subject: [PATCH 5/5] Update README TODO stuff should be opened as new Issues --- CHANGELOG.md | 9 +++++++++ README.md | 50 ++++++++++++++++---------------------------------- 2 files changed, 25 insertions(+), 34 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..ad6b1d8 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,9 @@ +# 0.1.1 +- Clean up repo + +# 0.1.0 +- After some bug fixes it finally works down to IE5.5 on the desktop and Opera Mini on mobile!! +- Also, I removed the dependency on jQuery. +- Now resizes correctly right after page load. +- Media query support!! (rudimentary, but check out the new demo!) +- Right now, media queries only apply to rules with vw,vh/vmin units. Other rules won't be applied just yet. More to come... diff --git a/README.md b/README.md index f674b40..a008fd6 100644 --- a/README.md +++ b/README.md @@ -1,40 +1,22 @@ -vminpoly -======== +

vminpoly

-A polyfill for CSS units vw, vh & vmin. +

+ Viewport units for old browsers +

-Simple online [demo](http://saabi.github.com/vminpoly) right here. A more sophisticated [responsive demo](http://saabi.github.com/vminpoly/demo2.html) demonstrating vw/vh/vmin units along with *media queries*, working right down to IE5.5 on the desktop and Opera Mini on mobiles!! (In Opera Mini the browser must be refreshed after changing phone orientations as it appears it doesn't trigger the window resize event) +### Installation +Just include [vminpoly.dist.min.js](vminpoly.dist.min.js) before the `` tag. -This is a working proof of concept right now. There's a lot of cleanup to do on the code. +### Bower +`bower install --save vminpoly` -Since most browsers ignore rules they don't understand, the code must load and parse the original CSS sourcecode. It does this using a javascript [CSS parser](https://github.com/tabatkins/css-parser). Once this is done, it filters the generated tree leaving only rules that use 'vh', 'vw' & 'vmin' units. -At window resize time, it generates CSS code for the 'px' equivalents and appends it in a 'style' element at the end of the 'head' element. The generated code respects media queries. +### Browser Support +- Modern browsers +- IE5.5+ +- Opera Mini -As it is, it's fast enough for a lot of cases, but the code can still be optimized greatly, both in parsing and in resizing. +### Note +vminpoly requires a [tokenizer](vendor/tokenizer.js) and [parser](vendor/parser.js). Feel free to combine your own with [src/vminpoly.js](src/vminpoly.js). -Also, any suggestions on how to better organize the repo, specially with respect to third party code, is greatly appreciated. - -Notes ------ -* It's working fine in IE5.5+, Firefox, Opera and even Opera Mini, which doesn't support any of the units or media queries. Chrome, Safari and the Firefox beta don't need it. -* Well... Chrome and Safari actually can benefit from it as they don't properly handle font-size natively while resizing the window. - - -TODO: ------ - -* IE9 and IE10 support vw, vh & vm, so the code should only translate 'vmin' units to 'vm' -* Only linked stylesheets are being parsed right now but it's very easy to also parse 'style' elements. -* Also, recursively parse @import rules. -* Add some more examples of what can be achieved. - -In short, the only browser with apparently full native support right now is Firefox beta (Aurora). The rest will benefit from this polyfill immediately, even without the badly needed code polishing. - -Latest Changes: ---------------- - -* After some bug fixes it finally works down to **IE5.5 on the desktop** and **Opera Mini on mobile**!! -* Also, I removed the dependency on jQuery. -* Now resizes correctly right after page load. -* Media query support!! (rudimentary, but check out the [new demo!](http://saabi.github.com/vminpoly/demo2.html)) -* Right now, media queries only apply to rules with vw,vh/vmin units. Other rules won't be applied just yet. More to come... +### Contribute +vminpoly works pretty well, but it could be **vastly optimized**. If you're pretty handy with JavaScript we'd love for you to pitch in!