"no use strict"; ;(function(window) { if (typeof window.window != "undefined" && window.document) { return; } window.console = function() { var msgs = Array.prototype.slice.call(arguments, 0); postMessage({type: "log", data: msgs}); }; window.console.error = window.console.warn = window.console.log = window.console.trace = window.console; window.window = window; window.ace = window; window.onerror = function(message, file, line, col, err) { postMessage({type: "error", data: { message: message, file: file, line: line, col: col, stack: err.stack }}); }; window.normalizeModule = function(parentId, moduleName) { // normalize plugin requires if (moduleName.indexOf("!") !== -1) { var chunks = moduleName.split("!"); return window.normalizeModule(parentId, chunks[0]) + "!" + window.normalizeModule(parentId, chunks[1]); } // normalize relative requires if (moduleName.charAt(0) == ".") { var base = parentId.split("/").slice(0, -1).join("/"); moduleName = (base ? base + "/" : "") + moduleName; while(moduleName.indexOf(".") !== -1 && previous != moduleName) { var previous = moduleName; moduleName = moduleName.replace(/^\.\//, "").replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, ""); } } return moduleName; }; window.require = function(parentId, id) { if (!id) { id = parentId; parentId = null; } if (!id.charAt) throw new Error("worker.js require() accepts only (parentId, id) as arguments"); id = window.normalizeModule(parentId, id); var module = window.require.modules[id]; if (module) { if (!module.initialized) { module.initialized = true; module.exports = module.factory().exports; } return module.exports; } var chunks = id.split("/"); if (!window.require.tlns) return console.log("unable to load " + id); chunks[0] = window.require.tlns[chunks[0]] || chunks[0]; var path = chunks.join("/") + ".js"; window.require.id = id; importScripts(path); return window.require(parentId, id); }; window.require.modules = {}; window.require.tlns = {}; window.define = function(id, deps, factory) { if (arguments.length == 2) { factory = deps; if (typeof id != "string") { deps = id; id = window.require.id; } } else if (arguments.length == 1) { factory = id; deps = []; id = window.require.id; } if (typeof factory != "function") { window.require.modules[id] = { exports: factory, initialized: true }; return; } if (!deps.length) // If there is no dependencies, we inject 'require', 'exports' and // 'module' as dependencies, to provide CommonJS compatibility. deps = ['require', 'exports', 'module']; var req = function(childId) { return window.require(id, childId); }; window.require.modules[id] = { exports: {}, factory: function() { var module = this; var returnExports = factory.apply(this, deps.map(function(dep) { switch(dep) { // Because 'require', 'exports' and 'module' aren't actual // dependencies, we must handle them seperately. case 'require': return req; case 'exports': return module.exports; case 'module': return module; // But for all other dependencies, we can just go ahead and // require them. default: return req(dep); } })); if (returnExports) module.exports = returnExports; return module; } }; }; window.define.amd = {}; window.initBaseUrls = function initBaseUrls(topLevelNamespaces) { require.tlns = topLevelNamespaces; }; window.initSender = function initSender() { var EventEmitter = window.require("ace/lib/event_emitter").EventEmitter; var oop = window.require("ace/lib/oop"); var Sender = function() {}; (function() { oop.implement(this, EventEmitter); this.callback = function(data, callbackId) { postMessage({ type: "call", id: callbackId, data: data }); }; this.emit = function(name, data) { postMessage({ type: "event", name: name, data: data }); }; }).call(Sender.prototype); return new Sender(); }; var main = window.main = null; var sender = window.sender = null; window.onmessage = function(e) { var msg = e.data; if (msg.command) { if (main[msg.command]) main[msg.command].apply(main, msg.args); else throw new Error("Unknown command:" + msg.command); } else if (msg.init) { initBaseUrls(msg.tlns); require("ace/lib/es5-shim"); sender = window.sender = initSender(); var clazz = require(msg.module)[msg.classname]; main = window.main = new clazz(sender); } else if (msg.event && sender) { sender._signal(msg.event, msg.data); } }; })(this); ace.define("ace/lib/oop",["require","exports","module"], function(require, exports, module) { "use strict"; exports.inherits = function(ctor, superCtor) { ctor.super_ = superCtor; ctor.prototype = Object.create(superCtor.prototype, { constructor: { value: ctor, enumerable: false, writable: true, configurable: true } }); }; exports.mixin = function(obj, mixin) { for (var key in mixin) { obj[key] = mixin[key]; } return obj; }; exports.implement = function(proto, mixin) { exports.mixin(proto, mixin); }; }); ace.define("ace/lib/lang",["require","exports","module"], function(require, exports, module) { "use strict"; exports.last = function(a) { return a[a.length - 1]; }; exports.stringReverse = function(string) { return string.split("").reverse().join(""); }; exports.stringRepeat = function (string, count) { var result = ''; while (count > 0) { if (count & 1) result += string; if (count >>= 1) string += string; } return result; }; var trimBeginRegexp = /^\s\s*/; var trimEndRegexp = /\s\s*$/; exports.stringTrimLeft = function (string) { return string.replace(trimBeginRegexp, ''); }; exports.stringTrimRight = function (string) { return string.replace(trimEndRegexp, ''); }; exports.copyObject = function(obj) { var copy = {}; for (var key in obj) { copy[key] = obj[key]; } return copy; }; exports.copyArray = function(array){ var copy = []; for (var i=0, l=array.length; i [" + this.end.row + "/" + this.end.column + "]"); }; this.contains = function(row, column) { return this.compare(row, column) == 0; }; this.compareRange = function(range) { var cmp, end = range.end, start = range.start; cmp = this.compare(end.row, end.column); if (cmp == 1) { cmp = this.compare(start.row, start.column); if (cmp == 1) { return 2; } else if (cmp == 0) { return 1; } else { return 0; } } else if (cmp == -1) { return -2; } else { cmp = this.compare(start.row, start.column); if (cmp == -1) { return -1; } else if (cmp == 1) { return 42; } else { return 0; } } }; this.comparePoint = function(p) { return this.compare(p.row, p.column); }; this.containsRange = function(range) { return this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0; }; this.intersects = function(range) { var cmp = this.compareRange(range); return (cmp == -1 || cmp == 0 || cmp == 1); }; this.isEnd = function(row, column) { return this.end.row == row && this.end.column == column; }; this.isStart = function(row, column) { return this.start.row == row && this.start.column == column; }; this.setStart = function(row, column) { if (typeof row == "object") { this.start.column = row.column; this.start.row = row.row; } else { this.start.row = row; this.start.column = column; } }; this.setEnd = function(row, column) { if (typeof row == "object") { this.end.column = row.column; this.end.row = row.row; } else { this.end.row = row; this.end.column = column; } }; this.inside = function(row, column) { if (this.compare(row, column) == 0) { if (this.isEnd(row, column) || this.isStart(row, column)) { return false; } else { return true; } } return false; }; this.insideStart = function(row, column) { if (this.compare(row, column) == 0) { if (this.isEnd(row, column)) { return false; } else { return true; } } return false; }; this.insideEnd = function(row, column) { if (this.compare(row, column) == 0) { if (this.isStart(row, column)) { return false; } else { return true; } } return false; }; this.compare = function(row, column) { if (!this.isMultiLine()) { if (row === this.start.row) { return column < this.start.column ? -1 : (column > this.end.column ? 1 : 0); }; } if (row < this.start.row) return -1; if (row > this.end.row) return 1; if (this.start.row === row) return column >= this.start.column ? 0 : -1; if (this.end.row === row) return column <= this.end.column ? 0 : 1; return 0; }; this.compareStart = function(row, column) { if (this.start.row == row && this.start.column == column) { return -1; } else { return this.compare(row, column); } }; this.compareEnd = function(row, column) { if (this.end.row == row && this.end.column == column) { return 1; } else { return this.compare(row, column); } }; this.compareInside = function(row, column) { if (this.end.row == row && this.end.column == column) { return 1; } else if (this.start.row == row && this.start.column == column) { return -1; } else { return this.compare(row, column); } }; this.clipRows = function(firstRow, lastRow) { if (this.end.row > lastRow) var end = {row: lastRow + 1, column: 0}; else if (this.end.row < firstRow) var end = {row: firstRow, column: 0}; if (this.start.row > lastRow) var start = {row: lastRow + 1, column: 0}; else if (this.start.row < firstRow) var start = {row: firstRow, column: 0}; return Range.fromPoints(start || this.start, end || this.end); }; this.extend = function(row, column) { var cmp = this.compare(row, column); if (cmp == 0) return this; else if (cmp == -1) var start = {row: row, column: column}; else var end = {row: row, column: column}; return Range.fromPoints(start || this.start, end || this.end); }; this.isEmpty = function() { return (this.start.row === this.end.row && this.start.column === this.end.column); }; this.isMultiLine = function() { return (this.start.row !== this.end.row); }; this.clone = function() { return Range.fromPoints(this.start, this.end); }; this.collapseRows = function() { if (this.end.column == 0) return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row-1), 0) else return new Range(this.start.row, 0, this.end.row, 0) }; this.toScreenRange = function(session) { var screenPosStart = session.documentToScreenPosition(this.start); var screenPosEnd = session.documentToScreenPosition(this.end); return new Range( screenPosStart.row, screenPosStart.column, screenPosEnd.row, screenPosEnd.column ); }; this.moveBy = function(row, column) { this.start.row += row; this.start.column += column; this.end.row += row; this.end.column += column; }; }).call(Range.prototype); Range.fromPoints = function(start, end) { return new Range(start.row, start.column, end.row, end.column); }; Range.comparePoints = comparePoints; Range.comparePoints = function(p1, p2) { return p1.row - p2.row || p1.column - p2.column; }; exports.Range = Range; }); ace.define("ace/anchor",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"], function(require, exports, module) { "use strict"; var oop = require("./lib/oop"); var EventEmitter = require("./lib/event_emitter").EventEmitter; var Anchor = exports.Anchor = function(doc, row, column) { this.$onChange = this.onChange.bind(this); this.attach(doc); if (typeof column == "undefined") this.setPosition(row.row, row.column); else this.setPosition(row, column); }; (function() { oop.implement(this, EventEmitter); this.getPosition = function() { return this.$clipPositionToDocument(this.row, this.column); }; this.getDocument = function() { return this.document; }; this.$insertRight = false; this.onChange = function(e) { var delta = e.data; var range = delta.range; if (range.start.row == range.end.row && range.start.row != this.row) return; if (range.start.row > this.row) return; if (range.start.row == this.row && range.start.column > this.column) return; var row = this.row; var column = this.column; var start = range.start; var end = range.end; if (delta.action === "insertText") { if (start.row === row && start.column <= column) { if (start.column === column && this.$insertRight) { } else if (start.row === end.row) { column += end.column - start.column; } else { column -= start.column; row += end.row - start.row; } } else if (start.row !== end.row && start.row < row) { row += end.row - start.row; } } else if (delta.action === "insertLines") { if (start.row === row && column === 0 && this.$insertRight) { } else if (start.row <= row) { row += end.row - start.row; } } else if (delta.action === "removeText") { if (start.row === row && start.column < column) { if (end.column >= column) column = start.column; else column = Math.max(0, column - (end.column - start.column)); } else if (start.row !== end.row && start.row < row) { if (end.row === row) column = Math.max(0, column - end.column) + start.column; row -= (end.row - start.row); } else if (end.row === row) { row -= end.row - start.row; column = Math.max(0, column - end.column) + start.column; } } else if (delta.action == "removeLines") { if (start.row <= row) { if (end.row <= row) row -= end.row - start.row; else { row = start.row; column = 0; } } } this.setPosition(row, column, true); }; this.setPosition = function(row, column, noClip) { var pos; if (noClip) { pos = { row: row, column: column }; } else { pos = this.$clipPositionToDocument(row, column); } if (this.row == pos.row && this.column == pos.column) return; var old = { row: this.row, column: this.column }; this.row = pos.row; this.column = pos.column; this._signal("change", { old: old, value: pos }); }; this.detach = function() { this.document.removeEventListener("change", this.$onChange); }; this.attach = function(doc) { this.document = doc || this.document; this.document.on("change", this.$onChange); }; this.$clipPositionToDocument = function(row, column) { var pos = {}; if (row >= this.document.getLength()) { pos.row = Math.max(0, this.document.getLength() - 1); pos.column = this.document.getLine(pos.row).length; } else if (row < 0) { pos.row = 0; pos.column = 0; } else { pos.row = row; pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column)); } if (column < 0) pos.column = 0; return pos; }; }).call(Anchor.prototype); }); ace.define("ace/document",["require","exports","module","ace/lib/oop","ace/lib/event_emitter","ace/range","ace/anchor"], function(require, exports, module) { "use strict"; var oop = require("./lib/oop"); var EventEmitter = require("./lib/event_emitter").EventEmitter; var Range = require("./range").Range; var Anchor = require("./anchor").Anchor; var Document = function(text) { this.$lines = []; if (text.length === 0) { this.$lines = [""]; } else if (Array.isArray(text)) { this._insertLines(0, text); } else { this.insert({row: 0, column:0}, text); } }; (function() { oop.implement(this, EventEmitter); this.setValue = function(text) { var len = this.getLength(); this.remove(new Range(0, 0, len, this.getLine(len-1).length)); this.insert({row: 0, column:0}, text); }; this.getValue = function() { return this.getAllLines().join(this.getNewLineCharacter()); }; this.createAnchor = function(row, column) { return new Anchor(this, row, column); }; if ("aaa".split(/a/).length === 0) this.$split = function(text) { return text.replace(/\r\n|\r/g, "\n").split("\n"); }; else this.$split = function(text) { return text.split(/\r\n|\r|\n/); }; this.$detectNewLine = function(text) { var match = text.match(/^.*?(\r\n|\r|\n)/m); this.$autoNewLine = match ? match[1] : "\n"; this._signal("changeNewLineMode"); }; this.getNewLineCharacter = function() { switch (this.$newLineMode) { case "windows": return "\r\n"; case "unix": return "\n"; default: return this.$autoNewLine || "\n"; } }; this.$autoNewLine = ""; this.$newLineMode = "auto"; this.setNewLineMode = function(newLineMode) { if (this.$newLineMode === newLineMode) return; this.$newLineMode = newLineMode; this._signal("changeNewLineMode"); }; this.getNewLineMode = function() { return this.$newLineMode; }; this.isNewLine = function(text) { return (text == "\r\n" || text == "\r" || text == "\n"); }; this.getLine = function(row) { return this.$lines[row] || ""; }; this.getLines = function(firstRow, lastRow) { return this.$lines.slice(firstRow, lastRow + 1); }; this.getAllLines = function() { return this.getLines(0, this.getLength()); }; this.getLength = function() { return this.$lines.length; }; this.getTextRange = function(range) { if (range.start.row == range.end.row) { return this.getLine(range.start.row) .substring(range.start.column, range.end.column); } var lines = this.getLines(range.start.row, range.end.row); lines[0] = (lines[0] || "").substring(range.start.column); var l = lines.length - 1; if (range.end.row - range.start.row == l) lines[l] = lines[l].substring(0, range.end.column); return lines.join(this.getNewLineCharacter()); }; this.$clipPosition = function(position) { var length = this.getLength(); if (position.row >= length) { position.row = Math.max(0, length - 1); position.column = this.getLine(length-1).length; } else if (position.row < 0) position.row = 0; return position; }; this.insert = function(position, text) { if (!text || text.length === 0) return position; position = this.$clipPosition(position); if (this.getLength() <= 1) this.$detectNewLine(text); var lines = this.$split(text); var firstLine = lines.splice(0, 1)[0]; var lastLine = lines.length == 0 ? null : lines.splice(lines.length - 1, 1)[0]; position = this.insertInLine(position, firstLine); if (lastLine !== null) { position = this.insertNewLine(position); // terminate first line position = this._insertLines(position.row, lines); position = this.insertInLine(position, lastLine || ""); } return position; }; this.insertLines = function(row, lines) { if (row >= this.getLength()) return this.insert({row: row, column: 0}, "\n" + lines.join("\n")); return this._insertLines(Math.max(row, 0), lines); }; this._insertLines = function(row, lines) { if (lines.length == 0) return {row: row, column: 0}; while (lines.length > 0xF000) { var end = this._insertLines(row, lines.slice(0, 0xF000)); lines = lines.slice(0xF000); row = end.row; } var args = [row, 0]; args.push.apply(args, lines); this.$lines.splice.apply(this.$lines, args); var range = new Range(row, 0, row + lines.length, 0); var delta = { action: "insertLines", range: range, lines: lines }; this._signal("change", { data: delta }); return range.end; }; this.insertNewLine = function(position) { position = this.$clipPosition(position); var line = this.$lines[position.row] || ""; this.$lines[position.row] = line.substring(0, position.column); this.$lines.splice(position.row + 1, 0, line.substring(position.column, line.length)); var end = { row : position.row + 1, column : 0 }; var delta = { action: "insertText", range: Range.fromPoints(position, end), text: this.getNewLineCharacter() }; this._signal("change", { data: delta }); return end; }; this.insertInLine = function(position, text) { if (text.length == 0) return position; var line = this.$lines[position.row] || ""; this.$lines[position.row] = line.substring(0, position.column) + text + line.substring(position.column); var end = { row : position.row, column : position.column + text.length }; var delta = { action: "insertText", range: Range.fromPoints(position, end), text: text }; this._signal("change", { data: delta }); return end; }; this.remove = function(range) { if (!(range instanceof Range)) range = Range.fromPoints(range.start, range.end); range.start = this.$clipPosition(range.start); range.end = this.$clipPosition(range.end); if (range.isEmpty()) return range.start; var firstRow = range.start.row; var lastRow = range.end.row; if (range.isMultiLine()) { var firstFullRow = range.start.column == 0 ? firstRow : firstRow + 1; var lastFullRow = lastRow - 1; if (range.end.column > 0) this.removeInLine(lastRow, 0, range.end.column); if (lastFullRow >= firstFullRow) this._removeLines(firstFullRow, lastFullRow); if (firstFullRow != firstRow) { this.removeInLine(firstRow, range.start.column, this.getLine(firstRow).length); this.removeNewLine(range.start.row); } } else { this.removeInLine(firstRow, range.start.column, range.end.column); } return range.start; }; this.removeInLine = function(row, startColumn, endColumn) { if (startColumn == endColumn) return; var range = new Range(row, startColumn, row, endColumn); var line = this.getLine(row); var removed = line.substring(startColumn, endColumn); var newLine = line.substring(0, startColumn) + line.substring(endColumn, line.length); this.$lines.splice(row, 1, newLine); var delta = { action: "removeText", range: range, text: removed }; this._signal("change", { data: delta }); return range.start; }; this.removeLines = function(firstRow, lastRow) { if (firstRow < 0 || lastRow >= this.getLength()) return this.remove(new Range(firstRow, 0, lastRow + 1, 0)); return this._removeLines(firstRow, lastRow); }; this._removeLines = function(firstRow, lastRow) { var range = new Range(firstRow, 0, lastRow + 1, 0); var removed = this.$lines.splice(firstRow, lastRow - firstRow + 1); var delta = { action: "removeLines", range: range, nl: this.getNewLineCharacter(), lines: removed }; this._signal("change", { data: delta }); return removed; }; this.removeNewLine = function(row) { var firstLine = this.getLine(row); var secondLine = this.getLine(row+1); var range = new Range(row, firstLine.length, row+1, 0); var line = firstLine + secondLine; this.$lines.splice(row, 2, line); var delta = { action: "removeText", range: range, text: this.getNewLineCharacter() }; this._signal("change", { data: delta }); }; this.replace = function(range, text) { if (!(range instanceof Range)) range = Range.fromPoints(range.start, range.end); if (text.length == 0 && range.isEmpty()) return range.start; if (text == this.getTextRange(range)) return range.end; this.remove(range); if (text) { var end = this.insert(range.start, text); } else { end = range.start; } return end; }; this.applyDeltas = function(deltas) { for (var i=0; i=0; i--) { var delta = deltas[i]; var range = Range.fromPoints(delta.range.start, delta.range.end); if (delta.action == "insertLines") this._removeLines(range.start.row, range.end.row - 1); else if (delta.action == "insertText") this.remove(range); else if (delta.action == "removeLines") this._insertLines(range.start.row, delta.lines); else if (delta.action == "removeText") this.insert(range.start, delta.text); } }; this.indexToPosition = function(index, startRow) { var lines = this.$lines || this.getAllLines(); var newlineLength = this.getNewLineCharacter().length; for (var i = startRow || 0, l = lines.length; i < l; i++) { index -= lines[i].length + newlineLength; if (index < 0) return {row: i, column: index + lines[i].length + newlineLength}; } return {row: l-1, column: lines[l-1].length}; }; this.positionToIndex = function(pos, startRow) { var lines = this.$lines || this.getAllLines(); var newlineLength = this.getNewLineCharacter().length; var index = 0; var row = Math.min(pos.row, lines.length); for (var i = startRow || 0; i < row; ++i) index += lines[i].length + newlineLength; return index + pos.column; }; }).call(Document.prototype); exports.Document = Document; }); ace.define("ace/worker/mirror",["require","exports","module","ace/document","ace/lib/lang"], function(require, exports, module) { "use strict"; var Document = require("../document").Document; var lang = require("../lib/lang"); var Mirror = exports.Mirror = function(sender) { this.sender = sender; var doc = this.doc = new Document(""); var deferredUpdate = this.deferredUpdate = lang.delayedCall(this.onUpdate.bind(this)); var _self = this; sender.on("change", function(e) { doc.applyDeltas(e.data); if (_self.$timeout) return deferredUpdate.schedule(_self.$timeout); _self.onUpdate(); }); }; (function() { this.$timeout = 500; this.setTimeout = function(timeout) { this.$timeout = timeout; }; this.setValue = function(value) { this.doc.setValue(value); this.deferredUpdate.schedule(this.$timeout); }; this.getValue = function(callbackId) { this.sender.callback(this.doc.getValue(), callbackId); }; this.onUpdate = function() { }; this.isPending = function() { return this.deferredUpdate.isPending(); }; }).call(Mirror.prototype); }); ace.define("ace/mode/css/csslint",["require","exports","module"], function(require, exports, module) { var parserlib = {}; (function(){ function EventTarget(){ this._listeners = {}; } EventTarget.prototype = { constructor: EventTarget, addListener: function(type, listener){ if (!this._listeners[type]){ this._listeners[type] = []; } this._listeners[type].push(listener); }, fire: function(event){ if (typeof event == "string"){ event = { type: event }; } if (typeof event.target != "undefined"){ event.target = this; } if (typeof event.type == "undefined"){ throw new Error("Event object missing 'type' property."); } if (this._listeners[event.type]){ var listeners = this._listeners[event.type].concat(); for (var i=0, len=listeners.length; i < len; i++){ listeners[i].call(this, event); } } }, removeListener: function(type, listener){ if (this._listeners[type]){ var listeners = this._listeners[type]; for (var i=0, len=listeners.length; i < len; i++){ if (listeners[i] === listener){ listeners.splice(i, 1); break; } } } } }; function StringReader(text){ this._input = text.replace(/\n\r?/g, "\n"); this._line = 1; this._col = 1; this._cursor = 0; } StringReader.prototype = { constructor: StringReader, getCol: function(){ return this._col; }, getLine: function(){ return this._line ; }, eof: function(){ return (this._cursor == this._input.length); }, peek: function(count){ var c = null; count = (typeof count == "undefined" ? 1 : count); if (this._cursor < this._input.length){ c = this._input.charAt(this._cursor + count - 1); } return c; }, read: function(){ var c = null; if (this._cursor < this._input.length){ if (this._input.charAt(this._cursor) == "\n"){ this._line++; this._col=1; } else { this._col++; } c = this._input.charAt(this._cursor++); } return c; }, mark: function(){ this._bookmark = { cursor: this._cursor, line: this._line, col: this._col }; }, reset: function(){ if (this._bookmark){ this._cursor = this._bookmark.cursor; this._line = this._bookmark.line; this._col = this._bookmark.col; delete this._bookmark; } }, readTo: function(pattern){ var buffer = "", c; while (buffer.length < pattern.length || buffer.lastIndexOf(pattern) != buffer.length - pattern.length){ c = this.read(); if (c){ buffer += c; } else { throw new Error("Expected \"" + pattern + "\" at line " + this._line + ", col " + this._col + "."); } } return buffer; }, readWhile: function(filter){ var buffer = "", c = this.read(); while(c !== null && filter(c)){ buffer += c; c = this.read(); } return buffer; }, readMatch: function(matcher){ var source = this._input.substring(this._cursor), value = null; if (typeof matcher == "string"){ if (source.indexOf(matcher) === 0){ value = this.readCount(matcher.length); } } else if (matcher instanceof RegExp){ if (matcher.test(source)){ value = this.readCount(RegExp.lastMatch.length); } } return value; }, readCount: function(count){ var buffer = ""; while(count--){ buffer += this.read(); } return buffer; } }; function SyntaxError(message, line, col){ this.col = col; this.line = line; this.message = message; } SyntaxError.prototype = new Error(); function SyntaxUnit(text, line, col, type){ this.col = col; this.line = line; this.text = text; this.type = type; } SyntaxUnit.fromToken = function(token){ return new SyntaxUnit(token.value, token.startLine, token.startCol); }; SyntaxUnit.prototype = { constructor: SyntaxUnit, valueOf: function(){ return this.text; }, toString: function(){ return this.text; } }; function TokenStreamBase(input, tokenData){ this._reader = input ? new StringReader(input.toString()) : null; this._token = null; this._tokenData = tokenData; this._lt = []; this._ltIndex = 0; this._ltIndexCache = []; } TokenStreamBase.createTokenData = function(tokens){ var nameMap = [], typeMap = {}, tokenData = tokens.concat([]), i = 0, len = tokenData.length+1; tokenData.UNKNOWN = -1; tokenData.unshift({name:"EOF"}); for (; i < len; i++){ nameMap.push(tokenData[i].name); tokenData[tokenData[i].name] = i; if (tokenData[i].text){ typeMap[tokenData[i].text] = i; } } tokenData.name = function(tt){ return nameMap[tt]; }; tokenData.type = function(c){ return typeMap[c]; }; return tokenData; }; TokenStreamBase.prototype = { constructor: TokenStreamBase, match: function(tokenTypes, channel){ if (!(tokenTypes instanceof Array)){ tokenTypes = [tokenTypes]; } var tt = this.get(channel), i = 0, len = tokenTypes.length; while(i < len){ if (tt == tokenTypes[i++]){ return true; } } this.unget(); return false; }, mustMatch: function(tokenTypes, channel){ var token; if (!(tokenTypes instanceof Array)){ tokenTypes = [tokenTypes]; } if (!this.match.apply(this, arguments)){ token = this.LT(1); throw new SyntaxError("Expected " + this._tokenData[tokenTypes[0]].name + " at line " + token.startLine + ", col " + token.startCol + ".", token.startLine, token.startCol); } }, advance: function(tokenTypes, channel){ while(this.LA(0) !== 0 && !this.match(tokenTypes, channel)){ this.get(); } return this.LA(0); }, get: function(channel){ var tokenInfo = this._tokenData, reader = this._reader, value, i =0, len = tokenInfo.length, found = false, token, info; if (this._lt.length && this._ltIndex >= 0 && this._ltIndex < this._lt.length){ i++; this._token = this._lt[this._ltIndex++]; info = tokenInfo[this._token.type]; while((info.channel !== undefined && channel !== info.channel) && this._ltIndex < this._lt.length){ this._token = this._lt[this._ltIndex++]; info = tokenInfo[this._token.type]; i++; } if ((info.channel === undefined || channel === info.channel) && this._ltIndex <= this._lt.length){ this._ltIndexCache.push(i); return this._token.type; } } token = this._getToken(); if (token.type > -1 && !tokenInfo[token.type].hide){ token.channel = tokenInfo[token.type].channel; this._token = token; this._lt.push(token); this._ltIndexCache.push(this._lt.length - this._ltIndex + i); if (this._lt.length > 5){ this._lt.shift(); } if (this._ltIndexCache.length > 5){ this._ltIndexCache.shift(); } this._ltIndex = this._lt.length; } info = tokenInfo[token.type]; if (info && (info.hide || (info.channel !== undefined && channel !== info.channel))){ return this.get(channel); } else { return token.type; } }, LA: function(index){ var total = index, tt; if (index > 0){ if (index > 5){ throw new Error("Too much lookahead."); } while(total){ tt = this.get(); total--; } while(total < index){ this.unget(); total++; } } else if (index < 0){ if(this._lt[this._ltIndex+index]){ tt = this._lt[this._ltIndex+index].type; } else { throw new Error("Too much lookbehind."); } } else { tt = this._token.type; } return tt; }, LT: function(index){ this.LA(index); return this._lt[this._ltIndex+index-1]; }, peek: function(){ return this.LA(1); }, token: function(){ return this._token; }, tokenName: function(tokenType){ if (tokenType < 0 || tokenType > this._tokenData.length){ return "UNKNOWN_TOKEN"; } else { return this._tokenData[tokenType].name; } }, tokenType: function(tokenName){ return this._tokenData[tokenName] || -1; }, unget: function(){ if (this._ltIndexCache.length){ this._ltIndex -= this._ltIndexCache.pop();//--; this._token = this._lt[this._ltIndex - 1]; } else { throw new Error("Too much lookahead."); } } }; parserlib.util = { StringReader: StringReader, SyntaxError : SyntaxError, SyntaxUnit : SyntaxUnit, EventTarget : EventTarget, TokenStreamBase : TokenStreamBase }; })(); (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, StringReader = parserlib.util.StringReader, SyntaxError = parserlib.util.SyntaxError, SyntaxUnit = parserlib.util.SyntaxUnit; var Colors = { aliceblue :"#f0f8ff", antiquewhite :"#faebd7", aqua :"#00ffff", aquamarine :"#7fffd4", azure :"#f0ffff", beige :"#f5f5dc", bisque :"#ffe4c4", black :"#000000", blanchedalmond :"#ffebcd", blue :"#0000ff", blueviolet :"#8a2be2", brown :"#a52a2a", burlywood :"#deb887", cadetblue :"#5f9ea0", chartreuse :"#7fff00", chocolate :"#d2691e", coral :"#ff7f50", cornflowerblue :"#6495ed", cornsilk :"#fff8dc", crimson :"#dc143c", cyan :"#00ffff", darkblue :"#00008b", darkcyan :"#008b8b", darkgoldenrod :"#b8860b", darkgray :"#a9a9a9", darkgrey :"#a9a9a9", darkgreen :"#006400", darkkhaki :"#bdb76b", darkmagenta :"#8b008b", darkolivegreen :"#556b2f", darkorange :"#ff8c00", darkorchid :"#9932cc", darkred :"#8b0000", darksalmon :"#e9967a", darkseagreen :"#8fbc8f", darkslateblue :"#483d8b", darkslategray :"#2f4f4f", darkslategrey :"#2f4f4f", darkturquoise :"#00ced1", darkviolet :"#9400d3", deeppink :"#ff1493", deepskyblue :"#00bfff", dimgray :"#696969", dimgrey :"#696969", dodgerblue :"#1e90ff", firebrick :"#b22222", floralwhite :"#fffaf0", forestgreen :"#228b22", fuchsia :"#ff00ff", gainsboro :"#dcdcdc", ghostwhite :"#f8f8ff", gold :"#ffd700", goldenrod :"#daa520", gray :"#808080", grey :"#808080", green :"#008000", greenyellow :"#adff2f", honeydew :"#f0fff0", hotpink :"#ff69b4", indianred :"#cd5c5c", indigo :"#4b0082", ivory :"#fffff0", khaki :"#f0e68c", lavender :"#e6e6fa", lavenderblush :"#fff0f5", lawngreen :"#7cfc00", lemonchiffon :"#fffacd", lightblue :"#add8e6", lightcoral :"#f08080", lightcyan :"#e0ffff", lightgoldenrodyellow :"#fafad2", lightgray :"#d3d3d3", lightgrey :"#d3d3d3", lightgreen :"#90ee90", lightpink :"#ffb6c1", lightsalmon :"#ffa07a", lightseagreen :"#20b2aa", lightskyblue :"#87cefa", lightslategray :"#778899", lightslategrey :"#778899", lightsteelblue :"#b0c4de", lightyellow :"#ffffe0", lime :"#00ff00", limegreen :"#32cd32", linen :"#faf0e6", magenta :"#ff00ff", maroon :"#800000", mediumaquamarine:"#66cdaa", mediumblue :"#0000cd", mediumorchid :"#ba55d3", mediumpurple :"#9370d8", mediumseagreen :"#3cb371", mediumslateblue :"#7b68ee", mediumspringgreen :"#00fa9a", mediumturquoise :"#48d1cc", mediumvioletred :"#c71585", midnightblue :"#191970", mintcream :"#f5fffa", mistyrose :"#ffe4e1", moccasin :"#ffe4b5", navajowhite :"#ffdead", navy :"#000080", oldlace :"#fdf5e6", olive :"#808000", olivedrab :"#6b8e23", orange :"#ffa500", orangered :"#ff4500", orchid :"#da70d6", palegoldenrod :"#eee8aa", palegreen :"#98fb98", paleturquoise :"#afeeee", palevioletred :"#d87093", papayawhip :"#ffefd5", peachpuff :"#ffdab9", peru :"#cd853f", pink :"#ffc0cb", plum :"#dda0dd", powderblue :"#b0e0e6", purple :"#800080", red :"#ff0000", rosybrown :"#bc8f8f", royalblue :"#4169e1", saddlebrown :"#8b4513", salmon :"#fa8072", sandybrown :"#f4a460", seagreen :"#2e8b57", seashell :"#fff5ee", sienna :"#a0522d", silver :"#c0c0c0", skyblue :"#87ceeb", slateblue :"#6a5acd", slategray :"#708090", slategrey :"#708090", snow :"#fffafa", springgreen :"#00ff7f", steelblue :"#4682b4", tan :"#d2b48c", teal :"#008080", thistle :"#d8bfd8", tomato :"#ff6347", turquoise :"#40e0d0", violet :"#ee82ee", wheat :"#f5deb3", white :"#ffffff", whitesmoke :"#f5f5f5", yellow :"#ffff00", yellowgreen :"#9acd32", activeBorder :"Active window border.", activecaption :"Active window caption.", appworkspace :"Background color of multiple document interface.", background :"Desktop background.", buttonface :"The face background color for 3-D elements that appear 3-D due to one layer of surrounding border.", buttonhighlight :"The color of the border facing the light source for 3-D elements that appear 3-D due to one layer of surrounding border.", buttonshadow :"The color of the border away from the light source for 3-D elements that appear 3-D due to one layer of surrounding border.", buttontext :"Text on push buttons.", captiontext :"Text in caption, size box, and scrollbar arrow box.", graytext :"Grayed (disabled) text. This color is set to #000 if the current display driver does not support a solid gray color.", greytext :"Greyed (disabled) text. This color is set to #000 if the current display driver does not support a solid grey color.", highlight :"Item(s) selected in a control.", highlighttext :"Text of item(s) selected in a control.", inactiveborder :"Inactive window border.", inactivecaption :"Inactive window caption.", inactivecaptiontext :"Color of text in an inactive caption.", infobackground :"Background color for tooltip controls.", infotext :"Text color for tooltip controls.", menu :"Menu background.", menutext :"Text in menus.", scrollbar :"Scroll bar gray area.", threeddarkshadow :"The color of the darker (generally outer) of the two borders away from the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.", threedface :"The face background color for 3-D elements that appear 3-D due to two concentric layers of surrounding border.", threedhighlight :"The color of the lighter (generally outer) of the two borders facing the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.", threedlightshadow :"The color of the darker (generally inner) of the two borders facing the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.", threedshadow :"The color of the lighter (generally inner) of the two borders away from the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.", window :"Window background.", windowframe :"Window frame.", windowtext :"Text in windows." }; function Combinator(text, line, col){ SyntaxUnit.call(this, text, line, col, Parser.COMBINATOR_TYPE); this.type = "unknown"; if (/^\s+$/.test(text)){ this.type = "descendant"; } else if (text == ">"){ this.type = "child"; } else if (text == "+"){ this.type = "adjacent-sibling"; } else if (text == "~"){ this.type = "sibling"; } } Combinator.prototype = new SyntaxUnit(); Combinator.prototype.constructor = Combinator; function MediaFeature(name, value){ SyntaxUnit.call(this, "(" + name + (value !== null ? ":" + value : "") + ")", name.startLine, name.startCol, Parser.MEDIA_FEATURE_TYPE); this.name = name; this.value = value; } MediaFeature.prototype = new SyntaxUnit(); MediaFeature.prototype.constructor = MediaFeature; function MediaQuery(modifier, mediaType, features, line, col){ SyntaxUnit.call(this, (modifier ? modifier + " ": "") + (mediaType ? mediaType : "") + (mediaType && features.length > 0 ? " and " : "") + features.join(" and "), line, col, Parser.MEDIA_QUERY_TYPE); this.modifier = modifier; this.mediaType = mediaType; this.features = features; } MediaQuery.prototype = new SyntaxUnit(); MediaQuery.prototype.constructor = MediaQuery; function Parser(options){ EventTarget.call(this); this.options = options || {}; this._tokenStream = null; } Parser.DEFAULT_TYPE = 0; Parser.COMBINATOR_TYPE = 1; Parser.MEDIA_FEATURE_TYPE = 2; Parser.MEDIA_QUERY_TYPE = 3; Parser.PROPERTY_NAME_TYPE = 4; Parser.PROPERTY_VALUE_TYPE = 5; Parser.PROPERTY_VALUE_PART_TYPE = 6; Parser.SELECTOR_TYPE = 7; Parser.SELECTOR_PART_TYPE = 8; Parser.SELECTOR_SUB_PART_TYPE = 9; Parser.prototype = function(){ var proto = new EventTarget(), //new prototype prop, additions = { constructor: Parser, DEFAULT_TYPE : 0, COMBINATOR_TYPE : 1, MEDIA_FEATURE_TYPE : 2, MEDIA_QUERY_TYPE : 3, PROPERTY_NAME_TYPE : 4, PROPERTY_VALUE_TYPE : 5, PROPERTY_VALUE_PART_TYPE : 6, SELECTOR_TYPE : 7, SELECTOR_PART_TYPE : 8, SELECTOR_SUB_PART_TYPE : 9, _stylesheet: function(){ var tokenStream = this._tokenStream, charset = null, count, token, tt; this.fire("startstylesheet"); this._charset(); this._skipCruft(); while (tokenStream.peek() == Tokens.IMPORT_SYM){ this._import(); this._skipCruft(); } while (tokenStream.peek() == Tokens.NAMESPACE_SYM){ this._namespace(); this._skipCruft(); } tt = tokenStream.peek(); while(tt > Tokens.EOF){ try { switch(tt){ case Tokens.MEDIA_SYM: this._media(); this._skipCruft(); break; case Tokens.PAGE_SYM: this._page(); this._skipCruft(); break; case Tokens.FONT_FACE_SYM: this._font_face(); this._skipCruft(); break; case Tokens.KEYFRAMES_SYM: this._keyframes(); this._skipCruft(); break; case Tokens.VIEWPORT_SYM: this._viewport(); this._skipCruft(); break; case Tokens.UNKNOWN_SYM: //unknown @ rule tokenStream.get(); if (!this.options.strict){ this.fire({ type: "error", error: null, message: "Unknown @ rule: " + tokenStream.LT(0).value + ".", line: tokenStream.LT(0).startLine, col: tokenStream.LT(0).startCol }); count=0; while (tokenStream.advance([Tokens.LBRACE, Tokens.RBRACE]) == Tokens.LBRACE){ count++; //keep track of nesting depth } while(count){ tokenStream.advance([Tokens.RBRACE]); count--; } } else { throw new SyntaxError("Unknown @ rule.", tokenStream.LT(0).startLine, tokenStream.LT(0).startCol); } break; case Tokens.S: this._readWhitespace(); break; default: if(!this._ruleset()){ switch(tt){ case Tokens.CHARSET_SYM: token = tokenStream.LT(1); this._charset(false); throw new SyntaxError("@charset not allowed here.", token.startLine, token.startCol); case Tokens.IMPORT_SYM: token = tokenStream.LT(1); this._import(false); throw new SyntaxError("@import not allowed here.", token.startLine, token.startCol); case Tokens.NAMESPACE_SYM: token = tokenStream.LT(1); this._namespace(false); throw new SyntaxError("@namespace not allowed here.", token.startLine, token.startCol); default: tokenStream.get(); //get the last token this._unexpectedToken(tokenStream.token()); } } } } catch(ex) { if (ex instanceof SyntaxError && !this.options.strict){ this.fire({ type: "error", error: ex, message: ex.message, line: ex.line, col: ex.col }); } else { throw ex; } } tt = tokenStream.peek(); } if (tt != Tokens.EOF){ this._unexpectedToken(tokenStream.token()); } this.fire("endstylesheet"); }, _charset: function(emit){ var tokenStream = this._tokenStream, charset, token, line, col; if (tokenStream.match(Tokens.CHARSET_SYM)){ line = tokenStream.token().startLine; col = tokenStream.token().startCol; this._readWhitespace(); tokenStream.mustMatch(Tokens.STRING); token = tokenStream.token(); charset = token.value; this._readWhitespace(); tokenStream.mustMatch(Tokens.SEMICOLON); if (emit !== false){ this.fire({ type: "charset", charset:charset, line: line, col: col }); } } }, _import: function(emit){ var tokenStream = this._tokenStream, tt, uri, importToken, mediaList = []; tokenStream.mustMatch(Tokens.IMPORT_SYM); importToken = tokenStream.token(); this._readWhitespace(); tokenStream.mustMatch([Tokens.STRING, Tokens.URI]); uri = tokenStream.token().value.replace(/^(?:url\()?["']?([^"']+?)["']?\)?$/, "$1"); this._readWhitespace(); mediaList = this._media_query_list(); tokenStream.mustMatch(Tokens.SEMICOLON); this._readWhitespace(); if (emit !== false){ this.fire({ type: "import", uri: uri, media: mediaList, line: importToken.startLine, col: importToken.startCol }); } }, _namespace: function(emit){ var tokenStream = this._tokenStream, line, col, prefix, uri; tokenStream.mustMatch(Tokens.NAMESPACE_SYM); line = tokenStream.token().startLine; col = tokenStream.token().startCol; this._readWhitespace(); if (tokenStream.match(Tokens.IDENT)){ prefix = tokenStream.token().value; this._readWhitespace(); } tokenStream.mustMatch([Tokens.STRING, Tokens.URI]); uri = tokenStream.token().value.replace(/(?:url\()?["']([^"']+)["']\)?/, "$1"); this._readWhitespace(); tokenStream.mustMatch(Tokens.SEMICOLON); this._readWhitespace(); if (emit !== false){ this.fire({ type: "namespace", prefix: prefix, uri: uri, line: line, col: col }); } }, _media: function(){ var tokenStream = this._tokenStream, line, col, mediaList;// = []; tokenStream.mustMatch(Tokens.MEDIA_SYM); line = tokenStream.token().startLine; col = tokenStream.token().startCol; this._readWhitespace(); mediaList = this._media_query_list(); tokenStream.mustMatch(Tokens.LBRACE); this._readWhitespace(); this.fire({ type: "startmedia", media: mediaList, line: line, col: col }); while(true) { if (tokenStream.peek() == Tokens.PAGE_SYM){ this._page(); } else if (tokenStream.peek() == Tokens.FONT_FACE_SYM){ this._font_face(); } else if (tokenStream.peek() == Tokens.VIEWPORT_SYM){ this._viewport(); } else if (!this._ruleset()){ break; } } tokenStream.mustMatch(Tokens.RBRACE); this._readWhitespace(); this.fire({ type: "endmedia", media: mediaList, line: line, col: col }); }, _media_query_list: function(){ var tokenStream = this._tokenStream, mediaList = []; this._readWhitespace(); if (tokenStream.peek() == Tokens.IDENT || tokenStream.peek() == Tokens.LPAREN){ mediaList.push(this._media_query()); } while(tokenStream.match(Tokens.COMMA)){ this._readWhitespace(); mediaList.push(this._media_query()); } return mediaList; }, _media_query: function(){ var tokenStream = this._tokenStream, type = null, ident = null, token = null, expressions = []; if (tokenStream.match(Tokens.IDENT)){ ident = tokenStream.token().value.toLowerCase(); if (ident != "only" && ident != "not"){ tokenStream.unget(); ident = null; } else { token = tokenStream.token(); } } this._readWhitespace(); if (tokenStream.peek() == Tokens.IDENT){ type = this._media_type(); if (token === null){ token = tokenStream.token(); } } else if (tokenStream.peek() == Tokens.LPAREN){ if (token === null){ token = tokenStream.LT(1); } expressions.push(this._media_expression()); } if (type === null && expressions.length === 0){ return null; } else { this._readWhitespace(); while (tokenStream.match(Tokens.IDENT)){ if (tokenStream.token().value.toLowerCase() != "and"){ this._unexpectedToken(tokenStream.token()); } this._readWhitespace(); expressions.push(this._media_expression()); } } return new MediaQuery(ident, type, expressions, token.startLine, token.startCol); }, _media_type: function(){ return this._media_feature(); }, _media_expression: function(){ var tokenStream = this._tokenStream, feature = null, token, expression = null; tokenStream.mustMatch(Tokens.LPAREN); feature = this._media_feature(); this._readWhitespace(); if (tokenStream.match(Tokens.COLON)){ this._readWhitespace(); token = tokenStream.LT(1); expression = this._expression(); } tokenStream.mustMatch(Tokens.RPAREN); this._readWhitespace(); return new MediaFeature(feature, (expression ? new SyntaxUnit(expression, token.startLine, token.startCol) : null)); }, _media_feature: function(){ var tokenStream = this._tokenStream; tokenStream.mustMatch(Tokens.IDENT); return SyntaxUnit.fromToken(tokenStream.token()); }, _page: function(){ var tokenStream = this._tokenStream, line, col, identifier = null, pseudoPage = null; tokenStream.mustMatch(Tokens.PAGE_SYM); line = tokenStream.token().startLine; col = tokenStream.token().startCol; this._readWhitespace(); if (tokenStream.match(Tokens.IDENT)){ identifier = tokenStream.token().value; if (identifier.toLowerCase() === "auto"){ this._unexpectedToken(tokenStream.token()); } } if (tokenStream.peek() == Tokens.COLON){ pseudoPage = this._pseudo_page(); } this._readWhitespace(); this.fire({ type: "startpage", id: identifier, pseudo: pseudoPage, line: line, col: col }); this._readDeclarations(true, true); this.fire({ type: "endpage", id: identifier, pseudo: pseudoPage, line: line, col: col }); }, _margin: function(){ var tokenStream = this._tokenStream, line, col, marginSym = this._margin_sym(); if (marginSym){ line = tokenStream.token().startLine; col = tokenStream.token().startCol; this.fire({ type: "startpagemargin", margin: marginSym, line: line, col: col }); this._readDeclarations(true); this.fire({ type: "endpagemargin", margin: marginSym, line: line, col: col }); return true; } else { return false; } }, _margin_sym: function(){ var tokenStream = this._tokenStream; if(tokenStream.match([Tokens.TOPLEFTCORNER_SYM, Tokens.TOPLEFT_SYM, Tokens.TOPCENTER_SYM, Tokens.TOPRIGHT_SYM, Tokens.TOPRIGHTCORNER_SYM, Tokens.BOTTOMLEFTCORNER_SYM, Tokens.BOTTOMLEFT_SYM, Tokens.BOTTOMCENTER_SYM, Tokens.BOTTOMRIGHT_SYM, Tokens.BOTTOMRIGHTCORNER_SYM, Tokens.LEFTTOP_SYM, Tokens.LEFTMIDDLE_SYM, Tokens.LEFTBOTTOM_SYM, Tokens.RIGHTTOP_SYM, Tokens.RIGHTMIDDLE_SYM, Tokens.RIGHTBOTTOM_SYM])) { return SyntaxUnit.fromToken(tokenStream.token()); } else { return null; } }, _pseudo_page: function(){ var tokenStream = this._tokenStream; tokenStream.mustMatch(Tokens.COLON); tokenStream.mustMatch(Tokens.IDENT); return tokenStream.token().value; }, _font_face: function(){ var tokenStream = this._tokenStream, line, col; tokenStream.mustMatch(Tokens.FONT_FACE_SYM); line = tokenStream.token().startLine; col = tokenStream.token().startCol; this._readWhitespace(); this.fire({ type: "startfontface", line: line, col: col }); this._readDeclarations(true); this.fire({ type: "endfontface", line: line, col: col }); }, _viewport: function(){ var tokenStream = this._tokenStream, line, col; tokenStream.mustMatch(Tokens.VIEWPORT_SYM); line = tokenStream.token().startLine; col = tokenStream.token().startCol; this._readWhitespace(); this.fire({ type: "startviewport", line: line, col: col }); this._readDeclarations(true); this.fire({ type: "endviewport", line: line, col: col }); }, _operator: function(inFunction){ var tokenStream = this._tokenStream, token = null; if (tokenStream.match([Tokens.SLASH, Tokens.COMMA]) || (inFunction && tokenStream.match([Tokens.PLUS, Tokens.STAR, Tokens.MINUS]))){ token = tokenStream.token(); this._readWhitespace(); } return token ? PropertyValuePart.fromToken(token) : null; }, _combinator: function(){ var tokenStream = this._tokenStream, value = null, token; if(tokenStream.match([Tokens.PLUS, Tokens.GREATER, Tokens.TILDE])){ token = tokenStream.token(); value = new Combinator(token.value, token.startLine, token.startCol); this._readWhitespace(); } return value; }, _unary_operator: function(){ var tokenStream = this._tokenStream; if (tokenStream.match([Tokens.MINUS, Tokens.PLUS])){ return tokenStream.token().value; } else { return null; } }, _property: function(){ var tokenStream = this._tokenStream, value = null, hack = null, tokenValue, token, line, col; if (tokenStream.peek() == Tokens.STAR && this.options.starHack){ tokenStream.get(); token = tokenStream.token(); hack = token.value; line = token.startLine; col = token.startCol; } if(tokenStream.match(Tokens.IDENT)){ token = tokenStream.token(); tokenValue = token.value; if (tokenValue.charAt(0) == "_" && this.options.underscoreHack){ hack = "_"; tokenValue = tokenValue.substring(1); } value = new PropertyName(tokenValue, hack, (line||token.startLine), (col||token.startCol)); this._readWhitespace(); } return value; }, _ruleset: function(){ var tokenStream = this._tokenStream, tt, selectors; try { selectors = this._selectors_group(); } catch (ex){ if (ex instanceof SyntaxError && !this.options.strict){ this.fire({ type: "error", error: ex, message: ex.message, line: ex.line, col: ex.col }); tt = tokenStream.advance([Tokens.RBRACE]); if (tt == Tokens.RBRACE){ } else { throw ex; } } else { throw ex; } return true; } if (selectors){ this.fire({ type: "startrule", selectors: selectors, line: selectors[0].line, col: selectors[0].col }); this._readDeclarations(true); this.fire({ type: "endrule", selectors: selectors, line: selectors[0].line, col: selectors[0].col }); } return selectors; }, _selectors_group: function(){ var tokenStream = this._tokenStream, selectors = [], selector; selector = this._selector(); if (selector !== null){ selectors.push(selector); while(tokenStream.match(Tokens.COMMA)){ this._readWhitespace(); selector = this._selector(); if (selector !== null){ selectors.push(selector); } else { this._unexpectedToken(tokenStream.LT(1)); } } } return selectors.length ? selectors : null; }, _selector: function(){ var tokenStream = this._tokenStream, selector = [], nextSelector = null, combinator = null, ws = null; nextSelector = this._simple_selector_sequence(); if (nextSelector === null){ return null; } selector.push(nextSelector); do { combinator = this._combinator(); if (combinator !== null){ selector.push(combinator); nextSelector = this._simple_selector_sequence(); if (nextSelector === null){ this._unexpectedToken(tokenStream.LT(1)); } else { selector.push(nextSelector); } } else { if (this._readWhitespace()){ ws = new Combinator(tokenStream.token().value, tokenStream.token().startLine, tokenStream.token().startCol); combinator = this._combinator(); nextSelector = this._simple_selector_sequence(); if (nextSelector === null){ if (combinator !== null){ this._unexpectedToken(tokenStream.LT(1)); } } else { if (combinator !== null){ selector.push(combinator); } else { selector.push(ws); } selector.push(nextSelector); } } else { break; } } } while(true); return new Selector(selector, selector[0].line, selector[0].col); }, _simple_selector_sequence: function(){ var tokenStream = this._tokenStream, elementName = null, modifiers = [], selectorText= "", components = [ function(){ return tokenStream.match(Tokens.HASH) ? new SelectorSubPart(tokenStream.token().value, "id", tokenStream.token().startLine, tokenStream.token().startCol) : null; }, this._class, this._attrib, this._pseudo, this._negation ], i = 0, len = components.length, component = null, found = false, line, col; line = tokenStream.LT(1).startLine; col = tokenStream.LT(1).startCol; elementName = this._type_selector(); if (!elementName){ elementName = this._universal(); } if (elementName !== null){ selectorText += elementName; } while(true){ if (tokenStream.peek() === Tokens.S){ break; } while(i < len && component === null){ component = components[i++].call(this); } if (component === null){ if (selectorText === ""){ return null; } else { break; } } else { i = 0; modifiers.push(component); selectorText += component.toString(); component = null; } } return selectorText !== "" ? new SelectorPart(elementName, modifiers, selectorText, line, col) : null; }, _type_selector: function(){ var tokenStream = this._tokenStream, ns = this._namespace_prefix(), elementName = this._element_name(); if (!elementName){ if (ns){ tokenStream.unget(); if (ns.length > 1){ tokenStream.unget(); } } return null; } else { if (ns){ elementName.text = ns + elementName.text; elementName.col -= ns.length; } return elementName; } }, _class: function(){ var tokenStream = this._tokenStream, token; if (tokenStream.match(Tokens.DOT)){ tokenStream.mustMatch(Tokens.IDENT); token = tokenStream.token(); return new SelectorSubPart("." + token.value, "class", token.startLine, token.startCol - 1); } else { return null; } }, _element_name: function(){ var tokenStream = this._tokenStream, token; if (tokenStream.match(Tokens.IDENT)){ token = tokenStream.token(); return new SelectorSubPart(token.value, "elementName", token.startLine, token.startCol); } else { return null; } }, _namespace_prefix: function(){ var tokenStream = this._tokenStream, value = ""; if (tokenStream.LA(1) === Tokens.PIPE || tokenStream.LA(2) === Tokens.PIPE){ if(tokenStream.match([Tokens.IDENT, Tokens.STAR])){ value += tokenStream.token().value; } tokenStream.mustMatch(Tokens.PIPE); value += "|"; } return value.length ? value : null; }, _universal: function(){ var tokenStream = this._tokenStream, value = "", ns; ns = this._namespace_prefix(); if(ns){ value += ns; } if(tokenStream.match(Tokens.STAR)){ value += "*"; } return value.length ? value : null; }, _attrib: function(){ var tokenStream = this._tokenStream, value = null, ns, token; if (tokenStream.match(Tokens.LBRACKET)){ token = tokenStream.token(); value = token.value; value += this._readWhitespace(); ns = this._namespace_prefix(); if (ns){ value += ns; } tokenStream.mustMatch(Tokens.IDENT); value += tokenStream.token().value; value += this._readWhitespace(); if(tokenStream.match([Tokens.PREFIXMATCH, Tokens.SUFFIXMATCH, Tokens.SUBSTRINGMATCH, Tokens.EQUALS, Tokens.INCLUDES, Tokens.DASHMATCH])){ value += tokenStream.token().value; value += this._readWhitespace(); tokenStream.mustMatch([Tokens.IDENT, Tokens.STRING]); value += tokenStream.token().value; value += this._readWhitespace(); } tokenStream.mustMatch(Tokens.RBRACKET); return new SelectorSubPart(value + "]", "attribute", token.startLine, token.startCol); } else { return null; } }, _pseudo: function(){ var tokenStream = this._tokenStream, pseudo = null, colons = ":", line, col; if (tokenStream.match(Tokens.COLON)){ if (tokenStream.match(Tokens.COLON)){ colons += ":"; } if (tokenStream.match(Tokens.IDENT)){ pseudo = tokenStream.token().value; line = tokenStream.token().startLine; col = tokenStream.token().startCol - colons.length; } else if (tokenStream.peek() == Tokens.FUNCTION){ line = tokenStream.LT(1).startLine; col = tokenStream.LT(1).startCol - colons.length; pseudo = this._functional_pseudo(); } if (pseudo){ pseudo = new SelectorSubPart(colons + pseudo, "pseudo", line, col); } } return pseudo; }, _functional_pseudo: function(){ var tokenStream = this._tokenStream, value = null; if(tokenStream.match(Tokens.FUNCTION)){ value = tokenStream.token().value; value += this._readWhitespace(); value += this._expression(); tokenStream.mustMatch(Tokens.RPAREN); value += ")"; } return value; }, _expression: function(){ var tokenStream = this._tokenStream, value = ""; while(tokenStream.match([Tokens.PLUS, Tokens.MINUS, Tokens.DIMENSION, Tokens.NUMBER, Tokens.STRING, Tokens.IDENT, Tokens.LENGTH, Tokens.FREQ, Tokens.ANGLE, Tokens.TIME, Tokens.RESOLUTION, Tokens.SLASH])){ value += tokenStream.token().value; value += this._readWhitespace(); } return value.length ? value : null; }, _negation: function(){ var tokenStream = this._tokenStream, line, col, value = "", arg, subpart = null; if (tokenStream.match(Tokens.NOT)){ value = tokenStream.token().value; line = tokenStream.token().startLine; col = tokenStream.token().startCol; value += this._readWhitespace(); arg = this._negation_arg(); value += arg; value += this._readWhitespace(); tokenStream.match(Tokens.RPAREN); value += tokenStream.token().value; subpart = new SelectorSubPart(value, "not", line, col); subpart.args.push(arg); } return subpart; }, _negation_arg: function(){ var tokenStream = this._tokenStream, args = [ this._type_selector, this._universal, function(){ return tokenStream.match(Tokens.HASH) ? new SelectorSubPart(tokenStream.token().value, "id", tokenStream.token().startLine, tokenStream.token().startCol) : null; }, this._class, this._attrib, this._pseudo ], arg = null, i = 0, len = args.length, elementName, line, col, part; line = tokenStream.LT(1).startLine; col = tokenStream.LT(1).startCol; while(i < len && arg === null){ arg = args[i].call(this); i++; } if (arg === null){ this._unexpectedToken(tokenStream.LT(1)); } if (arg.type == "elementName"){ part = new SelectorPart(arg, [], arg.toString(), line, col); } else { part = new SelectorPart(null, [arg], arg.toString(), line, col); } return part; }, _declaration: function(){ var tokenStream = this._tokenStream, property = null, expr = null, prio = null, error = null, invalid = null, propertyName= ""; property = this._property(); if (property !== null){ tokenStream.mustMatch(Tokens.COLON); this._readWhitespace(); expr = this._expr(); if (!expr || expr.length === 0){ this._unexpectedToken(tokenStream.LT(1)); } prio = this._prio(); propertyName = property.toString(); if (this.options.starHack && property.hack == "*" || this.options.underscoreHack && property.hack == "_") { propertyName = property.text; } try { this._validateProperty(propertyName, expr); } catch (ex) { invalid = ex; } this.fire({ type: "property", property: property, value: expr, important: prio, line: property.line, col: property.col, invalid: invalid }); return true; } else { return false; } }, _prio: function(){ var tokenStream = this._tokenStream, result = tokenStream.match(Tokens.IMPORTANT_SYM); this._readWhitespace(); return result; }, _expr: function(inFunction){ var tokenStream = this._tokenStream, values = [], value = null, operator = null; value = this._term(inFunction); if (value !== null){ values.push(value); do { operator = this._operator(inFunction); if (operator){ values.push(operator); } /*else { values.push(new PropertyValue(valueParts, valueParts[0].line, valueParts[0].col)); valueParts = []; }*/ value = this._term(inFunction); if (value === null){ break; } else { values.push(value); } } while(true); } return values.length > 0 ? new PropertyValue(values, values[0].line, values[0].col) : null; }, _term: function(inFunction){ var tokenStream = this._tokenStream, unary = null, value = null, endChar = null, token, line, col; unary = this._unary_operator(); if (unary !== null){ line = tokenStream.token().startLine; col = tokenStream.token().startCol; } if (tokenStream.peek() == Tokens.IE_FUNCTION && this.options.ieFilters){ value = this._ie_function(); if (unary === null){ line = tokenStream.token().startLine; col = tokenStream.token().startCol; } } else if (inFunction && tokenStream.match([Tokens.LPAREN, Tokens.LBRACE, Tokens.LBRACKET])){ token = tokenStream.token(); endChar = token.endChar; value = token.value + this._expr(inFunction).text; if (unary === null){ line = tokenStream.token().startLine; col = tokenStream.token().startCol; } tokenStream.mustMatch(Tokens.type(endChar)); value += endChar; this._readWhitespace(); } else if (tokenStream.match([Tokens.NUMBER, Tokens.PERCENTAGE, Tokens.LENGTH, Tokens.ANGLE, Tokens.TIME, Tokens.FREQ, Tokens.STRING, Tokens.IDENT, Tokens.URI, Tokens.UNICODE_RANGE])){ value = tokenStream.token().value; if (unary === null){ line = tokenStream.token().startLine; col = tokenStream.token().startCol; } this._readWhitespace(); } else { token = this._hexcolor(); if (token === null){ if (unary === null){ line = tokenStream.LT(1).startLine; col = tokenStream.LT(1).startCol; } if (value === null){ if (tokenStream.LA(3) == Tokens.EQUALS && this.options.ieFilters){ value = this._ie_function(); } else { value = this._function(); } } } else { value = token.value; if (unary === null){ line = token.startLine; col = token.startCol; } } } return value !== null ? new PropertyValuePart(unary !== null ? unary + value : value, line, col) : null; }, _function: function(){ var tokenStream = this._tokenStream, functionText = null, expr = null, lt; if (tokenStream.match(Tokens.FUNCTION)){ functionText = tokenStream.token().value; this._readWhitespace(); expr = this._expr(true); functionText += expr; if (this.options.ieFilters && tokenStream.peek() == Tokens.EQUALS){ do { if (this._readWhitespace()){ functionText += tokenStream.token().value; } if (tokenStream.LA(0) == Tokens.COMMA){ functionText += tokenStream.token().value; } tokenStream.match(Tokens.IDENT); functionText += tokenStream.token().value; tokenStream.match(Tokens.EQUALS); functionText += tokenStream.token().value; lt = tokenStream.peek(); while(lt != Tokens.COMMA && lt != Tokens.S && lt != Tokens.RPAREN){ tokenStream.get(); functionText += tokenStream.token().value; lt = tokenStream.peek(); } } while(tokenStream.match([Tokens.COMMA, Tokens.S])); } tokenStream.match(Tokens.RPAREN); functionText += ")"; this._readWhitespace(); } return functionText; }, _ie_function: function(){ var tokenStream = this._tokenStream, functionText = null, expr = null, lt; if (tokenStream.match([Tokens.IE_FUNCTION, Tokens.FUNCTION])){ functionText = tokenStream.token().value; do { if (this._readWhitespace()){ functionText += tokenStream.token().value; } if (tokenStream.LA(0) == Tokens.COMMA){ functionText += tokenStream.token().value; } tokenStream.match(Tokens.IDENT); functionText += tokenStream.token().value; tokenStream.match(Tokens.EQUALS); functionText += tokenStream.token().value; lt = tokenStream.peek(); while(lt != Tokens.COMMA && lt != Tokens.S && lt != Tokens.RPAREN){ tokenStream.get(); functionText += tokenStream.token().value; lt = tokenStream.peek(); } } while(tokenStream.match([Tokens.COMMA, Tokens.S])); tokenStream.match(Tokens.RPAREN); functionText += ")"; this._readWhitespace(); } return functionText; }, _hexcolor: function(){ var tokenStream = this._tokenStream, token = null, color; if(tokenStream.match(Tokens.HASH)){ token = tokenStream.token(); color = token.value; if (!/#[a-f0-9]{3,6}/i.test(color)){ throw new SyntaxError("Expected a hex color but found '" + color + "' at line " + token.startLine + ", col " + token.startCol + ".", token.startLine, token.startCol); } this._readWhitespace(); } return token; }, _keyframes: function(){ var tokenStream = this._tokenStream, token, tt, name, prefix = ""; tokenStream.mustMatch(Tokens.KEYFRAMES_SYM); token = tokenStream.token(); if (/^@\-([^\-]+)\-/.test(token.value)) { prefix = RegExp.$1; } this._readWhitespace(); name = this._keyframe_name(); this._readWhitespace(); tokenStream.mustMatch(Tokens.LBRACE); this.fire({ type: "startkeyframes", name: name, prefix: prefix, line: token.startLine, col: token.startCol }); this._readWhitespace(); tt = tokenStream.peek(); while(tt == Tokens.IDENT || tt == Tokens.PERCENTAGE) { this._keyframe_rule(); this._readWhitespace(); tt = tokenStream.peek(); } this.fire({ type: "endkeyframes", name: name, prefix: prefix, line: token.startLine, col: token.startCol }); this._readWhitespace(); tokenStream.mustMatch(Tokens.RBRACE); }, _keyframe_name: function(){ var tokenStream = this._tokenStream, token; tokenStream.mustMatch([Tokens.IDENT, Tokens.STRING]); return SyntaxUnit.fromToken(tokenStream.token()); }, _keyframe_rule: function(){ var tokenStream = this._tokenStream, token, keyList = this._key_list(); this.fire({ type: "startkeyframerule", keys: keyList, line: keyList[0].line, col: keyList[0].col }); this._readDeclarations(true); this.fire({ type: "endkeyframerule", keys: keyList, line: keyList[0].line, col: keyList[0].col }); }, _key_list: function(){ var tokenStream = this._tokenStream, token, key, keyList = []; keyList.push(this._key()); this._readWhitespace(); while(tokenStream.match(Tokens.COMMA)){ this._readWhitespace(); keyList.push(this._key()); this._readWhitespace(); } return keyList; }, _key: function(){ var tokenStream = this._tokenStream, token; if (tokenStream.match(Tokens.PERCENTAGE)){ return SyntaxUnit.fromToken(tokenStream.token()); } else if (tokenStream.match(Tokens.IDENT)){ token = tokenStream.token(); if (/from|to/i.test(token.value)){ return SyntaxUnit.fromToken(token); } tokenStream.unget(); } this._unexpectedToken(tokenStream.LT(1)); }, _skipCruft: function(){ while(this._tokenStream.match([Tokens.S, Tokens.CDO, Tokens.CDC])){ } }, _readDeclarations: function(checkStart, readMargins){ var tokenStream = this._tokenStream, tt; this._readWhitespace(); if (checkStart){ tokenStream.mustMatch(Tokens.LBRACE); } this._readWhitespace(); try { while(true){ if (tokenStream.match(Tokens.SEMICOLON) || (readMargins && this._margin())){ } else if (this._declaration()){ if (!tokenStream.match(Tokens.SEMICOLON)){ break; } } else { break; } this._readWhitespace(); } tokenStream.mustMatch(Tokens.RBRACE); this._readWhitespace(); } catch (ex) { if (ex instanceof SyntaxError && !this.options.strict){ this.fire({ type: "error", error: ex, message: ex.message, line: ex.line, col: ex.col }); tt = tokenStream.advance([Tokens.SEMICOLON, Tokens.RBRACE]); if (tt == Tokens.SEMICOLON){ this._readDeclarations(false, readMargins); } else if (tt != Tokens.RBRACE){ throw ex; } } else { throw ex; } } }, _readWhitespace: function(){ var tokenStream = this._tokenStream, ws = ""; while(tokenStream.match(Tokens.S)){ ws += tokenStream.token().value; } return ws; }, _unexpectedToken: function(token){ throw new SyntaxError("Unexpected token '" + token.value + "' at line " + token.startLine + ", col " + token.startCol + ".", token.startLine, token.startCol); }, _verifyEnd: function(){ if (this._tokenStream.LA(1) != Tokens.EOF){ this._unexpectedToken(this._tokenStream.LT(1)); } }, _validateProperty: function(property, value){ Validation.validate(property, value); }, parse: function(input){ this._tokenStream = new TokenStream(input, Tokens); this._stylesheet(); }, parseStyleSheet: function(input){ return this.parse(input); }, parseMediaQuery: function(input){ this._tokenStream = new TokenStream(input, Tokens); var result = this._media_query(); this._verifyEnd(); return result; }, parsePropertyValue: function(input){ this._tokenStream = new TokenStream(input, Tokens); this._readWhitespace(); var result = this._expr(); this._readWhitespace(); this._verifyEnd(); return result; }, parseRule: function(input){ this._tokenStream = new TokenStream(input, Tokens); this._readWhitespace(); var result = this._ruleset(); this._readWhitespace(); this._verifyEnd(); return result; }, parseSelector: function(input){ this._tokenStream = new TokenStream(input, Tokens); this._readWhitespace(); var result = this._selector(); this._readWhitespace(); this._verifyEnd(); return result; }, parseStyleAttribute: function(input){ input += "}"; // for error recovery in _readDeclarations() this._tokenStream = new TokenStream(input, Tokens); this._readDeclarations(); } }; for (prop in additions){ if (additions.hasOwnProperty(prop)){ proto[prop] = additions[prop]; } } return proto; }(); var Properties = { "align-items" : "flex-start | flex-end | center | baseline | stretch", "align-content" : "flex-start | flex-end | center | space-between | space-around | stretch", "align-self" : "auto | flex-start | flex-end | center | baseline | stretch", "-webkit-align-items" : "flex-start | flex-end | center | baseline | stretch", "-webkit-align-content" : "flex-start | flex-end | center | space-between | space-around | stretch", "-webkit-align-self" : "auto | flex-start | flex-end | center | baseline | stretch", "alignment-adjust" : "auto | baseline | before-edge | text-before-edge | middle | central | after-edge | text-after-edge | ideographic | alphabetic | hanging | mathematical | | ", "alignment-baseline" : "baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical", "animation" : 1, "animation-delay" : { multi: "