diff --git a/best-practices/cs/lets-create-contact-form.texy b/best-practices/cs/lets-create-contact-form.texy index 80503acf55..aa24fb819f 100644 --- a/best-practices/cs/lets-create-contact-form.texy +++ b/best-practices/cs/lets-create-contact-form.texy @@ -131,7 +131,7 @@ Zatím se odesílá prostý textový email obsahující pouze zprávu odeslanou ``` -Zbývá upravit `ContactFacade`, aby tuto šablonu používal. V konstruktoru si vyžádáme třídu `LatteFactory`, která umí vyrobit objekt `Latte\Engine`, tedy [vykreslovač Latte šablon |latte:develop#jak-vykreslit-sablonu]. Pomocí metody `renderToString()` šablonu vykreslíme do souboru, prvním parametrem je cesta k šabloně a druhým jsou proměnné. +Zbývá upravit `ContactFacade`, aby tuto šablonu používal. V konstruktoru si vyžádáme třídu `LatteFactory`, která umí vyrobit objekt `Latte\Engine`, tedy [vykreslovač Latte šablon |latte:develop#vykresleni-sablony]. Pomocí metody `renderToString()` šablonu vykreslíme do souboru, prvním parametrem je cesta k šabloně a druhým jsou proměnné. ```php namespace App\Model; diff --git a/latte/cs/cookbook/how-to-write-sql-queries-in-latte.texy b/latte/cs/cookbook/how-to-write-sql-queries-in-latte.texy index bdfc0feedc..07fb5dec84 100644 --- a/latte/cs/cookbook/how-to-write-sql-queries-in-latte.texy +++ b/latte/cs/cookbook/how-to-write-sql-queries-in-latte.texy @@ -2,9 +2,9 @@ Jak psát SQL queries v Latte? ***************************** .[perex] -Latte se může hodit i pro generování opravdu složitých SQL dotazů. +Latte může být užitečným nástrojem i pro generování komplexních SQL dotazů, což zvyšuje jejich čitelnost a udržovatelnost. -Pokud vytvoření SQL dotazu obsahuje řadu podmínek a proměnných, může být opravdu přehlednější ho napsat v Latte. Velmi jednoduchý příklad: +Když SQL dotaz obsahuje mnoho podmínek a proměnných, může být jeho zápis v Latte přehlednější a flexibilnější. Zde je jednoduchý příklad demonstrující tuto výhodu: ```latte SELECT users.* FROM users @@ -14,8 +14,13 @@ SELECT users.* FROM users WHERE groups.name = 'Admins' {ifset $country} AND country.name = {$country} {/ifset} ``` -Pomocí `$latte->setContentType()` řekneme Latte, aby k obsahu přistupovalo jako k prostému textu (nikoliv jako k HTML) a dále -připravíme escapovací funkci, která bude řetězce escapovat přímo databázovým driverem: +Pro správné fungování je třeba provést několik kroků: + +1. Nastavení typu obsahu: pomocí `$latte->setContentType()` informujeme Latte, že obsah má být zpracován jako prostý text, nikoliv jako HTML. + +2. Definice escapovací funkce: vytvoříme vlastní escapovací funkci, která bude řetězce escapovat přímo pomocí databázového driveru. Tím zajistíme bezpečnost proti SQL injection. + +Zde je ukázka implementace těchto kroků: ```php $db = new PDO(/* ... */); @@ -31,13 +36,28 @@ $latte->addFilter('escape', fn($val) => match (true) { }); ``` -Použití by vypadalo takto: +Tato escapovací funkce zajišťuje správné ošetření různých datových typů: +- Řetězce jsou escapovány pomocí metody `quote()` databázového driveru. +- Čísla (celá i s plovoucí desetinnou čárkou) jsou převedena na řetězce. +- Booleovské hodnoty jsou převedeny na '1' nebo '0'. +- Null hodnoty jsou převedeny na 'NULL'. +- Pro nepodporované typy je vyhozena výjimka. + +Použití v praxi by pak vypadalo takto: ```php $sql = $latte->renderToString('query.sql.latte', ['country' => $country]); $result = $db->query($sql); ``` -*Uvedený příklad vyžaduje Latte v3.0.5 nebo vyšší.* +Tento přístup umožňuje: +1. Dynamické sestavování SQL dotazů s využitím logiky Latte. +2. Bezpečné vkládání proměnných do dotazu díky vlastní escapovací funkci. +3. Lepší čitelnost a udržovatelnost komplexních SQL dotazů. + +.[note] +Tento příklad vyžaduje Latte ve verzi 3.0.5 nebo novější. + +Využití Latte pro generování SQL dotazů může výrazně zjednodušit práci s komplexními dotazy, zejména v situacích, kdy se dotaz dynamicky mění na základě různých podmínek. Zároveň tento přístup pomáhá udržet kód čistý a snadno upravitelný. {{leftbar: /@left-menu}} diff --git a/latte/cs/cookbook/migration-from-php.texy b/latte/cs/cookbook/migration-from-php.texy index f17181af91..2bec5df959 100644 --- a/latte/cs/cookbook/migration-from-php.texy +++ b/latte/cs/cookbook/migration-from-php.texy @@ -2,27 +2,30 @@ Migrace z PHP do Latte ********************** .[perex] -Převádíte starý projekt napsaný v čistém PHP do Latte? Máme pro vás nástroj, které vám migraci usnadní. [Vyzkoušejte jej online |https://php2latte.nette.org]. +Převádíte starší projekt napsaný v čistém PHP na Latte? Máme pro vás nástroj, který tento proces výrazně zjednoduší. [Vyzkoušejte jej online |https://php2latte.nette.org]. -Nástroj si můžete stáhnout z [GitHubu|https://github.com/nette/latte-tools] nebo nainstalovat pomocí Composeru: +Tento užitečný nástroj můžete získat dvěma způsoby: + +1. Stáhnout z [GitHubu|https://github.com/nette/latte-tools] +2. Nainstalovat pomocí Composeru: ```shell composer create-project latte/tools ``` -Převodník nepoužívá jednoduché záměny pomocí regulárních výrazů, naopak využívá přímo PHP parser, takže si poradí s jakkoliv složitou syntaxí. +Na rozdíl od jednoduchých nástrojů využívajících regulární výrazy, tento převodník používá sofistikovaný PHP parser. Díky tomu si poradí i s komplexní PHP syntaxí. -K převodu z PHP do Latte slouží skript `php-to-latte.php`: +Pro převod z PHP do Latte použijte skript `php-to-latte.php`: ```shell php-to-latte.php input.php [output.latte] ``` -Příklad -------- +Příklad použití +--------------- -Vstupní soubor může vypadat třeba takto (jde o část kódu fóra PunBB): +Podívejme se na konkrétní příklad. Níže je ukázka vstupního PHP souboru (část kódu fóra PunBB): ```php

@@ -48,7 +51,7 @@ foreach ($result as $cur_group) { ``` -Vygeneruje tuto šablonu: +Po zpracování nástrojem získáme následující Latte šablonu: ```latte

{$lang_common['User list']}

@@ -69,4 +72,13 @@ Vygeneruje tuto šablonu: ``` +Hlavní výhody tohoto převodu: + +1. **Čistší syntaxe**: Latte šablona je čitelnější a snáze udržovatelná. +2. **Automatické escapování**: Latte automaticky escapuje výstup, čímž zvyšuje bezpečnost (např. `htmlspecialchars()` již není potřeba). +3. **Lepší struktura**: Latte tagy (`{foreach}`, `{if}`) jasně oddělují logiku od prezentace. +4. **Zjednodušení**: Odstraňuje nutnost explicitního výpisu pomocí `echo`. + +Tento nástroj významně urychluje a zjednodušuje proces migrace z PHP na Latte, což vám umožní rychleji modernizovat vaše projekty a využít všech výhod, které Latte nabízí. + {{leftbar: /@left-menu}} diff --git a/latte/cs/cookbook/migration-from-twig.texy b/latte/cs/cookbook/migration-from-twig.texy index 4ded46f341..8a7fb5bd9c 100644 --- a/latte/cs/cookbook/migration-from-twig.texy +++ b/latte/cs/cookbook/migration-from-twig.texy @@ -2,37 +2,40 @@ Migrace z Twigu do Latte ************************ .[perex] -Převádíte projekt napsaný v Twigu do modernějšího Latte? Máme pro vás nástroj, které vám migraci usnadní. [Vyzkoušejte jej online |https://twig2latte.nette.org]. +Převádíte projekt z Twigu na modernější a mnohem bezpečnější Latte? Máme pro vás nástroj, který tento proces výrazně zjednoduší. [Vyzkoušejte jej online |https://twig2latte.nette.org]. -Nástroj si můžete stáhnout z [GitHubu|https://github.com/nette/latte-tools] nebo nainstalovat pomocí Composeru: +Tento užitečný nástroj je dostupný dvěma způsoby: + +1. Stažením z [GitHubu|https://github.com/nette/latte-tools] +2. Instalací pomocí Composeru: ```shell composer create-project latte/tools ``` -Převodník nepoužívá jednoduché záměny pomocí regulárních výrazů, naopak využívá přímo Twig parser, takže si poradí s jakkoliv složitou syntaxí. +Na rozdíl od jednoduchých nástrojů využívajících regulární výrazy, tento převodník používá sofistikovaný Twig parser. Díky tomu si poradí i s komplexní Twig syntaxí. -K převodu z Twigu do Latte slouží skript `twig-to-latte.php`: +Pro převod z Twigu do Latte použijte skript `twig-to-latte.php`: ```shell twig-to-latte.php input.twig.html [output.latte] ``` -Konverze --------- +Konverze a její specifika +------------------------- -Převod předpokládá ruční úpravu výsledku, protože konverzi nelze provést jednoznačně. Twig používá tečkovou syntax, kde `{{ a.b }}` může znamenat `$a->b`, `$a['b']` nebo `$a->getB()`, což nelze rozlišit při kompilaci. Převaděč proto vše převádí na `$a->b`. +Je důležité poznamenat, že převod může vyžadovat ruční úpravy výsledku. Důvodem je, že některé konstrukce v Twigu nelze jednoznačně převést do Latte. Například, Twig používá tečkovou syntax, kde `{{ a.b }}` může znamenat `$a->b`, `$a['b']` nebo `$a->getB()`. Tento rozdíl nelze rozlišit při kompilaci, proto převaděč vše převádí na `$a->b`. -Některé funkce, filtry nebo tagy nemají obdobu v Latte, nebo se mohou chovat mírně jinak. +Některé funkce, filtry nebo tagy v Twigu nemají přímou obdobu v Latte, nebo se mohou chovat mírně odlišně. To je další důvod, proč může být potřeba ruční úprava po automatickém převodu. -Příklad -------- +Příklad použití +--------------- -Vstupní soubor může vypadat třeba takto: +Podívejme se na konkrétní příklad. Níže je ukázka vstupního Twig souboru: -```latte +```twig {% use "blocks.twig" %} @@ -54,7 +57,7 @@ Vstupní soubor může vypadat třeba takto: ``` -Po konverzi do Latte získáme tuto šablonu: +Po konverzi do Latte získáme následující šablonu: ```latte {import 'blocks.latte'} @@ -78,4 +81,15 @@ Po konverzi do Latte získáme tuto šablonu: ``` +Hlavní rozdíly a výhody po převodu: + +1. **Změna syntaxe**: Twig používá `{% ... %}` pro logiku a `{{ ... }}` pro výpis, zatímco Latte používá jednotnou `{ ... }` syntaxi +2. **Bloky**: `{% block ... %}` se mění na `{block ...}` +3. **Cykly**: `{% for ... %}` se převádí na `{foreach ...}` +4. **Podmínky**: `{% if ... %}` zůstává podobné, ale používá se `{if ...}`. +5. **Přístup k proměnným**: Tečková notace `item.caption` se mění na objektovou notaci `$item->caption` +6. **Import**: `{% use ... %}` se mění na `{import ...}` + +Tento nástroj významně urychluje a zjednodušuje proces migrace z Twigu na Latte. Umožňuje vám rychle modernizovat vaše projekty a využít všech výhod, které Latte nabízí, včetně jeho výkonu a flexibilnity. Nezapomeňte však po automatickém převodu zkontrolovat a případně upravit výsledný kód, aby plně odpovídal vašim potřebám a specifikům vašeho projektu. + {{leftbar: /@left-menu}} diff --git a/latte/cs/cookbook/passing-variables.texy b/latte/cs/cookbook/passing-variables.texy index b4840427c2..7bb477af7a 100644 --- a/latte/cs/cookbook/passing-variables.texy +++ b/latte/cs/cookbook/passing-variables.texy @@ -1,14 +1,14 @@ Předávání proměnných napříč šablonami ************************************* -Tento průvodce vám vysvětlí, jak se proměnné předávají mezi šablonami v Latte pomocí různých tagů jako `{include}`, `{import}`, `{embed}`, `{layout}`, `{sandbox}` a dalších. Dozvíte se také, jak pracovat s proměnnými v tagu `{block}` a `{define}`, a k čemu slouží značka `{parameters}`. +Tento průvodce objasňuje, jak se v Latte předávají proměnné mezi šablonami pomocí různých tagů jako `{include}`, `{import}`, `{embed}`, `{layout}`, `{sandbox}` a dalších. Dozvíte se také, jak pracovat s proměnnými v tagu `{block}` a `{define}`, a k čemu slouží značka `{parameters}`. Typy proměnných --------------- -Proměnné v Latte můžeme rozdělit do tří kategorií podle toho, jak a kde jsou definovány: +V Latte rozlišujeme tři kategorie proměnných podle jejich definice a dostupnosti: -**Vstupní proměnné** jsou ty, které jsou do šablony předávány zvenčí, například z PHP skriptu nebo pomocí tagu jako `{include}`. +**Vstupní proměnné** jsou předávány do šablony zvenčí, typicky z PHP skriptu nebo pomocí tagů jako `{include}`. ```php $latte->render('template.latte', ['userName' => 'Jan', 'userAge' => 30]); @@ -45,7 +45,7 @@ Tag `{block}` se používá k definování opakovaně použitelných bloků kód `{define}` ---------- -Tag `{define}` slouží k vytváření bloků, které se renderují až po jejich zavolání pomocí `{include}`. Proměnné dostupné uvnitř těchto bloků závisí na tom, zda jsou v definici uvedeny parametry. Pokud ano, přístup mají jen k těmto parametrům. Pokud ne, přístup mají ke všem vstupním proměnným šablony, ve které jsou bloky definovány. +Tag `{define}` vytváří bloky, které se renderují až po jejich explicitním zavolání pomocí `{include}`. Dostupnost proměnných uvnitř těchto bloků závisí na přítomnosti parametrů v definici. S parametry mají bloky přístup pouze k těmto parametrům. Bez parametrů mají přístup ke všem vstupním proměnným šablony, ve které jsou definovány. ```latte {define hello} @@ -60,7 +60,7 @@ Tag `{define}` slouží k vytváření bloků, které se renderují až po jejic `{parameters}` -------------- -Tag `{parameters}` slouží k explicitní deklaraci očekávaných vstupních proměnných na začátku šablony. Tímto způsobem lze snadno dokumentovat očekávané proměnné a jejich datové typy. Také je možné definovat výchozí hodnoty. +Tag `{parameters}` slouží k explicitní deklaraci očekávaných vstupních proměnných na začátku šablony. Tímto způsobem lze efektivně dokumentovat očekávané proměnné a jejich datové typy. Umožňuje také definovat výchozí hodnoty. ```latte {parameters int $age, string $name = 'neznámé'} @@ -70,7 +70,7 @@ Tag `{parameters}` slouží k explicitní deklaraci očekávaných vstupních pr `{include file}` ---------------- -Tag `{include file}` slouží k vložení celé šablony. Této šabloně se předávají jak vstupní proměnné šablony, ve které je značka použita, tak proměnné v ní explicitně definované. Cílová šablona ale může rozsah omezit pomocí `{parameters}`. +Tag `{include file}` vkládá celou šablonu. Do vkládané šablony se předávají vstupní proměnné šablony, ve které je značka použita, spolu s explicitně definovanými proměnnými. Cílová šablona může omezit rozsah přijímaných proměnných pomocí `{parameters}`. ```latte {include 'profile.latte', userId: $user->id} @@ -79,7 +79,7 @@ Tag `{include file}` slouží k vložení celé šablony. Této šabloně se př `{include block}` ----------------- -Když vkládáte blok definovaný ve stejné šabloně, předávají se do něj všechny okolní a explicitně definované proměnné: +Při vkládání bloku definovaného ve stejné šabloně se do něj předávají všechny okolní a explicitně definované proměnné: ```latte {define blockName} @@ -90,9 +90,9 @@ Když vkládáte blok definovaný ve stejné šabloně, předávají se do něj {include blockName} ``` -V tomto příkladu se proměnné `$name` a `$age` předají do bloku `blockName`. Stejným způsobem se chová i `{include parent}`. +V tomto příkladu jsou proměnné `$name` a `$age` předány do bloku `blockName`. Stejně se chová i `{include parent}`. -Při vkládání bloku z jiné šablony jsou předávány pouze vstupní proměnné a explicitně definované. Okolní proměnné nejsou automaticky dostupné. +Při vkládání bloku z jiné šablony se předávají pouze vstupní proměnné a explicitně definované proměnné. Okolní proměnné nejsou automaticky dostupné. ```latte {include blockInOtherTemplate, name: $name, age: $age} @@ -101,7 +101,7 @@ Při vkládání bloku z jiné šablony jsou předávány pouze vstupní proměn `{layout}` nebo `{extends}` --------------------------- -Tyto tagy definují layout, do kterého se předávají vstupní proměnné podřízené šablony a dále proměnné vytvořené v kódu před bloky: +Tyto tagy definují layout, do kterého se předávají vstupní proměnné podřízené šablony a proměnné vytvořené v kódu před bloky: ```latte {layout 'layout.latte'} @@ -134,7 +134,7 @@ Naopak v blocích uvnitř `{embed}` je přístup ke všem okolním proměnným: {var $name = 'Jan'} {embed 'menu.latte', items: $menuItems} {block foo} - {$nam} + {$name} {/block} {/embed} ``` @@ -142,7 +142,7 @@ Naopak v blocích uvnitř `{embed}` je přístup ke všem okolním proměnným: `{import}` ---------- -Tag `{import}` se využívá pro načítání bloků z jiných šablon. Přenáší se jak vstupní, tak explicitně deklarované proměnné do importovaných bloků. +Tag `{import}` se používá pro načítání bloků z jiných šablon. Do importovaných bloků se předávají jak vstupní, tak explicitně deklarované proměnné. ```latte {import 'buttons.latte'} @@ -151,11 +151,13 @@ Tag `{import}` se využívá pro načítání bloků z jiných šablon. Přená `{sandbox}` ----------- -Tag `{sandbox}` izoluje šablonu pro bezpečné zpracování. Proměnné jsou předávány výhradně explicitně. +Tag `{sandbox}` izoluje šablonu pro bezpečné zpracování. Proměnné jsou předávány výhradně explicitně, což zvyšuje kontrolu nad daty vstupujícími do izolovaného prostředí. ```latte {sandbox 'secure.latte', data: $secureData} ``` +Tento mechanismus umožňuje přesnou kontrolu nad tím, jaká data jsou dostupná v izolované šabloně, což je užitečné pro zpracování potenciálně nebezpečného obsahu. + {{leftbar: /@left-menu}} diff --git a/latte/cs/creating-extension.texy b/latte/cs/creating-extension.texy index 24ff44bc2a..7608d85ebc 100644 --- a/latte/cs/creating-extension.texy +++ b/latte/cs/creating-extension.texy @@ -2,25 +2,24 @@ Vytváříme Extension ******************* .[perex] -Tzv. rozšíření je opakovatelně použitelná třída, která může definovat vlastní značky, filtry, funkce, providery, atd. +Rozšíření (extension) je znovupoužitelná třída, která může definovat vlastní značky, filtry, funkce, providery a další prvky pro Latte. Vytváříme je, když chceme své úpravy Latte použít v různých projektech nebo je sdílet s komunitou. -Rozšíření vytváříme tehdy, pokud chceme své úpravy Latte znovu použít v různých projektech nebo je sdílet s ostatními. -Je užitečné vytvářet rozšíření i pro každý webový projekt, které bude obsahovat všechny specifické značky a filtry, které chcete v šablonách projektu využívat. +Rozšíření je užitečné vytvořit i pro každý webový projekt. Může obsahovat všechny specifické značky a filtry, které chcete v šablonách projektu využívat. Třída rozšíření =============== -Rozšíření je třída dědící od [api:Latte\Extension]. Do Latte se registruje pomocí `addExtension()` (případně [konfiguračním souborem |application:configuration#Šablony Latte]): +Rozšíření je třída dědící od [api:Latte\Extension]. Do Latte se registruje pomocí `addExtension()` nebo [konfiguračním souborem |application:configuration#Šablony Latte]: ```php $latte = new Latte\Engine; $latte->addExtension(new MyLatteExtension); ``` -Pokud zaregistrujete vícero rozšíření a ty definují stejně pojmenované tagy, filtry nebo funkce, vyhrává poslední přidané rozšíření. Z toho také plyne, že vaše rozšíření mohou přepisovat nativní značky/filtry/funkce. +Pokud zaregistrujete více rozšíření definujících stejně pojmenované tagy, filtry nebo funkce, platí poslední přidané. To znamená, že vaše rozšíření může přepisovat nativní značky/filtry/funkce. -Kdykoliv v třídě provedete změnu a není vypnutý auto-refresh, Latte automaticky překompiluje vaše šablony. +Kdykoliv provedete změnu ve třídě rozšíření a není vypnutý auto-refresh, Latte automaticky překompiluje vaše šablony. Třída může implementovat kteroukoliv z následujících metod: @@ -76,11 +75,13 @@ abstract class Extension Pro představu, jak rozšíření vypadá, se podívejte na vestavěné "CoreExtension":https://github.com/nette/latte/blob/master/src/Latte/Essential/CoreExtension.php. +Nyní si podrobněji rozebereme jednotlivé metody: + beforeCompile(Latte\Engine $engine): void .[method] --------------------------------------------------- -Volá se před kompilací šablony. Metodu lze využít např. pro inicializace související s kompilací. +Tato metoda se volá před kompilací šablony. Můžete ji využít například pro inicializace související s kompilací. getTags(): array .[method] @@ -102,18 +103,18 @@ public function getTags(): array Značka `n:baz` představuje ryzí n:atribut, tj. jde o značku, kterou lze zapisovat pouze jako atribut. -V případě značek `foo` a `bar` Latte samo rozezná, zda jsou párové, a pokud ano, bude je možné automaticky zapisovat i pomocí n:atributů, včetně variant s prefixy `n:inner-foo` a `n:tag-foo`. +Latte automaticky rozpozná, zda jsou značky `foo` a `bar` párové. Pokud ano, bude je možné zapisovat i pomocí n:atributů, včetně variant s prefixy `n:inner-foo` a `n:tag-foo`. -Pořadí provádění takovýchto n:atributů je dáno jejich pořadím v poli vráceném `getTags()`. Tedy `n:foo` se provede vždy před `n:bar`, i kdyby byly atributy v HTML značce uvedeny v opačném pořadí jako `
`. +Pořadí provádění n:atributů je dáno jejich pořadím v poli vráceném `getTags()`. Tedy `n:foo` se provede vždy před `n:bar`, i kdyby byly atributy v HTML značce uvedeny v opačném pořadí. -Pokud potřebujete stanovit pořadí n:atributů napříč více rozšířeními, použijte pomocnou metodu `order()`, kde parametr `before` a nebo `after` určuje, před nebo za kterými značkami se daná značka zařadí. +Pro stanovení pořadí n:atributů napříč více rozšířeními použijte pomocnou metodu `order()`. Parametry `before` a `after` určují, před nebo za kterými značkami se daná značka zařadí: ```php public function getTags(): array { return [ - 'foo' => self::order([FooNode::class, 'create'], before: 'bar')] - 'bar' => self::order([BarNode::class, 'create'], after: ['block', 'snippet'])] + 'foo' => self::order([FooNode::class, 'create'], before: 'bar'), + 'bar' => self::order([BarNode::class, 'create'], after: ['block', 'snippet']), ]; } ``` @@ -122,7 +123,7 @@ public function getTags(): array getPasses(): array .[method] ---------------------------- -Volá se při kompilaci šablony. Vrací asociativní pole *název pass => callable*, což jsou funkce představující tzv. [#průchody kompilátoru], které procházejí a modifikujou AST. +Volá se při kompilaci šablony. Vrací asociativní pole *název pass => callable*, což jsou funkce představující tzv. [#průchody kompilátoru], které procházejí a modifikují AST. Opět je možné využít pomocnou metodu `order()`. Hodnotou parametrů `before` nebo `after` může být `'*'` s významem před/za všemi. @@ -141,7 +142,7 @@ public function getPasses(): array beforeRender(Latte\Engine $engine): void .[method] -------------------------------------------------- -Volá se před každým vykreslením šablony. Metodu lze využít např. pro inicializaci proměnných používaných při vykreslování. +Volá se před každým vykreslením šablony. Metodu lze využít například pro inicializaci proměnných používaných při vykreslování. getFilters(): array .[method] @@ -181,7 +182,7 @@ public function getFunctions(): array getProviders(): array .[method] ------------------------------- -Volá se před vykreslením šablony. Vrací pole tzv. providers, což jsou zpravidla objekty, které za běhu využívají tagy. Přistupují k nim přes `$this->global->...`. +Volá se před vykreslením šablony. Vrací pole tzv. providerů, což jsou zpravidla objekty, které za běhu využívají tagy. Přistupují k nim přes `$this->global->...`. ```php public function getProviders(): array @@ -198,7 +199,7 @@ public function getProviders(): array getCacheKey(Latte\Engine $engine): mixed .[method] -------------------------------------------------- -Volá se před vykreslením šablony. Vrácená hodnota se stane součástí klíče, jehož hash je obsažen v názvu souboru se zkompilovanou šablonou. Tedy pro různé vrácené hodnoty Latte vygeneruje různé soubory v cache. +Volá se před vykreslením šablony. Vrácená hodnota se stane součástí klíče, jehož hash je obsažen v názvu souboru se zkompilovanou šablonou. Pro různé vrácené hodnoty tedy Latte vygeneruje různé soubory v cache. Jak Latte funguje? @@ -208,20 +209,19 @@ Pro pochopení toho, jak definovat vlastní tagy nebo compiler passes, je nezbyt Kompilace šablon v Latte probíhá zjednodušeně takto: -- Nejprve **lexer** tokenizuje zdrojový kód šablony na malé části (tokeny) pro snadnější zpracování. -- Poté **parser** převede proud tokenů na smysluplný strom uzlů (abstraktní syntaktický strom, AST). -- Nakonec překladač **vygeneruje** z AST třídu PHP, která vykresluje šablonu, a uloží ji do cache. +1. **Lexer** tokenizuje zdrojový kód šablony na menší části (tokeny) pro snadnější zpracování. +2. **Parser** převede proud tokenů na smysluplný strom uzlů (abstraktní syntaktický strom, AST). +3. **Překladač** vygeneruje z AST třídu PHP, která vykresluje šablonu, a uloží ji do cache. Ve skutečnosti je kompilace o něco složitější. Latte **má dva** lexery a parsery: jeden pro HTML šablonu a druhý pro PHP-like kód uvnitř tagů. A také parsování neprobíhá až po tokenizaci, ale lexer i parser běží paralelně ve dvou "vláknech" a koordinují se. Je to raketová věda :-) -Dále své parsovací rutiny mají i všechny tagy. Když parser narazí na tag, zavolá jeho parsovací funkci (vrací je [Extension::getTags()|#getTags]). -Jejich úkolem je naparsovat argumenty značky a v případě párových značek i vnitřní obsah. Vrací *uzel*, který se stane součástí AST. Podrobně v části [#Parsovací funkce tagu]. +Každý tag má svou parsovací rutinu. Když parser narazí na tag, zavolá jeho parsovací funkci (vrací je [Extension::getTags()|#getTags]). Jejich úkolem je naparsovat argumenty značky a v případě párových značek i vnitřní obsah. Vrací *uzel*, který se stane součástí AST. Podrobně v části [#Parsovací funkce tagu]. -Když parser dokončí práci, máme kompletní AST reprezentující šablonu. Kořenovým uzlem je `Latte\Compiler\Nodes\TemplateNode`. Jednotlivé uzly uvnitř stromu pak reprezentují nejen tagy, ale i HTML elementy, jejich atributy, všechny výrazy použité uvnitř značek atd. +Po dokončení parsování máme kompletní AST reprezentující šablonu. Kořenovým uzlem je `Latte\Compiler\Nodes\TemplateNode`. Jednotlivé uzly uvnitř stromu reprezentují nejen tagy, ale i HTML elementy, jejich atributy, všechny výrazy použité uvnitř značek atd. Poté přicházejí na řadu tzv. [#Průchody kompilátoru], což jsou funkce (vrací je [Extension::getPasses()|#getPasses]), které modifikují AST. -Celý proces od načtení obsahu šablony přes parsování až po vygenerování výsledného souboru se dá sekvenčně vykonat tímto kódem, se kterým můžete experimentovat a dumpovat si jednotlivé mezikroky: +Celý proces od načtení obsahu šablony přes parsování až po vygenerování výsledného souboru můžete sekvenčně vykonat tímto kódem: ```php $latte = new Latte\Engine; @@ -285,19 +285,21 @@ Vlastní tagy K definování nové značky jsou zapotřebí tři kroky: -- definování [#parsovací funkce tagu] (zodpovědná za parsování tagu do uzlu) -- vytvoření třídy uzlu (zodpovědné za [#generování PHP kódu] a [#procházení AST]) -- registrace tagu pomocí [Extension::getTags()|#getTags] +1. Definování [#parsovací funkce tagu] (zodpovědná za parsování tagu do uzlu) +2. Vytvoření třídy uzlu (zodpovědné za [#generování PHP kódu] a [#procházení AST]) +3. Registrace tagu pomocí [Extension::getTags()|#getTags] Parsovací funkce tagu --------------------- -Parsování tagů ma na starosti jeho parsovací funkce (ta, kterou vrací [Extension::getTags()|#getTags]). Jejím úkolem je naparsovat a zkontrolovat případné argumenty uvnitř značky (k tomu využívá TagParser). -A dále, pokud je značka párová, požádá TemplateParser o naparsování a vrácení vnitřního obsahu. -Funkce vytvoří a vrátí uzel, který je zpravidla potomkem `Latte\Compiler\Nodes\StatementNode`, a ten se stane součástí AST. +Parsování tagů má na starosti jeho parsovací funkce (ta, kterou vrací [Extension::getTags()|#getTags]). Jejím úkolem je: + +1. Naparsovat a zkontrolovat případné argumenty uvnitř značky (k tomu využívá TagParser). +2. Pokud je značka párová, požádat TemplateParser o naparsování a vrácení vnitřního obsahu. +3. Vytvořit a vrátit uzel, který je zpravidla potomkem `Latte\Compiler\Nodes\StatementNode`, a který se stane součástí AST. -Pro každý uzel si vytváříme třídu, což uděláme teď hned a parsovací funkci do ní elegantně umístíme jako statickou továrnu. Jako příklad si zkusíme vytvořit známý tag `{foreach}`: +Pro každý uzel vytváříme třídu a parsovací funkci do ní umístíme jako statickou továrnu. Jako příklad si vytvoříme známý tag `{foreach}`: ```php use Latte\Compiler\Nodes\StatementNode; @@ -338,7 +340,7 @@ a dále nízkoúrovňový [api:Latte\Compiler\TokenStream] operující přímo s - `$tag->parser->stream->consume(...): Token` - `$tag->parser->stream->tryConsume(...): ?Token` -Latte drobnými způsoby rozšiřuje syntaxi PHP, například o modifikátory, zkrácené ternání operátory, nebo umožňuje jednoduché alfanumerické řetězce psát bez uvozovek. Proto používáme termím *PHP-like* místo PHP. Tudíž metoda `parseExpression()` naparsuje např. `foo` jako `'foo'`. +Latte mírně rozšiřuje syntaxi PHP, například o modifikátory, zkrácené ternání operátory, nebo umožňuje jednoduché alfanumerické řetězce psát bez uvozovek. Proto používáme termín *PHP-like* místo PHP. Metoda `parseExpression()` tedy naparsuje např. `foo` jako `'foo'`. Vedle toho *unquoted-řetězec* je speciálním případem řetězce, který také nemusí být v uvozovkách, ale zároveň nemusí být ani alfanumerický. Jde třeba o cestu k souboru ve značce `{include ../file.latte}`. K jeho naparsování slouží metoda `parseUnquotedStringOrExpression()`. .[note] @@ -416,7 +418,7 @@ Každý uzel musí implementovat metodu `print()`. Vrací PHP kód vykreslujíc Metoda `format(string $mask, ...$args)` akceptuje v masce tyto placeholdery: - `%node` vypisuje Node -- `%dump` vyexporuje hodnotu do PHP +- `%dump` vyexportuje hodnotu do PHP - `%raw` vloží přímo text bez jakékoliv transformace - `%args` vypíše ArrayNode jako argumenty volání funkce - `%line` vypíše komentář s číslem řádku @@ -474,7 +476,7 @@ Všimněte si, že `getIterator()` vrací reference. Právě díky tomu mohou *n .[warning] Pokud má uzel poduzly, je nezbytné tuto metodu implementovat a všechny poduzly zpřístupnit. Jinak by mohla vzniknout bezpečnostní díra. Například režim sandboxu by nebyl schopen kontrolovat poduzly a zajistit, aby v nich nebyly volány nepovolené konstrukce. -Protože klíčové slovo `yield` musí být přítomno v těle metody i pokud nemá žádné podřízené uzly, zapište ji takto: +Pokud uzel nemá žádné poduzly, implementujte metodu takto: ```php public function &getIterator(): \Generator @@ -498,7 +500,7 @@ Pokud vytváříte nový tag pro Latte, je žádoucí, abyste pro něj vytvořil $node = new AuxiliaryNode( // tělo metody print(): fn(PrintContext $context, $argNode) => $context->format('myFunc(%node)', $argNode), - // uzly zpřístupnění přes getIterator() a také předané do metody print(): + // uzly zpřístupněné přes getIterator() a také předané do metody print(): [$argNode], ); ``` @@ -544,9 +546,9 @@ $ast = (new NodeTraverser)->traverse( ); ``` -Modul AST může snadno obsahovat tisíce uzlů a procházení všech uzlů může být pomalé. V některých případech je možné se úplnému procházení vyhnout. +AST může snadno obsahovat tisíce uzlů a procházení všech uzlů může být časově náročné. V některých případech je možné se úplnému procházení vyhnout. -Pokud ve stromu hledáte všechny uzly `Html\ElementNode`, pak víte, že jakmile jednou uvidíte uzel `Php\ExpressionNode`, nemá smysl kontrolovat také všechny jeho podřízené uzly, protože HTML nemůže být uvnitř ve výrazech. V takovém případě můžete traverseru přikázat, aby do uzlu třídy neprováděl rekurzi: +Pokud ve stromu hledáte všechny uzly `Html\ElementNode`, pak víte, že jakmile jednou uvidíte uzel `Php\ExpressionNode`, nemá smysl kontrolovat také všechny jeho podřízené uzly, protože HTML nemůže být uvnitř výrazů. V takovém případě můžete traverseru přikázat, aby do uzlu třídy neprováděl rekurzi: ```php $ast = (new NodeTraverser)->traverse( @@ -578,7 +580,7 @@ $ast = (new NodeTraverser)->traverse( Pomocníci pro uzly ------------------ -Třída [api:Latte\Compiler\NodeHelpers] poskytuje některé metody, které mohou najít uzly AST, které buď splňují určitou podmínku atd. Několik příkladů: +Třída [api:Latte\Compiler\NodeHelpers] poskytuje některé metody, které mohou najít uzly AST, které splňují určitou podmínku atd. Několik příkladů: ```php use Latte\Compiler\NodeHelpers; @@ -595,3 +597,5 @@ $value = NodeHelpers::toValue($node); // převede statický textový uzel na řetězec $text = NodeHelpers::toText($node); ``` + +Tímto způsobem můžete efektivně procházet a manipulovat s AST stromem ve vašich rozšířeních pro Latte. diff --git a/latte/cs/develop.texy b/latte/cs/develop.texy index 19e8f2d33a..db494d990c 100644 --- a/latte/cs/develop.texy +++ b/latte/cs/develop.texy @@ -5,7 +5,7 @@ Vývojářské postupy Instalace ========= -Nejlepší způsob, jak nainstalovat Latte, je pomocí Composeru: +Nejlepší způsob instalace Latte je pomocí Composeru: ```shell composer require latte/latte @@ -18,22 +18,22 @@ Podporované verze PHP (platí pro poslední setinkové verze Latte): | Latte 3.0 | PHP 8.0 – 8.2 -Jak vykreslit šablonu -===================== +Vykreslení šablony +================== Jak vykreslit šablonu? Stačí k tomu tento jednoduchý kód: ```php $latte = new Latte\Engine; -// adresář pro cache +// nastavení adresáře pro cache $latte->setTempDirectory('/path/to/tempdir'); $params = [ /* proměnné šablony */ ]; -// or $params = new TemplateParameters(/* ... */); +// nebo $params = new TemplateParameters(/* ... */); -// kresli na výstup +// vykreslení na výstup $latte->render('template.latte', $params); -// kresli do proměnné +// vykreslení do proměnné $output = $latte->renderToString('template.latte', $params); ``` @@ -46,23 +46,21 @@ Ukázky použití najdete také v repozitáři [Latte examples |https://github.c Výkon a cache ============= -Šablony v Latte jsou nesmírně rychlé, Latte je totiž kompiluje přímo do PHP kódu a ukládá do cache na disk. Nemají tedy žádnou režii navíc oproti šablonám psaným v čistém PHP. +Šablony v Latte jsou extrémně rychlé, protože se kompilují přímo do PHP kódu a ukládají do cache na disk. Nemají tedy žádnou režii navíc oproti šablonám psaným v čistém PHP. -Cache se automaticky regeneruje pokaždé, když změníte zdrojový soubor. Během vývoje si tedy pohodlně editujete šablony v Latte a změny okamžitě vidíte v prohlížeči. Tuto funkci můžete v produkčním prostředí vypnout a ušetřit tím malinko výkonu: +Cache se automaticky regeneruje při změně zdrojového souboru. Během vývoje tedy pohodlně editujete šablony v Latte a změny okamžitě vidíte v prohlížeči. Pro mírné zvýšení výkonu v produkčním prostředí můžete automatickou regeneraci vypnout: ```php $latte->setAutoRefresh(false); ``` -Při nasazení na produkčním serveru může prvotní vygenerování cache, zejména u rozsáhlejších aplikací, pochopitelně chviličku trvat. Latte má vestavěnou prevenci před "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede. -Jde o situaci, kdy se sejde větší počet souběžných požadavků, které spustí Latte, a protože cache ještě neexistuje, začaly by ji všechny generovat současně. Což by neúměrně zatížilo server. -Latte je chytré a při více souběžných požadavcích generuje cache pouze první vlákno, ostatní čekají a následně ji využíjí. +Při nasazení na produkční server může prvotní vygenerování cache, zejména u rozsáhlých aplikací, chvíli trvat. Latte má vestavěnou prevenci proti "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede, což je situace, kdy velký počet souběžných požadavků spustí generování cache současně, což by mohlo přetížit server. Latte tento problém řeší chytře - při více souběžných požadavcích generuje cache pouze první vlákno, zatímco ostatní čekají a následně využijí vytvořenou cache. Parametry jako třída ==================== -Lepší než předávat proměnné do šablony jako pole je vytvořit si třídu. Získáte tak [typově bezpečný zápis|type-system], [příjemné napovídání v IDE|recipes#Editory a IDE] a cestu pro [registraci filtrů|extending-latte#Filtry pomocí třídy] a [funkcí|extending-latte#Funkce pomocí třídy]. +Místo předávání proměnných do šablony jako pole je lepší vytvořit si třídu. Získáte tak [typově bezpečný zápis|type-system], [příjemné napovídání v IDE|recipes#Editory a IDE] a možnost [registrace filtrů|extending-latte#Filtry pomocí třídy] a [funkcí|extending-latte#Funkce pomocí třídy]. ```php class MailTemplateParameters @@ -89,9 +87,9 @@ $latte->render('mail.latte', new MailTemplateParameters( Vypnutí auto-escapování proměnné ================================ -Pokud proměnná obsahuje řetězec v HTML, můžete ji označit tak, aby ji Latte automaticky (a tedy dvojitě) neescapovalo. Vyhnete se tak potřebě uvádět v šabloně `|noescape`. +Pokud proměnná obsahuje HTML řetězec, můžete ji označit tak, aby ji Latte automaticky (a tedy dvojitě) neescapovalo. Tím se vyhnete potřebě uvádět v šabloně `|noescape`. -Nejjednodušší cestou je řetězec zabalit do objektu `Latte\Runtime\Html`: +Nejjednodušší způsob je zabalit řetězec do objektu `Latte\Runtime\Html`: ```php $params = [ @@ -99,10 +97,10 @@ $params = [ ]; ``` -Latte dále neescapuje všechny objekty, které implementují rozhraní `Latte\HtmlStringable`. Můžete si tak vytvořit vlastní třídu, jejíž metoda `__toString()` bude vracet HTML kód, který se nebude automaticky escapovat: +Latte také neescapuje objekty implementující rozhraní `Latte\HtmlStringable`. Můžete si vytvořit vlastní třídu, jejíž metoda `__toString()` bude vracet HTML kód, který se nebude automaticky escapovat: ```php -class Emphasis extends Latte\HtmlStringable +class Emphasis implements Latte\HtmlStringable { public function __construct( private string $str, @@ -127,16 +125,14 @@ Metoda `__toString` musí vracet korektní HTML a zajistit escapování parametr Jak rozšířit Latte o filtry, značky atd. ======================================== -Jak do Latte přidat vlastní filtr, funkci, značku atd? O tom pojednává kapitola [rozšiřujeme Latte |extending-latte]. +Informace o přidávání vlastních filtrů, funkcí, značek atd. najdete v kapitole [rozšiřujeme Latte |extending-latte]. Pokud chcete své úpravy znovu použít v různých projektech nebo je sdílet s ostatními, měli byste [vytvořit rozšíření |creating-extension]. -Libovolný kód v šabloně `{php ...}` .{toc: RawPhpExtension} -=========================================================== +Libovolný PHP kód v šabloně `{php ...}` .{toc: RawPhpExtension} +=============================================================== -Uvnitř značky [`{do}`|tags#do] lze zapisovat pouze PHP výrazy, nemůžete tak třeba vložit konstrukce jako `if ... else` nebo statementy ukončené středníkem. - -Můžete si však zaregistrovat rozšíření `RawPhpExtension`, které přidává značku `{php ...}`. Pomocí té lze vkládat jakýkoliv PHP kód. Nevztahují se na něj žádná pravidla sandbox režimu, použití je tedy na zodpovědnost autora šablony. +Zatímco uvnitř značky [`{do}`|tags#do] lze zapisovat pouze PHP výrazy, rozšíření `RawPhpExtension` přidává značku `{php ...}`, která umožňuje vkládat jakýkoliv PHP kód. Použití je na zodpovědnost autora šablony, protože se na ni nevztahují pravidla sandbox režimu. ```php $latte->addExtension(new Latte\Essential\RawPhpExtension); @@ -146,12 +142,10 @@ $latte->addExtension(new Latte\Essential\RawPhpExtension); Kontrola vygenerovaného kódu .{data-version:3.0.7} ================================================== -Latte kompiluje šablony do PHP kódu. Samozřejmě dbá na to, aby vygenerovaný kód byl syntakticky validní. Nicméně při použítí rozšíření třetích stran nebo `RawPhpExtension` nemůže Latte zaručit správnost vygenerovaného souboru. -Také lze v PHP zapsat kód, který je sice syntakticky správný, ale je zakázaný (například přiřazení hodnoty do proměnné `$this`) a způsobí PHP Compile Error. +Latte kompiluje šablony do PHP kódu a dbá na jeho syntaktickou správnost. Nicméně při použití rozšíření třetích stran nebo `RawPhpExtension` nemůže Latte zaručit korektnost vygenerovaného souboru. V PHP lze také zapsat kód, který je syntakticky správný, ale zakázaný (například přiřazení hodnoty do `$this`) a způsobí PHP Compile Error. Pokud takovou operaci zapíšete v šabloně, dostane se i do vygenerovaného PHP kódu. Jelikož v PHP existují na dvě stovky různých zakázaných operací, nemá Latte ambici je odhalovat. Upozorní na ně až samotné PHP při vykreslení, což obvykle ničemu nevadí. -Jsou ale situace, kdy chcete vědět už v době kompilace šablony, že žádný PHP Compile Error neobsahuje. Zejména tehdy, pokud šablony mohou editovat uživatelé, nebo používáte [Sandbox]. V takovém případě si nechte šablony kontrolovat už v době kompilace. -Tuto funkčnost zapnete metodou `Engine::enablePhpLint()`. Jelikož ke kontrole potřebuje volat binárku PHP, cestu k ní předejte jako parametr: +Pokud chcete odhalit tyto problémy už v době kompilace šablony, zejména pokud šablony mohou editovat uživatelé nebo používáte [Sandbox], můžete zapnout kontrolu pomocí `Engine::enablePhpLint()`. Ke kontrole je potřeba volat binárku PHP, jejíž cestu předáte jako parametr: ```php $latte = new Latte\Engine; @@ -185,7 +179,7 @@ Vyžaduje PHP rozšíření `intl`. Nastavení v Latte neovlivňuje globální n Striktní režim .{data-version:3.0.8} ==================================== -Ve striktním režimu parsování Latte kontroluje, zda nechybí uzavírací HTML značky a také zakazuje používání proměnné `$this`. Zapnete jej takto: +Ve striktním režimu parsování Latte kontroluje, zda nechybí uzavírací HTML značky a zakazuje používání proměnné `$this`. Zapnete jej takto: ```php $latte = new Latte\Engine; @@ -203,7 +197,7 @@ $latte->setStrictTypes(); Překládání v šablonách .{toc: TranslatorExtension} ================================================== -Pomocí rozšíření `TranslatorExtension` přidáte do šablony značky [`{_...}`|tags#_], [`{translate}`|tags#translate] a filtr [`translate`|filters#translate]. Slouží k překládání hodnot nebo částí šablony do jiných jazyků. Jako parametr uvedeme metodu (PHP callable) provádějící překlad: +Rozšíření `TranslatorExtension` přidává do šablony značky [`{_...}`|tags#_], [`{translate}`|tags#translate] a filtr [`translate`|filters#translate] pro překládání hodnot nebo částí šablony do jiných jazyků. Jako parametr uvedeme metodu provádějící překlad: ```php class MyTranslator @@ -249,7 +243,7 @@ public function translate(string $original, ...$params): string Debuggování a Tracy =================== -Latte se vám snaží vývoj co nejvíce zpříjemnit. Přímo pro účely debugování existuje trojice značek [`{dump}`|tags#dump], [`{debugbreak}`|tags#debugbreak] a [`{trace}`|tags#trace]. +Latte se vám snaží vývoj co nejvíce zpříjemnit. Nabízí několik nástrojů pro debugování, včetně značek [`{dump}`|tags#dump], [`{debugbreak}`|tags#debugbreak] a [`{trace}`|tags#trace]. Největší komfort získáte, když ještě si nainstalujete skvělý [ladicí nástroj Tracy|tracy:] a aktivujete doplněk pro Latte: @@ -267,13 +261,13 @@ Zároveň v pravém dolním rohu v tzv. Tracy Baru se objeví záložka pro Latt [* latte-debugging.webp *] -Jelikož Latte kompiluje šablony do přehledného PHP kódu, můžete je pohodlně ve svém IDE krokovat. +Jelikož Latte kompiluje šablony do přehledného PHP kódu, můžete je pohodlně krokovat ve svém IDE. Linter: validace syntaxe šablon .{toc: Linter} ============================================== -Projít všechny šablony a zkontrolovat, zda neobsahují syntaktické chyby, vám pomůže nástroj Linter. Spouští se z konzole: +Pro kontrolu syntaxe všech šablon můžete použít nástroj Linter, který se spouští z konzole: ```shell vendor/bin/latte-lint @@ -281,31 +275,30 @@ vendor/bin/latte-lint Parametrem `--strict` aktivujete [striktní režim|#striktní režim]. -Pokud používáte vlastní značky, vytvořte si také vlastní verzi Linteru, např. `custom-latte-lint`: +Pokud používáte vlastní značky, vytvořte si vlastní verzi Linteru, např. `custom-latte-lint`: ```php #!/usr/bin/env php getEngine(); -// tady přidejte jednotlivá svá rozšíření +// zde přidejte svá rozšíření $latte->addExtension(/* ... */); $ok = $linter->scanDirectory($path); exit($ok ? 0 : 1); ``` -Alternativně můžete vlastní objekt `Latte\Engine` předat do Linteru: +Alternativně můžete předat vlastní objekt `Latte\Engine` do Linteru: ```php $latte = new Latte\Engine; -// tady nakonfigurujeme objekt $latte +// zde nakonfigurujeme objekt $latte $linter = new Latte\Tools\Linter(engine: $latte); ``` @@ -313,7 +306,7 @@ $linter = new Latte\Tools\Linter(engine: $latte); Načítání šablon z řetězce ========================= -Potřebujete načítat šablony z řetězců místo souborů, třeba pro účely testování? Pomůže vám [StringLoader|extending-latte#stringloader]: +Pro načítání šablon z řetězců, například pro účely testování, můžete použít [StringLoader|extending-latte#stringloader]: ```php $latte->setLoader(new Latte\Loaders\StringLoader([ @@ -359,4 +352,4 @@ $latte = new Latte\Engine; $latte->addProvider('coreParentFinder', $finder); ``` -Pokud šablona nemá mít layout, oznámí to značkou `{layout none}`. +Pokud šablona nemá mít layout, použije se značka `{layout none}`. diff --git a/latte/cs/extending-latte.texy b/latte/cs/extending-latte.texy index 15442df8e8..3a4089c0aa 100644 --- a/latte/cs/extending-latte.texy +++ b/latte/cs/extending-latte.texy @@ -2,74 +2,76 @@ Rozšiřujeme Latte ***************** .[perex] -Latte je velmi flexibilní a lze jej rozšířit mnoha způsoby: můžete přidat vlastní filtry, funkce, značky, loadery atd. Ukážeme si jak na to. +Latte je mimořádně flexibilní šablonovací systém, který můžete přizpůsobit svým potřebám mnoha způsoby. Ať už potřebujete přidat vlastní filtry, funkce, značky nebo změnit způsob načítání šablon, Latte vám to umožní. Pojďme se podívat, jak na to. -Tato kapitola popisuje jednotlivé cesty rozšiřování Latte. Pokud chcete své úpravy znovu použít v různých projektech nebo je sdílet s ostatními, měli byste [vytvořit tzv. rozšíření |creating-extension]. +Tato kapitola vás provede různými metodami rozšíření Latte. Pokud plánujete své rozšíření použít ve více projektech nebo ho sdílet s komunitou, doporučujeme vytvořit [samostatné rozšíření |creating-extension]. Kolik cest vede do Říma? ======================== -Protože některé způsoby rozšíření Latte mohou splývat, zkusíme si nejprve vysvětlit rozdíly mezi nimi. Jako příklad se pokusíme implementovat generátor *Lorem ipsum*, kterému předáme počet slov, jenž má vygenerovat. +Jelikož některé způsoby rozšíření Latte mohou být podobné, pojďme si nejprve objasnit rozdíly mezi nimi. Jako příklad implementujeme generátor textu *Lorem ipsum*, kterému předáme požadovaný počet slov. -Hlavní konstrukcí jazyka Latte je značka (tag). Generátor můžeme implementovat rozšířením jazyka Latte o nový tag: +Základním stavebním kamenem jazyka Latte je značka (tag). Generátor bychom mohli implementovat jako novou značku: ```latte {lipsum 40} ``` +Tato značka by fungovala dobře, ale nemusí být dostatečně flexibilní, protože ji nelze použít ve výrazech. Mimochodem, v praxi je potřeba vytvářet nové značky jen zřídka, což je dobrá zpráva, protože jde o složitější způsob rozšíření. -Tag bude skvěle fungovat. Nicméně generátor v podobě tagu nemusí být dostatečně flexibilní, protože jej nelze použít ve výrazu. Mimochodem v praxi potřebujete tagy vytvářet jen zřídka; a to je dobrá zpráva, protože tagy jsou složitějším způsobem rozšíření. - -Dobrá, zkusme místo tagu vytvořit filtr: +Zkusme místo značky vytvořit filtr: ```latte {=40|lipsum} ``` -Opět validní možnost. Ale filtr by měl předanou hodnotu transformovat na něco jiného. Zde hodnotu `40`, která udává počet vygenerovaných slov, používáme jako argument filtru, nikoli jako hodnotu, kterou chceme transformovat. +To je také platná možnost. Avšak filtr by měl typicky transformovat předanou hodnotu. V tomto případě hodnotu `40`, která určuje počet generovaných slov, používáme jako argument filtru, nikoli jako hodnotu k transformaci. -Tak zkusíme použít funkci: +Pojďme tedy zkusit funkci: ```latte {lipsum(40)} ``` -To je ono! Pro tento konkrétní příklad je vytvoření funkce ideálním způsobem rozšíření. Můžete ji volat kdekoli, kde je akceptován výraz, například: +To je ono! Pro tento konkrétní případ je vytvoření funkce ideálním způsobem rozšíření. Můžete ji volat kdekoli, kde je povolen výraz, například: ```latte {var $text = lipsum(40)} ``` +Tento příklad ukazuje, že výběr správného způsobu rozšíření závisí na konkrétním použití. Nyní se pojďme podívat na jednotlivé metody podrobněji. + Filtry ====== -Filtr vytvoříme zaregistrováním jeho názvu a libovolného PHP callable, třeba funkce: +Filtry jsou mocné nástroje pro transformaci dat přímo v šabloně. Vytvořit vlastní filtr je jednoduché: ```php $latte = new Latte\Engine; -$latte->addFilter('shortify', fn(string $s) => mb_substr($s, 0, 10)); // zkrátí text na 10 písmen +$latte->addFilter('shortify', fn(string $s) => mb_substr($s, 0, 10)); // zkrátí text na 10 znaků ``` -V tomto případě by bylo šikovnější, kdyby filtr přijímal další parametr: +V tomto případě by bylo užitečné, kdyby filtr přijímal další parametr: ```php $latte->addFilter('shortify', fn(string $s, int $len = 10) => mb_substr($s, 0, $len)); ``` -V šabloně se potom volá takto: +V šabloně se pak volá takto: ```latte

{$text|shortify}

{$text|shortify:100}

``` -Jak vidíte, funkce obdrží levou stranu filtru před pipe `|` jako první argument a argumenty předané filtru za `:` jako další argumenty. +Všimněte si, že: +- První argument filtru je vždy hodnota nalevo od `|` +- Další argumenty se předávají za dvojtečkou +- Filtry mohou mít libovolný počet argumentů, včetně volitelných -Funkce představující filtr může samozřejmě přijímat libovolný počet parametrů, podporovány jsou i variadic parametry. - -Pokud filtr vrací řetězec v HTML, můžete jej označit tak, aby jej Latte automaticky (a tedy dvojitě) neescapovalo. Vyhnete se tak potřebě uvádět v šabloně `|noescape`. -Nejjednodušší cestou je řetězec zabalit do objektu `Latte\Runtime\Html`, druhou cestu představují [Kontextové filtry|#Kontextové filtry]. +Pokud filtr vrací řetězec v HTML, můžete jej označit tak, aby jej Latte automaticky (a tedy dvojitě) neescapovalo. Tím se vyhnete nutnosti používat v šabloně `|noescape`. +Nejjednodušší způsob je obalit řetězec do objektu `Latte\Runtime\Html`, alternativou jsou [Kontextové filtry|#Kontextové filtry]. ```php $latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("$amount Kč")); @@ -82,19 +84,19 @@ Filtr musí v takovém případě zajistit správné escapování dat. Filtry pomocí třídy ------------------- -Druhým způsobem definice filtru je [využití třídy|develop#Parametry jako třída]. Vytvoříme metodu s atributem `TemplateFilter`: +Alternativním způsobem definice filtru je [využití třídy|develop#Parametry jako třída]. Vytvoříme metodu s atributem `TemplateFilter`: ```php class TemplateParameters { public function __construct( - // parameters + // parametry ) {} #[Latte\Attributes\TemplateFilter] public function shortify(string $s, int $len = 10): string { - return mb_substr($s, 0, $len); + return mb_substr($s, 0, $len) . (mb_strlen($s) > $len ? '...' : ''); } } @@ -102,11 +104,13 @@ $params = new TemplateParameters(/* ... */); $latte->render('template.latte', $params); ``` +Tento přístup je zvláště užitečný, když máte více filtrů nebo když filtry potřebují přístup ke sdíleným zdrojům. + Zavaděč filtrů -------------- -Místo registrace jednotlivých filtrů lze vytvořit tzv. zavaděč, což je funkce, které se zavolá s názvem filtru jako argumentem a vrátí jeho PHP callable, nebo null. +Místo registrace jednotlivých filtrů lze vytvořit tzv. zavaděč. Jde o funkci, která se volá s názvem filtru jako argumentem a vrací jeho PHP callable, nebo null. ```php $latte->addFilterLoader([new Filters, 'load']); @@ -131,11 +135,13 @@ class Filters } ``` +Tento přístup umožňuje dynamicky načítat filtry podle potřeby, což může být užitečné v rozsáhlých aplikacích. + Kontextové filtry ----------------- -Kontextový filtr je takový, který v prvním parametru přijímá objekt [api:Latte\Runtime\FilterInfo] a teprve po něm následují další parametry jako u klasických filtrů. Registruje se stejný způsobem, Latte samo rozpozná, že filtr je kontextový: +Kontextové filtry jsou speciální typ filtrů, které mají přístup k dodatečným informacím o kontextu, ve kterém jsou použity: ```php use Latte\Runtime\FilterInfo; @@ -147,13 +153,13 @@ $latte->addFilter('foo', function (FilterInfo $info, string $str): string { Kontextové filtry mohou zjišťovat a měnit content-type, který obdrží v proměnné `$info->contentType`. Pokud se filtr volá klasicky nad proměnnou (např. `{$var|foo}`), bude `$info->contentType` obsahovat null. -Filtr by měl nejprve ověřit, zda content-type vstupního řetězce podporuje. A může ho také změnit. Příklad filtru, který přijímá text (nebo null) a vrací HTML: +Filtr by měl nejprve ověřit, zda podporuje content-type vstupního řetězce. Může ho také změnit. Příklad filtru, který přijímá text (nebo null) a vrací HTML: ```php use Latte\Runtime\FilterInfo; $latte->addFilter('money', function (FilterInfo $info, float $amount): string { - // nejprve oveříme, zda je vstupem content-type text + // nejprve ověříme, zda je vstupem content-type text if (!in_array($info->contentType, [null, ContentType::Text])) { throw new Exception("Filter |money used in incompatible content type $info->contentType."); } @@ -173,9 +179,9 @@ Všechny filtry, které se používají nad [bloky|tags#block] (např. jako `{bl Funkce ====== -V Latte lze standardně používat všechny nativní funkce z PHP, pokud to nezakáže sandbox. Ale zároveň si můžete definovat funkce vlastní. Mohou přepsat funkce nativní. +V Latte lze standardně používat všechny nativní funkce PHP, pokud to nezakáže sandbox. Zároveň si můžete definovat vlastní funkce, které mohou přepsat i nativní funkce. -Funkci vytvoříme zaregistrováním jejího názvu a libovolného PHP callable: +Funkci vytvoříme registrací jejího názvu a libovolného PHP callable: ```php $latte = new Latte\Engine; @@ -184,7 +190,7 @@ $latte->addFunction('random', function (...$args) { }); ``` -Použití je pak stejné, jako když voláte PHP funkci: +Použití je pak stejné jako při volání PHP funkce: ```latte {random(jablko, pomeranč, citron)} // vypíše například: jablko @@ -194,13 +200,13 @@ Použití je pak stejné, jako když voláte PHP funkci: Funkce pomocí třídy ------------------- -Druhým způsobem definice funkce je [využití třídy|develop#Parametry jako třída]. Vytvoříme metodu s atributem `TemplateFunction`: +Alternativním způsobem definice funkce je [využití třídy|develop#Parametry jako třída]. Vytvoříme metodu s atributem `TemplateFunction`: ```php class TemplateParameters { public function __construct( - // parameters + // parametry ) {} #[Latte\Attributes\TemplateFunction] @@ -214,17 +220,19 @@ $params = new TemplateParameters(/* ... */); $latte->render('template.latte', $params); ``` +Tento přístup je užitečný pro organizaci souvisejících funkcí a sdílení zdrojů mezi nimi. + Loadery ======= -Loadery jsou zodpovědné za načítání šablon ze zdroje, například ze souborového systému. Nastaví se metodou `setLoader()`: +Loadery jsou zodpovědné za načítání šablon ze zdroje, například ze souborového systému. Nastavují se metodou `setLoader()`: ```php $latte->setLoader(new MyLoader); ``` -Vestavěné loadery jsou tyto: +Latte nabízí tyto vestavěné loadery: FileLoader @@ -232,7 +240,7 @@ FileLoader Výchozí loader. Načítá šablony ze souborového systému. -Přístup k souborům je možné omezit nastavením základního adresáře: +Přístup k souborům lze omezit nastavením základního adresáře: ```php $latte->setLoader(new Latte\Loaders\FileLoader($templateDir)); @@ -243,7 +251,7 @@ $latte->render('test.latte'); StringLoader ------------ -Načítá šablony z řetězců. Tento loader je velmi užitečný pro testování. Lze jej také použít pro malé projekty, kde může mít smysl ukládat všechny šablony do jediného souboru PHP. +Načítá šablony z řetězců. Tento loader je velmi užitečný pro testování. Lze jej také použít pro menší projekty, kde může být výhodné ukládat všechny šablony do jediného PHP souboru. ```php $latte->setLoader(new Latte\Loaders\StringLoader([ @@ -272,20 +280,20 @@ Loader je třída, která implementuje rozhraní [api:Latte\Loader]. Tagy (makra) ============ -Jednou z nejzajímavějších funkcí šablonovacího jádra je možnost definovat nové jazykové konstrukce pomocí značek. Je to také složitější funkčnost a je třeba pochopit, jak Latte interně funguje. +Jednou z nejzajímavějších funkcí šablonovacího jádra je možnost definovat nové jazykové konstrukce pomocí značek. Je to také složitější funkcionalita a vyžaduje pochopení vnitřního fungování Latte. -Většinou však značka není potřeba: -- pokud by měla generovat nějaký výstup, použijte místo ní [funkci|#funkce] -- pokud měla upravovat nějaký vstup a vracet ho, použijte místo toho [filtr|#filtry] -- pokud měla upravovat oblast textu, obalte jej značkou [`{block}`|tags#block] a použijte [filtr|#Kontextové filtry] -- pokud neměla nic vypisovat, ale pouze volat funkci, zavolejte ji pomocí [`{do}`|tags#do] +Ve většině případů však značka není potřeba: +- pokud má generovat nějaký výstup, použijte místo ní [funkci|#funkce] +- pokud má upravovat nějaký vstup a vracet ho, použijte [filtr|#filtry] +- pokud má upravovat oblast textu, obalte jej značkou [`{block}`|tags#block] a použijte [filtr|#Kontextové filtry] +- pokud nemá nic vypisovat, ale pouze volat funkci, použijte [`{do}`|tags#do] -Pokud přesto chcete vytvořit tag, skvěle! Vše podstatné najdete v kapitole [Vytváříme Extension|creating-extension]. +Pokud se přesto rozhodnete vytvořit tag, skvělé! Vše potřebné najdete v kapitole [Vytváříme Extension|creating-extension]. Průchody kompilátoru ==================== -Průchody kompilátoru jsou funkce, které modifikují AST nebo sbírají v nich informace. V Latte je takto implementován například sandbox: projde všechny uzly AST, najde volání funkcí a metod a nahradí je za jím kontrolované volání. +Průchody kompilátoru jsou funkce, které modifikují AST (abstraktní syntaktický strom) nebo z něj sbírají informace. V Latte je takto implementován například sandbox: projde všechny uzly AST, najde volání funkcí a metod a nahradí je za kontrolovaná volání. -Stejně jako v případě značek se jedná o složitější funkcionalitu a je potřeba pochopit, jak funguje Latte pod kapotou. Vše podstatné najdete v kapitole [Vytváříme Extension|creating-extension]. +Stejně jako v případě značek se jedná o složitější funkcionalitu, která vyžaduje pochopení vnitřního fungování Latte. Vše potřebné najdete v kapitole [Vytváříme Extension|creating-extension]. diff --git a/latte/cs/filters.texy b/latte/cs/filters.texy index 0fa1e5a14e..a480d9c021 100644 --- a/latte/cs/filters.texy +++ b/latte/cs/filters.texy @@ -2,113 +2,111 @@ Latte filtry ************ .[perex] -V šablonách můžeme používat funkce, které pomáhají upravit nebo přeformátovat data do výsledné podoby. Říkáme jim *filtry*. +Filtry v šablonách Latte pomáhají upravit nebo přeformátovat data do požadované podoby .[table-latte-filters] |## Transformace -| `batch` | [výpis lineárních dat do tabulky |#batch] -| `breakLines` | [Před konce řádku přidá HTML odřádkování |#breakLines] +| `batch` | [rozdělí lineární data do bloků |#batch] +| `breakLines` | [přidá HTML odřádkování za konce řádků |#breakLines] | `bytes` | [formátuje velikost v bajtech |#bytes] -| `clamp` | [ohraničí hodnotu do daného rozsahu |#clamp] -| `dataStream` | [konverze pro Data URI protokol |#datastream] -| `date` | [formátuje datum a čas|#date] +| `clamp` | [omezí hodnotu do daného rozsahu |#clamp] +| `dataStream` | [převede data do formátu Data URI |#datastream] +| `date` | [formátuje datum a čas |#date] | `explode` | [rozdělí řetězec na pole podle oddělovače |#explode] -| `first` | [vrací první prvek pole nebo znak řetězce |#first] -| `group` | [seskupí data podle různých kritérií |#group] +| `first` | [vrátí první prvek pole nebo znak řetězce |#first] +| `group` | [seskupí data podle zadaných kritérií |#group] | `implode` | [spojí pole do řetězce |#implode] -| `indent` | [odsadí text zleva o daný počet tabulátorů |#indent] +| `indent` | [odsadí text zleva |#indent] | `join` | [spojí pole do řetězce |#implode] -| `last` | [vrací poslední prvek pole nebo znak řetězce |#last] -| `length` | [vrací délku řetězce ve znacích nebo pole |#length] -| `localDate` | [formátuje datum a čas podle národního prostředí|#localDate] +| `last` | [vrátí poslední prvek pole nebo znak řetězce |#last] +| `length` | [vrátí délku řetězce nebo počet prvků pole |#length] +| `localDate` | [formátuje datum a čas podle národního prostředí |#localDate] | `number` | [formátuje číslo |#number] | `padLeft` | [doplní řetězec zleva na požadovanou délku |#padLeft] | `padRight` | [doplní řetězec zprava na požadovanou délku |#padRight] -| `random` | [vrací náhodný prvek pole nebo znak řetězce |#random] -| `repeat` | [opakování řetězce |#repeat] -| `replace` | [zamění výskyty hledaného řetězce |#replace] -| `replaceRE` | [zamění výskyty dle regulárního výrazu |#replaceRE] -| `reverse` | [obrátí UTF‑8 řetězec nebo pole |#reverse] +| `random` | [vrátí náhodný prvek pole nebo znak řetězce |#random] +| `repeat` | [opakuje řetězec |#repeat] +| `replace` | [nahradí výskyty hledaného řetězce |#replace] +| `replaceRE` | [nahradí výskyty podle regulárního výrazu |#replaceRE] +| `reverse` | [obrátí pořadí znaků v řetězci nebo prvků v poli |#reverse] | `slice` | [extrahuje část pole nebo řetězce |#slice] | `sort` | [seřadí pole |#sort] -| `spaceless` | [odstraní bílé místo |#spaceless], podobně jako značka [spaceless |tags] tag +| `spaceless` | [odstraní nadbytečné bílé znaky |#spaceless] | `split` | [rozdělí řetězec na pole podle oddělovače |#explode] -| `strip` | [odstraní bílé místo |#spaceless] -| `stripHtml` | [odstraní HTML značky a HTML entity převede na znaky |#stripHtml] +| `strip` | [odstraní nadbytečné bílé znaky |#spaceless] +| `stripHtml` | [odstraní HTML značky a převede entity na znaky |#stripHtml] | `substr` | [vrátí část řetězce |#substr] -| `trim` | [odstraní počáteční a koncové mezery či jiné znaky |#trim] -| `translate` | [překlad do jiných jazyků |#translate] -| `truncate` | [zkrátí délku se zachováním slov |#truncate] -| `webalize` | [upraví UTF‑8 řetězec do tvaru používaného v URL |#webalize] +| `trim` | [odstraní bílé znaky na začátku a konci řetězce |#trim] +| `translate` | [přeloží text do jiného jazyka |#translate] +| `truncate` | [zkrátí text na danou délku se zachováním slov |#truncate] +| `webalize` | [upraví řetězec pro použití v URL |#webalize] .[table-latte-filters] |## Velikost písmen -| `capitalize` | [malá písmena, první písmeno ve slovech velké |#capitalize] +| `capitalize` | [převede první písmeno každého slova na velké |#capitalize] | `firstUpper` | [převede první písmeno na velké |#firstUpper] -| `lower` | [převede na malá písmena |#lower] -| `upper` | [převede na velká písmena |#upper] +| `lower` | [převede text na malá písmena |#lower] +| `upper` | [převede text na velká písmena |#upper] .[table-latte-filters] |## Zaokrouhlování -| `ceil` | [zaokrouhlí číslo nahoru na danou přesnost |#ceil] -| `floor` | [zaokrouhlí číslo dolů na danou přesnost |#floor] -| `round` | [zaokrouhlí číslo na danou přesnost |#round] +| `ceil` | [zaokrouhlí číslo nahoru |#ceil] +| `floor` | [zaokrouhlí číslo dolů |#floor] +| `round` | [zaokrouhlí číslo |#round] .[table-latte-filters] |## Escapování | `escapeUrl` | [escapuje parametr v URL |#escapeUrl] -| `noescape` | [vypíše proměnnou bez escapování |#noescape] +| `noescape` | [vypne automatické escapování |#noescape] | `query` | [generuje query string v URL |#query] -Dále existují escapovací filtry pro HTML (`escapeHtml` a `escapeHtmlComment`), XML (`escapeXml`), JavaScript (`escapeJs`), CSS (`escapeCss`) a iCalendar (`escapeICal`), které Latte používá samo díky [kontextově sensitivnímu escapování|safety-first#Kontextově sensitivní escapování] a nemusíte je zapisovat. +Latte automaticky používá escapovací filtry pro HTML (`escapeHtml` a `escapeHtmlComment`), XML (`escapeXml`), JavaScript (`escapeJs`), CSS (`escapeCss`) a iCalendar (`escapeICal`) díky [kontextově sensitivnímu escapování|safety-first#Kontextově sensitivní escapování]. Tyto filtry není třeba explicitně zapisovat. .[table-latte-filters] |## Bezpečnost -| `checkUrl` | [ošetří URL adresu od nebezpečných vstupů |#checkUrl] -| `nocheck` | [předejde automatickému ošetření URL adresy |#nocheck] - -Latte atributy `src` a `href` [kontroluje automaticky |safety-first#Kontrola odkazů], takže filtr `checkUrl` téměř nemusíte používat. +| `checkUrl` | [zkontroluje a případně upraví URL adresu |#checkUrl] +| `nocheck` | [vypne automatickou kontrolu URL adresy |#nocheck] .[note] -Všechny výchozí filtry jsou určeny pro řetězce v kódování UTF‑8. +Všechny výchozí filtry jsou navrženy pro práci s řetězci v kódování UTF-8. Použití ======= -Filtry se zapisují za svislítko (může být před ním mezera): +Filtry se aplikují pomocí svislítka za proměnnou nebo výrazem: ```latte

{$heading|upper}

``` -Filtry (ve starších verzích helpery) lze zřetězit a poté se aplikují v pořadí od levého k pravému: +Filtry lze řetězit, v takovém případě se aplikují zleva doprava: ```latte

{$heading|lower|capitalize}

``` -Parametry se zadávají za jménem filtru oddělené dvojtečkami nebo čárkami: +Parametry filtrů se zadávají za dvojtečkou: ```latte

{$heading|truncate:20,''}

``` -Filtry lze aplikovat i na výraz: +Filtry lze použít i na výrazy: ```latte -{var $name = ($title|upper) . ($subtitle|lower)} +{var $name = ($title|upper) . ($subtitle|lower)} ``` -[Vlastní filtry|extending-latte#filtry] lze registrovat tímto způsobem: +[Vlastní filtry|extending-latte#filtry] se registrují následovně: ```php $latte = new Latte\Engine; $latte->addFilter('shortify', fn(string $s, int $len = 10) => mb_substr($s, 0, $len)); ``` -V šabloně se potom volá takto: +V šabloně se pak volají stejně jako vestavěné filtry: ```latte

{$text|shortify}

@@ -122,7 +120,7 @@ Filtry batch(int length, mixed item): array .[filter] ---------------------------------------------- -Filtr, který zjednodušuje výpis lineárních dat do podoby tabulky. Vrací pole polí se zadaným počtem položek. Pokud zadáte druhý parametr, použije se k doplnění chybějících položek na posledním řádku. +Filtr `batch` usnadňuje výpis lineárních dat do tabulkové struktury. Vrací pole polí s požadovaným počtem položek. Pokud zadáte druhý parametr, použije se k doplnění chybějících položek v posledním řádku. ```latte {var $items = ['a', 'b', 'c', 'd', 'e']} @@ -137,7 +135,7 @@ Filtr, který zjednodušuje výpis lineárních dat do podoby tabulky. Vrací po ``` -Vypíše: +Výstup: ```latte @@ -159,7 +157,7 @@ Viz také [#group] a značka [iterateWhile|tags#iterateWhile]. breakLines .[filter] -------------------- -Přidává před každý znak nového řádku HTML značku `
` +Filtr `breakLines` vkládá HTML značku `
` před každý znak nového řádku. ```latte {var $s = "Text & with \n newline"} @@ -169,17 +167,19 @@ Přidává před každý znak nového řádku HTML značku `
` bytes(int precision = 2) .[filter] ---------------------------------- -Formátuje velikost v bajtech do lidsky čitelné podoby. Pokud je nastavené [národní prostředí |develop#locale], použijí se odpovídající oddělovače desetinných míst a tisíců. +Filtr `bytes` formátuje velikost v bajtech do lidsky čitelné podoby. Pokud je nastaveno [národní prostředí |develop#locale], použijí se odpovídající oddělovače desetinných míst a tisíců. ```latte {$size|bytes} 0 B, 1.25 GB, … {$size|bytes:0} 10 B, 1 GB, … ``` +Viz také [#number]. + ceil(int precision = 0) .[filter] --------------------------------- -Zaokrouhlí číslo nahoru na danou přesnost. +Filtr `ceil` zaokrouhlí číslo nahoru na danou přesnost. ```latte {=3.4|ceil} {* vypíše 4 *} @@ -192,7 +192,7 @@ Viz také [#floor], [#round]. capitalize .[filter] -------------------- -Slova budou začínat velkými písmeny, všechny zbývající znaky budou malá. Vyžaduje PHP rozšíření `mbstring`. +Filtr `capitalize` upraví text tak, že první písmeno každého slova bude velké a zbývající malá. Vyžaduje PHP rozšíření `mbstring`. ```latte {='i like LATTE'|capitalize} {* vypíše 'I Like Latte' *} @@ -203,7 +203,7 @@ Viz také [#firstUpper], [#lower], [#upper]. checkUrl .[filter] ------------------ -Vynutí ošetření URL adresy. Kontroluje, zda proměnná obsahuje webovou URL (tj. protokol HTTP/HTTPS) a předchází vypsání odkazů, které mohou představovat bezpečnostní riziko. +Filtr `checkUrl` zajistí kontrolu a případné ošetření URL adresy. Ověří, zda proměnná obsahuje webovou URL (tj. protokol HTTP/HTTPS) a zabrání vypsání odkazů, které by mohly představovat bezpečnostní riziko. ```latte {var $link = 'javascript:window.close()'} @@ -211,38 +211,40 @@ Vynutí ošetření URL adresy. Kontroluje, zda proměnná obsahuje webovou URL nekontrolované ``` -Vypíše: +Výstup: ```latte kontrolovanénekontrolované ``` +Latte automaticky [kontroluje atributy |safety-first#Kontrola odkazů] `src` a `href`, takže filtr `checkUrl` většinou není nutné explicitně uvádět. + Viz také [#nocheck]. clamp(int|float min, int|float max) .[filter] --------------------------------------------- -Ohraničí hodnotu do daného inkluzivního rozsahu min a max. +Filtr `clamp` omezí hodnotu do zadaného inkluzivního rozsahu min a max. ```latte {$level|clamp: 0, 255} ``` -Existuje také jako [funkce|functions#clamp]. +K dispozici je také jako [funkce|functions#clamp]. dataStream(string mimetype = detect) .[filter] ---------------------------------------------- -Konvertuje obsah do data URI scheme. Pomocí něj lze do HTML nebo CSS vkládat obrázky bez nutnosti linkovat externí soubory. +Filtr `dataStream` konvertuje obsah do schématu data URI. To umožňuje vkládat obrázky přímo do HTML nebo CSS bez nutnosti odkazovat na externí soubory. -Mějme v proměnné obrázek `$img = Image::fromFile('obrazek.gif')`, poté +Pokud máme v proměnné obrázek `$img = Image::fromFile('obrazek.gif')`, potom ```latte ``` -Vypíše například: +vypíše například: ```latte {$name} @@ -278,13 +280,13 @@ Viz také [#query]. explode(string separator = '') .[filter] ---------------------------------------- -Rozdělí řetězec na pole podle oddělovače. Alias pro `split`. +Filtr `explode` rozdělí řetězec na pole podle zadaného oddělovače. Je to alias pro `split`. ```latte {='one,two,three'|explode:','} {* vrací ['one', 'two', 'three'] *} ``` -Pokud je oddělovač prázdný řetězec (výchozí hodnota), bude vstup rozdělen na jednotlivé znaky: +Pokud je oddělovač prázdný řetězec (výchozí hodnota), vstup se rozdělí na jednotlivé znaky: ```latte {='123'|explode} {* vrací ['1', '2', '3'] *} @@ -301,7 +303,7 @@ Viz také [#implode]. first .[filter] --------------- -Vrací první prvek pole nebo znak řetězce: +Filtr `first` vrací první prvek pole nebo první znak řetězce: ```latte {=[1, 2, 3, 4]|first} {* vypíše 1 *} @@ -313,7 +315,7 @@ Viz také [#last], [#random]. floor(int precision = 0) .[filter] ---------------------------------- -Zaokrouhlí číslo dolů na danou přesnost. +Filtr `floor` zaokrouhlí číslo dolů na danou přesnost. ```latte {=3.5|floor} {* vypíše 3 *} @@ -326,7 +328,7 @@ Viz také [#ceil], [#round]. firstUpper .[filter] -------------------- -Převede první písmeno na velká. Vyžaduje PHP rozšíření `mbstring`. +Filtr `firstUpper` převede první písmeno na velké. Vyžaduje PHP rozšíření `mbstring`. ```latte {='the latte'|firstUpper} {* vypíše 'The latte' *} @@ -337,7 +339,7 @@ Viz také [#capitalize], [#lower], [#upper]. group(string|int|\Closure by): array .[filter]{data-version:3.0.16} ------------------------------------------------------------------- -Filtr seskupí data podle různých kritérií. +Filtr `group` umožňuje seskupit data podle různých kritérií. V tomto příkladu se řádky v tabulce seskupují podle sloupce `categoryId`. Výstupem je pole polí, kde klíčem je hodnota ve sloupci `categoryId`. [Přečtěte si podrobný návod|cookbook/grouping]. @@ -356,7 +358,7 @@ Viz také [#batch], funkce [group|functions#group] a značka [iterateWhile|tags# implode(string glue = '') .[filter] ----------------------------------- -Vrátí řetězec, který je zřetězením položek sekvence. Alias pro `join`. +Filtr `implode` spojí prvky pole do řetězce. Je to alias pro `join`. ```latte {=[1, 2, 3]|implode} {* vypíše '123' *} @@ -372,7 +374,7 @@ Můžete také použít alias `join`: indent(int level = 1, string char = "\t") .[filter] --------------------------------------------------- -Odsadí text zleva o daný počet tabulátorů nebo jiných znaků, které můžeme uvést ve druhém argumentu. Prázdné řádky nejsou odsazeny. +Filtr `indent` odsadí text zleva o zadaný počet tabulátorů nebo jiných znaků. Prázdné řádky nejsou odsazeny. ```latte
@@ -382,7 +384,7 @@ Odsadí text zleva o daný počet tabulátorů nebo jiných znaků, které můž
``` -Vypíše: +Výstup: ```latte
@@ -393,7 +395,7 @@ Vypíše: last .[filter] -------------- -Vrací poslední prvek pole nebo znak řetězce: +Filtr `last` vrací poslední prvek pole nebo poslední znak řetězce: ```latte {=[1, 2, 3, 4]|last} {* vypíše 4 *} @@ -405,13 +407,12 @@ Viz také [#first], [#random]. length .[filter] ---------------- -Vrátí délku řetězce nebo pole. - -- pro řetězce vrátí délku v UTF‑8 znacích -- pro pole vrátí počet položek -- pro objekty, které implementují rozhraní Countable, použije návratovou hodnotu metody count() -- pro objekty, které implementují rozhraní IteratorAggregate, použije návratovou hodnotu funkce iterator_count() +Filtr `length` vrátí délku řetězce nebo počet prvků v poli. +- pro řetězce vrátí počet unicode znaků +- pro pole vrátí počet prvků +- pro objekty implementující rozhraní Countable použije návratovou hodnotu metody count() +- pro objekty implementující rozhraní IteratorAggregate použije návratovou hodnotu funkce iterator_count() ```latte {if ($users|length) > 10} @@ -422,7 +423,7 @@ Vrátí délku řetězce nebo pole. localDate(string format = null, string date = null, string time = null) .[filter] --------------------------------------------------------------------------------- -Formátuje datum a čas podle [národního prostředí |develop#locale], což zajišťuje konzistentní a lokalizované zobrazení časových údajů napříč různými jazyky a regiony. Filtr přijímá datum jako UNIX timestamp, řetězec nebo objekt typu `DateTimeInterface`. +Filtr `localDate` formátuje datum a čas podle [národního prostředí |develop#locale]. To zajišťuje konzistentní a lokalizované zobrazení časových údajů napříč různými jazyky a regiony. Filtr přijímá datum jako UNIX timestamp, řetězec nebo objekt typu `DateTimeInterface`. ```latte {$date|localDate} {* 15. dubna 2024 *} @@ -430,20 +431,20 @@ Formátuje datum a čas podle [národního prostředí |develop#locale], což za {$date|localDate: date: medium} {* 15. 4. 2024 *} ``` -Pokud použijete filtr bez parametrů, vypíše se datum v úrovní `long`, viz dále. +Bez parametrů se datum vypíše v úrovni `long` (viz dále). **a) použití formátu** -Parametr `format` popisuje, které časové složky se mají zobrazit. Používá pro ně písmenné kódy, jejichž počet opakování ovlivňuje šířku výstupu: +Parametr `format` definuje, které časové složky se mají zobrazit. Používá písmena jako kódy, jejichž počet opakování ovlivňuje šířku výstupu: | rok | `y` / `yy` / `yyyy` | `2024` / `24` / `2024` | měsíc | `M` / `MM` / `MMM` / `MMMM` | `8` / `08` / `srp` / `srpen` | den | `d` / `dd` / `E` / `EEEE` | `1` / `01` / `ne` / `neděle` -| hodina | `j` / `H` / `h` | preferovaný / 24hodinový / 12hodinový +| hodina | `j` / `H` / `h` | preferovaná / 24hodinová / 12hodinová | minuta | `m` / `mm` | `5` / `05` (2 číslice v kombinaci se sekundami) | sekunda | `s` / `ss` | `8` / `08` (2 číslice v kombinaci s minutami) -Na pořadí kódů ve formátu nezáleží, protože pořadí složek se vypíše podle zvyklostí národního prostředí. Formát je tedy na něm nezávislý. Například formát `yyyyMMMMd` v postředí `en_US` vypíše `April 15, 2024`, zatímco v prostředí `cs_CZ` vypíše `15. dubna 2024`: +Pořadí kódů ve formátu nemá vliv na pořadí složek ve výstupu, protože to se řídí zvyklostmi národního prostředí. Formát je tedy na něm nezávislý. Například formát `yyyyMMMMd` v prostředí `en_US` vypíše `April 15, 2024`, zatímco v prostředí `cs_CZ` vypíše `15. dubna 2024`: | locale: | cs_CZ | en_US |--- @@ -458,7 +459,7 @@ Na pořadí kódů ve formátu nezáleží, protože pořadí složek se vypíš **b) použití přednastavených stylů** -Parametry `date` a `time` určují, jak podrobně se má datum a čas vypsat. Můžete si vybrat z několika úrovní: `full`, `long`, `medium`, `short`. Lze nechat vypsat jen datum, jen čas, nebo obojí: +Parametry `date` a `time` určují úroveň podrobnosti pro výpis data a času. K dispozici jsou úrovně: `full`, `long`, `medium`, `short`. Můžete nechat vypsat jen datum, jen čas, nebo obojí: | locale: | cs_CZ | en_US |--- @@ -473,7 +474,7 @@ Parametry `date` a `time` určují, jak podrobně se má datum a čas vypsat. M | `date: medium, time: short` | 23. 1. 1978 8:30 | Jan 23, 1978, 8:30 AM | `date: long, time: short` | 23. ledna 1978 v 8:30 | January 23, 1978 at 8:30 AM -U data lze navíc použít prefix `relative-` (např. `relative-short`), který pro data blízká současnosti zobrazí `včera`, `dnes` nebo `zítra`, jinak se vypíše standardním způsobem. +Pro datum lze použít prefix `relative-` (např. `relative-short`), který pro data blízká současnosti zobrazí `včera`, `dnes` nebo `zítra`, jinak se vypíše standardním způsobem. ```latte {$date|localDate: date: relative-short} {* včera *} @@ -484,7 +485,7 @@ Viz také [#date]. lower .[filter] --------------- -Převede řetězec na malá písmena. Vyžaduje PHP rozšíření `mbstring`. +Filtr `lower` převede řetězec na malá písmena. Vyžaduje PHP rozšíření `mbstring`. ```latte {='LATTE'|lower} {* vypíše 'latte' *} @@ -495,9 +496,9 @@ Viz také [#capitalize], [#firstUpper], [#upper]. nocheck .[filter] ----------------- -Předejde automatickému ošetření URL adresy. Latte [automaticky kontroluje|safety-first#Kontrola odkazů], zda proměnná obsahuje webovou URL (tj. protokol HTTP/HTTPS) a předchází vypsání odkazů, které mohou představovat bezpečnostní riziko. +Filtr `nocheck` vypne automatickou kontrolu URL adresy. Latte standardně [kontroluje |safety-first#Kontrola odkazů], zda proměnná obsahuje webovou URL (tj. protokol HTTP/HTTPS) a brání vypsání potenciálně nebezpečných odkazů. -Pokud odkaz používá jiné schéma, např. `javascript:` nebo `data:`, a jste si jistí jeho obsahem, můžete kontrolu vypnout pomoci `|nocheck`. +Pokud odkaz používá jiné schéma, např. `javascript:` nebo `data:`, a jste si jisti jeho obsahem, můžete kontrolu vypnout pomocí `|nocheck`. ```latte {var $link = 'javascript:window.close()'} @@ -506,7 +507,7 @@ Pokud odkaz používá jiné schéma, např. `javascript:` nebo `data:`, a jste nekontrolované ``` -Vypíše: +Výstup: ```latte kontrolované @@ -518,7 +519,7 @@ Viz také [#checkUrl]. noescape .[filter] ------------------ -Zakáže automatické escapování. +Filtr `noescape` vypne automatické escapování. ```latte {var $trustedHtmlString = 'hello'} @@ -526,7 +527,7 @@ Escapovaný: {$trustedHtmlString} Neescapovaný: {$trustedHtmlString|noescape} ``` -Vypíše: +Výstup: ```latte Escapovaný: <b>hello</b> @@ -534,12 +535,12 @@ Neescapovaný: hello ``` .[warning] -Špatné použití filtru `noescape` může vést ke vzniku zranitelnosti XSS! Nikdy jej nepoužívejte, pokud si nejste **zcela jisti** co děláte, a že vypisovaný řetězec pochází z důvěryhodného zdroje. +Nesprávné použití filtru `noescape` může vést ke zranitelnosti XSS! Používejte jej pouze tehdy, když si jste **naprosto jisti**, že vypisovaný řetězec pochází z důvěryhodného zdroje. number(int decimals = 0, string decPoint = '.', string thousandsSep = ',') .[filter] ------------------------------------------------------------------------------------ -Formátuje číslo na určitý počet desetinných míst. Pokud je nastavené [národní prostředí |develop#locale], použijí se odpovídající oddělovače desetinných míst a tisíců. +Filtr `number` formátuje číslo na zadaný počet desetinných míst. Pokud je nastaveno [národní prostředí |develop#locale], použijí se odpovídající oddělovače desetinných míst a tisíců. ```latte {1234.20|number} 1,234 @@ -551,16 +552,16 @@ Formátuje číslo na určitý počet desetinných míst. Pokud je nastavené [n number(string format) .[filter] ------------------------------- -Parametr `format` umožňuje definovat vzhled čísel přesně podle vašich potřeb. K tomu je potřeba mít nastavené [národní prostředí |develop#locale]. Formát se skládá z několika speciálních znaků, jejichž kompletní popis najdete v dokumentaci "DecimalFormat":https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns: +Parametr `format` umožňuje přesně definovat vzhled čísel podle vašich potřeb. K tomu je nutné mít nastavené [národní prostředí |develop#locale]. Formát se skládá z několika speciálních znaků, jejichž kompletní popis najdete v dokumentaci "DecimalFormat":https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns: - `0` povinná číslice, vždy se zobrazí, i kdyby to byla nula - `#` volitelná číslice, zobrazí se jen tehdy, pokud na tomto místě číslo skutečně je - `@` významná číslice, pomáhá zobrazit číslo s určitým počtem platných číslic -- `.` označuje, kde má být desetinná čárka (nebo tečka, podle země) +- `.` označuje pozici desetinné čárky (nebo tečky, podle země) - `,` slouží k oddělení skupin číslic, nejčastěji tisíců - `%` číslo vynásobí 100× a přidá znak procenta -Pojďme se podívat na příklady. V prvním příkladu jsou dvě desetinná místa povinná, ve druhém volitelná. Třetí příklad ukazuje doplnění nulami zleva i zprava, čtvrtý zobrazuje jen existující číslice: +Podívejme se na příklady. V prvním příkladu jsou dvě desetinná místa povinná, ve druhém volitelná. Třetí příklad ukazuje doplnění nulami zleva i zprava, čtvrtý zobrazuje jen existující číslice: ```latte {1234.5|number: '#,##0.00'} {* 1,234.50 *} @@ -569,7 +570,7 @@ Pojďme se podívat na příklady. V prvním příkladu jsou dvě desetinná mí {1.2 |number: '##.##'} {* 1.2 *} ``` -Významné číslice určují, kolik číslic bez ohledu na desetinou čárku má být zobrazeno, přičemž se zaokrouhluje: +Významné číslice určují, kolik číslic bez ohledu na desetinnou čárku má být zobrazeno, přičemž dochází k zaokrouhlování: ```latte {1234|number: '@@'} {* 1200 *} @@ -585,7 +586,7 @@ Snadný způsob, jak zobrazit číslo jako procenta. Číslo se vynásobí 100× {0.1234|number: '#.##%'} {* 12.34% *} ``` -Můžeme definovat odlišný formát pro kladná a záporná čísla, odděluje je znak `;`. Tímto způsobem lze například nastavit, že kladná čísla se mají zobrazovat se znaménkem `+`: +Můžeme definovat odlišný formát pro kladná a záporná čísla, oddělené znakem `;`. Tímto způsobem lze například nastavit, že kladná čísla se mají zobrazovat se znaménkem `+`: ```latte {42|number: '#.##;(#.##)'} {* 42 *} @@ -594,12 +595,12 @@ Můžeme definovat odlišný formát pro kladná a záporná čísla, odděluje {-42|number: '+#.##;-#.##'} {* -42 *} ``` -Pamatujte, že skutečný vzhled čísel se může lišit podle nastavení země. Například v některých zemích se používá čárka místo tečky jako oddělovač desetinných míst. Tento filtr to automaticky zohlední a nemusíte se o nic starat. +Nezapomeňte, že skutečný vzhled čísel se může lišit podle nastavení země. Například v některých zemích se používá čárka místo tečky jako oddělovač desetinných míst. Tento filtr to automaticky zohlední, takže se o to nemusíte starat. padLeft(int length, string pad = ' ') .[filter] ----------------------------------------------- -Doplní řetězec do určité délky jiným řetězcem zleva. +Filtr `padLeft` doplní řetězec zleva na požadovanou délku jiným řetězcem. ```latte {='hello'|padLeft: 10, '123'} {* vypíše '12312hello' *} @@ -608,7 +609,7 @@ Doplní řetězec do určité délky jiným řetězcem zleva. padRight(int length, string pad = ' ') .[filter] ------------------------------------------------ -Doplní řetězec do určité délky jiným řetězcem zprava. +Filtr `padRight` doplní řetězec zprava na požadovanou délku jiným řetězcem. ```latte {='hello'|padRight: 10, '123'} {* vypíše 'hello12312' *} @@ -617,18 +618,18 @@ Doplní řetězec do určité délky jiným řetězcem zprava. query .[filter] --------------- -Dynamicky generuje query string v URL: +Filtr `query` dynamicky generuje query string v URL: ```latte -click -search +klikněte +hledat ``` -Vypíše: +Výstup: ```latte -click -search +klikněte +hledat ``` Klíče s hodnotou `null` se vynechají. @@ -638,7 +639,7 @@ Viz také [#escapeUrl]. random .[filter] ---------------- -Vrací náhodný prvek pole nebo znak řetězce: +Filtr `random` vrací náhodný prvek pole nebo náhodný znak řetězce: ```latte {=[1, 2, 3, 4]|random} {* vypíše např.: 3 *} @@ -650,7 +651,7 @@ Viz také [#first], [#last]. repeat(int count) .[filter] --------------------------- -Opakuje řetězec x-krát. +Filtr `repeat` opakuje řetězec zadaný počet krát. ```latte {='hello'|repeat: 3} {* vypíše 'hellohellohello' *} @@ -659,7 +660,7 @@ Opakuje řetězec x-krát. replace(string|array search, string replace = '') .[filter] ----------------------------------------------------------- -Nahradí všechny výskyty vyhledávacího řetězce náhradním řetězcem. +Filtr `replace` nahradí všechny výskyty hledaného řetězce náhradním řetězcem. ```latte {='hello world'|replace: 'world', 'friend'} {* vypíše 'hello friend' *} @@ -674,7 +675,7 @@ Lze provést i více záměn najednou: replaceRE(string pattern, string replace = '') .[filter] -------------------------------------------------------- -Provede vyhledávání regulárních výrazů s nahrazením. +Filtr `replaceRE` provádí nahrazování podle regulárních výrazů. ```latte {='hello world'|replaceRE: '/l.*/', 'l'} {* vypíše 'hel' *} @@ -683,19 +684,19 @@ Provede vyhledávání regulárních výrazů s nahrazením. reverse .[filter] ----------------- -Obrátí daný řetězec nebo pole. +Filtr `reverse` obrátí pořadí znaků v řetězci nebo prvků v poli. ```latte {var $s = 'Nette'} {$s|reverse} {* vypíše 'etteN' *} {var $a = ['N', 'e', 't', 't', 'e']} -{$a|reverse} {* returns ['e', 't', 't', 'e', 'N'] *} +{$a|reverse} {* vrátí ['e', 't', 't', 'e', 'N'] *} ``` round(int precision = 0) .[filter] ---------------------------------- -Zaokrouhlí číslo na danou přesnost. +Filtr `round` zaokrouhlí číslo na zadanou přesnost. ```latte {=3.4|round} {* vypíše 3 *} @@ -709,25 +710,25 @@ Viz také [#ceil], [#floor]. slice(int start, int length = null, bool preserveKeys = false) .[filter] ------------------------------------------------------------------------ -Extrahuje část pole nebo řetězce. +Filtr `slice` extrahuje část pole nebo řetězce. ```latte {='hello'|slice: 1, 2} {* vypíše 'el' *} {=['a', 'b', 'c']|slice: 1, 2} {* vypíše ['b', 'c'] *} ``` -Filtr funguje jako funkce PHP `array_slice` pro pole nebo `mb_substr` pro řetězce s fallbackem na funkci `iconv_substr` v režimu UTF‑8. +Tento filtr funguje jako funkce PHP `array_slice` pro pole nebo `mb_substr` pro řetězce s fallbackem na funkci `iconv_substr` v režimu UTF-8. -Pokud je start kladný, posloupnost začné posunutá o tento počet od začátku pole/řetezce. Pokud je záporný posloupnost začné posunutá o tolik od konce. +Pokud je `start` kladný, posloupnost začíná posunutá o tento počet od začátku pole/řetězce. Pokud je záporný, posloupnost začíná posunutá o tolik od konce. -Pokud je zadaný parametr length a je kladný, posloupnost bude obsahovat tolik prvků. Pokud je do této funkce předán záporný parametr length, posloupnost bude obsahovat všechny prvky původního pole, začínající na pozici start a končicí na pozici menší na length prvků od konce pole. Pokud tento parametr nezadáte, posloupnost bude obsahovat všechny prvky původního pole, začínající pozici start. +Pokud je zadán parametr `length` a je kladný, posloupnost bude obsahovat tolik prvků. Pokud je do této funkce předán záporný parametr `length`, posloupnost bude obsahovat všechny prvky původního pole, začínající na pozici `start` a končící na pozici menší o `length` prvků od konce pole. Pokud tento parametr nezadáte, posloupnost bude obsahovat všechny prvky původního pole, začínající pozicí `start`. -Ve výchozím nastavení filtr změní pořadí a resetuje celočíselného klíče pole. Toto chování lze změnit nastavením preserveKeys na true. Řetězcové klíče jsou vždy zachovány, bez ohledu na tento parametr. +Ve výchozím nastavení filtr změní pořadí a resetuje celočíselné klíče pole. Toto chování lze změnit nastavením `preserveKeys` na true. Řetězcové klíče jsou vždy zachovány, bez ohledu na tento parametr. sort(?Closure comparison, string|int|\Closure|null by=null, string|int|\Closure|bool byKey=false) .[filter] ----------------------------------------------------------------------------------------------------------- -Filtr seřadí prvky pole nebo iterátoru a zachová jejich asociační klíče. Při nastaveném [národním prostředí |develop#locale] se řazení řídí jeho pravidly, pokud není specifikována vlastní porovnávací funkce. +Filtr `sort` seřadí prvky pole nebo iterátoru a zachová jejich asociační klíče. Při nastaveném [národním prostředí |develop#locale] se řazení řídí jeho pravidly, pokud není specifikována vlastní porovnávací funkce. ```latte {foreach ($names|sort) as $name} @@ -735,7 +736,7 @@ Filtr seřadí prvky pole nebo iterátoru a zachová jejich asociační klíče. {/foreach} ``` -Řazené pole v opačném pořadí: +Pro řazení pole v opačném pořadí: ```latte {foreach ($names|sort|reverse) as $name} @@ -757,7 +758,7 @@ Filtr `|sort` také umožňuje řadit prvky podle klíčů: {/foreach} ``` -Pokud potřebujete seřadit tabulku podle konkrétního sloupce, můžete použít parametr `by`. Hodnota `'name'` v ukázce určuje, že se bude řadit podle `$item->name` nebo `$item['name']`, v závislosti na tom, zda je `$item` pole nebo objekt: +Pokud potřebujete seřadit tabulku podle konkrétního sloupce, můžete použít parametr `by`. Hodnota `'name'` v ukázce určuje, že se bude řadit podle `$item->name` nebo `$item['name']`, v závislosti na tom, zda je `$item` objekt nebo pole: ```latte {foreach ($items|sort: by: 'name') as $item} @@ -768,7 +769,7 @@ Pokud potřebujete seřadit tabulku podle konkrétního sloupce, můžete použ Můžete také definovat callback funkci, která určí hodnotu, podle které se má řadit: ```latte -{foreach ($items|sort: by: fn($items) => $items->category->name) as $item} +{foreach ($items|sort: by: fn($item) => $item->category->name) as $item} {$item->name} {/foreach} ``` @@ -778,7 +779,7 @@ Stejným způsobem lze využít i parametr `byKey`. spaceless .[filter] ------------------- -Odstraní zbytečné bílé místo (mezery) z výstupu. Můžete také použít alias `strip`. +Filtr `spaceless` odstraní nadbytečné bílé znaky z výstupu. Můžete také použít alias `strip`. ```latte {block |spaceless} @@ -788,7 +789,7 @@ Odstraní zbytečné bílé místo (mezery) z výstupu. Můžete také použít {/block} ``` -Vypíše: +Výstup: ```latte
  • Hello
@@ -797,7 +798,7 @@ Vypíše: stripHtml .[filter] ------------------- -Převádí HTML na čistý text. Tedy odstraní z něj HTML značky a HTML entity převede na text. +Filtr `stripHtml` převádí HTML na čistý text. Odstraní HTML značky a převede HTML entity na jejich textovou reprezentaci. ```latte {='

one < two

'|stripHtml} {* vypíše 'one < two' *} @@ -808,7 +809,7 @@ Výsledný čistý text může přirozeně obsahovat znaky, které představují substr(int offset, int length = null) .[filter] ----------------------------------------------- -Extrahuje část řetězce. Tento filtr byl nahrazen filtrem [#slice]. +Filtr `substr` extrahuje část řetězce. Tento filtr byl nahrazen filtrem [#slice]. ```latte {$string|substr: 1, 2} @@ -817,7 +818,7 @@ Extrahuje část řetězce. Tento filtr byl nahrazen filtrem [#slice]. translate(string message, ...args) .[filter] -------------------------------------------- -Překládá výrazy do jiných jazyků. Aby byl filtr k dispozici, je potřeba [nastavit překladač|develop#TranslatorExtension]. Můžete také použít [tagy pro překlad|tags#Překlady]. +Filtr `translate` překládá výrazy do jiných jazyků. Aby byl filtr k dispozici, je potřeba [nastavit překladač|develop#TranslatorExtension]. Můžete také použít [tagy pro překlad|tags#Překlady]. ```latte {='Košík'|translate} @@ -827,7 +828,7 @@ Překládá výrazy do jiných jazyků. Aby byl filtr k dispozici, je potřeba [ trim(string charlist = " \t\n\r\0\x0B\u{A0}") .[filter] ------------------------------------------------------- -Odstraní prázdné znaky (nebo jiné znaky) od začátku a konce řetězce. +Filtr `trim` odstraní bílé znaky (nebo jiné zadané znaky) od začátku a konce řetězce. ```latte {=' I like Latte. '|trim} {* vypíše 'I like Latte.' *} @@ -837,7 +838,7 @@ Odstraní prázdné znaky (nebo jiné znaky) od začátku a konce řetězce. truncate(int length, string append = '…') .[filter] --------------------------------------------------- -Ořízne řetězec na uvedenou maximální délku, přičemž se snaží zachovávat celá slova. Pokud dojde ke zkrácení řetězce, přidá nakonec trojtečku (lze změnit druhým parametrem). +Filtr `truncate` zkrátí řetězec na uvedenou maximální délku, přičemž se snaží zachovávat celá slova. Pokud dojde ke zkrácení řetězce, přidá nakonec trojtečku (lze změnit druhým parametrem). ```latte {var $title = 'Hello, how are you?'} @@ -849,7 +850,7 @@ Ořízne řetězec na uvedenou maximální délku, přičemž se snaží zachov upper .[filter] --------------- -Převede řetězec na velká písmena. Vyžaduje PHP rozšíření `mbstring`. +Filtr `upper` převede řetězec na velká písmena. Vyžaduje PHP rozšíření `mbstring`. ```latte {='latte'|upper} {* vypíše 'LATTE' *} @@ -860,9 +861,9 @@ Viz také [#capitalize], [#firstUpper], [#lower]. webalize .[filter] ------------------ -Upraví UTF‑8 řetězec do tvaru používaného v URL. +Filtr `webalize` upraví UTF-8 řetězec do tvaru používaného v URL. -Převádí se na ASCII. Převede mezery na pomlčky. Odstraní znaky, které nejsou alfanumerické, podtržítka ani pomlčky. Převede na malá písmena. Také odstraní přední a koncové mezery. +Převádí znaky na ASCII ekvivalenty. Převádí mezery na pomlčky. Odstraní znaky, které nejsou alfanumerické, podtržítka ani pomlčky. Převádí text na malá písmena. Také odstraní úvodní a koncové bílé znaky. ```latte {var $s = 'Náš 10. produkt'} diff --git a/latte/cs/functions.texy b/latte/cs/functions.texy index c765b63c79..7f4fd0e8e0 100644 --- a/latte/cs/functions.texy +++ b/latte/cs/functions.texy @@ -2,24 +2,24 @@ Latte funkce ************ .[perex] -V šablonách můžeme kromě běžných PHP funkcí používat i tyto další. +V šablonách Latte můžeme kromě běžných PHP funkcí využívat i další speciální funkce, které rozšiřují možnosti při práci s daty a šablonami. .[table-latte-filters] -| `clamp` | [ohraničí hodnotu do daného rozsahu |#clamp] -| `divisibleBy`| [zkontroluje, zda je proměnná dělitelná číslem |#divisibleBy] -| `even` | [zkontroluje, zda je dané číslo sudé |#even] -| `first` | [vrací první prvek pole nebo znak řetězce |#first] -| `group` | [seskupí data podle různých kritérií |#group] -| `hasBlock` | [zjistí existenci bloku |#hasBlock] -| `last` | [vrací poslední prvek pole nebo znak řetězce |#last] -| `odd` | [zkontroluje, zda je dané číslo liché |#odd] +| `clamp` | [omezí hodnotu do zadaného rozsahu |#clamp] +| `divisibleBy`| [ověří dělitelnost čísla |#divisibleBy] +| `even` | [zkontroluje, zda je číslo sudé |#even] +| `first` | [získá první prvek pole nebo znak řetězce |#first] +| `group` | [seskupí data podle zadaných kritérií |#group] +| `hasBlock` | [ověří existenci bloku |#hasBlock] +| `last` | [získá poslední prvek pole nebo znak řetězce |#last] +| `odd` | [zkontroluje, zda je číslo liché |#odd] | `slice` | [extrahuje část pole nebo řetězce |#slice] Použití ======= -Funkce se používají strejně jaké běžné PHP funkce a lze je použít ve všechn výrazech: +Funkce v Latte se používají stejně jako běžné PHP funkce a lze je využít ve všech výrazech: ```latte

{clamp($num, 1, 100)}

@@ -27,14 +27,14 @@ Funkce se používají strejně jaké běžné PHP funkce a lze je použít ve v {if odd($num)} ... {/if} ``` -[Vlastní funkce|extending-latte#funkce] lze registrovat tímto způsobem: +[Vlastní funkce|extending-latte#funkce] můžete do Latte přidat takto: ```php $latte = new Latte\Engine; $latte->addFunction('shortify', fn(string $s, int $len = 10) => mb_substr($s, 0, $len)); ``` -V šabloně se potom volá takto: +V šabloně pak tuto funkci můžete volat následovně: ```latte

{shortify($text)}

@@ -48,7 +48,7 @@ Funkce clamp(int|float $value, int|float $min, int|float $max): int|float .[method] ---------------------------------------------------------------------------- -Ohraničí hodnotu do daného inkluzivního rozsahu min a max. +Funkce `clamp` omezí hodnotu do zadaného inkluzivního rozsahu mezi `$min` a `$max`. ```latte {=clamp($level, 0, 255)} @@ -59,7 +59,7 @@ Viz také [filtr clamp|filters#clamp]. divisibleBy(int $value, int $by): bool .[method] ------------------------------------------------ -Zkontroluje, zda je proměnná dělitelná číslem. +Funkce `divisibleBy` ověří, zda je číslo `$value` dělitelné číslem `$by`. ```latte {if divisibleBy($num, 5)} ... {/if} @@ -68,7 +68,7 @@ Zkontroluje, zda je proměnná dělitelná číslem. even(int $value): bool .[method] -------------------------------- -Zkontroluje, zda je dané číslo sudé. +Funkce `even` zkontroluje, zda je dané číslo sudé. ```latte {if even($num)} ... {/if} @@ -77,7 +77,7 @@ Zkontroluje, zda je dané číslo sudé. first(string|iterable $value): mixed .[method] ---------------------------------------------- -Vrací první prvek pole nebo znak řetězce: +Funkce `first` vrací první prvek pole nebo první znak řetězce: ```latte {=first([1, 2, 3, 4])} {* vypíše 1 *} @@ -89,9 +89,9 @@ Viz také [#last], [filtr first|filters#first]. group(iterable $data, string|int|\Closure $by): array .[method]{data-version:3.0.16} ------------------------------------------------------------------------------------ -Funkce seskupí data podle různých kritérií. +Funkce `group` seskupí data podle zadaných kritérií. -V tomto příkladu se řádky v tabulce seskupují podle sloupce `categoryId`. Výstupem je pole polí, kde klíčem je hodnota ve sloupci `categoryId`. [Přečtěte si podrobný návod|cookbook/grouping]. +V tomto příkladu se řádky v tabulce seskupují podle sloupce `categoryId`. Výsledkem je pole polí, kde klíčem je hodnota ve sloupci `categoryId`. [Podrobný návod najdete zde|cookbook/grouping]. ```latte {foreach group($items, categoryId) as $categoryId => $categoryItems} @@ -108,7 +108,7 @@ Viz také filtr [group|filters#group]. hasBlock(string $name): bool .[method]{data-version:3.0.10} ----------------------------------------------------------- -Zjistí, zda blok uvedeného jména existuje: +Funkce `hasBlock` ověří, zda existuje blok s uvedeným názvem: ```latte {if hasBlock(header)} ... {/if} @@ -119,7 +119,7 @@ Viz také [kontrola existence bloků|template-inheritance#Kontrola existence blo last(string|array $value): mixed .[method] ------------------------------------------ -Vrací poslední prvek pole nebo znak řetězce: +Funkce `last` vrací poslední prvek pole nebo poslední znak řetězce: ```latte {=last([1, 2, 3, 4])} {* vypíše 4 *} @@ -131,7 +131,7 @@ Viz také [#first], [filtr last|filters#last]. odd(int $value): bool .[method] ------------------------------- -Zkontroluje, zda je dané číslo liché. +Funkce `odd` zkontroluje, zda je dané číslo liché. ```latte {if odd($num)} ... {/if} @@ -140,17 +140,17 @@ Zkontroluje, zda je dané číslo liché. slice(string|array $value, int $start, int $length=null, bool $preserveKeys=false): string|array .[method] ---------------------------------------------------------------------------------------------------------- -Extrahuje část pole nebo řetězce. +Funkce `slice` extrahuje část pole nebo řetězce. ```latte {=slice('hello', 1, 2)} {* vypíše 'el' *} {=slice(['a', 'b', 'c'], 1, 2)} {* vypíše ['b', 'c'] *} ``` -Filtr funguje jako funkce PHP `array_slice` pro pole nebo `mb_substr` pro řetězce s fallbackem na funkci `iconv_substr` v režimu UTF‑8. +Tato funkce funguje podobně jako PHP funkce `array_slice` pro pole nebo `mb_substr` pro řetězce (s fallbackem na `iconv_substr` v režimu UTF-8). -Pokud je start kladný, posloupnost začné posunutá o tento počet od začátku pole/řetezce. Pokud je záporný posloupnost začné posunutá o tolik od konce. +- Pokud je `$start` kladný, výsledek začíná od tohoto indexu od začátku pole/řetězce. Pokud je záporný, začíná se od konce. -Pokud je zadaný parametr length a je kladný, posloupnost bude obsahovat tolik prvků. Pokud je do této funkce předán záporný parametr length, posloupnost bude obsahovat všechny prvky původního pole, začínající na pozici start a končicí na pozici menší na length prvků od konce pole. Pokud tento parametr nezadáte, posloupnost bude obsahovat všechny prvky původního pole, začínající pozici start. +- Pokud je `$length` kladný, výsledek bude obsahovat tolik prvků. Pokud je záporný, výsledek bude obsahovat všechny prvky kromě posledních `$length` prvků. Pokud není zadán, výsledek bude obsahovat všechny prvky od `$start` do konce. -Ve výchozím nastavení filtr změní pořadí a resetuje celočíselného klíče pole. Toto chování lze změnit nastavením preserveKeys na true. Řetězcové klíče jsou vždy zachovány, bez ohledu na tento parametr. +- Parametr `$preserveKeys` určuje, zda zachovat původní klíče pole. Ve výchozím nastavení (false) jsou číselné klíče resetovány. Řetězcové klíče jsou vždy zachovány bez ohledu na toto nastavení. diff --git a/latte/cs/recipes.texy b/latte/cs/recipes.texy index 90d74badb3..11389d60c2 100644 --- a/latte/cs/recipes.texy +++ b/latte/cs/recipes.texy @@ -5,19 +5,19 @@ Tipy a triky Editory a IDE ============= -Pište šablony v editoru nebo IDE, který má podporu pro Latte. Bude to mnohem příjemnější. +Efektivní práce s Latte šablonami začíná u správně nastaveného vývojového prostředí. Vhodný editor nebo IDE s podporou Latte vám významně usnadní práci a zvýší produktivitu. -- NetBeans IDE má podporu vestavěnou -- PhpStorm: nainstalujte v `Settings > Plugins > Marketplace` [plugin Latte|https://plugins.jetbrains.com/plugin/7457-latte] -- VS Code: hledejte v marketplace [Nette Latte + Neon|https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] nebo [Nette Latte templates|https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] plugin -- Sublime Text 3: v Package Control najděte a nainstalujte balíček `Nette` a zvolte Latte ve `View > Syntax` -- ve starých editorech použijte pro soubory .latte zvýrazňování Smarty +- PhpStorm: v `Settings > Plugins > Marketplace` nainstalujte [plugin Latte|https://plugins.jetbrains.com/plugin/7457-latte] +- VS Code: vyhledejte a nainstalujte [Nette Latte + Neon|https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] nebo [Nette Latte templates|https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] plugin +- NetBeans IDE: nativní podpora Latte je součástí instalace +- Sublime Text 3: přes Package Control nainstalujte balíček `Nette` a v `View > Syntax` zvolte Latte +- Pro starší editory: použijte zvýrazňování syntaxe pro Smarty u souborů s příponou .latte -Plugin pro PhpStorm je velmi pokročilý a umí výborně napovídat PHP kód. Aby fungoval optimálně, používejte [typované šablony|type-system]. +Plugin pro PhpStorm vyniká pokročilými funkcemi a nabízí vynikající napovídání PHP kódu. Pro jeho optimální funkčnost doporučujeme používat [typované šablony|type-system]. [* latte-phpstorm-plugin.webp *] -Podporu pro Latte najdete také ve webovém zvýrazňovači kódu [Prism.js|https://prismjs.com/#supported-languages] a editoru [Ace|https://ace.c9.io]. +Podporu Latte najdete také v online zvýrazňovači kódu [Prism.js|https://prismjs.com/#supported-languages] a webovém editoru [Ace|https://ace.c9.io]. Latte uvnitř JavaScriptu nebo CSS @@ -37,9 +37,11 @@ Latte lze velmi pohodlně používat i uvnitř JavaScriptu nebo CSS. Jak se vša ``` -**Varianta 1** +Existuje několik řešení: -Vyhněte se situaci, kdy následuje písmeno hned za `{`, třeba tím, že před něj vložíte mezeru, odřádkování nebo uvozovku: +**Řešení 1: Oddělení závorek** + +Vložte mezeru, odřádkování nebo uvozovku mezi `{` a následující písmeno: ```latte `. Naopak v atributech `style` a `on***` se pomocí HTML entit escapuje. -A samozřejmě uvnitř vnořeného JavaScriptu nebo CSS platí escapovací pravidla těchto jazyků. Takže řetezec v atributu např. `onload` se nejprve escapuje podle pravidel JS a potom podle pravidel HTML atributu. +A samozřejmě uvnitř vnořeného JavaScriptu nebo CSS platí escapovací pravidla těchto jazyků. Řetězec v atributu například `onload` se nejprve escapuje podle pravidel JS a potom podle pravidel HTML atributu. -Uff... Jak vidíte, HTML je velmi komplexní dokument, kde se vrství kontexty, a bez uvědomění si, kde přesně data vypisuji (tj. v jakém kontextu), nelze říct, jak to správně udělat. +Jak vidíte, HTML je velmi komplexní dokument, kde se vrství kontexty. Bez uvědomění si, kde přesně data vypisuji (tj. v jakém kontextu), nelze říct, jak to správně udělat. Chcete příklad? --------------- -Mějme řetězec `Rock'n'Roll`. +Vezměme řetězec `Rock'n'Roll`. -Pokud jej budete vypisovat v HTML textu, zrovna v tomhle případě netřeba dělat žádné záměny, protože řetězec neobsahuje žádný znak se speciálním významem. Jiná situace nastane, pokud jej vypíšete uvnitř HTML atributu uvozeného do jednoduchých uvozovek. V takovém případě je potřeba escapovat uvozovky na HTML entity: +Pokud jej budete vypisovat v HTML textu, v tomto konkrétním případě není třeba provádět žádné záměny, protože řetězec neobsahuje žádný znak se speciálním významem. Jiná situace nastane, pokud jej vypíšete uvnitř HTML atributu ohraničeného jednoduchými uvozovkami. V takovém případě je potřeba escapovat uvozovky na HTML entity: ```html
``` -Tohle bylo jednoduché. Mnohem zajímavější situace nastane při vrstvení kontextů, například pokud řetězec bude součástí JavaScriptu. +To bylo jednoduché. Mnohem zajímavější situace nastane při vrstvení kontextů, například pokud řetězec bude součástí JavaScriptu. -Nejprve jej tedy vypíšeme do samotného JavaScriptu. Tj. obalíme jej do uvozovek a zároveň escapujeme pomocí znaku `\` uvozovky v něm obsažené: +Nejprve jej vypíšeme do samotného JavaScriptu. Obalíme jej do uvozovek a zároveň escapujeme pomocí znaku `\` uvozovky v něm obsažené: ```js 'Rock\'n\'Roll' ``` -Ještě můžeme doplnit volání nějaké funkce, ať kód něco dělá: +Doplňme volání nějaké funkce, ať kód něco dělá: ```js alert('Rock\'n\'Roll'); ``` -Pokud tento kód vložíme do HTML dokumentu pomocí ``: ```html @@ -174,13 +173,13 @@ Pokud bychom jej však chtěli vložit do HTML atributu, musíme ještě escapov
``` -Vnořeným kontextem ale nemusí být jen JS nebo CSS. Běžně jím je také URL. Parametry v URL se escapují tak, že se znaky se speciálním významen převádějí na sekvence začínající `%`. Příklad: +Vnořeným kontextem ale nemusí být jen JS nebo CSS. Běžně jím je také URL. Parametry v URL se escapují tak, že se znaky se speciálním významem převádějí na sekvence začínající `%`. Příklad: ``` https://example.org/?a=Jazz&b=Rock%27n%27Roll ``` -A když tento řetězec vypíšeme v atributu, ještě aplikujeme escapování podle tohoto kontextu a nahradíme `&` za `&`: +A když tento řetězec vypíšeme v atributu, ještě aplikujeme escapování podle tohoto kontextu a nahradíme `&` za `&`: ```html @@ -192,13 +191,13 @@ Pokud jste dočetli až sem, gratulujeme, bylo to vyčerpávající. Teď už m Latte vs naivní systémy ======================= -Ukázali jsem si, jak se správně escapuje v HTML dokumentu a jak zásadní je znalost kontextu, tedy místa, kde data vypisujeme. Jinými slovy, jak funguje kontextově sensitvní escapování. -Ačkoliv jde o nezbytný předpoklad funkční obrany před XSS, **Latte je jediný šablonovací systém pro PHP, který tohle umí.** +Ukázali jsme si, jak se správně escapuje v HTML dokumentu a jak zásadní je znalost kontextu, tedy místa, kde data vypisujeme. Jinými slovy, jak funguje kontextově sensitivní escapování. +Ačkoliv jde o nezbytný předpoklad funkční obrany před XSS, **Latte je jediný šablonovací systém pro PHP, který tohle umí**. Jak je to možné, když všechny systémy dnes tvrdí, že mají automatické escapování? -Automatické escapování bez znalosti kontextu je trošku bullshit, který **vytváří falešný dojem bezpečí**. +Automatické escapování bez znalosti kontextu je poněkud zavádějící a **vytváří falešný dojem bezpečí**. -Šablonovací systémy, jako je Twig, Laravel Blade a další, nevidí v šabloně žádnou HTML strukturu. Nevidí tudíž ani kontexty. Oproti Latte jsou slepé a naivní. Zpracovávají jen vlastní značky, vše ostatní je pro ně nepodstatný tok znaků: +Šablonovací systémy jako Twig, Laravel Blade a další nevidí v šabloně žádnou HTMLstrukturu. Nevidí tudíž ani kontexty. Oproti Latte jsou slepé a naivní. Zpracovávají jen vlastní značky, vše ostatní je pro ně nepodstatný tok znaků:
@@ -230,7 +229,7 @@ Automatické escapování bez znalosti kontextu je trošku bullshit, který **vy
-Naivní systémy jen mechanicky převádějí znaky `< > & ' "` na HTML entity, což je sice ve většině případů užití platný způsob escapování, ale zdaleka ne vždy. Nemohou tak odhalit ani předejít vzniku různých bezpečnostní děr, jak si ukážeme dále. +Naivní systémy pouze mechanicky převádějí znaky `< > & ' "` na HTML entity, což je sice ve většině případů platný způsob escapování, ale zdaleka ne vždy. Nemohou tak odhalit ani předejít vzniku různých bezpečnostních děr, jak si ukážeme dále. Latte šablonu vidí stejně jako vy. Chápe HTML, XML, rozeznává značky, atributy atd. A díky tomu rozlišuje jednotlivé kontexty a podle nich ošetřuje data. Nabízí tak opravdu efektivní ochranu proti kritické zranitelnosti Cross-site Scripting. @@ -270,63 +269,60 @@ Vlevo vidíte šablonu v Latte, vpravo je vygenerovaný HTML kód. Několikrát
-Není to skvělé! Latte dělá kontextově sensitivní escapování automaticky, takže programátor: +Není to skvělé! Latte provádí kontextově sensitivní escapování automaticky, takže programátor: - nemusí přemýšlet ani vědět, jak se kde escapuje - nemůže se splést - nemůže na escapování zapomenout -Tohle dokonce nejsou všechny kontexty, které Latte při vypisování rozlišuje a pro které přizpůsobuje ošetření dat. Další zajimavé případy si projdeme nyní. +Tohle dokonce nejsou všechny kontexty, které Latte při vypisování rozlišuje a pro které přizpůsobuje ošetření dat. Další zajímavé případy si projdeme nyní. Jak hacknout naivní systémy =========================== -Na několika praktických příkladech si ukážeme, jak je rozlišování kontextů důležité a proč naivní šablonovací systémy neposkytují dostatečnou ochranu před XSS, na rozdíl od Latte. -Jako zástupce naivního systému použijeme v ukázkách Twig, ale totéž platí i pro ostatní systémy. +Nyní si na praktických příkladech ukážeme, proč je rozlišování kontextů tak důležité a proč naivní šablonovací systémy neposkytují dostatečnou ochranu před XSS, na rozdíl od Latte. +V ukázkách použijeme Twig jako zástupce naivních systémů, ale podobné principy platí i pro ostatní systémy. -Zranitelnost atributem ----------------------- +Zranitelnost pomocí atributu +---------------------------- -Pokusíme se do stránky injektovat škodlivý kód pomocí HTML atributu, jak jsme si [ukazovali výše|#Jak zranitelnost vzniká]. Mějme šablonu v Twigu vykreslující obrázek: +Pokusme se injektovat škodlivý kód do stránky pomocí HTML atributu. Představme si šablonu v Twigu pro vykreslení obrázku: ```twig .{file:Twig} {{ ``` -Všimněte si, že okolo hodnot atributů nejsou uvozovky. Kodér na ně mohl zapomenout, což se prostě stává. Například v Reactu se kód píše takto, bez uvozovek, a kodér, který střídá jazyky, pak na uvozovky může snadno zapomenout. +Všimněte si chybějících uvozovek kolem hodnot atributů. Takové opomenutí se může snadno stát, zejména když vývojář střídá různé technologie (např. v Reactu se atributy píší bez uvozovek). -Útočník jako popisek obrázku vloží šikovně sestavený řetězec `foo onload=alert('Hacked!')`. Už víme, že Twig nemůže poznat, jestli se proměnná vypisuje v toku HTML textu, uvnitř atributu, HTML komentáře, atd., zkrátka nerozlišuje kontexty. A jen mechanicky převádí znaky `< > & ' "` na HTML entity. -Takže výsledný kód bude vypadat takto: +Útočník by mohl jako popisek obrázku vložit řetězec `foo onload=alert('Hacked!')`. Twig nedokáže rozpoznat kontext, ve kterém se proměnná vypisuje, a pouze mechanicky převede znaky `< > & ' "` na HTML entity. Výsledný kód bude vypadat takto: ```html foo ``` -**A vznikla bezpečností díra!** +**Vznikla bezpečnostní díra!** Do stránky se dostal podvržený atribut `onload`, který prohlížeč spustí ihned po načtení obrázku. -Součástí stránky se stal podvržený atribut `onload` a prohlížeč ihned po stažení obrázku jej spustí. - -Nyní se podíváme, jak si se stejnou šablonou poradí Latte: +Srovnejme to s Latte: ```latte .{file:Latte} {$imageAlt} ``` -Latte vidí šablonu stejně jako vy. Na rozdíl od Twigu chápe HTML a ví, že proměnná se vypisuje jako hodnota atributu, který není v uvozovkách. Proto je doplní. Když útočník vloží stejný popisek, výsledný kód bude vypadat takto: +Latte chápe strukturu HTML a rozpozná, že proměnná se vypisuje jako hodnota atributu bez uvozovek. Proto je automaticky doplní. I když útočník vloží stejný škodlivý řetězec, výsledek bude bezpečný: ```html foo onload=alert('Hacked!') ``` -**Latte úspěšně zabránilo XSS.** +**Latte úspěšně odvrátilo XSS útok.** -Vypsání proměnné v JavaScript ------------------------------ +Bezpečné použití proměnných v JavaScriptu +----------------------------------------- -Díky kontextově sensitivnímu escapování je možné zcela nativně používat PHP proměnné uvnitř JavaScriptu. +Díky kontextově citlivému escapování můžete v Latte bezpečně používat PHP proměnné přímo v JavaScriptu: ```latte

{$movie}

@@ -334,7 +330,7 @@ Díky kontextově sensitivnímu escapování je možné zcela nativně používa ``` -Pokud bude proměnná `$movie` obsahovat řetězec `'Amarcord & 8 1/2'`, vygeneruje se následující výstup. Všimněte si, že uvnitř HTML se použije jiné escapování, než uvnitř JavaScriptu a ještě jiné v atributu `onclick`: +Pokud `$movie` obsahuje řetězec `'Amarcord & 8 1/2'`, Latte vygeneruje následující kód: ```latte

Amarcord & 8 1/2

@@ -342,11 +338,13 @@ Pokud bude proměnná `$movie` obsahovat řetězec `'Amarcord & 8 1/2'`, vygener ``` +Všimněte si, jak Latte použilo různé metody escapování pro HTML text, JavaScript v atributu `onclick` a JavaScript uvnitř tagu ` ``` -To je také důvod, proč se kolem proměnné **nepíší uvozovky**: Latte je u řetězců doplní samo. A pokud byste chtěli řetězcovou proměnnou vložit do jiného řetězce, jednoduše je spojte: +To je také důvod, proč se kolem proměnné **nepíší uvozovky**: Latte je u řetězců doplní samo. Pokud chcete řetězcovou proměnnou vložit do jiného řetězce, jednoduše je spojte: ```latte ``` -Latte lze velmi pohodlně používat i uvnitř JavaScriptu, jen se stačí vynout konstrukcím jako v tomto příkladě, kdy následuje písmeno hned za `{`, viz [Latte uvnitř JavaScriptu nebo CSS|recipes#Latte uvnitř JavaScriptu nebo CSS]. +Latte lze velmi pohodlně používat i uvnitř JavaScriptu, jen se stačí vyhnout konstrukcím jako v tomto příkladě, kdy následuje písmeno hned za `{`, viz [Latte uvnitř JavaScriptu nebo CSS|recipes#Latte uvnitř JavaScriptu nebo CSS]. -Pokud Latte vypnete pomocí `{syntax off}` (tj. značkou, nikoliv n:atributem), bude důsledně ignorovat všechny značky až do `{/syntax}` +Pokud Latte vypnete pomocí `{syntax off}` (tj. značkou, nikoliv n:atributem), bude důsledně ignorovat všechny značky až do `{/syntax}`. {trace} @@ -941,7 +938,7 @@ n:class Díky `n:class` velice snadno vygenerujete HTML atribut `class` přesně podle představ. -Příklad: potřebuji, aby aktivní prvek měl třídu `active`: +Příklad: potřebujeme, aby aktivní prvek měl třídu `active`: ```latte {foreach $items as $item} @@ -971,7 +968,7 @@ A všechny prvky mají mít třídu `list-item`: n:attr ------ -Atribut `n:attr` umí se stejnou elegancí jako má [n:class|#n:class] generovat libovolné HTML atributy. +Atribut `n:attr` umí se stejnou elegancí jako [n:class|#n:class] generovat libovolné HTML atributy. ```latte {foreach $data as $item} diff --git a/latte/cs/template-inheritance.texy b/latte/cs/template-inheritance.texy index ab6e030bdb..6c62b34f1c 100644 --- a/latte/cs/template-inheritance.texy +++ b/latte/cs/template-inheritance.texy @@ -2,15 +2,15 @@ Dědičnost a znovupoužitelnost šablon ************************************ .[perex] -Mechanismy opětovného použití a dědičnosti šablon zvýší vaši produktivitu, protože každá šablona obsahuje pouze svůj jedinečný obsah a opakované prvky a struktury se znovupoužijí. Představujeme tři koncepty: [#layoutová dědičnost], [#horizontální znovupoužití] a [#jednotková dědičnost]. +Mechanismy dědičnosti a znovupoužitelnosti šablon v Latte významně zvyšují produktivitu vývojářů. Každá šablona tak může obsahovat pouze svůj jedinečný obsah, zatímco opakující se prvky a struktury se efektivně znovupoužívají. V této kapitole představíme tři klíčové koncepty: [layoutovou dědičnost|#layoutová dědičnost], [#horizontální znovupoužití] a [jednotkovou dědičnost|#jednotková dědičnost]. -Koncept dědičnosti šablon Latte je podobný dědičnosti tříd v PHP. Definujete **nadřazenou šablonu**, od které mohou dědit další **podřízené šablony** a mohou přepsat části nadřazené šablony. Funguje to skvěle, když prvky sdílejí společnou strukturu. Zní to komplikovaně? Nebojte se, je to velmi snadné. +Koncept dědičnosti šablon v Latte je analogický k dědičnosti tříd v PHP. Definujete **nadřazenou šablonu**, od které mohou další **podřízené šablony** dědit a případně přepisovat její části. Tento přístup je zvláště účinný, když různé prvky sdílejí společnou strukturu. Ačkoli to může znít složitě, v praxi jde o velmi intuitivní a snadno použitelný systém. Layoutová dědičnost `{layout}` .{toc:Layoutová dědičnost} ========================================================= -Podívejme se na dědičnost šablony rozložení, tedy layoutu, rovnou příkladem. Toto je nadřazená šablona, kterou budeme nazývat například `layout.latte` a která definuje kostru HTML dokumentu: +Podívejme se na layoutovou dědičnost na konkrétním příkladu. Následující ukázka představuje nadřazenou šablonu, kterou můžeme nazvat například `layout.latte`. Tato šablona definuje základní kostru HTML dokumentu: ```latte @@ -30,36 +30,36 @@ Podívejme se na dědičnost šablony rozložení, tedy layoutu, rovnou příkla ``` -Značky `{block}` definují tři bloky, které mohou podřízené šablony vyplnit. Značka block dělá jen to, že oznámí, že toto místo může podřízená šablona přepsat definováním vlastního bloku se stejným názvem. +Značky `{block}` zde vymezují tři bloky, které mohou podřízené šablony naplnit vlastním obsahem. Blok v tomto kontextu jednoduše označuje místo, které může podřízená šablona přepsat definováním vlastního bloku se stejným názvem. -Podřízená šablona může vypadat takto: +Podřízená šablona pak může vypadat například takto: ```latte {layout 'layout.latte'} -{block title}My amazing blog{/block} +{block title}Můj úžasný blog{/block} {block content} -

Welcome to my awesome homepage.

+

Vítejte na mé skvělé domovské stránce.

{/block} ``` -Klíčem je zde značka `{layout}`. Říká Latte, že tato šablona „rozšiřuje“ další šablonu. Když Latte vykresluje tuto šablonu, nejprve najde nadřazenou šablonu - v tomto případě `layout.latte`. +Klíčovým prvkem je zde značka `{layout}`. Ta Latte sděluje, že tato šablona "rozšiřuje" jinou šablonu. Při vykreslování této šablony Latte nejprve nalezne nadřazenou šablonu - v tomto případě `layout.latte`. -V tomto okamžiku si Latte všimne tří blokových značek v `layout.latte` a nahradí tyto bloky obsahem podřízené šablony. Vzhledem k tomu, že podřízená šablona nedefinovala blok *footer*, použije se místo toho obsah z nadřazené šablony. Obsah ve značce `{block}` v nadřazené šabloně se vždy používá jako záložní. +V tomto okamžiku Latte identifikuje tři blokové značky v `layout.latte` a nahradí tyto bloky obsahem z podřízené šablony. Vzhledem k tomu, že podřízená šablona nedefinovala blok *footer*, použije se pro tento blok obsah z nadřazené šablony. Obsah uvnitř značky `{block}` v nadřazené šabloně vždy slouží jako výchozí, pokud není přepsán. -Výstup může vypadat takto: +Výsledný výstup může vypadat následovně: ```latte - My amazing blog + Můj úžasný blog
-

Welcome to my awesome homepage.

+

Vítejte na mé skvělé domovské stránce.