From 02c6094ccfe074568e850293c769ce6ddd797fc3 Mon Sep 17 00:00:00 2001 From: Ben Thomson Date: Tue, 22 Nov 2022 16:23:43 +0800 Subject: [PATCH 1/6] Convert Markdown parser to CommonMark Drops the requirement for the Parsedown library. --- composer.json | 1 - src/Parse/Markdown.php | 408 +++++++++++++++--- .../Markdown/CommonMarkCoreExtension.php | 174 ++++++++ src/Parse/ParseServiceProvider.php | 9 +- src/Parse/Parsedown/Parsedown.php | 13 - src/Support/aliases.php | 1 - 6 files changed, 520 insertions(+), 86 deletions(-) create mode 100644 src/Parse/Markdown/CommonMarkCoreExtension.php delete mode 100644 src/Parse/Parsedown/Parsedown.php diff --git a/composer.json b/composer.json index 6d7597aa2..2d30d9adf 100644 --- a/composer.json +++ b/composer.json @@ -38,7 +38,6 @@ "assetic/framework": "~3.0", "doctrine/dbal": "^2.6", "enshrined/svg-sanitize": "^0.15", - "erusev/parsedown-extra": "~0.7", "laravel/framework": "^9.1", "laravel/tinker": "^2.7", "league/csv": "~9.1", diff --git a/src/Parse/Markdown.php b/src/Parse/Markdown.php index 5146257d1..8fd1c26a5 100644 --- a/src/Parse/Markdown.php +++ b/src/Parse/Markdown.php @@ -1,135 +1,405 @@ (Rewritten implementation using CommonMark) **/ class Markdown { use \Winter\Storm\Support\Traits\Emitter; /** - * @var string Parsedown class + * Enables the parsing of attributes for block-level and inline content. */ - protected $parserClass = \Winter\Storm\Parse\Parsedown\Parsedown::class; + public bool $attributes = false; /** - * Gets an instance of the parser. - * - * We return a new instance each time to prevent contamination of clean instances. - * - * @return Parsedown + * Enables autolinking of URLs and email addresses in Markdown content. + */ + public bool $autolinking = true; + + /** + * Enables the parsing and generation of footnotes. + */ + public bool $footnotes = false; + + /** + * Enables the parsing of front matter (metadata). + */ + public bool $frontMatter = false; + + /** + * Enables the generation of permalinks for each heading. + */ + public bool $headingPermalinks = false; + + /** + * Enables inline-only formatting. This is used for rendering a single line of Markdown. + */ + public bool $inlineOnly = false; + + /** + * Enables safe mode - disables certain HTML tags. + */ + public bool $safeMode = false; + + /** + * Enables the parsing and generation of task lists. + */ + public bool $taskLists = false; + + /** + * Enables the generation of tables. + */ + public bool $tables = true; + + /** + * Enables the generation of a table of contents. + */ + public bool $tableOfContents = false; + + /** + * Custom configuration for the CommonMark environment. + */ + public array $config = []; + + /** + * Extracted front matter (metadata) from the Markdown content. + */ + protected ?array $frontMatterData = null; + + /** + * Extracted table of contents from the Markdown content. + */ + protected ?array $tableOfContentData = null; + + /** + * The Markdown parser class to use. */ - protected function getParser() + protected ?string $parserClass = null; + + /** + * The HTML renderer class to use. + */ + protected ?string $rendererClass = null; + + /** + * Constructor. + */ + final public function __construct() { - return new $this->parserClass; } /** - * Sets the Markdown parser. - * - * @param string|object $parserClass - * @return void + * Parse Markdown content and render as HTML. */ - public function setParser(string|object $parserClass) + public function parse(string $markdown): string { - if (is_object($parserClass)) { - $this->parserClass = get_class($parserClass); - } else { - $this->parserClass = $parserClass; + $environment = $this->createEnvironment(); + + if ($this->frontMatter) { + $markdown = $this->extractFrontMatter($markdown); } + + return $this->parseInternal($environment, $markdown); } /** - * Parse text using Markdown and Markdown-Extra - * @param string $text Markdown text to parse - * @return string Resulting HTML + * Parse Markdown content and render as HTML, with unsafe tags disabled. + * + * This will prevent tags such as