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

dg / texy / 39601969498

05 Oct 2026 06:36AM UTC coverage: 95.456% (-0.9%) from 96.335%
39601969498

push

github

dg
examples: Figure as Definition List lives in one directory

The demo sat in "Figure as Definition List" while its sample and image
were in "figure as definition list", and the readme linked the latter;
on a case-sensitive filesystem the demo did not find its sample.

3508 of 3675 relevant lines covered (95.46%)

0.95 hits per line

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

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

3
/**
4
 * This file is part of the Texy! (https://texy.deegee.dev)
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\Parsing\ParseContext;
13
use Texy\{Range, Syntax};
14
use function strlen;
15

16

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

27

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

42

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

52
                $startOffset = $offsets[0];
1 ✔
53
                $totalLength = strlen($matches[0]);
1 ✔
54

55
                // Collect lines with their absolute offsets
56
                $lines = [['content' => $mContent, 'offset' => $offsets[3]]];
1 ✔
57
                $spaces = max(1, strlen($mPrefix));
1 ✔
58

59
                while ($context->getBlockParser()->next("~^>(?: | ([ \\t]{1,$spaces} | :) (.*))$~mAx", $nextMatches, $nextOffsets)) {
1 ✔
60
                        // group 0 always participates in a successful match, but next() cannot type that
61
                        $line = $nextMatches[0] ?? throw new \LogicException('Match without group 0.');
1 ✔
62
                        $lineOffset = $nextOffsets[0] ?? throw new \LogicException('Match without group 0.');
1 ✔
63

64
                        $totalLength += strlen($line) + 1; // +1 for \n
1 ✔
65

66
                        // Track where this line's content starts in absolute terms
67
                        $lineContentOffset = $nextOffsets[2] ?? $lineOffset + 2; // after "> "
1 ✔
68
                        $lines[] = ['content' => $nextMatches[2] ?? '', 'offset' => $lineContentOffset];
1 ✔
69
                }
70

71
                // Join content for parsing, but track line boundaries
72
                $content = implode("\n", array_column($lines, 'content'));
1 ✔
73
                $trimmed = trim($content);
1 ✔
74

75
                // Parse nested content
76
                $parsed = $context->parseBlock($trimmed);
1 ✔
77
                if (!$parsed->children) {
1 ✔
78
                        return null;
×
79
                }
80

81
                // Fix positions in parsed content using offset map
82
                Texy\Parsing\OffsetMap::fromLines($lines, strlen($content) - strlen(ltrim($content)))
1 ✔
83
                        ->applyTo($parsed);
1 ✔
84

85
                return new BlockQuoteNode(
1 ✔
86
                        $parsed,
87
                        Texy\Modifier::parse($mMod, $offsets[1] ?? null),
1 ✔
88
                        new Range($startOffset, $totalLength),
1 ✔
89
                );
90
        }
91
}
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