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

nette / latte / 25697602057

11 May 2026 09:11PM UTC coverage: 95.002%. Remained the same
25697602057

push

github

dg
added |json filter with context-aware attribute encoding [WIP]

In HTML attribute context (via ExpressionAttributeNode), `|json` routes to
HtmlHelpers::formatJsonAttribute() which uses the same JSON + smart-quoting
mechanism as formatDataAttribute(). Elsewhere it uses Helpers::encodeJson(),
refactored out of escapeJs() without the HtmlStringable unwrap branch.

20 of 22 new or added lines in 5 files covered. (90.91%)

2 existing lines in 2 files now uncovered.

5721 of 6022 relevant lines covered (95.0%)

0.95 hits per line

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

91.67
/src/Latte/Compiler/Nodes/Php/ModifierNode.php
1
<?php declare(strict_types=1);
2

3
/**
4
 * This file is part of the Latte (https://latte.nette.org)
5
 * Copyright (c) 2008 David Grudl (https://davidgrudl.com)
6
 */
7

8
namespace Latte\Compiler\Nodes\Php;
9

10
use Latte\Compiler\Node;
11
use Latte\Compiler\Position;
12
use Latte\Compiler\PrintContext;
13
use Latte\Helpers;
14

15

16
/**
17
 * Chain of filters with auto-escape flag.
18
 */
19
class ModifierNode extends Node
20
{
21
        /** @deprecated */
22
        public bool $check = true;
23

24

25
        public function __construct(
1✔
26
                /** @var FilterNode[] */
27
                public array $filters,
28
                public bool $escape = false,
29
                public ?Position $position = null,
30
        ) {
31
                (function (FilterNode ...$args) {})(...$filters);
1✔
32
        }
1✔
33

34

35
        public function hasFilter(string $name): bool
1✔
36
        {
37
                foreach ($this->filters as $filter) {
1✔
38
                        if ($filter->name->name === $name) {
1✔
39
                                return true;
1✔
40
                        }
41
                }
42

43
                return false;
1✔
44
        }
45

46

47
        /**
48
         * Removes and returns a matching filter, or null if no matching filter is found at the requested position.
49
         * Position: '' (default) = anywhere, 'first' = only at index 0, 'last' = only at the last index.
50
         */
51
        public function removeFilter(string $name, string $position = ''): ?FilterNode
1✔
52
        {
53
                $indexes = match ($position) {
1✔
54
                        '' => array_keys($this->filters),
1✔
NEW
55
                        'first' => $this->filters ? [array_key_first($this->filters)] : [],
×
56
                        'last' => $this->filters ? [array_key_last($this->filters)] : [],
1✔
NEW
57
                        default => throw new \InvalidArgumentException("Invalid position '$position', expected '', 'first' or 'last'."),
×
58
                };
59
                foreach ($indexes as $i) {
1✔
60
                        if ($this->filters[$i]->name->name === $name) {
1✔
61
                                return array_splice($this->filters, $i, 1)[0];
1✔
62
                        }
63
                }
64
                return null;
1✔
65
        }
66

67

68
        public function print(PrintContext $context): string
69
        {
UNCOV
70
                throw new \LogicException('Cannot directly print ModifierNode');
×
71
        }
72

73

74
        public function printSimple(PrintContext $context, string $expr): string
1✔
75
        {
76
                $expr = FilterNode::printSimple($context, $this->filters, $expr);
1✔
77

78
                $escaper = $context->getEscaper();
1✔
79
                return $this->escape
1✔
80
                        ? $escaper->escape($expr)
1✔
81
                        : $escaper->escapeMandatory($expr, $this->position);
1✔
82
        }
83

84

85
        public function printContentAware(PrintContext $context, string $expr): string
1✔
86
        {
87
                foreach ($this->filters as $filter) {
1✔
88
                        $expr = $filter->printContentAware($context, $expr);
1✔
89
                }
90

91
                return $this->escape
1✔
92
                        ? $context->getEscaper()->escapeContent($expr)
1✔
93
                        : $expr;
1✔
94
        }
95

96

97
        public function &getIterator(): \Generator
1✔
98
        {
99
                foreach ($this->filters as &$filter) {
1✔
100
                        yield $filter;
1✔
101
                }
102
                Helpers::removeNulls($this->filters);
1✔
103
        }
1✔
104
}
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