Ejemplo n.º 1
0
 function add_rule(&$rule, &$pipeline)
 {
     $rule_obj = new CSSRule($rule, $pipeline);
     $this->rules[] = $rule_obj;
     $tag = $this->detect_applicable_tag($rule_obj->get_selector());
     if ($tag === null) {
         $tag = "*";
     }
     $this->tag_filtered[$tag][] = $rule_obj;
 }
function parse_style_attr($root, &$state, &$pipeline)
{
    $style = $root->get_attribute("style");
    // Some "designers" (obviously lacking the brain and ability to read ) use such constructs:
    //
    // <input maxLength=256 size=45 name=searchfor value="" style="{width:350px}">
    //
    // It is out of standard, as HTML 4.01 says:
    //
    // The syntax of the value of the style attribute is determined by the default style sheet language.
    // For example, for [[CSS2]] inline style, use the declaration block syntax described in section 4.1.8
    // *(without curly brace delimiters)*
    //
    // but still parsed by many browsers; let's be compatible with these idiots - remove curly braces
    //
    $style = preg_replace("/^\\s*{/", "", $style);
    $style = preg_replace("/}\\s*\$/", "", $style);
    $properties = parse_css_properties($style, $pipeline);
    $rule = new CSSRule(array(array(SELECTOR_ANY), $properties, $pipeline->get_base_url(), $root), $pipeline);
    $rule->apply($root, $state, $pipeline);
}
Ejemplo n.º 3
0
 private function parseRule()
 {
     $oRule = new CSSRule($this->parseIdentifier());
     $this->consumeWhiteSpace();
     $this->consume(':');
     $oValue = $this->parseValue(self::listDelimiterForRule($oRule->getRule()));
     $oRule->setValue($oValue);
     if ($this->comes('!')) {
         $this->consume('!');
         $this->consumeWhiteSpace();
         $sImportantMarker = $this->consume(strlen('important'));
         if (mb_convert_case($sImportantMarker, MB_CASE_LOWER) !== 'important') {
             throw new Exception("! was followed by “" . $sImportantMarker . "”. Expected “important”");
         }
         $oRule->setIsImportant(true);
     }
     if ($this->comes(';')) {
         $this->consume(';');
     }
     return $oRule;
 }
Ejemplo n.º 4
0
 public function addRule(CSSRule $oRule)
 {
     $this->aRules[$oRule->getRule()] = $oRule;
 }
Ejemplo n.º 5
0
 /**
  * Looks for long format CSS font properties (e.g. <tt>font-weight</tt>) and 
  * tries to convert them into a shorthand CSS <tt>font</tt> property. 
  * At least font-size AND font-family must be present in order to create a shorthand declaration.
  **/
 public function createFontShorthand()
 {
     $aFontProperties = array('font-style', 'font-variant', 'font-weight', 'font-size', 'line-height', 'font-family');
     $aRules = $this->getRules();
     if (!isset($aRules['font-size']) || !isset($aRules['font-family'])) {
         return;
     }
     $oNewRule = new CSSRule('font');
     foreach (array('font-style', 'font-variant', 'font-weight') as $sProperty) {
         if (isset($aRules[$sProperty])) {
             $oRule = $aRules[$sProperty];
             $mRuleValue = $oRule->getValue();
             $aValues = array();
             if (!$mRuleValue instanceof CSSRuleValueList) {
                 $aValues[] = $mRuleValue;
             } else {
                 $aValues = $mRuleValue->getListComponents();
             }
             if ($aValues[0] !== 'normal') {
                 $oNewRule->addValue($aValues[0]);
             }
         }
     }
     // Get the font-size value
     $oRule = $aRules['font-size'];
     $mRuleValue = $oRule->getValue();
     $aFSValues = array();
     if (!$mRuleValue instanceof CSSRuleValueList) {
         $aFSValues[] = $mRuleValue;
     } else {
         $aFSValues = $mRuleValue->getListComponents();
     }
     // But wait to know if we have line-height to add it
     if (isset($aRules['line-height'])) {
         $oRule = $aRules['line-height'];
         $mRuleValue = $oRule->getValue();
         $aLHValues = array();
         if (!$mRuleValue instanceof CSSRuleValueList) {
             $aLHValues[] = $mRuleValue;
         } else {
             $aLHValues = $mRuleValue->getListComponents();
         }
         if ($aLHValues[0] !== 'normal') {
             $val = new CSSRuleValueList('/');
             $val->addListComponent($aFSValues[0]);
             $val->addListComponent($aLHValues[0]);
             $oNewRule->addValue($val);
         }
     } else {
         $oNewRule->addValue($aFSValues[0]);
     }
     $oRule = $aRules['font-family'];
     $mRuleValue = $oRule->getValue();
     $aFFValues = array();
     if (!$mRuleValue instanceof CSSRuleValueList) {
         $aFFValues[] = $mRuleValue;
     } else {
         $aFFValues = $mRuleValue->getListComponents();
     }
     $oFFValue = new CSSRuleValueList(',');
     $oFFValue->setListComponents($aFFValues);
     $oNewRule->addValue($oFFValue);
     $this->addRule($oNewRule);
     foreach ($aFontProperties as $sProperty) {
         $this->removeRule($sProperty);
     }
 }
