mediawiki-extensions-Templa.../CSSRenderer.php
Coren 29bdd0c18e Add property filtering
Properties listed in $wgTemplateStylesPropertyBlacklist, or
those that contain function-like values not listed in
$wgTemplateStylesFunctionWhitelist cause the containing
declaration to be omitted from rendering entirely.

Additionally, rule selectors are unconditionally prepended
with '#mw-content-text' so that they cannot be applied to
UI elements outside the actual page content.

Change-Id: Id3d7dff465363d0163e4a5a1f31e770b4b0a67e2
2016-04-21 05:16:06 +00:00

98 lines
2.1 KiB
PHP

<?php
/**
* @file
* @ingroup Extensions
*/
/**
* Collects parsed CSS trees, and merges them for rendering into text.
*
* @class
*/
class CSSRenderer {
private $bymedia;
function __construct() {
$this->bymedia = [];
}
/**
* Adds (and merge) a parsed CSS tree to the render list.
*
* @param array $rules The parsed tree as created by CSSParser::rules()
* @param string $media Forcibly specified @media block selector. Normally unspecified
* and defaults to the empty string.
*/
function add( $rules, $media = '' ) {
if ( !array_key_exists( $media, $this->bymedia ) ) {
$this->bymedia[$media] = [];
}
foreach ( $rules as $at ) {
switch ( strtolower( $at['name'] ) ) {
case '@media':
if ( $media == '' ) {
$this->add( $at['rules'], "@media ".$at['text'] );
}
break;
case '':
$this->bymedia[$media] = array_merge( $this->bymedia[$media], $at['rules'] );
break;
}
}
}
/**
* Renders the collected CSS trees into a string suitable for inclusion
* in a <style> tag.
*
* @return string Rendered CSS
*/
function render( $functionWhitelist = [], $propertyBlacklist = [] ) {
$css = '';
foreach ( $this->bymedia as $at => $rules ) {
if ( $at != '' ) {
$css .= "$at {\n";
}
foreach ( $rules as $rule ) {
if ( $rule
and array_key_exists( 'selectors', $rule )
and array_key_exists( 'decls', $rule ) )
{
$css .= implode( ',', $rule['selectors'] ) . "{";
foreach ( $rule['decls'] as $key => $value ) {
if ( !in_array( strtolower( $key ), $propertyBlacklist ) ) {
$blacklisted = false;
foreach ( $value as $prop ) {
if ( preg_match( '/^ ([^ \n\t]+) [ \n\t]* \( $/x', $prop, $match ) ) {
if ( !in_array( strtolower( $match[1] ), $functionWhitelist ) ) {
$blacklisted = true;
break;
}
}
}
if ( !$blacklisted ) {
$css .= "$key:" . implode( '', $value ) . ';';
}
}
}
$css .= "} ";
}
}
if ( $at != '' ) {
$css .= "} ";
}
}
return $css;
}
}