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

dg / texy / 29746802114

20 Jul 2026 01:19PM UTC coverage: 94.677% (+0.04%) from 94.641%
29746802114

push

github

dg
Dead code removed

- Engine::getPatternNames() and Texy::getEngine(): no callers in src or tests.
- LinkDefinitionModule::resolveUrl(): unreachable. Both bracket forms it
  handles ([*img*] and [ref]) are already consumed by earlier returns in
  resolveLinkNodeUrl(), so it could only ever return its argument unchanged.
- Text\Renderer: CodeBlockNode type 'comment' never exists; comments are a
  separate CommentNode. Leftover from before the node split.

1 of 1 new or added line in 1 file covered. (100.0%)

74 existing lines in 15 files now uncovered.

3344 of 3532 relevant lines covered (94.68%)

0.95 hits per line

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

96.83
/src/Texy/Modules/BlockModule.php
1
<?php declare(strict_types=1);
2

3
/**
4
 * This file is part of the Texy! (https://texy.nette.org)
5
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
6
 */
7

8
namespace Texy\Modules;
9

10
use Texy;
11
use Texy\Helpers;
12
use Texy\Nodes\BlockNode;
13
use Texy\Nodes\CodeBlockNode;
14
use Texy\Nodes\CommentNode;
15
use Texy\Nodes\SectionNode;
16
use Texy\ParseContext;
17
use Texy\Range;
18
use Texy\Syntax;
19
use function strlen, trim;
20

21

22
/**
23
 * Processes special blocks (/-- code, html, text, div, etc.).
24
 */
