123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- /**
- * 注册命名空间:baidu.cssAnalytic
- */
- baidu.namespace.register("baidu.cssAnalytic");
- /**
- *
- * css分析器
- * 支持一下css规则:
- * css规则
- * 1、@charset "utf-8"; //设置字符集
- * 2、@import url("a.css"); //import
- * 3、_property:value //ie6
- * 4、*property:value //ie6,7
- * 5、property:value\9; //ie6,7,8,9
- * 6、property//:value //非ie6
- * 7、* html selector{} //各种选择符
- * 8、@media all and (-webkit-min-device-pixel-ratio:10000),not all and (-webkit-min-device-pixel-ratio:0) { ... } //设备
- * 9、@-moz-xxx //firefox
- * 10、property:value !important; //important
- * 11、property:expression(onmouseover=function(){}) //expression,值里有可能有 { 和 }
- * 12、-webkit-border-radious:value //浏览器私有,减号开头
- * 13、filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="ds_laby.png", sizingMethod='crop') //ie下的filter,有(和)
- *
- * @author lichengyin (FCP:PHP代码)
- * @cover zhaoxianlie (FCPHelper:将PHP代码重写为Javascript代码)
- */
- baidu.cssAnalytic = function(){
- /**
- * 当前解析到的位置
- * @var int
- */
- this.parsePos = 0;
-
- this.content = '';
-
- this.contentLength = 0;
-
- this._output = [];
-
- this._pre_type = ''; //上一个特殊类型
-
- this.run = function($content){
- this.content = $content.trim().replace(/\n/g, "\n");
- this.contentLength = this.content.length;
- this.tokenAnalytic();
- return this._output;
- };
- this.tokenAnalytic = function(){
- var $token;
- while (true){
- $token = this.getNextToken();
- if ($token){
- if ($token[1] === baidu.FL.FL_EOF) break;
- this._output.push($token);
- if ($token[1] === baidu.FL.CSS_PROPERTY) {
- this._output.push([':', baidu.FL.CSS_COLON]);
- } else if ($token[1] === baidu.FL.CSS_VALUE) {
- this._output.push([';', baidu.FL.CSS_SEMICOLON]);
- }
- }
- }
- };
- this.getNextToken = function(){
- if (this.parsePos >= this.contentLength){
- return ['', baidu.FL.FL_EOF];
- }
- $char = this.content[this.parsePos];
- this.parsePos++;
-
- if ($char === "\x0d") return ''; //\r
- if ($char === "\x0a") return [$char, baidu.FL.FL_NEW_LINE];
- //避免出现多个空格在一起的情况
- if ($char.trim() === '' || $char === ';') return '';
-
- var $result ;
-
- //处理@开头的;如:@charset "utf-8";@import url("a.css"), @media xxx{}
- if ($char === '@'){
- $result = this._getAtToken($char);
- if ($result) return $result;
- }else if ($char === '{'){
- switch (this._pre_type){
- case baidu.FL.CSS_DEVICE_DESC :
- this._pre_type = baidu.FL.CSS_DEVICE_START;
- return [$char, baidu.FL.CSS_DEVICE_START];
- default :
- this._pre_type = baidu.FL.CSS_SELECTOER_START;
- return [$char, baidu.FL.CSS_SELECTOER_START];
- }
- }else if ($char === '}'){
- switch (this._pre_type){
- case baidu.FL.CSS_SELECTOER_END:
- this._pre_type = baidu.FL.CSS_DEVICE_END;
- return [$char, baidu.FL.CSS_DEVICE_END];
- default:
- for(var $i=this._output.length-1;$i>=0;$i--){
- var $item = this._output[$i];
- if($item[1] === baidu.FL.CSS_SELECTOER_START){
- this._pre_type = baidu.FL.CSS_SELECTOER_END;
- return [$char, baidu.FL.CSS_SELECTOER_END];
- }else if($item[1] === baidu.FL.CSS_DEVICE_START){
- this._pre_type = baidu.FL.CSS_DEVICE_END;
- return [$char, baidu.FL.CSS_DEVICE_END];
- }
- }
- this._pre_type = baidu.FL.CSS_SELECTOER_END;
- return [$char, baidu.FL.CSS_SELECTOER_END];
- }
- }else if (this.content.substr( this.parsePos - 1, 2) === '/*'){
- $result = this._getCommentToken($char);
- if ($result) return $result;
- }else if ($char === "\x0d" || $char === "\x0a"){
- return [$char, baidu.FL.FL_NEW_LINE];
- }
- switch (this._pre_type){
- case baidu.FL.CSS_SELECTOER_START :
- case baidu.FL.CSS_VALUE :
- $result = this._getPropertyToken($char);
- this._pre_type = baidu.FL.CSS_PROPERTY;
- return $result;
- case baidu.FL.CSS_PROPERTY :
- $result = this._getValueToken($char);
- this._pre_type = baidu.FL.CSS_VALUE;
- return $result;
- case baidu.FL.CSS_DEVICE_START:
- var $pos = this.parsePos;
- $result = this._getPropertyToken($char);
- var $str = $result[0];
- if($str.indexOf('{') > -1){
- this.parsePos = $pos;
- $result = this._getSelectorToken($char);
- this._pre_type = baidu.FL.CSS_DEVICE_START;
- if ($result) return $result;
- }else{
- this._pre_type = baidu.FL.CSS_PROPERTY;
- return $result;
- }
- default:
- $result = this._getSelectorToken($char);
- if ($result) return $result;
-
- }
- return [$char, baidu.FL.CSS_NORMAL];
- };
-
- /**
- * 处理@开头的;如:@charset "utf-8";@import url("a.css"), @media xxx{}
- * @param {Object} $char
- */
- this._getAtToken = function($char){
- $resultString = $char;
- while (this.content[this.parsePos] !== ';'
- && this.content[this.parsePos] !== '{'
- && this.parsePos < this.contentLength){
-
- $resultString += this.content[this.parsePos];
- this.parsePos++;
- }
- if (this.content[this.parsePos] === ';'){
- $resultString += ';';
- this.parsePos++;
- return [$resultString.trim(), baidu.FL.CSS_AT];
- }
- this._pre_type = baidu.FL.CSS_DEVICE_DESC;
- return [$resultString.trim(), baidu.FL.CSS_DEVICE_DESC];
- };
- /**
- * comment
- * @param {Object} $char
- * @param {Object} $fromSelector=false
- */
- this._getCommentToken = function($char, $fromSelector){
- this.parsePos++;
- $resultString = '';
- while (!(this.content[this.parsePos] === '*'
- && this.content[this.parsePos + 1]
- && this.content[this.parsePos + 1] === '/')
- && this.parsePos < this.contentLength){
-
- $resultString += this.content[this.parsePos];
- this.parsePos++;
- }
- this.parsePos += 2;
- if ($fromSelector){
- return '/*' + $resultString + '*/';
- }
- return ['/*' + $resultString + '*/' , baidu.FL.CSS_COMMENT];
- };
-
- /**
- * selector content
- * 选择符里可能还有注释,注释里可能含有{}等字符
- */
- this._getSelectorToken = function($char){
- var $resultString = $char;
- while (this.content[this.parsePos] !== '{'
- && this.content[this.parsePos] !== '}'
- && this.parsePos < this.contentLength){
- //如果选择符中含有注释
- if (this.content[this.parsePos] === '/' &&
- this.content[this.parsePos+1] &&
- this.content[this.parsePos+1] === '*'){
- $resultString += this._getCommentToken('/', true);
- }else{
- $resultString += this.content[this.parsePos];
- this.parsePos++;
- }
- }
- return [$resultString.trim(), baidu.FL.CSS_SELECTOER];
- };
-
- /**
- * css property
- * @param {Object} $char
- */
- this._getPropertyToken = function($char){
- $resultString = $char;
- while (this.content[this.parsePos] !== ':' &&
- this.content[this.parsePos] !== ';' &&
- this.content[this.parsePos] !== '}' &&
- this.parsePos < this.contentLength){
- $resultString += this.content[this.parsePos];
- this.parsePos++;
- }
- //增加对div{color}的容错机制
- if (this.content[this.parsePos] !== '}'){
- this.parsePos++;
- }
- return [$resultString.trim().toLowerCase(), baidu.FL.CSS_PROPERTY];
- };
-
- /**
- * css value
- * @param {Object} $char
- */
- this._getValueToken = function($char){
- var $resultString = $char;
- var $isExpression = false;
- while (this.content[this.parsePos] !== ';'
- && this.content[this.parsePos] !== '}'
- && this.parsePos < this.contentLength){
-
- $char = this.content[this.parsePos];
- this.parsePos++;
- $resultString += $char;
- if (!$isExpression && $resultString.toLowerCase() === 'expression('){
- $isExpression = true;
- $resultString += this._getJSToken();
- }
- }
- if (this.content[this.parsePos] === ';'){
- this.parsePos++;
- }
- //将多个空格变成一个空格
- $resultString = $resultString.trim().replace(/\s+/ig, " ");
- return [$resultString, baidu.FL.CSS_VALUE];
- };
-
- /**
- * 处理expression里的javascript
- */
- this._getJSToken = function(){
- var $string = '',$char;
- while (this.parsePos < this.contentLength){
- $char = this.content[this.parsePos];
- this.parsePos++;
- $string += $char;
- //这里使用js分析器,然后判断(和) 个数是否相等
- if ($char === ')' && this._checkJSToken('(' + $string)){
- break;
- }
- }
- return $string;
- };
-
- /**
- * check js for expression
- * @param array $output
- */
- this._checkJSToken = function($output){
- var $expr_start = 0;
- var $expr_end = 0;
- for (var $i=0,$count=$output.length;$i<$count;$i++){
- var $item = $output[$i];
- if ($item[0] === '(') $expr_start++;
- else if ($item[0] === ')') $expr_end++;
- }
- return $expr_start === $expr_end;
- };
- };
|