diff --git a/src/Rules/HtmlRule.php b/src/Rules/HtmlRule.php
index df4bff5..a56e0cc 100644
--- a/src/Rules/HtmlRule.php
+++ b/src/Rules/HtmlRule.php
@@ -10,6 +10,13 @@
final class HtmlRule implements Rule, ProvidesFirstChar
{
+ /**
+ * Elements whose content is raw text rather than Markdown.
+ *
+ * @see https://spec.commonmark.org/0.31.2/#html-blocks
+ */
+ private const array RAW_TEXT_TAGS = ['pre', 'script', 'style', 'textarea'];
+
public string $firstChar = '<';
public function shouldParse(Parser $parser): bool
@@ -84,6 +91,13 @@ public function parse(Parser $parser): Token
$content .= $parser->consumeWhile(Parser::NEW_LINE);
- return new HtmlToken($content);
+ return new HtmlToken(
+ $content,
+ raw: in_array(
+ strtolower($tagName),
+ self::RAW_TEXT_TAGS,
+ strict: true,
+ ),
+ );
}
}
diff --git a/src/Tokens/HtmlToken.php b/src/Tokens/HtmlToken.php
index 93b0d61..5663e04 100644
--- a/src/Tokens/HtmlToken.php
+++ b/src/Tokens/HtmlToken.php
@@ -18,10 +18,17 @@ final class HtmlToken implements Token
{
public function __construct(
public string $html,
+
+ /** Whether the content is raw text that must never be parsed as Markdown. */
+ public bool $raw = false,
) {}
public function parse(Parser $parser): string
{
+ if ($this->raw) {
+ return $this->html;
+ }
+
return $parser
->forToken($this, [
new BoldAndItalicRule(),
diff --git a/tests/Rules/HtmlRuleTest.php b/tests/Rules/HtmlRuleTest.php
index aee0050..5f8208d 100644
--- a/tests/Rules/HtmlRuleTest.php
+++ b/tests/Rules/HtmlRuleTest.php
@@ -82,4 +82,64 @@ public function test_void_tags_are_case_insensitive(): void
$this->assertSame("
\n
Hello
", $html); } + + #[Test] + public function lex_keeps_script_content_raw(): void + { + $html = + (string) new Parser(highlighter: null, rules: [new HtmlRule()])->parse( + '', + ); + + $this->assertSame('', $html); + } + + #[Test] + public function lex_keeps_style_content_raw(): void + { + $html = + (string) new Parser(highlighter: null, rules: [new HtmlRule()])->parse( + '', + ); + + $this->assertSame('', $html); + } + + #[Test] + public function lex_keeps_pre_and_textarea_content_raw(): void + { + $parser = new Parser(highlighter: null, rules: [new HtmlRule()]); + + $this->assertSame( + '**a** _b_', + (string) $parser->parse('
**a** _b_'), + ); + + $this->assertSame( + '', + (string) $parser->parse(''), + ); + } + + #[Test] + public function lex_detects_raw_text_tags_case_insensitively(): void + { + $html = + (string) new Parser(highlighter: null, rules: [new HtmlRule()])->parse( + '', + ); + + $this->assertSame('', $html); + } + + #[Test] + public function lex_still_parses_markdown_in_other_elements(): void + { + $html = + (string) new Parser(highlighter: null, rules: [new HtmlRule()])->parse( + '