mirror of
https://github.com/renbaoshuo/S2OJ.git
synced 2024-12-25 01:31:53 +00:00
96d4a3ecf7
Due to historical reasons, the code is in subfolder "1". With SVN removal, we place the code back and remove the annoying "1" folder.
325 lines
10 KiB
PHP
325 lines
10 KiB
PHP
<?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 = <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
|