diff --git a/ai/cs/@home.texy b/ai/cs/@home.texy new file mode 100644 index 0000000000..e2385cdf80 --- /dev/null +++ b/ai/cs/@home.texy @@ -0,0 +1,11 @@ +Nette AI +******** + +- [Introduction |guide] +- [Getting Started |getting-started] +- [MCP Inspector |mcp-inspector] +- [Claude Code |claude-code] +- [Tips & Best Practices |tips] + +{{maintitle: Nette AI – Vibe Coding with Nette Framework}} +{{description: Build Nette applications with AI assistance. MCP Inspector gives any AI tool deep knowledge of your application's DI container, database, routing, and errors. No hallucinations, just clean code.}} diff --git a/ai/cs/@meta.texy b/ai/cs/@meta.texy new file mode 100644 index 0000000000..e06cc9886c --- /dev/null +++ b/ai/cs/@meta.texy @@ -0,0 +1 @@ +{{sitename: Nette AI}} diff --git a/ai/en/@home.texy b/ai/en/@home.texy new file mode 100644 index 0000000000..e2385cdf80 --- /dev/null +++ b/ai/en/@home.texy @@ -0,0 +1,11 @@ +Nette AI +******** + +- [Introduction |guide] +- [Getting Started |getting-started] +- [MCP Inspector |mcp-inspector] +- [Claude Code |claude-code] +- [Tips & Best Practices |tips] + +{{maintitle: Nette AI – Vibe Coding with Nette Framework}} +{{description: Build Nette applications with AI assistance. MCP Inspector gives any AI tool deep knowledge of your application's DI container, database, routing, and errors. No hallucinations, just clean code.}} diff --git a/ai/en/@left-menu.texy b/ai/en/@left-menu.texy new file mode 100644 index 0000000000..54132f474a --- /dev/null +++ b/ai/en/@left-menu.texy @@ -0,0 +1,5 @@ +- [Introduction |guide] +- [Getting Started |getting-started] +- [MCP Inspector |mcp-inspector] +- [Claude Code |claude-code] +- [Tips & Best Practices |tips] diff --git a/ai/en/@meta.texy b/ai/en/@meta.texy new file mode 100644 index 0000000000..e06cc9886c --- /dev/null +++ b/ai/en/@meta.texy @@ -0,0 +1 @@ +{{sitename: Nette AI}} diff --git a/ai/en/claude-code.texy b/ai/en/claude-code.texy new file mode 100644 index 0000000000..f12fa5faf1 --- /dev/null +++ b/ai/en/claude-code.texy @@ -0,0 +1,251 @@ +Claude Code Plugin +****************** + +
Cena: {$price|money}
+ +{if isWeekend($now)} ... {/if} +``` + +Pro složitější logiku můžete konfigurovat přímo objekt `Latte\Engine`: + +```php +protected function beforeRender(): void +{ $latte = $this->template->getLatte(); - $latte->addFilterLoader(/* ... */); + $latte->setFeature(Latte\Feature::MigrationWarnings); +} +``` + +**Pomocí atributů** + +Elegantní způsob je definovat filtry a funkce jako metody přímo ve [třídě parametrů šablony|#Typově bezpečné šablony] presenteru nebo komponenty a označit je atributy: + +```php +class ArticleTemplate extends Nette\Bridges\ApplicationLatte\Template +{ + #[Latte\Attributes\TemplateFilter] + public function money(float $val): string + { + return round($val) . ' Kč'; + } + + #[Latte\Attributes\TemplateFunction] + public function isWeekend(DateTimeInterface $date): bool + { + return $date->format('N') >= 6; + } } ``` -Latte ve verzi 3 nabízí pokročilejší způsob a to vytvoření si [extension |latte:extending-latte#Latte Extension] pro každý webový projekt. Kusý příklad takové třídy: +Latte automaticky rozpozná a zaregistruje metody označené těmito atributy. Název filtru nebo funkce v šabloně odpovídá názvu metody. Tyto metody nesmí být privátní. + +**Globálně pomocí Extension** + +Předchozí způsoby jsou vhodné pro filtry a funkce, které potřebujete jen v konkrétním presenteru nebo komponentě, nikoliv v celé aplikaci. Pro celou aplikaci je nejvhodnější vytvořit si [extension |latte:extending-latte#Latte Extension]. Jde o třídu, která centralizuje všechna rozšíření Latte pro celý projekt. Kusý příklad: ```php namespace App\Presentation\Accessory; @@ -251,11 +315,16 @@ final class LatteExtension extends Latte\Extension ]; } + private function filterTimeAgoInWords(DateTimeInterface $time): string + { + // ... + } + // ... } ``` -Zaregistrujeme ji pomocí [konfigurace |configuration#Šablony Latte]: +Extension zaregistrujeme pomocí [konfigurace |configuration#Šablony Latte]: ```neon latte: @@ -263,6 +332,8 @@ latte: - App\Presentation\Accessory\LatteExtension ``` +Výhodou extension je, že lze využít dependency injection, mít přístup k modelové vrstvě aplikace a všechna rozšíření mít přehledně na jednom místě. Extension umožnuje definovat i vlastní značky, providery, průchody pro Latte kompilátor a další. + Překládání ---------- diff --git a/application/de/routing.texy b/application/de/routing.texy index 251247119d..ff2f7378e0 100644 --- a/application/de/routing.texy +++ b/application/de/routing.texy @@ -314,7 +314,7 @@ use Nette\Routing\Route; $router->addRoute('Price: {$price|money}
+ +{if isWeekend($now)} ... {/if} +``` + +For more complex logic, you can configure the `Latte\Engine` object directly: + +```php +protected function beforeRender(): void +{ $latte = $this->template->getLatte(); - $latte->addFilterLoader(/* ... */); + $latte->setFeature(Latte\Feature::MigrationWarnings); +} +``` + +**Using Attributes** + +A more elegant approach is defining filters and functions as methods directly in the presenter or component's [template parameter class|#Type-safe templates], marked with attributes: + +```php +class ArticleTemplate extends Nette\Bridges\ApplicationLatte\Template +{ + #[Latte\Attributes\TemplateFilter] + public function money(float $val): string + { + return '$' . number_format($val, 2); + } + + #[Latte\Attributes\TemplateFunction] + public function isWeekend(DateTimeInterface $date): bool + { + return $date->format('N') >= 6; + } } ``` -Latte version 3 offers a more advanced way by creating an [extension |latte:extending-latte#Latte Extension] for each web project. Here is a brief example of such a class: +Latte automatically discovers and registers methods marked with these attributes. The filter or function name in templates matches the method name. These methods must not be private. + +**Globally Using Extensions** + +The previous approaches suit filters and functions needed only in specific presenters or components, not application-wide. For the entire application, creating an [extension |latte:extending-latte#Latte Extension] works best. This class centralizes all Latte extensions for your project. A brief example: ```php namespace App\Presentation\Accessory; @@ -251,11 +315,16 @@ final class LatteExtension extends Latte\Extension ]; } + private function filterTimeAgoInWords(DateTimeInterface $time): string + { + // ... + } + // ... } ``` -We register it using [configuration |configuration#Latte Templates]: +Register the extension through [configuration |configuration#Latte Templates]: ```neon latte: @@ -263,6 +332,8 @@ latte: - App\Presentation\Accessory\LatteExtension ``` +Extensions offer several advantages: dependency injection support, access to your application's model layer, and centralized management of all extensions. They also support custom tags, providers, compiler passes, and more. + Translating ----------- diff --git a/application/es/routing.texy b/application/es/routing.texy index 829edb3c7d..d906f83f48 100644 --- a/application/es/routing.texy +++ b/application/es/routing.texy @@ -314,7 +314,7 @@ use Nette\Routing\Route; $router->addRoute('Резултати от търсенето за ' . $search . 'alert("Hacked!")`. Тъй като изходът не е обработен по никакъв начин, той става част от показаната страница: -```html +```latte
Резултати от търсенето за
``` @@ -59,7 +59,7 @@ echo '
```
@@ -91,7 +91,7 @@ echo '#текст
```
@@ -330,7 +330,7 @@ Latte вижда шаблона по същия начин като вас. Ра
Latte вижда шаблона по същия начин като вас. За разлика от Twig, разбира HTML и знае, че променливата се извежда като стойност на атрибут, който не е в кавички. Затова ги допълва. Когато нападателят вмъкне същото описание, резултатният код ще изглежда така:
-```html
+```latte
```
diff --git a/latte/bg/type-system.texy b/latte/bg/type-system.texy
index 8f052cf074..aa1be010a5 100644
--- a/latte/bg/type-system.texy
+++ b/latte/bg/type-system.texy
@@ -21,7 +21,7 @@
class CatalogTemplateParameters
{
public function __construct(
- public string $langs,
+ public string $lang,
/** @var ProductEntity[] */
public array $products,
public Address $address,
@@ -35,7 +35,7 @@ $latte->render('template.latte', new CatalogTemplateParameters(
));
```
-След това в началото на шаблона поставете тага `{templateType}` с пълното име на класа (включително namespace). Това дефинира, че в шаблона има променливи `$langs` и `$products`, включително съответните типове. Типовете на локалните променливи можете да посочите с помощта на таговете [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Дефиниции].
+След това в началото на шаблона поставете тага `{templateType}` с пълното име на класа (включително namespace). Това дефинира, че в шаблона има променливи `$lang` и `$products`, включително съответните типове. Типовете на локалните променливи можете да посочите с помощта на таговете [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Дефиниции].
От този момент IDE може да ви подсказва правилно.
diff --git a/latte/cs/@left-menu.texy b/latte/cs/@left-menu.texy
index 31a85bcaf7..4556b26913 100644
--- a/latte/cs/@left-menu.texy
+++ b/latte/cs/@left-menu.texy
@@ -5,6 +5,7 @@
- [Dědičnost šablon |Template Inheritance]
- [Typový systém |type-system]
- [Sandbox]
+ - [HTML attributy |html-attributes]
- Pro designéry 🎨
- [Syntaxe |syntax]
diff --git a/latte/cs/cookbook/@home.texy b/latte/cs/cookbook/@home.texy
index b4d54b0b7e..b6af15e673 100644
--- a/latte/cs/cookbook/@home.texy
+++ b/latte/cs/cookbook/@home.texy
@@ -8,6 +8,7 @@ Příklady kódů a receptů pro provádění běžných úkolů pomocí Latte.
- [Předávání proměnných napříč šablonami |passing-variables]
- [Všechno, co jste kdy chtěli vědět o seskupování |grouping]
- [Jak psát SQL queries v Latte? |how-to-write-sql-queries-in-latte]
+- [Migrace z Latte 3.0 |migration-from-latte-30]
- [Migrace z Latte 2 |migration-from-latte2]
- [Migrace z PHP |migration-from-php]
- [Migrace z Twigu |migration-from-twig]
diff --git a/latte/cs/cookbook/migration-from-latte-30.texy b/latte/cs/cookbook/migration-from-latte-30.texy
new file mode 100644
index 0000000000..03211a226d
--- /dev/null
+++ b/latte/cs/cookbook/migration-from-latte-30.texy
@@ -0,0 +1,109 @@
+Migrace z Latte 3.0
+*******************
+
+.[perex]
+Latte 3.1 přináší několik vylepšení a změn, díky kterým je psaní šablon bezpečnější a pohodlnější. Většina změn je zpětně kompatibilní, ale některé vyžadují pozornost při přechodu. Tento průvodce shrnuje BC breaky a jak je řešit.
+
+Latte 3.1 vyžaduje **PHP 8.2** nebo novější.
+
+
+Chytré atributy a migrace
+=========================
+
+Nejvýznamnější změnou v Latte 3.1 je nové chování [chytrých atributů |/html-attributes]. To ovlivňuje, jak se vykreslují hodnoty `null` a logické hodnoty v `data-` atributech.
+
+1. **Hodnoty `null`:** Dříve se `title={$null}` vykresloval jako `title=""`. Nyní se atribut zcela vynechá.
+2. **`data-` atributy:** Dříve se `data-foo={=true}` / `data-foo={=false}` vykreslovaly jako `data-foo="1"` / `data-foo=""`. Nyní se vykreslují jako `data-foo="true"` / `data-foo="false"`.
+
+Abychom vám pomohli identifikovat místa, kde se výstup ve vaší aplikaci změnil, Latte poskytuje migrační nástroj.
+
+
+Migrační varování
+-----------------
+
+Můžete zapnout [migrační varování |/develop#Migrační varování], která vás během vykreslování upozorní, pokud se výstup liší od Latte 3.0.
+
+```php
+$latte = new Latte\Engine;
+$latte->setFeature(Latte\Feature::MigrationWarnings);
+```
+
+Pokud jsou povolena, sledujte logy aplikace nebo Tracy bar pro `E_USER_WARNING`. Každé varování bude ukazovat na konkrétní řádek a sloupec v šabloně.
+
+**Jak varování vyřešit:**
+
+Pokud je nové chování správné (např. chcete, aby prázdný atribut zmizel), potvrďte jej použitím filtru `|accept` pro potlačení varování:
+
+```latte
+
+```
+
+Pokud chcete atribut zachovat jako prázdný (např. `title=""`) místo jeho vynechání, použijte null coalescing operátor:
+
+```latte
+
+```
+
+Nebo, pokud striktně vyžadujete staré chování (např. `"1"` pro `true`), explicitně přetypujte hodnotu na string:
+
+```latte
+
+```
+
+**Poté, co vyřešíte všechna varování:**
+
+Jakmile vyřešíte všechna varování, vypněte migrační varování a **odstraňte všechny** filtry `|accept` ze svých šablon, protože již nejsou potřeba.
+
+
+Strict Types
+============
+
+Latte 3.1 zapíná `declare(strict_types=1)` ve výchozím nastavení pro všechny kompilované šablony. To zlepšuje typovou bezpečnost, ale může způsobit typové chyby v PHP výrazech uvnitř šablon, pokud jste spoléhali na volné typování.
+
+Pokud typy nemůžete opravit okamžitě, můžete toto chování vypnout:
+
+```php
+$latte->setFeature(Latte\Feature::StrictTypes, false);
+```
+
+
+Globální konstanty
+==================
+
+Parser šablon byl vylepšen, aby lépe rozlišoval mezi jednoduchými řetězci a konstantami. V důsledku toho musí být globální konstanty nyní prefixovány zpětným lomítkem `\`.
+
+```latte
+{* Starý způsob (vyhodí varování, v budoucnu bude interpretováno jako string 'PHP_VERSION') *}
+{if PHP_VERSION > ...}
+
+{* Nový způsob (správně interpretováno jako konstanta) *}
+{if \PHP_VERSION > ...}
+```
+
+Tato změna předchází nejednoznačnostem a umožňuje volnější používání neuvodzovkovaných řetězců.
+
+
+Odstraněné funkce
+=================
+
+**Rezervované proměnné:** Proměnné začínající na `$__` (dvou podtržítko) a proměnná `$this` jsou nyní vyhrazeny pro vnitřní použití Latte. Nemůžete je používat v šablonách.
+
+**Undefined-safe operátor:** Operátor `??->`, což byla specifická funkce Latte vytvořená před PHP 8, byl odstraněn. Jde o historický relikt. Používejte prosím standardní PHP nullsafe operátor `?->`.
+
+**Filter Loader**
+Metoda `Engine::addFilterLoader()` byla označena jako zastaralá a odstraněna. Šlo o nekonzistentní koncept, který se jinde v Latte nevyskytoval.
+
+**Date Format**
+Statická vlastnost `Latte\Runtime\Filters::$dateFormat` byla odstraněna, aby se předešlo globálnímu stavu.
+
+
+Nové funkce
+===========
+
+Během migrace si můžete začít užívat nové funkce:
+
+- **Chytré HTML atributy:** Předávání polí do `class` a `style`, automatické vynechání `null` atributů.
+- **Nullsafe filtry:** Použijte `{$var?|filter}` pro přeskočení filtrování null hodnot.
+- **`n:elseif`:** Nyní můžete používat `n:elseif` společně s `n:if` a `n:else`.
+- **Zjednodušená syntaxe:** Pište `Výsledky vyhledávání pro ' . $search . '
'; Útočník může do vyhledávacího políčka a potažmo do proměnné `$search` zapsat libovolný řetězec, tedy i HTML kód jako ``. Protože výstup není nijak ošetřen, stane se součástí zobrazené stránky: -```html +```latteVýsledky vyhledávání pro
``` @@ -59,7 +59,7 @@ echo '
```
@@ -91,7 +91,7 @@ Kontextově sensitivní escapování
Co se přesně myslí slovem kontext? Jde o místo v dokumentu s vlastními pravidly pro ošetřování vypisovaných dat. Odvíjí se od typu dokumentu (HTML, XML, CSS, JavaScript, plain text, ...) a může se lišit v jeho konkrétních částech. Například v HTML dokumentu je takových míst (kontextů), kde platí velmi odlišná pravidla, celá řada. Možná budete překvapeni, kolik jich je. Tady máme první čtveřici:
-```html
+```latte
#text
```
@@ -330,7 +330,7 @@ Nyní se podíváme, jak si se stejnou šablonou poradí Latte:
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:
-```html
+```latte
```
diff --git a/latte/cs/syntax.texy b/latte/cs/syntax.texy
index 0913d20fc7..39f1c621de 100644
--- a/latte/cs/syntax.texy
+++ b/latte/cs/syntax.texy
@@ -111,6 +111,34 @@ Což vypíše v závislosti na proměnné `$url`:
Avšak n:atributy nejsou jen zkratkou pro párové značky. Existují i ryzí n:atributy, jako třeba [n:href |application:creating-links#V šabloně presenteru] nebo velešikovný pomocník kodéra [n:class |tags#n:class].
+Kromě syntaxe s uvozovkami `Suchergebnisse für ' . $search . '
'; Ein Angreifer kann in das Suchfeld und somit in die Variable `$search` eine beliebige Zeichenkette eingeben, also auch HTML-Code wie ``. Da die Ausgabe nicht bereinigt wird, wird sie Teil der angezeigten Seite: -```html +```latteSuchergebnisse für
``` @@ -59,7 +59,7 @@ echo '
```
@@ -91,7 +91,7 @@ Kontextsensitives Escaping
Was genau ist mit dem Wort Kontext gemeint? Es handelt sich um eine Stelle im Dokument mit eigenen Regeln für die Bereinigung ausgegebener Daten. Sie hängt vom Dokumenttyp ab (HTML, XML, CSS, JavaScript, Plain Text, ...) und kann sich in seinen spezifischen Teilen unterscheiden. Beispielsweise gibt es in einem HTML-Dokument eine ganze Reihe solcher Stellen (Kontexte), an denen sehr unterschiedliche Regeln gelten. Vielleicht werden Sie überrascht sein, wie viele es sind. Hier sind die ersten vier:
-```html
+```latte
#text
```
@@ -330,7 +330,7 @@ Sehen wir uns nun an, wie Latte mit demselben Template umgeht:
Latte sieht das Template genauso wie Sie. Im Gegensatz zu Twig versteht es HTML und weiß, dass die Variable als Wert eines Attributs ausgegeben wird, das nicht in Anführungszeichen steht. Deshalb ergänzt es sie. Wenn ein Angreifer dieselbe Beschreibung einfügt, sieht der resultierende Code so aus:
-```html
+```latte
```
diff --git a/latte/de/type-system.texy b/latte/de/type-system.texy
index 88beabecd4..f8994c6ef0 100644
--- a/latte/de/type-system.texy
+++ b/latte/de/type-system.texy
@@ -21,7 +21,7 @@ Wie beginnt man mit der Verwendung von Typen? Erstellen Sie eine Template-Klasse
class CatalogTemplateParameters
{
public function __construct(
- public string $langs,
+ public string $lang,
/** @var ProductEntity[] */
public array $products,
public Address $address,
@@ -35,7 +35,7 @@ $latte->render('template.latte', new CatalogTemplateParameters(
));
```
-Fügen Sie dann am Anfang des Templates das Tag `{templateType}` mit dem vollständigen Klassennamen (einschließlich Namespace) ein. Dies definiert, dass im Template die Variablen `$langs` und `$products` einschließlich der entsprechenden Typen vorhanden sind. Die Typen lokaler Variablen können Sie mit den Tags [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Definition] angeben.
+Fügen Sie dann am Anfang des Templates das Tag `{templateType}` mit dem vollständigen Klassennamen (einschließlich Namespace) ein. Dies definiert, dass im Template die Variablen `$lang` und `$products` einschließlich der entsprechenden Typen vorhanden sind. Die Typen lokaler Variablen können Sie mit den Tags [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Definition] angeben.
Von diesem Moment an kann Ihnen die IDE korrekt Vorschläge machen.
diff --git a/latte/el/custom-tags.texy b/latte/el/custom-tags.texy
index cf69c32588..3c041dd29d 100644
--- a/latte/el/custom-tags.texy
+++ b/latte/el/custom-tags.texy
@@ -923,7 +923,7 @@ class MyLatteExtension extends Extension
Παραγόμενο HTML:
-```html
+```latte
Διαγραφή
```
diff --git a/latte/el/safety-first.texy b/latte/el/safety-first.texy
index bb4b7c09d7..65985510ef 100644
--- a/latte/el/safety-first.texy
+++ b/latte/el/safety-first.texy
@@ -33,7 +33,7 @@ echo 'Αποτελέσματα αναζήτησης για ' . $search .
Ένας εισβολέας μπορεί να γράψει στο πεδίο αναζήτησης και κατ' επέκταση στη μεταβλητή `$search` οποιοδήποτε string, δηλαδή και κώδικα HTML όπως ``. Επειδή η έξοδος δεν επεξεργάζεται με κανέναν τρόπο, γίνεται μέρος της εμφανιζόμενης σελίδας:
-```html
+```latte
Αποτελέσματα αναζήτησης για #κείμενο Search results for ' . $search . ' Search results for #text Resultados de la búsqueda para ' . $search . ' Resultados de la búsqueda para #texto Résultats de la recherche pour ' . $search . ' Résultats de la recherche pour #texte Keresési eredmények erre: ' . $search . ' Keresési eredmények erre: #szöveg';
Αρκεί ο εισβολέας να εισάγει ως λεζάντα ένα έξυπνα κατασκευασμένο string `" onload="alert('Hacked!')` και αν η εκτύπωση δεν επεξεργαστεί, ο προκύπτων κώδικας θα μοιάζει ως εξής:
-```html
+```latte
```
@@ -91,7 +91,7 @@ Context-Aware Escaping
Τι ακριβώς εννοούμε με τη λέξη context; Πρόκειται για ένα μέρος στο έγγραφο με τους δικούς του κανόνες για την επεξεργασία των εκτυπωμένων δεδομένων. Εξαρτάται από τον τύπο του εγγράφου (HTML, XML, CSS, JavaScript, plain text, ...) και μπορεί να διαφέρει σε συγκεκριμένα μέρη του. Για παράδειγμα, σε ένα έγγραφο HTML, υπάρχουν πολλά τέτοια μέρη (contexts) όπου ισχύουν πολύ διαφορετικοί κανόνες. Ίσως εκπλαγείτε πόσα είναι. Εδώ έχουμε την πρώτη τετράδα:
-```html
+```latte
@@ -108,7 +108,7 @@ Context-Aware Escaping
Τα contexts μπορούν επίσης να στρωματοποιηθούν, κάτι που συμβαίνει όταν ενσωματώνουμε JavaScript ή CSS σε HTML. Αυτό μπορεί να γίνει με δύο διαφορετικούς τρόπους, με στοιχείο και με attribute:
-```html
+```latte
@@ -132,7 +132,7 @@ Context-Aware Escaping
Αν το εκτυπώσετε σε κείμενο HTML, σε αυτή τη συγκεκριμένη περίπτωση δεν χρειάζεται να κάνετε καμία αντικατάσταση, επειδή το string δεν περιέχει κανέναν χαρακτήρα με ειδική σημασία. Η κατάσταση αλλάζει αν το εκτυπώσετε μέσα σε ένα attribute HTML που περικλείεται σε απλά εισαγωγικά. Σε αυτή την περίπτωση, πρέπει να κάνετε escape τα εισαγωγικά σε οντότητες HTML:
-```html
+```latte
```
@@ -152,13 +152,13 @@ alert('Rock\'n\'Roll');
Αν εισάγουμε αυτόν τον κώδικα σε ένα έγγραφο HTML χρησιμοποιώντας το ` alert('Rock\'n\'Roll');
```
Αν όμως θέλαμε να το εισάγουμε σε ένα attribute HTML, πρέπει ακόμα να κάνουμε escape τα εισαγωγικά σε οντότητες HTML:
-```html
+```latte
```
@@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll
Και όταν εκτυπώνουμε αυτό το string σε ένα attribute, εφαρμόζουμε επιπλέον το escaping σύμφωνα με αυτό το context και αντικαθιστούμε το `&` με `&`:
-```html
+```latte
```
@@ -314,7 +314,7 @@ Latte εναντίον απλοϊκών συστημάτων
Ένας εισβολέας εισάγει ως λεζάντα της εικόνας ένα έξυπνα κατασκευασμένο string `foo onload=alert('Hacked!')`. Γνωρίζουμε ήδη ότι το Twig δεν μπορεί να αναγνωρίσει αν η μεταβλητή εκτυπώνεται στη ροή του κειμένου HTML, μέσα σε ένα attribute, σε ένα σχόλιο HTML κ.λπ., με λίγα λόγια δεν διακρίνει τα contexts. Και απλώς μετατρέπει μηχανικά τους χαρακτήρες `< > & ' "` σε οντότητες HTML. Έτσι, ο προκύπτων κώδικας θα μοιάζει ως εξής:
-```html
+```latte
```
@@ -330,7 +330,7 @@ Latte εναντίον απλοϊκών συστημάτων
Το Latte βλέπει το πρότυπο όπως εσείς. Σε αντίθεση με το Twig, καταλαβαίνει HTML και ξέρει ότι η μεταβλητή εκτυπώνεται ως τιμή ενός attribute που δεν βρίσκεται σε εισαγωγικά. Γι' αυτό τα συμπληρώνει. Όταν ο εισβολέας εισάγει την ίδια λεζάντα, ο προκύπτων κώδικας θα μοιάζει ως εξής:
-```html
+```latte
```
diff --git a/latte/el/type-system.texy b/latte/el/type-system.texy
index 91b4f29239..26dff347f3 100644
--- a/latte/el/type-system.texy
+++ b/latte/el/type-system.texy
@@ -21,7 +21,7 @@
class CatalogTemplateParameters
{
public function __construct(
- public string $langs,
+ public string $lang,
/** @var ProductEntity[] */
public array $products,
public Address $address,
@@ -35,7 +35,7 @@ $latte->render('template.latte', new CatalogTemplateParameters(
));
```
-Και στη συνέχεια, στην αρχή του προτύπου, εισαγάγετε το tag `{templateType}` με το πλήρες όνομα της κλάσης (συμπεριλαμβανομένου του namespace). Αυτό ορίζει ότι στο πρότυπο υπάρχουν οι μεταβλητές `$langs` και `$products` συμπεριλαμβανομένων των αντίστοιχων τύπων τους. Μπορείτε να δηλώσετε τους τύπους των τοπικών μεταβλητών χρησιμοποιώντας τα tags [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Ορισμοί define].
+Και στη συνέχεια, στην αρχή του προτύπου, εισαγάγετε το tag `{templateType}` με το πλήρες όνομα της κλάσης (συμπεριλαμβανομένου του namespace). Αυτό ορίζει ότι στο πρότυπο υπάρχουν οι μεταβλητές `$lang` και `$products` συμπεριλαμβανομένων των αντίστοιχων τύπων τους. Μπορείτε να δηλώσετε τους τύπους των τοπικών μεταβλητών χρησιμοποιώντας τα tags [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Ορισμοί define].
Από εκείνη τη στιγμή, το IDE σας μπορεί να παρέχει σωστή αυτόματη συμπλήρωση.
diff --git a/latte/en/@left-menu.texy b/latte/en/@left-menu.texy
index eebab75253..88fc173a96 100644
--- a/latte/en/@left-menu.texy
+++ b/latte/en/@left-menu.texy
@@ -5,6 +5,7 @@
- [Template Inheritance]
- [Type System]
- [Sandbox]
+ - [HTML attributes]
- For Designers 🎨
- [Syntax]
diff --git a/latte/en/cookbook/@home.texy b/latte/en/cookbook/@home.texy
index 7c2738769a..58b23d4136 100644
--- a/latte/en/cookbook/@home.texy
+++ b/latte/en/cookbook/@home.texy
@@ -8,6 +8,7 @@ Example codes and recipes for accomplishing common tasks with Latte.
- [Passing variables across templates |passing-variables]
- [Everything you always wanted to know about grouping |grouping]
- [How to write SQL queries in Latte? |how-to-write-sql-queries-in-latte]
+- [Migration from Latte 3.0 |migration-from-latte-30]
- [Migration from Latte 2 |migration-from-latte2]
- [Migration from PHP |migration-from-php]
- [Migration from Twig |migration-from-twig]
diff --git a/latte/en/cookbook/migration-from-latte-30.texy b/latte/en/cookbook/migration-from-latte-30.texy
new file mode 100644
index 0000000000..0c73bfce8f
--- /dev/null
+++ b/latte/en/cookbook/migration-from-latte-30.texy
@@ -0,0 +1,110 @@
+Migration from Latte 3.0
+************************
+
+.[perex]
+Latte 3.1 brings several improvements and changes that make templates safer and more convenient to write. Most changes are backward compatible, but some require attention during migration. This guide summarizes the breaking changes and how to handle them.
+
+Latte 3.1 requires **PHP 8.2** or newer.
+
+
+Smart Attributes and Migration
+==============================
+
+The most significant change in Latte 3.1 is the new behavior of [Smart Attributes |/html-attributes]. This affects how `null` values and boolean values in `data-` attributes are rendered.
+
+1. **`null` values:** Previously, `title={$null}` rendered as `title=""`. Now, the attribute is completely dropped.
+2. **`data-` attributes:** Previously, `data-foo={=true}` / `data-foo={=false}` rendered as `data-foo="1"` / `data-foo=""`. Now, it renders as `data-foo="true"` / `data-foo="false"`.
+
+To help you identify places where the output has changed in your application, Latte provides a migration tool.
+
+
+Migration Warnings
+------------------
+
+You can enable [migration warnings |/develop#Migration Warnings], which will warn you during rendering if the output differs from Latte 3.0.
+
+```php
+$latte = new Latte\Engine;
+$latte->setFeature(Latte\Feature::MigrationWarnings);
+```
+
+When enabled, check your application logs or Tracy bar for `E_USER_WARNING`s. Each warning will point to the specific line, and column in template.
+
+**How to resolve warnings:**
+
+If the new behavior is correct (e.g. you want the empty attribute to disappear), confirm it using the `|accept` filter to suppress the warning:
+
+```latte
+
+```
+
+If you want to keep the attribute as empty (e.g. `title=""`) instead of dropping it, use the null coalescing operator:
+
+```latte
+
+```
+
+Or, if you strictly require the old behavior (e.g. `"1"` for `true`), explicitly cast the value to string:
+
+```latte
+
+```
+
+**After you resolve all warnings:**
+
+Once all warnings are resolved, disable migration warnings and **remove all** `|accept` filters from your templates, as they are no longer needed.
+
+
+Strict Types
+============
+
+Latte 3.1 enables `declare(strict_types=1)` by default for all compiled templates. This improves type safety but might cause type errors in PHP expressions inside your templates if you were relying on loose typing.
+
+If you cannot fix the types immediately, you can disable this behavior:
+
+```php
+$latte->setFeature(Latte\Feature::StrictTypes, false);
+```
+
+
+Global Constants
+================
+
+The template parser has been improved to better distinguish between simple strings and constants. As a result, global constants must now be prefixed with a backslash `\`.
+
+```latte
+{* Old way (throws a warning; in the future will be interpreted as the string 'PHP_VERSION') *}
+{if PHP_VERSION > ...}
+
+{* New way (correctly interpreted as constant) *}
+{if \PHP_VERSION > ...}
+```
+
+This change prevents ambiguity and allows you to use unquoted strings more freely.
+
+
+Removed Features
+================
+
+**Reserved Variables:** Variables starting with `$__` (double underscore) and the variable `$this` are now strictly reserved for Latte's internal use. You cannot use them in your templates.
+
+**Undefined-safe Operator:** The `??->` operator, which was a Latte-specific feature created before PHP 8, has been removed. It is a historical relic. Please use the standard PHP nullsafe operator `?->`.
+
+**Filter Loader**
+The `Engine::addFilterLoader()` method has been deprecated and removed. It was an inconsistent concept not found elsewhere in Latte.
+
+**Date Format**
+The static property `Latte\Runtime\Filters::$dateFormat` was removed to avoid global state.
+
+
+New Features
+============
+
+While migrating, you can start enjoying the new features:
+
+- **Smart HTML
+Attributes:** Pass arrays to `class` and `style`, auto-drop `null` attributes.
+- **Nullsafe filters:** Use `{$var?|filter}` to skip filtering null values.
+- **`n:elseif`:** You can now use `n:elseif` alongside `n:if` and `n:else`.
+- **Simplified syntax:** Write `';
An attacker simply needs to insert a cleverly crafted string `" onload="alert('Hacked!')` as the caption, and if the output is not sanitized, the resulting code will look like this:
-```html
+```latte
```
@@ -91,7 +91,7 @@ Context-Aware Escaping
What exactly is meant by the word context? It's a location within the document with its own rules for handling the data being printed. It depends on the document type (HTML, XML, CSS, JavaScript, plain text, ...) and can differ in specific parts. For example, in an HTML document, there are many places (contexts) where very different rules apply. You might be surprised how many there are. Here are the first four:
-```html
+```latte
@@ -108,7 +108,7 @@ It gets interesting inside HTML comments. Here, HTML entities are not used for e
Contexts can also be layered, which occurs when we embed JavaScript or CSS into HTML. This can be done in two different ways, using an element or an attribute:
-```html
+```latte
@@ -132,7 +132,7 @@ Let's take the string `Rock'n'Roll`.
If you print it in HTML text, in this particular case, no replacement is needed because the string does not contain any characters with special meaning. The situation changes if you print it inside an HTML attribute enclosed in single quotes. In that case, you need to escape the quotes into HTML entities:
-```html
+```latte
```
@@ -152,13 +152,13 @@ alert('Rock\'n\'Roll');
If we insert this code into an HTML document using ` alert('Rock\'n\'Roll');
```
However, if we wanted to insert it into an HTML attribute, we still need to escape the quotes into HTML entities:
-```html
+```latte
```
@@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll
And when we print this string in an attribute, we still apply escaping according to this context and replace `&` with `&`:
-```html
+```latte
```
@@ -314,7 +314,7 @@ Notice that there are no quotes around the attribute values. The coder might hav
An attacker inserts a cleverly crafted string `foo onload=alert('Hacked!')` as the image caption. We already know that Twig cannot determine whether a variable is being printed in the HTML text flow, inside an attribute, an HTML comment, etc.; in short, it does not distinguish contexts. And it just mechanically converts the characters `< > & ' "` into HTML entities. So the resulting code will look like this:
-```html
+```latte
```
@@ -330,7 +330,7 @@ Now let's see how Latte handles the same template:
Latte sees the template the same way you do. Unlike Twig, it understands HTML and knows that the variable is being printed as the value of an attribute that is not enclosed in quotes. Therefore, it adds them. When an attacker inserts the same caption, the resulting code will look like this:
-```html
+```latte
```
diff --git a/latte/en/syntax.texy b/latte/en/syntax.texy
index a65b056772..aa7e274f5f 100644
--- a/latte/en/syntax.texy
+++ b/latte/en/syntax.texy
@@ -111,6 +111,34 @@ Which outputs, depending on the variable `$url`:
However, n:attributes are not only a shortcut for pair tags, there are some pure n:attributes as well, for example the coder's best friend [n:class|tags#n:class] or the very handy [n:href |application:creating-links#In the Presenter Template].
+In addition to the syntax using quotes `{=' Hello world '|trim}
```
+If the value can be `null` and you want to avoid applying the filter in that case, use the [nullsafe filter |filters#Nullsafe Filters] `?|`:
+
+```latte
+
{$heading?|upper}
+```
+
Dynamic HTML Tags .{data-version:3.0.9}
=======================================
@@ -183,6 +218,41 @@ PHP comments work inside tags:
```
+Whitespace Control
+==================
+
+Latte handles whitespace intelligently. You can freely indent your code for readability, and the output stays clean. When a tag appears alone on a line, the entire line (indentation and newline) is removed from the output:
+
+```latte
+
+ {foreach $items as $item}
+
+```
+
+Outputs:
+
+```latte
+
+
+```
+
+What if a tag isn't alone on a line, but appears alongside other content? The whitespace before the tag then belongs *inside* the tag:
+
+```latte
+';
Al atacante le basta con insertar como descripción una cadena hábilmente construida `" onload="alert('Hacked!')` y si la impresión no está saneada, el código resultante se verá así:
-```html
+```latte
```
@@ -91,7 +91,7 @@ Escape sensible al contexto
¿Qué se entiende exactamente por la palabra contexto? Es un lugar en el documento con sus propias reglas para el saneamiento de los datos impresos. Depende del tipo de documento (HTML, XML, CSS, JavaScript, texto plano, ...) y puede diferir en sus partes específicas. Por ejemplo, en un documento HTML hay muchos lugares (contextos) donde se aplican reglas muy diferentes. Quizás se sorprenda de cuántos hay. Aquí tenemos los primeros cuatro:
-```html
+```latte
@@ -108,7 +108,7 @@ Es interesante dentro de los comentarios HTML. Aquí, el escape no se realiza ut
Los contextos también pueden anidarse, lo que ocurre cuando insertamos JavaScript o CSS en HTML. Esto se puede hacer de dos maneras diferentes, con un elemento y con un atributo:
-```html
+```latte
@@ -132,7 +132,7 @@ Tomemos la cadena `Rock'n'Roll`.
Si la imprime en texto HTML, en este caso particular no es necesario realizar ningún reemplazo, porque la cadena no contiene ningún carácter con significado especial. La situación cambia si la imprime dentro de un atributo HTML delimitado por comillas simples. En ese caso, es necesario escapar las comillas a entidades HTML:
-```html
+```latte
```
@@ -152,13 +152,13 @@ alert('Rock\'n\'Roll');
Si insertamos este código en un documento HTML usando ` alert('Rock\'n\'Roll');
```
Sin embargo, si quisiéramos insertarlo en un atributo HTML, aún debemos escapar las comillas a entidades HTML:
-```html
+```latte
```
@@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll
Y cuando imprimimos esta cadena en un atributo, aún aplicamos el escape según este contexto y reemplazamos `&` por `&`:
-```html
+```latte
```
@@ -314,7 +314,7 @@ Observe que no hay comillas alrededor de los valores de los atributos. El codifi
Un atacante inserta como descripción de la imagen una cadena hábilmente construida `foo onload=alert('Hacked!')`. Ya sabemos que Twig no puede saber si la variable se imprime en el flujo de texto HTML, dentro de un atributo, comentario HTML, etc., en resumen, no distingue contextos. Y solo convierte mecánicamente los caracteres `< > & ' "` en entidades HTML. Así que el código resultante se verá así:
-```html
+```latte
```
@@ -330,7 +330,7 @@ Ahora veamos cómo Latte maneja la misma plantilla:
Latte ve la plantilla igual que usted. A diferencia de Twig, entiende HTML y sabe que la variable se imprime como el valor de un atributo que no está entre comillas. Por eso las añade. Cuando un atacante inserta la misma descripción, el código resultante se verá así:
-```html
+```latte
```
diff --git a/latte/es/type-system.texy b/latte/es/type-system.texy
index b3b4097727..d1cacbcb12 100644
--- a/latte/es/type-system.texy
+++ b/latte/es/type-system.texy
@@ -21,7 +21,7 @@ Los tipos declarados son informativos y Latte no los verifica en este momento.
class CatalogTemplateParameters
{
public function __construct(
- public string $langs,
+ public string $lang,
/** @var ProductEntity[] */
public array $products,
public Address $address,
@@ -35,7 +35,7 @@ $latte->render('template.latte', new CatalogTemplateParameters(
));
```
-Y luego, al principio de la plantilla, inserte la etiqueta `{templateType}` con el nombre completo de la clase (incluido el namespace). Esto define que en la plantilla existen las variables `$langs` y `$products` con sus tipos correspondientes. Puede indicar los tipos de las variables locales usando las etiquetas [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Definiciones define].
+Y luego, al principio de la plantilla, inserte la etiqueta `{templateType}` con el nombre completo de la clase (incluido el namespace). Esto define que en la plantilla existen las variables `$lang` y `$products` con sus tipos correspondientes. Puede indicar los tipos de las variables locales usando las etiquetas [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Definiciones define].
A partir de ese momento, su IDE puede sugerir correctamente.
diff --git a/latte/files/html-attributes.webp b/latte/files/html-attributes.webp
new file mode 100644
index 0000000000..56e729541b
Binary files /dev/null and b/latte/files/html-attributes.webp differ
diff --git a/latte/fr/custom-tags.texy b/latte/fr/custom-tags.texy
index 29c14a08a8..9983a44429 100644
--- a/latte/fr/custom-tags.texy
+++ b/latte/fr/custom-tags.texy
@@ -923,7 +923,7 @@ Vous pouvez maintenant utiliser `n:confirm` sur des liens, des boutons ou des é
HTML généré :
-```html
+```latte
Supprimer
```
diff --git a/latte/fr/safety-first.texy b/latte/fr/safety-first.texy
index e4b3f5a93a..d9476e4305 100644
--- a/latte/fr/safety-first.texy
+++ b/latte/fr/safety-first.texy
@@ -33,7 +33,7 @@ echo '';
Il suffit à l'attaquant d'insérer comme légende une chaîne habilement construite `" onload="alert('Piraté !')` et si l'affichage n'est pas traité, le code résultant ressemblera à ceci :
-```html
+```latte
```
@@ -91,7 +91,7 @@ Cependant, XSS ne concerne pas seulement l'affichage des données dans les templ
Que signifie exactement le mot contexte ? C'est un endroit dans le document avec ses propres règles pour traiter les données affichées. Il dépend du type de document (HTML, XML, CSS, JavaScript, texte brut, ...) et peut varier dans ses parties spécifiques. Par exemple, dans un document HTML, il existe de nombreux endroits (contextes) où des règles très différentes s'appliquent. Vous serez peut-être surpris de leur nombre. Voici les quatre premiers :
-```html
+```latte
@@ -108,7 +108,7 @@ C'est intéressant à l'intérieur des commentaires HTML. Ici, l'échappement n'
Les contextes peuvent également être imbriqués, ce qui se produit lorsque nous insérons du JavaScript ou du CSS dans du HTML. Cela peut être fait de deux manières différentes, par élément et par attribut :
-```html
+```latte
@@ -132,7 +132,7 @@ Prenons la chaîne `Rock'n'Roll`.
Si vous l'affichez dans du texte HTML, dans ce cas précis, il n'est pas nécessaire de faire de remplacements, car la chaîne ne contient aucun caractère ayant une signification spéciale. La situation change si vous l'affichez à l'intérieur d'un attribut HTML entouré de guillemets simples. Dans ce cas, il faut échapper les guillemets en entités HTML :
-```html
+```latte
```
@@ -152,13 +152,13 @@ alert('Rock\'n\'Roll');
Si nous insérons ce code dans un document HTML à l'aide de ` alert('Rock\'n\'Roll');
```
Cependant, si nous voulions l'insérer dans un attribut HTML, nous devrions encore échapper les guillemets en entités HTML :
-```html
+```latte
```
@@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll
Et lorsque nous affichons cette chaîne dans un attribut, nous appliquons encore l'échappement selon ce contexte et remplaçons `&` par `&`:
-```html
+```latte
```
@@ -314,7 +314,7 @@ Notez qu'il n'y a pas de guillemets autour des valeurs des attributs. Le codeur
L'attaquant insère comme légende de l'image une chaîne habilement construite `foo onload=alert('Piraté !')`. Nous savons déjà que Twig ne peut pas savoir si la variable est affichée dans le flux de texte HTML, à l'intérieur d'un attribut, d'un commentaire HTML, etc., bref, il ne distingue pas les contextes. Et il ne fait que convertir mécaniquement les caractères `< > & ' "` en entités HTML. Le code résultant ressemblera donc à ceci :
-```html
+```latte
```
@@ -330,7 +330,7 @@ Voyons maintenant comment Latte gère le même template :
Latte voit le template de la même manière que vous. Contrairement à Twig, il comprend HTML et sait que la variable est affichée comme valeur d'un attribut qui n'est pas entre guillemets. C'est pourquoi il les ajoute. Lorsque l'attaquant insère la même légende, le code résultant ressemblera à ceci :
-```html
+```latte
```
diff --git a/latte/fr/type-system.texy b/latte/fr/type-system.texy
index 8419906504..0cac1c1ac0 100644
--- a/latte/fr/type-system.texy
+++ b/latte/fr/type-system.texy
@@ -21,7 +21,7 @@ Comment commencer à utiliser les types ? Créez une classe de template, par exe
class CatalogTemplateParameters
{
public function __construct(
- public string $langs,
+ public string $lang,
/** @var ProductEntity[] */
public array $products,
public Address $address,
@@ -35,7 +35,7 @@ $latte->render('template.latte', new CatalogTemplateParameters(
));
```
-Ensuite, au début du template, insérez la balise `{templateType}` avec le nom complet de la classe (y compris le namespace). Cela définit que les variables `$langs` et `$products` existent dans le template, y compris leurs types respectifs. Vous pouvez spécifier les types des variables locales à l'aide des balises [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Définitions].
+Ensuite, au début du template, insérez la balise `{templateType}` avec le nom complet de la classe (y compris le namespace). Cela définit que les variables `$lang` et `$products` existent dans le template, y compris leurs types respectifs. Vous pouvez spécifier les types des variables locales à l'aide des balises [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Définitions].
À partir de ce moment, l'IDE peut correctement vous faire des suggestions.
diff --git a/latte/hu/custom-tags.texy b/latte/hu/custom-tags.texy
index f8e2946305..6b7f70dbe5 100644
--- a/latte/hu/custom-tags.texy
+++ b/latte/hu/custom-tags.texy
@@ -923,7 +923,7 @@ Most már használhatja az `n:confirm`-ot linkeken, gombokon vagy űrlap elemeke
Generált HTML:
-```html
+```latte
Törlés
```
diff --git a/latte/hu/safety-first.texy b/latte/hu/safety-first.texy
index a07f648fe6..a1b2547fa0 100644
--- a/latte/hu/safety-first.texy
+++ b/latte/hu/safety-first.texy
@@ -33,7 +33,7 @@ echo '';
A támadónak elég leírásként egy ügyesen összeállított `" onload="alert('Hacked!')` stringet beilleszteni, és ha a kiírás nincs kezelve, az eredményül kapott kód így fog kinézni:
-```html
+```latte
```
@@ -91,7 +91,7 @@ Kontextusérzékeny escapelés
Mit jelent pontosan a kontextus szó? Ez egy hely a dokumentumban, saját szabályokkal a kiírt adatok kezelésére. A dokumentum típusától (HTML, XML, CSS, JavaScript, plain text, ...) függ, és eltérhet annak konkrét részeiben. Például egy HTML dokumentumban számos ilyen hely (kontextus) van, ahol nagyon eltérő szabályok érvényesek. Talán meglepődik, mennyi van belőlük. Íme az első négy:
-```html
+```latte
@@ -108,7 +108,7 @@ Talán meglepő, de speciális szabályok érvényesek a `