Merge pull request #576 from aidantwoods/enhancement/moar-ast

Produce AST prior to render
This commit is contained in:
Aidan Woods 2018-03-31 23:11:45 +01:00 committed by GitHub
commit ce073c9baa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 254 additions and 138 deletions

View File

@ -142,6 +142,11 @@ class Parsedown
# #
protected function lines(array $lines) protected function lines(array $lines)
{
return $this->elements($this->linesElements($lines));
}
protected function linesElements(array $lines)
{ {
$CurrentBlock = null; $CurrentBlock = null;
@ -255,9 +260,13 @@ class Parsedown
# ~ # ~
if (isset($CurrentBlock) and ! isset($CurrentBlock['type']) and ! isset($CurrentBlock['interrupted'])) if (
{ isset($CurrentBlock)
$CurrentBlock['element']['text'] .= "\n".$text; and isset($CurrentBlock['element']['name'])
and $CurrentBlock['element']['name'] === 'p'
and ! isset($CurrentBlock['interrupted'])
) {
$CurrentBlock['element']['handler']['argument'] .= "\n".$text;
} }
else else
{ {
@ -284,7 +293,7 @@ class Parsedown
# ~ # ~
$markup = ''; $Elements = array();
foreach ($Blocks as $Block) foreach ($Blocks as $Block)
{ {
@ -293,15 +302,12 @@ class Parsedown
continue; continue;
} }
$markup .= "\n"; $Elements[] = $Block['element'];
$markup .= $this->element($Block['element']);
} }
$markup .= "\n";
# ~ # ~
return $markup; return $Elements;
} }
protected function isBlockContinuable($Type) protected function isBlockContinuable($Type)
@ -331,8 +337,7 @@ class Parsedown
$Block = array( $Block = array(
'element' => array( 'element' => array(
'name' => 'pre', 'name' => 'pre',
'handler' => 'element', 'element' => array(
'text' => array(
'name' => 'code', 'name' => 'code',
'text' => $text, 'text' => $text,
), ),
@ -349,16 +354,16 @@ class Parsedown
{ {
if (isset($Block['interrupted'])) if (isset($Block['interrupted']))
{ {
$Block['element']['text']['text'] .= "\n"; $Block['element']['element']['text'] .= "\n";
unset($Block['interrupted']); unset($Block['interrupted']);
} }
$Block['element']['text']['text'] .= "\n"; $Block['element']['element']['text'] .= "\n";
$text = substr($Line['body'], 4); $text = substr($Line['body'], 4);
$Block['element']['text']['text'] .= $text; $Block['element']['element']['text'] .= $text;
return $Block; return $Block;
} }
@ -366,9 +371,9 @@ class Parsedown
protected function blockCodeComplete($Block) protected function blockCodeComplete($Block)
{ {
$text = $Block['element']['text']['text']; $text = $Block['element']['element']['text'];
$Block['element']['text']['text'] = $text; $Block['element']['element']['text'] = $text;
return $Block; return $Block;
} }
@ -386,7 +391,10 @@ class Parsedown
if (strpos($Line['text'], '<!--') === 0) if (strpos($Line['text'], '<!--') === 0)
{ {
$Block = array( $Block = array(
'element' => array('rawHtml' => $Line['body']), 'element' => array(
'rawHtml' => $Line['body'],
'autobreak' => true,
),
); );
if (strpos($Line['text'], '-->') !== false) if (strpos($Line['text'], '-->') !== false)
@ -440,8 +448,7 @@ class Parsedown
'char' => $Line['text'][0], 'char' => $Line['text'][0],
'element' => array( 'element' => array(
'name' => 'pre', 'name' => 'pre',
'handler' => 'element', 'element' => $Element,
'text' => $Element,
), ),
); );
@ -458,30 +465,30 @@ class Parsedown
if (isset($Block['interrupted'])) if (isset($Block['interrupted']))
{ {
$Block['element']['text']['text'] .= "\n"; $Block['element']['element']['text'] .= "\n";
unset($Block['interrupted']); unset($Block['interrupted']);
} }
if (preg_match('/^'.$Block['char'].'{3,}[ ]*$/', $Line['text'])) if (preg_match('/^'.$Block['char'].'{3,}[ ]*$/', $Line['text']))
{ {
$Block['element']['text']['text'] = substr($Block['element']['text']['text'], 1); $Block['element']['element']['text'] = substr($Block['element']['element']['text'], 1);
$Block['complete'] = true; $Block['complete'] = true;
return $Block; return $Block;
} }
$Block['element']['text']['text'] .= "\n".$Line['body']; $Block['element']['element']['text'] .= "\n".$Line['body'];
return $Block; return $Block;
} }
protected function blockFencedCodeComplete($Block) protected function blockFencedCodeComplete($Block)
{ {
$text = $Block['element']['text']['text']; $text = $Block['element']['element']['text'];
$Block['element']['text']['text'] = $text; $Block['element']['element']['text'] = $text;
return $Block; return $Block;
} }
@ -511,8 +518,11 @@ class Parsedown
$Block = array( $Block = array(
'element' => array( 'element' => array(
'name' => 'h' . min(6, $level), 'name' => 'h' . min(6, $level),
'text' => $text, 'handler' => array(
'handler' => 'line', 'function' => 'lineElements',
'argument' => $text,
'destination' => 'elements',
)
), ),
); );
@ -552,7 +562,7 @@ class Parsedown
), ),
'element' => array( 'element' => array(
'name' => $name, 'name' => $name,
'handler' => 'elements', 'elements' => array(),
), ),
); );
@ -576,11 +586,14 @@ class Parsedown
$Block['li'] = array( $Block['li'] = array(
'name' => 'li', 'name' => 'li',
'handler' => 'li', 'handler' => array(
'text' => !empty($matches[3]) ? array($matches[3]) : array(), 'function' => 'li',
'argument' => !empty($matches[3]) ? array($matches[3]) : array(),
'destination' => 'elements'
)
); );
$Block['element']['text'] []= & $Block['li']; $Block['element']['elements'] []= & $Block['li'];
return $Block; return $Block;
} }
@ -588,7 +601,7 @@ class Parsedown
protected function blockListContinue($Line, array $Block) protected function blockListContinue($Line, array $Block)
{ {
if (isset($Block['interrupted']) and empty($Block['li']['text'])) if (isset($Block['interrupted']) and empty($Block['li']['handler']['argument']))
{ {
return null; return null;
} }
@ -608,7 +621,7 @@ class Parsedown
) { ) {
if (isset($Block['interrupted'])) if (isset($Block['interrupted']))
{ {
$Block['li']['text'] []= ''; $Block['li']['handler']['argument'] []= '';
$Block['loose'] = true; $Block['loose'] = true;
@ -623,13 +636,14 @@ class Parsedown
$Block['li'] = array( $Block['li'] = array(
'name' => 'li', 'name' => 'li',
'handler' => 'li', 'handler' => array(
'text' => array( 'function' => 'li',
$text, 'argument' => array($text),
), 'destination' => 'elements'
)
); );
$Block['element']['text'] []= & $Block['li']; $Block['element']['elements'] []= & $Block['li'];
return $Block; return $Block;
} }
@ -647,14 +661,16 @@ class Parsedown
{ {
if (isset($Block['interrupted'])) if (isset($Block['interrupted']))
{ {
$Block['li']['text'] []= ''; $Block['li']['handler']['argument'] []= '';
$Block['loose'] = true;
unset($Block['interrupted']); unset($Block['interrupted']);
} }
$text = substr($Line['body'], $requiredIndent); $text = substr($Line['body'], $requiredIndent);
$Block['li']['text'] []= $text; $Block['li']['handler']['argument'] []= $text;
return $Block; return $Block;
} }
@ -663,7 +679,7 @@ class Parsedown
{ {
$text = preg_replace('/^[ ]{0,'.$requiredIndent.'}/', '', $Line['body']); $text = preg_replace('/^[ ]{0,'.$requiredIndent.'}/', '', $Line['body']);
$Block['li']['text'] []= $text; $Block['li']['handler']['argument'] []= $text;
return $Block; return $Block;
} }
@ -673,11 +689,11 @@ class Parsedown
{ {
if (isset($Block['loose'])) if (isset($Block['loose']))
{ {
foreach ($Block['element']['text'] as &$li) foreach ($Block['element']['elements'] as &$li)
{ {
if (end($li['text']) !== '') if (end($li['handler']['argument']) !== '')
{ {
$li['text'] []= ''; $li['handler']['argument'] []= '';
} }
} }
} }
@ -695,8 +711,11 @@ class Parsedown
$Block = array( $Block = array(
'element' => array( 'element' => array(
'name' => 'blockquote', 'name' => 'blockquote',
'handler' => 'lines', 'handler' => array(
'text' => (array) $matches[1], 'function' => 'linesElements',
'argument' => (array) $matches[1],
'destination' => 'elements',
)
), ),
); );
@ -713,14 +732,14 @@ class Parsedown
if ($Line['text'][0] === '>' and preg_match('/^>[ ]?(.*)/', $Line['text'], $matches)) if ($Line['text'][0] === '>' and preg_match('/^>[ ]?(.*)/', $Line['text'], $matches))
{ {
$Block['element']['text'] []= $matches[1]; $Block['element']['handler']['argument'] []= $matches[1];
return $Block; return $Block;
} }
if ( ! isset($Block['interrupted'])) if ( ! isset($Block['interrupted']))
{ {
$Block['element']['text'] []= $Line['text']; $Block['element']['handler']['argument'] []= $Line['text'];
return $Block; return $Block;
} }
@ -735,7 +754,7 @@ class Parsedown
{ {
$Block = array( $Block = array(
'element' => array( 'element' => array(
'name' => 'hr' 'name' => 'hr',
), ),
); );
@ -784,7 +803,10 @@ class Parsedown
$Block = array( $Block = array(
'name' => $matches[1], 'name' => $matches[1],
'element' => array('rawHtml' => $Line['text']), 'element' => array(
'rawHtml' => $Line['text'],
'autobreak' => true,
),
); );
return $Block; return $Block;
@ -843,7 +865,7 @@ class Parsedown
} }
if ( if (
strpos($Block['element']['text'], '|') === false strpos($Block['element']['handler']['argument'], '|') === false
and strpos($Line['text'], '|') === false and strpos($Line['text'], '|') === false
and strpos($Line['text'], ':') === false and strpos($Line['text'], ':') === false
) { ) {
@ -892,7 +914,7 @@ class Parsedown
$HeaderElements = array(); $HeaderElements = array();
$header = $Block['element']['text']; $header = $Block['element']['handler']['argument'];
$header = trim($header); $header = trim($header);
$header = trim($header, '|'); $header = trim($header, '|');
@ -910,8 +932,11 @@ class Parsedown
$HeaderElement = array( $HeaderElement = array(
'name' => 'th', 'name' => 'th',
'text' => $headerCell, 'handler' => array(
'handler' => 'line', 'function' => 'lineElements',
'argument' => $headerCell,
'destination' => 'elements',
)
); );
if (isset($alignments[$index])) if (isset($alignments[$index]))
@ -933,25 +958,22 @@ class Parsedown
'identified' => true, 'identified' => true,
'element' => array( 'element' => array(
'name' => 'table', 'name' => 'table',
'handler' => 'elements', 'elements' => array(),
), ),
); );
$Block['element']['text'] []= array( $Block['element']['elements'] []= array(
'name' => 'thead', 'name' => 'thead',
'handler' => 'elements',
); );
$Block['element']['text'] []= array( $Block['element']['elements'] []= array(
'name' => 'tbody', 'name' => 'tbody',
'handler' => 'elements', 'elements' => array(),
'text' => array(),
); );
$Block['element']['text'][0]['text'] []= array( $Block['element']['elements'][0]['elements'] []= array(
'name' => 'tr', 'name' => 'tr',
'handler' => 'elements', 'elements' => $HeaderElements,
'text' => $HeaderElements,
); );
return $Block; return $Block;
@ -983,8 +1005,11 @@ class Parsedown
$Element = array( $Element = array(
'name' => 'td', 'name' => 'td',
'handler' => 'line', 'handler' => array(
'text' => $cell, 'function' => 'lineElements',
'argument' => $cell,
'destination' => 'elements',
)
); );
if (isset($Block['alignments'][$index])) if (isset($Block['alignments'][$index]))
@ -999,11 +1024,10 @@ class Parsedown
$Element = array( $Element = array(
'name' => 'tr', 'name' => 'tr',
'handler' => 'elements', 'elements' => $Elements,
'text' => $Elements,
); );
$Block['element']['text'][1]['text'] []= $Element; $Block['element']['elements'][1]['elements'] []= $Element;
return $Block; return $Block;
} }
@ -1018,8 +1042,11 @@ class Parsedown
$Block = array( $Block = array(
'element' => array( 'element' => array(
'name' => 'p', 'name' => 'p',
'text' => $Line['text'], 'handler' => array(
'handler' => 'line', 'function' => 'lineElements',
'argument' => $Line['text'],
'destination' => 'elements',
)
), ),
); );
@ -1053,7 +1080,12 @@ class Parsedown
public function line($text, $nonNestables=array()) public function line($text, $nonNestables=array())
{ {
$markup = ''; return $this->elements($this->lineElements($text, $nonNestables));
}
protected function lineElements($text, $nonNestables = array())
{
$Elements = array();
# $excerpt is based on the first occurrence of a marker # $excerpt is based on the first occurrence of a marker
@ -1106,10 +1138,11 @@ class Parsedown
$unmarkedText = substr($text, 0, $Inline['position']); $unmarkedText = substr($text, 0, $Inline['position']);
# compile the unmarked text # compile the unmarked text
$markup .= $this->unmarkedText($unmarkedText); $InlineText = $this->inlineText($unmarkedText);
$Elements[] = $InlineText['element'];
# compile the inline # compile the inline
$markup .= $this->element($Inline['element']); $Elements[] = $Inline['element'];
# remove the examined text # remove the examined text
$text = substr($text, $Inline['position'] + $Inline['extent']); $text = substr($text, $Inline['position'] + $Inline['extent']);
@ -1121,14 +1154,25 @@ class Parsedown
$unmarkedText = substr($text, 0, $markerPosition + 1); $unmarkedText = substr($text, 0, $markerPosition + 1);
$markup .= $this->unmarkedText($unmarkedText); $InlineText = $this->inlineText($unmarkedText);
$Elements[] = $InlineText['element'];
$text = substr($text, $markerPosition + 1); $text = substr($text, $markerPosition + 1);
} }
$markup .= $this->unmarkedText($text); $InlineText = $this->inlineText($text);
$Elements[] = $InlineText['element'];
return $markup; $Elements = array_map(
function ($Element) {
$Element['autobreak'] = isset($Element['autobreak'])
? $Element['autobreak'] : false;
return $Element;
},
$Elements
);
return $Elements;
} }
# #
@ -1140,13 +1184,13 @@ class Parsedown
$Inline = array( $Inline = array(
'extent' => strlen($text), 'extent' => strlen($text),
'element' => array( 'element' => array(
'handler' => 'elements', 'elements' => array(),
), ),
); );
if ($this->breaksEnabled) if ($this->breaksEnabled)
{ {
$Inline['element']['text'] = self::pregReplaceElements( $Inline['element']['elements'] = self::pregReplaceElements(
'/[ ]*\n/', '/[ ]*\n/',
array( array(
array('name' => 'br'), array('name' => 'br'),
@ -1157,7 +1201,7 @@ class Parsedown
} }
else else
{ {
$Inline['element']['text'] = self::pregReplaceElements( $Inline['element']['elements'] = self::pregReplaceElements(
'/(?:[ ][ ]+|[ ]*\\\\)\n/', '/(?:[ ][ ]+|[ ]*\\\\)\n/',
array( array(
array('name' => 'br'), array('name' => 'br'),
@ -1245,8 +1289,11 @@ class Parsedown
'extent' => strlen($matches[0]), 'extent' => strlen($matches[0]),
'element' => array( 'element' => array(
'name' => $emphasis, 'name' => $emphasis,
'handler' => 'line', 'handler' => array(
'text' => $matches[1], 'function' => 'lineElements',
'argument' => $matches[1],
'destination' => 'elements',
)
), ),
); );
} }
@ -1284,8 +1331,9 @@ class Parsedown
'name' => 'img', 'name' => 'img',
'attributes' => array( 'attributes' => array(
'src' => $Link['element']['attributes']['href'], 'src' => $Link['element']['attributes']['href'],
'alt' => $Link['element']['text'], 'alt' => $Link['element']['handler']['argument'],
), ),
'autobreak' => true,
), ),
); );
@ -1300,9 +1348,12 @@ class Parsedown
{ {
$Element = array( $Element = array(
'name' => 'a', 'name' => 'a',
'handler' => 'line', 'handler' => array(
'function' => 'lineElements',
'argument' => null,
'destination' => 'elements',
),
'nonNestables' => array('Url', 'Link'), 'nonNestables' => array('Url', 'Link'),
'text' => null,
'attributes' => array( 'attributes' => array(
'href' => null, 'href' => null,
'title' => null, 'title' => null,
@ -1315,7 +1366,7 @@ class Parsedown
if (preg_match('/\[((?:[^][]++|(?R))*+)\]/', $remainder, $matches)) if (preg_match('/\[((?:[^][]++|(?R))*+)\]/', $remainder, $matches))
{ {
$Element['text'] = $matches[1]; $Element['handler']['argument'] = $matches[1];
$extent += strlen($matches[0]); $extent += strlen($matches[0]);
@ -1341,14 +1392,14 @@ class Parsedown
{ {
if (preg_match('/^\s*\[(.*?)\]/', $remainder, $matches)) if (preg_match('/^\s*\[(.*?)\]/', $remainder, $matches))
{ {
$definition = strlen($matches[1]) ? $matches[1] : $Element['text']; $definition = strlen($matches[1]) ? $matches[1] : $Element['handler']['argument'];
$definition = strtolower($definition); $definition = strtolower($definition);
$extent += strlen($matches[0]); $extent += strlen($matches[0]);
} }
else else
{ {
$definition = strtolower($Element['text']); $definition = strtolower($Element['handler']['argument']);
} }
if ( ! isset($this->DefinitionData['Reference'][$definition])) if ( ! isset($this->DefinitionData['Reference'][$definition]))
@ -1426,8 +1477,11 @@ class Parsedown
'extent' => strlen($matches[0]), 'extent' => strlen($matches[0]),
'element' => array( 'element' => array(
'name' => 'del', 'name' => 'del',
'text' => $matches[1], 'handler' => array(
'handler' => 'line', 'function' => 'lineElements',
'argument' => $matches[1],
'destination' => 'elements',
)
), ),
); );
} }
@ -1491,6 +1545,63 @@ class Parsedown
# Handlers # Handlers
# #
protected function handle(array $Element)
{
if (isset($Element['handler']))
{
if (!isset($Element['nonNestables']))
{
$Element['nonNestables'] = array();
}
if (is_string($Element['handler']))
{
$function = $Element['handler'];
$argument = $Element['text'];
$destination = 'rawHtml';
}
else
{
$function = $Element['handler']['function'];
$argument = $Element['handler']['argument'];
$destination = $Element['handler']['destination'];
}
$Element[$destination] = $this->{$function}($argument, $Element['nonNestables']);
if ($destination === 'handler')
{
$Element = $this->handle($Element);
}
}
unset($Element['handler']);
return $Element;
}
protected function handleElementRecursive(array $Element)
{
$Element = $this->handle($Element);
if (isset($Element['elements']))
{
$Element['elements'] = $this->handleElementsRecursive($Element['elements']);
}
elseif (isset($Element['element']))
{
$Element['element'] = $this->handleElementRecursive($Element['element']);
}
return $Element;
}
protected function handleElementsRecursive(array $Elements)
{
return array_map(array($this, 'handleElementRecursive'), $Elements);
}
protected function element(array $Element) protected function element(array $Element)
{ {
if ($this->safeMode) if ($this->safeMode)
@ -1498,6 +1609,9 @@ class Parsedown
$Element = $this->sanitiseElement($Element); $Element = $this->sanitiseElement($Element);
} }
# identity map if element has no handler
$Element = $this->handle($Element);
$hasName = isset($Element['name']); $hasName = isset($Element['name']);
$markup = ''; $markup = '';
@ -1536,26 +1650,30 @@ class Parsedown
$permitRawHtml = !$this->safeMode || $allowRawHtmlInSafeMode; $permitRawHtml = !$this->safeMode || $allowRawHtmlInSafeMode;
} }
if (isset($text)) $hasContent = isset($text) || isset($Element['element']) || isset($Element['elements']);
if ($hasContent)
{ {
$markup .= $hasName ? '>' : ''; $markup .= $hasName ? '>' : '';
if (!isset($Element['nonNestables'])) if (isset($Element['elements']))
{ {
$Element['nonNestables'] = array(); $markup .= $this->elements($Element['elements']);
} }
elseif (isset($Element['element']))
if (isset($Element['handler']))
{ {
$markup .= $this->{$Element['handler']}($text, $Element['nonNestables']); $markup .= $this->element($Element['element']);
}
elseif (!$permitRawHtml)
{
$markup .= self::escape($text, true);
} }
else else
{ {
$markup .= $text; if (!$permitRawHtml)
{
$markup .= self::escape($text, true);
}
else
{
$markup .= $text;
}
} }
$markup .= $hasName ? '</'.$Element['name'].'>' : ''; $markup .= $hasName ? '</'.$Element['name'].'>' : '';
@ -1576,11 +1694,14 @@ class Parsedown
foreach ($Elements as $Element) foreach ($Elements as $Element)
{ {
$autoBreakNext = (isset($Element['name'])
|| isset($Element['autobreak']) && $Element['autobreak']
);
// (autobreak === false) covers both sides of an element // (autobreak === false) covers both sides of an element
$autoBreak = !$autoBreak ? $autoBreak : isset($Element['name']); $autoBreak = !$autoBreak ? $autoBreak : $autoBreakNext;
$markup .= ($autoBreak ? "\n" : '') . $this->element($Element); $markup .= ($autoBreak ? "\n" : '') . $this->element($Element);
$autoBreak = isset($Element['name']); $autoBreak = $autoBreakNext;
} }
$markup .= $autoBreak ? "\n" : ''; $markup .= $autoBreak ? "\n" : '';
@ -1592,21 +1713,16 @@ class Parsedown
protected function li($lines) protected function li($lines)
{ {
$markup = $this->lines($lines); $Elements = $this->linesElements($lines);
$trimmedMarkup = trim($markup); if ( ! in_array('', $lines)
and isset($Elements[0]) and isset($Elements[0]['name'])
if ( ! in_array('', $lines) and substr($trimmedMarkup, 0, 3) === '<p>') and $Elements[0]['name'] === 'p'
{ ) {
$markup = $trimmedMarkup; unset($Elements[0]['name']);
$markup = substr($markup, 3);
$position = strpos($markup, "</p>");
$markup = substr_replace($markup, '', $position, 4);
} }
return $markup; return $Elements;
} }
# #

View File

@ -4,15 +4,15 @@ class UnsafeExtension extends Parsedown
{ {
protected function blockFencedCodeComplete($Block) protected function blockFencedCodeComplete($Block)
{ {
$text = $Block['element']['text']['text']; $text = $Block['element']['element']['text'];
unset($Block['element']['text']['text']); unset($Block['element']['element']['text']);
// WARNING: There is almost always a better way of doing things! // WARNING: There is almost always a better way of doing things!
// //
// This example is one of them, unsafe behaviour is NOT needed here. // This example is one of them, unsafe behaviour is NOT needed here.
// Only use this if you trust the input and have no idea what // Only use this if you trust the input and have no idea what
// the output HTML will look like (e.g. using an external parser). // the output HTML will look like (e.g. using an external parser).
$Block['element']['text']['rawHtml'] = "<p>$text</p>"; $Block['element']['element']['rawHtml'] = "<p>$text</p>";
return $Block; return $Block;
} }
@ -23,8 +23,8 @@ class TrustDelegatedExtension extends Parsedown
{ {
protected function blockFencedCodeComplete($Block) protected function blockFencedCodeComplete($Block)
{ {
$text = $Block['element']['text']['text']; $text = $Block['element']['element']['text'];
unset($Block['element']['text']['text']); unset($Block['element']['element']['text']);
// WARNING: There is almost always a better way of doing things! // WARNING: There is almost always a better way of doing things!
// //
@ -32,8 +32,8 @@ class TrustDelegatedExtension extends Parsedown
// Only use this if you are sure that the result being added into // Only use this if you are sure that the result being added into
// rawHtml is safe. // rawHtml is safe.
// (e.g. using an external parser with escaping capabilities). // (e.g. using an external parser with escaping capabilities).
$Block['element']['text']['rawHtml'] = "<p>$text</p>"; $Block['element']['element']['rawHtml'] = "<p>$text</p>";
$Block['element']['text']['allowRawHtmlInSafeMode'] = true; $Block['element']['element']['allowRawHtmlInSafeMode'] = true;
return $Block; return $Block;
} }

View File

@ -1,30 +1,30 @@
<ul> <ul>
<li>li <li>li<ul>
<ul> <li>li<ul>
<li>li
<ul>
<li>li</li> <li>li</li>
<li>li</li> <li>li</li>
</ul></li> </ul>
</li>
<li>li</li> <li>li</li>
</ul></li> </ul>
</li>
<li>li</li> <li>li</li>
</ul> </ul>
<hr /> <hr />
<ul> <ul>
<li>level 1 <li>level 1<ul>
<ul> <li>level 2<ul>
<li>level 2 <li>level 3<ul>
<ul> <li>level 4<ul>
<li>level 3
<ul>
<li>level 4
<ul>
<li>level 5</li> <li>level 5</li>
</ul></li> </ul>
</ul></li> </li>
</ul></li> </ul>
</ul></li> </li>
</ul>
</li>
</ul>
</li>
</ul> </ul>
<hr /> <hr />
<ul> <ul>