25
final class BlockModule extends Texy\Module
26
{
27
        public function __construct(
1✔
28
                private Texy\Texy $texy,
29
        ) {
30
                $texy->allowed[Syntax::BlockDefault] = true;
1✔
31
                $texy->allowed[Syntax::BlockPre] = true;
1✔
32
                $texy->allowed[Syntax::BlockCode] = true;
1✔
33
                $texy->allowed[Syntax::BlockHtml] = true;
1✔
34
                $texy->allowed[Syntax::BlockText] = true;
1✔
35
                $texy->allowed[Syntax::BlockTexySource] = true;
1✔
36
                $texy->allowed[Syntax::BlockComment] = true;
1✔
37
                $texy->allowed[Syntax::BlockDiv] = true;
1✔
38
                $texy->allowed[Syntax::CodeFenced] = true;
1✔
39
        }
1✔
40

41

42
        public function beforeParse(string &$text): void
1✔
43
        {
44
                $this->texy->registerBlockPattern(
1✔
45
                        $this->parse(...),
1✔
46
                        '~^
47
                                /--++ \ *+                    # opening tag /--
48
                                (.*)                          # content type (1)
49
                                ' . Texy\Patterns::ModifierHAlign . '? # modifier (2)
1✔
50
                                $
51
                                ((?:                         # content (3)
52
                                        \n (?0) |                # recursive nested blocks
53
                                        \n.*+                    # or any content
54
                                )*)
55
                                (?:
56
                                        \n \\\--.* $ |           # closing tag
57
                                        \z                       # or end of input
58
                                )
59
                        ~mUix',
60
                        Syntax::Blocks,
1✔
61
                );
62

63
                // ```language
64
                $this->texy->registerBlockPattern(
1✔
65
                        $this->parseFenced(...),
1✔
66
                        '~^
1✔
67
                                (`{3,}) \ *+                        # opening fence (1)
68
                                ([^\n`]*)                           # info string (2)
69
                                $
70
                                ((?: \n (?! \1 `*+ \ *+ $ ) .*+ )*) # content (3): lines that are not a valid closing fence
71
                                (?:
72
                                        \n \1 `*+ \ *+ $ |              # closing fence (same length or longer)
73
                                        \z                              # or end of input
74
                                )
75
                        ~mx',
76
                        Syntax::CodeFenced,
1✔
77
                );
78
        }
1✔
79

80

81
        /**
82
         * Parses ```language fenced code blocks; content is verbatim.
83
         * @param  array{string, string, string, string}  $matches
84
         * @param  array{int, int, int, int}  $offsets
85
         */
86
        public function parseFenced(ParseContext $context, array $matches, array $offsets): CodeBlockNode
1✔
87
        {
88
                [, , $mInfo, $mContent] = $matches;
1✔
89

90
                // first word of the info string is the language (GFM)
91
                $language = Texy\Regexp::split(trim($mInfo), '~\s+~', limit: 2)[0];
1✔
92

93
                return new CodeBlockNode(
1✔
94
                        'code',
1✔
95
                        substr($mContent, 1), // drop the separator "\n"; intentional blank lines stay
1✔
96
                        $language === '' ? null : $language,
1✔
97
                        null,
1✔
98
                        new Range($offsets[0], strlen($matches[0])),
1✔
99
                );
100
        }
101

102

103
        /**
104
         * Parses blocks /--foo
105
         * @param  array{string, string, ?string, string}  $matches
106
         * @param  array{int, int, ?int, int}  $offsets
107
         */
108
        public function parse(ParseContext $context, array $matches, array $offsets): ?BlockNode
1✔
109
        {
110
                [, $mParam, $mMod, $mContent] = $matches;
1✔
111

112
                $mod = Texy\Modifier::parse($mMod, $offsets[2] ?? null);
1✔
113
                $parts = Texy\Regexp::split($mParam, '~\s+~', limit: 2);
1✔
114
                $blocktype = empty($parts[0]) ? Syntax::BlockDefault : 'block/' . $parts[0];
1✔
115
                $param = empty($parts[1]) ? null : $parts[1];
1✔
116

117
                $content = Helpers::outdent($mContent);
1✔
118
                $range = new Range($offsets[0], strlen($matches[0]));
1✔
119

120
                if ($blocktype === Syntax::BlockCode) {
1✔
121
                        return new CodeBlockNode('code', $content, $param, $mod, $range);
1✔
122

123
                } elseif ($blocktype === Syntax::BlockDefault || $blocktype === Syntax::BlockPre) {
1✔
124
                        return new CodeBlockNode($blocktype === Syntax::BlockPre ? 'pre' : 'default', $content, $param, $mod, $range);
1✔
125

126
                } elseif ($blocktype === Syntax::BlockComment) {
1✔
127
                        return new CommentNode($content, $range);
1✔
128

129
                } elseif ($blocktype === Syntax::BlockHtml) {
1✔
130
                        // html/text blocks don't use outdent - preserve original indentation
131
                        return new CodeBlockNode('html', trim($mContent, "\n"), null, $mod, $range);
1✔
132

133
                } elseif ($blocktype === Syntax::BlockText) {
1✔
134
                        // html/text blocks don't use outdent - preserve original indentation
135
                        return new CodeBlockNode('text', trim($mContent, "\n"), null, $mod, $range);
1✔
136

137
                } elseif ($blocktype === Syntax::BlockDiv) {
1✔
138
                        [$content, $map] = Texy\OffsetMap::outdentLines(
1✔
139
                                Texy\OffsetMap::linesOf($mContent, $offsets[3]),
1✔
140
                                firstLine: true,
1✔
141
                        );
142
                        if ($content === '') {
1✔
UNCOV
143
                                return null;
×
144
                        }
145
                        $parsed = $context->parseBlock($content);
1✔
146
                        $map->applyTo($parsed);
1✔
147
                        return new SectionNode($parsed, 'div', $mod, $range);
1✔
148

149
                } elseif ($blocktype === Syntax::BlockTexySource) {
1✔
150
                        // Store raw texy content, will be parsed and displayed as HTML source in handler
151
                        $content = Helpers::outdent($mContent);
1✔
152
                        if ($content === '') {
1✔
UNCOV
153
                                return null;
×
154
                        }
155
                        return new CodeBlockNode('texysource', $content, null, $mod, $range);
1✔
156
                }
157

158
                return null;
1✔
159
        }
160
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc