From 87f03af20cf61937f799da56dc4f595aee54b4a7 Mon Sep 17 00:00:00 2001 From: upstream Date: Sat, 3 Oct 2026 02:31:49 +0200 Subject: [PATCH] Upstream thephpleague/html-to-markdown state of the touched files before aa29149d30 --- src/Converter/EmphasisConverter.php | 73 +++++++++++++++++++++++++++++ src/Converter/TextConverter.php | 48 +++++++++++++++++++ tests/HtmlConverterTest.php | 2 - 3 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 src/Converter/EmphasisConverter.php create mode 100644 src/Converter/TextConverter.php diff --git a/src/Converter/EmphasisConverter.php b/src/Converter/EmphasisConverter.php new file mode 100644 index 0000000..359b5ee --- /dev/null +++ b/src/Converter/EmphasisConverter.php @@ -0,0 +1,73 @@ +isText()) { + $tag = $element->getTagName(); + if ($tag === 'i' || $tag === 'em') { + return 'em'; + } + + if ($tag === 'b' || $tag === 'strong') { + return 'strong'; + } + } + + return ''; + } + + public function setConfig(Configuration $config): void + { + $this->config = $config; + } + + public function convert(ElementInterface $element): string + { + $tag = $this->getNormTag($element); + $value = $element->getValue(); + + if (! \trim($value)) { + return $value; + } + + if ($tag === 'em') { + $style = Coerce::toString($this->config->getOption('italic_style')); + } else { + $style = Coerce::toString($this->config->getOption('bold_style')); + } + + $prefix = \ltrim($value) !== $value ? ' ' : ''; + $suffix = \rtrim($value) !== $value ? ' ' : ''; + + /* If this node is immediately preceded or followed by one of the same type don't emit + * the start or end $style, respectively. This prevents foobar from + * being converted to *foo**bar* which is incorrect. We want *foobar* instead. + */ + $preStyle = $this->getNormTag($element->getPreviousSibling()) === $tag ? '' : $style; + $postStyle = $this->getNormTag($element->getNextSibling()) === $tag ? '' : $style; + + return $prefix . $preStyle . \trim($value) . $postStyle . $suffix; + } + + /** + * @return string[] + */ + public function getSupportedTags(): array + { + return ['em', 'i', 'strong', 'b']; + } +} diff --git a/src/Converter/TextConverter.php b/src/Converter/TextConverter.php new file mode 100644 index 0000000..465dd48 --- /dev/null +++ b/src/Converter/TextConverter.php @@ -0,0 +1,48 @@ +getValue(); + + // Remove leftover \n at the beginning of the line + $markdown = \ltrim($markdown, "\n"); + + // Replace sequences of invisible characters with spaces + $markdown = \preg_replace('~\s+~u', ' ', $markdown); + \assert(\is_string($markdown)); + + // Escape the following characters: '*', '_', '[', ']' and '\' + if (($parent = $element->getParent()) && $parent->getTagName() !== 'div') { + $markdown = \preg_replace('~([*_\\[\\]\\\\])~u', '\\\\$1', $markdown); + \assert(\is_string($markdown)); + } + + $markdown = \preg_replace('~^#~u', '\\\\#', $markdown); + \assert(\is_string($markdown)); + + if ($markdown === ' ') { + $next = $element->getNext(); + if (! $next || $next->isBlock()) { + $markdown = ''; + } + } + + return \htmlspecialchars($markdown, ENT_NOQUOTES, 'UTF-8'); + } + + /** + * @return string[] + */ + public function getSupportedTags(): array + { + return ['#text']; + } +} diff --git a/tests/HtmlConverterTest.php b/tests/HtmlConverterTest.php index dd9bd6d..e62247e 100644 --- a/tests/HtmlConverterTest.php +++ b/tests/HtmlConverterTest.php @@ -163,8 +163,6 @@ class HtmlConverterTest extends TestCase $this->assertHtmlGivesMarkdown('google.com', '[google.com](google.com)'); $this->assertHtmlGivesMarkdown('https://www.google.com', ''); $this->assertHtmlGivesMarkdown('ftp://files.example.com', ''); - $this->assertHtmlGivesMarkdown('https://example.com/?a=1&b=2', ''); - $this->assertHtmlGivesMarkdown('https://example.com/<b>', '[https://example.com/<b>](https://example.com/)'); $this->assertHtmlGivesMarkdown('test@example.com', ''); $this->assertHtmlGivesMarkdown('test+foo@example.bar-baz.com', '');