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

nette / latte / 25698863745

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

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

96.0
/src/Latte/Runtime/Helpers.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\Runtime;
9

10
use Latte;
11
use Latte\ContentType;
12
use Latte\RuntimeException;
13
use Nette;
14
use function addcslashes, is_string, json_encode, preg_replace, str_replace, strtoupper;
15
use const JSON_INVALID_UTF8_SUBSTITUTE, JSON_THROW_ON_ERROR, JSON_UNESCAPED_SLASHES, JSON_UNESCAPED_UNICODE;
16

17

18
/**
19
 * Template runtime helpers.
20
 * @internal
21
 */
22
class Helpers
23
{
24
        /**
25
         * Ensures the value is a string or returns null.
26
         * @return ($value is string ? string : null)
27
         */
28
        public static function stringOrNull(mixed $value): ?string
1✔
29
        {
30
                return is_string($value) ? $value : null;
1✔
31
        }
32

33

34
        /**
35
         * Escapes string for use inside CSS template.
36
         */
37
        public static function escapeCss(mixed $s): string
1✔
38
        {
39
                // http://www.w3.org/TR/2006/WD-CSS21-20060411/syndata.html#q6
40
                return addcslashes((string) $s, "\x00..\x1F!\"#$%&'()*+,./:;<=>?@[\\]^`{|}~");
1✔
41
        }
42

43

44
        /**
45
         * Escapes variables for use inside <script>.
46
         */
47
        public static function escapeJs(mixed $s): string
1✔
48
        {
49
                if ($s instanceof HtmlStringable || $s instanceof Nette\HtmlStringable) {
1✔
50
                        $s = $s->__toString();
1✔
51
                }
52

53
                return self::encodeJson($s);
1✔
54
        }
55

56

57
        /**
58
         * Encodes value as JSON, safe for embedding into HTML/XML (escapes ]]>, <!, </).
59
         */
60
        public static function encodeJson(mixed $value): string
1✔
61
        {
62
                $json = json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_INVALID_UTF8_SUBSTITUTE | JSON_THROW_ON_ERROR);
1✔
63
                return str_replace([']]>', '<!', '</'], [']]\u003E', '\u003C!', '<\/'], $json);
1✔
64
        }
65

66

67
        /**
68
         * Escapes string for use inside iCal template.
69
         */
70
        public static function escapeICal(mixed $s): string
1✔
71
        {
72
                // https://www.ietf.org/rfc/rfc5545.txt
73
                $s = str_replace("\r", '', (string) $s);
1✔
74
                $s = preg_replace('#[\x00-\x08\x0B-\x1F]#', "\u{FFFD}", (string) $s);
1✔
75
                return addcslashes($s, "\";\\,:\n");
1✔
76
        }
77

78

79
        /**
80
         * Converts content between content types.
81
         */
82
        public static function convertTo(FilterInfo $info, string $dest, string $s): string
1✔
83
        {
84
                $source = $info->contentType ?: ContentType::Text;
1✔
85
                if ($source === $dest) {
1✔
86
                        return $s;
1✔
87
                } elseif ($conv = Latte\Compiler\Escaper::getConvertor($source, $dest)) {
1✔
88
                        $info->contentType = $dest;
1✔
89
                        return $conv($s);
1✔
90
                } else {
UNCOV
91
                        throw new RuntimeException('Filters: unable to convert content type ' . strtoupper($source) . ' to ' . strtoupper($dest));
×
92
                }
93
        }
94

95

96
        public static function nop(mixed $s): string
1✔
97
        {
98
                return (string) $s;
1✔
99
        }
100
}
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