aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer
diff options
context:
space:
mode:
authorKlaus Weidenbach <Klaus.Weidenbach@gmx.net>2017-03-18 17:50:05 +0100
committerKlaus Weidenbach <Klaus.Weidenbach@gmx.net>2017-03-26 00:41:27 +0100
commitf718e2b0db0fe3477212a8dd6c3ec067f4432862 (patch)
tree8dfbd3b3d4bdcd967b50f1ee4655440bcdef5bb8 /vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer
parent2115eb26a7fd2ca937286bd4e98ab74c7d6e9525 (diff)
downloadvolse-hubzilla-f718e2b0db0fe3477212a8dd6c3ec067f4432862.tar.gz
volse-hubzilla-f718e2b0db0fe3477212a8dd6c3ec067f4432862.tar.bz2
volse-hubzilla-f718e2b0db0fe3477212a8dd6c3ec067f4432862.zip
:arrow_up: Update HTML Purifier library.
Updated HTML Purifier from 4.6.0 to 4.9.2 with better PHP7 compatibility. Used composer to manage this library.
Diffstat (limited to 'vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer')
-rw-r--r--vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/CSSDefinition.php44
-rw-r--r--vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.css10
-rw-r--r--vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.js5
-rw-r--r--vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.php451
-rw-r--r--vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/HTMLDefinition.php324
5 files changed, 834 insertions, 0 deletions
diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/CSSDefinition.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/CSSDefinition.php
new file mode 100644
index 000000000..29505fe12
--- /dev/null
+++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/CSSDefinition.php
@@ -0,0 +1,44 @@
+<?php
+
+class HTMLPurifier_Printer_CSSDefinition extends HTMLPurifier_Printer
+{
+ /**
+ * @type HTMLPurifier_CSSDefinition
+ */
+ protected $def;
+
+ /**
+ * @param HTMLPurifier_Config $config
+ * @return string
+ */
+ public function render($config)
+ {
+ $this->def = $config->getCSSDefinition();
+ $ret = '';
+
+ $ret .= $this->start('div', array('class' => 'HTMLPurifier_Printer'));
+ $ret .= $this->start('table');
+
+ $ret .= $this->element('caption', 'Properties ($info)');
+
+ $ret .= $this->start('thead');
+ $ret .= $this->start('tr');
+ $ret .= $this->element('th', 'Property', array('class' => 'heavy'));
+ $ret .= $this->element('th', 'Definition', array('class' => 'heavy', 'style' => 'width:auto;'));
+ $ret .= $this->end('tr');
+ $ret .= $this->end('thead');
+
+ ksort($this->def->info);
+ foreach ($this->def->info as $property => $obj) {
+ $name = $this->getClass($obj, 'AttrDef_');
+ $ret .= $this->row($property, $name);
+ }
+
+ $ret .= $this->end('table');
+ $ret .= $this->end('div');
+
+ return $ret;
+ }
+}
+
+// vim: et sw=4 sts=4
diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.css b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.css
new file mode 100644
index 000000000..3ff1a88aa
--- /dev/null
+++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.css
@@ -0,0 +1,10 @@
+
+.hp-config {}
+
+.hp-config tbody th {text-align:right; padding-right:0.5em;}
+.hp-config thead, .hp-config .namespace {background:#3C578C; color:#FFF;}
+.hp-config .namespace th {text-align:center;}
+.hp-config .verbose {display:none;}
+.hp-config .controls {text-align:center;}
+
+/* vim: et sw=4 sts=4 */
diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.js b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.js
new file mode 100644
index 000000000..cba00c9b8
--- /dev/null
+++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.js
@@ -0,0 +1,5 @@
+function toggleWriteability(id_of_patient, checked) {
+ document.getElementById(id_of_patient).disabled = checked;
+}
+
+// vim: et sw=4 sts=4
diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.php
new file mode 100644
index 000000000..65a777904
--- /dev/null
+++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.php
@@ -0,0 +1,451 @@
+<?php
+
+/**
+ * @todo Rewrite to use Interchange objects
+ */
+class HTMLPurifier_Printer_ConfigForm extends HTMLPurifier_Printer
+{
+
+ /**
+ * Printers for specific fields.
+ * @type HTMLPurifier_Printer[]
+ */
+ protected $fields = array();
+
+ /**
+ * Documentation URL, can have fragment tagged on end.
+ * @type string
+ */
+ protected $docURL;
+
+ /**
+ * Name of form element to stuff config in.
+ * @type string
+ */
+ protected $name;
+
+ /**
+ * Whether or not to compress directive names, clipping them off
+ * after a certain amount of letters. False to disable or integer letters
+ * before clipping.
+ * @type bool
+ */
+ protected $compress = false;
+
+ /**
+ * @param string $name Form element name for directives to be stuffed into
+ * @param string $doc_url String documentation URL, will have fragment tagged on
+ * @param bool $compress Integer max length before compressing a directive name, set to false to turn off
+ */
+ public function __construct(
+ $name,
+ $doc_url = null,
+ $compress = false
+ ) {
+ parent::__construct();
+ $this->docURL = $doc_url;
+ $this->name = $name;
+ $this->compress = $compress;
+ // initialize sub-printers
+ $this->fields[0] = new HTMLPurifier_Printer_ConfigForm_default();
+ $this->fields[HTMLPurifier_VarParser::BOOL] = new HTMLPurifier_Printer_ConfigForm_bool();
+ }
+
+ /**
+ * Sets default column and row size for textareas in sub-printers
+ * @param $cols Integer columns of textarea, null to use default
+ * @param $rows Integer rows of textarea, null to use default
+ */
+ public function setTextareaDimensions($cols = null, $rows = null)
+ {
+ if ($cols) {
+ $this->fields['default']->cols = $cols;
+ }
+ if ($rows) {
+ $this->fields['default']->rows = $rows;
+ }
+ }
+
+ /**
+ * Retrieves styling, in case it is not accessible by webserver
+ */
+ public static function getCSS()
+ {
+ return file_get_contents(HTMLPURIFIER_PREFIX . '/HTMLPurifier/Printer/ConfigForm.css');
+ }
+
+ /**
+ * Retrieves JavaScript, in case it is not accessible by webserver
+ */
+ public static function getJavaScript()
+ {
+ return file_get_contents(HTMLPURIFIER_PREFIX . '/HTMLPurifier/Printer/ConfigForm.js');
+ }
+
+ /**
+ * Returns HTML output for a configuration form
+ * @param HTMLPurifier_Config|array $config Configuration object of current form state, or an array
+ * where [0] has an HTML namespace and [1] is being rendered.
+ * @param array|bool $allowed Optional namespace(s) and directives to restrict form to.
+ * @param bool $render_controls
+ * @return string
+ */
+ public function render($config, $allowed = true, $render_controls = true)
+ {
+ if (is_array($config) && isset($config[0])) {
+ $gen_config = $config[0];
+ $config = $config[1];
+ } else {
+ $gen_config = $config;
+ }
+
+ $this->config = $config;
+ $this->genConfig = $gen_config;
+ $this->prepareGenerator($gen_config);
+
+ $allowed = HTMLPurifier_Config::getAllowedDirectivesForForm($allowed, $config->def);
+ $all = array();
+ foreach ($allowed as $key) {
+ list($ns, $directive) = $key;
+ $all[$ns][$directive] = $config->get($ns . '.' . $directive);
+ }
+
+ $ret = '';
+ $ret .= $this->start('table', array('class' => 'hp-config'));
+ $ret .= $this->start('thead');
+ $ret .= $this->start('tr');
+ $ret .= $this->element('th', 'Directive', array('class' => 'hp-directive'));
+ $ret .= $this->element('th', 'Value', array('class' => 'hp-value'));
+ $ret .= $this->end('tr');
+ $ret .= $this->end('thead');
+ foreach ($all as $ns => $directives) {
+ $ret .= $this->renderNamespace($ns, $directives);
+ }
+ if ($render_controls) {
+ $ret .= $this->start('tbody');
+ $ret .= $this->start('tr');
+ $ret .= $this->start('td', array('colspan' => 2, 'class' => 'controls'));
+ $ret .= $this->elementEmpty('input', array('type' => 'submit', 'value' => 'Submit'));
+ $ret .= '[<a href="?">Reset</a>]';
+ $ret .= $this->end('td');
+ $ret .= $this->end('tr');
+ $ret .= $this->end('tbody');
+ }
+ $ret .= $this->end('table');
+ return $ret;
+ }
+
+ /**
+ * Renders a single namespace
+ * @param $ns String namespace name
+ * @param array $directives array of directives to values
+ * @return string
+ */
+ protected function renderNamespace($ns, $directives)
+ {
+ $ret = '';
+ $ret .= $this->start('tbody', array('class' => 'namespace'));
+ $ret .= $this->start('tr');
+ $ret .= $this->element('th', $ns, array('colspan' => 2));
+ $ret .= $this->end('tr');
+ $ret .= $this->end('tbody');
+ $ret .= $this->start('tbody');
+ foreach ($directives as $directive => $value) {
+ $ret .= $this->start('tr');
+ $ret .= $this->start('th');
+ if ($this->docURL) {
+ $url = str_replace('%s', urlencode("$ns.$directive"), $this->docURL);
+ $ret .= $this->start('a', array('href' => $url));
+ }
+ $attr = array('for' => "{$this->name}:$ns.$directive");
+
+ // crop directive name if it's too long
+ if (!$this->compress || (strlen($directive) < $this->compress)) {
+ $directive_disp = $directive;
+ } else {
+ $directive_disp = substr($directive, 0, $this->compress - 2) . '...';
+ $attr['title'] = $directive;
+ }
+
+ $ret .= $this->element(
+ 'label',
+ $directive_disp,
+ // component printers must create an element with this id
+ $attr
+ );
+ if ($this->docURL) {
+ $ret .= $this->end('a');
+ }
+ $ret .= $this->end('th');
+
+ $ret .= $this->start('td');
+ $def = $this->config->def->info["$ns.$directive"];
+ if (is_int($def)) {
+ $allow_null = $def < 0;
+ $type = abs($def);
+ } else {
+ $type = $def->type;
+ $allow_null = isset($def->allow_null);
+ }
+ if (!isset($this->fields[$type])) {
+ $type = 0;
+ } // default
+ $type_obj = $this->fields[$type];
+ if ($allow_null) {
+ $type_obj = new HTMLPurifier_Printer_ConfigForm_NullDecorator($type_obj);
+ }
+ $ret .= $type_obj->render($ns, $directive, $value, $this->name, array($this->genConfig, $this->config));
+ $ret .= $this->end('td');
+ $ret .= $this->end('tr');
+ }
+ $ret .= $this->end('tbody');
+ return $ret;
+ }
+
+}
+
+/**
+ * Printer decorator for directives that accept null
+ */
+class HTMLPurifier_Printer_ConfigForm_NullDecorator extends HTMLPurifier_Printer
+{
+ /**
+ * Printer being decorated
+ * @type HTMLPurifier_Printer
+ */
+ protected $obj;
+
+ /**
+ * @param HTMLPurifier_Printer $obj Printer to decorate
+ */
+ public function __construct($obj)
+ {
+ parent::__construct();
+ $this->obj = $obj;
+ }
+
+ /**
+ * @param string $ns
+ * @param string $directive
+ * @param string $value
+ * @param string $name
+ * @param HTMLPurifier_Config|array $config
+ * @return string
+ */
+ public function render($ns, $directive, $value, $name, $config)
+ {
+ if (is_array($config) && isset($config[0])) {
+ $gen_config = $config[0];
+ $config = $config[1];
+ } else {
+ $gen_config = $config;
+ }
+ $this->prepareGenerator($gen_config);
+
+ $ret = '';
+ $ret .= $this->start('label', array('for' => "$name:Null_$ns.$directive"));
+ $ret .= $this->element('span', "$ns.$directive:", array('class' => 'verbose'));
+ $ret .= $this->text(' Null/Disabled');
+ $ret .= $this->end('label');
+ $attr = array(
+ 'type' => 'checkbox',
+ 'value' => '1',
+ 'class' => 'null-toggle',
+ 'name' => "$name" . "[Null_$ns.$directive]",
+ 'id' => "$name:Null_$ns.$directive",
+ 'onclick' => "toggleWriteability('$name:$ns.$directive',checked)" // INLINE JAVASCRIPT!!!!
+ );
+ if ($this->obj instanceof HTMLPurifier_Printer_ConfigForm_bool) {
+ // modify inline javascript slightly
+ $attr['onclick'] =
+ "toggleWriteability('$name:Yes_$ns.$directive',checked);" .
+ "toggleWriteability('$name:No_$ns.$directive',checked)";
+ }
+ if ($value === null) {
+ $attr['checked'] = 'checked';
+ }
+ $ret .= $this->elementEmpty('input', $attr);
+ $ret .= $this->text(' or ');
+ $ret .= $this->elementEmpty('br');
+ $ret .= $this->obj->render($ns, $directive, $value, $name, array($gen_config, $config));
+ return $ret;
+ }
+}
+
+/**
+ * Swiss-army knife configuration form field printer
+ */
+class HTMLPurifier_Printer_ConfigForm_default extends HTMLPurifier_Printer
+{
+ /**
+ * @type int
+ */
+ public $cols = 18;
+
+ /**
+ * @type int
+ */
+ public $rows = 5;
+
+ /**
+ * @param string $ns
+ * @param string $directive
+ * @param string $value
+ * @param string $name
+ * @param HTMLPurifier_Config|array $config
+ * @return string
+ */
+ public function render($ns, $directive, $value, $name, $config)
+ {
+ if (is_array($config) && isset($config[0])) {
+ $gen_config = $config[0];
+ $config = $config[1];
+ } else {
+ $gen_config = $config;
+ }
+ $this->prepareGenerator($gen_config);
+ // this should probably be split up a little
+ $ret = '';
+ $def = $config->def->info["$ns.$directive"];
+ if (is_int($def)) {
+ $type = abs($def);
+ } else {
+ $type = $def->type;
+ }
+ if (is_array($value)) {
+ switch ($type) {
+ case HTMLPurifier_VarParser::LOOKUP:
+ $array = $value;
+ $value = array();
+ foreach ($array as $val => $b) {
+ $value[] = $val;
+ }
+ //TODO does this need a break?
+ case HTMLPurifier_VarParser::ALIST:
+ $value = implode(PHP_EOL, $value);
+ break;
+ case HTMLPurifier_VarParser::HASH:
+ $nvalue = '';
+ foreach ($value as $i => $v) {
+ if (is_array($v)) {
+ // HACK
+ $v = implode(";", $v);
+ }
+ $nvalue .= "$i:$v" . PHP_EOL;
+ }
+ $value = $nvalue;
+ break;
+ default:
+ $value = '';
+ }
+ }
+ if ($type === HTMLPurifier_VarParser::MIXED) {
+ return 'Not supported';
+ $value = serialize($value);
+ }
+ $attr = array(
+ 'name' => "$name" . "[$ns.$directive]",
+ 'id' => "$name:$ns.$directive"
+ );
+ if ($value === null) {
+ $attr['disabled'] = 'disabled';
+ }
+ if (isset($def->allowed)) {
+ $ret .= $this->start('select', $attr);
+ foreach ($def->allowed as $val => $b) {
+ $attr = array();
+ if ($value == $val) {
+ $attr['selected'] = 'selected';
+ }
+ $ret .= $this->element('option', $val, $attr);
+ }
+ $ret .= $this->end('select');
+ } elseif ($type === HTMLPurifier_VarParser::TEXT ||
+ $type === HTMLPurifier_VarParser::ITEXT ||
+ $type === HTMLPurifier_VarParser::ALIST ||
+ $type === HTMLPurifier_VarParser::HASH ||
+ $type === HTMLPurifier_VarParser::LOOKUP) {
+ $attr['cols'] = $this->cols;
+ $attr['rows'] = $this->rows;
+ $ret .= $this->start('textarea', $attr);
+ $ret .= $this->text($value);
+ $ret .= $this->end('textarea');
+ } else {
+ $attr['value'] = $value;
+ $attr['type'] = 'text';
+ $ret .= $this->elementEmpty('input', $attr);
+ }
+ return $ret;
+ }
+}
+
+/**
+ * Bool form field printer
+ */
+class HTMLPurifier_Printer_ConfigForm_bool extends HTMLPurifier_Printer
+{
+ /**
+ * @param string $ns
+ * @param string $directive
+ * @param string $value
+ * @param string $name
+ * @param HTMLPurifier_Config|array $config
+ * @return string
+ */
+ public function render($ns, $directive, $value, $name, $config)
+ {
+ if (is_array($config) && isset($config[0])) {
+ $gen_config = $config[0];
+ $config = $config[1];
+ } else {
+ $gen_config = $config;
+ }
+ $this->prepareGenerator($gen_config);
+ $ret = '';
+ $ret .= $this->start('div', array('id' => "$name:$ns.$directive"));
+
+ $ret .= $this->start('label', array('for' => "$name:Yes_$ns.$directive"));
+ $ret .= $this->element('span', "$ns.$directive:", array('class' => 'verbose'));
+ $ret .= $this->text(' Yes');
+ $ret .= $this->end('label');
+
+ $attr = array(
+ 'type' => 'radio',
+ 'name' => "$name" . "[$ns.$directive]",
+ 'id' => "$name:Yes_$ns.$directive",
+ 'value' => '1'
+ );
+ if ($value === true) {
+ $attr['checked'] = 'checked';
+ }
+ if ($value === null) {
+ $attr['disabled'] = 'disabled';
+ }
+ $ret .= $this->elementEmpty('input', $attr);
+
+ $ret .= $this->start('label', array('for' => "$name:No_$ns.$directive"));
+ $ret .= $this->element('span', "$ns.$directive:", array('class' => 'verbose'));
+ $ret .= $this->text(' No');
+ $ret .= $this->end('label');
+
+ $attr = array(
+ 'type' => 'radio',
+ 'name' => "$name" . "[$ns.$directive]",
+ 'id' => "$name:No_$ns.$directive",
+ 'value' => '0'
+ );
+ if ($value === false) {
+ $attr['checked'] = 'checked';
+ }
+ if ($value === null) {
+ $attr['disabled'] = 'disabled';
+ }
+ $ret .= $this->elementEmpty('input', $attr);
+
+ $ret .= $this->end('div');
+
+ return $ret;
+ }
+}
+
+// vim: et sw=4 sts=4
diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/HTMLDefinition.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/HTMLDefinition.php
new file mode 100644
index 000000000..5f2f2f8a7
--- /dev/null
+++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/HTMLDefinition.php
@@ -0,0 +1,324 @@
+<?php
+
+class HTMLPurifier_Printer_HTMLDefinition extends HTMLPurifier_Printer
+{
+
+ /**
+ * @type HTMLPurifier_HTMLDefinition, for easy access
+ */
+ protected $def;
+
+ /**
+ * @param HTMLPurifier_Config $config
+ * @return string
+ */
+ public function render($config)
+ {
+ $ret = '';
+ $this->config =& $config;
+
+ $this->def = $config->getHTMLDefinition();
+
+ $ret .= $this->start('div', array('class' => 'HTMLPurifier_Printer'));
+
+ $ret .= $this->renderDoctype();
+ $ret .= $this->renderEnvironment();
+ $ret .= $this->renderContentSets();
+ $ret .= $this->renderInfo();
+
+ $ret .= $this->end('div');
+
+ return $ret;
+ }
+
+ /**
+ * Renders the Doctype table
+ * @return string
+ */
+ protected function renderDoctype()
+ {
+ $doctype = $this->def->doctype;
+ $ret = '';
+ $ret .= $this->start('table');
+ $ret .= $this->element('caption', 'Doctype');
+ $ret .= $this->row('Name', $doctype->name);
+ $ret .= $this->row('XML', $doctype->xml ? 'Yes' : 'No');
+ $ret .= $this->row('Default Modules', implode($doctype->modules, ', '));
+ $ret .= $this->row('Default Tidy Modules', implode($doctype->tidyModules, ', '));
+ $ret .= $this->end('table');
+ return $ret;
+ }
+
+
+ /**
+ * Renders environment table, which is miscellaneous info
+ * @return string
+ */
+ protected function renderEnvironment()
+ {
+ $def = $this->def;
+
+ $ret = '';
+
+ $ret .= $this->start('table');
+ $ret .= $this->element('caption', 'Environment');
+
+ $ret .= $this->row('Parent of fragment', $def->info_parent);
+ $ret .= $this->renderChildren($def->info_parent_def->child);
+ $ret .= $this->row('Block wrap name', $def->info_block_wrapper);
+
+ $ret .= $this->start('tr');
+ $ret .= $this->element('th', 'Global attributes');
+ $ret .= $this->element('td', $this->listifyAttr($def->info_global_attr), null, 0);
+ $ret .= $this->end('tr');
+
+ $ret .= $this->start('tr');
+ $ret .= $this->element('th', 'Tag transforms');
+ $list = array();
+ foreach ($def->info_tag_transform as $old => $new) {
+ $new = $this->getClass($new, 'TagTransform_');
+ $list[] = "<$old> with $new";
+ }
+ $ret .= $this->element('td', $this->listify($list));
+ $ret .= $this->end('tr');
+
+ $ret .= $this->start('tr');
+ $ret .= $this->element('th', 'Pre-AttrTransform');
+ $ret .= $this->element('td', $this->listifyObjectList($def->info_attr_transform_pre));
+ $ret .= $this->end('tr');
+
+ $ret .= $this->start('tr');
+ $ret .= $this->element('th', 'Post-AttrTransform');
+ $ret .= $this->element('td', $this->listifyObjectList($def->info_attr_transform_post));
+ $ret .= $this->end('tr');
+
+ $ret .= $this->end('table');
+ return $ret;
+ }
+
+ /**
+ * Renders the Content Sets table
+ * @return string
+ */
+ protected function renderContentSets()
+ {
+ $ret = '';
+ $ret .= $this->start('table');
+ $ret .= $this->element('caption', 'Content Sets');
+ foreach ($this->def->info_content_sets as $name => $lookup) {
+ $ret .= $this->heavyHeader($name);
+ $ret .= $this->start('tr');
+ $ret .= $this->element('td', $this->listifyTagLookup($lookup));
+ $ret .= $this->end('tr');
+ }
+ $ret .= $this->end('table');
+ return $ret;
+ }
+
+ /**
+ * Renders the Elements ($info) table
+ * @return string
+ */
+ protected function renderInfo()
+ {
+ $ret = '';
+ $ret .= $this->start('table');
+ $ret .= $this->element('caption', 'Elements ($info)');
+ ksort($this->def->info);
+ $ret .= $this->heavyHeader('Allowed tags', 2);
+ $ret .= $this->start('tr');
+ $ret .= $this->element('td', $this->listifyTagLookup($this->def->info), array('colspan' => 2));
+ $ret .= $this->end('tr');
+ foreach ($this->def->info as $name => $def) {
+ $ret .= $this->start('tr');
+ $ret .= $this->element('th', "<$name>", array('class' => 'heavy', 'colspan' => 2));
+ $ret .= $this->end('tr');
+ $ret .= $this->start('tr');
+ $ret .= $this->element('th', 'Inline content');
+ $ret .= $this->element('td', $def->descendants_are_inline ? 'Yes' : 'No');
+ $ret .= $this->end('tr');
+ if (!empty($def->excludes)) {
+ $ret .= $this->start('tr');
+ $ret .= $this->element('th', 'Excludes');
+ $ret .= $this->element('td', $this->listifyTagLookup($def->excludes));
+ $ret .= $this->end('tr');
+ }
+ if (!empty($def->attr_transform_pre)) {
+ $ret .= $this->start('tr');
+ $ret .= $this->element('th', 'Pre-AttrTransform');
+ $ret .= $this->element('td', $this->listifyObjectList($def->attr_transform_pre));
+ $ret .= $this->end('tr');
+ }
+ if (!empty($def->attr_transform_post)) {
+ $ret .= $this->start('tr');
+ $ret .= $this->element('th', 'Post-AttrTransform');
+ $ret .= $this->element('td', $this->listifyObjectList($def->attr_transform_post));
+ $ret .= $this->end('tr');
+ }
+ if (!empty($def->auto_close)) {
+ $ret .= $this->start('tr');
+ $ret .= $this->element('th', 'Auto closed by');
+ $ret .= $this->element('td', $this->listifyTagLookup($def->auto_close));
+ $ret .= $this->end('tr');
+ }
+ $ret .= $this->start('tr');
+ $ret .= $this->element('th', 'Allowed attributes');
+ $ret .= $this->element('td', $this->listifyAttr($def->attr), array(), 0);
+ $ret .= $this->end('tr');
+
+ if (!empty($def->required_attr)) {
+ $ret .= $this->row('Required attributes', $this->listify($def->required_attr));
+ }
+
+ $ret .= $this->renderChildren($def->child);
+ }
+ $ret .= $this->end('table');
+ return $ret;
+ }
+
+ /**
+ * Renders a row describing the allowed children of an element
+ * @param HTMLPurifier_ChildDef $def HTMLPurifier_ChildDef of pertinent element
+ * @return string
+ */
+ protected function renderChildren($def)
+ {
+ $context = new HTMLPurifier_Context();
+ $ret = '';
+ $ret .= $this->start('tr');
+ $elements = array();
+ $attr = array();
+ if (isset($def->elements)) {
+ if ($def->type == 'strictblockquote') {
+ $def->validateChildren(array(), $this->config, $context);
+ }
+ $elements = $def->elements;
+ }
+ if ($def->type == 'chameleon') {
+ $attr['rowspan'] = 2;
+ } elseif ($def->type == 'empty') {
+ $elements = array();
+ } elseif ($def->type == 'table') {
+ $elements = array_flip(
+ array(
+ 'col',
+ 'caption',
+ 'colgroup',
+ 'thead',
+ 'tfoot',
+ 'tbody',
+ 'tr'
+ )
+ );
+ }
+ $ret .= $this->element('th', 'Allowed children', $attr);
+
+ if ($def->type == 'chameleon') {
+
+ $ret .= $this->element(
+ 'td',
+ '<em>Block</em>: ' .
+ $this->escape($this->listifyTagLookup($def->block->elements)),
+ null,
+ 0
+ );
+ $ret .= $this->end('tr');
+ $ret .= $this->start('tr');
+ $ret .= $this->element(
+ 'td',
+ '<em>Inline</em>: ' .
+ $this->escape($this->listifyTagLookup($def->inline->elements)),
+ null,
+ 0
+ );
+
+ } elseif ($def->type == 'custom') {
+
+ $ret .= $this->element(
+ 'td',
+ '<em>' . ucfirst($def->type) . '</em>: ' .
+ $def->dtd_regex
+ );
+
+ } else {
+ $ret .= $this->element(
+ 'td',
+ '<em>' . ucfirst($def->type) . '</em>: ' .
+ $this->escape($this->listifyTagLookup($elements)),
+ null,
+ 0
+ );
+ }
+ $ret .= $this->end('tr');
+ return $ret;
+ }
+
+ /**
+ * Listifies a tag lookup table.
+ * @param array $array Tag lookup array in form of array('tagname' => true)
+ * @return string
+ */
+ protected function listifyTagLookup($array)
+ {
+ ksort($array);
+ $list = array();
+ foreach ($array as $name => $discard) {
+ if ($name !== '#PCDATA' && !isset($this->def->info[$name])) {
+ continue;
+ }
+ $list[] = $name;
+ }
+ return $this->listify($list);
+ }
+
+ /**
+ * Listifies a list of objects by retrieving class names and internal state
+ * @param array $array List of objects
+ * @return string
+ * @todo Also add information about internal state
+ */
+ protected function listifyObjectList($array)
+ {
+ ksort($array);
+ $list = array();
+ foreach ($array as $obj) {
+ $list[] = $this->getClass($obj, 'AttrTransform_');
+ }
+ return $this->listify($list);
+ }
+
+ /**
+ * Listifies a hash of attributes to AttrDef classes
+ * @param array $array Array hash in form of array('attrname' => HTMLPurifier_AttrDef)
+ * @return string
+ */
+ protected function listifyAttr($array)
+ {
+ ksort($array);
+ $list = array();
+ foreach ($array as $name => $obj) {
+ if ($obj === false) {
+ continue;
+ }
+ $list[] = "$name&nbsp;=&nbsp;<i>" . $this->getClass($obj, 'AttrDef_') . '</i>';
+ }
+ return $this->listify($list);
+ }
+
+ /**
+ * Creates a heavy header row
+ * @param string $text
+ * @param int $num
+ * @return string
+ */
+ protected function heavyHeader($text, $num = 1)
+ {
+ $ret = '';
+ $ret .= $this->start('tr');
+ $ret .= $this->element('th', $text, array('colspan' => $num, 'class' => 'heavy'));
+ $ret .= $this->end('tr');
+ return $ret;
+ }
+}
+
+// vim: et sw=4 sts=4