1
0
mirror of https://github.com/ezyang/htmlpurifier.git synced 2025-03-15 10:59:38 +01:00

[1.7.0] Add more convenience functions to HTMLModule, wire Edit and Hypertext to use new functionality

- Added LanguageCode to AttrTypes. We should prefer string representations of attribute definitions.

git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/trunk@1040 48356398-32a2-884e-a903-53898d9a118a
This commit is contained in:
Edward Z. Yang 2007-05-08 03:28:58 +00:00
parent 47fe34ad81
commit b81fb0af90
7 changed files with 127 additions and 45 deletions

View File

@ -32,6 +32,7 @@ class HTMLPurifier_AttrTypes
$this->info['Pixels'] = new HTMLPurifier_AttrDef_HTML_Pixels();
$this->info['Text'] = new HTMLPurifier_AttrDef_Text();
$this->info['URI'] = new HTMLPurifier_AttrDef_URI();
$this->info['LanguageCode'] = new HTMLPurifier_AttrDef_Lang();
// number is really a positive integer (one or more digits)
$this->info['Number'] = new HTMLPurifier_AttrDef_Integer(false, false, true);

View File

@ -16,6 +16,9 @@
class HTMLPurifier_HTMLModule
{
// -- Overloadable ----------------------------------------------------
/**
* Short unique string identifier of the module
*/
@ -120,13 +123,15 @@ class HTMLPurifier_HTMLModule
*/
function setup(&$definition) {}
// -- Convenience -----------------------------------------------------
/**
* Convenience function that sets up a new element
* @param $element Name of element to add
* @param $safe Is element safe for untrusted users to use?
* @param $type What content set should element be registered to?
* Set as false to skip this step.
* @param $content_model Content model definition in form of:
* @param $contents Allowed children in form of:
* "$content_model_type: $content_model"
* @param $attr_includes What attribute collections to register to
* element?
@ -134,14 +139,12 @@ class HTMLPurifier_HTMLModule
* @note See ElementDef for in-depth descriptions of these parameters.
* @protected
*/
function addElement($element, $safe, $type, $content_model, $attr_includes, $attr) {
function addElement($element, $safe, $type, $contents, $attr_includes, $attr) {
$this->elements[] = $element;
// parse content_model
list($content_model_type, $content_model) = explode(':', $content_model);
$content_model_type = strtolower(trim($content_model_type));
$content_model = trim($content_model);
list($content_model_type, $content_model) = $this->parseContents($contents);
// merge in attribute inclusions
$attr[0] = $attr_includes;
$this->mergeInAttrIncludes($attr, $attr_includes);
// add element to content sets
if ($type) $this->addElementToContentSet($element, $type);
// create element
@ -163,6 +166,41 @@ class HTMLPurifier_HTMLModule
$this->content_sets[$type] .= $element;
}
/**
* Convenience function that transforms single-string contents
* into separate content model and content model type
* @param $contents Allowed children in form of:
* "$content_model_type: $content_model"
*/
function parseContents($contents) {
switch ($contents) {
// check for shorthand content model forms
case 'Inline':
$contents = 'Optional: Inline | #PCDATA';
break;
case 'Flow':
$contents = 'Optional: Flow | #PCDATA';
break;
}
list($content_model_type, $content_model) = explode(':', $contents);
$content_model_type = strtolower(trim($content_model_type));
$content_model = trim($content_model);
return array($content_model_type, $content_model);
}
/**
* Convenience function that merges a list of attribute includes into
* an attribute array.
* @param $attr Reference to attr array to modify
* @param $attr_includes Array of includes / string include to merge in
*/
function mergeInAttrIncludes(&$attr, $attr_includes) {
if (!is_array($attr_includes)) {
if (empty($attr_includes)) $attr_includes = array();
else $attr_includes = array($attr_includes);
}
$attr[0] = $attr_includes;
}
}
?>

View File

@ -18,7 +18,7 @@ class HTMLPurifier_HTMLModule_Bdo extends HTMLPurifier_HTMLModule
function HTMLPurifier_HTMLModule_Bdo() {
$dir = new HTMLPurifier_AttrDef_Enum(array('ltr','rtl'), false);
$this->addElement(
'bdo', true, 'Inline', 'Optional: #PCDATA | Inline', array('Core', 'Lang'),
'bdo', true, 'Inline', 'Inline', array('Core', 'Lang'),
array(
'dir' => $dir, // required
// The Abstract Module specification has the attribute

View File

@ -13,7 +13,7 @@ class HTMLPurifier_HTMLModule_CommonAttributes extends HTMLPurifier_HTMLModule
'title' => 'CDATA',
),
'Lang' => array(
'xml:lang' => false, // see constructor
'xml:lang' => 'LanguageCode',
),
'I18N' => array(
0 => array('Lang'), // proprietary, for xml:lang/lang
@ -22,10 +22,6 @@ class HTMLPurifier_HTMLModule_CommonAttributes extends HTMLPurifier_HTMLModule
0 => array('Core', 'I18N')
)
);
function HTMLPurifier_HTMLModule_CommonAttributes() {
$this->attr_collections['Lang']['xml:lang'] = new HTMLPurifier_AttrDef_Lang();
}
}
?>

View File

@ -11,28 +11,28 @@ class HTMLPurifier_HTMLModule_Edit extends HTMLPurifier_HTMLModule
{
var $name = 'Edit';
var $elements = array('del', 'ins');
var $content_sets = array('Inline' => 'del | ins');
function HTMLPurifier_HTMLModule_Edit() {
foreach ($this->elements as $element) {
$this->info[$element] = new HTMLPurifier_ElementDef();
$this->info[$element]->attr = array(
0 => array('Common'),
'cite' => 'URI',
// 'datetime' => 'Datetime' // Datetime not implemented
);
// Inline context ! Block context (exclamation mark is
// separator, see getChildDef for parsing)
$this->info[$element]->content_model =
'#PCDATA | Inline ! #PCDATA | Flow';
// HTML 4.01 specifies that ins/del must not contain block
// elements when used in an inline context, chameleon is
// a complicated workaround to acheive this effect
$this->info[$element]->content_model_type = 'chameleon';
}
$contents = 'Chameleon: #PCDATA | Inline ! #PCDATA | Flow';
$attr = array(
'cite' => 'URI',
// 'datetime' => 'Datetime', // not implemented
);
$this->addElement(
'del', true, 'Inline', $contents, 'Common', $attr
);
$this->addElement(
'ins', true, 'Inline', $contents, 'Common', $attr
);
}
// HTML 4.01 specifies that ins/del must not contain block
// elements when used in an inline context, chameleon is
// a complicated workaround to acheive this effect
// Inline context ! Block context (exclamation mark is
// separator, see getChildDef for parsing)
var $defines_child_def = true;
function getChildDef($def) {
if ($def->content_model_type != 'chameleon') return false;

View File

@ -10,24 +10,21 @@ class HTMLPurifier_HTMLModule_Hypertext extends HTMLPurifier_HTMLModule
{
var $name = 'Hypertext';
var $elements = array('a');
var $content_sets = array('Inline' => 'a');
function HTMLPurifier_HTMLModule_Hypertext() {
$this->info['a'] = new HTMLPurifier_ElementDef();
$this->info['a']->attr = array(
0 => array('Common'),
// 'accesskey' => 'Character',
// 'charset' => 'Charset',
'href' => 'URI',
//'hreflang' => 'LanguageCode',
'rel' => new HTMLPurifier_AttrDef_HTML_LinkTypes('rel'),
'rev' => new HTMLPurifier_AttrDef_HTML_LinkTypes('rev'),
//'tabindex' => 'Number',
//'type' => 'ContentType',
$this->addElement(
'a', true, 'Inline', 'Inline', 'Common',
array(
// 'accesskey' => 'Character',
// 'charset' => 'Charset',
'href' => 'URI',
// 'hreflang' => 'LanguageCode',
'rel' => new HTMLPurifier_AttrDef_HTML_LinkTypes('rel'),
'rev' => new HTMLPurifier_AttrDef_HTML_LinkTypes('rev'),
// 'tabindex' => 'Number',
// 'type' => 'ContentType',
)
);
$this->info['a']->content_model = '#PCDATA | Inline';
$this->info['a']->content_model_type = 'optional';
$this->info['a']->excludes = array('a' => true);
}

View File

@ -45,6 +45,56 @@ class HTMLPurifier_HTMLModuleTest extends UnitTestCase
}
function test_parseContents() {
$module = new HTMLPurifier_HTMLModule();
// pre-defined templates
$this->assertIdentical(
$module->parseContents('Inline'),
array('optional', 'Inline | #PCDATA')
);
$this->assertIdentical(
$module->parseContents('Flow'),
array('optional', 'Flow | #PCDATA')
);
// normalization procedures
$this->assertIdentical(
$module->parseContents('optional: a'),
array('optional', 'a')
);
$this->assertIdentical(
$module->parseContents('OPTIONAL :a'),
array('optional', 'a')
);
$this->assertIdentical(
$module->parseContents('Optional: a'),
array('optional', 'a')
);
// others
$this->assertIdentical(
$module->parseContents('Optional: a | b | c'),
array('optional', 'a | b | c')
);
}
function test_mergeInAttrIncludes() {
$module = new HTMLPurifier_HTMLModule();
$attr = array();
$module->mergeInAttrIncludes($attr, 'Common');
$this->assertIdentical($attr, array(0 => array('Common')));
$attr = array('a' => 'b');
$module->mergeInAttrIncludes($attr, array('Common', 'Good'));
$this->assertIdentical($attr, array('a' => 'b', 0 => array('Common', 'Good')));
}
}
?>