Ejemplo n.º 6
0
 /**
  * Merge multiple CSS RuleSets by cascading according to the CSS 2.1 cascading rules 
  * (http://www.w3.org/TR/REC-CSS2/cascade.html#cascading-order).
  * 
  * @param array $aDeclarations An array of CSSDeclarationBlock objects.
  *
  * @return CSSDeclarationBlock.
  * 
  * ==== Cascading
  * If a CSSDeclarationBlock object has its +specificity+ defined, that specificity is 
  * used in the cascade calculations.  
  * 
  * If no specificity is explicitly set and the CSSDeclarationBlock has *one* selector, 
  * the specificity is calculated using that selector.
  * 
  * If no selectors or multiple selectors are present, the specificity is 
  * treated as 0.
  * 
  * ==== Example #1
  * <code>
  *   $oDecl_1 = new CSSDeclarationBlock();
  *   $oRule_1 = new CSSRule('color');
  *   $oRule_1->addValue(new CSSColor('#F00'));
  *   $oDecl_1->addRule($oRule_1);
  *   $oDecl_2 = new CSSDeclarationBlock();
  *   $oRule_2 = new CSSRule('margin');
  *   $oRule_2->addValue(
  *     new CSSSize(0, 'px')
  *   );
  *   $oDecl_2->addRule($oRule_2);
  * 
  *   $oMerged = CSSDocument::mergeDeclarations($oDecl_1, $oDecl_2);
  * 
  *   echo $oMerged;
  *   //=> "{ margin: 0px; color: rgb(255,0,0); }"
  * </code>
  * ==== Example #2
  * <code>
  *   $oDecl_1 = new CSSDeclarationBlock();
  *   $oRule_1 = new CSSRule('background-color');
  *   $oRule_1->addValue(new CSSColor('black'));
  *   $oDecl_1->addRule($oRule_1);
  *   $oDecl_2 = new CSSDeclarationBlock();
  *   $oRule_2 = new CSSRule('background-image');
  *   $oRule_2->addValue('none');
  *   $oDecl_2->addRule($oRule_2);
  * 
  *   $oMerged = CSSDocument::mergeDeclarations($oDecl_1, $oDecl_2);
  * 
  *   echo $oMerged;
  *   //=> "{ background: none rgb(0,0,0); }"
  * </code>
  **/
 static function mergeDeclarations(array $aDeclarations)
 {
     // Internal storage of CSS properties that we will keep
     $aProperties = array();
     foreach ($aDeclarations as $oDeclaration) {
         $oDeclaration->expandShorthands();
         $aSelectors = $oDeclaration->getSelectors();
         $iSpecificity = 0;
         if (count($aSelectors) == 1) {
             $iSpecificity = $aSelectors[0]->getSpecificity();
         }
         foreach ($oDeclaration->getRules() as $sProperty => $oRule) {
             // Add the property to the list to be folded per
             // http://www.w3.org/TR/CSS21/cascade.html#cascading-order
             if (!isset($aProperties[$sProperty])) {
                 $aProperties[$sProperty] = array('values' => $oRule->getValues(), 'specificity' => $iSpecificity, 'important' => $oRule->getIsImportant());
             } else {
                 $aProperty = $aProperties[$sProperty];
                 if ($aProperty['specificity'] <= $iSpecificity && !$aProperty['important']) {
                     $aProperties[$sProperty] = array('values' => $oRule->getValues(), 'specificity' => $iSpecificity, 'important' => $oRule->getIsImportant());
                 }
             }
             if ($oRule->getIsImportant()) {
                 $aProperties[$sProperty] = array('values' => $oRule->getValues(), 'specificity' => $iSpecificity, 'important' => $oRule->getIsImportant());
             }
         }
         // end foreach rules
     }
     // end foreach rulesets
     $oMerged = new CSSDeclarationBlock();
     foreach ($aProperties as $sProperty => $aDetails) {
         $oNewRule = new CSSRule($sProperty);
         foreach ($aDetails['values'] as $aValue) {
             $oNewRule->addvalue($aValue);
         }
         if ($aDetails['important']) {
             $oNewRule->setIsImportant(true);
         }
         $oMerged->addRule($oNewRule);
     }
     $oMerged->createShorthands();
     return $oMerged;
 }