You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							464 lines
						
					
					
						
							12 KiB
						
					
					
				
			
		
		
	
	
							464 lines
						
					
					
						
							12 KiB
						
					
					
				//.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, | 
						|
		"conditionBlock": true, | 
						|
		'documentRule-begin': true | 
						|
	}; | 
						|
 | 
						|
	var styleSheet = new CSSOM.CSSStyleSheet(); | 
						|
 | 
						|
	// @type CSSStyleSheet|CSSMediaRule|CSSSupportsRule|CSSFontFaceRule|CSSKeyframesRule|CSSDocumentRule | 
						|
	var currentScope = styleSheet; | 
						|
 | 
						|
	// @type CSSMediaRule|CSSSupportsRule|CSSKeyframesRule|CSSDocumentRule | 
						|
	var parentRule; | 
						|
 | 
						|
	var ancestorRules = []; | 
						|
	var hasAncestors = false; | 
						|
	var prevScope; | 
						|
 | 
						|
	var name, priority="", styleRule, mediaRule, supportsRule, importRule, fontFaceRule, keyframesRule, documentRule, hostRule; | 
						|
 | 
						|
	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("@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("@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 === "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 === "fontFaceRule-begin") { | 
						|
				if (parentRule) { | 
						|
					ancestorRules.push(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" | 
						|
						) { | 
						|
							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.CSSMediaRule = require("./CSSMediaRule").CSSMediaRule; | 
						|
CSSOM.CSSSupportsRule = require("./CSSSupportsRule").CSSSupportsRule; | 
						|
CSSOM.CSSFontFaceRule = require("./CSSFontFaceRule").CSSFontFaceRule; | 
						|
CSSOM.CSSHostRule = require("./CSSHostRule").CSSHostRule; | 
						|
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
 | 
						|
 |