diff options
Diffstat (limited to 'toolkit/devtools/sourceeditor/css-tokenizer.js')
-rw-r--r-- | toolkit/devtools/sourceeditor/css-tokenizer.js | 717 |
1 files changed, 717 insertions, 0 deletions
diff --git a/toolkit/devtools/sourceeditor/css-tokenizer.js b/toolkit/devtools/sourceeditor/css-tokenizer.js new file mode 100644 index 000000000..f7d596a80 --- /dev/null +++ b/toolkit/devtools/sourceeditor/css-tokenizer.js @@ -0,0 +1,717 @@ +/** + * This file is taken from the below mentioned url and is under CC0 license. + * https://github.com/tabatkins/css-parser/blob/master/tokenizer.js + * Please retain this comment while updating this file from upstream. + */ + +(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 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; } + } + var value = parseInt(digits.map(String.fromCharCode).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 if(namestartchar(next())) switchto("identifier") && reconsume(); + else emit(new DelimToken(code)); + } + else if(code == 0x2e) { + if(digit(next())) switchto("number") && reconsume(); + else emit(new DelimToken(code)); + } + else if(code == 0x2f) { + if(next() == 0x2a) 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("identifier") && 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 if((next(1) == 0x52 || next(1) == 0x72) && (next(2) == 0x4c || next(2) == 0x6c) && (next(3) == 0x28)) consume(3) && switchto("url"); + else switchto("identifier") && reconsume(); + } + else if(namestartchar(code)) switchto("identifier") && 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"); + 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(new DelimToken(0x23)) && 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())) consume() && create(new AtKeywordToken([0x40,code])) && switchto('at-keyword-rest'); + else 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 "identifier": + if(code == 0x2d) { + if(namestartchar(next())) create(new IdentifierToken(code)) && switchto('identifier-rest'); + else switchto('data') && reconsume(); + } + else if(namestartchar(code)) create(new IdentifierToken(code)) && switchto('identifier-rest'); + else if(code == 0x5c) { + if(badescape(next())) parseerror() && switchto("data") && reconsume(); + else create(new IdentifierToken(consumeEscape())) && switchto('identifier-rest'); + } + else switchto('data') && reconsume(); + break; + + case "identifier-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) emit(new FunctionToken(currtoken)) && switchto('data'); + else if(whitespace(code) && options.transformFunctionWhitespace) switchto('transform-function-whitespace'); + else emit() && switchto('data') && reconsume(); + break; + + case "transform-function-whitespace": + if(whitespace(code)) 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') && reconsume(); + else if(code == 0x45 || code == 0x65) { + if(!options.scientificNotation) create(new DimensionToken(currtoken,code)) && switchto('dimension'); + else 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)) 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 == 0x2e) emit() && switchto('data') && reconsume(); + else if(code == 0x25) emit(new PercentageToken(currtoken)) && switchto('data') && reconsume(); + else if(code == 0x45 || code == 0x65) { + if(!options.scientificNotation) create(new DimensionToken(currtoken,code)) && switchto('dimension'); + else 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)) 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": + if(digit(code)) currtoken.append(code); + else emit() && switchto('data') && reconsume(); + break; + + case "url": + 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 == undefined) create(new URLToken); + + 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 == undefined) create(new URLToken); + + 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(whitespace(code)) donothing(); + else if(code == 0x29) emit() && switchto('data'); + else parseerror() && switchto('bad-url') && reconsume(); + break; + + case "url-unquoted": + if(currtoken == undefined) create(new URLToken); + + 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(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: + console.log("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.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"; } + +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+")"; } + +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 = stringFromCodeArray(this.value); + return this; +} + +function IdentifierToken(val) { + this.value = []; + this.append(val); +} +IdentifierToken.prototype = new StringValuedToken; +IdentifierToken.prototype.tokenType = "IDENT"; +IdentifierToken.prototype.toString = function() { return "IDENT("+this.value+")"; } + +function FunctionToken(val) { + // These are always constructed by passing an IdentifierToken + this.value = val.finish().value; +} +FunctionToken.prototype = new CSSParserToken; +FunctionToken.prototype.tokenType = "FUNCTION"; +FunctionToken.prototype.toString = function() { return "FUNCTION("+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+")"; } + +function HashToken(val) { + this.value = []; + this.append(val); +} +HashToken.prototype = new StringValuedToken; +HashToken.prototype.tokenType = "HASH"; +HashToken.prototype.toString = function() { return "HASH("+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+"\""; } + +function URLToken(val) { + this.value = []; + this.append(val); +} +URLToken.prototype = new StringValuedToken; +URLToken.prototype.tokenType = "URL"; +URLToken.prototype.toString = 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.finish = function() { + this.repr = stringFromCodeArray(this.value); + 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+")"; } + +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.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.contains = function(code) { + return code >= this.start && code < this.end; +} + + +// Exportation. +// TODO: also export the various tokens objects? +module.exports = tokenize; + +})); |