mirror of
https://github.com/ezyang/htmlpurifier.git
synced 2025-01-18 11:41:52 +00:00
[1.4.0] CSS property background-position implemented. Also:
- Fixed some misinformation in Percentage - Add support for lowercase CSS length units git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/trunk@661 48356398-32a2-884e-a903-53898d9a118a
This commit is contained in:
parent
78cf7db82e
commit
a68b6afda1
7
NEWS
7
NEWS
@ -11,9 +11,10 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
|
|||||||
|
|
||||||
1.4.0, unknown release date
|
1.4.0, unknown release date
|
||||||
! Implemented list-style-image, URIs now allowed in list-style
|
! Implemented list-style-image, URIs now allowed in list-style
|
||||||
! Implemented background-image, background-repeat and background-attachment
|
! Implemented background-image, background-repeat, background-attachment
|
||||||
CSS properties. background shorthand property HAS NOT been extended
|
and background-position CSS properties. Background shorthand property is
|
||||||
to allow these, and background-position IS NOT implemented yet.
|
currently equivalent to background-image and does not support the
|
||||||
|
new properties.
|
||||||
! Configuration documentation looks nicer
|
! Configuration documentation looks nicer
|
||||||
! Added smoketest 'all.php', which loads all other smoketests via frames
|
! Added smoketest 'all.php', which loads all other smoketests via frames
|
||||||
! Added %Core.EscapeNonASCIICharacters to workaround loss of Unicode
|
! Added %Core.EscapeNonASCIICharacters to workaround loss of Unicode
|
||||||
|
130
library/HTMLPurifier/AttrDef/BackgroundPosition.php
Normal file
130
library/HTMLPurifier/AttrDef/BackgroundPosition.php
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require_once 'HTMLPurifier/AttrDef.php';
|
||||||
|
require_once 'HTMLPurifier/AttrDef/CSSLength.php';
|
||||||
|
require_once 'HTMLPurifier/AttrDef/Percentage.php';
|
||||||
|
|
||||||
|
/* W3C says:
|
||||||
|
[ // adjective and number must be in correct order, even if
|
||||||
|
// you could switch them without introducing ambiguity.
|
||||||
|
// some browsers support that syntax
|
||||||
|
[
|
||||||
|
<percentage> | <length> | left | center | right
|
||||||
|
]
|
||||||
|
[
|
||||||
|
<percentage> | <length> | top | center | bottom
|
||||||
|
]?
|
||||||
|
] |
|
||||||
|
[ // this signifies that the vertical and horizontal adjectives
|
||||||
|
// can be arbitrarily ordered, however, there can only be two,
|
||||||
|
// one of each, or none at all
|
||||||
|
[
|
||||||
|
left | center | right
|
||||||
|
] ||
|
||||||
|
[
|
||||||
|
top | center | bottom
|
||||||
|
]
|
||||||
|
]
|
||||||
|
top, left = 0%
|
||||||
|
center, (none) = 50%
|
||||||
|
bottom, right = 100%
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* QuirksMode says:
|
||||||
|
keyword + length/percentage must be ordered correctly, as per W3C
|
||||||
|
|
||||||
|
Internet Explorer and Opera, however, support arbitrary ordering. We
|
||||||
|
should fix it up.
|
||||||
|
|
||||||
|
Minor issue though, not strictly necessary.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// control freaks may appreciate the ability to convert these to
|
||||||
|
// percentages or something, but it's not necessary
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the value of background-position.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_BackgroundPosition extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
var $length;
|
||||||
|
var $percentage;
|
||||||
|
|
||||||
|
function HTMLPurifier_AttrDef_BackgroundPosition() {
|
||||||
|
$this->length = new HTMLPurifier_AttrDef_CSSLength();
|
||||||
|
$this->percentage = new HTMLPurifier_AttrDef_Percentage();
|
||||||
|
}
|
||||||
|
|
||||||
|
function validate($string, $config, &$context) {
|
||||||
|
$string = $this->parseCDATA($string);
|
||||||
|
$bits = explode(' ', $string);
|
||||||
|
|
||||||
|
$keywords = array();
|
||||||
|
$keywords['h'] = false; // left, right
|
||||||
|
$keywords['v'] = false; // top, bottom
|
||||||
|
$keywords['c'] = false; // center
|
||||||
|
$measures = array();
|
||||||
|
|
||||||
|
$i = 0;
|
||||||
|
|
||||||
|
$lookup = array(
|
||||||
|
'top' => 'v',
|
||||||
|
'bottom' => 'v',
|
||||||
|
'left' => 'h',
|
||||||
|
'right' => 'h',
|
||||||
|
'center' => 'c'
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($bits as $bit) {
|
||||||
|
if ($bit === '') continue;
|
||||||
|
|
||||||
|
// test for keyword
|
||||||
|
$lbit = ctype_lower($bit) ? $bit : strtolower($bit);
|
||||||
|
if (isset($lookup[$lbit])) {
|
||||||
|
$status = $lookup[$lbit];
|
||||||
|
$keywords[$status] = $lbit;
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// test for length
|
||||||
|
$r = $this->length->validate($bit, $config, &$context);
|
||||||
|
if ($r !== false) {
|
||||||
|
$measures[] = $r;
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// test for percentage
|
||||||
|
$r = $this->percentage->validate($bit, $config, &$context);
|
||||||
|
if ($r !== false) {
|
||||||
|
$measures[] = $r;
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$i) return false; // no valid values were caught
|
||||||
|
|
||||||
|
|
||||||
|
$ret = array();
|
||||||
|
|
||||||
|
// first keyword
|
||||||
|
if ($keywords['h']) $ret[] = $keywords['h'];
|
||||||
|
elseif (count($measures)) $ret[] = array_shift($measures);
|
||||||
|
elseif ($keywords['c']) {
|
||||||
|
$ret[] = $keywords['c'];
|
||||||
|
$keywords['c'] = false; // prevent re-use: center = center center
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($keywords['v']) $ret[] = $keywords['v'];
|
||||||
|
elseif (count($measures)) $ret[] = array_shift($measures);
|
||||||
|
elseif ($keywords['c']) $ret[] = $keywords['c'];
|
||||||
|
|
||||||
|
if (empty($ret)) return false;
|
||||||
|
return implode(' ', $ret);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
@ -40,6 +40,7 @@ class HTMLPurifier_AttrDef_CSSLength extends HTMLPurifier_AttrDef
|
|||||||
|
|
||||||
// we assume all units are two characters
|
// we assume all units are two characters
|
||||||
$unit = substr($length, $strlen - 2);
|
$unit = substr($length, $strlen - 2);
|
||||||
|
if (!ctype_lower($unit)) $unit = strtolower($unit);
|
||||||
$number = substr($length, 0, $strlen - 2);
|
$number = substr($length, 0, $strlen - 2);
|
||||||
|
|
||||||
if (!isset($this->units[$unit])) return false;
|
if (!isset($this->units[$unit])) return false;
|
||||||
|
@ -4,14 +4,13 @@ require_once 'HTMLPurifier/AttrDef.php';
|
|||||||
require_once 'HTMLPurifier/AttrDef/Number.php';
|
require_once 'HTMLPurifier/AttrDef/Number.php';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates a Percentage as defined by the HTML spec.
|
* Validates a Percentage as defined by the CSS spec.
|
||||||
* @note This also allows integer pixel values.
|
|
||||||
*/
|
*/
|
||||||
class HTMLPurifier_AttrDef_Percentage extends HTMLPurifier_AttrDef
|
class HTMLPurifier_AttrDef_Percentage extends HTMLPurifier_AttrDef
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instance of HTMLPurifier_AttrDef_Number to defer pixel validation
|
* Instance of HTMLPurifier_AttrDef_Number to defer number validation
|
||||||
*/
|
*/
|
||||||
var $number_def;
|
var $number_def;
|
||||||
|
|
||||||
|
@ -79,6 +79,7 @@ class HTMLPurifier_CSSDefinition
|
|||||||
$this->info['background-attachment'] = new HTMLPurifier_AttrDef_Enum(
|
$this->info['background-attachment'] = new HTMLPurifier_AttrDef_Enum(
|
||||||
array('scroll', 'fixed')
|
array('scroll', 'fixed')
|
||||||
);
|
);
|
||||||
|
$this->info['background-position'] = new HTMLPurifier_AttrDef_BackgroundPosition();
|
||||||
|
|
||||||
// pending its own validator as a shorthand
|
// pending its own validator as a shorthand
|
||||||
$this->info['background'] =
|
$this->info['background'] =
|
||||||
|
71
tests/HTMLPurifier/AttrDef/BackgroundPositionTest.php
Normal file
71
tests/HTMLPurifier/AttrDef/BackgroundPositionTest.php
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require_once 'HTMLPurifier/AttrDefHarness.php';
|
||||||
|
require_once 'HTMLPurifier/AttrDef/BackgroundPosition.php';
|
||||||
|
|
||||||
|
class HTMLPurifier_AttrDef_BackgroundPositionTest extends HTMLPurifier_AttrDefHarness
|
||||||
|
{
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
|
||||||
|
$this->def = new HTMLPurifier_AttrDef_BackgroundPosition();
|
||||||
|
|
||||||
|
// explicitly cited in spec
|
||||||
|
$this->assertDef('0% 0%');
|
||||||
|
$this->assertDef('100% 100%');
|
||||||
|
$this->assertDef('14% 84%');
|
||||||
|
$this->assertDef('2cm 1cm');
|
||||||
|
$this->assertDef('top');
|
||||||
|
$this->assertDef('left');
|
||||||
|
$this->assertDef('center');
|
||||||
|
$this->assertDef('right');
|
||||||
|
$this->assertDef('bottom');
|
||||||
|
$this->assertDef('left top');
|
||||||
|
$this->assertDef('center top');
|
||||||
|
$this->assertDef('right top');
|
||||||
|
$this->assertDef('left center');
|
||||||
|
$this->assertDef('right center');
|
||||||
|
$this->assertDef('left bottom');
|
||||||
|
$this->assertDef('center bottom');
|
||||||
|
$this->assertDef('right bottom');
|
||||||
|
|
||||||
|
// reordered due to internal impl details
|
||||||
|
$this->assertDef('top left', 'left top');
|
||||||
|
$this->assertDef('top center', 'center top');
|
||||||
|
$this->assertDef('top right', 'right top');
|
||||||
|
$this->assertDef('center left', 'left center');
|
||||||
|
$this->assertDef('center center', 'center'); // two centers collide
|
||||||
|
$this->assertDef('center right', 'right center');
|
||||||
|
$this->assertDef('bottom left', 'left bottom');
|
||||||
|
$this->assertDef('bottom center', 'center bottom');
|
||||||
|
$this->assertDef('bottom right', 'right bottom');
|
||||||
|
|
||||||
|
// more cases from the defined syntax
|
||||||
|
$this->assertDef('1.32in 4ex');
|
||||||
|
$this->assertDef('-14% -84.65%');
|
||||||
|
$this->assertDef('-1in -4ex');
|
||||||
|
$this->assertDef('-1pc 2.3%');
|
||||||
|
|
||||||
|
// keyword mixing
|
||||||
|
$this->assertDef('3em top');
|
||||||
|
$this->assertDef('left 50%');
|
||||||
|
|
||||||
|
// fixable keyword mixing
|
||||||
|
$this->assertDef('top 3em', '3em top');
|
||||||
|
$this->assertDef('50% left', 'left 50%');
|
||||||
|
|
||||||
|
// whitespace collapsing
|
||||||
|
$this->assertDef('3em top', '3em top');
|
||||||
|
$this->assertDef("left\n \t foo ", 'left');
|
||||||
|
|
||||||
|
// invalid uses (we're going to be strict on these)
|
||||||
|
$this->assertDef('foo bar', false);
|
||||||
|
$this->assertDef('left left', 'left');
|
||||||
|
$this->assertDef('left right top bottom center left', 'left bottom');
|
||||||
|
$this->assertDef('0fr 9%', '9%');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
@ -22,6 +22,8 @@ class HTMLPurifier_AttrDef_CSSLengthTest extends HTMLPurifier_AttrDefHarness
|
|||||||
$this->assertDef('3pt');
|
$this->assertDef('3pt');
|
||||||
$this->assertDef('3pc');
|
$this->assertDef('3pc');
|
||||||
|
|
||||||
|
$this->assertDef('3PX', '3px');
|
||||||
|
|
||||||
$this->assertDef('3', false);
|
$this->assertDef('3', false);
|
||||||
$this->assertDef('3miles', false);
|
$this->assertDef('3miles', false);
|
||||||
|
|
||||||
|
@ -78,6 +78,7 @@ class HTMLPurifier_AttrDef_CSSTest extends HTMLPurifier_AttrDefHarness
|
|||||||
$this->assertDef('background-image:none;');
|
$this->assertDef('background-image:none;');
|
||||||
$this->assertDef('background-repeat:repeat-y;');
|
$this->assertDef('background-repeat:repeat-y;');
|
||||||
$this->assertDef('background-attachment:fixed;');
|
$this->assertDef('background-attachment:fixed;');
|
||||||
|
$this->assertDef('background-position:left 90%;');
|
||||||
|
|
||||||
// duplicates
|
// duplicates
|
||||||
$this->assertDef('text-align:right;text-align:left;',
|
$this->assertDef('text-align:right;text-align:left;',
|
||||||
|
@ -49,6 +49,7 @@ $test_files[] = 'AttrDef/BorderTest.php';
|
|||||||
$test_files[] = 'AttrDef/ListStyleTest.php';
|
$test_files[] = 'AttrDef/ListStyleTest.php';
|
||||||
$test_files[] = 'AttrDef/Email/SimpleCheckTest.php';
|
$test_files[] = 'AttrDef/Email/SimpleCheckTest.php';
|
||||||
$test_files[] = 'AttrDef/CSSURITest.php';
|
$test_files[] = 'AttrDef/CSSURITest.php';
|
||||||
|
$test_files[] = 'AttrDef/BackgroundPositionTest.php';
|
||||||
$test_files[] = 'IDAccumulatorTest.php';
|
$test_files[] = 'IDAccumulatorTest.php';
|
||||||
$test_files[] = 'TagTransformTest.php';
|
$test_files[] = 'TagTransformTest.php';
|
||||||
$test_files[] = 'AttrTransform/LangTest.php';
|
$test_files[] = 'AttrTransform/LangTest.php';
|
||||||
|
Loading…
Reference in New Issue
Block a user