Spaces:
Running
Running
| //.CommonJS | |
| var CSSOM = {}; | |
| ///CommonJS | |
| /** | |
| * @param {string} token | |
| */ | |
| CSSOM.parse = function parse(token) { | |
| var i = 0; | |
| /** | |
| "before-selector" or | |
| "selector" or | |
| "atRule" or | |
| "atBlock" or | |
| "conditionBlock" or | |
| "before-name" or | |
| "name" or | |
| "before-value" or | |
| "value" | |
| */ | |
| var state = "before-selector"; | |
| var index; | |
| var buffer = ""; | |
| var valueParenthesisDepth = 0; | |
| var SIGNIFICANT_WHITESPACE = { | |
| "selector": true, | |
| "value": true, | |
| "value-parenthesis": true, | |
| "atRule": true, | |
| "importRule-begin": true, | |
| "importRule": true, | |
| "atBlock": true, | |
| "containerBlock": true, | |
| "conditionBlock": true, | |
| 'documentRule-begin': true | |
| }; | |
| var styleSheet = new CSSOM.CSSStyleSheet(); | |
| // @type CSSStyleSheet|CSSMediaRule|CSSContainerRule|CSSSupportsRule|CSSFontFaceRule|CSSKeyframesRule|CSSDocumentRule | |
| var currentScope = styleSheet; | |
| // @type CSSMediaRule|CSSContainerRule|CSSSupportsRule|CSSKeyframesRule|CSSDocumentRule | |
| var parentRule; | |
| var ancestorRules = []; | |
| var hasAncestors = false; | |
| var prevScope; | |
| var name, priority="", styleRule, mediaRule, containerRule, supportsRule, importRule, fontFaceRule, keyframesRule, documentRule, hostRule, startingStyleRule; | |
| var atKeyframesRegExp = /@(-(?:\w+-)+)?keyframes/g; | |
| var parseError = function(message) { | |
| var lines = token.substring(0, i).split('\n'); | |
| var lineCount = lines.length; | |
| var charCount = lines.pop().length + 1; | |
| var error = new Error(message + ' (line ' + lineCount + ', char ' + charCount + ')'); | |
| error.line = lineCount; | |
| /* jshint sub : true */ | |
| error['char'] = charCount; | |
| error.styleSheet = styleSheet; | |
| throw error; | |
| }; | |
| 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 '"': | |
| index = i + 1; | |
| do { | |
| index = token.indexOf('"', index) + 1; | |
| if (!index) { | |
| parseError('Unmatched "'); | |
| } | |
| } while (token[index - 2] === '\\'); | |
| buffer += token.slice(i, index); | |
| i = index - 1; | |
| switch (state) { | |
| case 'before-value': | |
| state = 'value'; | |
| break; | |
| case 'importRule-begin': | |
| state = 'importRule'; | |
| break; | |
| } | |
| break; | |
| case "'": | |
| index = i + 1; | |
| do { | |
| index = token.indexOf("'", index) + 1; | |
| if (!index) { | |
| parseError("Unmatched '"); | |
| } | |
| } while (token[index - 2] === '\\'); | |
| 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) { | |
| parseError("Missing */"); | |
| } else { | |
| i = index + 1; | |
| } | |
| } else { | |
| buffer += character; | |
| } | |
| if (state === "importRule-begin") { | |
| buffer += " "; | |
| state = "importRule"; | |
| } | |
| break; | |
| // At-rule | |
| case "@": | |
| if (token.indexOf("@-moz-document", i) === i) { | |
| state = "documentRule-begin"; | |
| documentRule = new CSSOM.CSSDocumentRule(); | |
| documentRule.__starts = i; | |
| i += "-moz-document".length; | |
| buffer = ""; | |
| break; | |
| } else if (token.indexOf("@media", i) === i) { | |
| state = "atBlock"; | |
| mediaRule = new CSSOM.CSSMediaRule(); | |
| mediaRule.__starts = i; | |
| i += "media".length; | |
| buffer = ""; | |
| break; | |
| } else if (token.indexOf("@container", i) === i) { | |
| state = "containerBlock"; | |
| containerRule = new CSSOM.CSSContainerRule(); | |
| containerRule.__starts = i; | |
| i += "container".length; | |
| buffer = ""; | |
| break; | |
| } else if (token.indexOf("@supports", i) === i) { | |
| state = "conditionBlock"; | |
| supportsRule = new CSSOM.CSSSupportsRule(); | |
| supportsRule.__starts = i; | |
| i += "supports".length; | |
| buffer = ""; | |
| break; | |
| } else if (token.indexOf("@host", i) === i) { | |
| state = "hostRule-begin"; | |
| i += "host".length; | |
| hostRule = new CSSOM.CSSHostRule(); | |
| hostRule.__starts = i; | |
| buffer = ""; | |
| break; | |
| } else if (token.indexOf("@starting-style", i) === i) { | |
| state = "startingStyleRule-begin"; | |
| i += "starting-style".length; | |
| startingStyleRule = new CSSOM.CSSStartingStyleRule(); | |
| startingStyleRule.__starts = i; | |
| buffer = ""; | |
| break; | |
| } else if (token.indexOf("@import", i) === i) { | |
| state = "importRule-begin"; | |
| i += "import".length; | |
| buffer += "@import"; | |
| break; | |
| } else if (token.indexOf("@font-face", i) === i) { | |
| state = "fontFaceRule-begin"; | |
| i += "font-face".length; | |
| fontFaceRule = new CSSOM.CSSFontFaceRule(); | |
| fontFaceRule.__starts = i; | |
| buffer = ""; | |
| break; | |
| } else { | |
| atKeyframesRegExp.lastIndex = i; | |
| var matchKeyframes = atKeyframesRegExp.exec(token); | |
| if (matchKeyframes && matchKeyframes.index === i) { | |
| state = "keyframesRule-begin"; | |
| keyframesRule = new CSSOM.CSSKeyframesRule(); | |
| keyframesRule.__starts = i; | |
| keyframesRule._vendorPrefix = matchKeyframes[1]; // Will come out as undefined if no prefix was found | |
| i += matchKeyframes[0].length - 1; | |
| buffer = ""; | |
| break; | |
| } else if (state === "selector") { | |
| state = "atRule"; | |
| } | |
| } | |
| buffer += character; | |
| break; | |
| case "{": | |
| if (state === "selector" || state === "atRule") { | |
| styleRule.selectorText = buffer.trim(); | |
| styleRule.style.__starts = i; | |
| buffer = ""; | |
| state = "before-name"; | |
| } else if (state === "atBlock") { | |
| mediaRule.media.mediaText = buffer.trim(); | |
| if (parentRule) { | |
| ancestorRules.push(parentRule); | |
| } | |
| currentScope = parentRule = mediaRule; | |
| mediaRule.parentStyleSheet = styleSheet; | |
| buffer = ""; | |
| state = "before-selector"; | |
| } else if (state === "containerBlock") { | |
| containerRule.containerText = buffer.trim(); | |
| if (parentRule) { | |
| ancestorRules.push(parentRule); | |
| } | |
| currentScope = parentRule = containerRule; | |
| containerRule.parentStyleSheet = styleSheet; | |
| buffer = ""; | |
| state = "before-selector"; | |
| } else if (state === "conditionBlock") { | |
| supportsRule.conditionText = buffer.trim(); | |
| if (parentRule) { | |
| ancestorRules.push(parentRule); | |
| } | |
| currentScope = parentRule = supportsRule; | |
| supportsRule.parentStyleSheet = styleSheet; | |
| buffer = ""; | |
| state = "before-selector"; | |
| } else if (state === "hostRule-begin") { | |
| if (parentRule) { | |
| ancestorRules.push(parentRule); | |
| } | |
| currentScope = parentRule = hostRule; | |
| hostRule.parentStyleSheet = styleSheet; | |
| buffer = ""; | |
| state = "before-selector"; | |
| } else if (state === "startingStyleRule-begin") { | |
| if (parentRule) { | |
| ancestorRules.push(parentRule); | |
| } | |
| currentScope = parentRule = startingStyleRule; | |
| startingStyleRule.parentStyleSheet = styleSheet; | |
| buffer = ""; | |
| state = "before-selector"; | |
| } else if (state === "fontFaceRule-begin") { | |
| if (parentRule) { | |
| fontFaceRule.parentRule = parentRule; | |
| } | |
| fontFaceRule.parentStyleSheet = styleSheet; | |
| styleRule = fontFaceRule; | |
| buffer = ""; | |
| state = "before-name"; | |
| } else if (state === "keyframesRule-begin") { | |
| keyframesRule.name = buffer.trim(); | |
| if (parentRule) { | |
| ancestorRules.push(parentRule); | |
| keyframesRule.parentRule = parentRule; | |
| } | |
| keyframesRule.parentStyleSheet = styleSheet; | |
| currentScope = parentRule = keyframesRule; | |
| buffer = ""; | |
| state = "keyframeRule-begin"; | |
| } else if (state === "keyframeRule-begin") { | |
| styleRule = new CSSOM.CSSKeyframeRule(); | |
| styleRule.keyText = buffer.trim(); | |
| styleRule.__starts = i; | |
| buffer = ""; | |
| state = "before-name"; | |
| } else if (state === "documentRule-begin") { | |
| // FIXME: what if this '{' is in the url text of the match function? | |
| documentRule.matcher.matcherText = buffer.trim(); | |
| if (parentRule) { | |
| ancestorRules.push(parentRule); | |
| documentRule.parentRule = parentRule; | |
| } | |
| currentScope = parentRule = documentRule; | |
| documentRule.parentStyleSheet = styleSheet; | |
| buffer = ""; | |
| state = "before-selector"; | |
| } | |
| break; | |
| case ":": | |
| if (state === "name") { | |
| name = buffer.trim(); | |
| buffer = ""; | |
| state = "before-value"; | |
| } else { | |
| buffer += character; | |
| } | |
| break; | |
| case "(": | |
| if (state === 'value') { | |
| // ie css expression mode | |
| if (buffer.trim() === 'expression') { | |
| var info = (new CSSOM.CSSValueExpression(token, i)).parse(); | |
| if (info.error) { | |
| parseError(info.error); | |
| } else { | |
| buffer += info.expression; | |
| i = info.idx; | |
| } | |
| } else { | |
| state = 'value-parenthesis'; | |
| //always ensure this is reset to 1 on transition | |
| //from value to value-parenthesis | |
| valueParenthesisDepth = 1; | |
| buffer += character; | |
| } | |
| } else if (state === 'value-parenthesis') { | |
| valueParenthesisDepth++; | |
| buffer += character; | |
| } else { | |
| buffer += character; | |
| } | |
| break; | |
| case ")": | |
| if (state === 'value-parenthesis') { | |
| valueParenthesisDepth--; | |
| if (valueParenthesisDepth === 0) state = 'value'; | |
| } | |
| 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": | |
| styleRule.style.setProperty(name, buffer.trim(), priority); | |
| priority = ""; | |
| buffer = ""; | |
| state = "before-name"; | |
| break; | |
| case "atRule": | |
| buffer = ""; | |
| state = "before-selector"; | |
| break; | |
| case "importRule": | |
| importRule = new CSSOM.CSSImportRule(); | |
| importRule.parentStyleSheet = importRule.styleSheet.parentStyleSheet = styleSheet; | |
| importRule.cssText = buffer + character; | |
| styleSheet.cssRules.push(importRule); | |
| buffer = ""; | |
| state = "before-selector"; | |
| break; | |
| default: | |
| buffer += character; | |
| break; | |
| } | |
| break; | |
| case "}": | |
| switch (state) { | |
| case "value": | |
| styleRule.style.setProperty(name, buffer.trim(), priority); | |
| priority = ""; | |
| /* falls through */ | |
| case "before-name": | |
| case "name": | |
| styleRule.__ends = i + 1; | |
| if (parentRule) { | |
| styleRule.parentRule = parentRule; | |
| } | |
| styleRule.parentStyleSheet = styleSheet; | |
| currentScope.cssRules.push(styleRule); | |
| buffer = ""; | |
| if (currentScope.constructor === CSSOM.CSSKeyframesRule) { | |
| state = "keyframeRule-begin"; | |
| } else { | |
| state = "before-selector"; | |
| } | |
| break; | |
| case "keyframeRule-begin": | |
| case "before-selector": | |
| case "selector": | |
| // End of media/supports/document rule. | |
| if (!parentRule) { | |
| parseError("Unexpected }"); | |
| } | |
| // Handle rules nested in @media or @supports | |
| hasAncestors = ancestorRules.length > 0; | |
| while (ancestorRules.length > 0) { | |
| parentRule = ancestorRules.pop(); | |
| if ( | |
| parentRule.constructor.name === "CSSMediaRule" | |
| || parentRule.constructor.name === "CSSSupportsRule" | |
| || parentRule.constructor.name === "CSSContainerRule" | |
| || parentRule.constructor.name === "CSSStartingStyleRule" | |
| ) { | |
| prevScope = currentScope; | |
| currentScope = parentRule; | |
| currentScope.cssRules.push(prevScope); | |
| break; | |
| } | |
| if (ancestorRules.length === 0) { | |
| hasAncestors = false; | |
| } | |
| } | |
| if (!hasAncestors) { | |
| currentScope.__ends = i + 1; | |
| styleSheet.cssRules.push(currentScope); | |
| currentScope = styleSheet; | |
| parentRule = null; | |
| } | |
| buffer = ""; | |
| state = "before-selector"; | |
| break; | |
| } | |
| break; | |
| default: | |
| switch (state) { | |
| case "before-selector": | |
| state = "selector"; | |
| styleRule = new CSSOM.CSSStyleRule(); | |
| styleRule.__starts = i; | |
| break; | |
| case "before-name": | |
| state = "name"; | |
| break; | |
| case "before-value": | |
| state = "value"; | |
| break; | |
| case "importRule-begin": | |
| state = "importRule"; | |
| break; | |
| } | |
| buffer += character; | |
| break; | |
| } | |
| } | |
| return styleSheet; | |
| }; | |
| //.CommonJS | |
| exports.parse = CSSOM.parse; | |
| // The following modules cannot be included sooner due to the mutual dependency with parse.js | |
| CSSOM.CSSStyleSheet = require("./CSSStyleSheet").CSSStyleSheet; | |
| CSSOM.CSSStyleRule = require("./CSSStyleRule").CSSStyleRule; | |
| CSSOM.CSSImportRule = require("./CSSImportRule").CSSImportRule; | |
| CSSOM.CSSGroupingRule = require("./CSSGroupingRule").CSSGroupingRule; | |
| CSSOM.CSSMediaRule = require("./CSSMediaRule").CSSMediaRule; | |
| CSSOM.CSSContainerRule = require("./CSSContainerRule").CSSContainerRule; | |
| CSSOM.CSSConditionRule = require("./CSSConditionRule").CSSConditionRule; | |
| CSSOM.CSSSupportsRule = require("./CSSSupportsRule").CSSSupportsRule; | |
| CSSOM.CSSFontFaceRule = require("./CSSFontFaceRule").CSSFontFaceRule; | |
| CSSOM.CSSHostRule = require("./CSSHostRule").CSSHostRule; | |
| CSSOM.CSSStartingStyleRule = require("./CSSStartingStyleRule").CSSStartingStyleRule; | |
| CSSOM.CSSStyleDeclaration = require('./CSSStyleDeclaration').CSSStyleDeclaration; | |
| CSSOM.CSSKeyframeRule = require('./CSSKeyframeRule').CSSKeyframeRule; | |
| CSSOM.CSSKeyframesRule = require('./CSSKeyframesRule').CSSKeyframesRule; | |
| CSSOM.CSSValueExpression = require('./CSSValueExpression').CSSValueExpression; | |
| CSSOM.CSSDocumentRule = require('./CSSDocumentRule').CSSDocumentRule; | |
| ///CommonJS | |