1499 lines
52 KiB
PHP
1499 lines
52 KiB
PHP
<?php
|
|
/**
|
|
* Helper class to read in a CSS style
|
|
*
|
|
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
|
|
* @author LarsDW223
|
|
*/
|
|
|
|
// must be run within Dokuwiki
|
|
if (!defined('DOKU_INC')) die();
|
|
|
|
require_once DOKU_PLUGIN . 'odt/helper/csscolors.php';
|
|
|
|
/**
|
|
* Abstract class to define kind of enum for the CSS value types.
|
|
* Actually only used by adjustLengthValues().
|
|
*/
|
|
abstract class CSSValueType
|
|
{
|
|
const Other = 0;
|
|
const LengthValueXAxis = 1;
|
|
const LengthValueYAxis = 2;
|
|
const StrokeOrBorderWidth = 3;
|
|
// etc.
|
|
}
|
|
|
|
/**
|
|
* Class css_declaration
|
|
*
|
|
* @package CSS\css_declaration
|
|
*/
|
|
class css_declaration {
|
|
protected static $css_units = array ('em', 'ex', '%', 'px', 'cm', 'mm', 'in', 'pt',
|
|
'pc', 'ch', 'rem', 'vh', 'vw', 'vmin', 'vmax');
|
|
protected $property;
|
|
protected $value;
|
|
|
|
/**
|
|
* Create a new declaration (property:value).
|
|
*
|
|
* @param string $property The property name of the declaration
|
|
* @param string $value The assigned value
|
|
*/
|
|
public function __construct($property, $value) {
|
|
$this->property = $property;
|
|
$this->value = trim($value, ';');
|
|
}
|
|
|
|
/**
|
|
* Get the property name of this declaration.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getProperty () {
|
|
return $this->property;
|
|
}
|
|
|
|
/**
|
|
* Get the value assigned to the property of this declaration.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getValue () {
|
|
return $this->value;
|
|
}
|
|
|
|
/**
|
|
* @param css_declaration[] $decls
|
|
*/
|
|
public function explode (&$decls) {
|
|
if ( empty ($this->property) ) {
|
|
return;
|
|
}
|
|
|
|
switch ($this->property) {
|
|
case 'background':
|
|
$this->explodeBackgroundShorthand ($decls);
|
|
break;
|
|
case 'font':
|
|
$this->explodeFontShorthand ($decls);
|
|
break;
|
|
case 'padding':
|
|
$this->explodePaddingShorthand ($decls);
|
|
break;
|
|
case 'margin':
|
|
$this->explodeMarginShorthand ($decls);
|
|
break;
|
|
case 'border':
|
|
$this->explodeBorderShorthand ($decls);
|
|
break;
|
|
case 'list-style':
|
|
$this->explodeListStyleShorthand ($decls);
|
|
break;
|
|
case 'flex':
|
|
$this->explodeFlexShorthand ($decls);
|
|
break;
|
|
case 'transition':
|
|
$this->explodeTransitionShorthand ($decls);
|
|
break;
|
|
case 'outline':
|
|
$this->explodeOutlineShorthand ($decls);
|
|
break;
|
|
case 'animation':
|
|
$this->explodeAnimationShorthand ($decls);
|
|
break;
|
|
case 'border-bottom':
|
|
$this->explodeBorderBottomShorthand ($decls);
|
|
break;
|
|
case 'columns':
|
|
$this->explodeColumnsShorthand ($decls);
|
|
break;
|
|
case 'column-rule':
|
|
$this->explodeColumnRuleShorthand ($decls);
|
|
break;
|
|
|
|
//FIXME: Implement all the shorthands missing
|
|
//case ...
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return bool
|
|
*/
|
|
public function isShorthand () {
|
|
switch ($this->property) {
|
|
case 'background':
|
|
case 'font':
|
|
case 'padding':
|
|
case 'margin':
|
|
case 'border':
|
|
case 'list-style':
|
|
case 'flex':
|
|
case 'transition':
|
|
case 'outline':
|
|
case 'animation':
|
|
case 'border-bottom':
|
|
case 'columns':
|
|
case 'column-rule':
|
|
return true;
|
|
break;
|
|
|
|
//FIXME: Implement all the shorthands missing
|
|
//case ...
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @param css_declaration[] $decls
|
|
*/
|
|
protected function explodeBackgroundShorthand (&$decls) {
|
|
if ( $this->property == 'background' ) {
|
|
$values = preg_split ('/\s+/', $this->value);
|
|
$index = 0;
|
|
if ($index < count($values)) {
|
|
$color_done = true;
|
|
$value = $values [$index];
|
|
if ($value [0] == '#' || csscolors::isKnownColorName($value)) {
|
|
$decls [] = new css_declaration ('background-color', $value);
|
|
$index++;
|
|
} else {
|
|
switch ($value) {
|
|
case 'transparent':
|
|
case 'inherit':
|
|
case 'initial':
|
|
$decls [] = new css_declaration ('background-color', $value);
|
|
$index++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if ($index < count($values)) {
|
|
$decls [] = new css_declaration ('background-image', $values [$index]);
|
|
$index++;
|
|
}
|
|
if ($index < count($values)) {
|
|
$decls [] = new css_declaration ('background-repeat', $values [$index]);
|
|
$index++;
|
|
}
|
|
if ($index < count($values)) {
|
|
$decls [] = new css_declaration ('background-attachment', $values [$index]);
|
|
$index++;
|
|
}
|
|
if ($index < count($values)) {
|
|
$decls [] = new css_declaration ('background-position', $values [$index]);
|
|
$index++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param css_declaration[] $decls
|
|
*/
|
|
protected function explodeFontShorthand (&$decls, $setDefaults=false) {
|
|
if ( $this->property == 'font' ) {
|
|
$values = preg_split ('/\s+/', $this->value);
|
|
|
|
$font_style_set = false;
|
|
$font_variant_set = false;
|
|
$font_weight_set = false;
|
|
$font_size_set = false;
|
|
$font_family = '';
|
|
|
|
foreach ($values as $value) {
|
|
if ( $font_style_set === false ) {
|
|
$default = false;
|
|
switch ($value) {
|
|
case 'normal':
|
|
case 'italic':
|
|
case 'oblique':
|
|
case 'initial':
|
|
case 'inherit':
|
|
$decls [] = new css_declaration ('font-style', $value);
|
|
break;
|
|
default:
|
|
$default = true;
|
|
if ($setDefaults) {
|
|
$decls [] = new css_declaration ('font-style', 'normal');
|
|
}
|
|
break;
|
|
}
|
|
$font_style_set = true;
|
|
if ( $default === false ) {
|
|
continue;
|
|
}
|
|
}
|
|
if ( $font_variant_set === false ) {
|
|
$default = false;
|
|
switch ($value) {
|
|
case 'normal':
|
|
case 'small-caps':
|
|
case 'initial':
|
|
case 'inherit':
|
|
$decls [] = new css_declaration ('font-variant', $value);
|
|
break;
|
|
default:
|
|
$default = true;
|
|
if ($setDefaults) {
|
|
$decls [] = new css_declaration ('font-variant', 'normal');
|
|
}
|
|
break;
|
|
}
|
|
$font_variant_set = true;
|
|
if ( $default === false ) {
|
|
continue;
|
|
}
|
|
}
|
|
if ( $font_weight_set === false ) {
|
|
$default = false;
|
|
switch ($value) {
|
|
case 'normal':
|
|
case 'bold':
|
|
case 'bolder':
|
|
case 'lighter':
|
|
case '100':
|
|
case '200':
|
|
case '300':
|
|
case '400':
|
|
case '500':
|
|
case '600':
|
|
case '700':
|
|
case '800':
|
|
case '900':
|
|
case 'initial':
|
|
case 'inherit':
|
|
$decls [] = new css_declaration ('font-weight', $value);
|
|
break;
|
|
default:
|
|
$default = true;
|
|
if ($setDefaults) {
|
|
$decls [] = new css_declaration ('font-weight', 'normal');
|
|
}
|
|
break;
|
|
}
|
|
$font_weight_set = true;
|
|
if ( $default === false ) {
|
|
continue;
|
|
}
|
|
}
|
|
if ( $font_size_set === false ) {
|
|
$default = false;
|
|
$params = explode ('/', $value);
|
|
switch ($params [0]) {
|
|
case 'medium':
|
|
case 'xx-small':
|
|
case 'x-small':
|
|
case 'small':
|
|
case 'large':
|
|
case 'x-large':
|
|
case 'xx-large':
|
|
case 'smaller':
|
|
case 'larger':
|
|
case 'initial':
|
|
case 'inherit':
|
|
$decls [] = new css_declaration ('font-size', $params [0]);
|
|
break;
|
|
default:
|
|
$found = false;
|
|
foreach (self::$css_units as $css_unit) {
|
|
if ( strpos ($value, $css_unit) !== false ) {
|
|
$decls [] = new css_declaration ('font-size', $params [0]);
|
|
$found = true;
|
|
break;
|
|
}
|
|
}
|
|
if ( $found === false ) {
|
|
$default = true;
|
|
if ($setDefaults) {
|
|
$decls [] = new css_declaration ('font-size', 'medium');
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
if ( !empty($params [1]) ) {
|
|
$decls [] = new css_declaration ('line-height', $params [1]);
|
|
} else {
|
|
if ($setDefaults) {
|
|
$decls [] = new css_declaration ('line-height', 'normal');
|
|
}
|
|
}
|
|
$font_size_set = true;
|
|
if ( $default === false ) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// All other properties are found.
|
|
// The rest is assumed to be a font-family.
|
|
if (empty ($font_family)) {
|
|
$font_family = $value;
|
|
} else {
|
|
$font_family .= ' '.$value;
|
|
}
|
|
}
|
|
if (!empty ($font_family)) {
|
|
$decls [] = new css_declaration ('font-family', $font_family);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param css_declaration[] $decls
|
|
*/
|
|
protected function explodePaddingShorthand (&$decls) {
|
|
if ( $this->property == 'padding' ) {
|
|
$values = preg_split ('/\s+/', $this->value);
|
|
switch (count($values)) {
|
|
case 4:
|
|
$decls [] = new css_declaration ('padding-top', $values [0]);
|
|
$decls [] = new css_declaration ('padding-right', $values [1]);
|
|
$decls [] = new css_declaration ('padding-bottom', $values [2]);
|
|
$decls [] = new css_declaration ('padding-left', $values [3]);
|
|
break;
|
|
case 3:
|
|
$decls [] = new css_declaration ('padding-top', $values [0]);
|
|
$decls [] = new css_declaration ('padding-right', $values [1]);
|
|
$decls [] = new css_declaration ('padding-left', $values [1]);
|
|
$decls [] = new css_declaration ('padding-bottom', $values [2]);
|
|
break;
|
|
case 2:
|
|
$decls [] = new css_declaration ('padding-top', $values [0]);
|
|
$decls [] = new css_declaration ('padding-bottom', $values [0]);
|
|
$decls [] = new css_declaration ('padding-right', $values [1]);
|
|
$decls [] = new css_declaration ('padding-left', $values [1]);
|
|
break;
|
|
case 1:
|
|
$decls [] = new css_declaration ('padding-top', $values [0]);
|
|
$decls [] = new css_declaration ('padding-bottom', $values [0]);
|
|
$decls [] = new css_declaration ('padding-right', $values [0]);
|
|
$decls [] = new css_declaration ('padding-left', $values [0]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param css_declaration[] $decls
|
|
*/
|
|
protected function explodeMarginShorthand (&$decls) {
|
|
if ( $this->property == 'margin' ) {
|
|
$values = preg_split ('/\s+/', $this->value);
|
|
switch (count($values)) {
|
|
case 4:
|
|
$decls [] = new css_declaration ('margin-top', $values [0]);
|
|
$decls [] = new css_declaration ('margin-right', $values [1]);
|
|
$decls [] = new css_declaration ('margin-bottom', $values [2]);
|
|
$decls [] = new css_declaration ('margin-left', $values [3]);
|
|
break;
|
|
case 3:
|
|
$decls [] = new css_declaration ('margin-top', $values [0]);
|
|
$decls [] = new css_declaration ('margin-right', $values [1]);
|
|
$decls [] = new css_declaration ('margin-left', $values [1]);
|
|
$decls [] = new css_declaration ('margin-bottom', $values [2]);
|
|
break;
|
|
case 2:
|
|
$decls [] = new css_declaration ('margin-top', $values [0]);
|
|
$decls [] = new css_declaration ('margin-bottom', $values [0]);
|
|
$decls [] = new css_declaration ('margin-right', $values [1]);
|
|
$decls [] = new css_declaration ('margin-left', $values [1]);
|
|
break;
|
|
case 1:
|
|
$decls [] = new css_declaration ('margin-top', $values [0]);
|
|
$decls [] = new css_declaration ('margin-bottom', $values [0]);
|
|
$decls [] = new css_declaration ('margin-right', $values [0]);
|
|
$decls [] = new css_declaration ('margin-left', $values [0]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param css_declaration[] $decls
|
|
*/
|
|
protected function explodeBorderShorthand (&$decls) {
|
|
$border_sides = array ('border-left', 'border-right', 'border-top', 'border-bottom');
|
|
if ( $this->property == 'border' ) {
|
|
$values = preg_split ('/\s+/', $this->value);
|
|
$index = 0;
|
|
$border_width_set = false;
|
|
$border_style_set = false;
|
|
$border_color_set = false;
|
|
while ( $index < 3 ) {
|
|
if ( $border_width_set === false ) {
|
|
switch ($values [$index]) {
|
|
case 'thin':
|
|
case 'medium':
|
|
case 'thick':
|
|
$decls [] = new css_declaration ('border-width', $values [$index]);
|
|
foreach ($border_sides as $border_side) {
|
|
$decls [] = new css_declaration ($border_side.'-width', $values [$index]);
|
|
}
|
|
break;
|
|
default:
|
|
if ( strpos ($values [$index], 'px') !== false ) {
|
|
$decls [] = new css_declaration ('border-width', $values [$index]);
|
|
foreach ($border_sides as $border_side) {
|
|
$decls [] = new css_declaration ($border_side.'-width', $values [$index]);
|
|
}
|
|
} else {
|
|
// There is no default value? So leave it unset.
|
|
}
|
|
break;
|
|
}
|
|
$border_width_set = true;
|
|
$index++;
|
|
continue;
|
|
}
|
|
if ( $border_style_set === false ) {
|
|
switch ($values [$index]) {
|
|
case 'none':
|
|
case 'dotted':
|
|
case 'dashed':
|
|
case 'solid':
|
|
case 'double':
|
|
case 'groove':
|
|
case 'ridge':
|
|
case 'inset':
|
|
case 'outset':
|
|
$decls [] = new css_declaration ('border-style', $values [$index]);
|
|
foreach ($border_sides as $border_side) {
|
|
$decls [] = new css_declaration ($border_side.'-style', $values [$index]);
|
|
}
|
|
break;
|
|
default:
|
|
$decls [] = new css_declaration ('border-style', 'none');
|
|
foreach ($border_sides as $border_side) {
|
|
$decls [] = new css_declaration ($border_side.'-style', 'none');
|
|
}
|
|
break;
|
|
}
|
|
$border_style_set = true;
|
|
$index++;
|
|
continue;
|
|
}
|
|
if ( $border_color_set === false ) {
|
|
$decls [] = new css_declaration ('border-color', $values [$index]);
|
|
foreach ($border_sides as $border_side) {
|
|
$decls [] = new css_declaration ($border_side.'-color', $values [$index]);
|
|
}
|
|
|
|
// This is the last value.
|
|
break;
|
|
}
|
|
}
|
|
foreach ($border_sides as $border_side) {
|
|
$decls [] = new css_declaration ($border_side, $values [0].' '.$values [1].' '.$values [2]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param css_declaration[] $decls
|
|
*/
|
|
protected function explodeListStyleShorthand (&$decls) {
|
|
if ( $this->property == 'list-style' ) {
|
|
$values = preg_split ('/\s+/', $this->value);
|
|
|
|
$list_style_type_set = false;
|
|
$list_style_position_set = false;
|
|
$list_style_image_set = false;
|
|
foreach ($values as $value) {
|
|
if ( $list_style_type_set === false ) {
|
|
$default = false;
|
|
switch ($value) {
|
|
case 'disc':
|
|
case 'armenian':
|
|
case 'circle':
|
|
case 'cjk-ideographic':
|
|
case 'decimal':
|
|
case 'decimal-leading-zero':
|
|
case 'georgian':
|
|
case 'hebrew':
|
|
case 'hiragana':
|
|
case 'hiragana-iroha':
|
|
case 'katakana':
|
|
case 'katakana-iroha':
|
|
case 'lower-alpha':
|
|
case 'lower-greek':
|
|
case 'lower-latin':
|
|
case 'lower-roman':
|
|
case 'none':
|
|
case 'square':
|
|
case 'upper-alpha':
|
|
case 'upper-latin':
|
|
case 'upper-roman':
|
|
case 'initial':
|
|
case 'inherit':
|
|
$decls [] = new css_declaration ('list-style-type', $value);
|
|
break;
|
|
default:
|
|
$default = true;
|
|
$decls [] = new css_declaration ('list-style-type', 'disc');
|
|
break;
|
|
}
|
|
$list_style_type_set = true;
|
|
if ( $default === false ) {
|
|
continue;
|
|
}
|
|
}
|
|
if ( $list_style_position_set === false ) {
|
|
$default = false;
|
|
switch ($value) {
|
|
case 'inside':
|
|
case 'outside':
|
|
case 'initial':
|
|
case 'inherit':
|
|
$decls [] = new css_declaration ('list-style-position', $value);
|
|
break;
|
|
default:
|
|
$default = true;
|
|
$decls [] = new css_declaration ('list-style-position', 'outside');
|
|
break;
|
|
}
|
|
$list_style_position_set = true;
|
|
if ( $default === false ) {
|
|
continue;
|
|
}
|
|
}
|
|
if ( $list_style_image_set === false ) {
|
|
$decls [] = new css_declaration ('list-style-image', $value);
|
|
$list_style_image_set = true;
|
|
}
|
|
}
|
|
if ( $list_style_image_set === false ) {
|
|
$decls [] = new css_declaration ('list-style-image', 'none');
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param css_declaration[] $decls
|
|
*/
|
|
protected function explodeFlexShorthand (&$decls) {
|
|
if ( $this->property == 'flex' ) {
|
|
$values = preg_split ('/\s+/', $this->value);
|
|
if ( count($values) > 0 ) {
|
|
$decls [] = new css_declaration ('flex-grow', $values [0]);
|
|
}
|
|
if ( count($values) > 1 ) {
|
|
$decls [] = new css_declaration ('flex-shrink', $values [1]);
|
|
}
|
|
if ( count($values) > 2 ) {
|
|
$decls [] = new css_declaration ('flex-basis', $values [2]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param css_declaration[] $decls
|
|
*/
|
|
protected function explodeTransitionShorthand (&$decls) {
|
|
if ( $this->property == 'transition' ) {
|
|
$values = preg_split ('/\s+/', $this->value);
|
|
if ( count($values) > 0 ) {
|
|
$decls [] = new css_declaration ('transition-property', $values [0]);
|
|
}
|
|
if ( count($values) > 1 ) {
|
|
$decls [] = new css_declaration ('transition-duration', $values [1]);
|
|
}
|
|
if ( count($values) > 2 ) {
|
|
$decls [] = new css_declaration ('transition-timing-function', $values [2]);
|
|
}
|
|
if ( count($values) > 3 ) {
|
|
$decls [] = new css_declaration ('transition-delay', $values [3]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param css_declaration[] $decls
|
|
*/
|
|
protected function explodeOutlineShorthand (&$decls) {
|
|
if ( $this->property == 'outline' ) {
|
|
$values = preg_split ('/\s+/', $this->value);
|
|
|
|
$outline_color_set = false;
|
|
$outline_style_set = false;
|
|
$outline_width_set = false;
|
|
foreach ($values as $value) {
|
|
if ( $outline_color_set === false ) {
|
|
$decls [] = new css_declaration ('outline-color', $value);
|
|
$outline_color_set = true;
|
|
continue;
|
|
}
|
|
if ( $outline_style_set === false ) {
|
|
$default = false;
|
|
switch ($value) {
|
|
case 'none':
|
|
case 'hidden':
|
|
case 'dotted':
|
|
case 'dashed':
|
|
case 'solid':
|
|
case 'double':
|
|
case 'groove':
|
|
case 'ridge':
|
|
case 'inset':
|
|
case 'outset':
|
|
case 'initial':
|
|
case 'inherit':
|
|
$decls [] = new css_declaration ('outline-style', $value);
|
|
break;
|
|
default:
|
|
$default = true;
|
|
$decls [] = new css_declaration ('outline-style', 'none');
|
|
break;
|
|
}
|
|
$outline_style_set = true;
|
|
if ( $default === false ) {
|
|
continue;
|
|
}
|
|
}
|
|
if ( $outline_width_set === false ) {
|
|
$default = false;
|
|
switch ($value) {
|
|
case 'medium':
|
|
case 'thin':
|
|
case 'thick':
|
|
case 'initial':
|
|
case 'inherit':
|
|
$decls [] = new css_declaration ('outline-width', $value);
|
|
break;
|
|
default:
|
|
$found = false;
|
|
foreach (self::$css_units as $css_unit) {
|
|
if ( strpos ($value, $css_unit) !== false ) {
|
|
$decls [] = new css_declaration ('outline-width', $value);
|
|
$found = true;
|
|
break;
|
|
}
|
|
}
|
|
if ( $found === false ) {
|
|
$default = true;
|
|
$decls [] = new css_declaration ('outline-width', 'medium');
|
|
}
|
|
break;
|
|
}
|
|
$outline_width_set = true;
|
|
if ( $default === false ) {
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param css_declaration[] $decls
|
|
*/
|
|
protected function explodeAnimationShorthand (&$decls) {
|
|
if ( $this->property == 'animation' ) {
|
|
$values = preg_split ('/\s+/', $this->value);
|
|
if ( count($values) > 0 ) {
|
|
$decls [] = new css_declaration ('animation-name', $values [0]);
|
|
}
|
|
if ( count($values) > 1 ) {
|
|
$decls [] = new css_declaration ('animation-duration', $values [1]);
|
|
}
|
|
if ( count($values) > 2 ) {
|
|
$decls [] = new css_declaration ('animation-timing-function', $values [2]);
|
|
}
|
|
if ( count($values) > 3 ) {
|
|
$decls [] = new css_declaration ('animation-delay', $values [3]);
|
|
}
|
|
if ( count($values) > 4 ) {
|
|
$decls [] = new css_declaration ('animation-iteration-count', $values [4]);
|
|
}
|
|
if ( count($values) > 5 ) {
|
|
$decls [] = new css_declaration ('animation-direction', $values [5]);
|
|
}
|
|
if ( count($values) > 6 ) {
|
|
$decls [] = new css_declaration ('animation-fill-mode', $values [6]);
|
|
}
|
|
if ( count($values) > 7 ) {
|
|
$decls [] = new css_declaration ('animation-play-state', $values [7]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param css_declaration[] $decls
|
|
*/
|
|
protected function explodeBorderBottomShorthand (&$decls) {
|
|
if ( $this->property == 'border-bottom' ) {
|
|
$values = preg_split ('/\s+/', $this->value);
|
|
|
|
$border_bottom_width_set = false;
|
|
$border_bottom_style_set = false;
|
|
$border_bottom_color_set = false;
|
|
foreach ($values as $value) {
|
|
if ( $border_bottom_width_set === false ) {
|
|
$default = false;
|
|
switch ($value) {
|
|
case 'medium':
|
|
case 'thin':
|
|
case 'thick':
|
|
case 'initial':
|
|
case 'inherit':
|
|
$decls [] = new css_declaration ('border-bottom-width', $value);
|
|
break;
|
|
default:
|
|
$found = false;
|
|
foreach (self::$css_units as $css_unit) {
|
|
if ( strpos ($value, $css_unit) !== false ) {
|
|
$decls [] = new css_declaration ('border-bottom-width', $value);
|
|
$found = true;
|
|
break;
|
|
}
|
|
}
|
|
if ( $found === false ) {
|
|
$default = true;
|
|
$decls [] = new css_declaration ('border-bottom-width', 'medium');
|
|
}
|
|
break;
|
|
}
|
|
$border_bottom_width_set = true;
|
|
if ( $default === false ) {
|
|
continue;
|
|
}
|
|
}
|
|
if ( $border_bottom_style_set === false ) {
|
|
$default = false;
|
|
switch ($value) {
|
|
case 'none':
|
|
case 'hidden':
|
|
case 'dotted':
|
|
case 'dashed':
|
|
case 'solid':
|
|
case 'double':
|
|
case 'groove':
|
|
case 'ridge':
|
|
case 'inset':
|
|
case 'outset':
|
|
case 'initial':
|
|
case 'inherit':
|
|
$decls [] = new css_declaration ('border-bottom-style', $value);
|
|
break;
|
|
default:
|
|
$default = true;
|
|
$decls [] = new css_declaration ('border-bottom-style', 'none');
|
|
break;
|
|
}
|
|
$border_bottom_style_set = true;
|
|
if ( $default === false ) {
|
|
continue;
|
|
}
|
|
}
|
|
if ( $border_bottom_color_set === false ) {
|
|
$decls [] = new css_declaration ('border-bottom-color', $value);
|
|
$border_bottom_color_set = true;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param css_declaration[] $decls
|
|
*/
|
|
protected function explodeColumnsShorthand (&$decls) {
|
|
if ( $this->property == 'columns' ) {
|
|
$values = preg_split ('/\s+/', $this->value);
|
|
if ( count($values) == 1 && $values [0] == 'auto' ) {
|
|
$decls [] = new css_declaration ('column-width', 'auto');
|
|
$decls [] = new css_declaration ('column-count', 'auto');
|
|
return;
|
|
}
|
|
if ( count($values) > 0 ) {
|
|
$decls [] = new css_declaration ('column-width', $values [0]);
|
|
}
|
|
if ( count($values) > 1 ) {
|
|
$decls [] = new css_declaration ('column-count', $values [1]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param css_declaration[] $decls
|
|
*/
|
|
protected function explodeColumnRuleShorthand (&$decls) {
|
|
if ( $this->property == 'column-rule' ) {
|
|
$values = preg_split ('/\s+/', $this->value);
|
|
if ( count($values) > 0 ) {
|
|
$decls [] = new css_declaration ('column-rule-width', $values [0]);
|
|
}
|
|
if ( count($values) > 1 ) {
|
|
$decls [] = new css_declaration ('column-rule-style', $values [1]);
|
|
}
|
|
if ( count($values) > 2 ) {
|
|
$decls [] = new css_declaration ('column-rule-color', $values [2]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param $callback
|
|
*/
|
|
public function adjustLengthValues ($callback, $rule=NULL) {
|
|
switch ($this->property) {
|
|
case 'border-width':
|
|
case 'outline-width':
|
|
case 'border-bottom-width':
|
|
case 'column-rule-width':
|
|
$this->value =
|
|
call_user_func($callback, $this->property, $this->value, CSSValueType::StrokeOrBorderWidth, $rule);
|
|
break;
|
|
|
|
case 'margin-left':
|
|
case 'margin-right':
|
|
case 'padding-left':
|
|
case 'padding-right':
|
|
case 'width':
|
|
case 'column-width':
|
|
$this->value =
|
|
call_user_func($callback, $this->property, $this->value, CSSValueType::LengthValueXAxis, $rule);
|
|
break;
|
|
|
|
case 'margin-top':
|
|
case 'margin-bottom':
|
|
case 'padding-top':
|
|
case 'padding-bottom':
|
|
case 'min-height':
|
|
case 'height':
|
|
case 'line-height':
|
|
$this->value =
|
|
call_user_func($callback, $this->property, $this->value, CSSValueType::LengthValueYAxis, $rule);
|
|
break;
|
|
|
|
case 'border':
|
|
case 'border-left':
|
|
case 'border-right':
|
|
case 'border-top':
|
|
case 'border-bottom':
|
|
$this->adjustLengthValuesBorder ($callback, $rule);
|
|
break;
|
|
|
|
// FIXME: Shorthands are currently not processed.
|
|
// Every Shorthand would need an extra function which knows if it has any length values.
|
|
// Just like the explode...Shorthand functions.
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param $callback
|
|
*/
|
|
protected function adjustLengthValuesBorder ($callback, $rule=NULL) {
|
|
switch ($this->property) {
|
|
case 'border':
|
|
case 'border-left':
|
|
case 'border-right':
|
|
case 'border-top':
|
|
case 'border-bottom':
|
|
$values = preg_split ('/\s+/', $this->value);
|
|
$width =
|
|
call_user_func($callback, $this->property, $values [0], CSSValueType::StrokeOrBorderWidth, $rule);
|
|
$this->value = $width . ' ' . $values [1] . ' ' . $values [2];
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param $callback
|
|
*/
|
|
public function replaceURLPrefixes ($callback) {
|
|
if (strncmp($this->value, 'url(', 4) == 0) {
|
|
$url = substr($this->value, 4, -1);
|
|
$this->value = call_user_func($callback, $this->property, $this->value, $url);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Class css_rule
|
|
*
|
|
* @package CSS\css_rule
|
|
*/
|
|
class css_rule {
|
|
protected $media = NULL;
|
|
protected $selectors = array ();
|
|
/** @var css_declaration[] */
|
|
protected $declarations = array ();
|
|
|
|
/**
|
|
* @param $selector
|
|
* @param $decls
|
|
* @param null $media
|
|
*/
|
|
public function __construct($selector, $decls, $media = NULL) {
|
|
|
|
$this->media = trim ($media);
|
|
//print ("\nNew rule: ".$media."\n"); //Debuging
|
|
|
|
$this->selectors = explode (' ', $selector);
|
|
|
|
$decls = trim ($decls, '{}');
|
|
|
|
// Parse declarations
|
|
$pos = 0;
|
|
$end = strlen ($decls);
|
|
while ( $pos < $end ) {
|
|
$colon = strpos ($decls, ':', $pos);
|
|
if ( $colon === false ) {
|
|
break;
|
|
}
|
|
$semi = strpos ($decls, ';', $colon + 1);
|
|
if ( $semi === false ) {
|
|
break;
|
|
}
|
|
|
|
$property = substr ($decls, $pos, $colon - $pos);
|
|
$property = trim($property);
|
|
|
|
$value = substr ($decls, $colon + 1, $semi - ($colon + 1));
|
|
$value = trim ($value);
|
|
$values = preg_split ('/\s+/', $value);
|
|
$value = '';
|
|
foreach ($values as $part) {
|
|
if ( $part != '!important' ) {
|
|
$value .= ' '.$part;
|
|
}
|
|
}
|
|
$value = trim($value);
|
|
|
|
// Create new declaration
|
|
$declaration = new css_declaration ($property, $value);
|
|
$this->declarations [] = $declaration;
|
|
|
|
// Handle CSS shorthands, e.g. 'border'
|
|
if ( $declaration->isShorthand () === true ) {
|
|
$declaration->explode ($this->declarations);
|
|
}
|
|
|
|
$pos = $semi + 1;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
public function toString () {
|
|
$returnString = '';
|
|
$returnString .= "Media= \"".$this->media."\"\n";
|
|
foreach ($this->selectors as $selector) {
|
|
$returnString .= $selector.' ';
|
|
}
|
|
$returnString .= "{\n";
|
|
foreach ($this->declarations as $declaration) {
|
|
$returnString .= ' '.$declaration->getProperty ().':'.$declaration->getValue ().";\n";
|
|
}
|
|
$returnString .= "}\n";
|
|
return $returnString;
|
|
}
|
|
|
|
/**
|
|
* @param $element
|
|
* @param $classString
|
|
* @param null $media
|
|
* @return bool|int
|
|
*/
|
|
public function matches ($element, $classString, $media = NULL, $cssId=NULL) {
|
|
|
|
$media = trim ($media);
|
|
if ( !empty($this->media) && $media != $this->media ) {
|
|
// Wrong media
|
|
//print ("\nNo-Match ".$this->media."==".$media); //Debuging
|
|
return false;
|
|
}
|
|
|
|
$matches = 0;
|
|
$classes = explode (' ', $classString);
|
|
|
|
foreach ($this->selectors as $selector) {
|
|
if ( !empty($classString) ) {
|
|
foreach ($classes as $class) {
|
|
if ( $selector [0] == '.' && $selector == '.'.$class ) {
|
|
$matches++;
|
|
break;
|
|
} else if ( $selector [0] == '#' && $selector == '#'.$cssId ) {
|
|
$matches++;
|
|
break;
|
|
} else if ( $selector == $element || $selector == $element.'.'.$class ) {
|
|
$matches++;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
if ( $selector [0] == '#' && $selector == '#'.$cssId ) {
|
|
$matches++;
|
|
} else if ( $selector == $element ) {
|
|
$matches++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// We only got a match if all selectors were matched
|
|
if ( $matches == count($this->selectors) ) {
|
|
// Return the number of matched selectors
|
|
// This enables the caller to choose the most specific rule
|
|
return $matches;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @param $name
|
|
* @return null
|
|
*/
|
|
public function getProperty ($name) {
|
|
foreach ($this->declarations as $declaration) {
|
|
if ( $name == $declaration->getProperty () ) {
|
|
return $declaration->getValue ();
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* @param $values
|
|
* @return null
|
|
*/
|
|
public function getProperties (&$values) {
|
|
foreach ($this->declarations as $declaration) {
|
|
$property = $declaration->getProperty ();
|
|
$value = $declaration->getValue ();
|
|
$values [$property] = $value;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* @param $callback
|
|
*/
|
|
public function adjustLengthValues ($callback) {
|
|
foreach ($this->declarations as $declaration) {
|
|
$declaration->adjustLengthValues ($callback);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Class helper_plugin_odt_cssimport
|
|
*
|
|
* @package helper\cssimport
|
|
*/
|
|
class helper_plugin_odt_cssimport extends DokuWiki_Plugin {
|
|
protected $replacements = array();
|
|
protected $raw;
|
|
/** @var css_rule[] */
|
|
protected $rules = array ();
|
|
|
|
/**
|
|
* Imports CSS from a file.
|
|
* @deprecated since 3015-05-23, use importFromFile
|
|
*
|
|
* @param $filename
|
|
*/
|
|
function importFrom($filename) {
|
|
dbg_deprecated('importFromFile');
|
|
$this->importFromFile($filename);
|
|
}
|
|
|
|
/**
|
|
* @param $contents
|
|
* @return bool
|
|
*/
|
|
function importFromString($contents) {
|
|
$this->deleteComments ($contents);
|
|
return $this->importFromStringInternal ($contents);
|
|
}
|
|
|
|
/**
|
|
* Delete comments in $contents. All comments are overwritten with spaces.
|
|
* The '&' is required. DO NOT DELETE!!!
|
|
* @param $contents
|
|
*/
|
|
protected function deleteComments (&$contents) {
|
|
// Delete all comments first
|
|
$pos = 0;
|
|
$max = strlen ($contents);
|
|
$in_comment = false;
|
|
while ( $pos < $max ) {
|
|
if ( ($pos+1) < $max &&
|
|
$contents [$pos] == '/' &&
|
|
$contents [$pos+1] == '*' ) {
|
|
$in_comment = true;
|
|
|
|
$contents [$pos] = ' ';
|
|
$contents [$pos+1] = ' ';
|
|
$pos += 2;
|
|
continue;
|
|
}
|
|
if ( ($pos+1) < $max &&
|
|
$contents [$pos] == '*' &&
|
|
$contents [$pos+1] == '/' &&
|
|
$in_comment === true ) {
|
|
$in_comment = false;
|
|
|
|
$contents [$pos] = ' ';
|
|
$contents [$pos+1] = ' ';
|
|
$pos += 2;
|
|
continue;
|
|
}
|
|
if ( $in_comment === true ) {
|
|
$contents [$pos] = ' ';
|
|
}
|
|
$pos++;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param $contents
|
|
* @param null $media
|
|
* @return bool
|
|
*/
|
|
protected function importFromStringInternal($contents, $media = NULL, &$processed = NULL) {
|
|
// Find all CSS rules
|
|
$pos = 0;
|
|
$max = strlen ($contents);
|
|
while ( $pos < $max ) {
|
|
$bracket_open = strpos ($contents, '{', $pos);
|
|
if ( $bracket_open === false ) {
|
|
return false;
|
|
}
|
|
$bracket_close = strpos ($contents, '}', $pos);
|
|
if ( $bracket_close === false ) {
|
|
return false;
|
|
}
|
|
|
|
// If this is a nested call we might hit a closing } for the media section
|
|
// which was the reason for this function call. In this case break and return.
|
|
if ( $bracket_close < $bracket_open ) {
|
|
$pos = $bracket_close + 1;
|
|
break;
|
|
}
|
|
|
|
// Get the part before the open bracket and the last closing bracket
|
|
// (or the start of the string).
|
|
$before_open_bracket = substr ($contents, $pos, $bracket_open - $pos);
|
|
|
|
// Is it a @media rule?
|
|
$before_open_bracket = trim ($before_open_bracket);
|
|
$mediapos = stripos($before_open_bracket, '@media');
|
|
if ( $mediapos !== false ) {
|
|
|
|
// Yes, decode content as normal rules with @media ... { ... }
|
|
//$new_media = substr_replace ($before_open_bracket, NULL, $mediapos, strlen ('@media'));
|
|
$new_media = substr ($before_open_bracket, $mediapos + strlen ('@media'));
|
|
$contents_in_media = substr ($contents, $bracket_open + 1);
|
|
|
|
$nested_processed = 0;
|
|
$result = $this->importFromStringInternal ($contents_in_media, $new_media, $nested_processed);
|
|
if ( $result !== true ) {
|
|
// Stop parsing on error.
|
|
return false;
|
|
}
|
|
unset ($new_media);
|
|
$pos = $bracket_open + 1 + $nested_processed;
|
|
} else {
|
|
|
|
// No, decode rule the normal way selector { ... }
|
|
$selectors = explode (',', $before_open_bracket);
|
|
|
|
$decls = substr ($contents, $bracket_open + 1, $bracket_close - $bracket_open);
|
|
|
|
// Create a own, new rule for every selector
|
|
foreach ( $selectors as $selector ) {
|
|
$selector = trim ($selector);
|
|
$this->rules [] = new css_rule ($selector, $decls, $media);
|
|
}
|
|
|
|
$pos = $bracket_close + 1;
|
|
}
|
|
}
|
|
if ( $processed !== NULL ) {
|
|
$processed = $pos;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @param $filename
|
|
* @return bool|void
|
|
*/
|
|
function importFromFile($filename) {
|
|
// Try to read in the file content
|
|
if ( empty($filename) ) {
|
|
return false;
|
|
}
|
|
|
|
$handle = fopen($filename, "rb");
|
|
if ( $handle === false ) {
|
|
return false;
|
|
}
|
|
|
|
$contents = fread($handle, filesize($filename));
|
|
fclose($handle);
|
|
if ( $contents === false ) {
|
|
return false;
|
|
}
|
|
|
|
return $this->importFromString ($contents);
|
|
}
|
|
|
|
/**
|
|
* @param $filename
|
|
* @return bool
|
|
*/
|
|
function loadReplacements($filename) {
|
|
// Try to read in the file content
|
|
if ( empty($filename) ) {
|
|
return false;
|
|
}
|
|
|
|
$handle = fopen($filename, "rb");
|
|
if ( $handle === false ) {
|
|
return false;
|
|
}
|
|
|
|
$filesize = filesize($filename);
|
|
$contents = fread($handle, $filesize);
|
|
fclose($handle);
|
|
if ( $contents === false ) {
|
|
return false;
|
|
}
|
|
|
|
// Delete all comments first
|
|
$contents = preg_replace ('/;.*/', ' ', $contents);
|
|
|
|
// Find the start of the replacements section
|
|
$rep_start = strpos ($contents, '[replacements]');
|
|
if ( $rep_start === false ) {
|
|
return false;
|
|
}
|
|
$rep_start += strlen ('[replacements]');
|
|
|
|
// Find the end of the replacements section
|
|
// (The end is either the next section or the end of file)
|
|
$rep_end = strpos ($contents, '[', $rep_start);
|
|
if ( $rep_end === false ) {
|
|
$rep_end = $filesize - 1;
|
|
}
|
|
|
|
// Find all replacment definitions
|
|
$defs = substr ($contents, $rep_start, $rep_end - $rep_start);
|
|
$defs_end = strlen ($defs);
|
|
|
|
$def_pos = 0;
|
|
while ( $def_pos < $defs_end ) {
|
|
$linestart = strpos ($defs, "\n", $def_pos);
|
|
if ( $linestart === false ) {
|
|
break;
|
|
}
|
|
$linestart += strlen ("\n");
|
|
|
|
$lineend = strpos ($defs, "\n", $linestart);
|
|
if ( $lineend === false ) {
|
|
$lineend = $defs_end;
|
|
}
|
|
|
|
$equal_sign = strpos ($defs, '=', $linestart);
|
|
if ( $equal_sign === false || $equal_sign > $lineend ) {
|
|
$def_pos = $linestart;
|
|
continue;
|
|
}
|
|
|
|
$quote_start = strpos ($defs, '"', $equal_sign + 1);
|
|
if ( $quote_start === false || $quote_start > $lineend ) {
|
|
$def_pos = $linestart;
|
|
continue;
|
|
}
|
|
|
|
$quote_end = strpos ($defs, '"', $quote_start + 1);
|
|
if ( $quote_end === false || $quote_start > $lineend) {
|
|
$def_pos = $linestart;
|
|
continue;
|
|
}
|
|
if ( $quote_end - $quote_start < 2 ) {
|
|
$def_pos = $linestart;
|
|
continue;
|
|
}
|
|
|
|
$replacement = substr ($defs, $linestart, $equal_sign - $linestart);
|
|
$value = substr ($defs, $quote_start + 1, $quote_end - ($quote_start + 1));
|
|
$replacement = trim($replacement);
|
|
$value = trim($value);
|
|
|
|
$this->replacements [$replacement] = $value;
|
|
|
|
$def_pos = $lineend;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @return mixed
|
|
*/
|
|
public function getRaw () {
|
|
return $this->raw;
|
|
}
|
|
|
|
/**
|
|
* @param $name
|
|
* @return mixed
|
|
*/
|
|
public function getReplacement ($name) {
|
|
return $this->replacements [$name];
|
|
}
|
|
|
|
/**
|
|
* @param $element
|
|
* @param $classString
|
|
* @param $name
|
|
* @param null $media
|
|
* @return null
|
|
*/
|
|
public function getPropertyForElement ($element, $classString, $name, $media = NULL) {
|
|
if ( empty ($name) ) {
|
|
return NULL;
|
|
}
|
|
|
|
$value = NULL;
|
|
foreach ($this->rules as $rule) {
|
|
$matched = $rule->matches ($element, $classString, $media);
|
|
if ( $matched !== false ) {
|
|
$current = $rule->getProperty ($name);
|
|
if ( !empty ($current) ) {
|
|
$value = $current;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $value;
|
|
}
|
|
|
|
/**
|
|
* @param $classString
|
|
* @param $name
|
|
* @return null
|
|
*/
|
|
public function getProperty ($classString, $name) {
|
|
if ( empty ($classString) || empty ($name) ) {
|
|
return NULL;
|
|
}
|
|
|
|
$value = $this->getPropertyForElement (NULL, $classString, $name);
|
|
return $value;
|
|
}
|
|
|
|
/**
|
|
* @param $dest
|
|
* @param $element
|
|
* @param $classString
|
|
* @param null $media
|
|
*/
|
|
public function getPropertiesForElement (&$dest, $element, $classString, $media = NULL, $cssId=NULL) {
|
|
if ( empty ($element) && empty ($classString) && empty ($cssId) ) {
|
|
return;
|
|
}
|
|
|
|
foreach ($this->rules as $rule) {
|
|
$matched = $rule->matches ($element, $classString, $media, $cssId);
|
|
if ( $matched !== false ) {
|
|
$rule->getProperties ($dest);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param $value
|
|
* @param int $emValue
|
|
* @return string
|
|
*/
|
|
public function adjustValueForODT ($value, $emValue = 0) {
|
|
// ODT specific function. Shouldn't be used anymore.
|
|
// Call the ODT renderer's function instead.
|
|
dbg_deprecated('renderer_plugin_odt_page::adjustValueForODT');
|
|
|
|
$values = preg_split ('/\s+/', $value);
|
|
$value = '';
|
|
foreach ($values as $part) {
|
|
// Replace it if necessary
|
|
$part = trim($part);
|
|
$rep = $this->getReplacement($part);
|
|
if ( !empty ($rep) ) {
|
|
$part = $rep;
|
|
}
|
|
$length = strlen ($part);
|
|
|
|
// If it is a short color value (#xxx) then convert it to long value (#xxxxxx)
|
|
// (ODT does not support the short form)
|
|
if ( $part [0] == '#' && $length == 4 ) {
|
|
$part = '#'.$part [1].$part [1].$part [2].$part [2].$part [3].$part [3];
|
|
} else {
|
|
// If it is a CSS color name, get it's real color value
|
|
/** @var helper_plugin_odt_csscolors $odt_colors */
|
|
$odt_colors = plugin_load('helper', 'odt_csscolors');
|
|
$color = $odt_colors->getColorValue ($part);
|
|
if ( $part == 'black' || $color != '#000000' ) {
|
|
$part = $color;
|
|
}
|
|
}
|
|
|
|
if ( $length > 2 && $part [$length-2] == 'e' && $part [$length-1] == 'm' ) {
|
|
$number = substr ($part, 0, $length-2);
|
|
if ( is_numeric ($number) && !empty ($emValue) ) {
|
|
$part = ($number * $emValue).'pt';
|
|
}
|
|
}
|
|
|
|
// Replace px with pt (px does not seem to be supported by ODT)
|
|
if ( $length > 2 && $part [$length-2] == 'p' && $part [$length-1] == 'x' ) {
|
|
$part [$length-1] = 't';
|
|
}
|
|
|
|
$value .= ' '.$part;
|
|
}
|
|
$value = trim($value);
|
|
|
|
return $value;
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
public function rulesToString () {
|
|
$returnString = '';
|
|
foreach ($this->rules as $rule) {
|
|
$returnString .= $rule->toString ();
|
|
}
|
|
return $returnString;
|
|
}
|
|
|
|
/**
|
|
* @param $URL
|
|
* @param $replacement
|
|
* @return string
|
|
*/
|
|
public function replaceURLPrefix ($URL, $replacement) {
|
|
if ( !empty ($URL) && !empty ($replacement) ) {
|
|
// Replace 'url(...)' with $replacement
|
|
$URL = substr ($URL, 3);
|
|
$URL = trim ($URL, '()');
|
|
$URL = $replacement.$URL;
|
|
}
|
|
return $URL;
|
|
}
|
|
|
|
/**
|
|
* @param $callback
|
|
*/
|
|
public function adjustLengthValues ($callback) {
|
|
foreach ($this->rules as $rule) {
|
|
$rule->adjustLengthValues ($callback);
|
|
}
|
|
}
|
|
}
|
|
|