@vituum/vite-plugin-latte 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -0
- package/handler.js +9 -0
- package/index.js +138 -0
- package/index.php +173 -0
- package/latte/AssetFilter.php +11 -0
- package/latte/FetchFunction.php +28 -0
- package/latte/IconFilter.php +14 -0
- package/latte/JsonTag.php +64 -0
- package/latte/PlaceholderFunction.php +11 -0
- package/latte/RandomColorFunction.php +14 -0
- package/latte/TelFilter.php +22 -0
- package/package.json +35 -0
- package/vendor/autoload.php +7 -0
- package/vendor/bin/latte-lint +107 -0
- package/vendor/composer/ClassLoader.php +572 -0
- package/vendor/composer/InstalledVersions.php +350 -0
- package/vendor/composer/LICENSE +21 -0
- package/vendor/composer/autoload_classmap.php +183 -0
- package/vendor/composer/autoload_namespaces.php +9 -0
- package/vendor/composer/autoload_psr4.php +9 -0
- package/vendor/composer/autoload_real.php +57 -0
- package/vendor/composer/autoload_static.php +193 -0
- package/vendor/composer/installed.json +93 -0
- package/vendor/composer/installed.php +32 -0
- package/vendor/composer/platform_check.php +26 -0
- package/vendor/latte/latte/bin/latte-lint +29 -0
- package/vendor/latte/latte/composer.json +53 -0
- package/vendor/latte/latte/license.md +60 -0
- package/vendor/latte/latte/ncs.php +14 -0
- package/vendor/latte/latte/ncs.xml +9 -0
- package/vendor/latte/latte/readme.md +21 -0
- package/vendor/latte/latte/src/Bridges/Tracy/BlueScreenPanel.php +114 -0
- package/vendor/latte/latte/src/Bridges/Tracy/LattePanel.php +99 -0
- package/vendor/latte/latte/src/Bridges/Tracy/templates/LattePanel.panel.phtml +98 -0
- package/vendor/latte/latte/src/Bridges/Tracy/templates/LattePanel.tab.phtml +15 -0
- package/vendor/latte/latte/src/Latte/Compiler/Block.php +44 -0
- package/vendor/latte/latte/src/Latte/Compiler/Escaper.php +244 -0
- package/vendor/latte/latte/src/Latte/Compiler/ExpressionBuilder.php +128 -0
- package/vendor/latte/latte/src/Latte/Compiler/Node.php +28 -0
- package/vendor/latte/latte/src/Latte/Compiler/NodeHelpers.php +132 -0
- package/vendor/latte/latte/src/Latte/Compiler/NodeTraverser.php +77 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/AreaNode.php +17 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/AuxiliaryNode.php +27 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/FragmentNode.php +59 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/AttributeNode.php +48 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/BogusTagNode.php +46 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/CommentNode.php +39 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/ElementNode.php +129 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/QuotedValue.php +53 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/NopNode.php +21 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ArgumentNode.php +45 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ComplexTypeNode.php +17 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ArrayAccessNode.php +41 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ArrayItemNode.php +52 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ArrayNode.php +94 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AssignNode.php +39 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AssignOpNode.php +45 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/BinaryOpNode.php +65 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/CastNode.php +43 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ClassConstantFetchNode.php +42 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/CloneNode.php +36 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ClosureNode.php +73 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ClosureUseNode.php +37 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ConstantFetchNode.php +37 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/EmptyNode.php +36 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ErrorSuppressNode.php +36 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/FilterCallNode.php +39 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/FunctionCallNode.php +45 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/FunctionCallableNode.php +39 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/InRangeNode.php +42 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/InstanceofNode.php +40 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/IssetNode.php +40 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/MatchNode.php +49 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/MethodCallNode.php +50 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/MethodCallableNode.php +42 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/NewNode.php +45 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/NotNode.php +36 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PostOpNode.php +43 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PreOpNode.php +43 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PropertyFetchNode.php +42 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticCallNode.php +55 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticCallableNode.php +47 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticPropertyFetchNode.php +42 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/TernaryNode.php +50 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/UnaryOpNode.php +45 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/VariableNode.php +40 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ExpressionNode.php +17 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/FilterNode.php +67 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/IdentifierNode.php +36 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/IntersectionTypeNode.php +39 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/MatchArmNode.php +45 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ModifierNode.php +107 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/NameNode.php +89 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/NullableTypeNode.php +35 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ParameterNode.php +54 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/BooleanNode.php +30 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/EncapsedStringNode.php +80 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/EncapsedStringPartNode.php +30 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/FloatNode.php +63 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/IntegerNode.php +70 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/NullNode.php +29 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/StringNode.php +40 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ScalarNode.php +15 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/SuperiorTypeNode.php +29 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/UnionTypeNode.php +39 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/VarLikeIdentifierNode.php +21 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/StatementNode.php +15 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/TemplateNode.php +34 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/TextNode.php +37 -0
- package/vendor/latte/latte/src/Latte/Compiler/PhpHelpers.php +227 -0
- package/vendor/latte/latte/src/Latte/Compiler/Position.php +43 -0
- package/vendor/latte/latte/src/Latte/Compiler/PrintContext.php +334 -0
- package/vendor/latte/latte/src/Latte/Compiler/Tag.php +117 -0
- package/vendor/latte/latte/src/Latte/Compiler/TagLexer.php +399 -0
- package/vendor/latte/latte/src/Latte/Compiler/TagParser.php +388 -0
- package/vendor/latte/latte/src/Latte/Compiler/TagParserData.php +580 -0
- package/vendor/latte/latte/src/Latte/Compiler/TemplateGenerator.php +206 -0
- package/vendor/latte/latte/src/Latte/Compiler/TemplateLexer.php +391 -0
- package/vendor/latte/latte/src/Latte/Compiler/TemplateParser.php +448 -0
- package/vendor/latte/latte/src/Latte/Compiler/TemplateParserHtml.php +506 -0
- package/vendor/latte/latte/src/Latte/Compiler/Token.php +259 -0
- package/vendor/latte/latte/src/Latte/Compiler/TokenStream.php +151 -0
- package/vendor/latte/latte/src/Latte/ContentType.php +22 -0
- package/vendor/latte/latte/src/Latte/Engine.php +591 -0
- package/vendor/latte/latte/src/Latte/Essential/Blueprint.php +160 -0
- package/vendor/latte/latte/src/Latte/Essential/CachingIterator.php +232 -0
- package/vendor/latte/latte/src/Latte/Essential/CoreExtension.php +232 -0
- package/vendor/latte/latte/src/Latte/Essential/Filters.php +591 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/BlockNode.php +161 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/CaptureNode.php +98 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/ContentTypeNode.php +74 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/DebugbreakNode.php +53 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/DefineNode.php +134 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/DoNode.php +49 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/DumpNode.php +58 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/EmbedNode.php +125 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/ExtendsNode.php +60 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/FirstLastSepNode.php +81 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/ForNode.php +91 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/ForeachNode.php +155 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/IfChangedNode.php +141 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/IfContentNode.php +82 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/IfNode.php +180 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/ImportNode.php +49 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/IncludeBlockNode.php +140 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/IncludeFileNode.php +81 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/IterateWhileNode.php +94 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/NAttrNode.php +105 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/NClassNode.php +54 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/NTagNode.php +79 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/ParametersNode.php +84 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/PrintNode.php +70 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/RawPhpNode.php +46 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/RollbackNode.php +37 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/SkipNode.php +71 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/SpacelessNode.php +62 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/SwitchNode.php +118 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/TemplatePrintNode.php +39 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/TemplateTypeNode.php +38 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/TraceNode.php +35 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/TranslateNode.php +104 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/TryNode.php +75 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/VarNode.php +106 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/VarPrintNode.php +40 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/VarTypeNode.php +36 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/WhileNode.php +81 -0
- package/vendor/latte/latte/src/Latte/Essential/Passes.php +115 -0
- package/vendor/latte/latte/src/Latte/Essential/RawPhpExtension.php +28 -0
- package/vendor/latte/latte/src/Latte/Essential/RollbackException.php +16 -0
- package/vendor/latte/latte/src/Latte/Essential/Tracer.php +117 -0
- package/vendor/latte/latte/src/Latte/Essential/TranslatorExtension.php +101 -0
- package/vendor/latte/latte/src/Latte/Extension.php +97 -0
- package/vendor/latte/latte/src/Latte/Helpers.php +96 -0
- package/vendor/latte/latte/src/Latte/Loader.php +37 -0
- package/vendor/latte/latte/src/Latte/Loaders/FileLoader.php +95 -0
- package/vendor/latte/latte/src/Latte/Loaders/StringLoader.php +76 -0
- package/vendor/latte/latte/src/Latte/Policy.php +24 -0
- package/vendor/latte/latte/src/Latte/PositionAwareException.php +50 -0
- package/vendor/latte/latte/src/Latte/Runtime/Block.php +24 -0
- package/vendor/latte/latte/src/Latte/Runtime/FilterExecutor.php +151 -0
- package/vendor/latte/latte/src/Latte/Runtime/FilterInfo.php +39 -0
- package/vendor/latte/latte/src/Latte/Runtime/Filters.php +234 -0
- package/vendor/latte/latte/src/Latte/Runtime/Html.php +35 -0
- package/vendor/latte/latte/src/Latte/Runtime/HtmlStringable.php +17 -0
- package/vendor/latte/latte/src/Latte/Runtime/Template.php +381 -0
- package/vendor/latte/latte/src/Latte/Sandbox/Nodes/FunctionCallNode.php +30 -0
- package/vendor/latte/latte/src/Latte/Sandbox/Nodes/FunctionCallableNode.php +29 -0
- package/vendor/latte/latte/src/Latte/Sandbox/Nodes/MethodCallNode.php +32 -0
- package/vendor/latte/latte/src/Latte/Sandbox/Nodes/MethodCallableNode.php +30 -0
- package/vendor/latte/latte/src/Latte/Sandbox/Nodes/PropertyFetchNode.php +32 -0
- package/vendor/latte/latte/src/Latte/Sandbox/Nodes/SandboxNode.php +73 -0
- package/vendor/latte/latte/src/Latte/Sandbox/Nodes/StaticCallNode.php +31 -0
- package/vendor/latte/latte/src/Latte/Sandbox/Nodes/StaticCallableNode.php +30 -0
- package/vendor/latte/latte/src/Latte/Sandbox/Nodes/StaticPropertyFetchNode.php +32 -0
- package/vendor/latte/latte/src/Latte/Sandbox/RuntimeChecker.php +116 -0
- package/vendor/latte/latte/src/Latte/Sandbox/SandboxExtension.php +132 -0
- package/vendor/latte/latte/src/Latte/Sandbox/SecurityPolicy.php +185 -0
- package/vendor/latte/latte/src/Latte/Strict.php +101 -0
- package/vendor/latte/latte/src/Latte/attributes.php +24 -0
- package/vendor/latte/latte/src/Latte/exceptions.php +69 -0
- package/vendor/latte/latte/src/Tools/Linter.php +175 -0
|
@@ -0,0 +1,591 @@
|
|
|
1
|
+
<?php
|
|
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
|
+
declare(strict_types=1);
|
|
9
|
+
|
|
10
|
+
namespace Latte\Essential;
|
|
11
|
+
|
|
12
|
+
use Latte;
|
|
13
|
+
use Latte\ContentType;
|
|
14
|
+
use Latte\Runtime\FilterInfo;
|
|
15
|
+
use Latte\Runtime\Html;
|
|
16
|
+
use Stringable;
|
|
17
|
+
use function is_array, is_string, count, strlen;
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Template filters. Uses UTF-8 only.
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
final class Filters
|
|
25
|
+
{
|
|
26
|
+
/**
|
|
27
|
+
* Converts HTML to plain text.
|
|
28
|
+
*/
|
|
29
|
+
public static function stripHtml(FilterInfo $info, $s): string
|
|
30
|
+
{
|
|
31
|
+
$info->validate([null, 'html', 'html/attr', 'xml', 'xml/attr'], __FUNCTION__);
|
|
32
|
+
$info->contentType = ContentType::Text;
|
|
33
|
+
return html_entity_decode(strip_tags((string) $s), ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Removes tags from HTML (but remains HTML entites).
|
|
39
|
+
*/
|
|
40
|
+
public static function stripTags(FilterInfo $info, $s): string
|
|
41
|
+
{
|
|
42
|
+
$info->contentType ??= ContentType::Html;
|
|
43
|
+
$info->validate(['html', 'html/attr', 'xml', 'xml/attr'], __FUNCTION__);
|
|
44
|
+
return strip_tags((string) $s);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Replaces all repeated white spaces with a single space.
|
|
50
|
+
*/
|
|
51
|
+
public static function strip(FilterInfo $info, string $s): string
|
|
52
|
+
{
|
|
53
|
+
return $info->contentType === ContentType::Html
|
|
54
|
+
? trim(self::spacelessHtml($s))
|
|
55
|
+
: trim(self::spacelessText($s));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Replaces all repeated white spaces with a single space.
|
|
61
|
+
*/
|
|
62
|
+
public static function spacelessHtml(string $s, bool &$strip = true): string
|
|
63
|
+
{
|
|
64
|
+
return preg_replace_callback(
|
|
65
|
+
'#[ \t\r\n]+|<(/)?(textarea|pre|script)(?=\W)#si',
|
|
66
|
+
function ($m) use (&$strip) {
|
|
67
|
+
if (empty($m[2])) {
|
|
68
|
+
return $strip ? ' ' : $m[0];
|
|
69
|
+
} else {
|
|
70
|
+
$strip = !empty($m[1]);
|
|
71
|
+
return $m[0];
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
$s,
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Output buffering handler for spacelessHtml.
|
|
81
|
+
*/
|
|
82
|
+
public static function spacelessHtmlHandler(string $s, ?int $phase = null): string
|
|
83
|
+
{
|
|
84
|
+
static $strip;
|
|
85
|
+
$left = $right = '';
|
|
86
|
+
|
|
87
|
+
if ($phase & PHP_OUTPUT_HANDLER_START) {
|
|
88
|
+
$strip = true;
|
|
89
|
+
$tmp = ltrim($s);
|
|
90
|
+
$left = substr($s, 0, strlen($s) - strlen($tmp));
|
|
91
|
+
$s = $tmp;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if ($phase & PHP_OUTPUT_HANDLER_FINAL) {
|
|
95
|
+
$tmp = rtrim($s);
|
|
96
|
+
$right = substr($s, strlen($tmp));
|
|
97
|
+
$s = $tmp;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return $left . self::spacelessHtml($s, $strip) . $right;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Replaces all repeated white spaces with a single space.
|
|
106
|
+
*/
|
|
107
|
+
public static function spacelessText(string $s): string
|
|
108
|
+
{
|
|
109
|
+
return preg_replace('#[ \t\r\n]+#', ' ', $s);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Indents plain text or HTML the content from the left.
|
|
115
|
+
*/
|
|
116
|
+
public static function indent(FilterInfo $info, string $s, int $level = 1, string $chars = "\t"): string
|
|
117
|
+
{
|
|
118
|
+
if ($level < 1) {
|
|
119
|
+
// do nothing
|
|
120
|
+
} elseif ($info->contentType === ContentType::Html) {
|
|
121
|
+
$s = preg_replace_callback('#<(textarea|pre).*?</\1#si', fn($m) => strtr($m[0], " \t\r\n", "\x1F\x1E\x1D\x1A"), $s);
|
|
122
|
+
if (preg_last_error()) {
|
|
123
|
+
throw new Latte\RegexpException;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
$s = preg_replace('#(?:^|[\r\n]+)(?=[^\r\n])#', '$0' . str_repeat($chars, $level), $s);
|
|
127
|
+
$s = strtr($s, "\x1F\x1E\x1D\x1A", " \t\r\n");
|
|
128
|
+
} else {
|
|
129
|
+
$s = preg_replace('#(?:^|[\r\n]+)(?=[^\r\n])#', '$0' . str_repeat($chars, $level), $s);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return $s;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Join array of text or HTML elements with a string.
|
|
138
|
+
* @param string[] $arr
|
|
139
|
+
*/
|
|
140
|
+
public static function implode(array $arr, string $glue = ''): string
|
|
141
|
+
{
|
|
142
|
+
return implode($glue, $arr);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Splits a string by a string.
|
|
148
|
+
*/
|
|
149
|
+
public static function explode(string $value, string $separator = ''): array
|
|
150
|
+
{
|
|
151
|
+
return $separator === ''
|
|
152
|
+
? preg_split('//u', $value, -1, PREG_SPLIT_NO_EMPTY)
|
|
153
|
+
: explode($separator, $value);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Repeats text.
|
|
159
|
+
*/
|
|
160
|
+
public static function repeat(FilterInfo $info, $s, int $count): string
|
|
161
|
+
{
|
|
162
|
+
return str_repeat((string) $s, $count);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Date/time formatting.
|
|
168
|
+
*/
|
|
169
|
+
public static function date(string|int|\DateTimeInterface|\DateInterval|null $time, ?string $format = null): ?string
|
|
170
|
+
{
|
|
171
|
+
if ($time == null) { // intentionally ==
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (!isset($format)) {
|
|
176
|
+
$format = Latte\Runtime\Filters::$dateFormat;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if ($time instanceof \DateInterval) {
|
|
180
|
+
return $time->format($format);
|
|
181
|
+
|
|
182
|
+
} elseif (is_numeric($time)) {
|
|
183
|
+
$time = new \DateTime('@' . $time);
|
|
184
|
+
$time->setTimeZone(new \DateTimeZone(date_default_timezone_get()));
|
|
185
|
+
|
|
186
|
+
} elseif (!$time instanceof \DateTimeInterface) {
|
|
187
|
+
$time = new \DateTime($time);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (str_contains($format, '%')) {
|
|
191
|
+
if (PHP_VERSION_ID >= 80100) {
|
|
192
|
+
trigger_error("Function strftime() used by filter |date is deprecated since PHP 8.1, use format without % characters like 'Y-m-d'.", E_USER_DEPRECATED);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return @strftime($format, $time->format('U') + 0);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return $time->format($format);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Converts to human readable file size.
|
|
204
|
+
*/
|
|
205
|
+
public static function bytes(float $bytes, int $precision = 2): string
|
|
206
|
+
{
|
|
207
|
+
$bytes = round($bytes);
|
|
208
|
+
$units = ['B', 'kB', 'MB', 'GB', 'TB', 'PB'];
|
|
209
|
+
foreach ($units as $unit) {
|
|
210
|
+
if (abs($bytes) < 1024 || $unit === end($units)) {
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
$bytes /= 1024;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return round($bytes, $precision) . ' ' . $unit;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Performs a search and replace.
|
|
223
|
+
*/
|
|
224
|
+
public static function replace(
|
|
225
|
+
FilterInfo $info,
|
|
226
|
+
string|array $subject,
|
|
227
|
+
string|array $search,
|
|
228
|
+
string|array|null $replace = null,
|
|
229
|
+
): string {
|
|
230
|
+
$subject = (string) $subject;
|
|
231
|
+
if (is_array($search)) {
|
|
232
|
+
if (is_array($replace)) {
|
|
233
|
+
return strtr($subject, array_combine($search, $replace));
|
|
234
|
+
} elseif ($replace === null && is_string(key($search))) {
|
|
235
|
+
return strtr($subject, $search);
|
|
236
|
+
} else {
|
|
237
|
+
return strtr($subject, array_fill_keys($search, $replace));
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return str_replace($search, $replace ?? '', $subject);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Perform a regular expression search and replace.
|
|
247
|
+
*/
|
|
248
|
+
public static function replaceRe(string $subject, string $pattern, string $replacement = ''): string
|
|
249
|
+
{
|
|
250
|
+
$res = preg_replace($pattern, $replacement, $subject);
|
|
251
|
+
if (preg_last_error()) {
|
|
252
|
+
throw new Latte\RegexpException;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return $res;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* The data: URI generator.
|
|
261
|
+
*/
|
|
262
|
+
public static function dataStream(string $data, ?string $type = null): string
|
|
263
|
+
{
|
|
264
|
+
if ($type === null) {
|
|
265
|
+
$type = finfo_buffer(finfo_open(FILEINFO_MIME_TYPE), $data);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return 'data:' . ($type ? "$type;" : '') . 'base64,' . base64_encode($data);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
public static function breaklines(string|Stringable|null $s): Html
|
|
273
|
+
{
|
|
274
|
+
$s = htmlspecialchars((string) $s, ENT_NOQUOTES | ENT_SUBSTITUTE, 'UTF-8');
|
|
275
|
+
return new Html(nl2br($s, Latte\Runtime\Filters::$xml));
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Returns a part of string.
|
|
281
|
+
*/
|
|
282
|
+
public static function substring(string|Stringable|null $s, int $start, ?int $length = null): string
|
|
283
|
+
{
|
|
284
|
+
$s = (string) $s;
|
|
285
|
+
if ($length === null) {
|
|
286
|
+
$length = self::strLength($s);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (function_exists('mb_substr')) {
|
|
290
|
+
return mb_substr($s, $start, $length, 'UTF-8'); // MB is much faster
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return iconv_substr($s, $start, $length, 'UTF-8');
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Truncates string to maximal length.
|
|
299
|
+
*/
|
|
300
|
+
public static function truncate(string|Stringable|null $s, int $length, string $append = "\u{2026}"): string
|
|
301
|
+
{
|
|
302
|
+
$s = (string) $s;
|
|
303
|
+
if (self::strLength($s) > $length) {
|
|
304
|
+
$length -= self::strLength($append);
|
|
305
|
+
if ($length < 1) {
|
|
306
|
+
return $append;
|
|
307
|
+
|
|
308
|
+
} elseif (preg_match('#^.{1,' . $length . '}(?=[\s\x00-/:-@\[-`{-~])#us', $s, $matches)) {
|
|
309
|
+
return $matches[0] . $append;
|
|
310
|
+
|
|
311
|
+
} else {
|
|
312
|
+
return self::substring($s, 0, $length) . $append;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
return $s;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Convert to lower case.
|
|
322
|
+
*/
|
|
323
|
+
public static function lower($s): string
|
|
324
|
+
{
|
|
325
|
+
return mb_strtolower((string) $s, 'UTF-8');
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Convert to upper case.
|
|
331
|
+
*/
|
|
332
|
+
public static function upper($s): string
|
|
333
|
+
{
|
|
334
|
+
return mb_strtoupper((string) $s, 'UTF-8');
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Convert first character to upper case.
|
|
340
|
+
*/
|
|
341
|
+
public static function firstUpper($s): string
|
|
342
|
+
{
|
|
343
|
+
$s = (string) $s;
|
|
344
|
+
return self::upper(self::substring($s, 0, 1)) . self::substring($s, 1);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Capitalize string.
|
|
350
|
+
*/
|
|
351
|
+
public static function capitalize($s): string
|
|
352
|
+
{
|
|
353
|
+
return mb_convert_case((string) $s, MB_CASE_TITLE, 'UTF-8');
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Returns length of string or iterable.
|
|
359
|
+
*/
|
|
360
|
+
public static function length(array|\Countable|\Traversable|string $val): int
|
|
361
|
+
{
|
|
362
|
+
if (is_array($val) || $val instanceof \Countable) {
|
|
363
|
+
return count($val);
|
|
364
|
+
} elseif ($val instanceof \Traversable) {
|
|
365
|
+
return iterator_count($val);
|
|
366
|
+
} else {
|
|
367
|
+
return self::strLength($val);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
private static function strLength(string $s): int
|
|
373
|
+
{
|
|
374
|
+
return function_exists('mb_strlen')
|
|
375
|
+
? mb_strlen($s, 'UTF-8')
|
|
376
|
+
: strlen(utf8_decode($s));
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Strips whitespace.
|
|
382
|
+
*/
|
|
383
|
+
public static function trim(FilterInfo $info, string $s, string $charlist = " \t\n\r\0\x0B\u{A0}"): string
|
|
384
|
+
{
|
|
385
|
+
$charlist = preg_quote($charlist, '#');
|
|
386
|
+
$s = preg_replace('#^[' . $charlist . ']+|[' . $charlist . ']+$#Du', '', (string) $s);
|
|
387
|
+
if (preg_last_error()) {
|
|
388
|
+
throw new Latte\RegexpException;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
return $s;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Pad a string to a certain length with another string.
|
|
397
|
+
*/
|
|
398
|
+
public static function padLeft($s, int $length, string $append = ' '): string
|
|
399
|
+
{
|
|
400
|
+
$s = (string) $s;
|
|
401
|
+
$length = max(0, $length - self::strLength($s));
|
|
402
|
+
$l = self::strLength($append);
|
|
403
|
+
return str_repeat($append, (int) ($length / $l)) . self::substring($append, 0, $length % $l) . $s;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Pad a string to a certain length with another string.
|
|
409
|
+
*/
|
|
410
|
+
public static function padRight($s, int $length, string $append = ' '): string
|
|
411
|
+
{
|
|
412
|
+
$s = (string) $s;
|
|
413
|
+
$length = max(0, $length - self::strLength($s));
|
|
414
|
+
$l = self::strLength($append);
|
|
415
|
+
return $s . str_repeat($append, (int) ($length / $l)) . self::substring($append, 0, $length % $l);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Reverses string or array.
|
|
421
|
+
*/
|
|
422
|
+
public static function reverse(string|array|\Traversable $val, bool $preserveKeys = false): string|array
|
|
423
|
+
{
|
|
424
|
+
if (is_array($val)) {
|
|
425
|
+
return array_reverse($val, $preserveKeys);
|
|
426
|
+
} elseif ($val instanceof \Traversable) {
|
|
427
|
+
return array_reverse(iterator_to_array($val), $preserveKeys);
|
|
428
|
+
} else {
|
|
429
|
+
return iconv('UTF-32LE', 'UTF-8', strrev(iconv('UTF-8', 'UTF-32BE', (string) $val)));
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Chunks items by returning an array of arrays with the given number of items.
|
|
436
|
+
*/
|
|
437
|
+
public static function batch(array|\Traversable $list, int $length, $rest = null): \Generator
|
|
438
|
+
{
|
|
439
|
+
$batch = [];
|
|
440
|
+
foreach ($list as $key => $value) {
|
|
441
|
+
$batch[$key] = $value;
|
|
442
|
+
if (count($batch) >= $length) {
|
|
443
|
+
yield $batch;
|
|
444
|
+
$batch = [];
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
if ($batch) {
|
|
449
|
+
if ($rest !== null) {
|
|
450
|
+
while (count($batch) < $length) {
|
|
451
|
+
$batch[] = $rest;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
yield $batch;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Sorts an array.
|
|
462
|
+
* @param mixed[] $array
|
|
463
|
+
* @return mixed[]
|
|
464
|
+
*/
|
|
465
|
+
public static function sort(array $array, ?\Closure $callback = null): array
|
|
466
|
+
{
|
|
467
|
+
$callback ? uasort($array, $callback) : asort($array);
|
|
468
|
+
return $array;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* Returns value clamped to the inclusive range of min and max.
|
|
474
|
+
*/
|
|
475
|
+
public static function clamp(int|float $value, int|float $min, int|float $max): int|float
|
|
476
|
+
{
|
|
477
|
+
if ($min > $max) {
|
|
478
|
+
throw new \InvalidArgumentException("Minimum ($min) is not less than maximum ($max).");
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
return min(max($value, $min), $max);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* Generates URL-encoded query string
|
|
487
|
+
*/
|
|
488
|
+
public static function query(string|array $data): string
|
|
489
|
+
{
|
|
490
|
+
return is_array($data)
|
|
491
|
+
? http_build_query($data, '', '&')
|
|
492
|
+
: urlencode($data);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Is divisible by?
|
|
498
|
+
*/
|
|
499
|
+
public static function divisibleBy(int $value, int $by): bool
|
|
500
|
+
{
|
|
501
|
+
return $value % $by === 0;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Is odd?
|
|
507
|
+
*/
|
|
508
|
+
public static function odd(int $value): bool
|
|
509
|
+
{
|
|
510
|
+
return $value % 2 !== 0;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* Is even?
|
|
516
|
+
*/
|
|
517
|
+
public static function even(int $value): bool
|
|
518
|
+
{
|
|
519
|
+
return $value % 2 === 0;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* Returns the first item from the array or null if array is empty.
|
|
525
|
+
*/
|
|
526
|
+
public static function first(string|array $value): mixed
|
|
527
|
+
{
|
|
528
|
+
return is_array($value)
|
|
529
|
+
? (count($value) ? reset($value) : null)
|
|
530
|
+
: self::substring($value, 0, 1);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* Returns the last item from the array or null if array is empty.
|
|
536
|
+
*/
|
|
537
|
+
public static function last(string|array $value): mixed
|
|
538
|
+
{
|
|
539
|
+
return is_array($value)
|
|
540
|
+
? (count($value) ? end($value) : null)
|
|
541
|
+
: self::substring($value, -1);
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
/**
|
|
546
|
+
* Extracts a slice of an array or string.
|
|
547
|
+
*/
|
|
548
|
+
public static function slice(
|
|
549
|
+
string|array $value,
|
|
550
|
+
int $start,
|
|
551
|
+
?int $length = null,
|
|
552
|
+
bool $preserveKeys = false,
|
|
553
|
+
): string|array {
|
|
554
|
+
return is_array($value)
|
|
555
|
+
? array_slice($value, $start, $length, $preserveKeys)
|
|
556
|
+
: self::substring($value, $start, $length);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
|
|
560
|
+
public static function round(float $value, int $precision = 0): float
|
|
561
|
+
{
|
|
562
|
+
return round($value, $precision);
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
|
|
566
|
+
public static function floor(float $value, int $precision = 0): float
|
|
567
|
+
{
|
|
568
|
+
return floor($value * 10 ** $precision) / 10 ** $precision;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
|
|
572
|
+
public static function ceil(float $value, int $precision = 0): float
|
|
573
|
+
{
|
|
574
|
+
return ceil($value * 10 ** $precision) / 10 ** $precision;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
/**
|
|
579
|
+
* Picks random element/char.
|
|
580
|
+
*/
|
|
581
|
+
public static function random(string|array $values): mixed
|
|
582
|
+
{
|
|
583
|
+
if (is_string($values)) {
|
|
584
|
+
$values = preg_split('//u', $values, -1, PREG_SPLIT_NO_EMPTY);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
return $values
|
|
588
|
+
? $values[array_rand($values, 1)]
|
|
589
|
+
: null;
|
|
590
|
+
}
|
|
591
|
+
}
|