123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362 |
- //.CommonJS
- var CSSOM = {
- CSSStyleSheet: require("./CSSStyleSheet").CSSStyleSheet,
- CSSStyleRule: require("./CSSStyleRule").CSSStyleRule,
- CSSImportRule: require("./CSSImportRule").CSSImportRule,
- CSSMediaRule: require("./CSSMediaRule").CSSMediaRule
- };
- ///CommonJS
- CSSOM.Parser = function Parser() {};
- /**
- * @param {string} cssText
- * @param {Object} options
- */
- CSSOM.Parser.prototype.parseStyleSheet = function(cssText, options) {
- options = options || {};
- var i = options.startIndex || 0;
- for (var character; character = token.charAt(i); i++) {
- switch (character) {
- case " ":
- case "\t":
- case "\r":
- case "\n":
- case "\f":
- if (SIGNIFICANT_WHITESPACE[state]) {
- buffer += character;
- }
- break;
- }
- };
- CSSOM.Parser.prototype.parse = function(token, options) {
- options = options || {};
- var i = options.startIndex || 0;
- this.styleSheetStart(i);
- /**
- "before-selector" or
- "selector" or
- "atRule" or
- "atBlock" or
- "before-name" or
- "name" or
- "before-value" or
- "value"
- */
- var state = options.state || "before-selector";
- var index;
- var j = i;
- var buffer = "";
- var SIGNIFICANT_WHITESPACE = {
- "selector": true,
- "value": true,
- "atRule": true,
- "importRule-begin": true,
- "importRule": true,
- "atBlock": true
- };
- var styleSheet = new CSSOM.CSSStyleSheet;
- // @type CSSStyleSheet|CSSMediaRule
- var currentScope = styleSheet;
- var selector, name, value, priority="", styleRule, mediaRule, importRule;
- var declarationStarts;
- var declarationEnds;
- for (var character; character = token.charAt(i); i++) {
- switch (character) {
- case " ":
- case "\t":
- case "\r":
- case "\n":
- case "\f":
- if (SIGNIFICANT_WHITESPACE[state]) {
- buffer += character;
- }
- break;
- // String
- case '"':
- j = i + 1;
- index = token.indexOf('"', j) + 1;
- if (!index) {
- throw '" is missing';
- }
- buffer += token.slice(i, index);
- i = index - 1;
- if (state == 'before-value') {
- state = 'value';
- }
- break;
- case "'":
- j = i + 1;
- index = token.indexOf("'", j) + 1;
- if (!index) {
- throw "' is missing";
- }
- buffer += token.slice(i, index);
- i = index - 1;
- switch (state) {
- case 'before-value':
- state = 'value';
- break;
- case 'importRule-begin':
- state = 'importRule';
- break;
- }
- break;
- // Comment
- case "/":
- if (token.charAt(i + 1) == "*") {
- i += 2;
- index = token.indexOf("*/", i);
- if (index == -1) {
- throw SyntaxError("Missing */");
- } else {
- i = index + 1;
- }
- } else {
- buffer += character;
- }
- if (state == "importRule-begin") {
- buffer += " ";
- state = "importRule";
- }
- break;
- // At-rule
- case "@":
- if (token.indexOf("@media", i) == i) {
- state = "atBlock";
- mediaRule = new CSSOM.CSSMediaRule;
- mediaRule.__starts = i;
- i += "media".length;
- buffer = "";
- break;
- } else if (token.indexOf("@import", i) == i) {
- state = "importRule-begin";
- i += "import".length;
- buffer += "@import";
- break;
- } else if (state == "selector") {
- state = "atRule";
- }
- buffer += character;
- break;
- case "{":
- if (state == "selector" || state == "atRule") {
- this.selectorEnd(i, buffer);
- buffer = "";
- state = "before-name";
- } else if (state == "atBlock") {
- mediaRule.media.mediaText = buffer.trim();
- currentScope = mediaRule;
- buffer = "";
- state = "before-selector";
- }
- break;
- case ":":
- if (state == "name") {
- name = buffer;
- buffer = "";
- state = "before-value";
- } else {
- buffer += character;
- }
- break;
- case '(':
- if (state == 'value') {
- index = token.indexOf(')', i + 1);
- if (index == -1) {
- throw i + ': unclosed "("';
- }
- buffer += token.slice(i, index + 1);
- i = index;
- } else {
- buffer += character;
- }
- break;
- case "!":
- if (state == "value" && token.indexOf("!important", i) === i) {
- priority = "important";
- i += "important".length;
- } else {
- buffer += character;
- }
- break;
- case ";":
- switch (state) {
- case "value":
- this.declarationEnd(i, name, buffer, priority);
- priority = "";
- buffer = "";
- state = "before-name";
- break;
- case "atRule":
- buffer = "";
- state = "before-selector";
- break;
- case "importRule":
- importRule = new CSSOM.CSSImportRule;
- importRule.cssText = buffer + character;
- currentScope.cssRules.push(importRule);
- buffer = "";
- state = "before-selector";
- break;
- default:
- buffer += character;
- break;
- }
- break;
- case "}":
- switch (state) {
- case "value":
- this.declarationEnd(i, name, buffer, priority);
- // fall down
- case "before-name":
- this.styleRuleEnd(i);
- buffer = "";
- break;
- case "name":
- throw i + ": Oops";
- break;
- case "before-selector":
- case "selector":
- // End of media rule.
- // Nesting rules aren't supported yet
- if (!mediaRule) {
- throw "unexpected }";
- }
- mediaRule.__ends = i + 1;
- styleSheet.cssRules.push(mediaRule);
- currentScope = styleSheet;
- buffer = "";
- break;
- }
- state = "before-selector";
- break;
- default:
- switch (state) {
- case "before-selector":
- this.styleRuleStart(i);
- state = "selector";
- break;
- case "before-name":
- state = "name";
- break;
- case "before-value":
- state = "value";
- break;
- case "importRule-begin":
- state = "importRule";
- break;
- }
- buffer += character;
- break;
- }
- }
- return styleSheet;
- };
- CSSOM.Parser.prototype.compile = function() {
- var handlers = {
- styleSheetStart: this.styleSheetStart,
- styleRuleStart: this.styleRuleStart,
- selectorEnd: this.selectorEnd,
- declarationEnd: this.declarationEnd,
- styleRuleEnd: this.styleRuleEnd,
- styleSheetEnd: this.styleSheetEnd
- };
- var parser = this.parse.toString();
- for (var key in handlers) {
- if (!handlers.hasOwnProperty(key)) {
- continue;
- }
- parser = parser.replace(new RegExp('^.*' + key + '.*$', 'gm'), handlers[key].toString()
- .replace(/^function.+$/m, '')
- .replace(/^}/m, ''))
- .replace(/this\.?/g, '');
- }
- return parser;
- };
- CSSOM.Parser.prototype.styleSheetStart = function(i) {
- console.log('styleSheetStart', i);
- this.styleSheet = new CSSOM.CSSStyleSheet;
- this.scopeRules = this.styleSheet.cssRules;
- };
- CSSOM.Parser.prototype.styleRuleStart = function(i) {
- console.log('styleRuleStart', i);
- this.styleRule = new CSSOM.CSSStyleRule;
- this.styleRule._start = i;
- };
- CSSOM.Parser.prototype.selectorEnd = function(i, buffer) {
- this.styleRule.selectorText = buffer.trimRight();
- this.styleRule.style._start = i;
- };
- CSSOM.Parser.prototype.declarationEnd = function(name, value, priority, startIndex, endIndex) {
- console.log('declarationEnd', name, value, priority, startIndex, endIndex);
- };
- CSSOM.Parser.prototype.styleRuleEnd = function(i) {
- this.styleRule._end = i;
- this.scopeRules.push(this.styleRule);
- };
- CSSOM.Parser.prototype.styleSheetEnd = function(i) {
- return this.styleSheet;
- };
- /*
- Parser.prototype.nameStart = function(i) {
- this.nameStartIndex = i;
- };
- Parser.prototype.nameEnd = function(i, buffer) {
- this.name = buffer.trimRight();
- this.nameEndIndex = this.nameStartIndex + this.name.length;
- };
- Parser.prototype.valueStart = function(i) {
- this.valueStartIndex = i;
- };
- Parser.prototype.valueEnd = function(i, buffer) {
- var value = buffer.trimRight();
- this.styleRule.style.add(this.name, value, this.nameStartIndex, this.nameEndIndex, this.valueStartIndex, this.valueStartIndex + value.length);
- };
- */
- //.CommonJS
- exports.Parser = CSSOM.Parser;
- ///CommonJS
|