• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

eliashaeussler / typo3-solver / 19680832166

25 Nov 2025 06:57PM UTC coverage: 88.098% (-0.1%) from 88.195%
19680832166

push

github

web-flow
Merge pull request #503 from eliashaeussler/task/markdown

2 of 3 new or added lines in 1 file covered. (66.67%)

903 of 1025 relevant lines covered (88.1%)

2.32 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.87
/Classes/ViewHelpers/MarkdownToHtmlViewHelper.php
1
<?php
2

3
declare(strict_types=1);
4

5
/*
6
 * This file is part of the TYPO3 CMS extension "solver".
7
 *
8
 * Copyright (C) 2023-2025 Elias Häußler <elias@haeussler.dev>
9
 *
10
 * This program is free software: you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation, either version 2 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22
 */
23

24
namespace EliasHaeussler\Typo3Solver\ViewHelpers;
25

26
use FastVolt\Helper\Markdown;
27
use TYPO3Fluid\Fluid;
28

29
/**
30
 * MarkdownToHtmlViewHelper
31
 *
32
 * @author Elias Häußler <elias@haeussler.dev>
33
 * @license GPL-2.0-or-later
34
 */
35
final class MarkdownToHtmlViewHelper extends Fluid\Core\ViewHelper\AbstractViewHelper
36
{
37
    protected $escapeChildren = false;
38
    protected $escapeOutput = false;
39

40
    public function initializeArguments(): void
1✔
41
    {
42
        $this->registerArgument(
1✔
43
            'markdown',
1✔
44
            'string',
1✔
45
            'The markdown text to convert',
1✔
46
            true,
1✔
47
        );
1✔
48
        $this->registerArgument(
1✔
49
            'replaceLineNumbersInCodeSnippets',
1✔
50
            'boolean',
1✔
51
            'Whether to replace line numbers following the error page markup',
1✔
52
            false,
1✔
53
            false,
1✔
54
        );
1✔
55
    }
56

57
    public function getContentArgumentName(): string
3✔
58
    {
59
        return 'markdown';
3✔
60
    }
61

62
    public function render(): string
3✔
63
    {
64
        $markdown = $this->renderChildren();
3✔
65
        /** @var bool $replaceLineNumbers */
66
        $replaceLineNumbers = $this->arguments['replaceLineNumbersInCodeSnippets'] ?? false;
3✔
67

68
        // This should never happen, but makes PHPStan happy :)
69
        if (!is_string($markdown)) {
3✔
NEW
70
            return '';
×
71
        }
72

73
        // Convert markdown to HTML
74
        $html = (string)Markdown::new()->setContent($markdown)->toHtml();
3✔
75

76
        // Replace line numbers
77
        if ($replaceLineNumbers) {
3✔
78
            $html = self::replaceLineNumbersInCodeSnippets($html);
1✔
79
        }
80

81
        return $html;
3✔
82
    }
83

84
    private static function replaceLineNumbersInCodeSnippets(string $html): string
1✔
85
    {
86
        return \preg_replace(
1✔
87
            '/<\/span>\s*<span/',
1✔
88
            '</span><span',
1✔
89
            \preg_replace_callback(
1✔
90
                '/<pre><code>(.*?)<\/code><\/pre>/s',
1✔
91
                static fn(array $matches): string => self::replaceLineNumbersInCodeSnippet($matches[1]),
1✔
92
                $html,
1✔
93
            ) ?? $html,
1✔
94
        ) ?? $html;
1✔
95
    }
96

97
    private static function replaceLineNumbersInCodeSnippet(string $codeSnippet): string
1✔
98
    {
99
        $replacements = 0;
1✔
100
        $codeSnippetWithLineNumbers = \preg_replace(
1✔
101
            '/^(\d+)\s(.*)$/m',
1✔
102
            '<span data-line="$1">$2</span>',
1✔
103
            $codeSnippet,
1✔
104
            -1,
1✔
105
            $replacements,
1✔
106
        );
1✔
107

108
        if ($replacements === 0) {
1✔
109
            return '<pre><code>' . $codeSnippet . '</code></pre>';
1✔
110
        }
111

112
        return '<pre class="has-line-numbers">' . $codeSnippetWithLineNumbers . '</pre>';
1✔
113
    }
114
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc