mirror of
https://github.com/erusev/parsedown.git
synced 2024-09-20 03:51:29 +02:00
Markup like CommonMark
This commit is contained in:
parent
7fd6e0bb31
commit
82d20d8ffe
@ -1,88 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Erusev\Parsedown\Components\Blocks;
|
|
||||||
|
|
||||||
use Erusev\Parsedown\AST\Handler;
|
|
||||||
use Erusev\Parsedown\AST\StateRenderable;
|
|
||||||
use Erusev\Parsedown\Components\Block;
|
|
||||||
use Erusev\Parsedown\Components\ContinuableBlock;
|
|
||||||
use Erusev\Parsedown\Configurables\SafeMode;
|
|
||||||
use Erusev\Parsedown\Html\Renderables\RawHtml;
|
|
||||||
use Erusev\Parsedown\Html\Renderables\Text;
|
|
||||||
use Erusev\Parsedown\Parsing\Context;
|
|
||||||
use Erusev\Parsedown\State;
|
|
||||||
|
|
||||||
final class Comment implements ContinuableBlock
|
|
||||||
{
|
|
||||||
use BlockAcquisition;
|
|
||||||
|
|
||||||
/** @var string */
|
|
||||||
private $html;
|
|
||||||
|
|
||||||
/** @var bool */
|
|
||||||
private $isClosed;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $html
|
|
||||||
* @param bool $isClosed
|
|
||||||
*/
|
|
||||||
public function __construct($html, $isClosed)
|
|
||||||
{
|
|
||||||
$this->html = $html;
|
|
||||||
$this->isClosed = $isClosed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Context $Context
|
|
||||||
* @param Block|null $Block
|
|
||||||
* @param State|null $State
|
|
||||||
* @return static|null
|
|
||||||
*/
|
|
||||||
public static function build(
|
|
||||||
Context $Context,
|
|
||||||
Block $Block = null,
|
|
||||||
State $State = null
|
|
||||||
) {
|
|
||||||
if (\strpos($Context->line()->text(), '<!--') === 0) {
|
|
||||||
return new self(
|
|
||||||
$Context->line()->rawLine(),
|
|
||||||
\strpos($Context->line()->text(), '-->') !== false
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Context $Context
|
|
||||||
* @return self|null
|
|
||||||
*/
|
|
||||||
public function advance(Context $Context)
|
|
||||||
{
|
|
||||||
if ($this->isClosed) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new self(
|
|
||||||
$this->html . "\n" . $Context->line()->rawLine(),
|
|
||||||
\strpos($Context->line()->text(), '-->') !== false
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Handler<Text|RawHtml>
|
|
||||||
*/
|
|
||||||
public function stateRenderable()
|
|
||||||
{
|
|
||||||
return new Handler(
|
|
||||||
/** @return Text|RawHtml */
|
|
||||||
function (State $State) {
|
|
||||||
if ($State->get(SafeMode::class)->isEnabled()) {
|
|
||||||
return new Text($this->html);
|
|
||||||
} else {
|
|
||||||
return new RawHtml($this->html);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -19,15 +19,33 @@ final class Markup implements ContinuableBlock
|
|||||||
|
|
||||||
const REGEX_HTML_ATTRIBUTE = '[a-zA-Z_:][\w:.-]*+(?:\s*+=\s*+(?:[^"\'=<>`\s]+|"[^"]*+"|\'[^\']*+\'))?+';
|
const REGEX_HTML_ATTRIBUTE = '[a-zA-Z_:][\w:.-]*+(?:\s*+=\s*+(?:[^"\'=<>`\s]+|"[^"]*+"|\'[^\']*+\'))?+';
|
||||||
|
|
||||||
|
/** @var array{2: string, 3: string, 4: string, 5: string} */
|
||||||
|
private static $simpleContainsEndConditions = [
|
||||||
|
2 => '-->',
|
||||||
|
3 => '?>',
|
||||||
|
4 => '>',
|
||||||
|
5 => ']]>'
|
||||||
|
];
|
||||||
|
|
||||||
/** @var string */
|
/** @var string */
|
||||||
private $html;
|
private $html;
|
||||||
|
|
||||||
|
/** @var 1|2|3|4|5|6|7 */
|
||||||
|
private $type;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
private $closed;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $html
|
* @param string $html
|
||||||
|
* @param 1|2|3|4|5|6|7 $type
|
||||||
|
* @param bool $closed
|
||||||
*/
|
*/
|
||||||
public function __construct($html)
|
private function __construct($html, $type, $closed = false)
|
||||||
{
|
{
|
||||||
$this->html = $html;
|
$this->html = $html;
|
||||||
|
$this->type = $type;
|
||||||
|
$this->closed = $closed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,15 +59,40 @@ final class Markup implements ContinuableBlock
|
|||||||
Block $Block = null,
|
Block $Block = null,
|
||||||
State $State = null
|
State $State = null
|
||||||
) {
|
) {
|
||||||
if (\preg_match('/^<[\/]?+(\w*)(?:[ ]*+'.self::REGEX_HTML_ATTRIBUTE.')*+[ ]*+(\/)?>/', $Context->line()->text(), $matches)) {
|
$text = $Context->line()->text();
|
||||||
|
$rawLine = $Context->line()->rawLine();
|
||||||
|
|
||||||
|
if (\preg_match('/^<(?:script|pre|style)(?:\s++|>|$)/i', $text)) {
|
||||||
|
return new self($rawLine, 1, self::closes12345TypeMarkup(1, $text));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (\substr($text, 0, 4) === '<!--') {
|
||||||
|
return new self($rawLine, 2, self::closes12345TypeMarkup(2, $text));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (\substr($text, 0, 2) === '<?') {
|
||||||
|
return new self($rawLine, 3, self::closes12345TypeMarkup(3, $text));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (\preg_match('/^<![A-Z]/', $text)) {
|
||||||
|
return new self($rawLine, 4, self::closes12345TypeMarkup(4, $text));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (\substr($text, 0, 9) === '<![CDATA[') {
|
||||||
|
return new self($rawLine, 5, self::closes12345TypeMarkup(5, $text));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (\preg_match('/^<[\/]?+(\w*)(?:[ ]*+'.self::REGEX_HTML_ATTRIBUTE.')*+[ ]*+(\/)?>/', $text, $matches)) {
|
||||||
$element = \strtolower($matches[1]);
|
$element = \strtolower($matches[1]);
|
||||||
|
|
||||||
if (\array_key_exists($element, Element::$TEXT_LEVEL_ELEMENTS)) {
|
if (\array_key_exists($element, Element::$TEXT_LEVEL_ELEMENTS)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new self($Context->line()->text());
|
return new self($rawLine, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -58,13 +101,43 @@ final class Markup implements ContinuableBlock
|
|||||||
*/
|
*/
|
||||||
public function advance(Context $Context)
|
public function advance(Context $Context)
|
||||||
{
|
{
|
||||||
if ($Context->previousEmptyLines() > 0) {
|
$closed = $this->closed;
|
||||||
|
$type = $this->type;
|
||||||
|
|
||||||
|
if ($closed) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$html = $this->html . "\n" . $Context->line()->rawLine();
|
if (($type === 6 || $type === 7) && $Context->previousEmptyLines() > 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return new self($html);
|
if ($type === 1 || $type === 2 || $type === 3 || $type === 4 || $type === 5) {
|
||||||
|
$closed = self::closes12345TypeMarkup($type, $Context->line()->text());
|
||||||
|
}
|
||||||
|
|
||||||
|
$html = $this->html . \str_repeat("\n", $Context->previousEmptyLines() + 1);
|
||||||
|
$html .= $Context->line()->rawLine();
|
||||||
|
|
||||||
|
return new self($html, $type, $closed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param 1|2|3|4|5 $type
|
||||||
|
* @param string $text
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private static function closes12345TypeMarkup($type, $text)
|
||||||
|
{
|
||||||
|
if ($type === 1) {
|
||||||
|
if (\preg_match('/<\/(?:script|pre|style)>/i', $text)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} elseif (\stripos($text, self::$simpleContainsEndConditions[$type]) !== false) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4,7 +4,6 @@ namespace Erusev\Parsedown\Configurables;
|
|||||||
|
|
||||||
use Erusev\Parsedown\Components\Block;
|
use Erusev\Parsedown\Components\Block;
|
||||||
use Erusev\Parsedown\Components\Blocks\BlockQuote;
|
use Erusev\Parsedown\Components\Blocks\BlockQuote;
|
||||||
use Erusev\Parsedown\Components\Blocks\Comment;
|
|
||||||
use Erusev\Parsedown\Components\Blocks\FencedCode;
|
use Erusev\Parsedown\Components\Blocks\FencedCode;
|
||||||
use Erusev\Parsedown\Components\Blocks\Header;
|
use Erusev\Parsedown\Components\Blocks\Header;
|
||||||
use Erusev\Parsedown\Components\Blocks\IndentedCode;
|
use Erusev\Parsedown\Components\Blocks\IndentedCode;
|
||||||
@ -38,7 +37,7 @@ final class BlockTypes implements Configurable
|
|||||||
'8' => [TList::class],
|
'8' => [TList::class],
|
||||||
'9' => [TList::class],
|
'9' => [TList::class],
|
||||||
':' => [Table::class],
|
':' => [Table::class],
|
||||||
'<' => [Comment::class, BlockMarkup::class],
|
'<' => [BlockMarkup::class],
|
||||||
'=' => [SetextHeader::class],
|
'=' => [SetextHeader::class],
|
||||||
'>' => [BlockQuote::class],
|
'>' => [BlockQuote::class],
|
||||||
'[' => [Reference::class],
|
'[' => [Reference::class],
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace Erusev\Parsedown\Tests;
|
namespace Erusev\Parsedown\Tests;
|
||||||
|
|
||||||
use Erusev\Parsedown\Components\Blocks\Comment;
|
|
||||||
use Erusev\Parsedown\Components\Blocks\Markup as BlockMarkup;
|
use Erusev\Parsedown\Components\Blocks\Markup as BlockMarkup;
|
||||||
use Erusev\Parsedown\Components\Inlines\Markup as InlineMarkup;
|
use Erusev\Parsedown\Components\Inlines\Markup as InlineMarkup;
|
||||||
use Erusev\Parsedown\Configurables\BlockTypes;
|
use Erusev\Parsedown\Configurables\BlockTypes;
|
||||||
@ -139,7 +138,7 @@ color: red;
|
|||||||
EXPECTED_HTML;
|
EXPECTED_HTML;
|
||||||
|
|
||||||
$parsedownWithNoMarkup = new Parsedown(new State([
|
$parsedownWithNoMarkup = new Parsedown(new State([
|
||||||
BlockTypes::initial()->removing([BlockMarkup::class, Comment::class]),
|
BlockTypes::initial()->removing([BlockMarkup::class]),
|
||||||
InlineTypes::initial()->removing([InlineMarkup::class]),
|
InlineTypes::initial()->removing([InlineMarkup::class]),
|
||||||
]));
|
]));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user