1 | <?php |
||
2 | |||
3 | declare(strict_types=1); |
||
4 | |||
5 | namespace League\HTMLToMarkdown\Converter; |
||
6 | |||
7 | use League\HTMLToMarkdown\ElementInterface; |
||
8 | |||
9 | class CodeConverter implements ConverterInterface |
||
10 | { |
||
11 | public function convert(ElementInterface $element): string |
||
12 | { |
||
13 | $language = ''; |
||
14 | 18 | ||
15 | // Checking for language class on the code block |
||
16 | 18 | $classes = $element->getAttribute('class'); |
|
17 | |||
18 | if ($classes) { |
||
19 | 18 | // Since tags can have more than one class, we need to find the one that starts with 'language-' |
|
20 | $classes = \explode(' ', $classes); |
||
21 | 18 | foreach ($classes as $class) { |
|
22 | if (\strpos($class, 'language-') !== false) { |
||
23 | 3 | // Found one, save it as the selected language and stop looping over the classes. |
|
24 | 3 | $language = \str_replace('language-', '', $class); |
|
25 | 3 | break; |
|
26 | } |
||
27 | 3 | } |
|
28 | 3 | } |
|
29 | |||
30 | 2 | $markdown = ''; |
|
31 | 2 | $code = \html_entity_decode($element->getChildrenAsString()); |
|
32 | |||
33 | 18 | // In order to remove the code tags we need to search for them and, in the case of the opening tag |
|
34 | 18 | // use a regular expression to find the tag and the other attributes it might have |
|
35 | $code = \preg_replace('/<code\b[^>]*>/', '', $code); |
||
36 | \assert($code !== null); |
||
37 | $code = \str_replace('</code>', '', $code); |
||
38 | 18 | ||
39 | 18 | // Checking if it's a code block or span |
|
40 | if ($this->shouldBeBlock($element, $code)) { |
||
41 | // Code block detected, newlines will be added in parent |
||
42 | 18 | $markdown .= '```' . $language . "\n" . $code . "\n" . '```'; |
|
43 | } else { |
||
44 | 6 | // One line of code, wrapping it on one backtick, removing new lines |
|
45 | 4 | $markdown .= '`' . \preg_replace('/\r\n|\r|\n/', '', $code) . '`'; |
|
46 | } |
||
47 | 15 | ||
48 | return $markdown; |
||
49 | } |
||
50 | 18 | ||
51 | /** |
||
52 | * @return string[] |
||
53 | */ |
||
54 | public function getSupportedTags(): array |
||
55 | { |
||
56 | 99 | return ['code']; |
|
57 | } |
||
58 | 99 | ||
59 | private function shouldBeBlock(ElementInterface $element, string $code): bool |
||
60 | { |
||
61 | $parent = $element->getParent(); |
||
62 | if ($parent !== null && $parent->getTagName() === 'pre') { |
||
63 | return true; |
||
64 | } |
||
65 | |||
66 | return \preg_match('/[^\s]` `/', $code) === 1; |
||
67 | 18 | } |
|
68 | } |
||
69 |