You are here

class SassPropertyNode in Sassy 7

Same name and namespace in other branches
  1. 7.3 phpsass/tree/SassPropertyNode.php \SassPropertyNode

SassPropertyNode class. Represents a CSS property. @package PHamlP @subpackage Sass.tree

Hierarchy

Expanded class hierarchy of SassPropertyNode

File

phamlp/sass/tree/SassPropertyNode.php, line 18

View source
class SassPropertyNode extends SassNode {
  const MATCH_PROPERTY_NEW = '/^([^\\s=:"]+)\\s*(?:(= )|:)(.*?)$/';
  const MATCH_PROPERTY_OLD = '/^:([^\\s=:]+)(?:\\s*(=)\\s*|\\s+|$)(.*)/';
  const MATCH_PSUEDO_SELECTOR = '/^:?\\w[-\\w]+\\(?/i';
  const MATCH_INTERPOLATION = '/^#\\{(.*?)\\}/i';
  const NAME = 1;
  const SCRIPT = 2;
  const VALUE = 3;
  const IS_SCRIPT = '= ';
  private static $psuedoSelectors = array(
    'root',
    'nth-child(',
    'nth-last-child(',
    'nth-of-type(',
    'nth-last-of-type(',
    'first-child',
    'last-child',
    'first-of-type',
    'last-of-type',
    'only-child',
    'only-of-type',
    'empty',
    'link',
    'visited',
    'active',
    'hover',
    'focus',
    'target',
    'lang(',
    'enabled',
    'disabled',
    'checked',
    ':first-line',
    ':first-letter',
    ':before',
    ':after',
    // CSS 2.1
    'first-line',
    'first-letter',
    'before',
    'after',
  );

  /**
   * @var string property name
   */
  private $name;

  /**
   * @var string property value or expression to evaluate
   */
  private $value;

  /**
   * SassPropertyNode constructor.
   * @param object source token
   * @param string property syntax
   * @return SassPropertyNode
   */
  public function __construct($token, $syntax = 'new') {
    parent::__construct($token);
    $matches = self::match($token, $syntax);
    $this->name = $matches[self::NAME];
    $this->value = $matches[self::VALUE];
    if ($matches[self::SCRIPT] === self::IS_SCRIPT) {
      $this
        ->addWarning('Setting CSS properties with "=" is deprecated; use "{name}: {value};"', array(
        '{name}' => $this->name,
        '{value}' => $this->value,
      ));
    }
  }

  /**
   * Parse this node.
   * If the node is a property namespace return all parsed child nodes. If not
   * return the parsed version of this node.
   * @param SassContext the context in which this node is parsed
   * @return array the parsed node
   */
  public function parse($context) {
    $return = array();
    if ($this->value !== "") {
      $node = clone $this;
      $node->name = ($this
        ->inNamespace() ? "{$this->namespace}-" : '') . $this
        ->interpolate($this->name, $context);
      $node->value = $this
        ->evaluate($this
        ->interpolate($this->value, $context), $context, SassScriptParser::CSS_PROPERTY)
        ->toString();
      if (array_key_exists($node->name, $this->vendor_properties)) {
        foreach ($this->vendor_properties[$node->name] as $vendorProperty) {
          $_node = clone $node;
          $_node->name = $vendorProperty;
          $return[] = $_node;
        }
      }
      $return[] = $node;
    }
    if ($this->children) {
      $return = array_merge($return, $this
        ->parseChildren($context));
    }
    return $return;
  }

  /**
   * Render this node.
   * @return string the rendered node
   */
  public function render() {
    return $this->renderer
      ->renderProperty($this);
  }

  /**
   * Returns a value indicating if this node is in a namespace
   * @return boolean true if this node is in a property namespace, false if not
   */
  public function inNamespace() {
    $parent = $this->parent;
    do {
      if ($parent instanceof SassPropertyNode) {
        return true;
      }
      $parent = $parent->parent;
    } while (is_object($parent));
    return false;
  }

  /**
   * Returns the namespace for this node
   * @return string the namespace for this node
   */
  protected function getNamespace() {
    $namespace = array();
    $parent = $this->parent;
    do {
      if ($parent instanceof SassPropertyNode) {
        $namespace[] = $parent->name;
      }
      $parent = $parent->parent;
    } while (is_object($parent));
    return join('-', array_reverse($namespace));
  }

  /**
   * Returns the name of this property.
   * If the property is in a namespace the namespace is prepended
   * @return string the name of this property
   */
  public function getName() {
    return $this->name;
  }

  /**
   * Returns the parsed value of this property.
   * @return string the parsed value of this property
   */
  public function getValue() {
    return $this->value;
  }

  /**
   * Returns a value indicating if the token represents this type of node.
   * @param object token
   * @param string the property syntax being used
   * @return boolean true if the token represents this type of node, false if not
   */
  public static function isa($token) {
    if (!is_array($token)) {
      $syntax = 'old';
    }
    else {
      $syntax = $token['syntax'];
      $token = $token['token'];
    }
    $matches = self::match($token, $syntax);
    if (!empty($matches)) {
      if (isset($matches[self::VALUE]) && self::isPseudoSelector($matches[self::VALUE])) {
        return false;
      }
      if ($token->level === 0) {
        throw new SassPropertyNodeException('Properties can not be assigned at root level', array(), null);
      }
      else {
        return true;
      }
    }
    else {
      return false;
    }
  }

