/** * Easy opacity * Adds vendor-specific versions of opacity * * Usage: #foo { opacity: 0.5; } * Result: #foo { -moz-opacity: 0.5; -webkit-opacity: 0.5; -kthml-opacity: 0.5; -ms-filter: "alpha(opacity=50)"; filter: alpha(opacity=50); opacity: 0.5;} * Status: Stable * Version: 1.1 * * @param mixed &$parsed * @return void */ function opacity(&$parsed) { global $cssp, $browser; foreach ($parsed as $block => $css) { foreach ($parsed[$block] as $selector => $styles) { if (isset($parsed[$block][$selector]['opacity'])) { foreach ($styles as $property => $values) { if ($property == 'opacity') { $opacity_properties = array(); // Build prefixed properties $prefixes = array('-moz-', '-webkit-', '-khtml-'); foreach ($prefixes as $prefix) { $opacity_properties[$prefix . 'opacity'] = $parsed[$block][$selector]['opacity']; } // Create IE filters and insert everything $filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity=' . round(floatval($parsed[$block][$selector]['opacity'][0]) * 100) . ')'; // Legacy IE compliance if ($browser->engine == 'ie' && $browser->engine_version < 8) { $opacity_properties['filter'] = array($filter); } elseif ($browser->engine == 'ie' && $browser->engine_version < 9) { $opacity_properties['-ms-filter'] = array($filter); } $cssp->insert_properties($opacity_properties, $block, $selector, $property, NULL); // Comment the newly inserted properties foreach ($opacity_properties as $opacity_property => $opacity_value) { CSSP::comment($parsed[$block][$selector], $opacity_property, 'Added by opacity plugin'); } } } } } } }
/** * Easy and extended border radius * Adds vendor-specific versions of border-radius and adds border-top-radius, * border-bottom-radius, border-left-radius and border-right-radius * For IE, only general radius works. And make sure, border-radius declaration * comes before any (box-)shadow-declaration in CSS-code! * * Usage: border-radius[-top/-bottom/-left/-right/-top-left/...]: value; * Example 1: border-top-radius:4px; * Example 2: border-bottom-left-radius:2em; * Status: Stable * Version: 1.1 * * @param mixed &$parsed * @return void */ function borderradius(&$parsed) { global $cssp, $browser; $htc_path = rtrim(dirname($_SERVER['SCRIPT_NAME']), '/') . '/plugins/borderradius/chromacorners.htc'; foreach ($parsed as $block => $css) { foreach ($parsed[$block] as $selector => $styles) { foreach ($styles as $property => $values) { if (preg_match('/border(?:-(top|right|bottom|left)(?:-(right|left))*)*-radius/', $property, $matches)) { // Create the new rules and insert them $borderradius_rules = borderradius_glue_rules($matches, $values); $borderradius_rules['behavior'][] = 'url(' . $htc_path . ')'; $cssp->insert_properties($borderradius_rules, $block, $selector, null, $property); // Comment the newly inserted properties foreach ($borderradius_rules as $border_property => $border_value) { CSSP::comment($parsed[$block][$selector], $border_property, 'Added by border radius plugin'); } // Remove Top/Left/Bottom/Right shortcuts if (count($matches) == 2) { unset($parsed[$block][$selector][$property]); } } } } } }
/** * Easy box shadow * Adds vendor-specific versions of box-shadow * * Usage: #foo { box-shadow: 2px 2px 8px #666; } * Result: #foo { box-shadow: 2px 2px 8px #666; -moz-box-shadow: 2px 2px 8px #666; -webkit-box-shadow: 2px 2px 8px #666; } * Status: Stable * Version: 1.1 * * @param mixed &$parsed * @return void */ function boxshadow(&$parsed) { global $cssp; foreach ($parsed as $block => $css) { foreach ($parsed[$block] as $selector => $styles) { if (isset($parsed[$block][$selector]['box-shadow'])) { foreach ($styles as $property => $values) { if ($property == 'box-shadow') { $shadow_properties = array(); // Build prefixed properties $prefixes = array('-moz-', '-webkit-'); foreach ($prefixes as $prefix) { $shadow_properties[$prefix . 'box-shadow'] = $parsed[$block][$selector]['box-shadow']; } // Get IE filters, merge them with the other new properties and insert everything $filter_properties = boxshadow_filters($values); $shadow_properties = array_merge($shadow_properties, $filter_properties); $cssp->insert_properties($shadow_properties, $block, $selector, null, 'box-shadow'); // Comment the newly inserted properties foreach ($shadow_properties as $shadow_property => $shadow_value) { CSSP::comment($parsed[$block][$selector], $shadow_property, 'Added by box shadow plugin'); } } } } } } }
/** * A bunch of general browser bugfixes * * Usage: Nobrainer, just switch it on * Example: - * Status: Stable * Version: 1.0 * * @param mixed &$parsed * @return void */ function bugfixes(&$parsed) { global $cssp, $browser; $changed = array(); // IE6: Image margin bottom bug $changed['img']['vertical-align'][] = 'bottom'; // IE6: Background image flickers on hover $changed['html']['filter'][] = 'expression(document.execCommand("BackgroundImageCache",false,true))'; // IE6: Fix transparent PNGs, see http://www.twinhelix.com/css/iepngfix/ $htc_path = rtrim(dirname($_SERVER['SCRIPT_NAME']), '/') . '/plugins/bugfixes/iepngfix.htc'; $changed['img']['behavior'][] = 'url("' . $htc_path . '")'; // IE6 and 7: resample images bicubic instead of using nearest neighbor method $changed['img']['-ms-interpolation-mode'][] = 'bicubic'; // IE6 and 7: Enable full styleability for buttons, see http://www.sitepoint.com/forums/showthread.php?t=547059 $changed['button']['overflow'][] = 'visible'; $changed['button']['width'][] = 'auto'; $changed['button']['white-space'][] = 'nowrap'; // IE6 and 7: Missing :hover-property on every tag except a, see http://www.xs4all.nl/~peterned/csshover.html $htc_path = rtrim(dirname($_SERVER['SCRIPT_NAME']), '/') . '/plugins/bugfixes/csshover3.htc'; $changed['body']['behavior'][] = 'url("' . $htc_path . '")'; // Firefox: Ghost margin around buttons, see http://www.sitepoint.com/forums/showthread.php?t=547059 $changed['button::-moz-focus-inner']['padding'][] = '0'; $changed['button::-moz-focus-inner']['border'][] = 'none'; // Add comments for the global fixes foreach ($changed as $selector => $styles) { foreach ($styles as $property => $value) { CSSP::comment($changed[$selector], $property, 'Added by bugfix plugin'); } } // Insert the global bugfixes $cssp->insert($changed, 'global'); // Apply per-element-bugfixes foreach ($cssp->parsed as $block => $css) { foreach ($cssp->parsed[$block] as $selector => $styles) { // IE 6 per-element-bugfixes if ($browser->browser == 'ie' && floatval($browser->browser_version) < 7) { // Float double margin bug, fixed with a behavior as this only affects the floating object and no descendant of it if (isset($cssp->parsed[$block][$selector]['float']) && $cssp->get_final_value($cssp->parsed[$block][$selector]['float']) != 'none') { $htc_path = rtrim(dirname($_SERVER['SCRIPT_NAME']), '/') . '/plugins/bugfixes/doublemargin.htc'; $cssp->parsed[$block][$selector]['behavior'][] = 'url("' . $htc_path . '")'; CSSP::comment($cssp->parsed[$block][$selector], 'behavior', 'Added by bugfix plugin'); } // Min-height for IE6 if (isset($cssp->parsed[$block][$selector]['min-height']) && !isset($cssp->parsed[$block][$selector]['height'])) { $cssp->parsed[$block][$selector]['height'] = $cssp->parsed[$block][$selector]['min-height']; CSSP::comment($cssp->parsed[$block][$selector], 'height', 'Added by bugfix plugin'); } } // IE 6 + 7 per-element-bugfixes if ($browser->browser == 'ie' && floatval($browser->browser_version) < 8) { // Enable overflow:hidden, if present if (isset($cssp->parsed[$block][$selector]['overflow']) && $cssp->get_final_value($cssp->parsed[$block][$selector]['overflow']) == 'hidden' && !isset($cssp->parsed[$block][$selector]['position'])) { $cssp->parsed[$block][$selector]['position'][] = 'relative'; CSSP::comment($cssp->parsed[$block][$selector], 'position', 'Added by bugfix plugin'); } } } } }
/** * Colormodels * HSL(A) and RGBA support for most older browsers * * Usage: Nobrainer, just switch it on * Example: - * Status: Beta * Version: 1.0 * * @param mixed &$parsed * @return void */ function colormodels(&$parsed) { $models = array('rgba', 'hsla', 'hsl'); $hslapattern = '/(hsl(?:a)?)\\([\\s]*(.*?)[\\s]*,[\\s]*(.*?)%[\\s]*,[\\s]*(.*?)%[\\s]*(:?,[\\s]*(.*?)[\\s]*)?\\)/i'; $rgbapattern = '/(rgba)\\([\\s]*(.*?)[\\s]*,[\\s]*(.*?)[\\s]*,[\\s]*(.*?)[\\s]*,[\\s]*(.*?)[\\s]*\\)/i'; $properties = array('background', 'background-color', 'color', 'border', 'border-color', 'border-top', 'border-left', 'border-bottom', 'border-right', 'text-shadow', 'box-shadow'); $capabilities = colormodels_get_browser_capabilities(); // Only continue if we can be sure to know anything about the browser's capabilities if (!empty($capabilities)) { // For every possible property... foreach ($properties as $search) { // ... loop through the css... foreach ($parsed as $block => $css) { foreach ($parsed[$block] as $selector => $styles) { if ($selector != '@turbine' && isset($parsed[$block][$selector][$search])) { $num_values = count($parsed[$block][$selector][$search]); // ... loop through the values for ($i = 0; $i < $num_values; $i++) { // Found something that we may have to replace? if (preg_match($hslapattern, $parsed[$block][$selector][$search][$i], $matches) || preg_match($rgbapattern, $parsed[$block][$selector][$search][$i], $matches)) { // See if the browser supports the color model, convert if not $rgba = colormodels_to_rgba($matches); foreach ($models as $model) { if ($model == $matches[1]) { if (!isset($capabilities[$model])) { $recalculated = colormodels_recalculate($model, $rgba, $capabilities, $search); if (!empty($recalculated)) { // Apply the recalculated properties and values to $parsed foreach ($recalculated as $property => $value) { if (!isset($parsed[$block][$selector][$property])) { $parsed[$block][$selector][$property][$i] = $value; CSSP::comment($parsed[$block][$selector], $property, 'Added by colormodels plugin'); } else { $parsed[$block][$selector][$property][$i] = str_replace($matches[0], $value, $parsed[$block][$selector][$property][$i]); CSSP::comment($parsed[$block][$selector], $property, 'Modified by colormodels plugin'); } } } } } } } } } } } } } }
/** * Cross-browser-box-sizing * * Usage: box-sizing:inherit|content-box|border-box * Status: Beta * Version: 1.0 * * @param mixed &$parsed * @return void */ function boxsizing(&$parsed) { global $browser, $cssp; $htc_path = rtrim(dirname($_SERVER['SCRIPT_NAME']), '/') . '/plugins/boxsizing/boxsizing.htc'; foreach ($parsed as $block => $css) { foreach ($parsed[$block] as $selector => $styles) { if (isset($styles['box-sizing'])) { // Create the vendor-specific rules and insert them $boxsizing_rules = array('-moz-box-sizing' => $styles['box-sizing'], '-webkit-box-sizing' => $styles['box-sizing'], 'behavior' => 'url(' . $htc_path . ')'); $cssp->insert_properties($boxsizing_rules, $block, $selector, null, 'box-sizing'); // Comment the newly inserted properties foreach ($boxsizing_rules as $property => $value) { CSSP::comment($parsed[$block][$selector], $property, 'Added by box-sizing plugin'); } } } } }
/** * Color * Provides HSL(A) support for all browsers * * Usage: Nobrainer, just switch it on * Example: - * Status: Beta * Version: 2.0 * * @param mixed &$cssp->parsed * @return void */ function color() { include 'lib/utility.php'; global $browser, $cssp; $properties = array('background', 'background-color', 'color', 'border', 'border-color', 'border-top', 'border-left', 'border-bottom', 'border-right', 'text-shadow', 'box-shadow'); // For every possible property... foreach ($properties as $search) { // ... loop through the css... foreach ($cssp->parsed as $block => $css) { foreach ($cssp->parsed[$block] as $selector => $styles) { if ($selector != '@turbine' && isset($cssp->parsed[$block][$selector][$search])) { $num_values = count($cssp->parsed[$block][$selector][$search]); // ... loop through the values for ($i = 0; $i < $num_values; $i++) { // Found something that we may have to replace? $hslamatch = preg_match(Utility::$hslapattern, $cssp->parsed[$block][$selector][$search][$i]); $rgbamatch = preg_match(Utility::$rgbapattern, $cssp->parsed[$block][$selector][$search][$i]); if ($hslamatch || $rgbamatch) { $rgba = Utility::any2rgba($cssp->parsed[$block][$selector][$search][$i]); // For HSL recalculate to RGBA just to be sure the color will work everywhere if ($hslamatch) { $replacement = Utility::rgbasyntax($rgba); $cssp->parsed[$block][$selector][$search][$i] = preg_replace(Utility::$hslapattern, $replacement, $cssp->parsed[$block][$selector][$search][$i]); CSSP::comment($cssp->parsed[$block][$selector], $search, 'Modified by color plugin'); } // If we detect IE and work with a background, try filters... if ($browser->browser == 'ie' && $browser->browser_version < 9 && ($search == 'background' || $search == 'background-color')) { $filter = color_get_filter($rgba, $search); $cssp->insert_properties($filter, $block, $selector, NULL, $search); foreach ($filter as $filter_property => $filter_value) { CSSP::comment($cssp->parsed[$block][$selector], $filter_property, 'Modified by color plugin'); } } else { $fallback = Utility::rgbsyntax($rgba); array_unshift($cssp->parsed[$block][$selector][$search], preg_replace(Utility::$rgbapattern, $fallback, $cssp->parsed[$block][$selector][$search][$i])); CSSP::comment($cssp->parsed[$block][$selector], $search, 'Modified by color plugin'); } } } } } } } }
/** * Inline Block * Implements the "display: inline-block" property for all current browsers * * Usage: Nobrainer, just switch it on * Example: - * Status: Stable * Version: 1.0 * * @param mixed &$parsed * @return void */ function inlineblock(&$parsed) { global $browser, $cssp; foreach ($cssp->parsed as $block => $css) { foreach ($cssp->parsed[$block] as $selector => $styles) { // Everywhere if (isset($cssp->parsed[$block][$selector]['display']) && $cssp->get_final_value($cssp->parsed[$block][$selector]['display'], 'display') == 'inline-block') { if ($browser->engine == 'ie' && floatval($browser->engine_version) < 8) { $cssp->parsed[$block][$selector]['display'][] = 'inline'; CSSP::comment($cssp->parsed[$block][$selector], 'display', 'Added by inline-block plugin'); $cssp->parsed[$block][$selector]['zoom'][] = '1'; CSSP::comment($cssp->parsed[$block][$selector], 'zoom', 'Added by inline-block plugin'); } elseif ($browser->engine == 'gecko' && floatval($browser->engine_version) < 1.9) { $cssp->parsed[$block][$selector]['display'][] = '-moz-inline-stack'; CSSP::comment($cssp->parsed[$block][$selector], 'display', 'Added by inline-block plugin'); } } } } }
/** * Easy and extended border radius * Adds vendor-specific versions of border-radius and adds border-top-radius, * border-bottom-radius, border-left-radius and border-right-radius * For IE, only general radius works. And make sure, border-radius declaration * comes before any (box-)shadow-declaration in CSS-code! * * Usage: border-radius[-top/-bottom/-left/-right/-top-left/...]: value; * Example 1: border-top-radius:4px; * Example 2: border-bottom-left-radius:2em; * Status: Stable * Version: 1.1 * * @param mixed &$parsed * @return void */ function borderradius(&$parsed) { global $cssp; foreach ($parsed as $block => $css) { foreach ($parsed[$block] as $selector => $styles) { foreach ($styles as $property => $values) { if (preg_match('/border(?:-(top|right|bottom|left)(?:-(right|left))*)*-radius/', $property, $matches)) { // Create the new rules and insert them $borderradius_rules = borderradius_glue_rules($matches, $values); $cssp->insert_properties($borderradius_rules, $block, $selector, null, $property); // Comment the newly inserted properties foreach ($borderradius_rules as $border_property => $border_value) { CSSP::comment($parsed[$block][$selector], $border_property, 'Added by border radius plugin'); } // Remove Top/Left/Bottom/Right shortcuts if (count($matches) == 2) { unset($parsed[$block][$selector][$property]); } } } } } }
/** * background gradient * creates a cross-browser linear vertical or horizontal background gradient (other angles or radial gradient not supported) * Adds vendor-specific code for gradients * * Usage: Use simplest possible notation as planned by W3C: http://dev.w3.org/csswg/css3-images/#linear-gradients * background: linear-gradient([direction:<top|left>],[startcolor<hex|rgb|rgba>],[endcolor<hex|rgb|rgba>]) * * Example 1: background: linear-gradient(top,#FFF,#000) // vertical gradient, from top to bottom, from white to black * Example 2: background-image: linear-gradient(left,rgb(255,255,255),rgb(0,0,0)) // horizontal gradient, from left to right, from white to black * Status: Stable * Version: 2.0 * * * backgroundgradient * @param mixed &$parsed * @return void */ function backgroundgradient(&$parsed) { global $cssp, $browser; include 'lib/utility.php'; $settings = Plugin::get_settings('backgroundgradient'); // Searches for W3C-style two-stepped linear gradient $gradientregex = '/linear-gradient\\s*?\\(\\s*?(top|left)\\s*?,\\s*(\\#[0-9A-F]+|(?:rgb|hsl)(?:a)*\\s*\\(.+\\)),\\s*(.*)\\s*\\)/i'; // In which properties to search $urlproperties = array('background', 'background-image'); // Loop through the array foreach ($parsed as $block => $css) { foreach ($parsed[$block] as $selector => $styles) { foreach ($urlproperties as $property) { if (isset($parsed[$block][$selector][$property])) { $num_values = count($parsed[$block][$selector][$property]); for ($i = 0; $i < $num_values; $i++) { if (preg_match($gradientregex, $parsed[$block][$selector][$property][$i], $matches) > 0) { // Recalculate the matched colors to rgba for maximum compatibility $matches[2] = Utility::rgbasyntax(Utility::any2rgba($matches[2])); $matches[3] = Utility::rgbasyntax(Utility::any2rgba($matches[3])); // Gecko $parsed[$block][$selector][$property][] = preg_replace($gradientregex, '-moz-linear-gradient(' . $matches[1] . ',' . $matches[2] . ',' . $matches[3] . ')', $parsed[$block][$selector][$property][$i]); // Webkit and KHTML if (strtolower($matches[1]) == 'top') { $webkit_gradientdirection = 'left top,left bottom'; } else { $webkit_gradientdirection = 'left top,right top'; } $parsed[$block][$selector][$property][] = preg_replace($gradientregex, '-webkit-gradient(linear,' . $webkit_gradientdirection . ',from(' . $matches[2] . '),to(' . $matches[3] . '))', $parsed[$block][$selector][$property][$i]); $parsed[$block][$selector][$property][] = preg_replace($gradientregex, '-khtml-gradient(linear,' . $webkit_gradientdirection . ',from(' . $matches[2] . '),to(' . $matches[3] . '))', $parsed[$block][$selector][$property][$i]); // Use a SVG background for Opera if ($browser->engine == 'opera') { $svg_path = rtrim(dirname($_SERVER['SCRIPT_NAME']), '/') . '/plugins/backgroundgradient/svg.php'; $svg_params = 'direction=' . strtolower($matches[1]); $svg_params .= '&startcolor=' . urlencode($matches[2]); $svg_params .= '&endcolor=' . urlencode($matches[3]); $parsed[$block][$selector][$property][] = preg_replace($gradientregex, 'url(' . $svg_path . '?' . $svg_params . ')', $parsed[$block][$selector][$property][$i]); } // Add comment for the background property CSSP::comment($parsed[$block][$selector], $property, 'Modified by background-gradient plugin'); // Use filter fallbacks in IE if (!in_array('noie', $settings)) { $filter_properties = array(); if (strtolower($matches[1]) == 'top') { $ie_gradienttype = '0'; } else { $ie_gradienttype = '1'; } // Convert colors to hex $matches[2] = Utility::hexsyntax(Utility::any2rgba($matches[2]), true); $matches[3] = Utility::hexsyntax(Utility::any2rgba($matches[3]), true); // Build filter $filter = 'progid:DXImageTransform.Microsoft.gradient(startColorstr=' . $matches[2] . ',endColorstr=' . $matches[3] . ',gradientType=' . $ie_gradienttype . ')'; // Legacy IE compliance $filter_properties['filter'] = array($filter); // IE8 compliance $filter_properties['-ms-filter'] = array($filter); // Salvage any background information that is NOT gradient stuff and preserve it in a form IE can handle $background_rest = preg_replace('/(-moz-|-webkit-|-khtml-)*linear-gradient\\s*?\\(\\s*?(top|left)\\s*?,\\s*(\\#[0-9A-F]+|(?:rgb|hsl)(?:a)*\\s*\\(.+\\)),\\s*(.*)\\s*\\)/i', '', $parsed[$block][$selector][$property][$i]); $background_rest = trim($background_rest); if ($background_rest != '') { $filter_properties['*background'] = array($background_rest); // IE7 and 6 $filter_properties['background /*\\**/'] = array($background_rest . '\\9'); // IE8 } // hasLayout stuff $filter_properties['zoom'] = array('1'); // Insert all filters $cssp->insert_properties($filter_properties, $block, $selector, NULL, $property); foreach ($filter_properties as $filter_property => $filter_value) { CSSP::comment($parsed[$block][$selector], $filter_property, 'Modified by background-gradient plugin'); } } // End if(!in_array('noie', $settings)) // Remove the original value unset($parsed[$block][$selector][$property][$i]); } } } } } } }
/** * Easy and extended transform * Adds vendor-specific versions of transform * * Usage: Use any currently known transform-property wihtout vendor-prefixes, * BUT NOT YET! transform-origin. * For IE you need to define width and height dimensions and use the same units (px/em) * for dimensions and translation * Example 1: width: 100px; height: 100px; transform: translate(2px, 2px); * Example 1: width: 20em; height: 20em; transform: translate(1em, 2em); * Example 3: width: 100px; height: 100px; transform: translate(2px, 2px) rotate(90deg); * Example 4:width: 100px; height: 100px; transform: skew(15deg,25deg); * Status: Beta * Version: 1.0 * * @param mixed &$parsed * @return void */ function transform(&$parsed) { global $browser, $cssp; foreach ($parsed as $block => $css) { foreach ($parsed[$block] as $selector => $styles) { $width = 0; $height = 0; $width_unit = 'px'; $height_unit = 'px'; $rotate_x = 0; $rotate_y = 0; $translate_x = 0; $translate_y = 0; $translate_x_unit = 'px'; $translate_y_unit = 'px'; $scale_x = 1; $scale_y = 1; $rotate_before_translate = false; $scale_before_translate = false; if (isset($parsed[$block][$selector]['transform'])) { // Creating good browser CSS if ($browser->engine != 'ie' || floatval($browser->engine_version) >= 9) { $num_values = count($parsed[$block][$selector]['transform']); for ($i = 0; $i < $num_values; $i++) { $value = $parsed[$block][$selector]['transform'][$i]; $newproperties = array('-moz-transform' => array($value), '-o-transform' => array($value), '-webkit-transform' => array($value)); $cssp->insert_properties($newproperties, $block, $selector, null, 'transform'); } } // Applying the matrix-filter for IE if ($browser->engine == 'ie' && floatval($browser->engine_version) < 9) { // If we have width & height defined, the replicate transforms with the help of IE's matrix-filter if (isset($parsed[$block][$selector]['width'][0]) && isset($parsed[$block][$selector]['height'][0])) { $values = explode(' ', implode(' ', $parsed[$block][$selector]['transform'])); $num_values = count($values); for ($i = 0; $i < $num_values; $i++) { $value = $values[$i]; // If we are dealing with a matrix-transformation if (preg_match('/matrix\\(\\D*([0-9\\-]+)\\s([0-9\\-]+)\\s([0-9\\-]+)\\s([0-9\\-]+)\\s([0-9\\-]+)\\s([0-9\\-]+)\\D*\\)/i', $value, $matches) == 1) { $matrix_a = $matches[1]; $matrix_b = $matches[2]; $matrix_c = $matches[3]; $matrix_d = $matches[4]; } else { // If we are dealing with a rotation if (preg_match('/rotate\\(\\D*([0-9\\-\\.]+)(deg|rad|grad)\\D*\\)/i', $value, $matches) == 1) { $rotate_x = $matches[1]; $rotate_x_unit = $matches[2]; $rotate_y = $matches[1]; $rotate_y_unit = $matches[2]; } // If we are dealing with a scaling on the X-axis if (preg_match('/scaleX\\(\\D*([0-9\\.]+)\\D*\\)/i', $value, $matches) == 1) { $scale_x = $matches[1]; } // If we are dealing with a scaling on the Y-axis if (preg_match('/scaleY\\(\\D*([0-9\\.]+)\\D*\\)/i', $value, $matches) == 1) { $scale_y = $matches[1]; } // If we are dealing with a scaling on both axis if (preg_match('/scale\\(\\D*([0-9\\.]+)\\D*\\)/i', $value, $matches) == 1) { $scale_x = $matches[1]; $scale_y = $matches[1]; } // If we are dealing with a skew-transform on the X-axis if (preg_match('/skewX*\\(\\D*([0-9\\-\\.]+)(deg|rad|grad)\\D*\\)/i', $value, $matches) == 1) { $rotate_x = $matches[1] * -1; $rotate_x_unit = $matches[2]; } // If we are dealing with a skew-transform on the Y-axis if (preg_match('/skewY\\(\\D*([0-9\\-\\.]+)(deg|rad|grad)\\D*\\)/i', $value, $matches) == 1) { $rotate_y = $matches[1] * -1; $rotate_y_unit = $matches[4]; } // If we are dealing with a skew-transform on the both axis if (preg_match('/skew\\(\\D*([0-9\\-\\.]+)(deg|rad|grad)\\D*,\\D*([0-9\\-\\.]+)(deg|rad|grad)\\D*\\)/i', $value, $matches) == 1) { $rotate_x = $matches[1] * -1; $rotate_x_unit = $matches[2]; $rotate_y = $matches[3] * -1; $rotate_y_unit = $matches[4]; } // If we are dealing with a translation if (preg_match('/translate\\(\\D*([0-9\\.\\-]+)([a-z%]*),\\s*([0-9\\.\\-]+)([a-z%]*)\\D*\\)/i', $value, $matches) == 1) { $translate_x = $matches[1]; if ($matches[2] != '') { $translate_x_unit = $matches[2]; } if ($matches[3] != '') { $translate_y = $matches[3]; } if ($matches[4] != '') { $translate_y_unit = $matches[4]; } if ($rotate_x != 0 || $rotate_y != 0) { $rotate_before_translate = true; } if ($scale_x != 1 || $scale_y != 1) { $scale_before_translate = true; } } } } // Convert translation, rotation, scale and skew into matrix values if ($rotate_x_unit == 'deg') { $radian_x = deg2rad(floatval($rotate_x)); } if ($rotate_x_unit == 'rad') { $radian_x = floatval($rotate_x); } if ($rotate_x_unit == 'grad') { $radian_x = deg2rad(floatval($rotate_x) / 400 * 360); } if ($rotate_y_unit == 'deg') { $radian_y = deg2rad(floatval($rotate_y)); } if ($rotate_y_unit == 'rad') { $radian_y = floatval($rotate_y); } if ($rotate_y_unit == 'grad') { $radian_y = deg2rad(floatval($rotate_y) / 400 * 360); } $matrix_a = floatval(number_format(cos($radian_x), 8, '.', '')); $matrix_b = -1 * floatval(number_format(sin($radian_x), 8, '.', '')); $matrix_c = floatval(number_format(sin($radian_y), 8, '.', '')); $matrix_d = floatval(number_format(cos($radian_y), 8, '.', '')); $filter = 'progid:DXImageTransform.Microsoft.Matrix(Dx=1.0,Dy=1.0,M11=' . $matrix_a * floatval($scale_x) . ',M12=' . $matrix_b * floatval($scale_x) . ',M21=' . $matrix_c * floatval($scale_y) . ',M22=' . $matrix_d * floatval($scale_y) . ',sizingMethod=\'auto expand\')'; // Adjust transforms for IEs, needs to come in first $newproperties = array(); // If position-property is not set, or static set it if (!isset($parsed[$block][$selector]['position']) || $parsed[$block][$selector]['position'][0] == 'static') { $newproperties['position'] = array('relative'); $cssp->insert_properties($newproperties, $block, $selector, null, 'transform'); CSSP::comment($parsed[$block][$selector], 'position', 'Added by transform plugin'); } //Include behavior to compansate for IEs auto expand feature $htc_path = rtrim(dirname($_SERVER['SCRIPT_NAME']), '/') . '/plugins/transform/transform.htc'; $parsed[$block][$selector]['behavior'] = array('url(' . $htc_path . ')'); CSSP::comment($parsed[$block][$selector], 'behavior', 'Added by transform plugin'); //Legacy IE-compliance if (floatval($browser->engine_version) < 8) { //If filter-property not yet set if (!isset($parsed[$block][$selector]['filter'])) { $parsed[$block][$selector]['filter'] = array($filter); } else { //Needs its filter-value to be put in first place! array_unshift($parsed[$block][$selector]['filter'], $filter); } CSSP::comment($parsed[$block][$selector], 'filter', 'Added by transform plugin'); } else { //IE8-compliance (note: value inside apostrophes!) //If -ms-filter-property not yet set if (!isset($parsed[$block][$selector]['-ms-filter'])) { $parsed[$block][$selector]['-ms-filter'] = array($filter); } else { //Needs its filter-value to be put in first place! array_unshift($parsed[$block][$selector]['-ms-filter'], $filter); } CSSP::comment($parsed[$block][$selector], '-ms-filter', 'Added by transform plugin'); } //Set hasLayout $parsed[$block][$selector]['zoom'] = array('1'); CSSP::comment($parsed[$block][$selector], 'zoom', 'Added by transform plugin'); $newproperties = array(); // Adjust translation to scaling if ($scale_before_translate) { $translate_x = $translate_x * floatval($scale_x); $translate_y = $translate_y * floatval($scale_y); } // Adjust translation to rotation if ($rotate_before_translate) { $translate_x = $translate_x * cos($radian_x) + $translate_y * sin($radian_y); $translate_y = $translate_x * sin($radian_x) + $translate_y * cos($radian_y); } if ($translate_x_unit == 'px') { $translate_x = round($translate_x); } if ($translate_y_unit == 'px') { $translate_y = round($translate_y); } // If position-property is not set, or not set to absolute if ($parsed[$block][$selector]['position'][0] != 'absolute') { // Translation on x-axis if ($translate_x > 0 && !isset($parsed[$block][$selector]['left'])) { $newproperties['left'] = array($translate_x . $translate_x_unit); CSSP::comment($parsed[$block][$selector], 'left', 'Added by transform plugin'); } elseif ($translate_x < 0 && !isset($parsed[$block][$selector]['right'])) { $newproperties['right'] = array(abs($translate_x) . $translate_x_unit); CSSP::comment($parsed[$block][$selector], 'right', 'Added by transform plugin'); } elseif ($translate_x != 0 && !isset($parsed[$block][$selector]['margin-left']) && !isset($parsed[$block][$selector]['margin-right'])) { $newproperties['margin-left'] = array($translate_x . $translate_x_unit); CSSP::comment($parsed[$block][$selector], 'margin-left', 'Added by transform plugin'); $newproperties['margin-right'] = array(-1 * $translate_x . $translate_x_unit); CSSP::comment($parsed[$block][$selector], 'margin-right', 'Added by transform plugin'); } // Translation on y-axis if ($translate_y > 0 && !isset($parsed[$block][$selector]['top'])) { $newproperties['top'] = array($translate_y . $translate_y_unit); CSSP::comment($parsed[$block][$selector], 'top', 'Added by transform plugin'); } elseif ($translate_y < 0 && !isset($parsed[$block][$selector]['bottom'])) { $newproperties['bottom'] = array(abs($translate_y) . $translate_y_unit); CSSP::comment($parsed[$block][$selector], 'bottom', 'Added by transform plugin'); } elseif ($translate_y != 0 && !isset($parsed[$block][$selector]['margin-left']) && !isset($parsed[$block][$selector]['margin-right'])) { $newproperties['margin-top'] = array($translate_y . $translate_y_unit); CSSP::comment($parsed[$block][$selector], 'margin-top', 'Added by transform plugin'); $newproperties['margin-bottom'] = array(-1 * $translate_y . $translate_y_unit); CSSP::comment($parsed[$block][$selector], 'margin-bottom', 'Added by transform plugin'); } } else { if ($translate_x != 0 && !isset($parsed[$block][$selector]['margin-left']) && !isset($parsed[$block][$selector]['margin-right'])) { $newproperties['margin-left'] = array($translate_x . $translate_x_unit); CSSP::comment($parsed[$block][$selector], 'margin-left', 'Added by transform plugin'); $newproperties['margin-right'] = array(-1 * $translate_x . $translate_x_unit); CSSP::comment($parsed[$block][$selector], 'margin-right', 'Added by transform plugin'); } if ($translate_y != 0 && !isset($parsed[$block][$selector]['margin-left']) && !isset($parsed[$block][$selector]['margin-right'])) { $newproperties['margin-top'] = array($translate_y . $translate_y_unit); CSSP::comment($parsed[$block][$selector], 'margin-top', 'Added by transform plugin'); $newproperties['margin-bottom'] = array(-1 * $translate_y . $translate_y_unit); CSSP::comment($parsed[$block][$selector], 'margin-bottom', 'Added by transform plugin'); } } $cssp->insert_properties($newproperties, $block, $selector, 'transform', null); } } } } } }
/** * apply_inheritance * Applies inheritance to the stylesheet * @return void */ public function apply_inheritance() { foreach ($this->parsed as $block => $css) { foreach ($this->parsed[$block] as $selector => $styles) { // Full inheritance if (isset($this->parsed[$block][$selector]['extends'])) { $num_extends = count($this->parsed[$block][$selector]['extends']); for ($i = 0; $i < $num_extends; $i++) { $found = false; // Parse ancestors $ancestors = $this->tokenize($this->parsed[$block][$selector]['extends'][$i], array('"', "'", ',')); // List to keep track of all the ancestor's selectors for debugging comment $ancestors_list = array(); // First merge all the ancestor's rules into one... $ancestors_rules = array(); foreach ($ancestors as $ancestor) { // Find ancestors $ancestor_keys = $this->find_ancestor_keys($ancestor, $block); // Add ancestors to the list $ancestors_list = array_merge($ancestors_list, $ancestor_keys); // Merge ancestor's rules with own rules if (!empty($ancestor_keys)) { $found = true; foreach ($ancestor_keys as $ancestor_key) { $ancestors_rules = $this->merge_rules($ancestors_rules, $this->parsed[$block][$ancestor_key], array(), true); } } } // ... then merge the combined ancestor's rules into $parsed $this->parsed[$block][$selector] = $this->merge_rules($this->parsed[$block][$selector], $ancestors_rules, array(), false); // Report error if no ancestor was found if (!$found) { $this->report_error($selector . ' could not find ' . $this->parsed[$block][$selector]['extends'][$i] . ' to inherit properties from.'); } else { CSSP::comment($this->parsed[$block][$selector], null, 'Inherited properties from: "' . implode('", "', $ancestors_list) . '"'); } } // Unset the extends property unset($this->parsed[$block][$selector]['extends']); } } } }
/** * Automatic @font-face syntax * * Usage: * 1) Add fontface to @turbine plugin list * 2) Put all different font-files into one directory and give them the same basename, * e.g. "SaginaMedium": * SaginawMedium.eot * SaginawMedium.woff * SaginawMedium.otf * SaginawMedium.ttf * SaginawMedium.svg * 3) Build a special @font-face-rule with a single src-property pointing not to a real * file but to that common basename, e.g. "src:url('fonts/SaginawMedium')" * 4) The plugin will look after any known fontfile format by appending the suffixes * .eot, .woff, .otf, .ttf and .svg. * For IE <= 8 it will serve the .eot if there is a corresponding file. * For the other browser it will serve as many of the other flavors as available. * A truetype-file will only be served when there is no opentype-file available. * * Example: * @font-face * font-family:'SaginawMedium' * src:url('fonts/SaginawMedium') * font-weight:bold * font-style:italic * * Result for IE <= 8: * @font-face { * font-family: 'SaginawMedium'; * src: url("fonts/SaginawMedium.eot"); * font-weight: bold; * font-style: italic; * } * * Result for all other browsers: * @font-face { * font-family: 'SaginawMedium'; * src: url("fonts/SaginawMedium.woff") format("woff"),url("fonts/SaginawMedium.ttf") format("truetype"),url("fonts/SaginawMedium.svg#SaginawMedium") format("svg"); * font-weight: bold; * font-style: italic; * } * * Status: Stable * Version: 1.1 * * @todo Include a fix for webkit? http://paulirish.com/2010/font-face-gotchas/ * @param mixed &$parsed * @return void */ function fontface(&$parsed) { global $browser; $basedirectory = str_replace('\\', '/', dirname(realpath($_SERVER['SCRIPT_FILENAME']))); foreach ($parsed as $block => $css) { if (isset($parsed[$block]['@font-face'])) { foreach ($parsed[$block]['@font-face'] as $key => $font) { // Check if user has set required src-property if (isset($font['src'])) { $num_src = count($font['src']); for ($i = 0; $i < $num_src; $i++) { // Extract common basename for all files $fontfile_base = preg_replace('/url\\([\'"]*([^\'"]+)[\'"]*\\)/i', '$1', $font['src'][$i]); // Create new src-property storage $newfont = ''; $message = ''; // If we are dealing with IE <= 8 then check for EOT only if ($browser->engine == 'ie' && floatval($browser->engine_version) <= 8) { $fontfile_eot = $fontfile_base . '.eot'; // If there exists an EOT-file point to it if (file_exists($basedirectory . '/' . $fontfile_eot)) { $newfont .= 'url("' . $fontfile_eot . '")'; } else { $message .= 'Missing ' . $fontfile_eot . '-file,'; } } else { $fontfile_woff = $fontfile_base . '.woff'; $fontfile_otf = $fontfile_base . '.otf'; $fontfile_ttf = $fontfile_base . '.ttf'; $fontfile_svg = $fontfile_base . '.svg'; // If there exists an WOFF-file enqueue it if (file_exists($basedirectory . '/' . $fontfile_woff)) { $newfont .= 'url("' . $fontfile_woff . '") format("woff"),'; } else { $message .= 'Missing ' . $fontfile_woff . '-file,'; } // If there exists an OTF-file enqueue it if (file_exists($basedirectory . '/' . $fontfile_otf)) { $newfont .= 'url("' . $fontfile_otf . '") format("opentype"),'; } elseif (file_exists($basedirectory . '/' . $fontfile_ttf)) { $newfont .= 'url("' . $fontfile_ttf . '") format("truetype"),'; $message .= 'Missing ' . $fontfile_otf . '-file,'; } else { $message .= 'Missing ' . $fontfile_otf . '-file,Missing ' . $fontfile_ttf . '-file,'; } // If there exists an SVG-file enqueue it if (file_exists($basedirectory . '/' . $fontfile_svg)) { $newfont .= 'url("' . $fontfile_svg . '#' . basename($fontfile_base) . '") format("svg"),'; } else { $message .= 'Missing ' . $fontfile_svg . '-file,'; } } // If we found at least one font replace old src-property with new one if ($newfont != '') { $parsed[$block]['@font-face'][$key]['src'][$i] = trim($newfont, ', '); } if ($message != '') { CSSP::comment($parsed[$block]['@font-face'][$key], 'src', trim($message, ', ')); } } } } } } }
/** * background gradient * creates a cross-browser linear vertical or horizontal background gradient (other angles or radial gradient not supported) * Adds vendor-specific code for gradients * * Usage: Use simplest possible notation as planned by W3C: http://dev.w3.org/csswg/css3-images/#linear-gradients * background: linear-gradient([direction:<top|left>],[startcolor<hex|rgb|rgba>],[endcolor<hex|rgb|rgba>]) * * Example 1: background: linear-gradient(top,#FFF,#000) // vertical gradient, from top to bottom, from white to black * Example 2: background-image: linear-gradient(left,rgb(255,255,255),rgb(0,0,0)) // horizontal gradient, from left to right, from white to black * Status: Stable * Version: 2.0 * * * backgroundgradient * @param mixed &$parsed * @return void */ function backgroundgradient(&$parsed) { global $cssp, $browser; include 'lib/utility.php'; $settings = Plugin::get_settings('backgroundgradient'); // Searches for W3C-style two-stepped linear gradient $gradientregex = '/linear-gradient\\s*?\\(\\s*?(top|left)\\s*?,\\s*(\\#[0-9A-F]+|(?:rgb|hsl)(?:a)*\\s*\\(.+\\)),\\s*(.*)\\s*\\)/i'; // In which properties to search $urlproperties = array('background', 'background-image'); // Loop through the array foreach ($parsed as $block => $css) { foreach ($parsed[$block] as $selector => $styles) { foreach ($urlproperties as $property) { if (isset($parsed[$block][$selector][$property])) { $num_values = count($parsed[$block][$selector][$property]); for ($i = 0; $i < $num_values; $i++) { if (preg_match($gradientregex, $parsed[$block][$selector][$property][$i], $matches) > 0) { // Recalculate the matched colors to rgba for maximum compatibility $matches[2] = Utility::rgbasyntax(Utility::any2rgba($matches[2])); $matches[3] = Utility::rgbasyntax(Utility::any2rgba($matches[3])); // Gecko $parsed[$block][$selector][$property][] = preg_replace($gradientregex, '-moz-linear-gradient(' . $matches[1] . ',' . $matches[2] . ',' . $matches[3] . ')', $parsed[$block][$selector][$property][$i]); // Webkit and KHTML if (strtolower($matches[1]) == 'top') { $webkit_gradientdirection = 'left top,left bottom'; } else { $webkit_gradientdirection = 'left top,right top'; } $parsed[$block][$selector][$property][] = preg_replace($gradientregex, '-webkit-gradient(linear,' . $webkit_gradientdirection . ',from(' . $matches[2] . '),to(' . $matches[3] . '))', $parsed[$block][$selector][$property][$i]); $parsed[$block][$selector][$property][] = preg_replace($gradientregex, '-khtml-gradient(linear,' . $webkit_gradientdirection . ',from(' . $matches[2] . '),to(' . $matches[3] . '))', $parsed[$block][$selector][$property][$i]); // Use a SVG background for Opera if ($browser->engine == 'opera') { $svg_path = rtrim(dirname($_SERVER['SCRIPT_NAME']), '/') . '/plugins/backgroundgradient/svg.php'; $svg_params = 'direction=' . strtolower($matches[1]); $svg_params .= '&startcolor=' . urlencode($matches[2]); $svg_params .= '&endcolor=' . urlencode($matches[3]); $parsed[$block][$selector][$property][] = preg_replace($gradientregex, 'url(' . $svg_path . '?' . $svg_params . ')', $parsed[$block][$selector][$property][$i]); } // Add comment for the background property CSSP::comment($parsed[$block][$selector], $property, 'Modified by background-gradient plugin'); // Use filter fallbacks in IE if (!in_array('noie', $settings)) { $filter_properties = array(); if (strtolower($matches[1]) == 'top') { $ie_gradienttype = '0'; } else { $ie_gradienttype = '1'; } // Convert colors to hex $matches[2] = Utility::hexsyntax(Utility::any2rgba($matches[2]), true); $matches[3] = Utility::hexsyntax(Utility::any2rgba($matches[3]), true); // Build filter $filter = 'progid:DXImageTransform.Microsoft.gradient(startColorstr=' . $matches[2] . ',endColorstr=' . $matches[3] . ',gradientType=' . $ie_gradienttype . ')'; // Legacy IE compliance $filter_properties['filter'] = array($filter); // IE8 compliance $filter_properties['-ms-filter'] = array($filter); // Salvage any background information that is NOT gradient stuff and preserve it in a form IE can handle $background_rest = preg_replace('/(-moz-|-webkit-|-khtml-)*linear-gradient\\s*?\\(\\s*?(top|left)\\s*?,\\s*(\\#[0-9A-F]+|(?:rgb|hsl)(?:a)*\\s*\\(.+\\)),\\s*(.*)\\s*\\)/i', '', $parsed[$block][$selector][$property][$i]); $background_rest = trim($background_rest); if ($background_rest != '') { $filter_properties['*background'] = array($background_rest); // IE7 and 6 $filter_properties['background /*\\**/'] = array($background_rest . '\\9'); // IE8 } // hasLayout stuff $filter_properties['zoom'] = array('1'); // Insert all filters $cssp->insert_properties($filter_properties, $block, $selector, NULL, $property); foreach ($filter_properties as $filter_property => $filter_value) { CSSP::comment($parsed[$block][$selector], $filter_property, 'Modified by background-gradient plugin'); } } // End if(!in_array('noie', $settings)) // Remove the original value unset($parsed[$block][$selector][$property][$i]); } else { /*.............................=MMMMMMMMMMMMMMMM,............................... ............................ MMMMMMMMMMMMMMMMMMMMMM............................. ...........................MMMMMMMMMMMMMMMMMMMMMMMMMM... . . .... .. .. .. .. ................. ... ...IMMMMMMMMMMMMMMMMMMMMMMMMMMMM . . .... . .. . . ............ .... ...8MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM. . . . . . ............ ... ...NMMMM.MMMMMMMMMMMMMMMMMMMMMMMMMMM .. . .. . ............ ..........MMMM.IMMMMMMMMMMMMMMMMMMMMMMMMMMM ........ . . ..... .. ............ . =MMM..MMMMMMMMMMMMMMMMMMMMMMMMMMMMM .. . . .. . . ............ . .. ZMM:.MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM. . ...... .. ..... ... ............ . ZMM.=MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM . .. . ........... . .. ZMM.MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM ... ... . ............ . .. .ZMM MMMM .....MMMMMMM .....MMMMMMMM ... .... . ... . . . ............ .. ~MM.MMM........MMMMM .. . .MMM MM8 . .. . . .. . ............ . MM.MM8........MMMMM ..... MMM MM. . . .. . ... . .. . ... . .............M.MM+ . ZMMMMMM . . 7MM M= . . ..... . . .. ... .. ......... MMN ..8MMM MMMM ... MMM.. . . ... . . .. .... . ............. MMMMMD .MMMMM..MMMMMO ?MMMMM$ ........................ ........ .............MMMMMMMMMMMMMMM. .MMMMMMMMMMMMMMM..................... . ... . .. ..............MMMMMMMMMMMMM....MMMMMMMMMMMMMM,........................ ..........................MMMMMMMMMMM.NM.MMMMMMMMMMMM.... . . ..... .. .. ... .... . .. ................ .MMMMMMMMMMMMMMMMMMMMM. ............................ .... ................... ... . :MMMMMMMMMMMMMMMM .......... ........ ..... ..... .... . . ................ MZ ,MMMMMMMMMMMMM8. $M............. ..... ..... .. ...... . +M=................MMM .. . . . ..MMM ............................ .... . MMMMMM............ . MMM$ .M=DM=M.M M.. MMMM .... ... ......MM~. ... ... . . 7MMMMMMMM$......... .. MMMM .. :,. ,.. ..MMMM .. . . . .MMMMMMM. . .. ...MMMMMMMMMMMMD........... MMMM . ... . .. .ZMMM~...... . . . MMMMMMMMM . ... .MMMMMMMMMMMMMMMM...........:MMMN.M OO$M..M.. MMMM............. MMMMMMMMMMM..... MMMMMMMMMMMMMMMMMMN..... .. NMMMM ...M. ? +MMMM+ ...........NMMMMMMMMMMMMMM7.. MMMMMMMM.MMMMMMMMMMM+.........NMMMMMMMMMMMMMMMMM............:MMMMMMMMMMMMMMMMMD MMMMMMMM .~MMMMMMMMMMMM ... ....MMMMMMMMMMMMMMM ........ .MMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMI =MMMMMMMMMMM...... NMMMMMMMMMMMO... .. ZMMMMMMMMMMMMMM,MMMMMMMM= ..8MMMMMMMMMMMMMMMMMMMMMMM. ................... MMMMMMMMMMMMM. ,MMMMMMMMMMM . .........$MMMMMMMMMMMMMMMMMM8 ............. ~MMMMMMMMMMMMMMMMMMMMMMMMMMM8... . ........... MMMMMMMMMMMMMMMMM?..........ZMMMMMMMMMMMMMMMMMMMMMI. ......... . ......... ......MMMMMMMMMMMMMMMM. . .MMMMMMMMMMMMMMMMMMM~........ ......... .... ..... ... ... =MMMMMMMMMMMMMMM. MMMMMMMMMMMMMMZ ..................... . ........................ NMMMMMMMMMMMMMM.+MMMMMMM+. ......................... . .. ... .... .. .. DMMMMMMMMMMMMM7.O+...................... .. .... ........... . ......... ...~MMMN OMMMMMMMMMMMMM, .... . ......... .. . . ... ... ................... DMMMMMMMMM, MMMMMMMMMMMMMM........ ............ ....... .... ................NMMMMMMMMMMMMMMMM. MMMMMMMMMMMMMM..... . .......... . ..... . MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM...... .MMMMMMMMMMMMMMM .................... MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM. ........... ,MMMMMMMMMMMMMMMMMMMMMMMN8+ ...... MMMMMDNMMMMMMMMMMMMMMMMMMMMZ.................. .:MMMMMMMMMMMMMMMMMMMMMMMMMMM ... MMMMMMMMMMMMMMMMMMMMMMMM ...................... .. MMMMM.$MMMMMMMMMMMM=MMMMM .. .MMMMMMMDMMMMMMMMMMM ... . .... . ... ..... . ... .. ZMMMN:MMMMMMMMMMMMMMMM... ....=MMMM.MMOMMMMMM ..... ... .. .... . .. . . . .... NMMM~7MMMMMMMMMMMMMN... .....MMMMMMMMMMM+..........................................MMMM~IMMMMMMMNM, .... ......MMMMMMMM ............................................. MMMMMZMMMM,........ . . .......... ................................ ............. MMMMMMM........*/ // This is f*****g ugly, but must be done to keep things sane for css developers. In order to have background // declarations that don't contain any gradient _remove_ gradients that the element may have inherited, // we have to explicitly add disabled filters for IE - always. So in the end what this does is adding three // lines of css code for every background property as long as it doesn't add a gradient. Talk about bloated // code... but hey, blame the IE team for their f****d up browsers, not us... if (!in_array('noie', $settings)) { $filter_properties = array(); $filter = 'progid:DXImageTransform.Microsoft.gradient(enabled:false)'; $filter_properties['zoom'] = array('1'); $filter_properties['filter'] = array($filter); $filter_properties['-ms-filter'] = array($filter); $cssp->insert_properties($filter_properties, $block, $selector, NULL, $property); foreach ($filter_properties as $filter_property => $filter_value) { CSSP::comment($parsed[$block][$selector], $filter_property, 'Modified by background-gradient plugin'); } } } } } } } } }
/** * background gradient * creates a cross-browser linear vertical or horizontal background gradient (other angles or radial gradient not supported) * Adds vendor-specific code for gradients * * Usage: Use simplest possible notation as planned by W3C: http://dev.w3.org/csswg/css3-images/#linear-gradients * background: linear-gradient([direction:<top|left>],[startcolor<hex|rgb|rgba>],[endcolor<hex|rgb|rgba>]) * * Example 1: background: linear-gradient(top,#FFF,#000) // vertical gradient, from top to bottom, from white to black * Example 2: background-image: linear-gradient(left,rgb(255,255,255),rgb(0,0,0)) // horizontal gradient, from left to right, from white to black * Status: Beta * Version: 1.0 * * * backgroundgradient * @param mixed &$parsed * @return void */ function backgroundgradient(&$parsed) { global $cssp, $browser; // Searches for W3C-style two-stepped linear gradient $urlregex = '/linear-gradient\\s*\\(\\s*(top|left)\\s*,\\s*(#[0-9A-F]+|rgba*\\([0-9,]+\\))\\s*,\\s*(#[0-9A-F]+|rgba*\\([0-9,]+\\))\\s*\\)/i'; // In which properties to searcg $urlproperties = array('background', 'background-image'); // Loop through the array foreach ($parsed as $block => $css) { foreach ($parsed[$block] as $selector => $styles) { foreach ($urlproperties as $property) { if (isset($parsed[$block][$selector][$property])) { $num_values = count($parsed[$block][$selector][$property]); for ($i = 0; $i < $num_values; $i++) { if (preg_match($urlregex, $parsed[$block][$selector][$property][$i], $matches) > 0) { switch ($browser->engine) { // Gecko case 'gecko': $parsed[$block][$selector][$property][$i] = preg_replace($urlregex, '-moz-linear-gradient(' . $matches[1] . ',' . $matches[2] . ',' . $matches[3] . ')', $parsed[$block][$selector][$property][$i]); CSSP::comment($parsed[$block][$selector], $property, 'Modified by background-gradient plugin'); break; // Webkit // Webkit case 'webkit': if (strtolower($matches[1]) == 'top') { $webkit_gradientdirection = 'left top,left bottom'; } else { $webkit_gradientdirection = 'left top,right top'; } $parsed[$block][$selector][$property][$i] = preg_replace($urlregex, '-webkit-gradient(linear,' . $webkit_gradientdirection . ',from(' . $matches[2] . '),to(' . $matches[3] . '))', $parsed[$block][$selector][$property][$i]); CSSP::comment($parsed[$block][$selector], $property, 'Modified by background-gradient plugin'); break; // Konqueror // Konqueror case 'khtml': if (strtolower($matches[1]) == 'top') { $webkit_gradientdirection = 'left top,left bottom'; } else { $webkit_gradientdirection = 'left top,right top'; } $parsed[$block][$selector][$property][$i] = preg_replace($urlregex, '-khtml-gradient(linear,' . $webkit_gradientdirection . ',from(' . $matches[2] . '),to(' . $matches[3] . '))', $parsed[$block][$selector][$property][$i]); CSSP::comment($parsed[$block][$selector], $property, 'Modified by background-gradient plugin'); break; // Opera // Opera case 'opera': $svg_path = rtrim(dirname($_SERVER['SCRIPT_NAME']), '/') . '/plugins/backgroundgradient/svg.php'; $svg_params = 'direction=' . strtolower($matches[1]); $svg_params .= '&startcolor=' . str_replace('#', '%23', strtolower($matches[2])); $svg_params .= '&endcolor=' . str_replace('#', '%23', strtolower($matches[3])); $parsed[$block][$selector][$property][$i] = preg_replace($urlregex, 'url(' . $svg_path . '?' . $svg_params . ')', $parsed[$block][$selector][$property][$i]); CSSP::comment($parsed[$block][$selector], $property, 'Modified by background-gradient plugin'); break; // IE // IE case 'ie': $filter_properties = array(); if (strtolower($matches[1]) == 'top') { $ie_gradienttype = '0'; } else { $ie_gradienttype = '1'; } // Expand shorthand colors $shorthandpattern = '/^#([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i'; if (preg_match($shorthandpattern, $matches[2], $shorthandmatches)) { $matches[2] = '#FF' . strtoupper($shorthandmatches[1] . $shorthandmatches[1] . $shorthandmatches[2] . $shorthandmatches[2] . $shorthandmatches[3] . $shorthandmatches[3]); } if (preg_match($shorthandpattern, $matches[3], $shorthandmatches)) { $matches[3] = '#FF' . strtoupper($shorthandmatches[1] . $shorthandmatches[1] . $shorthandmatches[2] . $shorthandmatches[2] . $shorthandmatches[3] . $shorthandmatches[3]); } // Convert from RGB colors $rgbpattern = '/rgb\\([\\s]*(.+?)[\\s]*,[\\s]*(.+?)[\\s]*,[\\s]*(.+?)[\\s]*\\)/i'; if (preg_match($rgbpattern, $matches[2], $rgbmatches)) { $matches[2] = '#FF' . strtoupper(dechex(intval($rgbmatches[1])) . dechex(intval($rgbmatches[2])) . dechex(intval($rgbmatches[3]))); } if (preg_match($rgbpattern, $matches[3], $rgbmatches)) { $matches[3] = '#FF' . strtoupper(dechex(intval($rgbmatches[1])) . dechex(intval($rgbmatches[2])) . dechex(intval($rgbmatches[3]))); } // Convert from RGBA colors $rgbapattern = '/rgba\\([\\s]*(.+?)[\\s]*,[\\s]*(.+?)[\\s]*,[\\s]*(.+?)[\\s]*,[\\s]*(.+?)[\\s]*\\)/i'; if (preg_match($rgbapattern, $matches[2], $rgbamatches)) { $matches[2] = '#' . strtoupper(dechex(intval(floatval($rgbamatches[4]) * 255)) . dechex(intval($rgbamatches[1])) . dechex(intval($rgbamatches[2])) . dechex(intval($rgbamatches[3]))); } if (preg_match($rgbapattern, $matches[3], $rgbamatches)) { $matches[3] = '#' . strtoupper(dechex(intval(floatval($rgbamatches[4]) * 255)) . dechex(intval($rgbamatches[1])) . dechex(intval($rgbamatches[2])) . dechex(intval($rgbamatches[3]))); } $filter = 'progid:DXImageTransform.Microsoft.gradient(startColorstr=' . $matches[2] . ',endColorstr=' . $matches[3] . ',gradientType=' . $ie_gradienttype . ')'; // Legacy IE compliance if ($browser->engine_version < 8) { $filter_properties['filter'] = array($filter); } elseif ($browser->engine_version < 9) { $filter_properties['-ms-filter'] = array($filter); } // Insert all $cssp->insert_properties($filter_properties, $block, $selector, NULL, $property); foreach ($filter_properties as $filter_property => $filter_value) { CSSP::comment($parsed[$block][$selector], $filter_property, 'Added by background-gradient plugin'); } break; } } } } } } } }
/** * background gradient * creates a cross-browser linear vertical or horizontal background gradient (other angles or radial gradient not supported) * Adds vendor-specific code for gradients * * Usage: Use simplest possible notation as planned by W3C: http://dev.w3.org/csswg/css3-images/#linear-gradients * background: linear-gradient([direction:<top|left>],[startcolor<hex|rgb|rgba>],[endcolor<hex|rgb|rgba>]) * * Example 1: background: linear-gradient(top,#FFF,#000) // vertical gradient, from top to bottom, from white to black * Example 2: background-image: linear-gradient(left,rgb(255,255,255),rgb(0,0,0)) // horizontal gradient, from left to right, from white to black * Status: Beta * Version: 1.01 * * * backgroundgradient * @param mixed &$parsed * @return void */ function backgroundgradient(&$parsed) { global $cssp, $browser; // Searches for W3C-style two-stepped linear gradient $urlregex = '/linear-gradient\\s*\\(\\s*(top|left)\\s*,\\s*(#[0-9A-F]+|rgba*\\([0-9,]+\\))\\s*,\\s*(#[0-9A-F]+|rgba*\\([0-9,]+\\))\\s*\\)/i'; // In which properties to search $urlproperties = array('background', 'background-image'); // Loop through the array foreach ($parsed as $block => $css) { foreach ($parsed[$block] as $selector => $styles) { foreach ($urlproperties as $property) { if (isset($parsed[$block][$selector][$property])) { $num_values = count($parsed[$block][$selector][$property]); for ($i = 0; $i < $num_values; $i++) { if (preg_match($urlregex, $parsed[$block][$selector][$property][$i], $matches) > 0) { // For all non-ie browsers, sniff the engine and use the appropriate syntax/hack switch ($browser->engine) { // Gecko case 'gecko': $parsed[$block][$selector][$property][$i] = preg_replace($urlregex, '-moz-linear-gradient(' . $matches[1] . ',' . $matches[2] . ',' . $matches[3] . ')', $parsed[$block][$selector][$property][$i]); CSSP::comment($parsed[$block][$selector], $property, 'Modified by background-gradient plugin'); break; // Webkit // Webkit case 'webkit': if (strtolower($matches[1]) == 'top') { $webkit_gradientdirection = 'left top,left bottom'; } else { $webkit_gradientdirection = 'left top,right top'; } $parsed[$block][$selector][$property][$i] = preg_replace($urlregex, '-webkit-gradient(linear,' . $webkit_gradientdirection . ',from(' . $matches[2] . '),to(' . $matches[3] . '))', $parsed[$block][$selector][$property][$i]); CSSP::comment($parsed[$block][$selector], $property, 'Modified by background-gradient plugin'); break; // Konqueror // Konqueror case 'khtml': if (strtolower($matches[1]) == 'top') { $webkit_gradientdirection = 'left top,left bottom'; } else { $webkit_gradientdirection = 'left top,right top'; } $parsed[$block][$selector][$property][$i] = preg_replace($urlregex, '-khtml-gradient(linear,' . $webkit_gradientdirection . ',from(' . $matches[2] . '),to(' . $matches[3] . '))', $parsed[$block][$selector][$property][$i]); CSSP::comment($parsed[$block][$selector], $property, 'Modified by background-gradient plugin'); break; // Opera // Opera case 'opera': $svg_path = rtrim(dirname($_SERVER['SCRIPT_NAME']), '/') . '/plugins/backgroundgradient/svg.php'; $svg_params = 'direction=' . strtolower($matches[1]); $svg_params .= '&startcolor=' . str_replace('#', '%23', strtolower($matches[2])); $svg_params .= '&endcolor=' . str_replace('#', '%23', strtolower($matches[3])); $parsed[$block][$selector][$property][$i] = preg_replace($urlregex, 'url(' . $svg_path . '?' . $svg_params . ')', $parsed[$block][$selector][$property][$i]); CSSP::comment($parsed[$block][$selector], $property, 'Modified by background-gradient plugin'); break; } // End switch // Use filter fallbacks in IE $filter_properties = array(); if (strtolower($matches[1]) == 'top') { $ie_gradienttype = '0'; } else { $ie_gradienttype = '1'; } // Expand shorthand colors $shorthandpattern = '/^#([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i'; if (preg_match($shorthandpattern, $matches[2], $shorthandmatches)) { $matches[2] = '#FF' . strtoupper($shorthandmatches[1] . $shorthandmatches[1] . $shorthandmatches[2] . $shorthandmatches[2] . $shorthandmatches[3] . $shorthandmatches[3]); } if (preg_match($shorthandpattern, $matches[3], $shorthandmatches)) { $matches[3] = '#FF' . strtoupper($shorthandmatches[1] . $shorthandmatches[1] . $shorthandmatches[2] . $shorthandmatches[2] . $shorthandmatches[3] . $shorthandmatches[3]); } // Convert from RGB colors $rgbpattern = '/rgb\\([\\s]*(.+?)[\\s]*,[\\s]*(.+?)[\\s]*,[\\s]*(.+?)[\\s]*\\)/i'; if (preg_match($rgbpattern, $matches[2], $rgbmatches)) { $matches[2] = '#FF' . strtoupper(dechex(intval($rgbmatches[1])) . dechex(intval($rgbmatches[2])) . dechex(intval($rgbmatches[3]))); } if (preg_match($rgbpattern, $matches[3], $rgbmatches)) { $matches[3] = '#FF' . strtoupper(dechex(intval($rgbmatches[1])) . dechex(intval($rgbmatches[2])) . dechex(intval($rgbmatches[3]))); } // Convert from RGBA colors $rgbapattern = '/rgba\\([\\s]*(.+?)[\\s]*,[\\s]*(.+?)[\\s]*,[\\s]*(.+?)[\\s]*,[\\s]*(.+?)[\\s]*\\)/i'; if (preg_match($rgbapattern, $matches[2], $rgbamatches)) { $matches[2] = '#' . strtoupper(dechex(intval(floatval($rgbamatches[4]) * 255)) . dechex(intval($rgbamatches[1])) . dechex(intval($rgbamatches[2])) . dechex(intval($rgbamatches[3]))); } if (preg_match($rgbapattern, $matches[3], $rgbamatches)) { $matches[3] = '#' . strtoupper(dechex(intval(floatval($rgbamatches[4]) * 255)) . dechex(intval($rgbamatches[1])) . dechex(intval($rgbamatches[2])) . dechex(intval($rgbamatches[3]))); } // TODO: Convert from HSL colors. See colormodels for converting algorithm // TODO: Convert from HSLA colors. See colormodels for converting algorithm $filter = 'progid:DXImageTransform.Microsoft.gradient(startColorstr=' . $matches[2] . ',endColorstr=' . $matches[3] . ',gradientType=' . $ie_gradienttype . ')'; // Legacy IE compliance $filter_properties['filter'] = array($filter); // IE8 compliance $filter_properties['-ms-filter'] = array($filter); // Salvage any background information that is NOT gradient stuff and preserve it in a form IE can handle $background_rest = preg_replace('/(-moz-|-webkit-)*linear-gradient\\s*\\(.*?\\)/i', '', $parsed[$block][$selector][$property][$i]); $background_rest = trim($background_rest); if ($background_rest != '') { $filter_properties['*background'] = array($background_rest); // IE7 and 6 $filter_properties['background /*\\**/'] = array($background_rest . '\\9'); // IE8 } // hasLayout stuff $filter_properties['zoom'] = array('1'); // Insert all filters $cssp->insert_properties($filter_properties, $block, $selector, NULL, $property); foreach ($filter_properties as $filter_property => $filter_value) { CSSP::comment($parsed[$block][$selector], $filter_property, 'Added by background-gradient plugin'); } } else { // This is f*****g ugly, but must be done to keep thing sane for css developers. In order to have background // declarations that don't contain any gradient _remove_ gradients that the element may have inherited // we have to explicitly add disabled filters for IE - always. So in the end what this does is adding three // lines of css code for every background property as long as it doesn't add a gradient. Talk about bloated // code... but hey, blame the IE team for their f****d up browsers, not us... $filter_properties = array(); $filter = 'progid:DXImageTransform.Microsoft.gradient(enabled:false)'; $filter_properties['zoom'] = array('1'); $filter_properties['filter'] = array($filter); $filter_properties['-ms-filter'] = array($filter); $cssp->insert_properties($filter_properties, $block, $selector, NULL, $property); foreach ($filter_properties as $filter_property => $filter_value) { CSSP::comment($parsed[$block][$selector], $filter_property, 'Added by background-gradient plugin'); } } } } } } } }