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

dg / texy / 29654833201

18 Jul 2026 04:09PM UTC coverage: 93.039% (+0.04%) from 93.004%
29654833201

push

github

dg
Restored test coverage dropped during the AST migration

The migration removed five test files coupled to v3 contracts (block,
content-model, formatter-indent, html, latte) with the intent to bring
them back once the output layer settled. Restored here, ported to the
AST-era API; latte and most of content-model pass unchanged.

Expected outputs were re-derived and every difference against the v3
files reviewed case by case. The differences fall into the intentional
categories: list items merge continuation lines, whitespace-sensitive
typography follows visible length instead of protection-mark key length,
rejected tags are escaped consistently (both halves of a pair) with
typography applied to the escaped text, paragraphs of escaped markup are
<p>-wrapped, and <p> inside <form> is preserved. Inner texysource
fragments are parsed without the transform phase, so their passthrough
tags stay live - a documented wrinkle.

content-model.phpt again guards the WellFormer content model, nesting
prohibitions, transparent and unknown elements and auto-closing in the
public suite, independently of the private regression corpus.

3248 of 3491 relevant lines covered (93.04%)

0.93 hits per line

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

97.14
/src/Texy/Modules/BlockQuoteModule.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\Nodes\BlockQuoteNode;
12
use Texy\ParseContext;
13
use Texy\Position;
14
use Texy\Syntax;
15
use function max, strlen;
16

17

18
/**
19
 * Processes blockquote syntax with nested content.
20
 */
21
final class BlockQuoteModule extends Texy\Module
22
{
23
        public function __construct(
1✔
24
                private Texy\Texy $texy,
25
        ) {
26
        }
1✔
27

28

29
        public function beforeParse(string &$text): void
1✔
30
        {
31
                $this->texy->registerBlockPattern(
1✔
32
                        $this->parse(...),
1✔
33
                        '~^
34
                                (?: ' . Texy\Patterns::MODIFIER_H . '\n)? # modifier (1)
1✔
35
                                >                                      # blockquote char
36
                                ( [ \t]++ | : )                        # space/tab or colon (2)
37
                                ( \S.*+ )                              # content (3)
38
                        $~mU',
39
                        Syntax::Blockquote,
1✔
40
                );
41
        }
1✔
42

43

44
        /**
45
         * Parses blockquote.
46
         * @param  array<?string>  $matches
47
         * @param  array<?int>  $offsets
48
         */
49
        public function parse(ParseContext $context, array $matches, array $offsets): ?BlockQuoteNode
1✔
50
        {
51
                /** @var array{string, ?string, string, string} $matches */
52
                [, $mMod, $mPrefix, $mContent] = $matches;
1✔
53

54
                $startOffset = $offsets[0];
1✔
55
                $totalLength = strlen($matches[0]);
1✔
56
                $contentOffset = $offsets[3] ?? $offsets[0] + 2; // offset of first line content
1✔
57

58
                // Collect lines with their absolute offsets
59
                $lines = [['content' => $mContent ?? '', 'offset' => $contentOffset]];
1✔
60
                $spaces = '';
1✔
61

62
                do {
63
                        if ($spaces === '') {
1✔
64
                                $spaces = max(1, strlen($mPrefix ?? ''));
1✔
65
                        }
66

67
                        if (!$context->getBlockParser()->next("~^>(?: | ([ \\t]{1,$spaces} | :) (.*))$~mA", $matches, $nextOffsets)) {
1✔
68
                                break;
1✔
69
                        }
70

71
                        $totalLength += strlen($matches[0]) + 1; // +1 for \n
1✔
72
                        [, $mPrefix, $mContent] = $matches;
1✔
73

74
                        // Track where this line's content starts in absolute terms
75
                        $lineContentOffset = $nextOffsets[2] ?? ($nextOffsets[0] + 2); // after "> "
1✔
76
                        $lines[] = ['content' => $mContent ?? '', 'offset' => $lineContentOffset];
1✔
77
                } while (true);
1✔
78

79
                // Join content for parsing, but track line boundaries
80
                $content = implode("\n", array_column($lines, 'content'));
1✔
81
                $trimmed = trim($content);
1✔
82

83
                // Parse nested content
84
                $parsed = $context->parseBlock($trimmed);
1✔
85
                if (!$parsed->children) {
1✔
86
                        return null;
×
87
                }
88

89
                // Fix positions in parsed content using offset map
90
                Texy\OffsetMap::fromLines($lines, strlen($content) - strlen(ltrim($content)))
1✔
91
                        ->applyTo($parsed);
1✔
92

93
                return new BlockQuoteNode(
1✔
94
                        $parsed,
1✔
95
                        Texy\Modifier::parse($mMod),
1✔
96
                        new Position($startOffset, $totalLength),
1✔
97
                );
98
        }
99
}
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