public function test3() { $this->getFlInstance(); $tokens = $this->getTokens('3.text'); $tokens = $tokens[0]; $score = Fl_Css_Static::getSelectorSpecificity($tokens); //print_r($score); }
/** * * 获取选择器的属性 */ public function getSelectorProperties() { $attr = $value = ''; $attrs = array(); $hasColon = false; $hasTpl = false; while (true) { $token = $this->tokenInstance->getNextToken(); if (empty($token)) { break; } if ($token['type'] === FL_TOKEN_CSS_PROPERTY) { $attr = $token['value']; } elseif ($token['type'] === FL_TOKEN_CSS_COLON) { $hasColon = true; } elseif ($token['type'] === FL_TOKEN_CSS_VALUE) { $value = $token['value']; } elseif ($token['type'] === FL_TOKEN_TPL) { if ($hasColon) { $value .= $token['value']; } else { $attr .= $token['value']; } $hasTpl = true; } elseif ($token['type'] === FL_TOKEN_CSS_HACK) { $attrs[] = array('property' => '', 'value' => $token['value'], 'type' => FL_TOKEN_CSS_HACK); } elseif ($token['type'] === FL_TOKEN_CSS_SEMICOLON || $token['type'] === FL_TOKEN_CSS_BRACES_ONE_END) { if ($hasTpl || $this->containTpl($attr)) { $attrs[] = array('property' => $attr, 'value' => $value, 'type' => FL_TOKEN_TPL); } else { if (!empty($attr) || !empty($value)) { $propertyDetail = Fl_Css_Static::getPropertyDetail($attr); $valueDetail = Fl_Css_Static::getValueDetail($value); $detail = $propertyDetail + $valueDetail; $attrs[] = $detail; } } $hasTpl = $hasColon = false; $attr = $value = ''; } if ($token['type'] === FL_TOKEN_CSS_BRACES_ONE_END) { break; } } return $attrs; }
/** * * beautify * @param array $ast */ public function beautifyAst($ast, $parentType = '') { $result = ''; $first = true; foreach ($ast as $item) { if (!$first) { $result = rtrim($result, FL_NEWLINE) . FL_NEWLINE; } $hasComment = false; if (count($item['value']['commentBefore'])) { $hasComment = true; } $comment = $this->beautifyComment($item['value']); if ($comment['remove']) { $result = rtrim($result, FL_NEWLINE); } $result .= $comment['value']; // if ($item['type'] === FL_TOKEN_HTML_TAG_END) { continue; } if ($first) { $first = false; } $indent = $newline = false; if ($item['type'] === FL_TOKEN_HTML_TAG) { $count = count($item['children']); if ($count > 1) { $indent = true; $newline = true; } elseif ($count === 1) { $c = $item['children'][$count - 1]; if ($c['type'] !== FL_TOKEN_HTML_TEXT) { $indent = true; $newline = true; } } } else { if (count($ast) > 1) { $newline = true; } if ($item['type'] === FL_TOKEN_HTML_DOCTYPE || $item['type'] === FL_TOKEN_HTML_SINGLE_TAG) { $newline = true; } if ($item['type'] === FL_TOKEN_HTML_STYLE_TAG || $item['type'] === FL_TOKEN_HTML_SCRIPT_TAG) { $newline = true; $indent = true; } } if ($item['type'] !== FL_TOKEN_HTML_TEXT) { $result .= $this->getIndentString(); } else { if (count($ast) > 1) { $result .= $this->getIndentString(); } } if ($parentType === FL_TOKEN_HTML_STYLE_TAG) { Fl::loadClass("Fl_Css_Static"); $value = Fl_Css_Static::getStyleDetail($item['value']['value']); if ($value['prefix']) { $result .= $value['prefix'] . FL_NEWLINE; } $result .= $this->beautify_special($value['value'], 'css'); if ($value['suffix']) { $result .= FL_NEWLINE . $value['suffix'] . FL_NEWLINE; } } elseif ($parentType === FL_TOKEN_HTML_SCRIPT_TAG) { $result .= $this->beautify_special($item['value']['value'], 'js'); } else { $result .= $item['value']['value']; } if ($newline) { $result .= FL_NEWLINE; } if ($indent) { $this->indent++; } if (count($item['children'])) { $type = $item['type']; if ($type === FL_TOKEN_HTML_SCRIPT_TAG) { $tagInfo = Fl_Html_Static::getScriptTagInfo($item['value']['value'], $this); //虽然是script标签,但不一定是Js if (!$tagInfo['script'] || $tagInfo['external']) { $type = ''; } } $children = $this->beautifyAst($item['children'], $type); if ($tagInfo['external'] && !strlen(trim($children))) { $result = rtrim($result, FL_NEWLINE); $newline = false; $indent = 2; } else { $result .= $children; } } $types = array(FL_TOKEN_HTML_TAG => 1, FL_TOKEN_HTML_SCRIPT_TAG => 1, FL_TOKEN_HTML_PRE_TAG => 1, FL_TOKEN_HTML_STYLE_TAG => 1, FL_TOKEN_HTML_TEXTAREA_TAG => 1); $this->preToken = $item['value']; if (isset($types[$item['type']])) { if ($newline) { $result = rtrim($result, FL_NEWLINE); $result .= FL_NEWLINE; } if ($indent) { $this->indent--; if ($indent === true) { $result .= $this->getIndentString(); } } if (!empty($item['end'])) { $this->preToken = $item['end']; $comment = $this->beautifyComment($item['end']); $result .= rtrim($comment['value'], FL_NEWLINE); } $result .= '</' . $item['tag'] . '>'; } } return $result; }
/** * * 获取@的详细类型 */ public function getAtDetailType($result = '') { return $this->preTokenType = Fl_Css_Static::getAtDetailType($result, $this); }
/** * * get such as :hover token * @param string $char */ public function getPseudoClassToken($char) { $result = $char; $this->getNextChar(); $parenthesesNum = 0; while (!$this->isEof()) { $char = $this->getCurrentChar(); if ($parenthesesNum === 0 && Fl_Css_Static::isSelectorCharUtil($char)) { break; } else { if ($char === '(') { $parenthesesNum++; } else { if ($char === ')') { $parenthesesNum--; } else { if ($char === '"' || $char === "'") { $char = $this->getQuoteText($char, true, true); } } } } $result .= $char; if (!$this->pendingNextChar) { $this->getNextChar(); } else { $this->pendingNextChar = false; } } if ($parenthesesNum !== 0) { $this->throwException('get Pseudo Class error'); } return $result; }
/** * * short padding,margin properties * @param array $attrs */ public function shortProperties($attrs = array()) { $attrs = Fl_Css_Static::combineProperty($attrs, 'padding', Fl_Css_Static::$paddingChildren); $attrs = Fl_Css_Static::combineProperty($attrs, 'margin', Fl_Css_Static::$marginChildren); return $attrs; }
/** * * Calculating a selector's specificity * see more: http://www.w3.org/TR/selectors/#specificity * @param array $selectorTokens */ public static function getSelectorSpecificity($selectorTokens = array()) { if (!is_array($selectorTokens)) { $selectorTokens = self::getSelectorTokens($selectorTokens); } $score = array(0, 0, 0); $notPattern = '/^\\:not\\(/ies'; foreach ($selectorTokens as $item) { $type = $item['type']; switch ($type) { case FL_TOKEN_CSS_SELECTOR_ID: $score[0]++; break; case FL_TOKEN_CSS_SELECTOR_TYPE: case FL_TOKEN_CSS_SELECTOR_PSEUDO_ELEMENT: $score[2]++; break; case FL_TOKEN_CSS_SELECTOR_CLASS: case FL_TOKEN_CSS_SELECTOR_ATTRIBUTES: $score[1]++; break; case FL_TOKEN_CSS_SELECTOR_PSEUDO_CLASS: $value = $item['value']; //:not(xxx) if (preg_match($notPattern, $value)) { $value = trim(preg_replace($notPattern, "", $value)); $value = substr($value, 0, strlen($value) - 1); Fl::loadClass('Fl_Css_SelectorToken'); $instance = new Fl_Css_SelectorToken($value); $tokens = $instance->run(); $notScore = Fl_Css_Static::getSelectorSpecificity($tokens[0]); $score[0] += $notScore[0]; $score[1] += $notScore[1]; $score[2] += $notScore[2]; } else { $score[1]++; } break; } } return $score; }
/** * * 背景图 * @param array $tokens */ public function updateBackgroundImageTokenType($tokens) { foreach ($tokens as &$token) { $value = $token['value']; $urlValue = Fl_Css_Static::isUrlValue($value); if ($urlValue) { //背景图 $token['type'] = 'background-image'; $token['clean_value'] = $urlValue; } } return $tokens; }
/** * * token值里可能含有color * @param array $token */ public static function mayHasColor($token) { if ($token['type'] != FL_TOKEN_CSS_PROPERTY) { return false; } $value = $token['value']; $detail = Fl_Css_Static::getPropertyDetail($value); $name = strtolower($detail['property']); if (isset(Fl_Css_Static::$mayHasColorProperties[$name])) { return true; } return false; }
/** * * compress style * @param array $token */ public function compressStyle($token) { if (!$this->options['compress_tag']) { return $token['value']; } $info = Fl_Html_Static::splitSpecialValue($token['value'], 'style', $this); $content = trim($info['content']); if ($this->options['remove_empty_style'] && !$content) { return ''; } if ($this->options['compress_inline_css'] && $content) { Fl::loadClass("Fl_Css_Static"); $value = Fl_Css_Static::getStyleDetail($content); $containTpl = $this->containTpl($value['value']); //自定义内联CSS压缩方法 if (!$containTpl && $this->cssCompressMethod) { $content = call_user_func($this->cssCompressMethod, $value['value'], $this); } else { $content = $this->getInstance("Fl_Css_Compress", $value['value'])->run(); } } if ($this->options['remove_optional_attrs']) { $tagInfo = $this->getInstance("Fl_Html_TagToken", $info['tag_start'])->run(); $tagInfo['lowerTag'] = strtolower($tagInfo['tag']); $info['tag_start'] = $this->compressStartTag($tagInfo); } if ($this->options['merge_adjacent_css']) { $endStyle = '</style>'; $outputLen = strlen($this->output); $last = substr($this->output, $outputLen - 8); if (strtolower($last) === $endStyle) { $this->output = substr($this->output, 0, $outputLen - 8); return $content . $info['tag_end']; } } return $info['tag_start'] . $content . $info['tag_end']; }
/** * * validate css property * @param array $token */ public function validateProperty($token) { if (!$this->options['property_hack']) { return true; } if (!Fl_Css_Static::checkPropertyPattern($token['value'])) { return $this->addMessage("property `" . $token['value'] . "` is not valid", 'property_hack', $token); } if (strpos($token['value'], 'filter') !== false) { return $this->addMessage("property `" . $token['value'] . "` is not valid", 'filter', $token); } }
/** * * beautify default token * @param array $token */ public function beautifyDefault($token) { //for ;;; if ($token['type'] === FL_TOKEN_CSS_SEMICOLON && $this->preToken['type'] === FL_TOKEN_CSS_SEMICOLON) { return ''; } if (isset($this->preToken['type'])) { //for @ type if ($token['type'] === FL_TOKEN_CSS_AT_KEYFRAMES || $token['type'] === FL_TOKEN_CSS_AT_MOZILLA) { return FL_NEWLINE . $this->getIndentString() . $token['value']; } else { if (Fl_Css_Static::isAtType($token['type'])) { return FL_NEWLINE . $token['value']; } } } if ($token['type'] === FL_TOKEN_CSS_HACK) { return FL_NEWLINE . $this->getIndentString() . $token['value']; } return $token['value']; }