  /**
   * Returns the matches for this type of node.
   * @param array the line to match
   * @param string the property syntax being used
   * @return array matches
   */
  public static function match($token, $syntax) {
    switch ($syntax) {
      case 'new':
        preg_match(self::MATCH_PROPERTY_NEW, $token->source, $matches);
        break;
      case 'old':
        preg_match(self::MATCH_PROPERTY_OLD, $token->source, $matches);
        break;
      default:
        if (preg_match(self::MATCH_PROPERTY_NEW, $token->source, $matches) == 0) {
          preg_match(self::MATCH_PROPERTY_OLD, $token->source, $matches);
        }
        break;
    }
    return $matches;
  }

  /**
   * Returns a value indicating if the string starts with a pseudo selector.
   * This is used to reject pseudo selectors as property values as, for example,
   * "a:hover" and "text-decoration:underline" look the same to the property
   * match regex.
   * It will also match interpolation to allow for constructs such as
   * content:#{$pos}
   * @see isa()
   * @param string the string to test
   * @return bool true if the string starts with a pseudo selector, false if not
   */
  private static function isPseudoSelector($string) {
    preg_match(self::MATCH_PSUEDO_SELECTOR, $string, $matches);
    return isset($matches[0]) && in_array($matches[0], self::$psuedoSelectors) || preg_match(self::MATCH_INTERPOLATION, $string);
  }

}

Members

Namesort descending Modifiers Type Description Overrides
SassNode::$children protected property *
SassNode::$parent protected property *
SassNode::$root protected property *
SassNode::$token protected property *
SassNode::addChild public function * Adds a child to this node. *
SassNode::addWarning public function * Adds a warning to the node. *
SassNode::evaluate protected function * Evaluates a SassScript expression. *
SassNode::getChildren public function * Returns the node's children *
SassNode::getDebug_info private function * Returns the debug_info option setting for this node *
SassNode::getFilename private function * Returns the filename for this node *
SassNode::getLastChild public function * Returns the last child node of this node. *
SassNode::getLevel private function * Returns the level of this node. *
SassNode::getLine private function * Returns the line number for this node *
SassNode::getLine_numbers private function * Returns the line_numbers option setting for this node *
SassNode::getParent public function * Returns the node's parent *
SassNode::getParser public function * Returns the Sass parser. *
SassNode::getPropertySyntax public function * Returns the property syntax being used. *
SassNode::getRenderer public function * Returns the renderer. *
SassNode::getScript public function * Returns the SassScript parser. *
SassNode::getSource private function * Returns the source for this node *
SassNode::getStyle public function * Returns the render style of the document tree. *
SassNode::getVendor_properties private function * Returns vendor specific properties *
SassNode::hasChildren public function * Returns a value indicating if this node has children *
SassNode::hasParent public function * Return a value indicating if this node has a parent *
SassNode::inDirective public function * Returns a value indicating whether this node is in a directive *
SassNode::inSassScriptDirective public function * Returns a value indicating whether this node is in a SassScript directive *
SassNode::interpolate protected function * Replace interpolated SassScript contained in '#{}' with the parsed value. *
SassNode::isChildOf public function * Returns a value indicating if this node is a child of the passed node. * This just checks the levels of the nodes. If this node is at a greater * level than the passed node if is a child of it. *
SassNode::parseChildren protected function * Parse the children of the node. *
SassNode::__clone public function * Resets children when cloned *
SassNode::__get public function * Getter. *
SassNode::__set public function * Setter. *
SassPropertyNode::$name private property *
SassPropertyNode::$psuedoSelectors private static property
SassPropertyNode::$value private property *
SassPropertyNode::getName public function * Returns the name of this property. * If the property is in a namespace the namespace is prepended *
SassPropertyNode::getNamespace protected function * Returns the namespace for this node *
SassPropertyNode::getValue public function * Returns the parsed value of this property. *
SassPropertyNode::inNamespace public function * Returns a value indicating if this node is in a namespace *
SassPropertyNode::isa public static function * Returns a value indicating if the token represents this type of node. * Overrides SassNode::isa
SassPropertyNode::isPseudoSelector private static function * Returns a value indicating if the string starts with a pseudo selector. * This is used to reject pseudo selectors as property values as, for example, * "a:hover" and "text-decoration:underline" look the same to the property …
SassPropertyNode::IS_SCRIPT constant
SassPropertyNode::match public static function * Returns the matches for this type of node. *
SassPropertyNode::MATCH_INTERPOLATION constant
SassPropertyNode::MATCH_PROPERTY_NEW constant
SassPropertyNode::MATCH_PROPERTY_OLD constant
SassPropertyNode::MATCH_PSUEDO_SELECTOR constant
SassPropertyNode::NAME constant
SassPropertyNode::parse public function * Parse this node. * If the node is a property namespace return all parsed child nodes. If not * return the parsed version of this node. *
SassPropertyNode::render public function * Render this node. *
SassPropertyNode::SCRIPT constant
SassPropertyNode::VALUE constant
SassPropertyNode::__construct public function * SassPropertyNode constructor. * Overrides SassNode::__construct