From 8fc32a939144092fa078d8e01de64ab6d3430f03 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Fri, 3 Oct 2025 14:59:06 +0200 Subject: [PATCH 01/50] added dibi & texy --- contributing/bg/syntax.texy | 2 +- contributing/cs/syntax.texy | 2 +- contributing/de/syntax.texy | 2 +- contributing/el/syntax.texy | 2 +- contributing/en/syntax.texy | 2 +- contributing/es/syntax.texy | 2 +- contributing/fr/syntax.texy | 2 +- contributing/hu/syntax.texy | 2 +- contributing/it/syntax.texy | 2 +- contributing/ja/syntax.texy | 2 +- contributing/pl/syntax.texy | 2 +- contributing/pt/syntax.texy | 2 +- contributing/ro/syntax.texy | 2 +- contributing/ru/syntax.texy | 2 +- contributing/sl/syntax.texy | 2 +- contributing/tr/syntax.texy | 2 +- contributing/uk/syntax.texy | 2 +- dibi/cs/@home.texy | 657 +++++++++++++++++++++ dibi/cs/@menu.texy | 4 + dibi/cs/@meta.texy | 1 + dibi/en/@home.texy | 656 +++++++++++++++++++++ dibi/en/@menu.texy | 3 + dibi/en/@meta.texy | 1 + dibi/meta.json | 5 + texy/cs/@home.texy | 32 ++ texy/cs/@menu.texy | 8 + texy/cs/@meta.texy | 1 + texy/cs/@try.texy | 15 + texy/cs/api-block-module.texy | 11 + texy/cs/api-blockquote-module.texy | 8 + texy/cs/api-emoticon-module.texy | 47 ++ texy/cs/api-figure-module.texy | 33 ++ texy/cs/api-heading-module.texy | 42 ++ texy/cs/api-horizline-module.texy | 8 + texy/cs/api-html-module.texy | 21 + texy/cs/api-htmloutput-module.texy | 17 + texy/cs/api-image-module.texy | 35 ++ texy/cs/api-link-module.texy | 42 ++ texy/cs/api-list-module.texy | 12 + texy/cs/api-longwords-module.texy | 19 + texy/cs/api-paragraph-module.texy | 4 + texy/cs/api-phrase-module.texy | 22 + texy/cs/api-script-module.texy | 23 + texy/cs/api-table-module.texy | 18 + texy/cs/api-texy.texy | 69 +++ texy/cs/api-typography-module.texy | 21 + texy/cs/api-zaklady.texy | 25 + texy/cs/api.texy | 28 + texy/cs/napsali-o-texy.texy | 160 ++++++ texy/cs/priklady-vyuziti.texy | 26 + texy/cs/syntax-podrobne.texy | 889 +++++++++++++++++++++++++++++ texy/cs/syntax.texy | 464 +++++++++++++++ texy/cs/texy-vs-wysiwyg.texy | 23 + texy/cs/try-settings.texy | 55 ++ texy/en/@home.texy | 31 + texy/en/@menu.texy | 6 + texy/en/@meta.texy | 1 + texy/en/@try.texy | 15 + texy/en/syntax-full.texy | 889 +++++++++++++++++++++++++++++ texy/en/syntax.texy | 463 +++++++++++++++ texy/en/try-settings.texy | 55 ++ texy/files/image.gif | Bin 0 -> 942 bytes texy/meta.json | 5 + 63 files changed, 4987 insertions(+), 17 deletions(-) create mode 100644 dibi/cs/@home.texy create mode 100644 dibi/cs/@menu.texy create mode 100644 dibi/cs/@meta.texy create mode 100644 dibi/en/@home.texy create mode 100644 dibi/en/@menu.texy create mode 100644 dibi/en/@meta.texy create mode 100644 dibi/meta.json create mode 100644 texy/cs/@home.texy create mode 100644 texy/cs/@menu.texy create mode 100644 texy/cs/@meta.texy create mode 100644 texy/cs/@try.texy create mode 100644 texy/cs/api-block-module.texy create mode 100644 texy/cs/api-blockquote-module.texy create mode 100644 texy/cs/api-emoticon-module.texy create mode 100644 texy/cs/api-figure-module.texy create mode 100644 texy/cs/api-heading-module.texy create mode 100644 texy/cs/api-horizline-module.texy create mode 100644 texy/cs/api-html-module.texy create mode 100644 texy/cs/api-htmloutput-module.texy create mode 100644 texy/cs/api-image-module.texy create mode 100644 texy/cs/api-link-module.texy create mode 100644 texy/cs/api-list-module.texy create mode 100644 texy/cs/api-longwords-module.texy create mode 100644 texy/cs/api-paragraph-module.texy create mode 100644 texy/cs/api-phrase-module.texy create mode 100644 texy/cs/api-script-module.texy create mode 100644 texy/cs/api-table-module.texy create mode 100644 texy/cs/api-texy.texy create mode 100644 texy/cs/api-typography-module.texy create mode 100644 texy/cs/api-zaklady.texy create mode 100644 texy/cs/api.texy create mode 100644 texy/cs/napsali-o-texy.texy create mode 100644 texy/cs/priklady-vyuziti.texy create mode 100644 texy/cs/syntax-podrobne.texy create mode 100644 texy/cs/syntax.texy create mode 100644 texy/cs/texy-vs-wysiwyg.texy create mode 100644 texy/cs/try-settings.texy create mode 100644 texy/en/@home.texy create mode 100644 texy/en/@menu.texy create mode 100644 texy/en/@meta.texy create mode 100644 texy/en/@try.texy create mode 100644 texy/en/syntax-full.texy create mode 100644 texy/en/syntax.texy create mode 100644 texy/en/try-settings.texy create mode 100644 texy/files/image.gif create mode 100644 texy/meta.json diff --git a/contributing/bg/syntax.texy b/contributing/bg/syntax.texy index 23db082cf4..94bbb02a7a 100644 --- a/contributing/bg/syntax.texy +++ b/contributing/bg/syntax.texy @@ -1,7 +1,7 @@ Синтаксис на документацията *************************** -Документацията използва Markdown & [синтаксис на Texy |https://texy.info/cs/syntax] с някои разширения. +Документацията използва Markdown & [синтаксис на Texy |https://texy.nette.org/syntax] с някои разширения. Връзки diff --git a/contributing/cs/syntax.texy b/contributing/cs/syntax.texy index ad8f3ea4c1..039f8c32ac 100644 --- a/contributing/cs/syntax.texy +++ b/contributing/cs/syntax.texy @@ -1,7 +1,7 @@ Dokumentační syntax ******************* -Dokumentace používá Markdown & [Texy syntaxi |https://texy.info/cs/syntax] s některými rozšířeními. +Dokumentace používá Markdown & [Texy syntaxi |https://texy.nette.org/syntax] s některými rozšířeními. Odkazy diff --git a/contributing/de/syntax.texy b/contributing/de/syntax.texy index 64257e971f..02b8af3554 100644 --- a/contributing/de/syntax.texy +++ b/contributing/de/syntax.texy @@ -1,7 +1,7 @@ Dokumentationssyntax ******************** -Die Dokumentation verwendet Markdown & [Texy-Syntax |https://texy.info/de/syntax] mit einigen Erweiterungen. +Die Dokumentation verwendet Markdown & [Texy-Syntax |https://texy.nette.org/syntax] mit einigen Erweiterungen. Links diff --git a/contributing/el/syntax.texy b/contributing/el/syntax.texy index 8727317430..2f46730e28 100644 --- a/contributing/el/syntax.texy +++ b/contributing/el/syntax.texy @@ -1,7 +1,7 @@ Σύνταξη Τεκμηρίωσης ******************* -Η τεκμηρίωση χρησιμοποιεί Markdown & [σύνταξη Texy |https://texy.info/cs/syntax] με ορισμένες επεκτάσεις. +Η τεκμηρίωση χρησιμοποιεί Markdown & [σύνταξη Texy |https://texy.nette.org/syntax] με ορισμένες επεκτάσεις. Σύνδεσμοι diff --git a/contributing/en/syntax.texy b/contributing/en/syntax.texy index a04894a8b9..c7d81ac54f 100644 --- a/contributing/en/syntax.texy +++ b/contributing/en/syntax.texy @@ -1,7 +1,7 @@ Documentation Syntax ******************** -Documentation uses Markdown & [Texy syntax |https://texy.info/en/syntax] with several enhancements. +Documentation uses Markdown & [Texy syntax |https://texy.nette.org/syntax] with several enhancements. Links diff --git a/contributing/es/syntax.texy b/contributing/es/syntax.texy index 97d8316c1c..559dc80217 100644 --- a/contributing/es/syntax.texy +++ b/contributing/es/syntax.texy @@ -1,7 +1,7 @@ Sintaxis de la documentación **************************** -La documentación utiliza Markdown y la [sintaxis Texy |https://texy.info/cs/syntax] con algunas extensiones. +La documentación utiliza Markdown y la [sintaxis Texy |https://texy.nette.org/syntax] con algunas extensiones. Enlaces diff --git a/contributing/fr/syntax.texy b/contributing/fr/syntax.texy index 29c724851e..9b6df676f7 100644 --- a/contributing/fr/syntax.texy +++ b/contributing/fr/syntax.texy @@ -1,7 +1,7 @@ Syntaxe de la documentation *************************** -La documentation utilise Markdown & la [syntaxe Texy |https://texy.info/cs/syntax] avec quelques extensions. +La documentation utilise Markdown & la [syntaxe Texy |https://texy.nette.org/syntax] avec quelques extensions. Liens diff --git a/contributing/hu/syntax.texy b/contributing/hu/syntax.texy index 66b8b50260..11e46f6417 100644 --- a/contributing/hu/syntax.texy +++ b/contributing/hu/syntax.texy @@ -1,7 +1,7 @@ Dokumentációs szintaxis *********************** -A dokumentáció Markdown & [Texy szintaxist |https://texy.info/cs/syntax] használ néhány kiterjesztéssel. +A dokumentáció Markdown & [Texy szintaxist |https://texy.nette.org/syntax] használ néhány kiterjesztéssel. Linkek diff --git a/contributing/it/syntax.texy b/contributing/it/syntax.texy index ef704f10e4..c60a00fb10 100644 --- a/contributing/it/syntax.texy +++ b/contributing/it/syntax.texy @@ -1,7 +1,7 @@ Sintassi della documentazione ***************************** -La documentazione utilizza Markdown e la [sintassi Texy |https://texy.info/cs/syntax] con alcune estensioni. +La documentazione utilizza Markdown e la [sintassi Texy |https://texy.nette.org/syntax] con alcune estensioni. Link diff --git a/contributing/ja/syntax.texy b/contributing/ja/syntax.texy index 4ee286ef64..2fe4e0c515 100644 --- a/contributing/ja/syntax.texy +++ b/contributing/ja/syntax.texy @@ -1,7 +1,7 @@ ドキュメント構文 ******** -ドキュメントはMarkdownと [Texy構文 |https://texy.info/cs/syntax] を使用し、いくつかの拡張機能があります。 +ドキュメントはMarkdownと [Texy構文 |https://texy.nette.org/syntax] を使用し、いくつかの拡張機能があります。 リンク diff --git a/contributing/pl/syntax.texy b/contributing/pl/syntax.texy index 0090da8000..08b4227f42 100644 --- a/contributing/pl/syntax.texy +++ b/contributing/pl/syntax.texy @@ -1,7 +1,7 @@ Składnia dokumentacji ********************* -Dokumentacja używa składni Markdown & [składni Texy |https://texy.info/cs/syntax] z niektórymi rozszerzeniami. +Dokumentacja używa składni Markdown & [składni Texy |https://texy.nette.org/syntax] z niektórymi rozszerzeniami. Linki diff --git a/contributing/pt/syntax.texy b/contributing/pt/syntax.texy index c820a98389..e810926f67 100644 --- a/contributing/pt/syntax.texy +++ b/contributing/pt/syntax.texy @@ -1,7 +1,7 @@ Sintaxe da Documentação *********************** -A documentação usa Markdown e a [sintaxe Texy |https://texy.info/cs/syntax] com algumas extensões. +A documentação usa Markdown e a [sintaxe Texy |https://texy.nette.org/syntax] com algumas extensões. Links diff --git a/contributing/ro/syntax.texy b/contributing/ro/syntax.texy index dd1a95cf97..d756e4e2b0 100644 --- a/contributing/ro/syntax.texy +++ b/contributing/ro/syntax.texy @@ -1,7 +1,7 @@ Sintaxa documentației ********************* -Documentația utilizează Markdown & [sintaxa Texy |https://texy.info/en/syntax] cu unele extensii. +Documentația utilizează Markdown & [sintaxa Texy |https://texy.nette.org/syntax] cu unele extensii. Linkuri diff --git a/contributing/ru/syntax.texy b/contributing/ru/syntax.texy index ad1bbc8511..af9411a740 100644 --- a/contributing/ru/syntax.texy +++ b/contributing/ru/syntax.texy @@ -1,7 +1,7 @@ Синтаксис документации ********************** -Документация использует синтаксис Markdown и [синтаксис Texy |https://texy.info/cs/syntax] с некоторыми расширениями. +Документация использует синтаксис Markdown и [синтаксис Texy |https://texy.nette.org/syntax] с некоторыми расширениями. Ссылки diff --git a/contributing/sl/syntax.texy b/contributing/sl/syntax.texy index 8486f3ea0e..55aed5ac18 100644 --- a/contributing/sl/syntax.texy +++ b/contributing/sl/syntax.texy @@ -1,7 +1,7 @@ Sintaksa dokumentacije ********************** -Dokumentacija uporablja Markdown & [sintakso Texy |https://texy.info/sl/syntax] z nekaterimi razširitvami. +Dokumentacija uporablja Markdown & [sintakso Texy |https://texy.nette.org/syntax] z nekaterimi razširitvami. Povezave diff --git a/contributing/tr/syntax.texy b/contributing/tr/syntax.texy index 650cfe37eb..41bbf226ef 100644 --- a/contributing/tr/syntax.texy +++ b/contributing/tr/syntax.texy @@ -1,7 +1,7 @@ Dokümantasyon sözdizimi *********************** -Dokümantasyon, bazı uzantılarla birlikte Markdown & [Texy sözdizimini |https://texy.info/cs/syntax] kullanır. +Dokümantasyon, bazı uzantılarla birlikte Markdown & [Texy sözdizimini |https://texy.nette.org/syntax] kullanır. Bağlantılar diff --git a/contributing/uk/syntax.texy b/contributing/uk/syntax.texy index de3c97be92..c9d1b66d60 100644 --- a/contributing/uk/syntax.texy +++ b/contributing/uk/syntax.texy @@ -1,7 +1,7 @@ Синтаксис документації ********************** -Документація використовує Markdown та [синтаксис Texy |https://texy.info/cs/syntax] з деякими розширеннями. +Документація використовує Markdown та [синтаксис Texy |https://texy.nette.org/syntax] з деякими розширеннями. Посилання diff --git a/dibi/cs/@home.texy b/dibi/cs/@home.texy new file mode 100644 index 0000000000..0270991509 --- /dev/null +++ b/dibi/cs/@home.texy @@ -0,0 +1,657 @@ +Dibi: Šikovná Database Abstraction Library pro PHP +************************************************** + +Nejnovější stabilní verzi Dibi instalujte pomocí [Composer|best-practices:composer] příkazem: + +``` +composer require dibi/dibi +``` + +Přehled verzí najdete na stánce [Releases | https://github.com/dg/dibi/releases]. + +Vyžaduje PHP 8.0 nebo vyšší. + + +Připojení k databázi +==================== + +Databázové spojení je reprezentováno objektem [Dibi\Connection|api:]: + +```php +$database = new Dibi\Connection([ + 'driver' => 'mysqli', + 'host' => 'localhost', + 'username' => 'root', + 'password' => '***', + 'database' => 'table', +]); + +$result = $database->query('SELECT * FROM users'); +``` + +Alternativně můžete používat statický registr `dibi`, který udržuje v globálně dostupném úložišti objekt spojení a nad ním volá všechny funkce: + +```php +dibi::connect([ + 'driver' => 'mysqli', + 'host' => 'localhost', + 'username' => 'root', + 'password' => '***', + 'database' => 'test', + 'charset' => 'utf8', +]); + +$result = dibi::query('SELECT * FROM users'); +``` + +V případě chyby připojení se vyhodí `Dibi\Exception`. + + +Dotazy +====== + +Databázové dotazy pokládáme metodou `query()`, která vrací [Dibi\Result |api:Dibi\Result]. Řádky jako objekty [Dibi\Row |api:Dibi\Row]. + +Všechny příklady si můžete zkoušet [online na hřišti |https://repl.it/@DavidGrudl/dibi-playground]. + +```php +$result = $database->query('SELECT * FROM users'); + +foreach ($result as $row) { + echo $row->id; + echo $row->name; +} + +// pole všech řádků +$all = $result->fetchAll(); + +// pole všech řádků, klíčem je 'id' +$all = $result->fetchAssoc('id'); + +// asociativní pole id => name +$pairs = $result->fetchPairs('id', 'name'); + +// počet řádků výsledku, pokud je znám, nebo počet ovlivněných řádků +$count = $result->getRowCount(); +``` + +Metoda fetchAssoc() umí vracet i [složitější asociativní pole |#Výsledek jako asociativní pole]. + +Do dotazu lze velmi snadno přidávat i parametry, všimněte si otazníku: + +```php +$result = $database->query('SELECT * FROM users WHERE name = ? AND active = ?', $name, $active); + +// nebo +$result = $database->query('SELECT * FROM users WHERE name = ?', $name, 'AND active = ?', $active); + +$ids = [10, 20, 30]; +$result = $database->query('SELECT * FROM users WHERE id IN (?)', $ids); +``` + +
+**POZOR, nikdy dotazy neskládejte jako řetězce, vznikla by zranitelnost [SQL injection |https://cs.wikipedia.org/wiki/SQL_injection]** +/-- +$database->query('SELECT * FROM users WHERE id = ' . $id); // ŠPATNĚ!!! +\-- +
+ +Místo otazníku lze používat i tzv. [#modifikátory]. + +```php +$result = $database->query('SELECT * FROM users WHERE name = %s', $name); +``` + +V případě selhání `query()` vyhodí buď `Dibi\Exception`, nebo některého z potomků: + +- [ConstraintViolationException |api:Dibi\ConstraintViolationException] - porušení nějakého omezení pro tabulku +- [ForeignKeyConstraintViolationException |api:Dibi\ForeignKeyConstraintViolationException] - neplatný cizí klíč +- [NotNullConstraintViolationException |api:Dibi\NotNullConstraintViolationException] - porušení podmínky NOT NULL +- [UniqueConstraintViolationException |api:Dibi\UniqueConstraintViolationException] - koliduje unikátní index + +Dotazy lze pokládat také pomocí zkratek: + +```php +// vrátí asociativní pole id => name, zkratka pro query(...)->fetchPairs() +$pairs = $database->fetchPairs('SELECT id, name FROM users'); + +// vrátí pole všech řádků, zkratka pro query(...)->fetchAll() +$rows = $database->fetchAll('SELECT * FROM users'); + +// vrátí řádek, zkratka pro query(...)->fetch() +$row = $database->fetch('SELECT * FROM users WHERE id = ?', $id); + +// vrátí buňku, zkratka pro query(...)->fetchSingle() +$name = $database->fetchSingle('SELECT name FROM users WHERE id = ?', $id); +``` + + +Modifikátory +============ + +Kromě zástupného symbolu `?` můžeme používat i modifikátory: + +| %s | string +| %sN | string, ale '' se přeloží jako NULL +| %bin | binární data +| %b | boolean +| %i | integer +| %iN | integer, ale 0 se přeloží jako NULL +| %f | float +| %d | datum (očekává DateTime, string nebo UNIX timestamp) +| %dt | datum & čas (očekává DateTime, string nebo UNIX timestamp) +| %n | identifikátor, tedy název tabulky či sloupce +| %N | identifikátor, považuje tečku za běžný znak +| %SQL | SQL - přímo vloží do SQL (alternativou je Dibi\Literal) +| %ex | expanduje pole +| %lmt | speciální - doplní do dotazu LIMIT +| %ofs | speciální - doplní do dotazu OFFSET + +Příklad: + +```php +$result = $database->query('SELECT * FROM users WHERE name = %s', $name); +``` + +Pokud `$name` je `null`, vloží se do SQL příkazu `NULL`. + +Pokud proměnná je pole, tak se modifikátor aplikuje na všechny jeho prvky a ty se vloží do SQL oddělené čárkami: + +```php +$ids = [10, '20', 30]; +$result = $database->query('SELECT * FROM users WHERE id IN (%i)', $ids); +// SELECT * FROM users WHERE id IN (10, 20, 30) +``` + +Modifikátor `%n` využijete v případě, že název tabulky nebo sloupce je proměnnou. (Pozor, nedovolte uživateli manipulovat s obsahem takové proměnné): + +```php +$table = 'blog.users'; +$column = 'name'; +$result = $database->query('SELECT * FROM %n WHERE %n = ?', $table, $column, $value); +// SELECT * FROM `blog`.`users` WHERE `name` = 'Jim' +``` + +Pro operátor LIKE jsou k dispozici čtyři speciální modifikátory: + +| %like~ | výraz začíná řetězcem +| %~like | výraz končí řetězcem +| %~like~ | výraz obsahuje řetězec +| `%like` | výraz je řetězec + +Hledej jména začínající na určitý řetězec: + +```php +$result = $database->query('SELECT * FROM table WHERE name LIKE %like~', $query); +``` + + +Modifikátory polí +================= + +Parameterem vkládaným do SQL dotazu může být i pole. Tyto modifikátory určují, jak z něj sestavit SQL příkaz: + +| %and | | `key1 = value1 AND key2 = value2 AND ...` +| %or | | `key1 = value1 OR key2 = value2 OR ...` +| %a | assoc | `key1 = value1, key2 = value2, ...` +| %l %in | list | `(val1, val2, ...)` +| %v | values | `(key1, key2, ...) VALUES (value1, value2, ...)` +| %m | multi | `(key1, key2, ...) VALUES (value1, value2, ...), (value1, value2, ...), ...` +| %by | řazení | `key1 ASC, key2 DESC ...` +| %n | názvy | `key1, key2 AS alias, ...` + +Příklad: + +```php +$arr = [ + 'a' => 'hello', + 'b' => true, +]; + +$database->query('INSERT INTO table %v', $arr); +// INSERT INTO `table` (`a`, `b`) VALUES ('hello', 1) + +$database->query('UPDATE `table` SET %a', $arr); +// UPDATE `table` SET `a`='hello', `b`=1 +``` + +V klauzuli WHERE lze použít modifikátory `%and` nebo `%or`: + +```php +$result = $database->query('SELECT * FROM users WHERE %and', [ + 'name' => $name, + 'year' => $year, +]); +// SELECT * FROM users WHERE `name` = 'Jim' AND `year` = 1978 +``` + +Viz také [#Složitější dotazy]. + +Modifikátor `%by` slouží k řazení, v klíčích uvedeme sloupce a hodnotou bude boolean určující, zda řadit vzestupně: + +```php +$result = $database->query('SELECT id FROM author ORDER BY %by', [ + 'id' => true, // vzestupně + 'name' => false, // sestupně +]); +// SELECT id FROM author ORDER BY `id`, `name` DESC +``` + + +Insert, Update & Delete +======================= + +Data vkládáme do SQL dotazu jako asociativní pole. Modifikátory ani zástupný znak `?` není nutné v těchto případech uvádět. + +```php +$database->query('INSERT INTO users', [ + 'name' => $name, + 'year' => $year, +]); +// INSERT INTO users (`name`, `year`) VALUES ('Jim', 1978) + +$id = $database->getInsertId(); // vrátí auto-increment vloženého záznamu + +$id = $database->getInsertId($sequence); // nebo hodnotu sekvence +``` + +Vícenásobný INSERT: + +```php +$database->query( + 'INSERT INTO users', + [ + 'name' => 'Jim', + 'year' => 1978, + ], + [ + 'name' => 'Jack', + 'year' => 1987, + ] +); +// INSERT INTO users (`name`, `year`) VALUES ('Jim', 1978), ('Jack', 1987) +``` + +Mazání: + +```php +$database->query('DELETE FROM users WHERE id = ?', $id); + +// vrací počet smazaných řádků +$affectedRows = $database->getAffectedRows(); +``` + +Úprava záznamů: + +```php +$database->query('UPDATE users SET', [ + 'name' => $name, + 'year' => $year, +], 'WHERE id = ?', $id); +// UPDATE users SET `name` = 'Jim', `year` = 1978 WHERE id = 123 + +// vrací počet změněných řádků +$affectedRows = $database->getAffectedRows(); +``` + +Vložení záznamu, nebo úprava, pokud již existuje: + +```php +$database->query('INSERT INTO users', [ + 'id' => $id, + 'name' => $name, + 'year' => $year, +], 'ON DUPLICATE KEY UPDATE %a', [ // tady už modifikátor %a uvést musíme + 'name' => $name, + 'year' => $year, +]); +// INSERT INTO users (`id`, `name`, `year`) VALUES (123, 'Jim', 1978) +// ON DUPLICATE KEY UPDATE `name` = 'Jim', `year` = 1978 +``` + + +Transakce +========= + +Pro práci s transakcemi slouží čtveřice metod: + +```php +$database->beginTransaction(); // zahájení transakce + +$database->commit(); // potvrzení + +$database->rollback(); // vrácení zpět + +$database->transaction(function () { + // nejaka akce +}); +``` + + +Testování +========= + +Abyste si mohli trošku s Dibi hrát, je tu připravena metoda `test()`, které předáte parametry stejně jako `query()`, ovšem místo provedení SQL příkazu se tento barevně vypíše na obrazovku. + +Výsledky dotazu je možné vypsat jako tabulku pomocí `$result->dump()`. + +K dispozici jsou dále proměnné: + +```php +dibi::$sql; // poslední SQL příklaz +dibi::$elapsedTime; // jeho doba trvání v sec +dibi::$numOfQueries; // celkem SQL příkazů +dibi::$totalTime; // celkový čas v sec +``` + + +Složitější dotazy +================= + +Parametrem může být také objekt `DateTime`. + +```php +$result = $database->query('SELECT * FROM users WHERE created < ?', new DateTime); + +$database->query('INSERT INTO users', [ + 'created' => new DateTime, +]); +``` + +Nebo SQL literál: + +```php +$database->query('UPDATE table SET', [ + 'date' => $database->literal('NOW()'), +]); +// UPDATE table SET `date` = NOW() +``` + +Nebo výraz, ve kterém lze používat zástupné znaky `?` nebo modifikátory: + +```php +$database->query('UPDATE `table` SET', [ + 'title' => $database::expression('SHA1(?)', 'tajne'), +]); +// UPDATE `table` SET `title` = SHA1('tajne') +``` + +Při update lze modifikátory uvádět přímo v klíčích: + +```php +$database->query('UPDATE table SET', [ + 'date%SQL' => 'NOW()', // %SQL znamená SQL ;) +]); +// UPDATE table SET `date` = NOW() +``` + +V podmínkách (tj. u modifikátorů `%and` a `%or`) není nutné uvádět klíče: + +```php +$result = $database->query('SELECT * FROM `table` WHERE %and', [ + 'number > 10', + 'number < 100', +]); +// SELECT * FROM `table` WHERE (number > 10) AND (number < 100) +``` + +V položkách lze používat i modifikátory nebo zástupné znaky: + +```php +$result = $database->query('SELECT * FROM `table` WHERE %and', [ + ['number > ?', 10], // nebo $database::expression('number > ?', 10) + ['number < ?', 100], + ['%or', [ + 'left' => 1, + 'top' => 2, + ]], +]); +// SELECT * FROM `table` WHERE (number > 10) AND (number < 100) AND (`left` = 1 OR `top` = 2) +``` + +Modifikátor `%ex` vloží do SQL všechny prvky pole: + +```php +$result = $database->query('SELECT * FROM `table` WHERE %ex', [ + $database::expression('left = ?', 1), + 'AND', + 'top IS NULL', +]); +// SELECT * FROM `table` WHERE left = 1 AND top IS NULL +``` + + +Podmínky v SQL příkazu +====================== + +Podmíněné SQL příkazy se ovládají pomocí tří modifikátorů `%if`, `%else` a `%end`. První z nich `%if` se musí nacházet zcela na konci řetězce představujícího SQL a za ním následuje proměnná: + +```php +//$user = ???; + +$result = $database->query(' + SELECT * + FROM table + %if', isset($user), 'WHERE user=%s', $user, '%end + ORDER BY name +'); +``` + +Podmínku lze doplnit o část `%else`: + +```php +$result = $database->query(' + SELECT * + FROM %if', $cond, 'one_table %else second_table +'); +``` + +Podmínky můžete zanořovat do sebe. + + +Identifikátory a řetězce v SQL +============================== + +Samotné SQL prochází zpracováním, aby vyhovovalo konvencím dané databáze. Identifikátory (jména tabulek a sloupců) lze uvozovat do hranatých závorek nebo zpětných uvozovek, dále řetězce jednoduchými či dvojitými uvozovkami, nicméně na server se pošle vždy to, co databáze žádá. Příklad + +```php +$database->query("UPDATE `table` SET [status]='I''m fine'"); +// MySQL: UPDATE `table` SET `status`='I\'m fine' +// ODBC: UPDATE [table] SET [status]='I''m fine' +``` + +Uvozovka se uvnitř řetězce v SQL zapisuje zdvojením. + + +Výsledek jako asociativní pole +============================== + +Příklad: vrátí výsledky jako asociativního pole, kde klíčem bude hodnota políčka `id`: + +```php +$assoc = $result->fetchAssoc('id'); +``` + +Největší síla funkce `fetchAssoc()` se projeví u SQL dotazu spojujícího několik tabulek s různými typy vazeb. Databáze z toho udělá plochou tabulku, fetchAssoc jí vrátí tvar. + +Příklad: Mějme tabulku zákazníků a objednávek (vazba N:M) a položíme dotaz: + +```php +$result = $database->query(' + SELECT customer_id, customers.name, order_id, orders.number, ... + FROM customers + INNER JOIN orders USING (customer_id) + WHERE ... +'); +``` + +A rádi bychom získali vnořené asociativní pole podle ID zákazníka a poté podle ID objednávky: + +```php +$all = $result->fetchAssoc('customer_id|order_id'); + +// budeme jej procházet takto: +foreach ($all as $customerId => $orders) { + foreach ($orders as $orderId => $order) { + // ... + } +} +``` + +Asociativní deskriptor má obdobnou syntax, jako když pole píšete pomocí přiřazení v PHP. Tedy `'customer_id|order_id'` představuje sérii přiřazení `$all[$customerId][$orderId] = $row;`, postupně pro všechny řádky. + +Někdy by se hodilo, aby se asociovalo podle jména zákazníka namísto jeho ID: + +```php +$all = $result->fetchAssoc('name|order_id'); + +// k prvkům pak přistupujeme třeba takto: +$order = $all['Arnold Rimmer'][$orderId]; +``` + +Co když ale existuje více zákazníků se stejným jménem? Tabulka by měla mít spíš tvar: + +```php +$row = $all['Arnold Rimmer'][0][$orderId]; +$row = $all['Arnold Rimmer'][1][$orderId]; +``` + +Rozlišujeme tedy více možných Rimmerů pomocí klasického pole. Asociativní deskriptor má opět formát podobný přiřazování, s tím, že sekvenční pole představuje `[]`: + +```php +$all = $result->fetchAssoc('name[]order_id'); + +// iterujeme všechny Arnoldy ve výsledcích +foreach ($all['Arnold Rimmer'] as $arnoldOrders) { + foreach ($arnoldOrders as $orderId => $order) { + // ... + } +} +``` + +Vrátíme se k příkladu s deskriptorem `'customer_id|order_id'` a zkusíme vypsat objednávky jednotlivých zákazníků: + +```php +$all = $result->fetchAssoc('customer_id|order_id'); + +foreach ($all as $customerId => $orders) { + echo "Objednávky zákazníka $customerId:"; + + foreach ($orders as $orderId => $order) { + echo "Číslo dokladu: $order->number"; + // jméno zákazníka je v $order->name + } +} +``` + +Bylo by hezké místo ID zákazníka vypsat jeho jméno. Jenže to bychom museli dohledávat v poli `$orders`. Výsledky si proto necháme upravit do takovéhoto tvaru: + +```php +$all[$customerId]->name = 'John Doe'; +$all[$customerId]->order_id[$orderId] = $row; +$all[$customerId]->order_id[$orderId2] = $row2; +``` + +Tedy mezi `$customerId` a `$orderId` vložíme ještě mezičlánek. Tentokrát ne číslované indexy, jaké jsme použili pro odlišení jednotlivých Rimmerů, ale rovnou databázový záznam. Řešení je velmi podobné, jen si stačí zapamatovat, že záznam symbolizuje šipka: + +```php +$all = $result->fetchAssoc('customer_id->order_id'); + +foreach ($all as $customerId => $row) { + echo "Objednávky zákazníka $row->name:"; + + foreach ($row->order_id as $orderId => $order) { + echo "Číslo dokladu: $order->number"; + } +} +``` + + +Prefixy & substituce +==================== + +Názvy tabulek a sloupců mohou obsahovat proměnné části. Ty si nejprve nadefinujeme: + +```php +// vytvoří novou substituci :blog: ==> wp_ +$database->substitute('blog', 'wp_'); +``` + +a poté použijeme v SQL. Všimněte si, že v SQL jsou uvozeny dvojtečkama: + +```php +$database->query("UPDATE [:blog:items] SET [text]='Hello World'"); +// UPDATE `wp_items` SET `text`='Hello World' +``` + + +Datové typy buňek +================= + +Dibi automaticky detekuje typy jednotlivých sloupců dotazu a převádí buňky na nativní typy PHP. Typ můžeme určit i manuálně. Možné typy najdete ve třídě [Dibi\Type |api:Dibi\Type]. + +```php +$result->setType('id', Dibi\Type::INTEGER); // id bude integer +$row = $result->fetch(); + +is_int($row->id) // true +``` + + +Logování +======== + +Dibi má v sobě zabudovaný logger, kterým můžete sledovat všechny vykonané SQL příkazy a měřit délku jejich trvání. Aktivace: + +```php +$database->connect([ + 'driver' => 'sqlite', + 'database' => 'sample.sdb', + 'profiler' => [ + 'file' => 'file.log', + ], +]); +``` + +Šikovnější profiler je panel pro Tracy, který se aktivuje při propojení s Nette. + + +Připojení do [Nette |https://nette.org] +======================================= + +V konfiguračním souboru zaregistrujeme DI rozšíření a přidáme sekci `dibi` - tím se vytvoří potřebné objekty a také databázový panel v [Tracy |https://tracy.nette.org] debugger baru. + +```neon +extensions: + dibi: Dibi\Bridges\Nette\DibiExtension22 + +dibi: + host: localhost + username: root + password: *** + database: foo + lazy: true +``` + +Poté objekt spojení [získáme jako službu z DI kontejneru |https://doc.nette.org/di-usage], např.: + +```php +class Model +{ + private $database; + + public function __construct(Dibi\Connection $database) + { + $this->database = $database; + } +} +``` + + +Komunitní rozšíření +=================== + +Nad Dibi staví nejrůznější knihovny, ORM a rozšíření. Celý jejich seznam najdete na "Packagistu":https://packagist.org/packages/dibi/dibi/dependents?order_by=downloads&requires=require. + + +{{maintitle: Dibi – Šikovná Database Abstraction Library pro PHP}} diff --git a/dibi/cs/@menu.texy b/dibi/cs/@menu.texy new file mode 100644 index 0000000000..271662aad7 --- /dev/null +++ b/dibi/cs/@menu.texy @@ -0,0 +1,4 @@ +- [Úvod | @home] +- "Blog .[link-external]":https://phpfashion.com/category/dibi +- "API .[link-external]":https://api.nette.org/dibi/ +- "GitHub .[link-external]":https://github.com/dg/dibi diff --git a/dibi/cs/@meta.texy b/dibi/cs/@meta.texy new file mode 100644 index 0000000000..49d44d0cfa --- /dev/null +++ b/dibi/cs/@meta.texy @@ -0,0 +1 @@ +{{sitename: Dibi Dokumentace}} diff --git a/dibi/en/@home.texy b/dibi/en/@home.texy new file mode 100644 index 0000000000..a227c5627e --- /dev/null +++ b/dibi/en/@home.texy @@ -0,0 +1,656 @@ +Dibi: Smart Database Abstraction Library for PHP +************************************************ + +To install the latest stable Dibi version, use the [Composer|best-practices:composer] command: + +``` +composer require dibi/dibi +``` + +You can find version overview on the [Releases | https://github.com/dg/dibi/releases] page. + +Requires PHP 8.0 or newer. + + +Connecting to Database +====================== + +The database connection is represented by the [Dibi\Connection|api:] object: + +```php +$database = new Dibi\Connection([ + 'driver' => 'mysqli', + 'host' => 'localhost', + 'username' => 'root', + 'password' => '***', + 'database' => 'table', +]); + +$result = $database->query('SELECT * FROM users'); +``` + +Alternatively, you can use the `dibi` static registry, which maintains a connection object in globally accessible storage and calls all functions on it: + +```php +dibi::connect([ + 'driver' => 'mysqli', + 'host' => 'localhost', + 'username' => 'root', + 'password' => '***', + 'database' => 'test', + 'charset' => 'utf8', +]); + +$result = dibi::query('SELECT * FROM users'); +``` + +In case of a connection error, it throws `Dibi\Exception`. + + +Queries +======= + +We query the database using the `query()` method, which returns [Dibi\Result |api:Dibi\Result]. Rows are returned as [Dibi\Row |api:Dibi\Row] objects. + +You can try all the examples [online at the playground |https://repl.it/@DavidGrudl/dibi-playground]. + +```php +$result = $database->query('SELECT * FROM users'); + +foreach ($result as $row) { + echo $row->id; + echo $row->name; +} + +// array of all rows +$all = $result->fetchAll(); + +// array of all rows, keyed by 'id' +$all = $result->fetchAssoc('id'); + +// associative pairs id => name +$pairs = $result->fetchPairs('id', 'name'); + +// number of result rows, if known, or number of affected rows +$count = $result->getRowCount(); +``` + +The fetchAssoc() method can return [more complex associative arrays |#Result as associative array]. + +You can easily add parameters to the query - note the question mark: + +```php +$result = $database->query('SELECT * FROM users WHERE name = ? AND active = ?', $name, $active); + +// or +$result = $database->query('SELECT * FROM users WHERE name = ?', $name, 'AND active = ?', $active); + +$ids = [10, 20, 30]; +$result = $database->query('SELECT * FROM users WHERE id IN (?)', $ids); +``` + +
+**WARNING: never concatenate parameters into SQL queries, as this would create [SQL injection |https://en.wikipedia.org/wiki/SQL_injection] vulnerability** +/-- +$database->query('SELECT * FROM users WHERE id = ' . $id); // BAD!!! +\-- +
+ +Instead of question marks, you can also use so-called [#modifiers]. + +```php +$result = $database->query('SELECT * FROM users WHERE name = %s', $name); +``` + +In case of failure, `query()` throws either `Dibi\Exception` or one of its descendants: + +- [ConstraintViolationException |api:Dibi\ConstraintViolationException] - violation of some table constraint +- [ForeignKeyConstraintViolationException |api:Dibi\ForeignKeyConstraintViolationException] - invalid foreign key +- [NotNullConstraintViolationException |api:Dibi\NotNullConstraintViolationException] - violation of the NOT NULL condition +- [UniqueConstraintViolationException |api:Dibi\UniqueConstraintViolationException] - collision with unique index + +You can also use shortcut methods: + +```php +// returns associative pairs id => name, shortcut for query(...)->fetchPairs() +$pairs = $database->fetchPairs('SELECT id, name FROM users'); + +// returns array of all rows, shortcut for query(...)->fetchAll() +$rows = $database->fetchAll('SELECT * FROM users'); + +// returns row, shortcut for query(...)->fetch() +$row = $database->fetch('SELECT * FROM users WHERE id = ?', $id); + +// returns cell, shortcut for query(...)->fetchSingle() +$name = $database->fetchSingle('SELECT name FROM users WHERE id = ?', $id); +``` + + +Modifiers +========= + +In addition to the `?` placeholder, we can also use modifiers: + +| %s | string +| %sN | string, but '' translates as NULL +| %bin | binary data +| %b | boolean +| %i | integer +| %iN | integer, but 0 translates as NULL +| %f | float +| %d | date (accepts DateTime, string or UNIX timestamp) +| %dt | datetime (accepts DateTime, string or UNIX timestamp) +| %n | identifier, i.e. table or column name +| %N | identifier, treats period as ordinary character +| %SQL | SQL - directly inserts into SQL (alternative is Dibi\Literal) +| %ex | expands array +| %lmt | special - adds LIMIT to the query +| %ofs | special - adds OFFSET to the query + +Example: + +```php +$result = $database->query('SELECT * FROM users WHERE name = %s', $name); +``` + +If `$name` is `null`, `NULL` is inserted into the SQL statement. + +If the variable is an array, the modifier is applied to all of its elements and they are inserted into SQL separated by commas: + +```php +$ids = [10, '20', 30]; +$result = $database->query('SELECT * FROM users WHERE id IN (%i)', $ids); +// SELECT * FROM users WHERE id IN (10, 20, 30) +``` + +The `%n` modifier is used when the table or column name is a variable. (Beware: do not allow the user to manipulate the content of such a variable): + +```php +$table = 'blog.users'; +$column = 'name'; +$result = $database->query('SELECT * FROM %n WHERE %n = ?', $table, $column, $value); +// SELECT * FROM `blog`.`users` WHERE `name` = 'Jim' +``` + +Four special modifiers are available for the LIKE operator: + +| %like~ | expression starts with string +| %~like | expression ends with string +| %~like~ | expression contains string +| `%like` | expression matches string + +Search for names starting with a certain string: + +```php +$result = $database->query('SELECT * FROM table WHERE name LIKE %like~', $query); +``` + + +Array Modifiers +=============== + +The parameter inserted into an SQL query can also be an array. These modifiers determine how to construct the SQL statement from it: + +| %and | | `key1 = value1 AND key2 = value2 AND ...` +| %or | | `key1 = value1 OR key2 = value2 OR ...` +| %a | assoc | `key1 = value1, key2 = value2, ...` +| %l %in | list | `(val1, val2, ...)` +| %v | values | `(key1, key2, ...) VALUES (value1, value2, ...)` +| %m | multi | `(key1, key2, ...) VALUES (value1, value2, ...), (value1, value2, ...), ...` +| %by | ordering | `key1 ASC, key2 DESC ...` +| %n | names | `key1, key2 AS alias, ...` + +Example: + +```php +$arr = [ + 'a' => 'hello', + 'b' => true, +]; + +$database->query('INSERT INTO table %v', $arr); +// INSERT INTO `table` (`a`, `b`) VALUES ('hello', 1) + +$database->query('UPDATE `table` SET %a', $arr); +// UPDATE `table` SET `a`='hello', `b`=1 +``` + +In the WHERE clause, you can use `%and` or `%or` modifiers: + +```php +$result = $database->query('SELECT * FROM users WHERE %and', [ + 'name' => $name, + 'year' => $year, +]); +// SELECT * FROM users WHERE `name` = 'Jim' AND `year` = 1978 +``` + +See also [#Complex queries]. + +The `%by` modifier is used for sorting - keys specify the columns, and the boolean value determines whether to sort in ascending order: + +```php +$result = $database->query('SELECT id FROM author ORDER BY %by', [ + 'id' => true, // ascending + 'name' => false, // descending +]); +// SELECT id FROM author ORDER BY `id`, `name` DESC +``` + + +Insert, Update & Delete +======================= + +We insert data into SQL queries as associative arrays. Modifiers and the `?` placeholder are not necessary in these cases. + +```php +$database->query('INSERT INTO users', [ + 'name' => $name, + 'year' => $year, +]); +// INSERT INTO users (`name`, `year`) VALUES ('Jim', 1978) + +$id = $database->getInsertId(); // returns the auto-increment of the inserted record + +$id = $database->getInsertId($sequence); // or sequence value +``` + +Multiple INSERT: + +```php +$database->query( + 'INSERT INTO users', + [ + 'name' => 'Jim', + 'year' => 1978, + ], + [ + 'name' => 'Jack', + 'year' => 1987, + ] +); +// INSERT INTO users (`name`, `year`) VALUES ('Jim', 1978), ('Jack', 1987) +``` + +Deleting: + +```php +$database->query('DELETE FROM users WHERE id = ?', $id); + +// returns number of deleted rows +$affectedRows = $database->getAffectedRows(); +``` + +Updating records: + +```php +$database->query('UPDATE users SET', [ + 'name' => $name, + 'year' => $year, +], 'WHERE id = ?', $id); +// UPDATE users SET `name` = 'Jim', `year` = 1978 WHERE id = 123 + +// returns the number of updated rows +$affectedRows = $database->getAffectedRows(); +``` + +Substitute any identifier: + +```php +$database->query('INSERT INTO users', [ + 'id' => $id, + 'name' => $name, + 'year' => $year, +], 'ON DUPLICATE KEY UPDATE %a', [ // here the modifier %a must be used + 'name' => $name, + 'year' => $year, +]); +// INSERT INTO users (`id`, `name`, `year`) VALUES (123, 'Jim', 1978) +// ON DUPLICATE KEY UPDATE `name` = 'Jim', `year` = 1978 +``` + + +Transaction +=========== + +There are four methods for dealing with transactions: + +```php +$database->beginTransaction(); + +$database->commit(); + +$database->rollback(); + +$database->transaction(function () { + // some action +}); +``` + + +Testing +======= + +In order to play with Dibi a little, there is a `test()` method that you pass parameters like to `query()`, but instead of executing the SQL statement, it is echoed on the screen. + +The query results can be echoed as a table using `$result->dump()`. + +These variables are also available: + +```php +dibi::$sql; // the latest SQL query +dibi::$elapsedTime; // its duration in sec +dibi::$numOfQueries; +dibi::$totalTime; +``` + + +Complex Queries +=============== + +The parameter may also be an object `DateTime`. + +```php +$result = $database->query('SELECT * FROM users WHERE created < ?', new DateTime); + +$database->query('INSERT INTO users', [ + 'created' => new DateTime, +]); +``` + +Or SQL literal: + +```php +$database->query('UPDATE table SET', [ + 'date' => $database->literal('NOW()'), +]); +// UPDATE table SET `date` = NOW() +``` + +Or an expression in which you can use `?` or modifiers: + +```php +$database->query('UPDATE `table` SET', [ + 'title' => $database::expression('SHA1(?)', 'secret'), +]); +// UPDATE `table` SET `title` = SHA1('secret') +``` + +When updating, modifiers can be placed directly in the keys: + +```php +$database->query('UPDATE table SET', [ + 'date%SQL' => 'NOW()', // %SQL means SQL ;) +]); +// UPDATE table SET `date` = NOW() +``` + +In conditions (ie, for `%and` and `%or` modifiers), it is not necessary to specify the keys: + +```php +$result = $database->query('SELECT * FROM `table` WHERE %and', [ + 'number > 10', + 'number < 100', +]); +// SELECT * FROM `table` WHERE (number > 10) AND (number < 100) +``` + +Modifiers or placeholders can also be used in expressions: + +```php +$result = $database->query('SELECT * FROM `table` WHERE %and', [ + ['number > ?', 10], // or $database::expression('number > ?', 10) + ['number < ?', 100], + ['%or', [ + 'left' => 1, + 'top' => 2, + ]], +]); +// SELECT * FROM `table` WHERE (number > 10) AND (number < 100) AND (`left` = 1 OR `top` = 2) +``` + +The `%ex` modifier inserts all items of the array into SQL: + +```php +$result = $database->query('SELECT * FROM `table` WHERE %ex', [ + $database::expression('left = ?', 1), + 'AND', + 'top IS NULL', +]); +// SELECT * FROM `table` WHERE left = 1 AND top IS NULL +``` + + +Conditions in SQL Statements +============================ + +Conditional SQL statements are controlled by three modifiers: `%if`, `%else`, and `%end`. The `%if` must be at the end of the string representing SQL and is followed by a variable: + +```php +//$user = ???; + +$result = $database->query(' + SELECT * + FROM table + %if', isset($user), 'WHERE user=%s', $user, '%end + ORDER BY name +'); +``` + +The condition can be supplemented with an `%else` section: + +```php +$result = $database->query(' + SELECT * + FROM %if', $cond, 'one_table %else second_table +'); +``` + +Conditions can be nested within each other. + + +Identifiers and Strings in SQL +============================== + +SQL itself goes through processing to meet the conventions of the given database. Identifiers (table and column names) can be enclosed in square brackets or backticks, and strings in single or double quotes, but the server always sends what the database requires. Example: + +```php +$database->query("UPDATE `table` SET [status]='I''m fine'"); +// MySQL: UPDATE `table` SET `status`='I\'m fine' +// ODBC: UPDATE [table] SET [status]='I''m fine' +``` + +Quotes inside strings in SQL are written by doubling them. + + +Result as Associative Array +=========================== + +Example: returns results as an associative array where the key will be the value of the `id` field: + +```php +$assoc = $result->fetchAssoc('id'); +``` + +The greatest power of `fetchAssoc()` is demonstrated in SQL queries joining several tables with different types of relationships. The database creates a flat table, fetchAssoc restores the shape. + +Example: Let's have a customer and order table (N:M relationship) and query: + +```php +$result = $database->query(' + SELECT customer_id, customers.name, order_id, orders.number, ... + FROM customers + INNER JOIN orders USING (customer_id) + WHERE ... +'); +``` + +And we'd like to get a nested associative array by Customer ID and then by Order ID: + +```php +$all = $result->fetchAssoc('customer_id|order_id'); + +// we will iterate like this: +foreach ($all as $customerId => $orders) { + foreach ($orders as $orderId => $order) { + // ... + } +} +``` + +The associative descriptor has similar syntax to when you write arrays using assignment in PHP. Thus `'customer_id|order_id'` represents the assignment series `$all[$customerId][$orderId] = $row;` sequentially for all rows. + +Sometimes it would be useful to associate by the customer's name instead of their ID: + +```php +$all = $result->fetchAssoc('name|order_id'); + +// elements are then accessed like this: +$order = $all['Arnold Rimmer'][$orderId]; +``` + +But what if there are multiple customers with the same name? The table should have the form: + +```php +$row = $all['Arnold Rimmer'][0][$orderId]; +$row = $all['Arnold Rimmer'][1][$orderId]; +``` + +So we distinguish multiple possible Rimmers using a regular array. The associative descriptor again has a format similar to assignment, with sequential arrays represented by `[]`: + +```php +$all = $result->fetchAssoc('name[]order_id'); + +// we iterate all Arnolds in the results +foreach ($all['Arnold Rimmer'] as $arnoldOrders) { + foreach ($arnoldOrders as $orderId => $order) { + // ... + } +} +``` + +Returning to the example with the `customer_id|order_id` descriptor, let's try to list orders for each customer: + +```php +$all = $result->fetchAssoc('customer_id|order_id'); + +foreach ($all as $customerId => $orders) { + echo "Orders for customer $customerId:"; + + foreach ($orders as $orderId => $order) { + echo "Document number: $order->number"; + // customer name is in $order->name + } +} +``` + +It would be nice to display the customer name instead of ID. But we would have to look it up in the `$orders` array. So let's modify the results to have this shape: + +```php +$all[$customerId]->name = 'John Doe'; +$all[$customerId]->order_id[$orderId] = $row; +$all[$customerId]->order_id[$orderId2] = $row2; +``` + +So, between `$customerId` and `$orderId`, we insert an intermediate element. This time not numbered indexes as we used to distinguish individual Rimmers, but directly a database record. The solution is very similar - just remember that a record is symbolized by an arrow: + +```php +$all = $result->fetchAssoc('customer_id->order_id'); + +foreach ($all as $customerId => $row) { + echo "Orders for customer $row->name:"; + + foreach ($row->order_id as $orderId => $order) { + echo "Document number: $order->number"; + } +} +``` + + +Prefixes & Substitutions +======================== + +Table and column names can contain variable parts. You will first define them: + +```php +// create new substitution :blog: ==> wp_ +$database->substitute('blog', 'wp_'); +``` + +and then use them in SQL. Note that in SQL they are enclosed in colons: + +```php +$database->query("UPDATE [:blog:items] SET [text]='Hello World'"); +// UPDATE `wp_items` SET `text`='Hello World' +``` + + +Field Data Types +================ + +Dibi automatically detects the types of individual query columns and converts cells to native PHP types. We can also specify the type manually. Possible types can be found in the [Dibi\Type |api:Dibi\Type] class. + +```php +$result->setType('id', Dibi\Type::INTEGER); // id will be integer +$row = $result->fetch(); + +is_int($row->id) // true +``` + + +Logging +======= + +Dibi has a built-in logger that lets you track all executed SQL statements and measure the duration of their execution. Activation: + +```php +$database->connect([ + 'driver' => 'sqlite', + 'database' => 'sample.sdb', + 'profiler' => [ + 'file' => 'file.log', + ], +]); +``` + +A more versatile profiler is the Tracy panel, which is activated when connecting to Nette. + + +Connect to [Nette |https://nette.org] +===================================== + +In the configuration file, we register the DI extension and add the `dibi` section - this creates the required objects and also the database panel in the [Tracy |https://tracy.nette.org] debugger bar. + +```neon +extensions: + dibi: Dibi\Bridges\Nette\DibiExtension22 + +dibi: + host: localhost + username: root + password: *** + database: foo + lazy: true +``` + +Then the connection object can be [obtained as a service from the DI container |https://doc.nette.org/di-usage], e.g.: + +```php +class Model +{ + private $database; + + public function __construct(Dibi\Connection $database) + { + $this->database = $database; + } +} +``` + + +Community Extensions +==================== + +Various libraries, ORMs and extensions are built on top of Dibi. You can find a complete list of them on "Packagist":https://packagist.org/packages/dibi/dibi/dependents?order_by=downloads&requires=require. + +{{maintitle: Dibi – Smart Database Abstraction Library for PHP}} diff --git a/dibi/en/@menu.texy b/dibi/en/@menu.texy new file mode 100644 index 0000000000..4add6468f0 --- /dev/null +++ b/dibi/en/@menu.texy @@ -0,0 +1,3 @@ +- [Home | @home] +- "API .[link-external]":https://api.nette.org/dibi/ +- "GitHub .[link-external]":https://github.com/dg/dibi diff --git a/dibi/en/@meta.texy b/dibi/en/@meta.texy new file mode 100644 index 0000000000..b9ca163d2f --- /dev/null +++ b/dibi/en/@meta.texy @@ -0,0 +1 @@ +{{sitename: Dibi Documentation}} diff --git a/dibi/meta.json b/dibi/meta.json new file mode 100644 index 0000000000..ef3653f6bc --- /dev/null +++ b/dibi/meta.json @@ -0,0 +1,5 @@ +{ + "version": "5.x", + "repo": "dg/dibi", + "composer": "dibi/dibi" +} diff --git a/texy/cs/@home.texy b/texy/cs/@home.texy new file mode 100644 index 0000000000..3a23512250 --- /dev/null +++ b/texy/cs/@home.texy @@ -0,0 +1,32 @@ +Texy! je sexy! +============== + +Texy je program, díky kterému můžete snadno, bez odborných znalostí, psát texty na webové stránky. + +Chcete zvýraznit písmo? Vytvořit nadpis či odrážky? Přidat obrázek nebo tabulku? Nemusíte zápasit se složitým textovým editorem. Stačí psát prostý text a Texy už úpravu zvládne za vás. Výsledkem bude hezky zformátovaná stránka. + +--> [Vyzkoušejte si to | https://fiddle.nette.org/texy/] + +Texy dnes používají [tisíce spokojených uživatelů | napsali o Texy]. + + +Co všechno umí? +--------------- + +- vytvářet odkazy, odrážky, tabulky,... +- vkládat do textu obrázky +- zná českou typografii +- a navíc je **zdarma!** (pod licencí BSD a GPL) +- generuje vždy validní HTML kód +- vkládá pevné mezery za jednopísmenné předložky +- je dokonale konfigurovatelné a přizpůsobitelné + + +Objevte Texy! +------------- + +- Srovnání [Texy versus WYSIWYG editory | texy-vs-wysiwyg] +- [Příklady využití | priklady-vyuziti] +- [Základy syntaxe | syntax] + +{{maintitle: Texy – formátovač textů pro PHP}} diff --git a/texy/cs/@menu.texy b/texy/cs/@menu.texy new file mode 100644 index 0000000000..eb7458d858 --- /dev/null +++ b/texy/cs/@menu.texy @@ -0,0 +1,8 @@ +- [úvodní stránka | @home] +- [syntax stručně | syntax] +- [syntax podrobně | syntax-podrobne] +- [fiddle | https://fiddle.nette.org/texy/] +- [manuál | api] +- [blog | https://phpfashion.com/category/texy] +- [API | https://api.nette.org/texy/] +- [GitHub | https://github.com/dg/texy] diff --git a/texy/cs/@meta.texy b/texy/cs/@meta.texy new file mode 100644 index 0000000000..41e2da6970 --- /dev/null +++ b/texy/cs/@meta.texy @@ -0,0 +1 @@ +{{sitename: Texy Dokumentace}} diff --git a/texy/cs/@try.texy b/texy/cs/@try.texy new file mode 100644 index 0000000000..9c443df131 --- /dev/null +++ b/texy/cs/@try.texy @@ -0,0 +1,15 @@ +Vítejte! +-------- + +Můžete používat syntax Texy!, pokud Vám vyhovuje: +- třeba **tučné** písmo nebo *kurzíva* +- a takto se dělá "odkaz":https://texy.info +- více najdete na stránce "syntax":[syntax] + + +Ale také můžete zůstat u HTML: +- takto HTML +- nebo i úplně hloupě, Texy! to pořeší + + +[syntax]: /cs/syntax diff --git a/texy/cs/api-block-module.texy b/texy/cs/api-block-module.texy new file mode 100644 index 0000000000..aae50f9b19 --- /dev/null +++ b/texy/cs/api-block-module.texy @@ -0,0 +1,11 @@ +Třída Texy\Modules\BlockModule +****************************** + +Má na starosti zpracování bloků `/-- xxx`. Modul vypneme zakázáním syntaxe `blocks`: + +/--code php +$texy->allowed['blocks'] = false; + +// nebo pro jednotlivé typy bloků +$texy->allowed['block/code'] = false; +\-- diff --git a/texy/cs/api-blockquote-module.texy b/texy/cs/api-blockquote-module.texy new file mode 100644 index 0000000000..b9fd28e72a --- /dev/null +++ b/texy/cs/api-blockquote-module.texy @@ -0,0 +1,8 @@ +Třída Texy\Modules\BlockQuoteModule +*********************************** + +Má na starosti blokové citace. Modul vypneme zakázáním syntaxe `blockquote`: + +/--code php +$texy->allowed['blockquote'] = false; +\-- diff --git a/texy/cs/api-emoticon-module.texy b/texy/cs/api-emoticon-module.texy new file mode 100644 index 0000000000..8f0f8fa475 --- /dev/null +++ b/texy/cs/api-emoticon-module.texy @@ -0,0 +1,47 @@ +Třída Texy\Modules\EmoticonModule +********************************* + +Má na starosti nahrazování smajlíků za obrázky. Ve výchozím nastavení je modul vypnutý, zapneme jej povolením syntaxe `emoticon`: + +/--code php +$texy->allowed['emoticon'] = true; +\-- + + +Konfigurace +----------- + +|---------------- +| proměnná | typ | výchozí | popis | +|---------------- +| $icons | array | | tabulka všech smajlíků a odpovídajících obrázků +| $class | string | null | CSS třída +| $root | string | | kořenový adresář obrázků na webu +| $fileRoot | string | | kořenový adresář obrázků na disku + +Pokud nenastavíte hodnoty pro `$root` a `$fileRoot`, použijí se ty z modulu [Texy\Modules\ImageModule|api-image-module]. Výchozí seznam smajlíků je tento: + +/--code php +$icons = [ + ':-)' => 'smile.gif', + ':-(' => 'sad.gif', + ';-)' => 'wink.gif', + ':-D' => 'biggrin.gif', + '8-O' => 'eek.gif', + '8-)' => 'cool.gif', + ':-?' => 'confused.gif', + ':-x' => 'mad.gif', + ':-P' => 'razz.gif', + ':-|' => 'neutral.gif', +]; +\-- + +Můžete jej pozměnit přímo zásahem do pole: + +/--code php +$texy->emoticonModule->icons[':-)'] = 'smile.png'; + +unset($texy->emoticonModule->icons[':-P']); +\-- + +Poslední znak smajlíku se může opakovat, tedy klíč. `:-)` akceptuje i smajlík v podobě `:-)))`. diff --git a/texy/cs/api-figure-module.texy b/texy/cs/api-figure-module.texy new file mode 100644 index 0000000000..db0d483886 --- /dev/null +++ b/texy/cs/api-figure-module.texy @@ -0,0 +1,33 @@ +Třída Texy\Modules\FigureModule +******************************* + +Má na starosti obrázky s popiskou. Module vypneme zakázáním syntaxe `figure`: + +/--code php +$texy->allowed['figure'] = false; +\-- + + +Konfigurace +----------- + +|---------------- +| proměnná | typ | výchozí | popis | +|---------------- +| $class | string | `'figure'` | třída neplovoucího kontejneru `
` +| $leftClass | string | null | třída `
` plovoucího vlevo +| $rightClass | string | null | třída `
` plovoucího vpravo +| $widthDelta | int | 10 | offset pro výpočet šířky + + +Neplovoucím kontejnerům `
` bude přiřazena třída `$class`, plovoucím `$leftClass` nebo `$rightClass`. Pokud není specifikována třída u plovoucích kontejnerů, Texy ji sestaví takto: + +`$texy->figureModule->class . '-' . $texy->alignClasses['left'] resp. 'right'` + +Není-li nastavená třída ani v poli `$alignClasses`, Texy kontejner zarovnává CSS vlastností `float`. + +U plovoucích kontejnerů Texy počítá a nastavuje šířků podle vzorce: + +`šířka
= šířka obrázku + $widthDelta` + +Je tedy nutné zjistit šířku obrázku. K tomu je potřeba korektně nastavit cestu `$texy->imageModule->fileRoot`, viz [Texy\Modules\ImageModule | api-image-module]. diff --git a/texy/cs/api-heading-module.texy b/texy/cs/api-heading-module.texy new file mode 100644 index 0000000000..701de25493 --- /dev/null +++ b/texy/cs/api-heading-module.texy @@ -0,0 +1,42 @@ +Třída Texy\Modules\HeadingModule +******************************** + +Má na starosti nadpisy a titulky. Module (de)aktivujeme zakázáním syntaxe: + +/--code php +// podtržené titulky +$texy->allowed['heading/underlined'] = false; + +// ohraničené titulky +$texy->allowed['heading/surrounded'] = false; +\-- + + +Konfigurace +----------- + +|---------------- +| proměnná | typ | výchozí | popis | +|---------------- +| $title | string | null | nejvyšší titulek +| $TOC | array | | zde se vygeneruje obsah +| $generateID | boolean| false | generovat titulkům ID? +| $idPrefix | string | `'toc-'` | prefix pro generované ID +| $top | int | 1 | strop, úroveň nejvyššího titulku +| $moreMeansHigher | boolean | true | více znaků znamená vyšší titulek +| $balancing | int | *dynamic* | způsob vážení titulků +| $levels | array | | tabulka vážení titulků + +Po zpracování textu bude první titulek uložen do proměnné $title (bez HTML kódování, tedy vhodné pro použití v ``). + +Způsob vážení titulků určuje $balancing, které může nabývat hodnot `Texy\Modules\HeadingModule::DYNAMIC` (výchozí) nebo `Texy\Modules\HeadingModule::FIXED`. Více informací [ve fóru | https://forum.texy.info/cs/viewtopic.php?pid=22]. + + +Příklady +-------- + +Nejvyšší titulek bude mít úroveň `<h2>` + +/--code php +$texy->headingModule->top = 2; +\-- diff --git a/texy/cs/api-horizline-module.texy b/texy/cs/api-horizline-module.texy new file mode 100644 index 0000000000..ebbd47da44 --- /dev/null +++ b/texy/cs/api-horizline-module.texy @@ -0,0 +1,8 @@ +Třída Texy\Modules\HorizLineModule +********************************** + +Má na starosti horizontální čáry. Modul vypneme zakázáním syntaxe `horizline`: + +/--code php +$texy->allowed['horizline'] = false; +\-- diff --git a/texy/cs/api-html-module.texy b/texy/cs/api-html-module.texy new file mode 100644 index 0000000000..f925f2ade8 --- /dev/null +++ b/texy/cs/api-html-module.texy @@ -0,0 +1,21 @@ +Třída Texy\Modules\HtmlModule +***************************** + +Má na starosti HTML značky a komentáře na vstupu. Modul vypneme zakázáním syntaxe: + +/--code php +// vypneme HTML značky +$texy->allowed['html/tag'] = false; + +// vypneme HTML komentáře +$texy->allowed['html/comment'] = false; +\-- + + +Konfigurace +----------- + +|---------------- +| proměnná | typ | výchozí | popis | +|---------------- +| $passComment | boolean | true | zobrazit HTML komentáře na výstupu? diff --git a/texy/cs/api-htmloutput-module.texy b/texy/cs/api-htmloutput-module.texy new file mode 100644 index 0000000000..ec049261fa --- /dev/null +++ b/texy/cs/api-htmloutput-module.texy @@ -0,0 +1,17 @@ +Třída Texy\Modules\HtmlOutputModule +*********************************** + +Má na starosti formátování výstupního XHTML / HTML. Formátuje výsledné HTML a zároveň hlídá a koriguje "wellformed" zápis. + + +Konfigurace +----------- + +|---------------- +| proměnná | typ | výchozí | popis | +|---------------- +| $indent | boolean | true | formátovat výstup do úhledné podoby? +| $baseIndent | int | 0 | minimální odsazení každého řádku +| $lineWrap | int | 80 | maximální šířka řádku + +Volitelné koncové značky se odstraňují pouze v režimu HTML. Zalamování řádků lze vypnout nastavením `$texy->htmlOutputModule->lineWrap = false`. diff --git a/texy/cs/api-image-module.texy b/texy/cs/api-image-module.texy new file mode 100644 index 0000000000..bebde249b3 --- /dev/null +++ b/texy/cs/api-image-module.texy @@ -0,0 +1,35 @@ +Třída Texy\Modules\ImageModule +****************************** + +Má na starosti obrázky. Tzv. obrázky s popiskou zpracovává [Texy\Modules\FigureModule|api-figure-module]. Modul vypneme zakázáním syntaxe: + +/--code php +// zákaz obrázků +$texy->allowed['image'] = false; + +// zákaz referencí +$texy->allowed['image/definition'] = false; +\-- + + +Konfigurace +----------- + +|---------------- +| proměnná | typ | výchozí | popis | +|---------------- +| $root | string | `'images/'` | kořenový adresář obrázků na webu +| $linkedRoot | string | `'images/'` | kořenový adresář obrázků v pozici odkazu +| $fileRoot | string | | kořenový adresář obrázků na disku +| $leftClass | string | null | třída obrázku plovoucího vlevo +| $rightClass | string | null | třída obrázku plovoucího vpravo +| $defaultAlt | string | `''` | výchozí hodnota atributu `alt` + + +Fyzická cesta k obrázkům `$fileRoot` se používá ke zjištění jich rozměrů, které se pak uvedou v HTML výstupu. Modul se cestu pokusí detekovat z prostředí serveru, nicméně je vhodnější ji nastavit manuálně. + +Proměnná `$linkedRoot` určuje kořenový adresář obrázků, které jsou použity jako cíl odkazu, tedy `[odkaz | * img.jpg *]`. + +Plovoucím obrázkům je nastavena třída `$leftClass` resp. `$rightClass`, nebo `$texy->alignClasses['left']` resp. `'right'`. Pokud není ani jedno specifikováno, Texy obrázky zarovnává CSS vlastností `float`. + +Protože Texy umí překlápět obrázky při přejetí myškou (onmouseover efekt), je nutné zajistit včasné načtení těchto obrázků (preload). K tomu slouží děsně fikaný skript, který se aktivuje událostí `onload` u jednotlivých obrázků. Skript je uložen v proměnné `$onLoad`. diff --git a/texy/cs/api-link-module.texy b/texy/cs/api-link-module.texy new file mode 100644 index 0000000000..f9fc26e49a --- /dev/null +++ b/texy/cs/api-link-module.texy @@ -0,0 +1,42 @@ +Třída Texy\Modules\LinkModule +***************************** + +Má na starosti definice, reference, odkazy. Modul vypneme zakázáním syntaxe: + +/--code php +// vypnout zpracování definicí [ref]: www.texy.info +$texy->allowed['link/definition'] = false; + +// vypnout zpracování referencí [ref] +$texy->allowed['link/reference'] = false; + +// vypnout dělání www adres klikatelnými +$texy->allowed['link/url'] = false; + +// vypnout dělání emailových adres klikatelnými +$texy->allowed['link/email'] = false; +\-- + + +Konfigurace +----------- + +|---------------- +| proměnná | typ | výchozí | popis | +|---------------- +| $root | string | `''` | kořenový adresář relativních odkazů +| $imageClass | string | | třída pro odkazy vedoucí na obrázky (od Texy 2.2) +| $forceNoFollow | boolean | false | doplňovat `rel="nofollow"`? +| $shorten | boolean | true | zkracovat URL? + +Texy automaticky doplňuje atribut nofollow odkazům, které mají pseudotřídu `nofollow`, např. `"odkaz .[nofollow]":www.texy.info`. + + +Příklad +------- + +Chceme přidávat nofollow ke všem odkazům + +/--code php +$texy->linkModule->forceNoFollow = true; +\-- diff --git a/texy/cs/api-list-module.texy b/texy/cs/api-list-module.texy new file mode 100644 index 0000000000..222f9d94e4 --- /dev/null +++ b/texy/cs/api-list-module.texy @@ -0,0 +1,12 @@ +Třída Texy\Modules\ListModule +***************************** + +Má na starosti číslované, nečíslované a definiční seznamy. Modul vypneme zakázáním syntaxe: + +/--code php +// číslované a nečíslované seznamy +$texy->allowed['list'] = false; + +// definiční listy +$texy->allowed['list/definition'] = false; +\-- diff --git a/texy/cs/api-longwords-module.texy b/texy/cs/api-longwords-module.texy new file mode 100644 index 0000000000..00c5ca765a --- /dev/null +++ b/texy/cs/api-longwords-module.texy @@ -0,0 +1,19 @@ +Třída Texy\Modules\LongWordsModule +********************************** + +Má na starosti rozdělení dlouhých slov. Modul vypneme zakázáním syntaxe `longwords`: + +/--code php +$texy->allowed['longwords'] = false; +\-- + + +Konfigurace +----------- + +|---------------- +| proměnná | typ | výchozí | popis | +|---------------- +| $wordLimit | int | 20 | maximální délka slova + +Texy vkládá do příliš dlouhých slov (nad $wordLimit) značku volitelného zalomení `­`. Snaží se přitom respektovat specifika dělení slov na slabiky. diff --git a/texy/cs/api-paragraph-module.texy b/texy/cs/api-paragraph-module.texy new file mode 100644 index 0000000000..28b10e479e --- /dev/null +++ b/texy/cs/api-paragraph-module.texy @@ -0,0 +1,4 @@ +Třída Texy\Modules\ParagraphModule +********************************** + +Má na starosti jednotlivé odstavce textu. diff --git a/texy/cs/api-phrase-module.texy b/texy/cs/api-phrase-module.texy new file mode 100644 index 0000000000..c978f68adc --- /dev/null +++ b/texy/cs/api-phrase-module.texy @@ -0,0 +1,22 @@ +Třída Texy\Modules\PhraseModule +******************************* + +Má na starosti tzv. fráze, tedy úseky textu (tučný text, odkaz, ...). Můžeme vypínat a zapínat jednotlivé syntaxe: + +/--code php +$texy->allowed['phrase/strong'] = false; +... +\-- + + +Konfigurace +----------- + +|---------------- +| proměnná | typ | výchozí | popis | +|---------------- +| $tags | array | | HTML značky pro jednotlivé fráze +| $linksAllowed | boolean | true | je možné k frázi přidat odkaz? + + +Pod pojmem fráze se rozumí jakákoliv řádková syntax jako `**tučné**`, `//kurzíva//`, `subskript_2`, `[odkaz | www.texy.info`]. diff --git a/texy/cs/api-script-module.texy b/texy/cs/api-script-module.texy new file mode 100644 index 0000000000..0e3ace4d82 --- /dev/null +++ b/texy/cs/api-script-module.texy @@ -0,0 +1,23 @@ +Třída Texy\Modules\ScriptModule +******************************* + +Má na starosti volání uživatelských funkcí a vkládání externích dat. Modul vypneme zakázáním syntaxe `script`: + +/--code php +$texy->allowed['script'] = false; +\-- + + +Konfigurace +----------- + +|---------------- +| proměnná | typ | výchozí | popis | +|---------------- +| $separator | string | `';'` | oddělovat argumentů + + +Příklady +-------- + +Najdete ve [fóru | https://forum.texy.info/cs/viewtopic.php?pid=1954]. diff --git a/texy/cs/api-table-module.texy b/texy/cs/api-table-module.texy new file mode 100644 index 0000000000..6114f24229 --- /dev/null +++ b/texy/cs/api-table-module.texy @@ -0,0 +1,18 @@ +Třída Texy\Modules\TableModule +****************************** + +Má na starosti tabulky. Modul vypneme zakázáním syntaxe `table`: + +/--code php +$texy->allowed['table'] = false; +\-- + + +Konfigurace +----------- + +|---------------- +| proměnná | typ | výchozí | popis | +|---------------- +| $oddClass | string | null | CSS třída přiřazená lichým řádkům tabulky +| $evenClass | string | null | CSS třída přiřazená sudým řádkům tabulky diff --git a/texy/cs/api-texy.texy b/texy/cs/api-texy.texy new file mode 100644 index 0000000000..6eba43a35c --- /dev/null +++ b/texy/cs/api-texy.texy @@ -0,0 +1,69 @@ +Třída Texy\Texy +*************** + +|---------------- +| proměnná | typ | výchozí | popis | +|---------------- +| `$allowed` | mixed | | povolené "Texy syntaxe" +| `$allowedTags` | mixed | *validní značky* | povolené HTML značky +| `$allowedClasses` | mixed | Texy::ALL | povolené CSS třídy a identifikátory +| `$allowedStyles` | mixed | Texy::ALL | povolené CSS styly +| `$alignClasses` | array | *vynulované* | CSS třídy pro zarovnání textu a obrázků +| `$mergeLines` | boolean | true | spojovat řádky? +| `$tabWidth` | int | 8 | šířka tabulátorů kvůli převední na mezery +| `$obfuscateEmail` | boolean| true | maskovat emailové adresy před roboty? +| `$urlSchemeFilters` | array| null | + + +Proměnné `$allowedTags`, `$allowedClasses` a `$allowedStyles` mohou nabývat hodnot: + +- `Texy::ALL` - jsou povoleny všechny HTML značky resp. styly resp. třídy +- `Texy::NONE` - naopak jsou všechny zakázány +- *array* - výčet povolených hodnot + - `$allowedTags` - povolené značky tvoří klíče, viz příklady níže + - `$allowedClasses` - seznam tříd a ID, přičemž ID začínají prefixem # + - `$allowedStyles` - seznam CSS vlastností + +Pole `$alignClasses` definuje CSS třídy pro zarovnání textu a obrázků. Blíže popsáno [ve fóru | https://forum.texy.info/cs/viewtopic.php?id=532]. + +Texy spojuje řádky následující za sebou do odstavců. Toto chování je možné vypnout nastavením vlastnosti `$texy->mergeLines = false`. + + +Příklady +-------- + +Povolíme pouze HTML elementy `<strong>, <div>, <a>` a některé jejich atributy: + +/--code php +$texy->allowedTags = [ + 'strong' => Texy::NONE, // <strong> nesmí mít žádné attributy + 'div' => Texy::ALL, // <div> může mít jakékoliv atributy + 'a' => ['href', 'lang', 'target'], // <a> může mít jen tyto atributy +]; +\-- + +Všechny HTML značky zakážeme: + +/--code php +$texy->allowedTags = Texy::NONE; +\-- + +Povolíme pouze CSS třídy `class1, class2` a CSS identifikátory `id1, id2` + +/--code php +$texy->allowedClasses = ['class1', 'class2', '#id1', '#id2']; +\-- + +Povolíme pouze CSS vlastnosti `font-size, color, width` + +/--code php +$texy->allowedStyles = ['font-size', 'color', 'width']; +\-- + +Místo přímých stylů `style="text-align:left"` apod. používej třídy `class="left"` apod. + +/--code php +$texy->alignClasses['left'] = 'left'; +$texy->alignClasses['right'] = 'right'; +... // dále možno definovat: center, justify, top, bottom, middle +\-- diff --git a/texy/cs/api-typography-module.texy b/texy/cs/api-typography-module.texy new file mode 100644 index 0000000000..a66748609f --- /dev/null +++ b/texy/cs/api-typography-module.texy @@ -0,0 +1,21 @@ +Třída Texy\Modules\TypographyModule +*********************************** + +Má na starosti typografické úpravy výsledného textu. Modul vypneme zakázáním syntaxe `typography`: + +/--code php +$texy->allowed['typography'] = false; +\-- + + +Konfigurace +----------- + +|---------------- +| proměnná | typ | výchozí | popis | +|---------------- +| $locale | string | `'cs'` | určení národních specifik +| static $locales | array | | předvolená specifika + + +Vlastnost $locale může nabývat hodnot: cs, en, fr, de, pl. Další specifika lze doplnit do statické proměnné $locales. diff --git a/texy/cs/api-zaklady.texy b/texy/cs/api-zaklady.texy new file mode 100644 index 0000000000..3672e3ba65 --- /dev/null +++ b/texy/cs/api-zaklady.texy @@ -0,0 +1,25 @@ +Základní dovednosti +******************* + +Jak přeformátovat text do HTML? Stačí do kódu začlenit knihovnu Texy, například pomocí Composeru: + +/-- +composer require texy/texy +\-- + +A vytvořit objekt `$texy = new Texy\Texy;`. Celý převod obstará metoda `$html = $texy->process($text)`, kde proměnná `$text` obsahuje vstupní text a vrací se zformátovaný HTML výstup. + +/--php +// vytvoříme objekt +$texy = new Texy\Texy; + +// můžeme jej nakonfigurovat +$texy->imageModule->root = 'images/'; + +// a zpracujeme vstupní $text +$html = $texy->process($text); +\-- + +Pokud potřebujete formátovat jednořádkový text (tedy bez blokových elementů), použijte `$html = $texy->processLine($text)`. + +V ukázce vidíte, jak je možné objekt `$texy` konfigurovat. Protože parametrů je hodně, jsou rozčleněny do logických celků označovaných jako moduly. Instance každého modulu je uložena v atributu `$texy->blockModule`, `$texy->emoticonModule` atd. (viz [jednotlivé moduly | api#moduly]). diff --git a/texy/cs/api.texy b/texy/cs/api.texy new file mode 100644 index 0000000000..e0d5c9e4db --- /dev/null +++ b/texy/cs/api.texy @@ -0,0 +1,28 @@ +Programátorský manuál +********************* + +Texy je napsané v objektovém PHP. Minimální požadovaná verze pro Texy 3.0 je PHP 7.1. + +--> [Základní dovednosti | api-zaklady] + +--> [API dokumentace | https://api.nette.org/texy/] + +--> Jednotlivé moduly: .[#moduly] +- [Texy\Texy | api-texy] - jádro Texy +- [Texy\Modules\BlockModule | api-block-module] - zpracování bloků `/-- xxx` +- [Texy\Modules\BlockQuoteModule | api-blockquote-module] - blokové citace +- [Texy\Modules\EmoticonModule | api-emoticon-module] - nahrazování smajlíků za obrázky +- [Texy\Modules\FigureModule | api-figure-module] - obrázky s popiskou +- [Texy\Modules\HeadingModule | api-heading-module] - nadpisy, titulky +- [Texy\Modules\HorizLineModule | api-horizline-module] - horizontální čáry +- [Texy\Modules\HtmlModule | api-html-module] - HTML značky a komentáře na vstupu +- [Texy\Modules\HtmlOutputModule | api-htmloutput-module] - formátování výstupního HTML +- [Texy\Modules\ImageModule | api-image-module] - obrázky +- [Texy\Modules\LinkModule | api-link-module] - odkazy a reference +- [Texy\Modules\ListModule | api-list-module] - číslované, nečíslované a definiční seznamy +- [Texy\Modules\LongWordsModule | api-longwords-module] - rozdělení dlouhých slov +- [Texy\Modules\ParagraphModule | api-paragraph-module] - jednotlivé odstavce textu +- [Texy\Modules\PhraseModule | api-phrase-module] - fráze, tedy úseky textu (tučný text, odkaz, ...) +- [Texy\Modules\ScriptModule | api-script-module] - volání uživatelských funkcí +- [Texy\Modules\TableModule | api-table-module] - tabulky +- [Texy\Modules\TypographyModule | api-typography-module] - typografické úpravy výsledného textu diff --git a/texy/cs/napsali-o-texy.texy b/texy/cs/napsali-o-texy.texy new file mode 100644 index 0000000000..c5906f0ba8 --- /dev/null +++ b/texy/cs/napsali-o-texy.texy @@ -0,0 +1,160 @@ +Napsali o Texy +************** + +{{nofollow:yes}} + +> Při volbě formátovače textu pro poslední dva weby jsme zkusili oproti dříve používaným WYSIWYG editorům implementovat systém Texy Davida Grudla, a nestačili jsme se divit. Neuvěřitelně komplexní formátovací možnosti, úžasná podpora české typografie a předem připravené instalační balíčky dělají Texy vynikajícím publikačním doplňkem. +> +> [Jan Brašna Alphanumeric | http://www.alphanumeric.cz] (3. 5. 2005) + + +> Dobrý den, s Texy jsem neuvěřitelně spokojen. Mnohokráte děkuji. +> +> Využíváme Texy jak na firemních stránkách www.logio.cz v sekci Novinky tak na našem novém projektu www.skladuj.cz. +> +> Dokonce si někteří kolegové navykli posílat příspěvky již předformátované v emailu. Což je neuvěřitelné. +> +> [Tomáš Formánek | http://www.skladuj.cz] (10. 4. 2006) + + +> Zdravím. Texy jsem začal používat na nokturno.net - je to luxusní věcička, hlavně dá minimálně práce zakomponovat jej do systému. +> +> [Jiří Reiter | http://www.nokturno.net] (5. 3. 2006) + + +> Použil jsem jej pro formátování aktuálních zpráviček na našem firemním webu. Celé zahrnutí trvalo cca hodinu, včetně pochopení o co jde a zavedení příznaku pro přepínání pro starší zprávy v HTML. Zadávání je teď výrazně intuitivnější a je menší riziko "rozhození" formátování stránek při ev. chybě v textu zprávy. +> +> Brilantní kus kódu, jak návrh, tak realizace. +> +> [Ing. Zdeněk Trojánek | http://www.daisy.cz] (3. 3. 2006) + + +> Nejprve jsem chtěl do svého implementovat nějaký wysiwyg editor, ale našel jsem Texy. +> +> Něco podobného jsem zatím nevidel, uplně nadchnul. Dokud nevyzkoušíte neuvěříte. +> +> [Petr Čada | http://error414.php5.cz/] (24. 11. 2005) + + + +> Texy je velmi šikovná a praktická věc, která dokáže i překvapit... spokojenost je určitě na místě. +> +> [Petr Vlček | http://saabinfo.net] (4. 10. 2005) + + +> Na Texy ma prekvapila jeho komplexnosť a sila. Umožňuje formátovať text akokoľvek len chcete, pritom dbá aj na správne postavenie predložiek a rozdelenie dlhých slov atď. Rozhodne Texy vyskúšajte. +> +> [Michal Poppe | http://www.mipo.ssag.sk/zapisnik/webowiny/2005-02-08-texy-konecne-vonku.html] (8. 2. 2005) + + +> Texy jsem implementoval do nekomerční obrázkové encyklopedie. Texy se mi stará o doprovodné texty k tématickým sekcím a já mám z toho, jak to dělá (dělá to hezky sexy ;-) ), **velikou radost**. Texy mi ušetří čas, a tak mám Texy rád a autorovi za něj děkuji tímto a ikonkou. +> +> Hlavně oceňuji logickou a jenoduchou syntaxi, jednoduchou implementaci do jiných php systémů, komplexnost. :) +> +> [Robert Nový | http://www.jablicko.cz] (18. 4. 2005) + + +> Texy používám už delší dobu jako svou hlavní pomůcku pro převod textů do HTML, což dělám v práci vlastně denně. +> +> [Jirka Chomát | http://www.chomat.net/articles/trublog] (5. 3. 2005) + + +> Ano je to tak. Skutečně používáme tento skvělý "převaděč textu do formátovaného HTML kódu". +> +> [WordPress CZ | http://wordpress.cz] (24. 2. 2005) + + +> **Elegance v phpRS .. to je Texy** Osobně mi vůbec nevadí psát příspěvky včetně TAGů, mám potom vše pod kontrolou a vím "wo co de !". Proč si ale neušetřit práci použitím formátovače Texy. Přeci jen jsem občas líný tvor a Texy je podle mě opravdu super. Celá operace "zasunutí" Texy do phpRS je velice jednoduchá +> +> [Pykaso | http://pykaso.net/?article=elegance-v-phprs-to-je-texy] (11. 3. 2005) + + +> Texy, skvělý nástroj od Davida Grudla (dgx), který usnadní práci nejen pisálkům, ale i těm, kteří komentují, jsem původně zamýšlel používat pouze k formátování komentářů - ode dneška jej používám i k formátování mnou napsaných článků. +> +> A co mě k tomu vedlo? Pohodlost! Člověk by nevěřil, jak je všechno najednou jednoduché +> +> [Luboš Bretschneider | http://www.bretik.com/?page=article&article=Texy-je-sexy-Texy-je-cool] (2. 3. 2005) + + +> Texy jsem si zaimplementoval do webu spíš jen tak. Chtěl jsem ho vyzkoušet a napadlo mě, že to můžu zkusit rovnou v reálu. Nečekal jsem nic nepřevratného, a to byla chyba. Texy mě úplně vzalo. +> +> Dnes už vůbec neuvažuji nad WYSIWYG editorem. Texy je pro mě jasná volba pro jednoduché, ale i složité formátování textů do XHTML. Což je věc, kterou Texy zvládá na jedničku! +> +> [Lukáš Knop, Knopdesign | http://www.knopdesign.net] (17. 3. 2005) + + +> **Texy je opravdu sexy** Texy využívám i já. Texy totiž není program jen pro neznalé HTML a počítačové analfabety, ale i pro ostřílené webdevelopery. Dnes jsem ho využil k převedení dlouhého textu do kódu pro jedny stránky, na kterých teď usilovně pracuji. Usnadní mi nudnou práci a tím pádem jsem o něco efektivnější... +> +> [Ondřej Kůrka | http://bernardyn.bloguje.cz/109088_item.php/] (1. 2. 2005) + + +> Články se publikují v podstatě sami, protože využívám Texy, jehož stvořitelem je David Grudl. +> +> [Lazy Byte | http://lazybyte.wz.cz/blog/za%c4%8dinam-blogovat] (6. 3. 2005) + + +> Kód je napsán hezky objektově a přehledně, navíc řekl bych i hodně univerzálně, autor s řadou věcí počítá a tak je radost s Texy pracovat. Podpora UTF-8 hned v základu a hlavně dgx vážně nekecal, když psal, že zapracování do kódu bude snadné. +> +> [Vojtěch Schlesinger | http://www.php-weblog.com] (1. 2. 2005) + + +> Budu se ale muset hodně ovládat, abych nepsal s dokonalou Texy syntaxí ... tedy ne že bych ji já psal dokonale, ale že ona je dokonalá. S klidem přiznám, že jsem z Texy už několik dní nepokrytě nadšený. Takový vybroušený kousek php kódu jsem ještě neviděl. +> +> [Juneau | http://reality-show.net/?text=486-a-tak-si-mezi-programovanim-blognu] (26. 2. 2005) + + +> Texy hodnotím výborně, velice mi usnadňuje psaní článků. A plugin pro BLOG:CMS je taky super věc! :-) DĚKUJU ZA TEXY! :-) +> +> [Miroslav Navrátil | http://kanevinternetu.blacksuns.net/] (14. 3. 2005) + + +> ... umožní jednoduché a intuitivní formátování textu bez znalosti HTML, čistě za použití plain textu. ... Implementace systému do existující PHP aplikace už snad ani nemůže být jednodušší, stačí includovat jeden soubor a vytvořit jeden objekt, Texy se postará o zbytek +> +> [Adam Šindelář, Root.cz | http://www.root.cz/clanky/nova-softwarova-sklizen-16-3-2005/] (16. 3. 2005) + + +> Jsem se zas jednou nudil, serfoval po netu a narazil na Texy, mno a to mě tak nadchlo až jsem z toho začal předělávat celej webík. Texy vřele doporučuji všem, kteří jsou aspoň z poloviny tak líní jako já. Je vhodný jak pro laiky tak pro zkušené programátory. Je prostě sexy! +> +> [Rozi.net | http://www.rozi.net/text-32.html] (11. 3. 2005) + + +> Izsak's Weblog používa na formátovanie článkov a komentárov nový, jednoduchý a komplexný systém Texy. +> +> [Jozef Izso | http://www.izsak.net/weblog/47/prechod-na-textpattern] (23. 2. 2005) + + +> Zdravím! Texy využívám v mém blogu, sám bych texy asi nedokázal zasadit do nějakého rs, ale RS2 ho obsahuje a tak ho využívám, jsem naprosto spokejen, texy mi vyhovuje, práce s ním je hned příjemnější. Přeji hodně úspěchů. +> +> [Martin Světlík alias QuickShare | http://blog.msvetlik.com] (20. 4. 2006) + +> Cau, ted sem se dostal k Texy! Zatim pouzivam WYSIWYG editor napsany v JS. Dobry, jen nekdy pomaly a ten kod taky nic moc. Navic JS pouzivam nerad. Cetl sem si jak je to udelany a musim rict ze uvazuju nad tim ze bych to cely nahradil :o) +> +> Kanadsky bod pro tebe...kdyz sem se dival na formatovani tabulek... no musel jsi s tim mit strasnou praci. +> +> Keep on ;) +> +> [Marek | liq@quick.cz] (17. 11. 2005) + + +> Konečně mám (po hokeji) zase jednou důvod být hrdý, že jsem Čech, stejně jako autor Texy ;) Moc pěkný kousek software! Smekám... +> +> [Pavel Beníšek | http://www.3dgrafika.cz] (17. 3. 2005) + + +Dále Texy používá +----------------- + +- síť obchodů [Internet Mall | http://www.mall.cz/] +- [H1.cz | http://www.h1.cz/] +- [Vitalita | http://www.vitalita.cz] +- [Václavák | http://www.vaclavak.net] +- [Rarouš weblog | http://rarous.net/] (běží na ASP.NET) +- [La Trine | https://www.latrine.cz] +- **...a stovky dalších webů** + + +Texy najdete v sytémech: +------------------------ + +- [Český TextPattern | http://www.vaclavak.net/weblog/23/textpattern-pro-ceske-prostredi] +- Český WordPress diff --git a/texy/cs/priklady-vyuziti.texy b/texy/cs/priklady-vyuziti.texy new file mode 100644 index 0000000000..f71b9616dc --- /dev/null +++ b/texy/cs/priklady-vyuziti.texy @@ -0,0 +1,26 @@ +Příklady využití +**************** + + +Běžní uživatelé .[#bfu] +----------------------- + +Texy původně vznikl jako nástroj, který umožnil i uživatelům neznalým HTML **snadno editovat obsah** webových stránek. Záměrem bylo vytvořit silnou **alternativu k WYSIWYG** editorům, které se v praxi [ukazují jako neefektivní | texy-vs-wysiwyg]. + +Běžný uživatel se může plně věnovat psaní "čistého textu .(například v Poznámkovém bloku)[about]", který si formátuje velmi [přirozeným způsobem | syntax]. A nemusí se téměř nic nového učit. + + +Zkušení pisatelé .[#experienced] +-------------------------------- + +Zkušení tvůrci internetového obsahu, jakými jsou například bloggeři, často jazyk HTML znají. Ale psát články přímo v něm je nepříjemné a proto si zjednodušují práci používáním chytrých editorů. Jedním z nich je i Texy Je navíc dostupný i přes webové rozhraní a nabízí **neobvykle vysoký konfort**. + +Díky Texy se autor může plně věnovat obsahu dokumentu a nemusí uvažovat nad HTML nebo typografickou úpravou. Texy dokáže psaní výrazně zjednodušit, přitom pokročilého uživatele nijak neomezuje - nabízí mu **vkládat i HTML značky** a CSS formátování. + + +Komentáře a diskuzní fóra .[#comments] +-------------------------------------- + +Texy počítá i s nasazením jako formátovač příspěvků v diskuzních fórech a komentářích. Přispívatelé mohou používat jednotnou a **intuitivní syntaxi** a programátorům **odpadne náročná práce** na vlastním formátovači. + +Tato oblast použití je charakteristická tím, že vyžaduje mnohem **přísnější kontrolu** vstupů. Texy proto obsahuje mechanismy, které zakáží nebo omezí použití určitých HTML značek (a jejich atributů), kaskádových stylů a tříd atd. diff --git a/texy/cs/syntax-podrobne.texy b/texy/cs/syntax-podrobne.texy new file mode 100644 index 0000000000..d10b62068c --- /dev/null +++ b/texy/cs/syntax-podrobne.texy @@ -0,0 +1,889 @@ +Podrobný popis syntaxe +********************** + + +- [#Filozofie] +- [#Odstavce textu] +- [#Titulky] +- [#Horizontální čáry] +- [#Kód] +- [#Vypnutí Texy] +- [#Citace] +- [#Odkazy] +- [#Obrázky] +- [#Fráze] +- [#Přímé HTML] +- [#Seznamy] +- [#Modifikátory] +- [#Typografie] +- [#Rozdělení velmi dlouhých slov] +- [#Tabulky] + + +Filozofie +========= + +Nástroj Texy vznikl proto, aby nezkušeným uživatelům umožnil snadno editovat obsah webových stránek. Proto je i syntaxe maximálně intuitivní. Záměrem je, aby text v čisté (nezformátované) formě byl přehledný a jeho formát tušitelný. + +Dnes Texy výborně slouží i zkušeným znalcům jazyka HTML. Dovoluje volně kombinovat Texy zápis s HTML značkami. Zkušení uživatelé se tedy nemusí učit nový meta-jazyk a plně využít svých znalostí. Texy jim pouze zjednodušuje práci. + +Prvotní logikou syntaxe je **žádnou syntaxi nepoužívat**. Jen psát čistý text. Vkládání rozšířených informací, jako třeba CSS třídy nebo odkazy, nenaruší tok textu. A zapíší se způsobem, který snadno pochopí i netechnicky založení uživatelé. + + +Odstavce textu +============== + +Za odstavec se považuje jeden nebo více bezprostředně za sebou následujících řádků textu. Odstavečky jsou od sebe oddělené prázdným řádkem. + +/--code texy +První odstavec lorem ipsum dolor sit amet. + +Druhý odstavec, který tvoří jeden řádek. +A druhý řádek textu. Texy je spojí. +\-- + +/--texysource +První odstavec lorem ipsum dolor sit amet. + +Druhý odstavec, který tvoří jeden řádek. +A druhý řádek textu. Texy je spojí. +\-- + +*V editačním políčku webové stránky (textarea) není rozdělení odstavce na dva řádky patrné. Proto je i Texy považuje za jeden odstavec.* + +Zalomení řádku v odstavci docílíte vložením jedné mezery vlevo: + +/--code texy +Kdoví jestli + jestli jsou na měsíci vůbec nějaký stopy + a proč kope kolem sebe kdo se topí + jakej sval to Zemí otáčí +\-- + +/--texysource +Kdoví jestli + jestli jsou na měsíci vůbec nějaký stopy + a proč kope kolem sebe kdo se topí + jakej sval to Zemí otáčí +\-- + + +Titulky +======= + +Titulky je možné zapsat hned dvěma způsoby: **podtržením** nebo **předsazením**. + +Každý titulek má svůj stupeň. V případě **podtržení** o důležitosti titulku rozhoduje podtrhávací znak. Od nejvyšší po nejnižší jsou to tyto: `#` `*` `=` `-` + +/--code texy +Hlavní titulek +************** + + +Podtitulek +========== +\-- + +/--texysource +Hlavní titulek +************** + + +Podtitulek +========== +\-- + +U titulků zapsaných **předsazením** určuje úroveň počet předsazených znaků. A ty mohou být `#` nebo `=` + +Platí: čím více znaků, tím důležitější titulek (minimum jsou dva znaky, maximum sedm). + +/--code texy +=== Hlavní titulek === + +## Podtitulek +\-- + +Jak vidíte v případě podtitulku, znaky vpravo je možné vynechat. + +*Stupně titulků jsou vždy jen relativní! Tedy Texy najde nejvyšší použitý titulek a ostatní titulky relativně od něj odstupňuje.* + + +Horizontální čáry +================= + +Texy zná tyto způsoby zápisu: + + +/--code texy +------------ + +******** +\-- + + +/--texysource +------------- + +******** +\-- + + +Kód +=== + +Používá se pro vložení zdrojového kódu. Použitím přídavného modulu lze aktivovat i zvýrazňování syntaxe. + +/--code texy + /---code php + function reImage($matches) { + $content = $matches[1]; + $align = $matches[5]; + $href = $matches[6]; + } + \--- +\-- + +/--texysource + /---code php + function reImage($matches) { + $content = $matches[1]; + $align = $matches[5]; + $href = $matches[6]; + } + \--- +\-- + +*Všimněte si slova `php` pro označení jazyka.* + + +Vypnutí Texy +============ + +Klíčové slovo `html` nebo `text` ovlivňuje, jestli obsah bude chápán jako HTML (včetně značek), nebo prostý text. + +/--code texy + /---html + <em>příklad</em>: **this is not strong** + \--- + + + /---text + <em>příklad</em>: **this is not strong** + \--- +\-- + +Pro inline vypnutí Texy je možné použít dvojitý apostrof `''` a obalit s ním část textu, který nemá být Texy zpracováván. + +/--code texy + Příklad: ''**this is not strong**'' +\-- + + +Rozdělování do bloků (div) +========================== + +Tuto schopnost využijete při tvorbě složitějších dokumentů. + +/--code texy + /---div .[header] + + content of div + + \--- +\-- + +/--texysource + /---div .[header] + + content of div + + \--- +\-- + + +Je možné bloky i vnořovat: + +/--code texy + /---div .[header] + + ## This is a header. + + /---div + vnořený div + \--- + + Texy je sexy! + + \--- +\-- + +/--texysource + /---div .[header] + + ## This is a header. + + /---div + vnořený div + \--- + + Texy je sexy! + + \--- +\-- + + +Citace +====== + +Citace jsou odsazené, podobně jako v emailech, znakem `>` + +/--code texy +> This is a blockquote with two paragraphs. +> +> 640 K should be enough for everyone +\-- + +/--texysource +> This is a blockquote with two paragraphs. +> +> 640 K should be enough for everyone +\-- + + +Odkazy +====== + +Odkazy se zapisují tak, že odkazující text uzavřete do uvozovek a následujete dvojtečkou a URL. Texy se snaží inteligentně odhadnout konec URL. Můžete mu i pomoci tím, že URI uzavřete do hranatých závorek. Část `http://` není povinná. + +Jako odkaz je možné vkládat i emaily, Texy je transformuje do podoby, která by měla zmást spamboty. + +/--code texy +Look at homepage:[https://texy.info]. + +Do you know "La Trine":https://www.latrine.cz? + +"Write me":me@example.com +\-- + +/--texysource +Look at homepage:[https://texy.info]. + +Do you know "La Trine":https://www.latrine.cz? + +"Write me":me@example.com +\-- + + +Reference +--------- + +Aby se tok textu "neznečišťoval" vkládáním URL, je možné všechny adresy uvést na jednom místě a pak se na ně jen odkazovat. Tomu se říká reference. Kromě adresy je možné doplnit i text odkazu a [modifikátor | #modifier]. + +/--code texy + [homepage]: https://texy.info/ Texy .(homepage) + [nette]: http://nette.org + +This is [homepage] + +Look at "this site":[nette] +\-- + + +Obrázky +======= + +Zapisují se mezi hranaté závorky s hvězdičkou: + +/--code texy +[* image.gif *] +\-- + +/--texysource line +[* image.gif *] +\-- + +V textových odstavcích je často třeba zvolit, má-li být obrázek zarovnán k levému nebo pravému kraji. Toho docílíte pomocí znaku `<` a `>` použitého před pravou závorkou: + +/--code texy +[* image.gif <] Left-aligned image + +[* image.gif >] Right-aligned image +\-- + +/--texysource +[* image.gif <] Left-aligned image + +[* image.gif >] Right-aligned image +\-- + +*Poznámka: V uvedeném příkladu Texy použil pro zarovnání přímý styl. Je možné systém nakonfigurovat tak, aby místo přiřadil obrázkům zvolenou třídu.* + +*Poznámka: pro všechny (relativní) URL obrázků je možné nastavit výchozí adresář. V uvedeným příkladech to byl `images/`, proto v Texy není adresář uveden, zatímco ve vygenerovaném HTML ano.* + +*Poznámka: pokud není implicitně určen alternativní text (jak na to viz níže), použije Texy výchozí. Zde je to prosté `image`* + + +Rozměry +------- + +U lokálních obrázků Texy zjistí rozměry automaticky. Pokud je chcete určit ručně, zapište je takto: + +/--code texy +[* image.gif 10x20 *] +\-- + +/--texysource line +[* image.gif 10x20 *] +\-- + + +Modifikátory +------------ + +O nich se více dozvíte v [jiné kapitole | #modifier], ale neuškodí si ukázat, jak se u obrázků zapisují. Zkusme si modifikátor pro určení alternativního textu a třídy: + +/--code texy +[* image.gif .(alt text)[foto] *] +\-- + +/--texysource line +[* image.gif .(alt text)[foto] *] +\-- + + +Reference +--------- + +Ze stejných důvodů, jako u odkazů, je i obrázky možné zapisovat pomocí referencí. Je třeba definovat URL (nebo více URL oddělených `|`) a případně i modifikátory. + +/--code texy +What a beautiful girl [* picture*] ! + +[* picture*]: image.gif .(my girl) +\-- + +/--texysource +What a beautiful girl [* picture*] ! + +[* picture*]: image.gif .(my girl) +\-- + + +Obrázek s popiskou +------------------ + +Za obrázkem uveďte tři hvězdičky a následuje popiska: + + +/--code texy +[* image.gif *] *** Toto je *popiska* pod obrázkem +\-- + +/--texysource +[* image.gif *] *** Toto je *popiska* pod obrázkem +\-- + + +Fráze +===== + +Asi nejpoužívanější syntax v Texy. Téměř ve všech případech se používá zdvojený znak. + +/--code texy +//kurzíva// + +*taky kurzíva* + +**tučné** + +superscript^2 vs. subscript_2 +\-- + +/--texysource +//kurzíva// + +*taky kurzíva* + +**tučné** + +superscript^2 vs. subscript_2 +\-- + +/--div .[output] +//kurzíva// + +*taky kurzíva* + +**tučné** + +***nejsilněji zdůrazněné*** + +superscript^2 vs. subscript_2 +\-- + +Speciálním případem fráze je tzv. kód. Od ostatních se liší tím, že jeho obsah nebude nadále formátován a zobrazí se doslovně: + +/--code texy +Odstraňte `<br />` a entitu `&ndash` +\-- + +/--texysource +Odstraňte `<br />` a entitu `&ndash` +\-- + +*Poznámka: jestli se použije element `<code>` nebo jiný (případně žádný) je možné rozhodnout pouhou konfigurací Texy* + + +S modifikátorem +--------------- + +Je možné jej vložit do každé fráze, vždy těsně před uzavírací znak: + +/--code texy +**silný a zelený .{color:green}** jako Hulk +\-- + +/--texysource +**silný a zelený .{color:green}** jako Hulk +\-- + +/--div .[output] +**silný a zelený .{color:green}** jako Hulk +\-- + + +Přímé HTML +========== + +Texy není náhrada za HTML. Nehledá ani alternativní způsoby zápisu HTML. Cílem je zjednodušit psaní obsahu. Pokud se Vám zdá jednodušší zapsat některou strukturu přímo v HTML, můžete tak učinit. HTML značky jsou plně podporované. + +/--code texy +This <strong class=info>is strong</strong> text. +<br> This is not. +\-- + +/--texysource +This <strong class=info>is strong</strong> text. +<br> This is not. +\-- + +*Poznámka: všimněte si, že Texy upraví zápis atributů a značek tak, aby byly validní (i pro XHTML výstup). Stejně tak dbá na **well-formed zápis**!* + +*Poznámka: Rozhodování, která značky a které atributy můžou být v textu použity, je plně uživatelsky ovladatelné. Demonstruje to jeden příklad z distribuce.* + + +Seznamy +======= + +Odrážkové seznamy zapisujeme pomocí `*` `+` nebo `-`. Musí být zapsán hned na začátku řádku a za ním musí následovat mezera. + +/--code texy +- Red +- Green +- Blue +\-- + +/--texysource +- Red +- Green +- Blue +\-- + +/--div .[output] +- Red +- Green +- Blue +\-- + + +Číslované seznamy +----------------- + +Texy zná těchto pět způsobů zápisu (první dva jsou ekvivalentní): + +/--code texy +1) Učit se +2) Učit se +3) Učit se + +a) Dlouhý +b) Široký +c) Krátkozraký + +A) DOS +B) Windows +C) Linux + +I) Yesterday +II) Today +III) Tomorrow +\-- + +/--texysource +1) Učit se +2) Učit se +3) Učit se + +a) Dlouhý +b) Široký +c) Krátkozraký + +A) DOS +B) Windows +C) Linux + +I) Yesterday +II) Today +III) Tomorrow +\-- + +/--div .[output] +1) Učit se +2) Učit se +3) Učit se + +a) Dlouhý +b) Široký +c) Krátkozraký + +A) DOS +B) Windows +C) Linux + +I) Yesterday +II) Today +III) Tomorrow +\-- + + +Vnořené seznamy +--------------- + +/--code texy +a) Bird + I) Bird + - Red + - Green + - Blue + II) McHale + III) Parish +b) McHale +c) Parish + 1) Bird + 2) McHale + 3) Parish +\-- + +/--texysource +a) Bird + I) Bird + - Red + - Green + - Blue + II) McHale + III) Parish +b) McHale +c) Parish + 1) Bird + 2) McHale + 3) Parish +\-- + + +Definiční seznam +---------------- + +/--code texy +Koncert Divokej Bill: + - termín: 9. 12. 2004 + - místo: Hala Vodová, Brno + - Cena: 260 Kč +\-- + +/--texysource +Koncert Divokej Bill: + - termín: 9. 12. 2004 + - místo: Hala Vodová, Brno + - Cena: 260 Kč +\-- + +/--div .[output] +Koncert Divokej Bill: + - termín: 9. 12. 2004 + - místo: Hala Vodová, Brno + - Cena: 260 Kč +\-- + + +S modifikátorem +--------------- + +Modifikátor, který ovlivňuje celý seznam, se uvádí na řádku před ním. Ostatní (klasicky) na konci řádku: + +/--code texy +.{color:red} +triangl: .{color:blue} + - trojúhelník .{color:green} + - neladěný bicí hudební nástroj + - tringulační věž +\-- + +/--div .[output] +.{color:red} +triangl: .{color:blue} + - trojúhelník .{color:green} + - neladěný bicí hudební nástroj + - tringulační věž +\-- + + +Modifikátory +============ + +Nejsilnější zbraň Texy Lze použít tyto druhy modifikátorů: + +- (titulek) popisné, přidají objektu titulek (nebo alternativní text obrázkům) +- `[class1 class2 #id]` určující třídu a / nebo ID prvku +- {class:blue} přímý zápis stylu +- {target:_blank} nebo přímý zápis HTML atributů +- horizontální zarovnání: + - doleva < + - doprava > + - vycentrovaný <> + - do bloku = + +- vertikální zarovnání: (jen u tabulek) + - nahoru ^ + - na střed - + - dolů _ + +Modifikátory se zapisují spojitě (bez mezer) a **musí jim předcházet tečka**. Takže třeba `.(popis)[left]` nastavuje atribut title na `popis` a třídu na `left`. + +**Modifikátory je vždy zapisují zcela doprava**. + +Příklad použití modifikátoru na odstavci textu: + +/--code texy +Vycentrováno modifikátorem .<> + +Obarveno modifikátorem .{color:blue; lang: cs} +\-- + +/--texysource +Vycentrováno modifikátorem .<> + +Obarveno modifikátorem .{color:blue; lang: cs} +\-- + + +Typografie +========== + +Sem patří všechny úpravy a náhrady textu, které upravují jeho vzhled v souladu s typografickými pravidly a podobně: + +/--code texy +- "české" 'typografické' uvozovky +- pomlčka vs. spojovník: 10-15 vs. česko-slovenský +- pomlčka: jedna -- dvě +- typografický křížek u rozměrů 10 x 20 +- šipky <- a -> a <-> ; +- tři tečky... +- zachování HTML entit & +- náhrady(TM) nebo(R) za příslušné entity(C) +\-- + +/--div .[output] +- "české" 'typografické' uvozovky +- pomlčka vs. spojovník: 10-15 vs. česko-slovenský +- pomlčka: jedna -- dvě +- typografický křížek u rozměrů 10 x 20 +- šipky <- a -> a <-> ; +- tři tečky... +- zachování HTML entit & +- náhrady(TM) nebo(R) za příslušné (C)entity +\-- + +práce s mezerami: + +/--code texy +- vkládání nezalomitelných mezer za jednopísmenné předložky (v autě u okna) +- nedělitelné mezery u telefonních čísel +420 776 552 046 +\-- + +/--code html +vkládání nezalomitelných mezer za jednopísmenné předložky (v autě u okna) + +nedělitelné mezery u telefonních čísel +420 776 552 046 +\-- + +*Poznámka: Nahrazování se obvykle řídí dalšími pravidly, které určují, kdy +symbol nahradit a kdy ne. Například šipka `->` nemůže být na konci řádku atd. Proto nebuďte překvapeni, když v některých případech Texy náhradu neprovede. Pokud to považujete za chybu, dejte mi vědět.* + + +Zkratky, akronymy +----------------- + +Používá se zápisu s dvojitou kulatou závorkou: + +/--code texy +jednoslovné: NATO((North Atlantic Treaty Organisation)) + +víceslovné: "et al."((a další)) +\-- + +/--texysource +jednoslovné: NATO((North Atlantic Treaty Organisation)) + +víceslovné: "et al."((a další)) +\-- + + +Klikatelné URI +-------------- + +Automatický převod URI do klikatelné formy (včetně emailů) + +/--code texy +další informace na www.texy.info a také ... +\-- + +/--div .[output] +další informace na www.texy.info a také ... +\-- + + +Rozdělení velmi dlouhých slov +============================= + +Velmi zajímavá a důležitá funkce Texy. Dlouhá slova mohou narušit vzhled stránky, proto je vhodné prohlížeči naznačit, kde je může zalomit. Texy tyto místa hledá s přihlédnutím k národním zvyklostem, tedy slovo rozděluje podle slabik: + +/--code texy +nejneobhospodařovávatelnějšími +\-- + +/--code html +nejneobhospoda­řovávatelnější­mi</p +\-- + +*Poznámka: limit délky slova je volitelný* + +*Poznámka: současné prohlížeče na jádru Gecko (Mozilla, Firefox) jsou k naznačenému dělení slepí. Doufám, že vývojáři tento nedostatek brzy odstraní. Nebo zkuste [tohle | https://forum.texy.info/cs/viewtopic.php?id=36]* + + +Tabulky +======= + +Příklad jednoduché tabulky, sloupce se oddělují znakem `|` + +/--code texy +| first col | second col | third col +| Adam | Eva | Franta +\-- + +A výsledek je: + +| first col | second col | third col +| Adam | Eva | Franta + + +Hlavičku tabulky můžeme definovat tímto zápisem: + +/--code texy +|----------------------------- +| First Name | Last Name | Age +|---------------------------- +| Jesus | Christ | 33 +| Cecilie | Svobodova | 74 +\-- + +|----------------------------- +| First Name | Last Name | Age +|---------------------------- +| Jesus | Christ | 33 +| Cecilie | Svobodova | 74 + +Pokud hlavičku netvoří řádek (řádky), můžeme ji definovat na úrovni buněk. Stačí vložit hvězdičku ihned po znaku `|` + + +/--code texy +|* First Name | Jesus | Cecilie +|* Last Name | Christ | Svobodova +|* Age | 33 | 74 +\-- + + +|* First Name | Jesus | Cecilie +|* Last Name | Christ | Svobodova +|* Age | 33 | 74 + + +Sloučení sloupců +---------------- + +všimněte si zdvojeného || + +/--code texy +|----------------------------- +| Name || Age +|---------------------------- +| Jesus | Christ | 33 +\-- + +|----------------------------- +| Name || Age +|---------------------------- +| Jesus | Christ | 33 + + +Sloučení řádků +-------------- + +Všimněte si znaku `^` symbolizujícího směr nahoru: + + +/--code texy +|----------------------------- +| First Name | Last Name | Age +|---------------------------- +| Bill || 50 +| ^| 52 +| Jim | Beam | 70 +\-- + +|----------------------------- +| First Name | Last Name | Age +|---------------------------- +| Bill || 50 +| ^| 52 +| Jim | Beam | 70 + + +Modifikátory +------------ + +Platí tato pravidla: +- modifikátor ovlivňující celou tabulku se vkládá bezprostředně před tabulku +- ovlivňující řádek se vkládá na konec řádku +- ovlivňující sloupec se vkládá na začátek buňky (vlevo v buňce) +- a nakonec ovlivňující buňku se vkládá na konec buňky (pravo v buňce) + +Podívejte se na příklad. + +/--code texy +.(people) +| .{color: green} first col | second col .>| third col | .{font-style:italic} +| Adam | Eva .{color: blue}| Franta | +\-- + +Zde je: +- `.(people)` modifikátor tabulky +- `.{color: green}` modifikátor sloupce +- `.{font-style:italic}` modifikátor řádku +- `.{color: blue}` a také `.>` modifikátor buňky + +Takže výsledná tabulka vypadá takto: + + +.(people) +| .{color: green} first col | second col .>| third col | .{font-style:italic} +| Adam | Eva .{color: blue}| Franta | diff --git a/texy/cs/syntax.texy b/texy/cs/syntax.texy new file mode 100644 index 0000000000..9a430f8080 --- /dev/null +++ b/texy/cs/syntax.texy @@ -0,0 +1,464 @@ +Syntaxe +******* + +--> "Podrobný popis syntaxe":syntax-podrobne + + +Nástroj Texy vznikl proto, aby nezkušeným uživatelům umožnil snadno editovat obsah webových stránek. Proto je i syntaxe maximálně intuitivní. Záměrem je, aby text v čisté (nezformátované) formě byl přehledný a jeho formát tušitelný. + +Dnes Texy výborně slouží i zkušeným znalcům jazyka HTML. Dovoluje volně kombinovat Texy zápis s HTML značkami. Zkušení uživatelé se tedy nemusí učit nový meta-jazyk a plně využít svých znalostí. Texy jim pouze zjednodušuje práci. + +Prvotní logikou syntaxe je **žádnou syntaxi nepoužívat**. Jen psát čistý text. Vkládání rozšířených informací, jako třeba CSS třídy nebo odkazy, nenaruší tok textu. A zapíší se způsobem, který snadno pochopí i netechnicky založení uživatelé. + + +Odstavce textu .[#paragraph] +============================ + +Za odstavec se považuje jeden nebo více bezprostředně za sebou následujících řádků textu. Odstavečky jsou od sebe oddělené prázdným řádkem. + +/--code texy +První odstavec lorem ipsum dolor sit amet. + +Druhý odstavec, který tvoří jeden řádek. +A druhý řádek textu. Texy je spojí. +\-- + +Zalomení řádku v odstavci docílíte vložením jedné mezery vlevo: + +/--code texy +Kdoví jestli + jestli jsou na měsíci vůbec nějaký stopy + a proč kope kolem sebe kdo se topí + jakej sval to Zemí otáčí +\-- + + +Titulky .[#heading] +=================== + +Titulky je možné zapsat hned dvěma způsoby: **podtržením** nebo **předsazením**. + +Každý titulek má svůj stupeň. V případě **podtržení** o důležitosti titulku rozhoduje podtrhávací znak. Od nejvyšší po nejnižší jsou to tyto: `#` `*` `=` `-` + +/--code texy +Hlavní titulek +************** + + +Podtitulek +========== +\-- + +U titulků zapsaných **předsazením** určuje úroveň počet předsazených znaků. A ty mohou být `#` nebo `=` + +Platí: čím více znaků, tím důležitější titulek (minimum jsou dva znaky, maximum sedm). + +/--code texy +=== Hlavní titulek === + +## Podtitulek +\-- + +Jak vidíte v případě podtitulku, znaky vpravo je možné vynechat. + + +Horizontální čáry .[#horizline] +=============================== + +Texy zná tyto způsoby zápisu: + + +/--code texy +------------ + +******** +\-- + + +Vypnutí Texy .[#disable-texy] +============================= + +Klíčové slovo `html` nebo `text` ovlivňuje, jestli obsah bude chápán jako HTML (včetně značek), nebo prostý text. + +/--code texy + /---html + <em>příklad</em>: **this is not strong** + \--- + + + /---text + <em>příklad</em>: **this is not strong** + \--- +\-- + +Pro inline vypnutí Texy je možné použít dvojitý apostrof `''` a obalit s ním část textu, který nemá být Texy zpracováván. + +/--code texy + Příklad: ''**this is not strong**'' +\-- + + +Citace .[#blockquote] +===================== + +Citace jsou odsazené, podobně jako v emailech, znakem `>` + +/--code texy +> This is a blockquote with two paragraphs. +> +> 640 K should be enough for everyone +\-- + + +Odkazy .[#link] +=============== + +Odkazy se zapisují tak, že odkazující text uzavřete do uvozovek a následujete dvojtečkou a URL. Texy se snaží inteligentně odhadnout konec URL. Můžete mu i pomoci tím, že URI uzavřete do hranatých závorek. Část `http://` není povinná. + +Jako odkaz je možné vkládat i emaily, Texy je transformuje do podoby, která by měla zmást spamboty. + +/--code texy +Look at homepage:[https://texy.info]. + +Do you know "La Trine":https://www.latrine.cz? + +"Write me":me@example.com + +\-- + + +Obrázky .[#image] +================= + +Zapisují se mezi hranaté závorky s hvězdičkou: + +/--code texy +[* image.gif .(alternativní text) *] +\-- + + +V textových odstavcích je často třeba zvolit, má-li být obrázek zarovnán k levému nebo pravému kraji. Toho docílíte pomocí znaku `<` a `>` použitého před pravou závorkou: + +/--code texy +[* image.gif <] Left-aligned image. Lorem ipsum ... + +[* image.gif >] Right-aligned image. Curabitur quam ... +\-- + + +Obrázek s popiskou +------------------ + +Za obrázkem uveďte tři hvězdičky a následuje popiska: + + +/--code texy +[* image.gif *] *** Toto je *popiska* pod obrázkem +\-- + + +Fráze .[#phrase] +================ + +Asi nejpoužívanější syntax v Texy. Téměř ve všech případech se používá zdvojený znak. + +/--code texy +//kurzíva// + +**tučné** + +x^2 + y^3 +\-- + + +/--div .[output] +//kurzíva// + +**tučné** + +x^2 + y^3 +\-- + + +Texy lze i dočasně vypnout - obsah nebude formátován a zobrazí se doslovně: + +/--code texy +Odstraňte ''<br />'' a entitu ''&ndash'' +\-- + + +Přímé HTML .[#html] +=================== + +Texy není náhrada za HTML. Nehledá ani alternativní způsoby zápisu HTML. Cílem je zjednodušit psaní obsahu. Pokud se Vám zdá jednodušší zapsat některou strukturu přímo v HTML, můžete tak učinit. HTML značky jsou plně podporované. + +/--code texy +This <strong class=info>is strong</strong> text. +<br> This is not. +\-- + + +Seznamy .[#list] +================ + +Odrážkové seznamy zapisujeme pomocí `*` `+` nebo `-`. Musí být zapsán hned na začátku řádku a za ním musí následovat mezera. + +/--code texy +- Red +- Green +- Blue +\-- + + +Číslované seznamy +----------------- + +Texy zná těchto pět způsobů zápisu (první dva jsou ekvivalentní): + +/--code texy +1) Učit se +2) Učit se +3) Učit se + +a) Dlouhý +b) Široký +c) Krátkozraký + +A) DOS +B) Windows +C) Linux + +I) Yesterday +II) Today +III) Tomorrow +\-- + + +Vnořené seznamy +--------------- + +/--code texy +a) Bird + I) Bird + - Red + - Green + - Blue + II) McHale + III) Parish +b) McHale +c) Parish + 1) Bird + 2) McHale + 3) Parish +\-- + + +Definiční seznam +---------------- + +Koncert "Divokej Bill":www.divokybill.cz: + - termín: 9. 12. 2004 + - místo: Hala Vodová, Brno + - Cena: 260 Kč + +/--code texy +Koncert Divokej Bill: + - termín: 9. 12. 2004 + - místo: Hala Vodová, Brno + - Cena: 260 Kč +\-- + + +Modifikátory .[#modifier] +========================= + +Nejsilnější zbraň Texy. Lze použít tyto druhy modifikátorů: + +- (titulek) popisné, přidají objektu titulek (nebo alternativní text obrázkům) +- `[class1 class2 #id]` určující třídu a / nebo ID prvku +- {class:blue} přímý zápis stylu +- {target:_blank} nebo přímý zápis HTML atributů +- horizontální zarovnání: + - doleva < + - doprava > + - vycentrovaný <> + - do bloku = + +- vertikální zarovnání: (jen u tabulek) + - nahoru ^ + - na střed - + - dolů _ + +Modifikátory se zapisují spojitě (bez mezer) a **musí jim předcházet tečka**. Takže třeba `.(popis)[left]` nastavuje atribut title na `popis` a třídu na `left`. + +**Modifikátory je vždy zapisují zcela doprava**. + +Příklad použití modifikátoru na odstavci textu: + +/--code texy +Vycentrováno modifikátorem .<> + +Obarveno modifikátorem .{color:blue; lang: cs} +\-- + +/--code html +<p style="text-align:center">Vycentrováno modifikátorem</p> + +<p style="color:blue" lang="cs">Obarveno modifikátorem</p> +\-- + + +Typografie .[#typography] +========================= + +Sem patří všechny úpravy a náhrady textu, které upravují jeho vzhled v souladu s typografickými pravidly a podobně: + +/--code texy +- "české" 'typografické' uvozovky +- pomlčka vs. spojovník: 10-15 vs. česko-slovenský +- pomlčka: jedna -- dvě +- typografický křížek u rozměrů 10 x 20 +- šipky <- a -> a <-> ; +- tři tečky... +- zachování HTML entit & +- náhrady(TM) nebo(R) za příslušné entity(C) +\-- + +/--div .[output] +- "české" 'typografické' uvozovky +- pomlčka vs. spojovník: 10-15 vs. česko-slovenský +- pomlčka: jedna -- dvě +- typografický křížek u rozměrů 10 x 20 +- šipky <- a -> a <-> ; +- tři tečky... +- zachování HTML entit & +- náhrady(TM) nebo(R) za příslušné (C)entity +\-- + +práce s mezerami: + +/--code texy +- vkládání nezalomitelných mezer za jednopísmenné předložky (v autě u okna) +- nedělitelné mezery u telefonních čísel +420 776 552 046 +\-- + +/--code html +vkládání nezalomitelných mezer za jednopísmenné předložky (v autě u okna) + +nedělitelné mezery u telefonních čísel +420 776 552 046 +\-- + +*Poznámka: Nahrazování se obvykle řídí dalšími pravidly, které určují, kdy +symbol nahradit a kdy ne. Například šipka `->` nemůže být na konci řádku atd. Proto nebuďte překvapeni, když v některých případech Texy náhradu neprovede.* + + +Zkratky, akronymy .[#acronym] +----------------------------- + +Používá se zápisu s dvojitou kulatou závorkou: + +/--code texy +jednoslovné: NATO((North Atlantic Treaty Organisation)) + +víceslovné: "et al."((a další)) +\-- + + +Klikatelné webové adresy +------------------------ + +Automatický převod webových adres a emailů do klikatelné formy + +/--code texy +další informace na www.texy.info a také ... +\-- + +/--div .[output] +další informace na www.texy.info a také ... +\-- + + +Rozdělení velmi dlouhých slov .[#longwords] +=========================================== + +Velmi zajímavá a důležitá funkce Texy. Dlouhá slova mohou narušit vzhled stránky, proto je vhodné prohlížeči naznačit, kde je může zalomit. Texy tyto místa hledá s přihlédnutím k národním zvyklostem, tedy slovo rozděluje podle slabik: + +/--code texy +nejneobhospodařovávatelnějšími +\-- + +/--code html +nejneobhospoda­řovávatelnější­mi</p +\-- + +*Poznámka: limit délky slova je volitelný* + + +Tabulky .[#table] +================= + +Příklad jednoduché tabulky, sloupce se oddělují znakem `|` + +/--code texy +| first col | second col | third col +| Adam | Eva | Franta +\-- + +A výsledek je: + +| first col | second col | third col +| Adam | Eva | Franta + + +Hlavičku tabulky můžeme definovat tímto zápisem: + +/--code texy +|----------------------------- +| First Name | Last Name | Age +|---------------------------- +| Jesus | Christ | 33 +| Cecilie | Svobodova | 74 +\-- + +|----------------------------- +| First Name | Last Name | Age +|---------------------------- +| Jesus | Christ | 33 +| Cecilie | Svobodova | 74 + + +Sloučení sloupců +---------------- + +všimněte si zdvojeného || + +/--code texy +| Name || Age +|---------------------------- +| Jesus | Christ | 33 +\-- + +| Name || Age +|---------------------------- +| Jesus | Christ | 33 + + +Sloučení řádků +-------------- + +Všimněte si znaku `^` symbolizujícího směr nahoru: + + +/--code texy +| First Name | Last Name | Age +|---------------------------- +| Bill || 50 +| ^| 52 +| Jim | Beam | 70 +\-- + +| First Name | Last Name | Age +|---------------------------- +| Bill || 50 +| ^| 52 +| Jim | Beam | 70 diff --git a/texy/cs/texy-vs-wysiwyg.texy b/texy/cs/texy-vs-wysiwyg.texy new file mode 100644 index 0000000000..c79d99679e --- /dev/null +++ b/texy/cs/texy-vs-wysiwyg.texy @@ -0,0 +1,23 @@ +Texy versus WYSIWYG editory +*************************** + + +WYSIWYG((What You See is What You Get)) editor zobrazuje dokument během editace takové podobě, v jaké bude vytištěn, zobrazen na webu atd. Příkladem takového editoru je Word. + +Tento druh editorů zažil v oblasti správy internetového obsahu skutečný boom. Kdo by také odolal jejich vizuálně atraktivnímu prostředí a myšoidnímu ovládání. Díky programátorům "šikovných komponent .[about](htmlArea, FCKeditor nebo tinyRTE)" se jejich implementace stala hračkou a dnes je nabízí každý CMS((Content Management Systém = Systém na správu obsahu)). V praxi se však ukazuje, jak jsou jejich **přednosti jen zdánlivé**. + + +WYSIWYG se pro web nehodí +------------------------- + +Web má totiž docela **jiná specifika** než tištěný dokument. Zatímco u tiskovin je prioritou vizuálním uspořádání (ze kterého si lidský mozek odvodí strukturu, tj. co je nadpis, co je text a co je popiska obrázku), u webu je základem struktura. + +S vizuálním editorem se vlastně neustále svádí boj. Nejprve bojuje tvůrce administračního rozhraní, který se jej snaží přinutit **generovat použitelný kód**. Poté s ním bojuje samotný uživatel, který se snaží s využitím plné škály dostupných barev a fontů vytvoří hrozivou stránku. Následuje snaha ořezat možnosti editoru, kterou střídá další touha uživatele využít jeho plný potenciál. + +Současné WYSIWYG editory se pro web zkrátka nehodí. Prohlašuji to s vědomím autora několika administračních rozhraní, které jej využívají. Potřeboval jsem přijít s vhodnějším nástrojem a tak vzniklo Texy + + +WYSIWYM +------- + +WYSIWYM znamená What You See Is What You Mean. diff --git a/texy/cs/try-settings.texy b/texy/cs/try-settings.texy new file mode 100644 index 0000000000..66be081ed6 --- /dev/null +++ b/texy/cs/try-settings.texy @@ -0,0 +1,55 @@ +Konfigurace dema +**************** + +Toto nastavení se používá v [demu | https://fiddle.nette.org/texy/]: + +/--php +$texy = new Texy\Texy; + +$texy->imageModule->root = '/images/'; +$texy->imageModule->linkedRoot = '/images/'; +$texy->headingModule->generateID = true; + +// syntax highlighting +$texy->addHandler('block', 'blockHandler'); +\-- + +Handler pro zvýrazňování syntaxe používá knihovnu Prism.js: + +/--php +function blockHandler( + Texy\HandlerInvocation $invocation, + string $blocktype, + string $content, + string $lang, + Texy\Modifier $modifier +): Texy\HtmlElement +{ + if ($blocktype !== 'block/code') { + // nothing to do + return $invocation->proceed(); + } + + $texy = $invocation->getTexy(); + $elPre = Texy\HtmlElement::el('pre'); + if ($modifier) { + $modifier->decorate($texy, $elPre); + } + $elPre->attrs['class'] = 'language-' . $lang; + $content = $texy->protect(htmlspecialchars($content), $texy::CONTENT_BLOCK); + $elPre->create('code', $content); + return $elPre; +} +\-- + +Po dokončení konverze se navíc v textu zamění některé znaky za entity, aby byly lépe patrné: + +/--php +$html = $texy->process($text); + +$html = str_replace( + ["\xc2\xa0", "\xc2\xad", "\xe2\x80\x93", "\xe2\x80\x94"], + [' ', '­', '–', '—'], + $html +); +\-- diff --git a/texy/en/@home.texy b/texy/en/@home.texy new file mode 100644 index 0000000000..73a74963b1 --- /dev/null +++ b/texy/en/@home.texy @@ -0,0 +1,31 @@ +What Is Texy +------------ + +Texy allows you to enter content using an **easy to read** [Texy syntax | syntax] which is filtered into *structurally valid* HTML. No knowledge of HTML is required. Texy is one of the most complex formatting tools. It allows adding of images, links, nested lists, tables and has full support for CSS. + +Texy supports hyphenation of long words (which reflects language rules), clickable emails and URL (emails are obfuscated against spambots), national typographic single and double quotation marks, ellipses, em dashes, dimension sign, nonbreakable spaces (e.g. in phone numbers), acronyms, arrows and many others. + +Texy is being developed by David Grudl since 2004. It is written in PHP. + +Texy is licenced by BSD and GNU General Public License. Plugins for several content-management systems are available. + + +Features +-------- + +- simple, intuitive and human friendy markup +- generate clean and valid HTML code +- may be used together with syntax highlighter +- designed with proper typography in mind +- supports hyphenation + + +Why Texy +-------- + +- bulletproof - ensures the well-formedness of the resulting code +- predectable behaviour +- flexible configuration + + +{{maintitle: Texy – human friendy markup for PHP}} diff --git a/texy/en/@menu.texy b/texy/en/@menu.texy new file mode 100644 index 0000000000..080eb567c1 --- /dev/null +++ b/texy/en/@menu.texy @@ -0,0 +1,6 @@ +- [home | @home] +- [syntax briefly | syntax] +- [syntax in detail | syntax-full] +- [fiddle | https://fiddle.nette.org/texy/] +- [API | https://api.nette.org/texy/] +- [GitHub | https://github.com/dg/texy] diff --git a/texy/en/@meta.texy b/texy/en/@meta.texy new file mode 100644 index 0000000000..4ec8857a1e --- /dev/null +++ b/texy/en/@meta.texy @@ -0,0 +1 @@ +{{sitename: Texy Documentation}} diff --git a/texy/en/@try.texy b/texy/en/@try.texy new file mode 100644 index 0000000000..77c2fe7dac --- /dev/null +++ b/texy/en/@try.texy @@ -0,0 +1,15 @@ +Welcome! +-------- + +You can use Texy if you like: +- **bold** font or *italic* +- and this is how to "link":https://texy.info +- see "syntax":[syntax] for more information + + +But you can also stay with HTML: +- like this <b>HTML</b> +- Or even <b class=xx>totally <i>stupid</b>, Texy will solve it + + +[syntax]: /en/syntax diff --git a/texy/en/syntax-full.texy b/texy/en/syntax-full.texy new file mode 100644 index 0000000000..2df749bac6 --- /dev/null +++ b/texy/en/syntax-full.texy @@ -0,0 +1,889 @@ +Detailed Description of Syntax +****************************** + + +- [#Philosophy] +- [#Paragraphs of Text] +- [#Headings] +- [#Horizontal lines] +- [#Code] +- [#Turning off the Texy] +- [#Quotes] +- [#Links] +- [#Images] +- [#Phrases] +- [#Direct HTML] +- [#Lists] +- [#Modifiers] +- [#Typography] +- [#Long Words Hyphenation] +- [#Tables] + + +Philosophy +========== + +The Texy tool was created to allow inexperienced users to easily edit the content of web pages. Therefore, the syntax is maximally intuitive. The intention is that the text in pure (unformatted) form is clear and its format can be guessed. + +Today, Texy also serves well-experienced HTML experts. Allows you to freely combine Texy notation with HTML tags. Thus, experienced users do not have to learn a new meta-language and make full use of their knowledge. Texy only simplifies their work. + +The primary logic of the syntax is ** not to use any syntax **. Just write plain text. Inserting advanced information, such as CSS classes or links, does not disrupt the flow of text. And it is written in a way that even non-technical users can easily understand. + + +Paragraphs of Text +================== + +A paragraph is considered to be one or more consecutive lines of text. The paragraphs are separated by a blank line. + +/--code texy +First paragraph lorem ipsum dolor sit amet. + +Second paragraph, který tvoří jeden řádek. +And second line of paragraph. Texy will join the lines. +\-- + +/--texysource +First paragraph lorem ipsum dolor sit amet. + +Second paragraph, který tvoří jeden řádek. +And second line of paragraph. Texy will join the lines. +\-- + +*In the edit box (textarea) is not a division into two lines of paragraph evident. That's why Texy considers them one paragraph.* + +To wrap a line in a paragraph, insert one space to the left: + +/--code texy +April is the cruellest month, breeding + Lilacs out of the dead land, mixing + Memory and desire, stirring + Dull roots with spring rain. +\-- + +/--texysource +April is the cruellest month, breeding + Lilacs out of the dead land, mixing + Memory and desire, stirring + Dull roots with spring rain. +\-- + + +Headings +======== + +Headings can be written in two ways: **underlined** or **surrounded**. + +Each headline has its own degree. In the case of **underlined**, the importance of the title is decided by the underline character. From the highest to the lowest, these are: `#` `*` `=` `-` + +/--code texy +Head Title +********** + + +Subtitle +======== +\-- + +/--texysource +Head Title +********** + + +Subtitle +======== +\-- + +For **surrounded** titles, the level determines the number of preceding characters. It can be `#` nebo `=` + +The following applies: the more characters, the more important the title (minimum two characters, maximum seven). + +/--code texy +=== Head title === + +## Subtitle +\-- + +As you can see in the case of the subtitle, the characters on the right can be omitted. + +*Subtitle levels are always relative only! So Texy finds the highest caption used and relatively differentiates the other captions.* + + +Horizontal Lines +================ + +Texy knows these notations: + +/--code texy +------------ + +******** +\-- + +/--texysource +------------- + +******** +\-- + + +Code +==== + +Used to insert source code. Syntax highlighting can also be activated using an add-on module. + +/--code texy + /---code php + function reImage($matches) { + $content = $matches[1]; + $align = $matches[5]; + $href = $matches[6]; + } + \--- +\-- + +/--texysource + /---code php + function reImage($matches) { + $content = $matches[1]; + $align = $matches[5]; + $href = $matches[6]; + } + \--- +\-- + +*Note the words `php` to indicate the language.* + + +Turning Off the Texy +==================== + +The keyword `html` or` text` affects whether the content will be understood as HTML (including tags) or plain text. + +/--code texy + /---html + <em>example</em>: **this is not strong** + \--- + + + /---text + <em>example</em>: **this is not strong** + \--- +\-- + +To turn off Texy inline, it is possible to use a double apostrophe `''` and wrap a part of the text that is not to be Texy processed. + +/--code texy + Example: ''**this is not strong**'' +\-- + + +Division into Blocks (Div) +========================== + +Use this ability to create more complex documents. + +/--code texy + /---div .[header] + + content of div + + \--- +\-- + +/--texysource + /---div .[header] + + content of div + + \--- +\-- + + +It is also possible to nest blocks: + +/--code texy + /---div .[header] + + ## This is a header. + + /---div + inner div + \--- + + Texy is sexy! + + \--- +\-- + +/--texysource + /---div .[header] + + ## This is a header. + + /---div + inner div + \--- + + Texy is sexy! + + \--- +\-- + + +Quotes +====== + +Quotes are indented, similarly to emails, by a character `>` + +/--code texy +> This is a blockquote with two paragraphs. +> +> 640 K should be enough for everyone +\-- + +/--texysource +> This is a blockquote with two paragraphs. +> +> 640 K should be enough for everyone +\-- + + +Links +===== + +Links are written by enclosing the referencing text in quotation marks, followed by a colon and a URL. Texy tries to intelligently guess the end of the URL. You can also help it by enclosing the URL in square brackets. The `http://` section is optional. + +It is also possible to insert emails as a link, Texy transforms them into a form that should confuse spambots. + +/--code texy +Look at homepage:[https://texy.info]. + +Do you know "La Trine":https://www.latrine.cz? + +"Write me":me@example.com +\-- + +/--texysource +Look at homepage:[https://texy.info]. + +Do you know "La Trine":https://www.latrine.cz? + +"Write me":me@example.com +\-- + + +References +---------- + +In order not to "pollute" the text flow by inserting URLs, it is possible to list all addresses in one place and then just link to them. This is called a reference. In addition to the address, it is possible to add the text of the link and the [modifier | #modifier]. + +/--code texy + [homepage]: https://texy.info/ Texy .(homepage) + [nette]: http://nette.org + +This is [homepage] + +Look at "this site":[nette] +\-- + + +Images +====== + +They are written between square brackets with an asterisk: + +/--code texy +[* image.gif *] +\-- + +/--texysource line +[* image.gif *] +\-- + +In text paragraphs, you often need to choose whether the image should be left-aligned or right-aligned. To do this, use the `<` and `>` character used before the right parenthesis: + +/--code texy +[* image.gif <] Left-aligned image + +[* image.gif >] Right-aligned image +\-- + +/--texysource +[* image.gif <] Left-aligned image + +[* image.gif >] Right-aligned image +\-- + +*Note: In the example above, Texy used a straight CSS style for alignment. It is possible to configure the system to assign a selected class to images instead.* + +*Note: it is possible to set a default directory for all (relative) image URLs. In the examples given, it was `images/`, so in Texy code the directory is not listed, while in the generated HTML it is.* + +*Note: if no alternative text is specified by default (as shown below), Texy will use the default. Here's a simple `image`* + + +Dimensions +---------- + +For local images, Texy detects the dimensions automatically. If you want to specify them manually, enter them as follows: + +/--code texy +[* image.gif 10x20 *] +\-- + +/--texysource line +[* image.gif 10x20 *] +\-- + + +Modifiers +--------- + +You can learn more about them in [another chapter | #modifier], but it doesn't hurt to show how they're written on images. Let's try a modifier to specify alternate text and class: + +/--code texy +[* image.gif .(alt text)[photo] *] +\-- + +/--texysource line +[* image.gif .(alt text)[photo] *] +\-- + + +Reference +--------- + +For the same reasons as for links, images can also be written using references. You need to define URLs (or multiple URLs separated by `|`) and possibly modifiers. + +/--code texy +What a beautiful girl [* picture*] ! + +[* picture*]: image.gif .(my girl) +\-- + +/--texysource +What a beautiful girl [* picture*] ! + +[* picture*]: image.gif .(my girl) +\-- + + +Figure with Caption +------------------- + +Enter three asterisks after the image, followed by a caption: + + +/--code texy +[* image.gif *] *** This is the *caption* below the image +\-- + +/--texysource +[* image.gif *] *** This is the *caption* below the image +\-- + + +Phrases +======= + +Probably the most used syntax in Texy. In almost all cases, a double character is used. + +/--code texy +//italics// + +*too italics* + +**bold** + +***heavy bold*** + +superscript^2 vs. subscript_2 +\-- + +/--texysource +//italics// + +*too italics* + +**bold** + +***heavy bold*** + +superscript^2 vs. subscript_2 +\-- + +/--div .[output] +//italics// + +*too italics* + +**bold** + +***heavy bold*** + +superscript^2 vs. subscript_2 +\-- + +A special case of a phrase is the so-called code. It differs from the other phrases in that its content will no longer be formatted and will be displayed literally: + +/--code texy +This is `<br />` and entity `&ndash` +\-- + +/--texysource +This is `<br />` and entity `&ndash` +\-- + +*Note: whether the `<code>` element is used or another (or none) can be changed simply by configuring Texy.* + + +With Modifier +------------- + +It is possible to insert it into each phrase, always just before the closing character: + +/--code texy +**strong and green .{color:green}** like Hulk +\-- + +/--texysource +**strong and green .{color:green}** like Hulk +\-- + +/--div .[output] +**strong and green .{color:green}** like Hulk +\-- + + +Direct HTML +=========== + +Texy is not a substitute for HTML. It also doesn't look for alternative ways to write HTML. The goal is to simplify content writing. If you find it easier to write a structure directly in HTML, you can do so. HTML tags are fully supported. + +/--code texy +This <strong class=info>is strong</strong> text. +<br> This is not. +\-- + +/--texysource +This <strong class=info>is strong</strong> text. +<br> This is not. +\-- + +*Note: note that Texy adjusts the notation of attributes and tags to be valid (even for XHTML output). It also pays attention to the **well-formed notation**!* + +*Note: Deciding which tags and which attributes can be used in the text is fully user configurable. This demonstrates one example from the distribution.* + + +Lists +===== + +Bulleted lists are written using `*`, `+` or `-`. It must be written at the very beginning of the line and followed by a space. + +/--code texy +- Red +- Green +- Blue +\-- + +/--texysource +- Red +- Green +- Blue +\-- + +/--div .[output] +- Red +- Green +- Blue +\-- + + +Numbered Lists +-------------- + +Texy knows these five ways of writing (the first two are equivalent): + +/--code texy +1) Learn +2) Learn +3) Learn + +a) Long +b) Wide +c) Shortsighted + +A) DOS +B) Windows +C) Linux + +I) Yesterday +II) Today +III) Tomorrow +\-- + +/--texysource +1) Learn +2) Learn +3) Learn + +a) Long +b) Wide +c) Shortsighted + +A) DOS +B) Windows +C) Linux + +I) Yesterday +II) Today +III) Tomorrow +\-- + +/--div .[output] +1) Learn +2) Learn +3) Learn + +a) Long +b) Wide +c) Shortsighted + +A) DOS +B) Windows +C) Linux + +I) Yesterday +II) Today +III) Tomorrow +\-- + + +Nested Lists +------------ + +/--code texy +a) Bird + I) Bird + - Red + - Green + - Blue + II) McHale + III) Parish +b) McHale +c) Parish + 1) Bird + 2) McHale + 3) Parish +\-- + +/--texysource +a) Bird + I) Bird + - Red + - Green + - Blue + II) McHale + III) Parish +b) McHale +c) Parish + 1) Bird + 2) McHale + 3) Parish +\-- + + +Definition List +--------------- + +/--code texy +Wild Bill concert: + - date: 9 December 2004 + - place: Vodová Hall, Brno + - price: 260 CZK +\-- + +/--texysource +Wild Bill concert: + - date: 9 December 2004 + - place: Vodová Hall, Brno + - price: 260 CZK +\-- + +/--div .[output] +Wild Bill concert: + - date: 9 December 2004 + - place: Vodová Hall, Brno + - price: 260 CZK +\-- + + +With Modifiers +-------------- + +The modifier that affects the entire list is listed in the line before it. Others (classic) at the end of the line: + +/--code texy +.{color:red} +triangl: .{color:blue} + - triangle .{color:green} + - untuned percussion musical instrument + - tringulation tower +\-- + +/--div .[output] +.{color:red} +triangl: .{color:blue} + - triangle .{color:green} + - untuned percussion musical instrument + - tringulation tower +\-- + + +Modifiers .[#modifier] +====================== + +Texy's most powerful weapon. The following types of modifiers can be used: + +- (caption) adds a title to the object (or alternative text to images) +- `[class1 class2 #id]` specifying the class and / or ID of the element +- {class: blue} direct style notation +- {target: _blank} or direct entry of HTML attributes +- horizontal alignment: + - left < + - right > + - centered <> + - to block = + +- vertical alignment: (only for tables) + - up ^ + - center - + - down _ + +Modifiers are written continuously (without spaces) and **must be preceded by a dot**. So for example `.(description)[left]` sets the title attribute to `description` and the class to `left`. + +**Modifiers are always written rightmost**. + +Example of applying a modifier to a paragraph of text: + +/--code texy +Centered with a modifier .<> + +Colored by a modifier .{color:blue; lang: cs} +\-- + +/--texysource +Centered with a modifier .<> + +Colored by a modifier .{color:blue; lang: cs} +\-- + + +Typography .[#typography] +========================= + +This includes all modifications and replacements of the text that modify its appearance in accordance with typographic rules and the like: + +/--code texy +- "English" 'typographic' quotation marks +- dash vs. hyphen: 10-15 vs. česko-slovenský +- dash: one -- two +- typographic cross for dimensions 10 x 20 +- arrows <- and -> and <-> ; +- three dots... +- preservation of HTML entities & +- replacing (TM) or (R) with the relevant entities (C) +\-- + +/--div .[output] +- "English" 'typographic' quotation marks +- dash vs. hyphen: 10-15 vs. česko-slovenský +- dash: one -- two +- typographic cross for dimensions 10 x 20 +- arrows <- and -> and <-> ; +- three dots... +- preservation of HTML entities & +- replacing (TM) or (R) with the relevant entities (C) +\-- + +Spaces handling: + +/--code texy +- inserting unbreakable spaces for one-letter prepositions (a car) +- unbreakable spaces for telephone numbers +420 776 552 046 +\-- + +/--code html +inserting unbreakable spaces for one-letter prepositions (a car) + +unbreakable spaces for telephone numbers +420 776 552 046 +\-- + +*Note: Replacements are usually governed by other rules that determine when +symbol replace and when not. For example, the arrow `->` cannot be at the end of a line, etc. So don't be surprised if in some cases Texy doesn't make the substitution.* + + +Abbreviations, Acronyms +----------------------- + +Double parenthetical notation is used: + +/--code texy +one word: NATO((North Atlantic Treaty Organisation)) + +multiword: "et al."((and more)) +\-- + +/--texysource +one word: NATO((North Atlantic Treaty Organisation)) + +multiword: "et al."((and more)) +\-- + + +Clickable Web Addresses +----------------------- + +Automatic conversion of web addresses and emails into a clickable form + +/--code texy +more information at www.texy.info and also ... +\-- + +/--div .[output] +more information at www.texy.info and also ... +\-- + + +Long Words Hyphenation +====================== + +Very interesting and important function of Texy. Long words can disrupt the appearance of the page, so it's a good idea to tell your browser where to wrap them. Texy searches for these places taking into account national customs, so he divides the word according to syllables: + +/--code texy +nejneobhospodařovávatelnějšími +\-- + +/--code html +nejneobhospoda­řovávatelnější­mi</p +\-- + +*Note: the word length limit is optional* + + +Tables .[#table] +================ + +Example of a simple table, columns are separated by a character `|` + +/--code texy +| first col | second col | third col +| Adam | Eva | Franta +\-- + +And the result is: + +| first col | second col | third col +| Adam | Eva | Franta + + +The table header can be defined with this notation: + +/--code texy +|----------------------------- +| First Name | Last Name | Age +|---------------------------- +| Jesus | Christ | 33 +| Cecilie | Svobodova | 74 +\-- + +|----------------------------- +| First Name | Last Name | Age +|---------------------------- +| Jesus | Christ | 33 +| Cecilie | Svobodova | 74 + +If the header does not form a row (rows), we can define it at the cell level. Just insert an asterisk immediately after the `|` character + + +/--code texy +|* First Name | Jesus | Cecilie +|* Last Name | Christ | Svobodova +|* Age | 33 | 74 +\-- + + +|* First Name | Jesus | Cecilie +|* Last Name | Christ | Svobodova +|* Age | 33 | 74 + + +Merging Columns +--------------- + +Notice the double `||`: + +/--code texy +|----------------------------- +| Name || Age +|---------------------------- +| Jesus | Christ | 33 +\-- + +|----------------------------- +| Name || Age +|---------------------------- +| Jesus | Christ | 33 + + +Merging Rows +------------ + +Notice the `^` character symbolizing the upward direction: + + +/--code texy +|----------------------------- +| First Name | Last Name | Age +|---------------------------- +| Bill || 50 +| ^| 52 +| Jim | Beam | 70 +\-- + +|----------------------------- +| First Name | Last Name | Age +|---------------------------- +| Bill || 50 +| ^| 52 +| Jim | Beam | 70 + + +Modifiers +--------- + +The following rules apply: +- a modifier affecting the whole table is inserted immediately before the table +- the modifier affecting the line is inserted at the end of the line +- the modifier affecting the column is inserted at the beginning of the cell (left in the cell) +- and finally the modifier affecting the cell is inserted at the end of the cell (right in the cell) + +Take a look at an example. + +/--code texy +.(people) +| .{color: green} first col | second col .>| third col | .{font-style:italic} +| Adam | Eva .{color: blue}| Franta | +\-- + +There is: +- `.(people)` table modifier +- `.{color: green}` column modifier +- `.{font-style:italic}` line modifier +- `.{color: blue}` a také `.>` cell modifier + +So the resulting table looks like this: + + +.(people) +| .{color: green} first col | second col .>| third col | .{font-style:italic} +| Adam | Eva .{color: blue}| Franta | diff --git a/texy/en/syntax.texy b/texy/en/syntax.texy new file mode 100644 index 0000000000..2e07405d68 --- /dev/null +++ b/texy/en/syntax.texy @@ -0,0 +1,463 @@ +Syntax +****** + +--> "Detailed syntax description":syntax-full + + +The Texy tool was created to allow inexperienced users to easily edit the content of web pages. Therefore, the syntax is maximally intuitive. The intention is that the text in pure (unformatted) form is clear and its format can be guessed. + +Today, Texy also serves well-experienced HTML experts. Allows you to freely combine Texy notation with HTML tags. Thus, experienced users do not have to learn a new meta-language and make full use of their knowledge. Texy only simplifies their work. + +The primary logic of the syntax is **not to use any syntax**. Just write plain text. Inserting advanced information, such as CSS classes or links, does not disrupt the flow of text. And it is written in a way that even non-technical users can easily understand. + + +Paragraphs .[#paragraph] +======================== + +A paragraph is considered to be one or more consecutive lines of text. The paragraphs are separated by a blank line. + +/--code texy +First paragraph lorem ipsum dolor sit amet. + +Second paragraph, který tvoří jeden řádek. +And second line of paragraph. Texy will join the lines. +\-- + +To wrap a line in a paragraph, insert one space to the left: + +/--code texy +April is the cruellest month, breeding + Lilacs out of the dead land, mixing + Memory and desire, stirring + Dull roots with spring rain. +\-- + + +Headings .[#heading] +==================== + +Headings can be written in two ways: **underlined** or **surrounded**. + +Each headline has its own degree. In the case of **underlined**, the importance of the title is decided by the underline character. From the highest to the lowest, these are: `#` `*` `=` `-` + +/--code texy +Head title +********** + + +Subtitle +======== +\-- + +For **surrounded** titles, the level determines the number of preceding characters. It can be `#` nebo `=` + +The following applies: the more characters, the more important the title (minimum two characters, maximum seven). + +/--code texy +=== Head title === + +## Subtitle +\-- + +As you can see in the case of the subtitle, the characters on the right can be omitted. + + +Horizontal Lines .[#horizline] +============================== + +Texy knows these notations: + + +/--code texy +------------ + +******** +\-- + + +Turning Off the Texy .[#disable-Texy] +===================================== + +The keyword `html` or` text` affects whether the content will be understood as HTML (including tags) or plain text. + +/--code texy + /---html + <em>example</em>: **this is not strong** + \--- + + + /---text + <em>example</em>: **this is not strong** + \--- +\-- + +To turn off Texy inline, it is possible to use a double apostrophe `''` and wrap a part of the text that is not to be Texy processed. + +/--code texy + Example: ''**this is not strong**'' +\-- + + +Quotes .[#blockquote] +===================== + +Quotes are indented, similarly to emails, by a character `>` + +/--code texy +> This is a blockquote with two paragraphs. +> +> 640 K should be enough for everyone +\-- + + +Links .[#link] +============== + +Links are written by enclosing the referencing text in quotation marks, followed by a colon and a URL. Texy tries to intelligently guess the end of the URL. You can also help it by enclosing the URL in square brackets. The `http://` section is optional. + +It is also possible to insert emails as a link, Texy transforms them into a form that should confuse spambots. + +/--code texy +Look at homepage:[https://texy.info]. + +Do you know "La Trine":https://www.latrine.cz? + +"Write me":me@example.com +\-- + + +Images .[#image] +================ + +They are written between square brackets with an asterisk: + +/--code texy +[* image.gif .(alternative text) *] +\-- + + +In text paragraphs, you often need to choose whether the image should be left-aligned or right-aligned. To do this, use the `<` and `>` character used before the right parenthesis: + +/--code texy +[* image.gif <] Left-aligned image. Lorem ipsum ... + +[* image.gif >] Right-aligned image. Curabitur quam ... +\-- + + +Figure with Caption +------------------- + +Enter three asterisks after the image, followed by a caption: + + +/--code texy +[* image.gif *] *** This is the *caption* below the image +\-- + + +Phrases .[#phrase] +================== + +Probably the most used syntax in Texy. In almost all cases, a double character is used. + +/--code texy +//italics// + +**bold** + +x^2 + y^3 +\-- + + +/--div .[output] +//italics// + +**bold** + +x^2 + y^3 +\-- + + +Texts can also be temporarily turned off - the content will not be formatted and will be displayed literally: + +/--code texy +Remove ''<br />'' and entity ''&ndash'' +\-- + + +Direct HTML .[#html] +==================== + +Texy is not a substitute for HTML. It also doesn't look for alternative ways to write HTML. The goal is to simplify content writing. If you find it easier to write a structure directly in HTML, you can do so. HTML tags are fully supported. + +/--code texy +This <strong class=info>is strong</strong> text. +<br> This is not. +\-- + + +Lists .[#list] +============== + +Bulleted lists are written using `*`, `+` or `-`. It must be written at the very beginning of the line and followed by a space. + +/--code texy +- Red +- Green +- Blue +\-- + + +Numbered Lists +-------------- + +Texy knows these five ways of writing (the first two are equivalent): + +/--code texy +1) Learn +2) Learn +3) Learn + +a) Long +b) Wide +c) Shortsighted + +A) DOS +B) Windows +C) Linux + +I) Yesterday +II) Today +III) Tomorrow +\-- + + +Nested Lists +------------ + +/--code texy +a) Bird + I) Bird + - Red + - Green + - Blue + II) McHale + III) Parish +b) McHale +c) Parish + 1) Bird + 2) McHale + 3) Parish +\-- + + +Definition List +--------------- + +Wild Bill concert: + - date: 9 December 2004 + - place: Vodová Hall, Brno + - price: 260 CZK + +/--code texy +Wild Bill concert: + - date: 9 December 2004 + - place: Vodová Hall, Brno + - price: 260 CZK +\-- + + +Modifiers .[#modifier] +====================== + +Texy's most powerful weapon. The following types of modifiers can be used: + +- (caption) adds a title to the object (or alternative text to images) +- `[class1 class2 #id]` specifying the class and / or ID of the element +- {class: blue} direct style notation +- {target: _blank} or direct entry of HTML attributes +- horizontal alignment: + - left < + - right > + - centered <> + - to block = + +- vertical alignment: (only for tables) + - up ^ + - center - + - down _ + +Modifiers are written continuously (without spaces) and **must be preceded by a dot**. So for example `.(description)[left]` sets the title attribute to `description` and the class to `left`. + +**Modifiers are always written rightmost**. + +Example of applying a modifier to a paragraph of text: + +/--code texy +Centered with a modifier .<> + +Colored by a modifier .{color:blue; lang: cs} +\-- + +/--code html +<p style="text-align:center">Centered with a modifier</p> + +<p style="color:blue" lang="cs">Colored by a modifier</p> +\-- + + +Typography .[#typography] +========================= + +This includes all modifications and replacements of the text that modify its appearance in accordance with typographic rules and the like: + +/--code texy +- "English" 'typographic' quotation marks +- dash vs. hyphen: 10-15 vs. česko-slovenský +- dash: one -- two +- typographic cross for dimensions 10 x 20 +- arrows <- and -> and <-> ; +- three dots... +- preservation of HTML entities & +- replacing (TM) or (R) with the relevant entities (C) +\-- + +/--div .[output] +- "English" 'typographic' quotation marks +- dash vs. hyphen: 10-15 vs. česko-slovenský +- dash: one -- two +- typographic cross for dimensions 10 x 20 +- arrows <- and -> and <-> ; +- three dots... +- preservation of HTML entities & +- replacing (TM) or (R) with the relevant entities (C) +\-- + +Spaces handling: + +/--code texy +- inserting unbreakable spaces for one-letter prepositions (a car) +- unbreakable spaces for telephone numbers +420 776 552 046 +\-- + +/--code html +inserting unbreakable spaces for one-letter prepositions (a car) + +unbreakable spaces for telephone numbers +420 776 552 046 +\-- + +*Note: Replacements are usually governed by other rules that determine when +symbol replace and when not. For example, the arrow `->` cannot be at the end of a line, etc. So don't be surprised if in some cases Texy doesn't make the substitution.* + + +Abbreviations, Acronyms .[#acronym] +----------------------------------- + +Double parenthetical notation is used: + +/--code texy +one word: NATO((North Atlantic Treaty Organisation)) + +multiword: "et al."((and more)) +\-- + + +Clickable Web Addresses +----------------------- + +Automatic conversion of web addresses and emails into a clickable form + +/--code texy +more information at www.texy.info and also ... +\-- + +/--div .[output] +more information at www.texy.info and also ... +\-- + + +Long Words Hyphenation .[#longwords] +==================================== + +Very interesting and important function of Texy. Long words can disrupt the appearance of the page, so it's a good idea to tell your browser where to wrap them. Texy searches for these places taking into account national customs, so he divides the word according to syllables: + +/--code texy +nejneobhospodařovávatelnějšími +\-- + +/--code html +nejneobhospoda­řovávatelnější­mi</p +\-- + +*Note: the word length limit is optional* + + +Tables .[#table] +================ + +Example of a simple table, columns are separated by a character `|` + +/--code texy +| first col | second col | third col +| Adam | Eva | Franta +\-- + +And the result is: + +| first col | second col | third col +| Adam | Eva | Franta + + +The table header can be defined with this notation: + +/--code texy +|----------------------------- +| First Name | Last Name | Age +|---------------------------- +| Jesus | Christ | 33 +| Cecilie | Svobodova | 74 +\-- + +|----------------------------- +| First Name | Last Name | Age +|---------------------------- +| Jesus | Christ | 33 +| Cecilie | Svobodova | 74 + + +Merging Columns +--------------- + +Notice the double `||`: + +/--code texy +| Name || Age +|---------------------------- +| Jesus | Christ | 33 +\-- + +| Name || Age +|---------------------------- +| Jesus | Christ | 33 + + +Merging Rows +------------ + +Notice the `^` character symbolizing the upward direction: + + +/--code texy +| First Name | Last Name | Age +|---------------------------- +| Bill || 50 +| ^| 52 +| Jim | Beam | 70 +\-- + +| First Name | Last Name | Age +|---------------------------- +| Bill || 50 +| ^| 52 +| Jim | Beam | 70 diff --git a/texy/en/try-settings.texy b/texy/en/try-settings.texy new file mode 100644 index 0000000000..0b8706a6a8 --- /dev/null +++ b/texy/en/try-settings.texy @@ -0,0 +1,55 @@ +Demo Configuration +****************** + +This setting is used in [demo | https://fiddle.nette.org/texy/]: + +/--php +$texy = new Texy\Texy; + +$texy->imageModule->root = '/images/'; +$texy->imageModule->linkedRoot = '/images/'; +$texy->headingModule->generateID = true; + +// syntax highlighting +$texy->addHandler('block', 'blockHandler'); +\-- + +The handler uses Prism.js to highlight syntax: + +/--php +function blockHandler( + Texy\HandlerInvocation $invocation, + string $blocktype, + string $content, + string $lang, + Texy\Modifier $modifier +): Texy\HtmlElement +{ + if ($blocktype !== 'block/code') { + // nothing to do + return $invocation->proceed(); + } + + $texy = $invocation->getTexy(); + $elPre = Texy\HtmlElement::el('pre'); + if ($modifier) { + $modifier->decorate($texy, $elPre); + } + $elPre->attrs['class'] = 'language-' . $lang; + $content = $texy->protect(htmlspecialchars($content), $texy::CONTENT_BLOCK); + $elPre->create('code', $content); + return $elPre; +} +\-- + +In addition, when the conversion is complete, some characters are replaced by entities in the text to make them more visible: + +/--php +$html = $texy->process($text); + +$html = str_replace( + ["\xc2\xa0", "\xc2\xad", "\xe2\x80\x93", "\xe2\x80\x94"], + [' ', '­', '–', '—'], + $html +); +\-- diff --git a/texy/files/image.gif b/texy/files/image.gif new file mode 100644 index 0000000000000000000000000000000000000000..b99eabeaf8b0c5aaaf75c040951fae1980ed96cd GIT binary patch literal 942 zcmV;f15x}(Nk%w1VK@LN0K@<QW{I`w=;p`I*_W)y^YZdfc&)g`+0xnJq_@xg{rwL| zk@NBG`T6-ERG8Z0>pW?r{rL0m?d#;}@Q9+q0z8ZC@b&-w`1$qm_4V~GU!M2(_;{AR z`}_Le-{1QB`v3p`A^sdZLr+jyK15-5X=ETra&=^EAa{3nE@WqTE@OHCA^8LV00000 zEC2ui05||B000I5;3tmNVVp-bu59bR@ak+u_7uQ#ORc9>6-I10#B4GE#32xfFasA) zMKA!=GK~gOK<utGg~DM$#&ABCih<TpG;osvVz7BA00eIrp*TP+fEo@60BsEq6d3{m zWQ`XQ2n`zy33@CN1qLDm6b}F!R&5Fo8wec*6ayU*7#a*79IzG!866&$D;pFDlo%6O zS~vp&s}~3q0388BE*cvL8kM*X$W4_N0Ug>+5fKZm4-JbL(#-_XxE}@L0pub+1o5pN zmB$m-LmcIL2dVh^8EP#{=OqjiW<w0@3Xq2&5d#Xw?R$|xhq7A^hmh)a=AplaA|x2V zU`dS%7PMCXX(%WV<A(`tHt2J~U}Y`}2KFT=Fkk_Ji7y-|xCe5=E>Axl7&!UC000RI zDpV30@#hEw54s^7G9lu?rW7_{6%gTrt^yVkOb|mLj1T}6#4V7v6M;{lE;wW;fDc1J z1P=^E$OAxuf+`y%STKrUR)$d>KprT-(aV9MtVA5!Yry9R2bl~{@L9n|lL8y=v?Jkw zfV(aO6bNPp_u1eN6$%LGDm#J&0f#SaC`I9(O%Vyuc`1CLY=WHvNn%1U0f12e7tHoC zKv@@p2)Cwxzzd^Bhu;7+6zTxM1A<Hg_(niA;mDl~1|Y0!Ug`3N_LdZKz%RT&gc=S9 z5YoZ_0va5U0Wt#Uke>vH9AH%f5;Wmb7X}0)fKME(F@XRCI52@XW_(7>BUD)7#sdh@ zrGavKIIsvAlzafe1@g@JS^^eaAV3ZP3=rFh0{lo&a;}w=04#LvGg$_<E#}oZ<YhEO z1xIYK;9wjS@W3h^X^9IhVk|J&N)<G4B1vZAGC%`8d7~U3WNj5E5ioVe%033owWk++ z_(|gjmk9>vphHl2B6t(wpdq7t3Up{w4K%kXr7(DM7Yn7?6+xDqe!xHmqa7y#7#pam zXQ?fa62%I+0ifoku(A*d7b6Hzz-WKw%GCoC7(fRA20ZeburOF~fRPB0$Rn=I_P_xP Q1Ut@Ctrt&1IcNv~JMQpsg8%>k literal 0 HcmV?d00001 diff --git a/texy/meta.json b/texy/meta.json new file mode 100644 index 0000000000..27991fd5a8 --- /dev/null +++ b/texy/meta.json @@ -0,0 +1,5 @@ +{ + "version": "3.x", + "repo": "dg/texy", + "composer": "texy/texy" +} From 70c558aea5cc510a97025e56a6c9fa3805bd0218 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Mon, 27 Apr 2026 17:21:29 +0200 Subject: [PATCH 02/50] neon: link to fiddle --- neon/bg/@home.texy | 2 +- neon/bg/format.texy | 2 +- neon/cs/@home.texy | 2 +- neon/cs/format.texy | 2 +- neon/de/@home.texy | 2 +- neon/de/format.texy | 2 +- neon/el/@home.texy | 2 +- neon/el/format.texy | 2 +- neon/en/@home.texy | 2 +- neon/en/format.texy | 2 +- neon/es/@home.texy | 2 +- neon/es/format.texy | 2 +- neon/fr/@home.texy | 2 +- neon/fr/format.texy | 2 +- neon/hu/@home.texy | 2 +- neon/hu/format.texy | 2 +- neon/it/@home.texy | 2 +- neon/it/format.texy | 2 +- neon/ja/@home.texy | 2 +- neon/ja/format.texy | 2 +- neon/pl/@home.texy | 2 +- neon/pl/format.texy | 2 +- neon/pt/@home.texy | 2 +- neon/pt/format.texy | 2 +- neon/ro/@home.texy | 2 +- neon/ro/format.texy | 2 +- neon/ru/@home.texy | 2 +- neon/ru/format.texy | 2 +- neon/sl/@home.texy | 2 +- neon/sl/format.texy | 2 +- neon/tr/@home.texy | 2 +- neon/tr/format.texy | 2 +- neon/uk/@home.texy | 2 +- neon/uk/format.texy | 2 +- www/bg/packages.texy | 2 +- www/cs/packages.texy | 2 +- www/de/packages.texy | 2 +- www/el/packages.texy | 2 +- www/en/packages.texy | 2 +- www/es/packages.texy | 2 +- www/fr/packages.texy | 2 +- www/hu/packages.texy | 2 +- www/it/packages.texy | 2 +- www/ja/packages.texy | 2 +- www/pl/packages.texy | 2 +- www/pt/packages.texy | 2 +- www/ro/packages.texy | 2 +- www/ru/packages.texy | 2 +- www/sl/packages.texy | 2 +- www/tr/packages.texy | 2 +- www/uk/packages.texy | 2 +- 51 files changed, 51 insertions(+), 51 deletions(-) diff --git a/neon/bg/@home.texy b/neon/bg/@home.texy index c25a22d34b..cf81855aa0 100644 --- a/neon/bg/@home.texy +++ b/neon/bg/@home.texy @@ -5,7 +5,7 @@ Nette NEON NEON е разбираем за човека език за сериализация на данни. Използва се в Nette за конфигурационни файлове. [api:Nette\Neon\Neon] е статичен клас за работа с NEON. -Запознайте се с [формата NEON |format] и [изпробвайте го |https://ne-on.org]. +Запознайте се с [формата NEON |format] и [изпробвайте го |https://fiddle.nette.org/neon/]. </div> diff --git a/neon/bg/format.texy b/neon/bg/format.texy index 5b31151ace..0b833e9108 100644 --- a/neon/bg/format.texy +++ b/neon/bg/format.texy @@ -2,7 +2,7 @@ *********** .[perex] -NEON е лесно четим структуриран формат за данни. В Nette се използва за конфигурационни файлове. Използва се и за структурирани данни, като настройки, езикови преводи и т.н. [Опитайте го|https://ne-on.org]. +NEON е лесно четим структуриран формат за данни. В Nette се използва за конфигурационни файлове. Използва се и за структурирани данни, като настройки, езикови преводи и т.н. [Опитайте го|https://fiddle.nette.org/neon/]. NEON е съкращение от *Nette Object Notation*. Той е по-малко сложен и тромав от XML или JSON, но предоставя подобни функции. Много е подобен на YAML. Основното предимство е, че NEON има така наречените [#ентитети], благодарение на които конфигурацията на DI сървисите е [също толкова секси |https://gist.github.com/dg/26baf3ce8f29d0f751e9dddfaa06504f]. И позволява индентация с табулации. diff --git a/neon/cs/@home.texy b/neon/cs/@home.texy index 5375b2e479..75a6e36deb 100644 --- a/neon/cs/@home.texy +++ b/neon/cs/@home.texy @@ -5,7 +5,7 @@ Nette NEON NEON je lidsky srozumitelný jazyk pro serializaci dat. Používá se v Nette pro konfigurační soubory. [api:Nette\Neon\Neon] je statická třída pro práci s NEONem. -Seznamte se s [formátem NEON|format] a [vyzkoušejte si jej |https://ne-on.org]. +Seznamte se s [formátem NEON|format] a [vyzkoušejte si jej |https://fiddle.nette.org/neon/]. </div> diff --git a/neon/cs/format.texy b/neon/cs/format.texy index 1f7f06bfcf..f8bf97f6d5 100644 --- a/neon/cs/format.texy +++ b/neon/cs/format.texy @@ -2,7 +2,7 @@ Formát NEON *********** .[perex] -NEON je v lidsky čitelný strukturovaný datový formát. V Nette se používá pro konfigurační soubory. Také se používá pro strukturovaná data, jako jsou nastavení, jazykové překlady atd. [Vyzkoušejte si jej|https://ne-on.org]. +NEON je v lidsky čitelný strukturovaný datový formát. V Nette se používá pro konfigurační soubory. Také se používá pro strukturovaná data, jako jsou nastavení, jazykové překlady atd. [Vyzkoušejte si jej|https://fiddle.nette.org/neon/]. NEON je zkratka pro *Nette Object Notation*. Je méně složitý a nemotorný než XML nebo JSON, ale poskytuje podobné funkce. Je velmi podobný YAML. Hlavní přednost je tom, že NEON má takzvané [#entity], díky kterým je konfigurace DI služeb [taky sexy |https://gist.github.com/dg/26baf3ce8f29d0f751e9dddfaa06504f]. A umožňuje odsazovat tabulátory. diff --git a/neon/de/@home.texy b/neon/de/@home.texy index 158c387de2..02745de78d 100644 --- a/neon/de/@home.texy +++ b/neon/de/@home.texy @@ -5,7 +5,7 @@ Nette NEON NEON ist eine für Menschen verständliche Sprache zur Serialisierung von Daten. Sie wird in Nette für Konfigurationsdateien verwendet. [api:Nette\Neon\Neon] ist eine statische Klasse für die Arbeit mit NEON. -Machen Sie sich mit dem [NEON-Format|format] vertraut und [probieren Sie es aus |https://ne-on.org]. +Machen Sie sich mit dem [NEON-Format|format] vertraut und [probieren Sie es aus |https://fiddle.nette.org/neon/]. </div> diff --git a/neon/de/format.texy b/neon/de/format.texy index bd78f27538..d95e6e9128 100644 --- a/neon/de/format.texy +++ b/neon/de/format.texy @@ -2,7 +2,7 @@ Das NEON-Format *************** .[perex] -NEON ist ein menschenlesbares strukturiertes Datenformat. In Nette wird es für Konfigurationsdateien verwendet. Es wird auch für strukturierte Daten wie Einstellungen, Sprachübersetzungen usw. verwendet. [Probieren Sie es aus|https://ne-on.org]. +NEON ist ein menschenlesbares strukturiertes Datenformat. In Nette wird es für Konfigurationsdateien verwendet. Es wird auch für strukturierte Daten wie Einstellungen, Sprachübersetzungen usw. verwendet. [Probieren Sie es aus|https://fiddle.nette.org/neon/]. NEON ist die Abkürzung für *Nette Object Notation*. Es ist weniger komplex und sperrig als XML oder JSON, bietet aber ähnliche Funktionen. Es ist YAML sehr ähnlich. Der Hauptvorteil ist, dass NEON sogenannte [#Entitäten] hat, dank derer die Konfiguration von DI-Diensten [auch sexy ist |https://gist.github.com/dg/26baf3ce8f29d0f751e9dddfaa06504f]. Und es erlaubt die Einrückung mit Tabulatoren. diff --git a/neon/el/@home.texy b/neon/el/@home.texy index 18c47bc4a6..acf29cb3fd 100644 --- a/neon/el/@home.texy +++ b/neon/el/@home.texy @@ -5,7 +5,7 @@ Nette NEON Το NEON είναι μια γλώσσα σειριοποίησης δεδομένων κατανοητή από τον άνθρωπο. Χρησιμοποιείται στο Nette για αρχεία διαμόρφωσης. Η [api:Nette\Neon\Neon] είναι μια στατική κλάση για την εργασία με το NEON. -Εξοικειωθείτε με [τη μορφή NEON|format] και [δοκιμάστε την |https://ne-on.org]. +Εξοικειωθείτε με [τη μορφή NEON|format] και [δοκιμάστε την |https://fiddle.nette.org/neon/]. </div> diff --git a/neon/el/format.texy b/neon/el/format.texy index 11d6436156..7aab34dd05 100644 --- a/neon/el/format.texy +++ b/neon/el/format.texy @@ -2,7 +2,7 @@ ********** .[perex] -Το NEON είναι μια ευανάγνωστη μορφή δομημένων δεδομένων. Στο Nette χρησιμοποιείται για αρχεία διαμόρφωσης. Χρησιμοποιείται επίσης για δομημένα δεδομένα, όπως ρυθμίσεις, γλωσσικές μεταφράσεις κ.λπ. [Δοκιμάστε το|https://ne-on.org]. +Το NEON είναι μια ευανάγνωστη μορφή δομημένων δεδομένων. Στο Nette χρησιμοποιείται για αρχεία διαμόρφωσης. Χρησιμοποιείται επίσης για δομημένα δεδομένα, όπως ρυθμίσεις, γλωσσικές μεταφράσεις κ.λπ. [Δοκιμάστε το|https://fiddle.nette.org/neon/]. Το NEON είναι ακρωνύμιο του *Nette Object Notation*. Είναι λιγότερο περίπλοκο και αδέξιο από το XML ή το JSON, αλλά παρέχει παρόμοιες λειτουργίες. Είναι πολύ παρόμοιο με το YAML. Το κύριο πλεονέκτημα είναι ότι το NEON διαθέτει τις λεγόμενες [οντότητες |#Entities], χάρη στις οποίες η διαμόρφωση των υπηρεσιών DI είναι [επίσης σέξι |https://gist.github.com/dg/26baf3ce8f29d0f751e9dddfaa06504f]. Και επιτρέπει την εσοχή με tabs. diff --git a/neon/en/@home.texy b/neon/en/@home.texy index d162c54f3f..644b40e72f 100644 --- a/neon/en/@home.texy +++ b/neon/en/@home.texy @@ -5,7 +5,7 @@ Nette NEON NEON is a human-friendly data serialization language. It is used in Nette for configuration files. [api:Nette\Neon\Neon] is a static class for working with NEON. -Get to know the [NEON format|format] and [try it out |https://ne-on.org]. +Get to know the [NEON format|format] and [try it out |https://fiddle.nette.org/neon/]. </div> diff --git a/neon/en/format.texy b/neon/en/format.texy index 5f6a51d2c8..6120dafc6a 100644 --- a/neon/en/format.texy +++ b/neon/en/format.texy @@ -2,7 +2,7 @@ NEON Format *********** .[perex] -NEON is a human-readable structured data format. In Nette, it is used for configuration files. It is also used for structured data such as settings, language translations, etc. [Try it on the sandbox |https://ne-on.org]. +NEON is a human-readable structured data format. In Nette, it is used for configuration files. It is also used for structured data such as settings, language translations, etc. [Try it on the sandbox |https://fiddle.nette.org/neon/]. NEON stands for *Nette Object Notation*. It is less complex and cumbersome than XML or JSON, but provides similar capabilities. It is very similar to YAML. The main advantage is that NEON has so-called [#entities], thanks to which the configuration of DI services is [so sexy |https://gist.github.com/dg/26baf3ce8f29d0f751e9dddfaa06504f]. And it allows tabs for indentation. diff --git a/neon/es/@home.texy b/neon/es/@home.texy index ee418ef146..987fd26060 100644 --- a/neon/es/@home.texy +++ b/neon/es/@home.texy @@ -5,7 +5,7 @@ Nette NEON NEON es un lenguaje legible por humanos para la serialización de datos. Se utiliza en Nette para archivos de configuración. [api:Nette\Neon\Neon] es una clase estática para trabajar con NEON. -Familiarícese con el [formato NEON|format] y [pruébelo |https://ne-on.org]. +Familiarícese con el [formato NEON|format] y [pruébelo |https://fiddle.nette.org/neon/]. </div> diff --git a/neon/es/format.texy b/neon/es/format.texy index 8503a12140..802c47aabe 100644 --- a/neon/es/format.texy +++ b/neon/es/format.texy @@ -2,7 +2,7 @@ Formato NEON ************ .[perex] -NEON es un formato de datos estructurados legible por humanos. En Nette se utiliza para archivos de configuración. También se utiliza para datos estructurados, como configuraciones, traducciones de idiomas, etc. [Pruébelo|https://ne-on.org]. +NEON es un formato de datos estructurados legible por humanos. En Nette se utiliza para archivos de configuración. También se utiliza para datos estructurados, como configuraciones, traducciones de idiomas, etc. [Pruébelo|https://fiddle.nette.org/neon/]. NEON es la abreviatura de *Nette Object Notation*. Es menos complejo y torpe que XML o JSON, pero proporciona funciones similares. Es muy similar a YAML. La principal ventaja es que NEON tiene las llamadas [#entidades], gracias a las cuales la configuración de los servicios DI es [tan sexy |https://gist.github.com/dg/26baf3ce8f29d0f751e9dddfaa06504f]. Y permite la indentación con tabuladores. diff --git a/neon/fr/@home.texy b/neon/fr/@home.texy index 280177a817..5718b806ce 100644 --- a/neon/fr/@home.texy +++ b/neon/fr/@home.texy @@ -5,7 +5,7 @@ Nette NEON NEON est un langage de sérialisation de données lisible par l'homme. Il est utilisé dans Nette pour les fichiers de configuration. [api:Nette\Neon\Neon] est une classe statique pour travailler avec NEON. -Familiarisez-vous avec le [format NEON|format] et [essayez-le |https://ne-on.org]. +Familiarisez-vous avec le [format NEON|format] et [essayez-le |https://fiddle.nette.org/neon/]. </div> diff --git a/neon/fr/format.texy b/neon/fr/format.texy index 87c410844f..d6bb2a37cf 100644 --- a/neon/fr/format.texy +++ b/neon/fr/format.texy @@ -2,7 +2,7 @@ Format NEON *********** .[perex] -NEON est un format de données structurées lisible par l'homme. Dans Nette, il est utilisé pour les fichiers de configuration. Il est également utilisé pour les données structurées, telles que les paramètres, les traductions linguistiques, etc. [Essayez-le|https://ne-on.org]. +NEON est un format de données structurées lisible par l'homme. Dans Nette, il est utilisé pour les fichiers de configuration. Il est également utilisé pour les données structurées, telles que les paramètres, les traductions linguistiques, etc. [Essayez-le|https://fiddle.nette.org/neon/]. NEON est l'acronyme de *Nette Object Notation*. Il est moins complexe et lourd que XML ou JSON, mais offre des fonctionnalités similaires. Il est très similaire à YAML. Le principal avantage est que NEON possède ce qu'on appelle des [#entités], grâce auxquelles la configuration des services DI est [aussi sexy |https://gist.github.com/dg/26baf3ce8f29d0f751e9dddfaa06504f]. Et il permet d'indenter avec des tabulations. diff --git a/neon/hu/@home.texy b/neon/hu/@home.texy index 2b63918f98..21bcd0f12e 100644 --- a/neon/hu/@home.texy +++ b/neon/hu/@home.texy @@ -5,7 +5,7 @@ Nette NEON A NEON egy ember által olvasható adatszerializációs nyelv. A Nette-ben konfigurációs fájlokhoz használják. A [api:Nette\Neon\Neon] egy statikus osztály a NEON-nal való munkához. -Ismerkedjen meg a [NEON formátummal|format] és [próbálja ki |https://ne-on.org]. +Ismerkedjen meg a [NEON formátummal|format] és [próbálja ki |https://fiddle.nette.org/neon/]. </div> diff --git a/neon/hu/format.texy b/neon/hu/format.texy index a47bd628d7..1ce3208a68 100644 --- a/neon/hu/format.texy +++ b/neon/hu/format.texy @@ -2,7 +2,7 @@ NEON Formátum ************* .[perex] -A NEON egy ember által olvasható, strukturált adatformátum. A Nette-ben konfigurációs fájlokhoz használják. Strukturált adatokhoz is használják, mint például beállítások, nyelvi fordítások stb. [Próbálja ki|https://ne-on.org]. +A NEON egy ember által olvasható, strukturált adatformátum. A Nette-ben konfigurációs fájlokhoz használják. Strukturált adatokhoz is használják, mint például beállítások, nyelvi fordítások stb. [Próbálja ki|https://fiddle.nette.org/neon/]. A NEON a *Nette Object Notation* rövidítése. Kevésbé bonyolult és nehézkes, mint az XML vagy a JSON, de hasonló funkciókat biztosít. Nagyon hasonlít a YAML-hez. A fő előnye az, hogy a NEON-nak vannak úgynevezett [entity |#Entitások] entitásai, amelyeknek köszönhetően a DI szolgáltatások konfigurálása [is szexi |https://gist.github.com/dg/26baf3ce8f29d0f751e9dddfaa06504f]. És lehetővé teszi a tabulátorokkal történő behúzást. diff --git a/neon/it/@home.texy b/neon/it/@home.texy index 3358f69547..426acfeb41 100644 --- a/neon/it/@home.texy +++ b/neon/it/@home.texy @@ -5,7 +5,7 @@ Nette NEON NEON è un linguaggio leggibile dall'uomo per la serializzazione dei dati. Viene utilizzato in Nette per i file di configurazione. [api:Nette\Neon\Neon] è una classe statica per lavorare con NEON. -Scopri il [formato NEON|format] e [provalo |https://ne-on.org]. +Scopri il [formato NEON|format] e [provalo |https://fiddle.nette.org/neon/]. </div> diff --git a/neon/it/format.texy b/neon/it/format.texy index 347d561bc0..29895c0557 100644 --- a/neon/it/format.texy +++ b/neon/it/format.texy @@ -2,7 +2,7 @@ Formato NEON ************ .[perex] -NEON è un formato di dati strutturati leggibile dall'uomo. In Nette viene utilizzato per i file di configurazione. Viene utilizzato anche per dati strutturati come impostazioni, traduzioni linguistiche, ecc. [Provatelo|https://ne-on.org]. +NEON è un formato di dati strutturati leggibile dall'uomo. In Nette viene utilizzato per i file di configurazione. Viene utilizzato anche per dati strutturati come impostazioni, traduzioni linguistiche, ecc. [Provatelo|https://fiddle.nette.org/neon/]. NEON è l'acronimo di *Nette Object Notation*. È meno complesso e goffo di XML o JSON, ma fornisce funzionalità simili. È molto simile a YAML. Il vantaggio principale è che NEON ha le cosiddette [#entità], grazie alle quali la configurazione dei servizi DI è [così sexy |https://gist.github.com/dg/26baf3ce8f29d0f751e9dddfaa06504f]. E consente l'indentazione con tabulazioni. diff --git a/neon/ja/@home.texy b/neon/ja/@home.texy index c1646c3b4d..4dd5573af1 100644 --- a/neon/ja/@home.texy +++ b/neon/ja/@home.texy @@ -5,7 +5,7 @@ Nette NEON NEONは、人間が理解しやすいデータシリアライズ言語です。Netteでは設定ファイルに使用されます。[api:Nette\Neon\Neon]は、NEONを操作するための静的クラスです。 -[NEON 形式|format]について学び、[試してみてください |https://ne-on.org]。 +[NEON 形式|format]について学び、[試してみてください |https://fiddle.nette.org/neon/]。 </div> diff --git a/neon/ja/format.texy b/neon/ja/format.texy index 4d668d9660..bb34a28dd0 100644 --- a/neon/ja/format.texy +++ b/neon/ja/format.texy @@ -2,7 +2,7 @@ NEONフォーマット ********** .[perex] -NEONは、人間が判読可能な構造化データ形式です。Netteでは設定ファイルに使用されます。また、設定、言語翻訳などの構造化データにも使用されます。[試してみてください |https://ne-on.org]。 +NEONは、人間が判読可能な構造化データ形式です。Netteでは設定ファイルに使用されます。また、設定、言語翻訳などの構造化データにも使用されます。[試してみてください |https://fiddle.nette.org/neon/]。 NEONは *Nette Object Notation* の略です。XMLやJSONよりも複雑でなく、扱いにくくありませんが、同様の機能を提供します。YAMLに非常に似ています。主な利点は、NEONにはいわゆる[#エンティティ]があり、これによりDIサービスの[設定 |https://gist.github.com/dg/26baf3ce8f29d0f751e9dddfaa06504f]が非常に洗練されることです。そして、タブによるインデントが可能です。 diff --git a/neon/pl/@home.texy b/neon/pl/@home.texy index 133d536c91..4419eac6b0 100644 --- a/neon/pl/@home.texy +++ b/neon/pl/@home.texy @@ -5,7 +5,7 @@ Nette NEON NEON to czytelny dla człowieka język do serializacji danych. Jest używany w Nette do plików konfiguracyjnych. [api:Nette\Neon\Neon] to statyczna klasa do pracy z NEONem. -Zapoznaj się z [formatem NEON|format] i [wypróbuj go |https://ne-on.org]. +Zapoznaj się z [formatem NEON|format] i [wypróbuj go |https://fiddle.nette.org/neon/]. </div> diff --git a/neon/pl/format.texy b/neon/pl/format.texy index 98a2ecc681..f70c1ab533 100644 --- a/neon/pl/format.texy +++ b/neon/pl/format.texy @@ -2,7 +2,7 @@ Format NEON *********** .[perex] -NEON to czytelny dla człowieka format danych strukturalnych. W Nette jest używany do plików konfiguracyjnych. Jest również używany do danych strukturalnych, takich jak ustawienia, tłumaczenia językowe itp. [Wypróbuj go|https://ne-on.org]. +NEON to czytelny dla człowieka format danych strukturalnych. W Nette jest używany do plików konfiguracyjnych. Jest również używany do danych strukturalnych, takich jak ustawienia, tłumaczenia językowe itp. [Wypróbuj go|https://fiddle.nette.org/neon/]. NEON to skrót od *Nette Object Notation*. Jest mniej skomplikowany i nieporęczny niż XML czy JSON, ale zapewnia podobne funkcje. Jest bardzo podobny do YAML. Główną zaletą jest to, że NEON ma tak zwane [#encje], dzięki którym konfiguracja usług DI jest [również seksowna |https://gist.github.com/dg/26baf3ce8f29d0f751e9dddfaa06504f]. I pozwala na wcięcia za pomocą tabulatorów. diff --git a/neon/pt/@home.texy b/neon/pt/@home.texy index a15233b262..4c1962f4e5 100644 --- a/neon/pt/@home.texy +++ b/neon/pt/@home.texy @@ -5,7 +5,7 @@ Nette NEON NEON é uma linguagem de serialização de dados legível por humanos. É usado no Nette para arquivos de configuração. [api:Nette\Neon\Neon] é uma classe estática para trabalhar com NEON. -Familiarize-se com o [formato NEON |format] e [experimente |https://ne-on.org]. +Familiarize-se com o [formato NEON |format] e [experimente |https://fiddle.nette.org/neon/]. </div> diff --git a/neon/pt/format.texy b/neon/pt/format.texy index 6de60e563b..4cbb9c9979 100644 --- a/neon/pt/format.texy +++ b/neon/pt/format.texy @@ -2,7 +2,7 @@ Formato NEON ************ .[perex] -NEON é um formato de dados estruturados legível por humanos. No Nette, é usado para arquivos de configuração. Também é usado para dados estruturados, como configurações, traduções de idiomas, etc. [Experimente |https://ne-on.org]. +NEON é um formato de dados estruturados legível por humanos. No Nette, é usado para arquivos de configuração. Também é usado para dados estruturados, como configurações, traduções de idiomas, etc. [Experimente |https://fiddle.nette.org/neon/]. NEON é a abreviação de *Nette Object Notation*. É menos complexo e desajeitado que XML ou JSON, mas fornece recursos semelhantes. É muito semelhante ao YAML. A principal vantagem é que o NEON possui as chamadas [#entidades], graças às quais a configuração dos serviços de DI é [tão sexy |https://gist.github.com/dg/26baf3ce8f29d0f751e9dddfaa06504f]. E permite indentação com tabulações. diff --git a/neon/ro/@home.texy b/neon/ro/@home.texy index d25985bcb0..af4d0d2fd4 100644 --- a/neon/ro/@home.texy +++ b/neon/ro/@home.texy @@ -5,7 +5,7 @@ Nette NEON NEON este un limbaj ușor de înțeles pentru serializarea datelor. Este utilizat în Nette pentru fișierele de configurare. [api:Nette\Neon\Neon] este o clasă statică pentru lucrul cu NEON. -Familiarizați-vă cu [formatul NEON|format] și [încercați-l |https://ne-on.org]. +Familiarizați-vă cu [formatul NEON|format] și [încercați-l |https://fiddle.nette.org/neon/]. </div> diff --git a/neon/ro/format.texy b/neon/ro/format.texy index 98b69e1935..3206bc7bbb 100644 --- a/neon/ro/format.texy +++ b/neon/ro/format.texy @@ -2,7 +2,7 @@ Formatul NEON ************* .[perex] -NEON este un format de date structurate lizibil pentru om. În Nette, este utilizat pentru fișierele de configurare. De asemenea, este utilizat pentru date structurate, cum ar fi setări, traduceri lingvistice etc. [Încercați-l|https://ne-on.org]. +NEON este un format de date structurate lizibil pentru om. În Nette, este utilizat pentru fișierele de configurare. De asemenea, este utilizat pentru date structurate, cum ar fi setări, traduceri lingvistice etc. [Încercați-l|https://fiddle.nette.org/neon/]. NEON este acronimul pentru *Nette Object Notation*. Este mai puțin complex și greoi decât XML sau JSON, dar oferă funcționalități similare. Este foarte asemănător cu YAML. Principalul avantaj este că NEON are așa-numitele [#entități], datorită cărora configurarea serviciilor DI este [la fel de sexy |https://gist.github.com/dg/26baf3ce8f29d0f751e9dddfaa06504f]. Și permite indentarea cu tabulatori. diff --git a/neon/ru/@home.texy b/neon/ru/@home.texy index b147c9f670..0678c994c7 100644 --- a/neon/ru/@home.texy +++ b/neon/ru/@home.texy @@ -5,7 +5,7 @@ Nette NEON NEON — это понятный человеку язык для сериализации данных. Он используется в Nette для конфигурационных файлов. [api:Nette\Neon\Neon] — это статический класс для работы с NEON. -Ознакомьтесь с [форматом NEON|format] и [попробуйте его |https://ne-on.org]. +Ознакомьтесь с [форматом NEON|format] и [попробуйте его |https://fiddle.nette.org/neon/]. </div> diff --git a/neon/ru/format.texy b/neon/ru/format.texy index b34e014c24..0420b2c34c 100644 --- a/neon/ru/format.texy +++ b/neon/ru/format.texy @@ -2,7 +2,7 @@ *********** .[perex] -NEON — это человекочитаемый формат структурированных данных. В Nette он используется для конфигурационных файлов. Он также используется для структурированных данных, таких как настройки, языковые переводы и т. д. [Попробуйте его|https://ne-on.org]. +NEON — это человекочитаемый формат структурированных данных. В Nette он используется для конфигурационных файлов. Он также используется для структурированных данных, таких как настройки, языковые переводы и т. д. [Попробуйте его|https://fiddle.nette.org/neon/]. NEON — это аббревиатура от *Nette Object Notation*. Он менее сложен и громоздок, чем XML или JSON, но предоставляет схожие функции. Он очень похож на YAML. Главное преимущество заключается в том, что NEON имеет так называемые [#сущности], благодаря которым конфигурация DI-сервисов [тоже сексуальна |https://gist.github.com/dg/26baf3ce8f29d0f751e9dddfaa06504f]. И позволяет использовать табуляцию для отступов. diff --git a/neon/sl/@home.texy b/neon/sl/@home.texy index a944ff0832..dd379d3b09 100644 --- a/neon/sl/@home.texy +++ b/neon/sl/@home.texy @@ -5,7 +5,7 @@ Nette NEON NEON je človeku razumljiv jezik za serializacijo podatkov. V Nette se uporablja za konfiguracijske datoteke. [api:Nette\Neon\Neon] je statični razred za delo z NEONom. -Spoznajte [format NEON|format] in [ga preizkusite |https://ne-on.org]. +Spoznajte [format NEON|format] in [ga preizkusite |https://fiddle.nette.org/neon/]. </div> diff --git a/neon/sl/format.texy b/neon/sl/format.texy index 25fe9ceed2..3d33a746a7 100644 --- a/neon/sl/format.texy +++ b/neon/sl/format.texy @@ -2,7 +2,7 @@ Format NEON *********** .[perex] -NEON je človeško berljiv strukturiran podatkovni format. V Nette se uporablja za konfiguracijske datoteke. Uporablja se tudi za strukturirane podatke, kot so nastavitve, jezikovni prevodi itd. [Preizkusite ga|https://ne-on.org]. +NEON je človeško berljiv strukturiran podatkovni format. V Nette se uporablja za konfiguracijske datoteke. Uporablja se tudi za strukturirane podatke, kot so nastavitve, jezikovni prevodi itd. [Preizkusite ga|https://fiddle.nette.org/neon/]. NEON je okrajšava za *Nette Object Notation*. Je manj zapleten in okoren kot XML ali JSON, vendar zagotavlja podobne funkcije. Je zelo podoben YAML. Glavna prednost je v tem, da ima NEON tako imenovane [#Entitete], zahvaljujoč katerim je konfiguracija DI storitev [tudi seksi |https://gist.github.com/dg/26baf3ce8f29d0f751e9dddfaa06504f]. In omogoča zamikanje s tabulatorji. diff --git a/neon/tr/@home.texy b/neon/tr/@home.texy index 05d3e314f1..85a02ccf3a 100644 --- a/neon/tr/@home.texy +++ b/neon/tr/@home.texy @@ -5,7 +5,7 @@ Nette NEON NEON, verilerin serileştirilmesi için insan tarafından okunabilir bir dildir. Nette'de yapılandırma dosyaları için kullanılır. [api:Nette\Neon\Neon], NEON ile çalışmak için statik bir sınıftır. -[NEON biçimiyle |format] tanışın ve [onu deneyin |https://ne-on.org]. +[NEON biçimiyle |format] tanışın ve [onu deneyin |https://fiddle.nette.org/neon/]. </div> diff --git a/neon/tr/format.texy b/neon/tr/format.texy index 7d724df789..62bf99acf4 100644 --- a/neon/tr/format.texy +++ b/neon/tr/format.texy @@ -2,7 +2,7 @@ NEON Formatı ************ .[perex] -NEON, insan tarafından okunabilir yapılandırılmış bir veri formatıdır. Nette'de yapılandırma dosyaları için kullanılır. Ayrıca ayarlar, dil çevirileri vb. gibi yapılandırılmış veriler için de kullanılır. [Deneyin |https://ne-on.org]. +NEON, insan tarafından okunabilir yapılandırılmış bir veri formatıdır. Nette'de yapılandırma dosyaları için kullanılır. Ayrıca ayarlar, dil çevirileri vb. gibi yapılandırılmış veriler için de kullanılır. [Deneyin |https://fiddle.nette.org/neon/]. NEON, *Nette Object Notation*'ın kısaltmasıdır. XML veya JSON'dan daha az karmaşık ve hantaldır, ancak benzer işlevler sunar. YAML'ye çok benzer. Ana avantajı, NEON'un DI servislerinin yapılandırılmasını [çok seksi |https://gist.github.com/dg/26baf3ce8f29d0f751e9dddfaa06504f] yapan sözde [#Varlıklar (Entities)]'a sahip olmasıdır. Ve sekmelerle girintilemeye izin verir. diff --git a/neon/uk/@home.texy b/neon/uk/@home.texy index bd187fa15f..19805388d7 100644 --- a/neon/uk/@home.texy +++ b/neon/uk/@home.texy @@ -5,7 +5,7 @@ Nette NEON NEON — це зрозуміла для людини мова серіалізації даних. Вона використовується в Nette для конфігураційних файлів. [api:Nette\Neon\Neon] — це статичний клас для роботи з NEON. -Ознайомтеся з [форматом NEON|format] та [спробуйте його |https://ne-on.org]. +Ознайомтеся з [форматом NEON|format] та [спробуйте його |https://fiddle.nette.org/neon/]. </div> diff --git a/neon/uk/format.texy b/neon/uk/format.texy index d168a547a3..9229ee9561 100644 --- a/neon/uk/format.texy +++ b/neon/uk/format.texy @@ -2,7 +2,7 @@ *********** .[perex] -NEON — це читабельний для людини структурований формат даних. У Nette він використовується для конфігураційних файлів. Також він використовується для структурованих даних, таких як налаштування, мовні переклади тощо. [Спробуйте його |https://ne-on.org]. +NEON — це читабельний для людини структурований формат даних. У Nette він використовується для конфігураційних файлів. Також він використовується для структурованих даних, таких як налаштування, мовні переклади тощо. [Спробуйте його |https://fiddle.nette.org/neon/]. NEON — це абревіатура від *Nette Object Notation*. Він менш складний і громіздкий, ніж XML або JSON, але надає схожі функції. Він дуже схожий на YAML. Головна перевага полягає в тому, що NEON має так звані [#сутності], завдяки яким конфігурація DI-сервісів [також сексі |https://gist.github.com/dg/26baf3ce8f29d0f751e9dddfaa06504f]. І дозволяє використовувати табуляцію для відступів. diff --git a/www/bg/packages.texy b/www/bg/packages.texy index cc362f1f78..8915f6a226 100644 --- a/www/bg/packages.texy +++ b/www/bg/packages.texy @@ -12,7 +12,7 @@ | **Http**:[http:] | Слой, капсулиращ HTTP заявка & отговор | [GitHub |https://github.com/nette/http] [API |https://api.nette.org/http/] | **Latte**:[latte:] | Страхотна система за шаблони | [GitHub |https://github.com/nette/latte] [API |https://api.nette.org/latte/] | **Mail**:[mail:] | Изпращане на имейли | [GitHub |https://github.com/nette/mail] [API |https://api.nette.org/mail/] -| **Neon**:[neon:] | Четене и запис на формат [NEON |https://ne-on.org] | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] +| **Neon**:[neon:] | Четене и запис на формат [NEON |https://fiddle.nette.org/neon/] | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] | **Php Generator**:[php-generator:] | Генератор на PHP код | [GitHub |https://github.com/nette/php-generator] [API |https://api.nette.org/php-generator/] | **Robot Loader**:[robot-loader:] | Най-удобното автоматично зареждане | [GitHub |https://github.com/nette/robot-loader] [API |https://api.nette.org/robot-loader/] | **Routing**:[application:routing] | Маршрутизация | [GitHub |https://github.com/nette/routing] [API |https://api.nette.org/routing/] diff --git a/www/cs/packages.texy b/www/cs/packages.texy index 22e1d9d7e2..01ad3a5618 100644 --- a/www/cs/packages.texy +++ b/www/cs/packages.texy @@ -12,7 +12,7 @@ Seznam balíčků Nette | **Http**:[http:] | Vrstva zapouzdřující HTTP request & response | [GitHub |https://github.com/nette/http] [API |https://api.nette.org/http/] | **Latte**:[latte:] | Skvělý šablonovací systém | [GitHub |https://github.com/nette/latte] [API |https://api.nette.org/latte/] | **Mail**:[mail:] | Odesílání e-mailů | [GitHub |https://github.com/nette/mail] [API |https://api.nette.org/mail/] -| **Neon**:[neon:] | Čtení a zápis formátu [NEON |https://ne-on.org] | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] +| **Neon**:[neon:] | Čtení a zápis formátu [NEON |https://fiddle.nette.org/neon/] | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] | **Php Generator**:[php-generator:] | Generátor PHP kódu | [GitHub |https://github.com/nette/php-generator] [API |https://api.nette.org/php-generator/] | **Robot Loader**:[robot-loader:] | Nejkomfortnější autoloading | [GitHub |https://github.com/nette/robot-loader] [API |https://api.nette.org/robot-loader/] | **Routing**:[application:routing] | Routování | [GitHub |https://github.com/nette/routing] [API |https://api.nette.org/routing/] diff --git a/www/de/packages.texy b/www/de/packages.texy index 1eabb71e2e..da060914a0 100644 --- a/www/de/packages.texy +++ b/www/de/packages.texy @@ -12,7 +12,7 @@ Liste der Nette-Pakete | **Http**:[http:] | Schicht zur Kapselung von HTTP Request & Response | GitHub |https://github.com/nette/http] [API |https://api.nette.org/http/] | **Latte**:[latte:] | Großartiges Template-System | GitHub |https://github.com/nette/latte] [API |https://api.nette.org/latte/] | **Mail**:[mail:] | Senden von E-Mails | GitHub |https://github.com/nette/mail] [API |https://api.nette.org/mail/] -| **Neon**:[neon:] | Lesen und Schreiben des [NEON |https://ne-on.org] Formats | GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] +| **Neon**:[neon:] | Lesen und Schreiben des [NEON |https://fiddle.nette.org/neon/] Formats | GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] | **Php Generator**:[php-generator:] | PHP-Code-Generator | GitHub |https://github.com/nette/php-generator] [API |https://api.nette.org/php-generator/] | **Robot Loader**:[robot-loader:] | Das komfortabelste Autoloading | GitHub |https://github.com/nette/robot-loader] [API |https://api.nette.org/robot-loader/] | **Routing**:[application:routing] | Routing | GitHub |https://github.com/nette/routing] [API |https://api.nette.org/routing/] diff --git a/www/el/packages.texy b/www/el/packages.texy index b4289bca58..a609f055d0 100644 --- a/www/el/packages.texy +++ b/www/el/packages.texy @@ -12,7 +12,7 @@ | **Http**:[http:] | Επίπεδο που ενσωματώνει το HTTP request & response | [GitHub |https://github.com/nette/http] [API |https://api.nette.org/http/] | **Latte**:[latte:] | Εξαιρετικό σύστημα προτύπων | [GitHub |https://github.com/nette/latte] [API |https://api.nette.org/latte/] | **Mail**:[mail:] | Αποστολή e-mail | [GitHub |https://github.com/nette/mail] [API |https://api.nette.org/mail/] -| **Neon**:[neon:] | Ανάγνωση και εγγραφή της μορφής [NEON |https://ne-on.org] | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] +| **Neon**:[neon:] | Ανάγνωση και εγγραφή της μορφής [NEON |https://fiddle.nette.org/neon/] | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] | **Php Generator**:[php-generator:] | Γεννήτρια κώδικα PHP | [GitHub |https://github.com/nette/php-generator] [API |https://api.nette.org/php-generator/] | **Robot Loader**:[robot-loader:] | Η πιο άνετη αυτόματη φόρτωση | [GitHub |https://github.com/nette/robot-loader] [API |https://api.nette.org/robot-loader/] | **Routing**:[application:routing] | Δρομολόγηση | [GitHub |https://github.com/nette/routing] [API |https://api.nette.org/routing/] diff --git a/www/en/packages.texy b/www/en/packages.texy index 61945fc199..60d091be49 100644 --- a/www/en/packages.texy +++ b/www/en/packages.texy @@ -12,7 +12,7 @@ List of Packages | **Http**:[http:] | Layer encapsulating HTTP request & response | [GitHub |https://github.com/nette/http] [API |https://api.nette.org/http/] | **Latte**:[latte:] | Amazing template engine | [GitHub |https://github.com/nette/latte] [API |https://api.nette.org/latte/] | **Mail**:[mail:] | Sending emails | [GitHub |https://github.com/nette/mail] [API |https://api.nette.org/mail/] -| **Neon**:[neon:] | Reading and writing [NEON format |https://ne-on.org] | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] +| **Neon**:[neon:] | Reading and writing [NEON format |https://fiddle.nette.org/neon/] | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] | **Php Generator**:[php-generator:] | PHP code generator | [GitHub |https://github.com/nette/php-generator] [API |https://api.nette.org/php-generator/] | **Robot Loader**:[robot-loader:] | The most comfortable class autoloading | [GitHub |https://github.com/nette/robot-loader] [API |https://api.nette.org/robot-loader/] | **Routing**:[application:routing] | URL routing | [GitHub |https://github.com/nette/routing] [API |https://api.nette.org/routing/] diff --git a/www/es/packages.texy b/www/es/packages.texy index ae2279ea62..6c48cc5a33 100644 --- a/www/es/packages.texy +++ b/www/es/packages.texy @@ -12,7 +12,7 @@ Lista de paquetes de Nette | **Http**:[http:] | Capa que encapsula la petición y respuesta HTTP | [GitHub |https://github.com/nette/http] [API |https://api.nette.org/http/] | **Latte**:[latte:] | Excelente sistema de plantillas | [GitHub |https://github.com/nette/latte] [API |https://api.nette.org/latte/] | **Mail**:[mail:] | Envío de correos electrónicos | [GitHub |https://github.com/nette/mail] [API |https://api.nette.org/mail/] -| **Neon**:[neon:] | Lectura y escritura del formato [NEON |https://ne-on.org] | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] +| **Neon**:[neon:] | Lectura y escritura del formato [NEON |https://fiddle.nette.org/neon/] | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] | **Php Generator**:[php-generator:] | Generador de código PHP | [GitHub |https://github.com/nette/php-generator] [API |https://api.nette.org/php-generator/] | **Robot Loader**:[robot-loader:] | El autoloading más cómodo | [GitHub |https://github.com/nette/robot-loader] [API |https://api.nette.org/robot-loader/] | **Routing**:[application:routing] | Enrutamiento | [GitHub |https://github.com/nette/routing] [API |https://api.nette.org/routing/] diff --git a/www/fr/packages.texy b/www/fr/packages.texy index 99c919906e..ecb97d45fd 100644 --- a/www/fr/packages.texy +++ b/www/fr/packages.texy @@ -12,7 +12,7 @@ Liste des paquets Nette | **[Http |http:]** | Couche encapsulant la requête & réponse HTTP | [GitHub |https://github.com/nette/http] [API |https://api.nette.org/http/] | **[Latte |latte:]** | Excellent système de template | [GitHub |https://github.com/nette/latte] [API |https://api.nette.org/latte/] | **[Mail |mail:]** | Envoi d'e-mails | [GitHub |https://github.com/nette/mail] [API |https://api.nette.org/mail/] -| **[Neon |neon:]** | Lecture et écriture du format [NEON |https://ne-on.org] | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] +| **[Neon |neon:]** | Lecture et écriture du format [NEON |https://fiddle.nette.org/neon/] | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] | **[Php Generator |php-generator:]** | Générateur de code PHP | [GitHub |https://github.com/nette/php-generator] [API |https://api.nette.org/php-generator/] | **[Robot Loader |robot-loader:]** | Autoloading le plus confortable | [GitHub |https://github.com/nette/robot-loader] [API |https://api.nette.org/robot-loader/] | **[Routing |application:routing]** | Routage | [GitHub |https://github.com/nette/routing] [API |https://api.nette.org/routing/] diff --git a/www/hu/packages.texy b/www/hu/packages.texy index a7b9279ea5..a7045aeafa 100644 --- a/www/hu/packages.texy +++ b/www/hu/packages.texy @@ -12,7 +12,7 @@ Nette csomagok listája | **Http**:[http:] | HTTP kérést és választ beágyazó réteg | [GitHub |https://github.com/nette/http] [API |https://api.nette.org/http/] | **Latte**:[latte:] | Nagyszerű sablonrendszer | [GitHub |https://github.com/nette/latte] [API |https://api.nette.org/latte/] | **Mail**:[mail:] | E-mailek küldése | [GitHub |https://github.com/nette/mail] [API |https://api.nette.org/mail/] -| **Neon**:[neon:] | [NEON |https://ne-on.org] formátum olvasása és írása | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] +| **Neon**:[neon:] | [NEON |https://fiddle.nette.org/neon/] formátum olvasása és írása | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] | **Php Generator**:[php-generator:] | PHP kódgenerátor | [GitHub |https://github.com/nette/php-generator] [API |https://api.nette.org/php-generator/] | **Robot Loader**:[robot-loader:] | A legkényelmesebb autoloading | [GitHub |https://github.com/nette/robot-loader] [API |https://api.nette.org/robot-loader/] | **Routing**:[application:routing] | Útválasztás | [GitHub |https://github.com/nette/routing] [API |https://api.nette.org/routing/] diff --git a/www/it/packages.texy b/www/it/packages.texy index f0ba73804f..27503bc5a7 100644 --- a/www/it/packages.texy +++ b/www/it/packages.texy @@ -12,7 +12,7 @@ Elenco dei pacchetti Nette | **Http**:[http:] | Livello che incapsula HTTP request & response | [GitHub |https://github.com/nette/http] [API |https://api.nette.org/http/] | **Latte**:[latte:] | Fantastico sistema di template | [GitHub |https://github.com/nette/latte] [API |https://api.nette.org/latte/] | **Mail**:[mail:] | Invio di e-mail | [GitHub |https://github.com/nette/mail] [API |https://api.nette.org/mail/] -| **Neon**:[neon:] | Lettura e scrittura del formato [NEON |https://ne-on.org] | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] +| **Neon**:[neon:] | Lettura e scrittura del formato [NEON |https://fiddle.nette.org/neon/] | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] | **Php Generator**:[php-generator:] | Generatore di codice PHP | [GitHub |https://github.com/nette/php-generator] [API |https://api.nette.org/php-generator/] | **Robot Loader**:[robot-loader:] | L'autoloading più comodo | [GitHub |https://github.com/nette/robot-loader] [API |https://api.nette.org/robot-loader/] | **Routing**:[application:routing] | Routing | [GitHub |https://github.com/nette/routing] [API |https://api.nette.org/routing/] diff --git a/www/ja/packages.texy b/www/ja/packages.texy index f458e2463c..d968ddcccc 100644 --- a/www/ja/packages.texy +++ b/www/ja/packages.texy @@ -12,7 +12,7 @@ Netteパッケージ一覧 | **Http**:[http:] | HTTPリクエスト&レスポンスをカプセル化する層 | [GitHub |https://github.com/nette/http] [API |https://api.nette.org/http/] | **Latte**:[latte:] | 素晴らしいテンプレートシステム | [GitHub |https://github.com/nette/latte] [API |https://api.nette.org/latte/] | **Mail**:[mail:] | メール送信 | [GitHub |https://github.com/nette/mail] [API |https://api.nette.org/mail/] -| **Neon**:[neon:] | [NEON |https://ne-on.org] 形式の読み書き | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] +| **Neon**:[neon:] | [NEON |https://fiddle.nette.org/neon/] 形式の読み書き | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] | **Php Generator**:[php-generator:] | PHPコードジェネレータ | [GitHub |https://github.com/nette/php-generator] [API |https://api.nette.org/php-generator/] | **Robot Loader**:[robot-loader:] | 最も快適なオートローディング | [GitHub |https://github.com/nette/robot-loader] [API |https://api.nette.org/robot-loader/] | **Routing**:[application:routing] | ルーティング | [GitHub |https://github.com/nette/routing] [API |https://api.nette.org/routing/] diff --git a/www/pl/packages.texy b/www/pl/packages.texy index 83d35268fa..f2ad154f60 100644 --- a/www/pl/packages.texy +++ b/www/pl/packages.texy @@ -12,7 +12,7 @@ Lista pakietów Nette | **Http**:[http:] | Warstwa hermetyzująca żądanie i odpowiedź HTTP | [GitHub |https://github.com/nette/http] [API |https://api.nette.org/http/] | **Latte**:[latte:] | Doskonały system szablonów | [GitHub |https://github.com/nette/latte] [API |https://api.nette.org/latte/] | **Mail**:[mail:] | Wysyłanie e-maili | [GitHub |https://github.com/nette/mail] [API |https://api.nette.org/mail/] -| **Neon**:[neon:] | Odczyt i zapis formatu [NEON |https://ne-on.org] | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] +| **Neon**:[neon:] | Odczyt i zapis formatu [NEON |https://fiddle.nette.org/neon/] | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] | **Php Generator**:[php-generator:] | Generator kodu PHP | [GitHub |https://github.com/nette/php-generator] [API |https://api.nette.org/php-generator/] | **Robot Loader**:[robot-loader:] | Najwygodniejszy autoloading | [GitHub |https://github.com/nette/robot-loader] [API |https://api.nette.org/robot-loader/] | **Routing**:[application:routing] | Routing | [GitHub |https://github.com/nette/routing] [API |https://api.nette.org/routing/] diff --git a/www/pt/packages.texy b/www/pt/packages.texy index e017413f0a..a9c9fe63d7 100644 --- a/www/pt/packages.texy +++ b/www/pt/packages.texy @@ -12,7 +12,7 @@ Lista de Pacotes Nette | **Http**:[http:] | Camada encapsulando requisição & resposta HTTP | [GitHub |https://github.com/nette/http] [API |https://api.nette.org/http/] | **Latte**:[latte:] | Ótimo sistema de templates | [GitHub |https://github.com/nette/latte] [API |https://api.nette.org/latte/] | **Mail**:[mail:] | Envio de e-mails | [GitHub |https://github.com/nette/mail] [API |https://api.nette.org/mail/] -| **Neon**:[neon:] | Leitura e escrita do formato [NEON |https://ne-on.org] | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] +| **Neon**:[neon:] | Leitura e escrita do formato [NEON |https://fiddle.nette.org/neon/] | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] | **Php Generator**:[php-generator:] | Gerador de código PHP | [GitHub |https://github.com/nette/php-generator] [API |https://api.nette.org/php-generator/] | **Robot Loader**:[robot-loader:] | O autoloading mais confortável | [GitHub |https://github.com/nette/robot-loader] [API |https://api.nette.org/robot-loader/] | **Routing**:[application:routing] | Roteamento | [GitHub |https://github.com/nette/routing] [API |https://api.nette.org/routing/] diff --git a/www/ro/packages.texy b/www/ro/packages.texy index 6dfbb6916f..a77a3ef94a 100644 --- a/www/ro/packages.texy +++ b/www/ro/packages.texy @@ -12,7 +12,7 @@ Lista pachetelor Nette | **Http**:[http:] | Strat care încapsulează cererea & răspunsul HTTP | [GitHub |https://github.com/nette/http] [API |https://api.nette.org/http/] | **Latte**:[latte:] | Sistem excelent de șabloane | [GitHub |https://github.com/nette/latte] [API |https://api.nette.org/latte/] | **Mail**:[mail:] | Trimiterea de e-mailuri | [GitHub |https://github.com/nette/mail] [API |https://api.nette.org/mail/] -| **Neon**:[neon:] | Citirea și scrierea formatului [NEON |https://ne-on.org] | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] +| **Neon**:[neon:] | Citirea și scrierea formatului [NEON |https://fiddle.nette.org/neon/] | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] | **Php Generator**:[php-generator:] | Generator de cod PHP | [GitHub |https://github.com/nette/php-generator] [API |https://api.nette.org/php-generator/] | **Robot Loader**:[robot-loader:] | Cel mai confortabil autoloading | [GitHub |https://github.com/nette/robot-loader] [API |https://api.nette.org/robot-loader/] | **Routing**:[application:routing] | Rutare | [GitHub |https://github.com/nette/routing] [API |https://api.nette.org/routing/] diff --git a/www/ru/packages.texy b/www/ru/packages.texy index 70d68370c5..fa212efcd5 100644 --- a/www/ru/packages.texy +++ b/www/ru/packages.texy @@ -12,7 +12,7 @@ | **Http**:[http:] | Слой, инкапсулирующий HTTP request & response | [GitHub |https://github.com/nette/http] [API |https://api.nette.org/http/] | **Latte**:[latte:] | Отличная система шаблонов | [GitHub |https://github.com/nette/latte] [API |https://api.nette.org/latte/] | **Mail**:[mail:] | Отправка электронной почты | [GitHub |https://github.com/nette/mail] [API |https://api.nette.org/mail/] -| **Neon**:[neon:] | Чтение и запись формата [NEON |https://ne-on.org] | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] +| **Neon**:[neon:] | Чтение и запись формата [NEON |https://fiddle.nette.org/neon/] | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] | **Php Generator**:[php-generator:] | Генератор PHP-кода | [GitHub |https://github.com/nette/php-generator] [API |https://api.nette.org/php-generator/] | **Robot Loader**:[robot-loader:] | Самый удобный автозагрузчик | [GitHub |https://github.com/nette/robot-loader] [API |https://api.nette.org/robot-loader/] | **Routing**:[application:routing] | Маршрутизация | [GitHub |https://github.com/nette/routing] [API |https://api.nette.org/routing/] diff --git a/www/sl/packages.texy b/www/sl/packages.texy index 81a32cb6c7..9b3c556109 100644 --- a/www/sl/packages.texy +++ b/www/sl/packages.texy @@ -12,7 +12,7 @@ Seznam paketov Nette | **Http**:[http:] | Plast, ki inkapsulira HTTP zahtevo & odgovor | [GitHub |https://github.com/nette/http] [API |https://api.nette.org/http/] | **Latte**:[latte:] | Odličen sistem predlog | [GitHub |https://github.com/nette/latte] [API |https://api.nette.org/latte/] | **Mail**:[mail:] | Pošiljanje e-pošte | [GitHub |https://github.com/nette/mail] [API |https://api.nette.org/mail/] -| **Neon**:[neon:] | Branje in pisanje formata [NEON |https://ne-on.org] | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] +| **Neon**:[neon:] | Branje in pisanje formata [NEON |https://fiddle.nette.org/neon/] | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] | **Php Generator**:[php-generator:] | Generator PHP kode | [GitHub |https://github.com/nette/php-generator] [API |https://api.nette.org/php-generator/] | **Robot Loader**:[robot-loader:] | Najudobnejši autoloading | [GitHub |https://github.com/nette/robot-loader] [API |https://api.nette.org/robot-loader/] | **Routing**:[application:routing] | Usmerjanje | [GitHub |https://github.com/nette/routing] [API |https://api.nette.org/routing/] diff --git a/www/tr/packages.texy b/www/tr/packages.texy index d53e725ad0..644f78541e 100644 --- a/www/tr/packages.texy +++ b/www/tr/packages.texy @@ -12,7 +12,7 @@ Nette Paket Listesi | **Http**:[http:] | HTTP isteğini ve yanıtını kapsayan katman | [GitHub |https://github.com/nette/http] [API |https://api.nette.org/http/] | **Latte**:[latte:] | Harika şablonlama sistemi | [GitHub |https://github.com/nette/latte] [API |https://api.nette.org/latte/] | **Mail**:[mail:] | E-posta gönderme | [GitHub |https://github.com/nette/mail] [API |https://api.nette.org/mail/] -| **Neon**:[neon:] | [NEON |https://ne-on.org] formatını okuma ve yazma | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] +| **Neon**:[neon:] | [NEON |https://fiddle.nette.org/neon/] formatını okuma ve yazma | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] | **Php Generator**:[php-generator:] | PHP kodu oluşturucu | [GitHub |https://github.com/nette/php-generator] [API |https://api.nette.org/php-generator/] | **Robot Loader**:[robot-loader:] | En konforlu otomatik yükleme | [GitHub |https://github.com/nette/robot-loader] [API |https://api.nette.org/robot-loader/] | **Routing**:[application:routing] | Yönlendirme | [GitHub |https://github.com/nette/routing] [API |https://api.nette.org/routing/] diff --git a/www/uk/packages.texy b/www/uk/packages.texy index 0e639722d6..983e47f622 100644 --- a/www/uk/packages.texy +++ b/www/uk/packages.texy @@ -12,7 +12,7 @@ | **Http**:[http:] | Шар, що інкапсулює HTTP request & response | [GitHub |https://github.com/nette/http] [API |https://api.nette.org/http/] | **Latte**:[latte:] | Чудова система шаблонів | [GitHub |https://github.com/nette/latte] [API |https://api.nette.org/latte/] | **Mail**:[mail:] | Надсилання електронних листів | [GitHub |https://github.com/nette/mail] [API |https://api.nette.org/mail/] -| **Neon**:[neon:] | Читання та запис формату [NEON |https://ne-on.org] | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] +| **Neon**:[neon:] | Читання та запис формату [NEON |https://fiddle.nette.org/neon/] | [GitHub |https://github.com/nette/neon] [API |https://api.nette.org/neon/] | **Php Generator**:[php-generator:] | Генератор PHP коду | [GitHub |https://github.com/nette/php-generator] [API |https://api.nette.org/php-generator/] | **Robot Loader**:[robot-loader:] | Найкомфортніше автозавантаження | [GitHub |https://github.com/nette/robot-loader] [API |https://api.nette.org/robot-loader/] | **Routing**:[application:routing] | Маршрутизація | [GitHub |https://github.com/nette/routing] [API |https://api.nette.org/routing/] From 496a723d558ed31eff191cfc82f2f6da63eb13fc Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Wed, 22 Oct 2025 00:18:43 +0200 Subject: [PATCH 03/50] texy: extensive documentation update --- texy/cs/@home.texy | 126 +++- texy/cs/@menu.texy | 15 +- texy/cs/@try.texy | 15 - texy/cs/api-block-module.texy | 11 - texy/cs/api-blockquote-module.texy | 8 - texy/cs/api-emoticon-module.texy | 47 -- texy/cs/api-figure-module.texy | 33 - texy/cs/api-heading-module.texy | 42 -- texy/cs/api-horizline-module.texy | 8 - texy/cs/api-html-module.texy | 21 - texy/cs/api-htmloutput-module.texy | 17 - texy/cs/api-image-module.texy | 35 - texy/cs/api-link-module.texy | 42 -- texy/cs/api-list-module.texy | 12 - texy/cs/api-longwords-module.texy | 19 - texy/cs/api-paragraph-module.texy | 4 - texy/cs/api-phrase-module.texy | 22 - texy/cs/api-script-module.texy | 23 - texy/cs/api-table-module.texy | 18 - texy/cs/api-texy.texy | 69 -- texy/cs/api-typography-module.texy | 21 - texy/cs/api-zaklady.texy | 25 - texy/cs/api.texy | 28 - texy/cs/architecture.texy | 425 ++++++++++++ texy/cs/configuration.texy | 719 ++++++++++++++++++++ texy/cs/custom-handlers.texy | 850 +++++++++++++++++++++++ texy/cs/custom-syntax.texy | 519 ++++++++++++++ texy/cs/develop.texy | 35 + texy/cs/priklady-vyuziti.texy | 26 - texy/cs/quickstart.texy | 205 ++++++ texy/cs/syntax-podrobne.texy | 889 ------------------------ texy/cs/syntax.texy | 997 +++++++++++++++++++-------- texy/cs/texy-vs-wysiwyg.texy | 23 - texy/en/@home.texy | 125 +++- texy/en/@menu.texy | 10 +- texy/en/@try.texy | 15 - texy/en/architecture.texy | 425 ++++++++++++ texy/en/configuration.texy | 719 ++++++++++++++++++++ texy/en/custom-handlers.texy | 850 +++++++++++++++++++++++ texy/en/custom-syntax.texy | 519 ++++++++++++++ texy/en/develop.texy | 35 + texy/en/quickstart.texy | 205 ++++++ texy/en/syntax-full.texy | 889 ------------------------ texy/en/syntax.texy | 1002 ++++++++++++++++++++-------- 44 files changed, 7159 insertions(+), 2984 deletions(-) delete mode 100644 texy/cs/@try.texy delete mode 100644 texy/cs/api-block-module.texy delete mode 100644 texy/cs/api-blockquote-module.texy delete mode 100644 texy/cs/api-emoticon-module.texy delete mode 100644 texy/cs/api-figure-module.texy delete mode 100644 texy/cs/api-heading-module.texy delete mode 100644 texy/cs/api-horizline-module.texy delete mode 100644 texy/cs/api-html-module.texy delete mode 100644 texy/cs/api-htmloutput-module.texy delete mode 100644 texy/cs/api-image-module.texy delete mode 100644 texy/cs/api-link-module.texy delete mode 100644 texy/cs/api-list-module.texy delete mode 100644 texy/cs/api-longwords-module.texy delete mode 100644 texy/cs/api-paragraph-module.texy delete mode 100644 texy/cs/api-phrase-module.texy delete mode 100644 texy/cs/api-script-module.texy delete mode 100644 texy/cs/api-table-module.texy delete mode 100644 texy/cs/api-texy.texy delete mode 100644 texy/cs/api-typography-module.texy delete mode 100644 texy/cs/api-zaklady.texy delete mode 100644 texy/cs/api.texy create mode 100644 texy/cs/architecture.texy create mode 100644 texy/cs/configuration.texy create mode 100644 texy/cs/custom-handlers.texy create mode 100644 texy/cs/custom-syntax.texy create mode 100644 texy/cs/develop.texy delete mode 100644 texy/cs/priklady-vyuziti.texy create mode 100644 texy/cs/quickstart.texy delete mode 100644 texy/cs/syntax-podrobne.texy delete mode 100644 texy/cs/texy-vs-wysiwyg.texy delete mode 100644 texy/en/@try.texy create mode 100644 texy/en/architecture.texy create mode 100644 texy/en/configuration.texy create mode 100644 texy/en/custom-handlers.texy create mode 100644 texy/en/custom-syntax.texy create mode 100644 texy/en/develop.texy create mode 100644 texy/en/quickstart.texy delete mode 100644 texy/en/syntax-full.texy diff --git a/texy/cs/@home.texy b/texy/cs/@home.texy index 3a23512250..cf88e684e4 100644 --- a/texy/cs/@home.texy +++ b/texy/cs/@home.texy @@ -1,32 +1,120 @@ Texy! je sexy! -============== +************** -Texy je program, díky kterému můžete snadno, bez odborných znalostí, psát texty na webové stránky. +.[perex] +Texy je **výkonný a bezpečný markup procesor** pro PHP, který převádí jednoduchý text do validního HTML. Na rozdíl od jiných markup jazyků není Texy jen další variantou Markdown – je to **plně konfigurovatelný systém**, který můžete přizpůsobit prakticky jakékoliv syntaxi. -Chcete zvýraznit písmo? Vytvořit nadpis či odrážky? Přidat obrázek nebo tabulku? Nemusíte zápasit se složitým textovým editorem. Stačí psát prostý text a Texy už úpravu zvládne za vás. Výsledkem bude hezky zformátovaná stránka. ---> [Vyzkoušejte si to | https://fiddle.nette.org/texy/] +Proč Texy? +========== -Texy dnes používají [tisíce spokojených uživatelů | napsali o Texy]. +Bezpečnost na prvním místě +-------------------------- -Co všechno umí? ---------------- +Texy je navrženo s důrazem na bezpečnost. Automaticky **chrání před XSS útoky**, validuje URL adresy a filtruje nebezpečné HTML značky. Vestavěný `safeMode()` je ideální pro zpracování uživatelského obsahu v komentářích nebo na fórech. -- vytvářet odkazy, odrážky, tabulky,... -- vkládat do textu obrázky -- zná českou typografii -- a navíc je **zdarma!** (pod licencí BSD a GPL) -- generuje vždy validní HTML kód -- vkládá pevné mezery za jednopísmenné předložky -- je dokonale konfigurovatelné a přizpůsobitelné +```php +Texy\Configurator::safeMode($texy); +// Nyní je Texy bezpečné pro obsah od uživatelů +``` -Objevte Texy! -------------- +Konfigurovatelnost bez kompromisů +--------------------------------- + +Chcete používat Markdown syntaxi? Nebo potřebujete úplně vlastní markup? **Texy to zvládne.** Můžete: + +- Vypnout nebo zapnout libovolné části syntaxe +- Změnit výchozí chování pomocí handlerů +- Přidat zcela vlastní syntaktické prvky +- Nakonfigurovat Texy tak, aby zpracovávalo Markdown nebo jakýkoliv jiný formát + +```php +$texy = new Texy; +$texy->allowed['image'] = false; // vypnout obrázky +$texy->allowed['phrase/strong'] = false; // vypnout tučné písmo +``` + + +České typografické speciality +----------------------------- + +Texy **dokonale rozumí češtině**. Automaticky: + +- Vkládá **pevné mezery** za jednopísmenné předložky a spojky: v autě, u okna, s kamarádem +- Rozděluje **dlouhá slova** podle slabik: nejneobhospodařovávatelnějšími +- Používá správné **typografické uvozovky**: „dvojité" a ‚jednoduché' +- Zaměňuje **spojovník za pomlčku**: 10–15 vs. česko-slovenský +- Přidává **nezalomitelné mezery** u telefonních čísel: +420 776 552 046 + + +Validní a wellformed HTML +------------------------- + +Texy generuje **vždy validní HTML5 kód**. Automaticky opravuje chybně vnořené značky, uzavírá nezavřené elementy a dbá na správnou strukturu dokumentu. Výstup je nejen validní, ale i **pěkně naformátovaný** s odsazením. + + +Co je Texy? +=========== + +Texy je **obecný procesor markup textu**. To znamená, že má sice svou výchozí syntaxi (podobnou Markdown, ale mnohem bohatší), ale můžete ji kompletně změnit nebo rozšířit. + +**Není to jen parser** – Texy je komplexní systém s modulární architekturou, kde každý modul zpracovává konkrétní část syntaxe (nadpisy, odkazy, obrázky, tabulky...). Díky systému handlerů můžete zasáhnout do libovolného bodu zpracování a změnit výsledek podle svých potřeb. + + +Texy vs. Markdown +================= + +Základní syntaxe je podobná, ale Texy nabízí mnohem více: + +|--------------------------- +| Funkce | Markdown | Texy +|--------------------------- +| Tučné písmo | `**text**` | `**text**` +| Kurzíva | `*text*` nebo `_text_` | `*text*` nebo `//text//` +| Nadpisy | `# Nadpis` | `# Nadpis` nebo podtržení +| Obrázky | `![alt](url)` | `[* url *]` +| Tabulky | omezené | plná podpora včetně sloučení +| Modifikátory | ne | ano – `.{color:red}[class]` +| Typografie | ne | ano – uvozovky, pomlčky, mezery +| Dělení slov | ne | ano – podle slabik +| Konfigurovatelnost | omezená | úplná – vlastní syntaxe +| Bezpečnost | závisí na impl. | vestavěná (safeMode) + +**Příklad rozdílů:** + +```texy +Markdown: +![Obrázek](image.jpg) + +Texy: +[* image.jpg 300x200 .(Popisek obrázku)[photo] <] +``` + +Texy umožňuje definovat rozměry, třídy, zarovnání a mnoho dalšího přímo v syntaxi. + + +Kdy použít Texy? +================ + +Texy je ideální pro: + +**CMS systémy** Potřebujete bezpečně zpracovávat obsah od editorů? Texy nabízí granulární kontrolu nad tím, co mohou uživatelé použít. + +**Blogy a dokumentace** Bohatá syntaxe pro tabulky, obrázky s popiskami, typografii a kód s syntax highlightingem. + +**Komentáře a diskuzní fóra** SafeMode zajistí, že uživatelé nemohou vložit nebezpečný kód, ale zároveň mají k dispozici formátování textu. + +**Projekty s vlastními požadavky** Potřebujete embed YouTube videí? Speciální syntax pro vaše makra? Vlastní markup jazyk? S Texy to vytvoříte snadno. + + +Historie +======== + +Texy vytvořil David Grudl před **20 lety** v roce 2004 jako jeden z prvních markup procesorů pro PHP. Původně bylo vyvinuto pro **PHP 4**, ale během své dlouhé historie prošlo mnoha aktualizacemi a dnes plně využívá všech možností **PHP 8**. + +Přes dvě dekády aktivního vývoje znamenají **vyzkoušenou a stabilní** knihovnu, které důvěřují stovky projektů. Texy je dnes **mature řešení** s velkou historií, ale stále aktivně udržované a moderní. -- Srovnání [Texy versus WYSIWYG editory | texy-vs-wysiwyg] -- [Příklady využití | priklady-vyuziti] -- [Základy syntaxe | syntax] {{maintitle: Texy – formátovač textů pro PHP}} diff --git a/texy/cs/@menu.texy b/texy/cs/@menu.texy index eb7458d858..bc703bedfb 100644 --- a/texy/cs/@menu.texy +++ b/texy/cs/@menu.texy @@ -1,8 +1,7 @@ -- [úvodní stránka | @home] -- [syntax stručně | syntax] -- [syntax podrobně | syntax-podrobne] -- [fiddle | https://fiddle.nette.org/texy/] -- [manuál | api] -- [blog | https://phpfashion.com/category/texy] -- [API | https://api.nette.org/texy/] -- [GitHub | https://github.com/dg/texy] +- [úvod | @home] +- [syntaxe | syntax] +- [pro programátory | develop] +- "blog .[link-external]":https://phpfashion.com/category/texy +- "hřiště .[link-external]":https://fiddle.nette.org/texy/ +- "API .[link-external]":https://api.nette.org/texy/ +- "GitHub .[link-external]":https://github.com/dg/texy diff --git a/texy/cs/@try.texy b/texy/cs/@try.texy deleted file mode 100644 index 9c443df131..0000000000 --- a/texy/cs/@try.texy +++ /dev/null @@ -1,15 +0,0 @@ -Vítejte! --------- - -Můžete používat syntax Texy!, pokud Vám vyhovuje: -- třeba **tučné** písmo nebo *kurzíva* -- a takto se dělá "odkaz":https://texy.info -- více najdete na stránce "syntax":[syntax] - - -Ale také můžete zůstat u HTML: -- takto <b>HTML</b> -- nebo i <b class=xx>úplně <i>hloupě</b>, Texy! to pořeší - - -[syntax]: /cs/syntax diff --git a/texy/cs/api-block-module.texy b/texy/cs/api-block-module.texy deleted file mode 100644 index aae50f9b19..0000000000 --- a/texy/cs/api-block-module.texy +++ /dev/null @@ -1,11 +0,0 @@ -Třída Texy\Modules\BlockModule -****************************** - -Má na starosti zpracování bloků `/-- xxx`. Modul vypneme zakázáním syntaxe `blocks`: - -/--code php -$texy->allowed['blocks'] = false; - -// nebo pro jednotlivé typy bloků -$texy->allowed['block/code'] = false; -\-- diff --git a/texy/cs/api-blockquote-module.texy b/texy/cs/api-blockquote-module.texy deleted file mode 100644 index b9fd28e72a..0000000000 --- a/texy/cs/api-blockquote-module.texy +++ /dev/null @@ -1,8 +0,0 @@ -Třída Texy\Modules\BlockQuoteModule -*********************************** - -Má na starosti blokové citace. Modul vypneme zakázáním syntaxe `blockquote`: - -/--code php -$texy->allowed['blockquote'] = false; -\-- diff --git a/texy/cs/api-emoticon-module.texy b/texy/cs/api-emoticon-module.texy deleted file mode 100644 index 8f0f8fa475..0000000000 --- a/texy/cs/api-emoticon-module.texy +++ /dev/null @@ -1,47 +0,0 @@ -Třída Texy\Modules\EmoticonModule -********************************* - -Má na starosti nahrazování smajlíků za obrázky. Ve výchozím nastavení je modul vypnutý, zapneme jej povolením syntaxe `emoticon`: - -/--code php -$texy->allowed['emoticon'] = true; -\-- - - -Konfigurace ------------ - -|---------------- -| proměnná | typ | výchozí | popis | -|---------------- -| $icons | array | | tabulka všech smajlíků a odpovídajících obrázků -| $class | string | null | CSS třída -| $root | string | | kořenový adresář obrázků na webu -| $fileRoot | string | | kořenový adresář obrázků na disku - -Pokud nenastavíte hodnoty pro `$root` a `$fileRoot`, použijí se ty z modulu [Texy\Modules\ImageModule|api-image-module]. Výchozí seznam smajlíků je tento: - -/--code php -$icons = [ - ':-)' => 'smile.gif', - ':-(' => 'sad.gif', - ';-)' => 'wink.gif', - ':-D' => 'biggrin.gif', - '8-O' => 'eek.gif', - '8-)' => 'cool.gif', - ':-?' => 'confused.gif', - ':-x' => 'mad.gif', - ':-P' => 'razz.gif', - ':-|' => 'neutral.gif', -]; -\-- - -Můžete jej pozměnit přímo zásahem do pole: - -/--code php -$texy->emoticonModule->icons[':-)'] = 'smile.png'; - -unset($texy->emoticonModule->icons[':-P']); -\-- - -Poslední znak smajlíku se může opakovat, tedy klíč. `:-)` akceptuje i smajlík v podobě `:-)))`. diff --git a/texy/cs/api-figure-module.texy b/texy/cs/api-figure-module.texy deleted file mode 100644 index db0d483886..0000000000 --- a/texy/cs/api-figure-module.texy +++ /dev/null @@ -1,33 +0,0 @@ -Třída Texy\Modules\FigureModule -******************************* - -Má na starosti obrázky s popiskou. Module vypneme zakázáním syntaxe `figure`: - -/--code php -$texy->allowed['figure'] = false; -\-- - - -Konfigurace ------------ - -|---------------- -| proměnná | typ | výchozí | popis | -|---------------- -| $class | string | `'figure'` | třída neplovoucího kontejneru `<div>` -| $leftClass | string | null | třída `<div>` plovoucího vlevo -| $rightClass | string | null | třída `<div>` plovoucího vpravo -| $widthDelta | int | 10 | offset pro výpočet šířky - - -Neplovoucím kontejnerům `<div>` bude přiřazena třída `$class`, plovoucím `$leftClass` nebo `$rightClass`. Pokud není specifikována třída u plovoucích kontejnerů, Texy ji sestaví takto: - -`$texy->figureModule->class . '-' . $texy->alignClasses['left'] resp. 'right'` - -Není-li nastavená třída ani v poli `$alignClasses`, Texy kontejner zarovnává CSS vlastností `float`. - -U plovoucích kontejnerů Texy počítá a nastavuje šířků podle vzorce: - -`šířka <div> = šířka obrázku <img> + $widthDelta` - -Je tedy nutné zjistit šířku obrázku. K tomu je potřeba korektně nastavit cestu `$texy->imageModule->fileRoot`, viz [Texy\Modules\ImageModule | api-image-module]. diff --git a/texy/cs/api-heading-module.texy b/texy/cs/api-heading-module.texy deleted file mode 100644 index 701de25493..0000000000 --- a/texy/cs/api-heading-module.texy +++ /dev/null @@ -1,42 +0,0 @@ -Třída Texy\Modules\HeadingModule -******************************** - -Má na starosti nadpisy a titulky. Module (de)aktivujeme zakázáním syntaxe: - -/--code php -// podtržené titulky -$texy->allowed['heading/underlined'] = false; - -// ohraničené titulky -$texy->allowed['heading/surrounded'] = false; -\-- - - -Konfigurace ------------ - -|---------------- -| proměnná | typ | výchozí | popis | -|---------------- -| $title | string | null | nejvyšší titulek -| $TOC | array | | zde se vygeneruje obsah -| $generateID | boolean| false | generovat titulkům ID? -| $idPrefix | string | `'toc-'` | prefix pro generované ID -| $top | int | 1 | strop, úroveň nejvyššího titulku -| $moreMeansHigher | boolean | true | více znaků znamená vyšší titulek -| $balancing | int | *dynamic* | způsob vážení titulků -| $levels | array | | tabulka vážení titulků - -Po zpracování textu bude první titulek uložen do proměnné $title (bez HTML kódování, tedy vhodné pro použití v `<title>`). - -Způsob vážení titulků určuje $balancing, které může nabývat hodnot `Texy\Modules\HeadingModule::DYNAMIC` (výchozí) nebo `Texy\Modules\HeadingModule::FIXED`. Více informací [ve fóru | https://forum.texy.info/cs/viewtopic.php?pid=22]. - - -Příklady --------- - -Nejvyšší titulek bude mít úroveň `<h2>` - -/--code php -$texy->headingModule->top = 2; -\-- diff --git a/texy/cs/api-horizline-module.texy b/texy/cs/api-horizline-module.texy deleted file mode 100644 index ebbd47da44..0000000000 --- a/texy/cs/api-horizline-module.texy +++ /dev/null @@ -1,8 +0,0 @@ -Třída Texy\Modules\HorizLineModule -********************************** - -Má na starosti horizontální čáry. Modul vypneme zakázáním syntaxe `horizline`: - -/--code php -$texy->allowed['horizline'] = false; -\-- diff --git a/texy/cs/api-html-module.texy b/texy/cs/api-html-module.texy deleted file mode 100644 index f925f2ade8..0000000000 --- a/texy/cs/api-html-module.texy +++ /dev/null @@ -1,21 +0,0 @@ -Třída Texy\Modules\HtmlModule -***************************** - -Má na starosti HTML značky a komentáře na vstupu. Modul vypneme zakázáním syntaxe: - -/--code php -// vypneme HTML značky -$texy->allowed['html/tag'] = false; - -// vypneme HTML komentáře -$texy->allowed['html/comment'] = false; -\-- - - -Konfigurace ------------ - -|---------------- -| proměnná | typ | výchozí | popis | -|---------------- -| $passComment | boolean | true | zobrazit HTML komentáře na výstupu? diff --git a/texy/cs/api-htmloutput-module.texy b/texy/cs/api-htmloutput-module.texy deleted file mode 100644 index ec049261fa..0000000000 --- a/texy/cs/api-htmloutput-module.texy +++ /dev/null @@ -1,17 +0,0 @@ -Třída Texy\Modules\HtmlOutputModule -*********************************** - -Má na starosti formátování výstupního XHTML / HTML. Formátuje výsledné HTML a zároveň hlídá a koriguje "wellformed" zápis. - - -Konfigurace ------------ - -|---------------- -| proměnná | typ | výchozí | popis | -|---------------- -| $indent | boolean | true | formátovat výstup do úhledné podoby? -| $baseIndent | int | 0 | minimální odsazení každého řádku -| $lineWrap | int | 80 | maximální šířka řádku - -Volitelné koncové značky se odstraňují pouze v režimu HTML. Zalamování řádků lze vypnout nastavením `$texy->htmlOutputModule->lineWrap = false`. diff --git a/texy/cs/api-image-module.texy b/texy/cs/api-image-module.texy deleted file mode 100644 index bebde249b3..0000000000 --- a/texy/cs/api-image-module.texy +++ /dev/null @@ -1,35 +0,0 @@ -Třída Texy\Modules\ImageModule -****************************** - -Má na starosti obrázky. Tzv. obrázky s popiskou zpracovává [Texy\Modules\FigureModule|api-figure-module]. Modul vypneme zakázáním syntaxe: - -/--code php -// zákaz obrázků -$texy->allowed['image'] = false; - -// zákaz referencí -$texy->allowed['image/definition'] = false; -\-- - - -Konfigurace ------------ - -|---------------- -| proměnná | typ | výchozí | popis | -|---------------- -| $root | string | `'images/'` | kořenový adresář obrázků na webu -| $linkedRoot | string | `'images/'` | kořenový adresář obrázků v pozici odkazu -| $fileRoot | string | | kořenový adresář obrázků na disku -| $leftClass | string | null | třída obrázku plovoucího vlevo -| $rightClass | string | null | třída obrázku plovoucího vpravo -| $defaultAlt | string | `''` | výchozí hodnota atributu `alt` - - -Fyzická cesta k obrázkům `$fileRoot` se používá ke zjištění jich rozměrů, které se pak uvedou v HTML výstupu. Modul se cestu pokusí detekovat z prostředí serveru, nicméně je vhodnější ji nastavit manuálně. - -Proměnná `$linkedRoot` určuje kořenový adresář obrázků, které jsou použity jako cíl odkazu, tedy `[odkaz | * img.jpg *]`. - -Plovoucím obrázkům je nastavena třída `$leftClass` resp. `$rightClass`, nebo `$texy->alignClasses['left']` resp. `'right'`. Pokud není ani jedno specifikováno, Texy obrázky zarovnává CSS vlastností `float`. - -Protože Texy umí překlápět obrázky při přejetí myškou (onmouseover efekt), je nutné zajistit včasné načtení těchto obrázků (preload). K tomu slouží děsně fikaný skript, který se aktivuje událostí `onload` u jednotlivých obrázků. Skript je uložen v proměnné `$onLoad`. diff --git a/texy/cs/api-link-module.texy b/texy/cs/api-link-module.texy deleted file mode 100644 index f9fc26e49a..0000000000 --- a/texy/cs/api-link-module.texy +++ /dev/null @@ -1,42 +0,0 @@ -Třída Texy\Modules\LinkModule -***************************** - -Má na starosti definice, reference, odkazy. Modul vypneme zakázáním syntaxe: - -/--code php -// vypnout zpracování definicí [ref]: www.texy.info -$texy->allowed['link/definition'] = false; - -// vypnout zpracování referencí [ref] -$texy->allowed['link/reference'] = false; - -// vypnout dělání www adres klikatelnými -$texy->allowed['link/url'] = false; - -// vypnout dělání emailových adres klikatelnými -$texy->allowed['link/email'] = false; -\-- - - -Konfigurace ------------ - -|---------------- -| proměnná | typ | výchozí | popis | -|---------------- -| $root | string | `''` | kořenový adresář relativních odkazů -| $imageClass | string | | třída pro odkazy vedoucí na obrázky (od Texy 2.2) -| $forceNoFollow | boolean | false | doplňovat `rel="nofollow"`? -| $shorten | boolean | true | zkracovat URL? - -Texy automaticky doplňuje atribut nofollow odkazům, které mají pseudotřídu `nofollow`, např. `"odkaz .[nofollow]":www.texy.info`. - - -Příklad -------- - -Chceme přidávat nofollow ke všem odkazům - -/--code php -$texy->linkModule->forceNoFollow = true; -\-- diff --git a/texy/cs/api-list-module.texy b/texy/cs/api-list-module.texy deleted file mode 100644 index 222f9d94e4..0000000000 --- a/texy/cs/api-list-module.texy +++ /dev/null @@ -1,12 +0,0 @@ -Třída Texy\Modules\ListModule -***************************** - -Má na starosti číslované, nečíslované a definiční seznamy. Modul vypneme zakázáním syntaxe: - -/--code php -// číslované a nečíslované seznamy -$texy->allowed['list'] = false; - -// definiční listy -$texy->allowed['list/definition'] = false; -\-- diff --git a/texy/cs/api-longwords-module.texy b/texy/cs/api-longwords-module.texy deleted file mode 100644 index 00c5ca765a..0000000000 --- a/texy/cs/api-longwords-module.texy +++ /dev/null @@ -1,19 +0,0 @@ -Třída Texy\Modules\LongWordsModule -********************************** - -Má na starosti rozdělení dlouhých slov. Modul vypneme zakázáním syntaxe `longwords`: - -/--code php -$texy->allowed['longwords'] = false; -\-- - - -Konfigurace ------------ - -|---------------- -| proměnná | typ | výchozí | popis | -|---------------- -| $wordLimit | int | 20 | maximální délka slova - -Texy vkládá do příliš dlouhých slov (nad $wordLimit) značku volitelného zalomení `­`. Snaží se přitom respektovat specifika dělení slov na slabiky. diff --git a/texy/cs/api-paragraph-module.texy b/texy/cs/api-paragraph-module.texy deleted file mode 100644 index 28b10e479e..0000000000 --- a/texy/cs/api-paragraph-module.texy +++ /dev/null @@ -1,4 +0,0 @@ -Třída Texy\Modules\ParagraphModule -********************************** - -Má na starosti jednotlivé odstavce textu. diff --git a/texy/cs/api-phrase-module.texy b/texy/cs/api-phrase-module.texy deleted file mode 100644 index c978f68adc..0000000000 --- a/texy/cs/api-phrase-module.texy +++ /dev/null @@ -1,22 +0,0 @@ -Třída Texy\Modules\PhraseModule -******************************* - -Má na starosti tzv. fráze, tedy úseky textu (tučný text, odkaz, ...). Můžeme vypínat a zapínat jednotlivé syntaxe: - -/--code php -$texy->allowed['phrase/strong'] = false; -... -\-- - - -Konfigurace ------------ - -|---------------- -| proměnná | typ | výchozí | popis | -|---------------- -| $tags | array | | HTML značky pro jednotlivé fráze -| $linksAllowed | boolean | true | je možné k frázi přidat odkaz? - - -Pod pojmem fráze se rozumí jakákoliv řádková syntax jako `**tučné**`, `//kurzíva//`, `subskript_2`, `[odkaz | www.texy.info`]. diff --git a/texy/cs/api-script-module.texy b/texy/cs/api-script-module.texy deleted file mode 100644 index 0e3ace4d82..0000000000 --- a/texy/cs/api-script-module.texy +++ /dev/null @@ -1,23 +0,0 @@ -Třída Texy\Modules\ScriptModule -******************************* - -Má na starosti volání uživatelských funkcí a vkládání externích dat. Modul vypneme zakázáním syntaxe `script`: - -/--code php -$texy->allowed['script'] = false; -\-- - - -Konfigurace ------------ - -|---------------- -| proměnná | typ | výchozí | popis | -|---------------- -| $separator | string | `';'` | oddělovat argumentů - - -Příklady --------- - -Najdete ve [fóru | https://forum.texy.info/cs/viewtopic.php?pid=1954]. diff --git a/texy/cs/api-table-module.texy b/texy/cs/api-table-module.texy deleted file mode 100644 index 6114f24229..0000000000 --- a/texy/cs/api-table-module.texy +++ /dev/null @@ -1,18 +0,0 @@ -Třída Texy\Modules\TableModule -****************************** - -Má na starosti tabulky. Modul vypneme zakázáním syntaxe `table`: - -/--code php -$texy->allowed['table'] = false; -\-- - - -Konfigurace ------------ - -|---------------- -| proměnná | typ | výchozí | popis | -|---------------- -| $oddClass | string | null | CSS třída přiřazená lichým řádkům tabulky -| $evenClass | string | null | CSS třída přiřazená sudým řádkům tabulky diff --git a/texy/cs/api-texy.texy b/texy/cs/api-texy.texy deleted file mode 100644 index 6eba43a35c..0000000000 --- a/texy/cs/api-texy.texy +++ /dev/null @@ -1,69 +0,0 @@ -Třída Texy\Texy -*************** - -|---------------- -| proměnná | typ | výchozí | popis | -|---------------- -| `$allowed` | mixed | | povolené "Texy syntaxe" -| `$allowedTags` | mixed | *validní značky* | povolené HTML značky -| `$allowedClasses` | mixed | Texy::ALL | povolené CSS třídy a identifikátory -| `$allowedStyles` | mixed | Texy::ALL | povolené CSS styly -| `$alignClasses` | array | *vynulované* | CSS třídy pro zarovnání textu a obrázků -| `$mergeLines` | boolean | true | spojovat řádky? -| `$tabWidth` | int | 8 | šířka tabulátorů kvůli převední na mezery -| `$obfuscateEmail` | boolean| true | maskovat emailové adresy před roboty? -| `$urlSchemeFilters` | array| null | - - -Proměnné `$allowedTags`, `$allowedClasses` a `$allowedStyles` mohou nabývat hodnot: - -- `Texy::ALL` - jsou povoleny všechny HTML značky resp. styly resp. třídy -- `Texy::NONE` - naopak jsou všechny zakázány -- *array* - výčet povolených hodnot - - `$allowedTags` - povolené značky tvoří klíče, viz příklady níže - - `$allowedClasses` - seznam tříd a ID, přičemž ID začínají prefixem # - - `$allowedStyles` - seznam CSS vlastností - -Pole `$alignClasses` definuje CSS třídy pro zarovnání textu a obrázků. Blíže popsáno [ve fóru | https://forum.texy.info/cs/viewtopic.php?id=532]. - -Texy spojuje řádky následující za sebou do odstavců. Toto chování je možné vypnout nastavením vlastnosti `$texy->mergeLines = false`. - - -Příklady --------- - -Povolíme pouze HTML elementy `<strong>, <div>, <a>` a některé jejich atributy: - -/--code php -$texy->allowedTags = [ - 'strong' => Texy::NONE, // <strong> nesmí mít žádné attributy - 'div' => Texy::ALL, // <div> může mít jakékoliv atributy - 'a' => ['href', 'lang', 'target'], // <a> může mít jen tyto atributy -]; -\-- - -Všechny HTML značky zakážeme: - -/--code php -$texy->allowedTags = Texy::NONE; -\-- - -Povolíme pouze CSS třídy `class1, class2` a CSS identifikátory `id1, id2` - -/--code php -$texy->allowedClasses = ['class1', 'class2', '#id1', '#id2']; -\-- - -Povolíme pouze CSS vlastnosti `font-size, color, width` - -/--code php -$texy->allowedStyles = ['font-size', 'color', 'width']; -\-- - -Místo přímých stylů `style="text-align:left"` apod. používej třídy `class="left"` apod. - -/--code php -$texy->alignClasses['left'] = 'left'; -$texy->alignClasses['right'] = 'right'; -... // dále možno definovat: center, justify, top, bottom, middle -\-- diff --git a/texy/cs/api-typography-module.texy b/texy/cs/api-typography-module.texy deleted file mode 100644 index a66748609f..0000000000 --- a/texy/cs/api-typography-module.texy +++ /dev/null @@ -1,21 +0,0 @@ -Třída Texy\Modules\TypographyModule -*********************************** - -Má na starosti typografické úpravy výsledného textu. Modul vypneme zakázáním syntaxe `typography`: - -/--code php -$texy->allowed['typography'] = false; -\-- - - -Konfigurace ------------ - -|---------------- -| proměnná | typ | výchozí | popis | -|---------------- -| $locale | string | `'cs'` | určení národních specifik -| static $locales | array | | předvolená specifika - - -Vlastnost $locale může nabývat hodnot: cs, en, fr, de, pl. Další specifika lze doplnit do statické proměnné $locales. diff --git a/texy/cs/api-zaklady.texy b/texy/cs/api-zaklady.texy deleted file mode 100644 index 3672e3ba65..0000000000 --- a/texy/cs/api-zaklady.texy +++ /dev/null @@ -1,25 +0,0 @@ -Základní dovednosti -******************* - -Jak přeformátovat text do HTML? Stačí do kódu začlenit knihovnu Texy, například pomocí Composeru: - -/-- -composer require texy/texy -\-- - -A vytvořit objekt `$texy = new Texy\Texy;`. Celý převod obstará metoda `$html = $texy->process($text)`, kde proměnná `$text` obsahuje vstupní text a vrací se zformátovaný HTML výstup. - -/--php -// vytvoříme objekt -$texy = new Texy\Texy; - -// můžeme jej nakonfigurovat -$texy->imageModule->root = 'images/'; - -// a zpracujeme vstupní $text -$html = $texy->process($text); -\-- - -Pokud potřebujete formátovat jednořádkový text (tedy bez blokových elementů), použijte `$html = $texy->processLine($text)`. - -V ukázce vidíte, jak je možné objekt `$texy` konfigurovat. Protože parametrů je hodně, jsou rozčleněny do logických celků označovaných jako moduly. Instance každého modulu je uložena v atributu `$texy->blockModule`, `$texy->emoticonModule` atd. (viz [jednotlivé moduly | api#moduly]). diff --git a/texy/cs/api.texy b/texy/cs/api.texy deleted file mode 100644 index e0d5c9e4db..0000000000 --- a/texy/cs/api.texy +++ /dev/null @@ -1,28 +0,0 @@ -Programátorský manuál -********************* - -Texy je napsané v objektovém PHP. Minimální požadovaná verze pro Texy 3.0 je PHP 7.1. - ---> [Základní dovednosti | api-zaklady] - ---> [API dokumentace | https://api.nette.org/texy/] - ---> Jednotlivé moduly: .[#moduly] -- [Texy\Texy | api-texy] - jádro Texy -- [Texy\Modules\BlockModule | api-block-module] - zpracování bloků `/-- xxx` -- [Texy\Modules\BlockQuoteModule | api-blockquote-module] - blokové citace -- [Texy\Modules\EmoticonModule | api-emoticon-module] - nahrazování smajlíků za obrázky -- [Texy\Modules\FigureModule | api-figure-module] - obrázky s popiskou -- [Texy\Modules\HeadingModule | api-heading-module] - nadpisy, titulky -- [Texy\Modules\HorizLineModule | api-horizline-module] - horizontální čáry -- [Texy\Modules\HtmlModule | api-html-module] - HTML značky a komentáře na vstupu -- [Texy\Modules\HtmlOutputModule | api-htmloutput-module] - formátování výstupního HTML -- [Texy\Modules\ImageModule | api-image-module] - obrázky -- [Texy\Modules\LinkModule | api-link-module] - odkazy a reference -- [Texy\Modules\ListModule | api-list-module] - číslované, nečíslované a definiční seznamy -- [Texy\Modules\LongWordsModule | api-longwords-module] - rozdělení dlouhých slov -- [Texy\Modules\ParagraphModule | api-paragraph-module] - jednotlivé odstavce textu -- [Texy\Modules\PhraseModule | api-phrase-module] - fráze, tedy úseky textu (tučný text, odkaz, ...) -- [Texy\Modules\ScriptModule | api-script-module] - volání uživatelských funkcí -- [Texy\Modules\TableModule | api-table-module] - tabulky -- [Texy\Modules\TypographyModule | api-typography-module] - typografické úpravy výsledného textu diff --git a/texy/cs/architecture.texy b/texy/cs/architecture.texy new file mode 100644 index 0000000000..bf213b08f0 --- /dev/null +++ b/texy/cs/architecture.texy @@ -0,0 +1,425 @@ +Architektura a principy +####################### + +.[perex] +Texy je nástroj pro převod textu napsaného ve vlastním markup jazyce do HTML. Na rozdíl od jednoduchých převodníků, které text zpracovávají lineárně pomocí série náhrad, používá Texy sofistikovaný systém založený na parsování, modulární architektuře a postupném budování DOM stromu. + +Základní tok zpracování probíhá ve čtyřech hlavních fázích: + +1. Předzpracování textu - normalizace, úprava mezer a tabulátorů, volání notification handlerů pro přípravu +2. Parsování - rozpoznání syntaxí pomocí regulárních výrazů a postupné budování DOM stromu +3. Post-processing - typografické úpravy, zpracování dlouhých slov, wellforming HTML +4. Finální sestavení - konverze DOM stromu do HTML řetězce + +Klíčovým rozdílem oproti naivním přístupům je oddělení fáze rozpoznávání syntaxí od jejich zpracování. Parser nejprve identifikuje, kde se v textu nachází která syntaktická konstrukce, a teprve poté předává nalezené části jednotlivým modulům ke zpracování. To umožňuje vnořování syntaxí a jejich postupné rozbalování. + +*Poznámka: všechny třídy se nacházejí ve jmenném prostoru `Texy`, takže pokud dokument zmiňuje například třídu `HtmlElement`, její plný název je `Texy\HtmlElement`. Moduly jsou ve jmenném prostoru `Texy\Modules`* + + +Klíčové komponenty +================== + +Architektura Texy se skládá z několika hlavních komponent, z nichž každá má jasně vymezenou zodpovědnost: + +Třída Texy funguje jako centrální orchestrátor celého systému. Obsahuje odkazy na všechny moduly, spravuje registrované syntaxe a handlery, udržuje stav zpracování a koordinuje jednotlivé fáze konverze. Je to jediné místo, kde se jednotlivé komponenty propojují. + +**[#Moduly]** představují funkční jednotky zodpovědné za konkrétní oblasti markup jazyka. Každý modul při své konstrukci registruje syntaxe, které rozpoznává, a element handlery, které je zpracovávají. Například PhraseModule se stará o inline formátování jako tučný nebo kurzívou psaný text, zatímco TableModule zpracovává tabulky. Moduly jsou navrženy jako samostatné, znovupoužitelné jednotky s vlastní konfigurací přístupnou přes veřejné properties. + +**[#Parsery]** existují ve dvou variantách podle typu zpracovávaného obsahu. BlockParser zpracovává blokové struktury jako odstavce, nadpisy, seznamy nebo tabulky. Prochází text po řádcích, hledá začátky blokových konstrukcí a předává je *syntax handlerům*. LineParser se stará o inline syntaxe uvnitř řádků - odkazy, obrázky, formátování textu. Na rozdíl od BlockParser umožňuje vnořování syntaxí a jejich postupné rozbalování. + + +Základní terminologie +===================== + +Pro správné pochopení fungování Texy je nutné rozlišovat několik klíčových pojmů, které se v dokumentaci často objevují. + +**Syntax** označuje pojmenovanou syntaktickou konstrukci markup jazyka. Každá syntax má jedinečný název, například `phrase/strong` pro tučný text nebo `image` pro obrázky. Název syntaxe se používá pro její zapnutí či vypnutí v poli `Texy::$allowed` a předává se jako parametr do syntax handlerů pro rozlišení, která konkrétní syntax byla nalezena. + +**Pattern** je regulární výraz, který definuje, jak syntax vypadá v textu. Pattern je implementační detail syntaxe - autor syntaxe musí napsat regex, který ji rozpozná, ale z pohledu uživatele Texy je podstatnější název syntaxe a její význam. Jeden modul typicky registruje více syntaxí s různými patterny. + +**Syntax handler** je funkce volaná parserem ve chvíli, kdy najde výskyt syntaxe v textu. Dostává nalezený text a vrací `HtmlElement` nebo řetězec, který se vloží na původní místo. Syntax handler je místem, kde se rozhoduje, co se s nalezenou syntaxí stane - typicky vyvolá element handler pro vlastní zpracování. + +**Element** je prvek, pro který se generuje HTML reprezentace. Například `image` je element pro obrázky, `linkURL` pro odkazy, `phrase` pro inline formátování. Každý element má svůj výchozí element handler, který se stará o standardní zpracování. + +**Element handler** je funkce registrovaná pro určitý typ prvků a volaná přes systém HandlerInvocation. Charakteristické je použití metody `proceed()`, která umožňuje delegovat zpracování na další handler v řetězu nebo na výchozí handler modulu. Element handlery slouží k modifikaci nebo nahrazení výchozího chování. + +**Notification handler** je funkce volaná pro notifikaci o určité události. Na rozdíl od element handlerů nevrací žádnou hodnotu a nemůže ovlivnit výsledek zpracování. Používá se pro přípravu dat, logování nebo modifikace již vytvořeného DOM stromu. + +Rozdíl mezi jednotlivými handlery je klíčový pro pochopení architektury. Syntax handler je těsně svázán s parserem a konkrétním patternem - řeší otázku *co dělat, když parser najde tento pattern*. Element handlery jsou na vyšší úrovni abstrakce - řeší otázku *jak zpracovat tento typ prvku*, bez ohledu na to, která konkrétní syntax ji vytvořila. + + +Celkový tok zpracování +====================== + +Když Texy dostane vstupní text, projde následujícím procesem zpracování. + +V předzpracování dochází k normalizaci textu. Koncové značky řádků se sjednotí na Unix formát, mezery se standardizují a tabulátory se případně nahradí mezerami. Následně se vyvolají *notification handlery* registrované pro událost `beforeParse`. Tyto handlery mohou provést přípravu dat, například načíst definice referencí nebo upravit konfiguraci podle obsahu textu. + +Samotné parsování začíná vytvořením kořenového `HtmlElement`, který reprezentuje dokument. Texy pak rozhodne, zda text zpracovat jako jeden řádek nebo jako kompletní dokument s blokovými strukturami. V případě blokového zpracování se vytvoří BlockParser, který postupně prochází text a hledá jednotlivé blokové konstrukce. + +LineParser pracuje jinak než BlockParser. Neprochází text lineárně, ale postupně hledá nejbližší výskyt jakékoliv registrované syntaxe. Když nějakou najde, zavolá příslušný syntax handler, který vytvoří odpovídající HTML element. Tento element se pomocí speciálního maskování vloží zpět do textu a parser pokračuje dál. Díky tomu může najít a zpracovat syntaxe vnořené uvnitř již zpracovaných konstrukcí. + +Po dokončení parsování vznikne kompletní DOM strom reprezentující strukturu dokumentu. Texy vyvolá notification handlery pro událost `afterParse`, které mohou provést závěrečné úpravy stromu, například doplnit identifikátory nadpisů nebo sestavit obsah. + +Post-processing probíhá během konverze DOM stromu na HTML řetězec. Každý element se rekurzivně převádí na HTML kód, přičemž se aplikují typografické úpravy jako nahrazení uvozovek, pomlček nebo vkládání nezlomitelných mezer. Dále se provádí wellforming HTML - automatické uzavírání tagů, oprava špatně vnořených elementů, formátování a odsazování kódu. + +Finální fází je dekódování všech maskovaných částí zpět na HTML tagy, odstranění pomocných značek a sestavení výsledného HTML řetězce. + + +Systém syntaxí +************** + +Syntax v terminologii Texy představuje pojmenovanou syntaktickou konstrukci markup jazyka. Je to abstraktní koncept spojující několik prvků: unikátní název, regulární výraz pro rozpoznání a způsob zpracování. Název syntaxe slouží jako identifikátor v celém systému - používá se v poli `Texy::$allowed` pro zapnutí či vypnutí, předává se do handlerů pro rozlišení typu konstrukce a objevuje se v dokumentaci a konfiguračních souborech. + +Jmenné konvence syntaxí následují dva hlavní vzory. Jednodušší syntaxe mají jednoslovný název odpovídající jejich účelu, například `image`, `table` nebo `script`. Složitější oblasti používají hierarchické pojmenování se lomítkem, například `phrase/strong`, `phrase/em` nebo `link/reference`. Lomítko slouží k logickému seskupení souvisejících syntaxí a usnadňuje hromadné operace s nimi. + + +Line syntaxe +============ + +Line syntaxe slouží k rozpoznávání inline prvků uvnitř řádků textu. Typicky jde o formátování jako tučný nebo kurzívou psaný text, odkazy, obrázky nebo inline kód. Charakteristické pro line syntaxe je, že mohou být vnořené do sebe a parser je postupně rozbaluje. + +Registrace line syntaxe probíhá voláním `Texy::registerLinePattern()` s několika parametry. První je syntax handler, tedy callback volaný při nálezu. Druhý parametr je regulární výraz definující podobu syntaxe v textu. Třetí parametr je název syntaxe používaný v celém systému. Volitelný čtvrtý parametr je další regex pro test, zda má smysl pattern vůbec hledat - používá se pro optimalizaci, aby se nespouštěl komplexní pattern na textu, který určitě nemůže matchnout. + +Pattern jako regulární výraz musí splňovat určitá pravidla. Nesmí být kotvený na začátek textu, protože se hledá kdekoliv v řádku. Měl by být co nejkonkrétnější, aby nedošlo k falešným matchům. + +Inline syntaxe uvnitř řádků textu zpracovává [#LineParser]. Když najde match, zavolá příslušný syntax handler. Ten dostává tři parametry. První je instance LineParser, která poskytuje přístup k Texy objektu a dalším informacím o kontextu. Druhý parametr je pole s výsledky regex matche včetně podvýrazů. Třetí parametr je název syntaxe, který je užitečný, když stejný callback obsluhuje více syntaxí. Handler musí vrátit buď `HtmlElement`, nebo řetězec, nebo null pokud zpracování odmítá. + + +Block syntaxe +============= + +Block syntaxe rozpoznávají víceřádkové blokové konstrukce jako nadpisy, seznamy, tabulky, citace nebo speciální bloky. Na rozdíl od line syntaxí se block syntaxe nikdy nepřekrývají - každý řádek textu patří maximálně do jedné blokové konstrukce. + +Registrace block syntaxe používá `Texy::registerBlockPattern()` se třemi parametry. Syntax handler, regulární výraz a název syntaxe. Pattern jako regulární výraz musí splňovat určitá pravidla. Musí matchnout od začátku řádku a často obsahuje kotvu pro konec řádku. BlockParser automaticky přidává modifikátory Am, takže pattern by je neměl obsahovat. + +Block syntaxe uvnitř dokumentu zpracovává [#BlockParser]. Když najde match, zavolá příslušný syntax handler. Ten dostává podobné parametry jako u line syntaxí - BlockParser instanci, pole s matchem a název syntaxe. Vrací `HtmlElement` reprezentující celý zpracovaný blok, nebo null při odmítnutí zpracování. + + +Zapnutí a vypnutí syntaxe +========================= + +Pole `Texy::$allowed` poskytuje jemně granulární kontrolu nad tím, které syntaxe jsou v Texy aktivní. Je to jednoduchý, ale mocný mechanismus pro konfiguraci chování bez nutnosti měnit kód modulů. Když zakážete syntaxi `phrase/strong` tímto nastavením, parser přestane hledat konstrukci tučného textu: + +```php +$texy->allowed['phrase/strong'] = false; +``` + +Kontrola probíhá jednou při začátku parsování, takže dynamická změna `$allowed` během zpracování nemá efekt. + +Při konstrukci modulů se pro většinu syntaxí nastavuje výchozí hodnota `$allowed`. Některé syntaxe jsou ve výchozím stavu zapnuté, protože tvoří základ markup jazyka. Jiné jsou vypnuté, protože jsou pokročilé nebo potenciálně nebezpečné. Například emotikony jsou vypnuté, protože ne každý dokument je potřebuje, zatímco základní formátování je zapnuté. + +Bezpečný režim je situace, kdy zpracováváte nedůvěryhodný vstup, například komentáře od uživatelů. Chcete povolit základní formátování, ale zakázat obrázky, skripty nebo HTML tagy. `Texy\Configurator::safeMode()` nastaví `$allowed` pro bezpečnou kombinaci syntaxí. Typicky zakáže image, figure, script a HTML tagy, ale ponechá odkazy a formátování. + + +Parsery +******* + + +Syntax handler +============== + +Jak jsme si říkali v předchozí části, LineParser nebo BlockParser prochází text a hledají všechny registrované patterny. Když najde match, zavolá příslušný syntax handler a předá mu informace o nálezu - zejména pole s výsledky regex matche. + +Syntax handler analyzuje nalezený text a připravuje data pro zpracování. Může extrahovat části textu z regex skupin, vytvořit pomocné objekty jako `Link` nebo `Image`, parsovat modifikátory. Rozhoduje také, jaký element handler vyvolat. Zavolá `Texy::invokeAroundHandlers()` s názvem elementu a připravenými parametry. Tím začne jejich vykonávání. Vrácený výsledek se dostává zpět do syntax handleru, který ho vrátí parseru. + + +Element handler +=============== + +Element handlery implementují vzor chain of responsibility, který umožňuje složit výsledné chování z více vrstev. + +Registrace element handleru probíhá voláním `Texy::addHandler()` se dvěma parametry - názvem elementu a funkcí handleru. Jeden název elementu může mít zaregistrováno více handlerů, které se pak vykonávají v pořadí od posledně registrovaného k prvnímu. + +Název elementu identifikuje, o jaký typ zpracování jde, například `phrase` pro formátování, `image` pro obrázky nebo `link` pro odkazy (pozor: jde o něco jiného než názvy syntaxe). Někdy se používají složené názvy jako `linkReference` nebo `linkEmail` pro rozlišení různých druhů odkazů. Názvy jsou obecnější než názvy syntaxí - zatímco syntaxe `phrase/strong` je specifická konstrukce, element `phrase` pokrývá všechny druhy inline formátování. + +Vyvolání element handleru používá metodu `Texy::invokeAroundHandlers()`. Tato metoda dostává název prvku, instanci parseru a pole parametrů. Vytvoří HandlerInvocation objekt, který zapouzdřuje celý řetěz zaregistrovaných handlerů. První handler v řetězu dostane kontrolu a rozhoduje, zda zavolat `HandlerInvocation::proceed()` pro pokračování na další handler, nebo vrátit vlastní výsledek. + +HandlerInvocation objekt je klíčem k pochopení, jak řetězení funguje. Obsahuje zásobník všech handlerů pro daný prvek a aktuální pozici v tomto zásobníku. Když handler zavolá `proceed()`, HandlerInvocation posune pozici o jedno místo zpět v zásobníku a zavolá další handler. Pokud handler zavolá `proceed()` s modifikovanými parametry, tyto nové parametry se předají všem následujícím handlerům. Pokud handler vůbec nezavolá `proceed()`, řetěz se přeruší a jeho návratová hodnota se stane výsledkem celého zpracování. + +Pořadí vykonávání handlerů je od posledně zaregistrovaného k prvnímu. To znamená, že uživatelský handler zaregistrovaný dodatečně dostane kontrolu první a může rozhodnout, zda vůbec zavolá výchozí handler modulu. Toto pořadí umožňuje uživatelům přepsat výchozí chování bez nutnosti měnit kód modulu. + +Typické použití element handleru vypadá následovně. Handler zkontroluje vstupní parametry a rozhodne, zda chce zasáhnout do zpracování. Pokud ano, upraví data, zavolá `proceed()` s novými parametry a případně ještě upraví vrácený výsledek. Pokud chce handler úplně nahradit výchozí zpracování, vytvoří vlastní výsledek a vrátí ho bez volání `proceed()`. + + +Notification handler +==================== + +Notification handlery představují jednodušší, jednosměrný komunikační mechanismus. Na rozdíl od element handlerů neslouží k transformaci dat, ale k provedení vedlejších akcí. + +Registrace notification handleru používá stejnou metodu `Texy::addHandler()` jako element handlery. Rozdíl je v tom, jak se handler používá - notification handler nevrací žádnou hodnotu a nemá přístup k HandlerInvocation. První parametr je název události. Používají se popisné názvy jako `beforeParse` a `afterParse` pro globální události okolo parsování, nebo specifičtější jako `afterTable`, `afterList`, `afterBlockquote` pro události po vytvoření konkrétní struktury. Prefix before/after jasně indikuje časování události. + +Vyvolání notification handlerů používá metodu `Texy::invokeHandlers()`. Tato metoda jednoduše zavolá všechny zaregistrované handlery v pořadí a ignoruje jejich návratové hodnoty. Notification handlery dostanou parametry předané při vyvolání, ale nemohou je měnit pro další handlery v řadě. + +Typické použití notification handlerů zahrnuje několik scénářů. Handler pro událost `beforeParse` může načíst definice referencí z textu ještě před začátkem parsování. Handler `afterParse` může projít vytvořený DOM strom a doplnit chybějící atributy nebo sestavit tabulku obsahu. Handlery jako `afterTable` nebo `afterList` umožňují modulům provést závěrečné úpravy vytvořených struktur. + +Důležitý rozdíl oproti element handlerům je v tom, že notification handlery nemohou zabránit dalšímu zpracování. Všechny zaregistrované handlery se vždy vykonají, žádný nemůže přerušit řetěz. To je zamýšlené chování - notification handlery jsou o vedlejších efektech, ne o kontrole toku. + + +LineParser +========== + +LineParser zpracovává inline syntaxe uvnitř řádků textu postupným způsobem, který umožňuje vnořování a složité interakce mezi syntaxemi. + +Základní princip spočívá v hledání prvního výskytu jakékoliv syntaxe. V každé iteraci projde všechny syntaxe a zjistí, která z nich matchuje nejblíže aktuální pozici v textu. Tato syntax *vyhrává* a zpracuje se. Pokud více syntaxí matchuje na stejné pozici, vyhrává ta, která byla registrována dříve - to je priorita podle pořadí registrace. + +Když parser najde nejbližší match, zavolá příslušný syntax handler. Ten vrátí výsledek, který může být `HtmlElement` nebo řetězec. A tímto výsledkem se přepíše nalezený match v textu. + +Poté hledá znovu od aktuální pozice. Tento systém zajišťuje, že parser vždy vidí aktuální stav textu. Když nahradíme match novým textem, který může obsahovat další syntaxe, tyto syntaxe se najdou v příští iteraci. + +Property `$again` na LineParser objektu slouží k jemnému řízení toho, zda by se měla právě matchnutá syntaxe hledat znovu na stejné pozici po zpracování aktuálního matche. Výchozí hodnota je false, která říká: *Na této pozici už nemá smysl hledat tuto stejnou syntaxi. Posuň se dál.* + +Průchod končí, když parser dojde na konec textu nebo když už žádná syntaxe nemá další match. Výsledkem je text, kde všechny rozpoznatelné syntaxe byly zpracovány a nahrazeny výsledky, připravený pro finální konverzi. + + +Vnořování +--------- + +Schopnost zpracovat vnořené syntaxe je jednou z klíčových vlastností LineParser a představuje základní výzvu - jak zabránit tomu, aby již zpracované HTML tagy byly omylem interpretovány jako další syntax k zpracování. + +Když parser zpracovává text obsahující vnořené syntaxe, nejprve najde vnější konstrukci. Například v textu `"odkaz **tučný** text":URL` parser nejprve najde syntaxi pro odkaz s uvozovkami. Pattern pro tuto syntaxi matchuje celý řetězec od první uvozovky po dvojtečku a URL. Syntax handler vytvoří `HtmlElement` pro tag `<a>` a obsah `odkaz **tučný** text` se přidá jako potomek elementu. Tento řetězec vloží zpět do textu a pokračuje v hledání dalších syntaxí (`**tučný**`, který představuje tučný text). + +Ale teď má problém - v textu jsou také HTML značky, která může matchnout jako začátek jiné syntaxe. Parser by začal zpracovávat již hotové HTML tagy jako kdyby byly část původního textu. + +Nechceme, aby parser viděl HTML tagy. Potřebujeme nějaký způsob, jak rozlišit již zpracované části od částí čekajících na zpracování. Metoda `Texy::protect()` řeší tyto problémy elegantním způsobem - nahradí HTML tagy unikátním placeholderem složeným z control characters - speciálních bytů mimo tisknutelné ASCII. + +Když se tedy `HtmlElement` převádí na řetězec (pomocí `toString()`), výsledek nevypadá jako `<a href="...">odkaz **tučný** text</a>`, ale například jako `\x17\x18\x19\x17odkaz **tučný** text\x17\x18\x1A\x17`. + +V textu během parsování tak nejsou nikdy přítomny skutečné HTML tagy. Místo nich jsou pouze placeholdery. Ale vnitřní text zůstává a parser ho normálně vidí a může v něm hledat další syntaxe. To umožňuje postupné vnořování - vnější syntax se zamaskuje, ale její obsah je stále přístupný pro vnitřní syntaxe. + +Na konci zpracování metoda `Texy::unProtect()` projde výsledný HTML řetězec a nahradí všechny placeholdery jejich skutečnými hodnotami. Teprve v tomto okamžiku se do výstupu dostanou skutečné HTML tagy. + + +Úrovně maskování +---------------- + +Různé druhy obsahu používají různé control characters pro své placeholdery, což umožňuje syntaxím selektivně rozhodnout, co mohou obsahovat. + +- `Patterns::CONTENT_MARKUP` označuje běžný HTML markup jako tagy pro formátování nebo odkazy. Je to nejběžnější typ a používá ho většina inline elementů. Placeholder začíná a končí `\x17`. +- `Patterns::CONTENT_REPLACED` označuje obsah, který byl nahrazen něčím jiným, typicky obrázky nebo jiné replaced elementy. Používá `\x16` jako marker. +- `Patterns::CONTENT_TEXTUAL` označuje text, který byl escapován nebo jinak ošetřen, aby se nezpracovával. Používá se pro konstrukce jako code nebo notexy, kde chceme zobrazit původní text včetně markup symbolů, ne jejich interpretaci. +- `Patterns::CONTENT_BLOCK` označuje blokové elementy. Je to nejnižší úroveň v hierarchii. Používá `\x14` jako marker. + +Hierarchie těchto typů není jen konvence, ale má praktický důsledek. Konstantní Patterns::MARK je definována jako `\x14-\x1F`, tedy rozsah pokrývající všechny tyto typy plus rezervu. Syntaxe používají tuto konstantu ve svých patterns pro vyloučení maskovaných částí. + +Různé syntaxe mohou mít různé požadavky na to, co mohou obsahovat za placeholdery. Pattern, který chce vidět pouze čistý text bez jakýchkoliv maskovaných částí, použije vyloučení `[^\x14-\x1F]`. To odmítne všechny placeholdery všech typů. Příkladem je pattern pro obrázky - URL obrázku by neměla obsahovat žádné HTML tagy ani bloky. + +Pattern, který akceptuje nižší úrovně, ale odmítá vyšší, použije užší rozsah. Například `[^\x17-\x1F]` odmítne pouze `CONTENT_MARKUP` a výš, ale akceptuje `CONTENT_BLOCK`, `CONTENT_TEXTUAL` a `CONTENT_REPLACED`. To je užitečné, pokud chceme povolit bloky, ale ne inline markup. Praktickým příkladem je TypographyModule, který provádí typografické úpravy jako nahrazení uvozovek nebo vkládání nezlomitelných mezer. Tyto úpravy by se měly aplikovat na běžný text, ale ne uvnitř bloků kódu nebo preformátovaného textu. + + +Kolize syntaxí +-------------- + +Kolize nastává, když více syntaxí může matchnout na stejné pozici, a systém musí vybrat jednu z nich. + +Typickým příkladem jsou různé délky stejného symbolu. Syntaxe `phrase/strong+em` používá tři hvězdičky pro kombinaci tučného a kurzívy. Syntaxe `phrase/strong` používá dvě hvězdičky pro samotný tučný text. Syntaxe `phrase/em-alt` používá jednu hvězdičku pro kurzívu. Když parser najde text začínající třemi hvězdičkami, všechny tři syntaxe technicky mohou matchnout. + +PhraseModule řeší tuto kolizi registrací syntaxí v pořadí od nejdelší po nejkratší. Nejprve registruje `phrase/strong+em` s patternem pro tři hvězdičky. Pak `phrase/strong` s patternem pro dvě hvězdičky. Nakonec `phrase/em-alt` s patternem pro jednu hvězdičku. Díky tomuto pořadí se při nálezu tří hvězdiček zpracuje nejprve `phrase/strong+em` a kratší syntaxe nedostanou šanci. + +Další příklad jsou odkazy v různých formátech. Syntaxe `phrase/wikilink` používá pattern pro `[text|url]`. Syntaxe `link/reference` používá pattern pro `[ref]`. Oba začínají otevírací hranatou závorkou. Pokud je v textu `[text|url]`, oba patterns technicky mohou začít matchnout. + +Řešením je opět specifičnost patterns. Pattern pro `phrase/wikilink` je specifičtější - vyžaduje svislítko uvnitř závorek. Pokud text obsahuje svislítko, matchne `phrase/wikilink`. Pokud ne, pattern selže a `link/reference` má šanci. Pořadí registrace zde také hraje roli - `phrase/wikilink` by měla být registrována dříve než `link/reference`. + + +BlockParser +=========== + +BlockParser používá fundamentálně odlišný přístup k zpracování, který reflektuje povahu blokových konstrukcí. Základní rozdíl je v absenci prolínání. Zatímco LineParser umožňuje, aby syntaxe byly vnořené do sebe a postupně se rozbalovaly, BlockParser pracuje s předpokladem, že každý blok je samostatná jednotka. Jeden řádek nebo skupina řádků patří k maximálně jednomu bloku. Bloky se nepřekrývají, nekříží a nevnoří na úrovni BlockParser. + +BlockParser začíná vyhledáním všech bloků, respektive jejich začátků. Parser projde všechny registrované block syntaxe a najde všechny jejich výskyty. Pokud více syntaxí matchuje na stejné pozici, použije se pořadí registrace - dříve registrovaná syntaxe má přednost. + + +API pro syntax handler +---------------------- + +BlockParser poskytuje syntax handlerům API pro práci s víceřádkovými strukturami. + +Metoda `BlockParser::moveBackward()` slouží k návratu na předchozí řádky. Přijímá počet řádků, o které se má vrátit. Parser posune svou interní pozici směrem k začátku textu, dokud nepřejde přes specifikovaný počet konců řádků. To umožňuje callbacku začít číst od začátku struktury, i když pattern matchnul až uprostřed nebo na konci. + +Metoda `BlockParser::next()` slouží k čtení dalšího řádku odpovídajícího určitému patternu. Přijímá regex pattern (automaticky přidá modifikátory `Am`) a referenci na proměnnou pro výsledek matche. Pokud další řádek v textu matchuje poskytnutý pattern, metoda naplní výsledek, posune interní pozici za tento řádek a vrátí true. Pokud další řádek nematchuje, metoda vrátí false a pozice se nezmění. + + +Moduly +****** + +Moduly jsou základní organizační jednotkou v architektuře Texy. Každý modul zapouzdřuje kompletní funkcionalitu pro určitou oblast markup jazyka. + +Primární zodpovědností modulu je registrace syntaxí. V konstruktoru modul volá `Texy::registerLinePattern()` nebo `registerBlockPattern()` pro všechny syntaxe, které chce zpracovávat. Tím říká parseru: *Když najdeš tyto patterny, zavolej mě.* Modul tak definuje, které konstrukce v textu rozpoznává. + +Druhá zodpovědnost je implementace element handlerů. Modul registruje handlery pro elementy, které jeho syntaxe vyvolávají. Tyto handlery obsahují logiku pro převod nalezených konstrukcí na HTML elementy. Element handler rozhoduje, jaký element vytvořit, jaké atributy nastavit a jak zpracovat obsah. + +Třetí zodpovědnost je poskytnutí konfigurace. Moduly mají veřejné properties, které umožňují uživatelům Texy upravit chování modulu bez nutnosti měnit jeho kód. Například ImageModule má properties pro nastavení root cesty k obrázkům nebo výchozího alt textu. + +Čtvrtá zodpovědnost je správa stavu specifického pro modul. Například HeadingModule sleduje všechny nalezené nadpisy v poli TOC pro sestavení obsahu. LinkModule spravuje slovník referencí pro odkazy. Tento stav je soukromý pro modul a ostatní části systému k němu nepřistupují přímo. + +Moduly jsou navrženy jako nezávislé jednotky. Každý modul může fungovat samostatně a neměl by záviset na implementačních detailech jiných modulů. Komunikace mezi moduly probíhá přes sdílené objekty jako `Link` nebo `Image`, ne přes přímé volání metod. + + +Struktura typického modulu +========================== + +Většina modulů v Texy následuje podobnou strukturu, která reflektuje jejich úlohu v systému. + +Modul dědí od základní třídy Module, která poskytuje přístup k Texy objektu přes protected property `$texy`. Konstruktor modulu přijímá instanci Texy a uloží si ji. To umožňuje modulu přistupovat ke konfiguraci a volat metody na Texy objektu. + +V konstruktoru probíhá veškerá inicializace. Modul nastaví výchozí hodnoty konfiguračních properties, případně nastaví výchozí hodnoty v poli `Texy::$allowed` pro své syntaxe. Pak registruje své syntaxe voláním `registerLinePattern()` nebo `registerBlockPattern()`. Každá registrace spojuje pattern, syntax handler a název syntaxe. Nakonec modul registruje své element handlery voláním `addHandler()`. + +Syntax handlery jsou metody modulu, které parser volá při nálezu syntaxe. Tyto metody typicky extrahují části z regex matche, vytvářejí pomocné objekty a vyvolávají element handlery. Syntax handler rozhoduje, jaký element handler vyvolat a jaké parametry předat. + +Element handlery jsou metody implementující skutečné zpracování. Dostávají HandlerInvocation objekt jako první parametr, následovaný parametry specifickými pro daný element. Element handler vytváří `HtmlElement`, aplikuje modifikátory, zpracovává obsah a vrací výsledek. Je to místo, kde se rozhoduje o finální podobě HTML. + +Veřejné properties slouží jako rozhraní pro konfiguraci. Uživatel Texy může nastavit tyto properties pro přizpůsobení chování modulu. Properties jsou typicky primitivní typy nebo pole, ne složité objekty, aby konfigurace byla jednoduchá. + + +Přehled klíčových modulů +======================== + +Standardní distribuce Texy obsahuje několik modulů pokrývajících různé aspekty markup jazyka. + +- **PhraseModule** zpracovává inline formátování textu. Registruje syntaxe pro tučný text, kurzívu, podtržení, horní a dolní index, kód a další. Všechny tyto syntaxe vyvolávají společný handler pro element `phrase` a handler rozlišuje podle názvu syntaxe, jaký tag vytvořit. Modul umožňuje konfigurovat, které tagy se použijí pro jednotlivé druhy formátování. + +- **LinkModule** spravuje odkazy v dokumentu. Registruje syntaxe pro různé formáty odkazů - explicitní URL, emailové adresy, reference na definované odkazy. Poskytuje factory metody pro vytváření `Link` objektů a spravuje slovník referencí. Modul umožňuje konfigurovat root pro relativní odkazy, automatické `rel="nofollow"` pro externí odkazy a zkracování dlouhých URL. + +- **ImageModule** zpracovává obrázky podobným způsobem jako LinkModule odkazy. Registruje syntaxi pro inline obrázky a spravuje slovník referencí na definované obrázky. Poskytuje factory metody pro vytváření `Image` objektů a automatickou detekci rozměrů obrázků. Konfigurovatelné jsou cesty k obrázkům, výchozí alt text a CSS třídy pro zarovnání. + +- **HeadingModule** rozpoznává nadpisy v různých formátech - podtržené pomlčkami nebo rovnítky, obklopené mřížkami. Shromažďuje všechny nadpisy do pole TOC pro možné sestavení obsahu. Umožňuje konfigurovat generování ID, top úroveň nadpisů a režim balancování úrovní. + +- **ListModule** zpracovává seznamy - nečíslované, číslované a definiční. Rozpoznává různé typy odrážek a automaticky detekuje vnořování podle odsazení. Umožňuje konfigurovat, které znaky slouží jako odrážky a jaké HTML listy generovat. + +- **TableModule** je jedním z nejkomplexnějších modulů. Rozpoznává tabulky s hlavičkami, těly, titulky a podporuje colspan a rowspan. Zpracovává modifikátory pro řádky i buňky. + +- **BlockModule** zpracovává speciální bloky ohraničené `/--` a `\--`. Podporuje různé typy bloků - code pro kód, html pro přímé HTML, div pro generický kontejner. Umožňuje uživatelům definovat vlastní handlery pro vlastní typy bloků. + +- **TypographyModule** provádí post-processing pro typografické úpravy. Nahrazuje tři tečky elipsou, dvojité pomlčky en-dash, přímé uvozovky typografickými a vkládá nezlomitelné mezery. Pracuje na úrovni finálního řetězce mezi blokovými elementy. + +- **HtmlOutputModule** formátuje finální HTML výstup. Zajišťuje wellformed HTML automatickým zavíráním tagů, opravou nesprávného vnořování, odsazením kódu a zalamováním dlouhých řádků. Umožňuje konfigurovat úroveň odsazení a šířku řádků. + + +Interakce mezi moduly +===================== + +Ačkoliv jsou moduly navrženy jako nezávislé, v některých případech musí spolupracovat. + +Sdílené objekty jsou hlavní mechanismus komunikace. `Link` objekt vytvořený LinkModule může být předán ImageModule pro vytvoření obrázkového odkazu. `Image` objekt vytvořený ImageModule může být předán FigureModule pro vytvoření obrázku s popiskem. Tyto objekty zapouzdřují veškeré potřebné informace a poskytují společné rozhraní. + +Reference systém umožňuje oddělit definici od použití. LinkModule poskytuje metody `addReference()` a `getReference()` pro správu slovníku pojmenovaných odkazů. Uživatel může v jedné části dokumentu definovat referenci a v jiné ji použít. ImageModule má analogický systém pro reference na obrázky. Moduly používající reference volají factory metody, které samy kontrolují, zda jde o referenci nebo přímou hodnotu. + +Element handlers mohou volat jiné element handlery. PhraseModule při zpracování `phrase/span` s odkazem vytvoří `Link` objekt a zavolá element handler LinkModule pro vytvoření odkazu. Tím deleguje odpovědnost za vytvoření a konfiguraci odkazu na specializovaný modul. + +Vztahy mezi moduly jsou typicky jednostranné. PhraseModule zná LinkModule a ImageModule, protože vytváří odkazy a obrázky. Ale LinkModule a ImageModule neznají PhraseModule. To udržuje závislosti jednoduché a umožňuje snadné nahrazení nebo rozšíření modulů. + + +DOM reprezentace +**************** + +`HtmlElement` reprezentuje jeden uzel v DOM stromu a poskytuje rozhraní pro jeho manipulaci a zpracování. + +Základní struktura elementu obsahuje název tagu, asociativní pole atributů a pole potomků. Potomci mohou být další instance `HtmlElement` nebo prostě textové řetězce. Tato kombinace umožňuje reprezentovat libovolnou HTML strukturu. + +Název elementu se nastavuje a získává přes metody `setName()` a `getName()`. Speciální hodnota null jako název znamená transparentní element, který nemá tagy, jen jeho obsah. + +Atributy jsou veřejně přístupné přes property `$attrs` jako asociativní pole. Hodnoty mohou být řetězce, čísla, boolean nebo pole. Boolean true znamená atribut bez hodnoty (jako checked), false nebo null znamená atribut se vůbec nevykreslí. Pokud je hodnota pole, různé prvky se spojí podle typu atributu - pro class mezerami, pro style středníky. Metoda `setAttribute()` nastaví hodnotu atributu. Metoda `getAttribute()` vrací hodnotu atributu nebo null. + +Potomci se spravují přes několik metod. Metoda `add()` přidává potomka na konec. Metoda `insert()` vkládá potomka na specifikovanou pozici, volitelně nahrazuje existujícího potomka. Metoda `create()` vytváří nový `HtmlElement` jako potomka a vrací ho pro další manipulaci. Metoda `removeChildren()` odstraní všechny potomky. + +Element implementuje ArrayAccess interface, takže s potomky lze pracovat jako s polem. Zápis `$el[0]` vrací prvního potomka, `$el[0] = $child` nastaví prvního potomka. Tento přístup je pohodlný pro rychlou manipulaci s konkrétními potomky. + +Metoda `toString()` prochází element a jeho potomky rekurzivně a sestavuje řetězcovou reprezentaci. HTML tagy se okamžitě zamaskují pomocí `Texy::protect()`, takže do výsledku jde placeholder místo skutečných HTML znaků. + +Metody `toHtml()` a `toText()` vrací výsledek nemaskovaný včetně post-processingu. + + +Parsování obsahu +================ + +`HtmlElement` může rekurzivně parsovat svůj obsah, čímž umožňuje postupné budování DOM stromu. + +Metoda `parseLine()` slouží k parsování inline syntaxí v řetězci. Vytvoří novou instanci LineParser s aktuálním elementem jako kontejnerem. Zavolá `parse()` na parseru s poskytnutým textem. LineParser postupně najde a zpracuje všechny inline syntaxe a výsledné elementy nebo řetězce přidá jako potomky aktuálního elementu. Metoda vrací použitý LineParser pro případné další použití. + +Metoda `parseBlock()` parsuje text jako blokový obsah. Vytvoří BlockParser a zavolá na něm `parse()`. BlockParser najde všechny blokové konstrukce v textu, zpracuje je a přidá jako potomky elementu. Text mezi bloky se zpracuje jako odstavce, které interně používají LineParser. Metoda přijímá boolean parametr indikující, zda text pochází z odsazeného bloku, což ovlivňuje zpracování odstavců. + +Tyto parsovací metody umožňují rekurzivní zpracování. Syntax handler může vytvořit element, nastavit jeho základní vlastnosti a pak zavolat `parseLine()` nebo `parseBlock()` pro zpracování obsahu. Výsledkem je, že obsah elementu prochází stejným procesem parsování jako hlavní dokument, včetně rozpoznávání syntaxí a vyvolávání handlerů. + + +Validace +======== + +`HtmlElement` poskytuje mechanismy pro validaci atributů a obsahu podle HTML DTD (Document Type Definition). + +DTD je statické pole definující pro každý HTML tag, které atributy jsou povolené a jaký obsah může obsahovat. Texy načítá DTD ze souboru při inicializaci a uloží ho do statického pole. Struktura DTD mapuje název tagu na dvojici - pole povolených atributů a pole povoleného obsahu. + +Metoda `validateAttrs()` kontroluje atributy elementu podle DTD. Pro daný tag získá seznam povolených atributů. Prochází všechny atributy elementu a ty, které nejsou v seznamu, odstraní. Speciální případy jsou atributy začínající data- nebo aria-, které jsou povolené, pokud je v DTD zástupný záznam `data-*` nebo `aria-*`. + +Tato validace se typicky volá při aplikaci modifikátorů metodou `decorate()`. Zajišťuje, že i když uživatel zadá modifikátor s neplatným atributem pro daný tag, atribut se do finálního HTML nedostane. To je důležité pro bezpečnost a správnost HTML. + +Metoda `validateChild()` kontroluje, zda daný potomek může být obsahem elementu. Přijímá potomka (`HtmlElement` nebo název tagu) a DTD. Pokud je element v DTD definován, metoda zkontroluje, zda potomek je v seznamu povoleného obsahu. Pokud ano, vrací true. Pokud ne, vrací false. + +Tato validace se může použít při dynamickém sestavování DOM stromu pro zajištění korektní struktury. Například paragraph element nesmí obsahovat blokové elementy, takže `validateChild()` by odmítlo přidat div do p. V praxi Texy tuto validaci používá omezeně, protože struktura generovaná moduly je typicky správná by design. + +Kombinace `validateAttrs()` a `validateChild()` poskytuje mechanismus pro zajištění validního HTML, i když vstup obsahuje nedůvěryhodná data nebo špatně formované konstrukce. Texy může být nakonfigurováno pro striktní validaci nebo může validaci vypnout pro maximální flexibilitu. + + +Modifikátory +************ + +Modifikátory poskytují způsob, jak přidat elementům dodatečné atributy, třídy, styly a zarovnání bez nutnosti psát přímé HTML. + +Základní formát modifikátoru je tečka následovaná kombinací různých částí v kulatých, hranatých a složených závorkách: `.(title)[class1 class2 #id]{style:value}<align>^valign`. Celý modifikátor se píše před nebo na konec konstrukce, na kterou se aplikuje. Například `"**text** .(Důležité)[highlight]{color:red}"` vytvoří tučný text se třídou highlight, červenou barvou a title atributem Důležité. + +Kulaté závorky obsahují title atribut nebo alt text. Text uvnitř se použije jako hodnota title atributu na výsledném elementu. Pokud element je obrázek, může se použít jako alt text. Uvnitř kulatých závorek je možné escapovat závorku zpětným lomítkem. + +Hranaté závorky obsahují CSS třídy a volitelně ID. Třídy se píší jako slova oddělená mezerami. ID se píše s prefixem mřížky. Například `[main-content selected #article-5]` nastaví dvě třídy a jedno ID. Pokud je ID uvedeno vícekrát, použije se poslední. + +Složené závorky obsahují CSS styly nebo HTML atributy. Styly se píší ve standardním CSS formátu property:value. Více stylů se odděluje středníky. Některé property jsou rozpoznány jako HTML atributy - například `{href:url}` se převede na atribut href, ne na CSS style. To umožňuje nastavit atributy, které není možné vyjádřit jinak. + +Zarovnání se zadává pomocí speciálních znaků. `<` znamená vlevo, `>` vpravo, `=` pro do bloku, `<>` pro na střed. Vertikální zarovnání používá `^` pro nahoru, `-` pro střed a `_` pro dolů. Tyto zkratky se převádějí buď na CSS třídy nebo inline styly podle konfigurace. + +Části modifikátoru mohou být v libovolném pořadí a některé mohou být vynechány. Platný je modifikátor obsahující jen třídy `.[highlight]`, jen title `.(Poznámka)` nebo jen styl `.{color:blue}`. Parser rozpozná jednotlivé části podle ohraničujících znaků. + + +Modifier třída +============== + +Třída `Modifier` slouží k parsování a uchovávání informací z modifikátoru. + +Instance `Modifier` se typicky vytváří syntax handler, který předá konstruktoru text modifikátoru extrahovaný z regex matche. Konstruktor zavolá metodu `setProperties()`, která parsuje text a naplní properties objektu. + +Veřejné properties obsahují jednotlivé části modifikátoru. Property `$id` obsahuje ID elementu jako řetězec nebo null. Property `$classes` je asociativní pole, kde klíče jsou názvy tříd a hodnoty jsou true. Property `$styles` je asociativní pole mapující CSS property na hodnoty. Property `$attrs` je asociativní pole s HTML atributy, které nejsou styly ani třídy. + +Dvě speciální properties `$hAlign` a `$vAlign` obsahují horizontální a vertikální zarovnání jako řetězce `left`, `right`, `center`, `justify` nebo `top`, `middle`, `bottom`. Tyto hodnoty se později převádějí na CSS třídy nebo styly podle konfigurace Texy. + +Property `$title` obsahuje text z kulatých závorek, který se použije jako title atribut nebo alt text u obrázků. Text je automaticky unescapován z HTML entit a zbaven escapovaných závorek. + + +Aplikace na elementy +==================== + +`Modifier` objekt se aplikuje na `HtmlElement` pomocí metody `Modifier::decorate()`. + +Metoda `decorate()` přijímá instanci Texy a `HtmlElement` jako parametry. Postupně aplikuje jednotlivé části modifikátoru na element s ohledem na konfiguraci Texy, která může některé části zakázat nebo omezit. + +Aplikace atributů kontroluje, které atributy jsou povolené pro daný tag podle `Texy::$allowedTags` konfigurace. Pokud jsou všechny atributy povolené, zkopírují se všechny atributy z `Modifier` do elementu. Pokud je povolen jen seznam konkrétních atributů, zkopírují se pouze ty, které jsou na seznamu. + +Title atribut se vždy aplikuje, pokud je nastaven, ale text prochází typografickým post-processingem pro nahrazení uvozovek a dalších úprav. + +Aplikace tříd a ID kontroluje konfiguraci `Texy::$allowedClasses`. Pokud jsou všechny třídy povolené, přidají se všechny třídy z `Modifier` do elementu a nastaví se ID. Pokud je povolen jen seznam konkrétních tříd, přidají se pouze ty, které jsou na seznamu. ID se přidá, jen pokud je v seznamu povolen řetězec začínající mřížkou. + +Aplikace stylů probíhá podobně s kontrolou `Texy::$allowedStyles`. Povolené CSS properties se přidají do style atributu elementu. Pokud element již měl nějaké styly, modifikátorové styly se přidají nebo přepíšou existující. + +Zarovnání se aplikuje buď jako CSS třída nebo inline style. Pokud je v Texy konfigurováno `Texy::$alignClasses` mapování pro daný typ zarovnání, přidá se odpovídající CSS třída. Pokud ne, přidá se inline style s text-align nebo vertical-align property. + +Výsledkem je, že element má všechny atributy, třídy, styly a další vlastnosti z modifikátoru, ale pouze ty, které jsou povoleny aktuální konfigurací Texy. To zajišťuje bezpečnost při zpracování nedůvěryhodného vstupu. + + +Propagace modifikátorů +====================== + +Modifikátory procházejí systémem v několika fázích, přičemž si zachovávají flexibilitu a umožňují úpravy na různých úrovních. + +Syntax handler extrahuje text modifikátoru z regex matche a vytvoří novou instanci `Modifier` a naplní se jeho properties. + +`Modifier` objekt se předává jako parametr do element handlerů. Handler dostává již parsovaný objekt, ne surový text. To umožňuje handleru snadno přistupovat k jednotlivým částem modifikátoru - třídám, stylům, zarovnání. Handler může modifikátor upravit před aplikací, například přidat další třídy nebo změnit styly. + +Element handler vytváří `HtmlElement` a předá jej metodě `Modifier::decorate()`. V tomto okamžiku se modifikátor aplikuje na element. Metoda `decorate()` kontroluje konfigurace Texy a zajišťuje, že se aplikují pouze povolené části. + +V některých případech modul kombinuje více modifikátorů. Například TableModule parsuje modifikátory na úrovni tabulky, řádků i buněk. Modifikátor buňky je vlastně klony modifikátoru sloupce, na kterém se pak aplikují dodatečné úpravy z modifikátoru konkrétní buňky. To umožňuje výchozí styly pro celý sloupec s možností přepsání v jednotlivých buňkách. diff --git a/texy/cs/configuration.texy b/texy/cs/configuration.texy new file mode 100644 index 0000000000..39f95f7469 --- /dev/null +++ b/texy/cs/configuration.texy @@ -0,0 +1,719 @@ +Konfigurace +*********** + +.[perex] +Kompletní průvodce konfigurací Texy. Naučíte se ovládat všechny moduly, nastavit bezpečnost a přizpůsobit Texy vašim potřebám. + +Texy se konfiguruje pomocí **public properties** hlavní třídy `Texy\Texy` a jejích **modulů**. Každý modul je zodpovědný za zpracování konkrétní části syntaxe (obrázky, odkazy, nadpisy...). + +Základní přístup: + +```php +$texy = new Texy\Texy; + +// Konfigurace hlavní třídy +$texy->allowedTags = Texy\Texy::NONE; + +// Konfigurace modulu +$texy->imageModule->root = '/images/'; +``` + + +Třída Texy\Texy .[#texy-class] +============================== + +Hlavní třída obsahuje globální nastavení a vlastnosti ovlivňující celé zpracování. + + +Povolené syntaxe ($allowed) .{toc: $allowed} +-------------------------------------------- + +Pole `$allowed` kontroluje, které části Texy syntaxe jsou aktivní: + +```php +// Výchozí: všechny syntaxe povoleny (kromě emotikonů) +$texy->allowed['image'] = true; +$texy->allowed['emoticon'] = false; + +// Vypnout obrázky +$texy->allowed['image'] = false; + +// Vypnout HTML značky ve vstupu +$texy->allowed['html/tag'] = false; +$texy->allowed['html/comment'] = false; + +// Vypnout různé typy odkazů +$texy->allowed['link/reference'] = false; +$texy->allowed['link/email'] = false; +$texy->allowed['link/url'] = false; +``` + +**Kompletní seznam syntaxí:** + +|--- +| Klíč | Výchozí | Popis +|--- +| `image` | `true` | Obrázky `[* img.jpg *]` +| `figure` | `true` | Obrázky s popiskou +| `link/reference` | `true` | Reference `[ref]` +| `link/email` | `true` | Email adresy +| `link/url` | `true` | Automatické URL +| `link/definition` | `true` | Definice referencí +| `heading/underlined` | `true` | Podtržené nadpisy +| `heading/surrounded` | `true` | Ohraničené nadpisy +| `horizline` | `true` | Horizontální čáry +| `blockquote` | `true` | Citace +| `list` | `true` | Seznamy +| `list/definition` | `true` | Definiční seznamy +| `table` | `true` | Tabulky +| `phrase/strong` | `true` | Tučné písmo `**text**` +| `phrase/em` | `true` | Kurzíva `//text//` +| `phrase/em-alt` | `true` | Kurzíva `*text*` +| `phrase/code` | `true` | Kód ```text``` +| `phrase/ins` | `false` | Vložený text `++text++` +| `phrase/del` | `false` | Smazaný text `--text--` +| `phrase/sup` | `false` | Horní index `^^text^^` +| `phrase/sub` | `false` | Dolní index `__text__` +| `html/tag` | `true` | HTML značky ve vstupu +| `html/comment` | `true` | HTML komentáře +| `emoticon` | `false` | Emotikony `:-)`, `:-(` +| `blocks` | `true` | Bloky `/-- \--` +| `typography` | `true` | Typografické úpravy +| `longwords` | `true` | Dělení dlouhých slov + + +Povolené HTML značky ($allowedTags) .{toc: $allowedTags} +-------------------------------------------------------- + +Kontroluje, které HTML značky mohou být ve výstupu (a na vstupu): + +```php +// Výchozí: všechny validní HTML5 značky povoleny +$texy->allowedTags = Texy\Texy::ALL; + +// Zakázat všechny HTML značky +$texy->allowedTags = Texy\Texy::NONE; + +// Povolit jen konkrétní značky +$texy->allowedTags = [ + 'strong' => [], // <strong> bez atributů + 'a' => ['href', 'title'], // <a> s atributy + 'img' => Texy\Texy::ALL, // <img> s jakýmikoliv atributy +]; +``` + +**Formáty:** +- `Texy::ALL` – všechny značky povoleny +- `Texy::NONE` – žádné značky povoleny +- Pole – povolené značky jako klíče, povolené atributy jako hodnoty + + +Povolené CSS třídy ($allowedClasses) .{toc: $allowedClasses} +------------------------------------------------------------ + +Kontroluje, které CSS třídy a ID mohou být použity: + +```php +// Výchozí: všechny třídy a ID povoleny +$texy->allowedClasses = Texy\Texy::ALL; + +// Zakázat třídy a ID +$texy->allowedClasses = Texy\Texy::NONE; + +// Povolit konkrétní třídy a ID +$texy->allowedClasses = [ + 'highlight', + 'important', + '#main', // ID začínají # + '#sidebar', +]; +``` + +Použití: +```texy +Text s třídou .[highlight] + +Text s ID .{toc: main} +``` + + +Povolené CSS styly ($allowedStyles) .{toc: $allowedStyles} +---------------------------------------------------------- + +Kontroluje, které inline CSS vlastnosti mohou být použity: + +```php +// Výchozí: všechny styly povoleny +$texy->allowedStyles = Texy\Texy::ALL; + +// Zakázat inline styly +$texy->allowedStyles = Texy\Texy::NONE; + +// Povolit konkrétní CSS vlastnosti +$texy->allowedStyles = [ + 'color', + 'background-color', + 'font-size', +]; +``` + +Použití: +```texy +Text s barvou .{color: red} +``` + + +CSS třídy pro zarovnání ($alignClasses) .{toc: $alignClasses} +------------------------------------------------------------- + +Místo inline stylů `style="text-align:left"` můžete použít CSS třídy: + +```php +// Výchozí: prázdné pole (použijí se inline styly) +$texy->alignClasses = [ + 'left' => null, + 'right' => null, + 'center' => null, + 'justify' => null, + 'top' => null, + 'middle' => null, + 'bottom' => null, +]; + +// Nastavit třídy +$texy->alignClasses['left'] = 'text-left'; +$texy->alignClasses['right'] = 'text-right'; +$texy->alignClasses['center'] = 'text-center'; +``` + +Použití: +```texy +Text zarovnaný doleva . + +Text zarovnaný doprava .> +``` + +S nastaveným `alignClasses` vygeneruje `<p class="text-left">` místo `<p style="text-align:left">`. + + +Další vlastnosti +---------------- + +```php +// Spojování řádků do odstavců (výchozí: true) +$texy->mergeLines = true; + +// Šířka tabulátoru (výchozí: 8) +$texy->tabWidth = 8; + +// Maskování emailů před roboty (výchozí: true) +$texy->obfuscateEmail = true; + +// Odstraňování měkkých spojovníků (výchozí: true) +$texy->removeSoftHyphens = true; + +// Element pro netextové odstavce (výchozí: 'div') +$texy->nontextParagraph = 'div'; +``` + + +Moduly +====== + +Každý modul zpracovává konkrétní část syntaxe. Moduly jsou přístupné jako public properties třídy `Texy\Texy`. + + +HeadingModule +------------- + +Zpracovává nadpisy (podtržené i ohraničené). + +```php +// Úroveň nejvyššího nadpisu (výchozí: 1) +$texy->headingModule->top = 1; // <h1> + +// Generovat automatická ID (výchozí: false) +$texy->headingModule->generateID = true; + +// Prefix pro generovaná ID (výchozí: 'toc-') +$texy->headingModule->idPrefix = 'section-'; + +// Více znaků = vyšší nadpis? (výchozí: true) +$texy->headingModule->moreMeansHigher = true; + +// Režim vyvažování (výchozí: DYNAMIC) +$texy->headingModule->balancing = Texy\Modules\HeadingModule::DYNAMIC; +``` + +Po zpracování: + +```php +// První nadpis (pro <title>) +echo $texy->headingModule->title; + +// Obsah (Table of Contents) +print_r($texy->headingModule->TOC); +``` + + +PhraseModule +------------ + +Zpracovává inline formátování (tučné, kurzíva, odkazy v textu...). + +```php +// HTML značky pro jednotlivé fráze (výchozí: viz níže) +$texy->phraseModule->tags = [ + 'phrase/strong' => 'strong', + 'phrase/em' => 'em', + 'phrase/code' => 'code', + // ... další +]; + +// Povolit odkazy ve frázích (výchozí: true) +$texy->phraseModule->linksAllowed = true; +``` + + +LinkModule +---------- + +Zpracovává odkazy, reference a URL. + +```php +// Kořenová cesta pro odkazy (výchozí: '') +$texy->linkModule->root = '/articles/'; + +// CSS třída pro odkazy na obrázky (výchozí: null) +$texy->linkModule->imageClass = 'image-link'; + +// Vždy přidávat rel="nofollow" (výchozí: false) +$texy->linkModule->forceNoFollow = false; + +// Zkracovat URL na čitelnější formu (výchozí: true) +$texy->linkModule->shorten = true; +``` + +**Reference:** + +```php +// Přidat referenci +$link = new Texy\Link('https://example.com'); +$link->modifier->title = 'Ukázková stránka'; +$link->label = 'Příklad'; +$texy->linkModule->addReference('example', $link); +``` + +Použití: +```texy +Odkaz na [example] +``` + + +ImageModule +----------- + +Zpracovává obrázky. + +```php +// Kořenová cesta pro obrázky (výchozí: 'images/') +$texy->imageModule->root = '/assets/images/'; + +// Kořenová cesta pro linkované obrázky (výchozí: 'images/') +$texy->imageModule->linkedRoot = '/assets/images/full/'; + +// Fyzická cesta na disku (pro zjištění rozměrů) +$texy->imageModule->fileRoot = __DIR__ . '/public/images/'; + +// CSS třída pro plovoucí obrázky (výchozí: null) +$texy->imageModule->leftClass = 'float-left'; +$texy->imageModule->rightClass = 'float-right'; + +// Výchozí alternativní text (výchozí: '') +$texy->imageModule->defaultAlt = 'Obrázek'; +``` + +**Reference:** + +```php +// Přidat referenci +$image = new Texy\Image; +$image->URL = 'photo.jpg'; +$image->modifier->title = 'Fotografie'; +$texy->imageModule->addReference('photo', $image); +``` + + +FigureModule +------------ + +Zpracovává obrázky s popiskou. + +```php +// HTML element (výchozí: 'div') +$texy->figureModule->tagName = 'figure'; + +// CSS třída (výchozí: 'figure') +$texy->figureModule->class = 'photo-figure'; + +// Třídy pro plovoucí obrázky (výchozí: null) +$texy->figureModule->leftClass = 'figure-left'; +$texy->figureModule->rightClass = 'figure-right'; + +// Offset pro výpočet šířky (výchozí: 10) +$texy->figureModule->widthDelta = 20; + +// Vyžadovat popisku (výchozí: true) +$texy->figureModule->requireCaption = true; +``` + + +ListModule +---------- + +Zpracovává odrážkové, číslované a definiční seznamy. + +```php +// Definice odrážek a stylu (výchozí: viz zdrojový kód) +$texy->listModule->bullets = [ + '*' => ['\*[\ \t]', 0, ''], + '-' => ['[\x{2013}-](?![>-])', 0, ''], + // ... další +]; +``` + + +TableModule +----------- + +Zpracovává tabulky. + +```php +// CSS třídy pro řádky (výchozí: null) +$texy->tableModule->oddClass = 'odd'; +$texy->tableModule->evenClass = 'even'; +``` + +*Poznámka: `oddClass` a `evenClass` jsou deprecated.* + + +HorizLineModule +--------------- + +Zpracovává horizontální čáry. + +```php +// CSS třídy podle typu (výchozí: null) +$texy->horizLineModule->classes = [ + '-' => 'hr-line', + '*' => 'hr-star', +]; +``` + + +TypographyModule +---------------- + +Zpracovává typografické úpravy. + +```php +// Locale (výchozí: 'cs') +$texy->typographyModule->locale = 'en'; +``` + +**Podporované locales:** +- `cs` – české uvozovky „text" a ‚text' +- `en` – anglické uvozovky "text" a 'text' +- `fr` – francouzské uvozovky «text» a ‹text› +- `de` – německé uvozovky „text" a ‚text' +- `pl` – polské uvozovky „text" a ‚text' + + +LongWordsModule +--------------- + +Rozděluje dlouhá slova pomocí `­`. + +```php +// Maximální délka slova (výchozí: 20) +$texy->longWordsModule->wordLimit = 25; +``` + + +EmoticonModule +-------------- + +Nahrazuje emotikony za obrázky nebo Unicode znaky. + +```php +// CSS třída (výchozí: null) +$texy->emoticonModule->class = 'emoji'; + +// Cesta k obrázkům (výchozí: null = použije imageModule->root) +$texy->emoticonModule->root = '/images/smilies/'; +$texy->emoticonModule->fileRoot = __DIR__ . '/public/smilies/'; + +// Definice emotikonů (výchozí: základní sada) +$texy->emoticonModule->icons = [ + ':-)' => '🙂', + ':-(' => '☹', + ';-)' => '😉', + // ... nebo cesty k obrázkům + ':cool:' => 'cool.gif', +]; +``` + + +HtmlModule +---------- + +Zpracovává HTML značky a komentáře ve vstupním textu. + +```php +// Zobrazit HTML komentáře na výstupu (výchozí: true) +$texy->htmlModule->passComment = true; +``` + + +HtmlOutputModule +---------------- + +Formátuje výstupní HTML. + +```php +// Formátovat výstup (odsazení) (výchozí: true) +$texy->htmlOutputModule->indent = true; + +// Základní odsazení (výchozí: 0) +$texy->htmlOutputModule->baseIndent = 0; + +// Maximální šířka řádku (výchozí: 80) +$texy->htmlOutputModule->lineWrap = 100; + +// Zachovat mezery v těchto elementech (výchozí: seznam) +$texy->htmlOutputModule->preserveSpaces = [ + 'textarea', 'pre', 'script', 'code', +]; +``` + + +ScriptModule +------------ + +Zpracovává volání `{{makro}}`. + +```php +// Oddělovač argumentů (výchozí: ',') +$texy->scriptModule->separator = ';'; +``` + + +Třída Texy\Configurator .{toc: Texy\Configurator} +================================================= + +Předpřipravené konfigurační sety pro časté use-case. + + +safeMode() – Bezpečný režim .{toc: safeMode()} +---------------------------------------------- + +Konfigurace pro zpracování **nedůvěryhodného obsahu** od uživatelů. + +```php +Texy\Configurator::safeMode($texy); +``` + +**Co dělá:** +- Zakáže třídy a ID (`$allowedClasses = NONE`) +- Zakáže inline styly (`$allowedStyles = NONE`) +- Povolí jen bezpečné HTML značky: + +```php +[ + 'a' => ['href', 'title'], + 'abbr' => ['title'], + 'b' => [], + 'br' => [], + 'cite' => [], + 'code' => [], + 'em' => [], + 'i' => [], + 'strong' => [], + 'sub' => [], + 'sup' => [], + 'q' => [], + 'small' => [], +] +``` + +- Filtruje URL schémata (jen `http:`, `https:`, `ftp:`, `mailto:`) +- Zakáže obrázky +- Zakáže definice referencí +- Zakáže HTML komentáře +- Přidá `rel="nofollow"` ke všem odkazům + + +disableLinks() – Vypnout odkazy .{toc: disableLinks()} +------------------------------------------------------ + +Zakáže všechny typy odkazů. + +```php +Texy\Configurator::disableLinks($texy); +``` + +**Co dělá:** +- Zakáže všechny typy odkazů (`link/reference`, `link/email`, `link/url`, `link/definition`) +- Zakáže odkazy ve frázích (`phraseModule->linksAllowed = false`) +- Odebere `<a>` z povolených značek + + +disableImages() – Vypnout obrázky .{toc: disableImages()} +--------------------------------------------------------- + +Zakáže všechny typy obrázků. + +```php +Texy\Configurator::disableImages($texy); +``` + +**Co dělá:** +- Zakáže obrázky (`image`, `figure`, `image/definition`) +- Odebere `<img>`, `<object>`, `<embed>`, `<applet>` z povolených značek + + +Bezpečnost +========== + +Texy je navrženo s důrazem na bezpečnost. Automaticky chrání před běžnými útoky. + + +Ochrana proti XSS +----------------- + +Cross-Site Scripting (XSS) je útok, kdy útočník vloží škodlivý JavaScript do stránky. + +**Příklad útoků, které Texy zablokuje:** + +```texy +Pokus o útok: <script>alert('XSS')</script> + +Pokus o útok: <img src=x onerror="alert('XSS')"> + +Pokus o útok: "klikni":javascript:alert('XSS') + +Pokus o útok: [* image.jpg onload="alert('XSS')" *] +``` + +Texy automaticky: +- **Validuje HTML** – odstraní nepovolené značky a atributy +- **Filtruje URL** – povolí jen bezpečná schémata (`http:`, `https:`, `mailto:`, `ftp:`) +- **Escapuje obsah** – správně escapuje text v atributech +- **Sanitizuje atributy** – odstraní event handlery (`onclick`, `onerror`, ...) + +```php +$texy = new Texy\Texy; +Texy\Configurator::safeMode($texy); + +$input = '<script>alert("XSS")</script>'; +$output = $texy->process($input); + +// Výstup: prázdný (script tag odstraněn) +``` + + +Validace URL +------------ + +Texy kontroluje URL ve všech odkazech a obrázcích: + +```php +$texy = new Texy\Texy; + +// Nastavit povolená schémata (výchozí v safeMode) +$texy->urlSchemeFilters[Texy\Texy::FILTER_ANCHOR] = + '#https?:|ftp:|mailto:#Ai'; +$texy->urlSchemeFilters[Texy\Texy::FILTER_IMAGE] = + '#https?:#Ai'; +``` + +**Příklady blokovaných URL:** + +```texy +"útok":javascript:alert('XSS') // blokováno +"útok":data:text/html,<script> // blokováno +[* javascript:alert() *] // blokováno +``` + + +Filtrování HTML značek +---------------------- + +Kontrola přes `$allowedTags`: + +```php +$texy = new Texy\Texy; + +// Povolit jen bezpečné značky +$texy->allowedTags = [ + 'p' => [], + 'strong' => [], + 'em' => [], + 'a' => ['href', 'title'], // jen tyto atributy +]; + +$input = '<p>Text <script>alert()</script></p>'; +$output = $texy->process($input); + +// Výstup: <p>Text alert()</p> +// (script tag odstraněn) +``` + + +Praktický příklad +----------------- + +```php +function processComment(string $userInput): string +{ + $texy = new Texy\Texy; + + // Bezpečný režim + Texy\Configurator::safeMode($texy); + + // Dodatečná omezení + $texy->allowed['link/url'] = false; // zakázat auto-linky + $texy->allowed['html/tag'] = false; // zakázat HTML + + // Zpracovat + return $texy->process($userInput); +} + +// Použití +$comment = $_POST['comment']; +$html = processComment($comment); +echo $html; // bezpečný výstup +``` + + +Best practices +-------------- + +1. **Vždy použijte safeMode()** pro uživatelský obsah +2. **Validujte vstup** před předáním Texy (délka, formát) +3. **Limitujte HTML značky** podle potřeby +4. **Kontrolujte výstup** – i když Texy je bezpečné, double-check nikdy neuškodí +5. **Logujte podezřelé pokusy** – může vám pomoci identifikovat útočníky + +```php +$texy = new Texy\Texy; +Texy\Configurator::safeMode($texy); + +// Logování +$texy->addHandler('htmlTag', function($invocation, $el, $isStart) { + if ($el->getName() === 'script') { + error_log('XSS attempt detected!'); + } + return $invocation->proceed(); +}); +``` diff --git a/texy/cs/custom-handlers.texy b/texy/cs/custom-handlers.texy new file mode 100644 index 0000000000..3cc43d4b78 --- /dev/null +++ b/texy/cs/custom-handlers.texy @@ -0,0 +1,850 @@ +Úprava chování prvků +******************** + +.[perex] +Tato kapitola popisuje, jak můžete změnit chování **existujících prvků** v Texy - například upravit, jak se zpracovávají obrázky, odkazy nebo formátování. Pokud chcete přidat **zcela novou syntaxi**, kterou Texy standardně nezná, přečtěte si kapitolu [Přidání vlastní syntaxe |custom-syntax]. + +Představte si, že chcete, aby standardní syntaxe pro obrázky `[* URL *]` rozpoznávala speciální adresu `[* youtube:dQw4w9WgXcQ *]` a místo běžného obrázku vytvořila embedded přehrávač. + +Nebo chcete obarvovat výpisy zdrojového kódu pomocí syntax highlighteru. A tak dále. Přesně k tomu slouží **element handlery** - funkce, které Texy volá při zpracování konkrétních prvků. Například zaregistrujete handler pro element `image`, který zkontroluje URL, a pokud začíná `youtube:`, vrátí iframe místo standardního obrázku. Neměníte syntaxi, jen upravujete, co se s nalezenou konstrukcí stane. + + +Elementy a jejich handlery +========================== + +V terminologii Texy je **element** název pro typ prvku, který může být v dokumentu zpracován. Například `image` je element pro obrázky, `linkURL` pro odkazy, viz [#výchozí elementy]. Každý element má svůj **výchozí handler**, který je implementován v příslušném modulu a stará se o standardní zpracování. + +Když napíšete v textu `[* image.jpg *]`, parser najde tuto syntaxi, vytvoří objekt `Texy\Image` s daty o obrázku a zavolá všechny handlery zaregistrované pro element `image`. Pokud žádný vlastní handler není, zavolá se pouze výchozí handler z `ImageModule`, který vytvoří HTML tag `<img>`. + +Handler zaregistrujete voláním metody `addHandler()`: + +```php +$texy->addHandler('image', function( + Texy\HandlerInvocation $invocation, + Texy\Image $image, + ?Texy\Link $link, +) { + // zde bude vaše logika +}); +``` + +První parametr je název elementu, druhý je callback funkce. Callback dostává jako první parametr vždy objekt `Texy\HandlerInvocation`, následují parametry jsou specifické pro daný element. + +.[note] +Podrobné vysvětlení všech typů handlerů najdete v kapitole [Architektura a principy |architecture]. + + +Jak funguje zpracování +====================== + +Když Texy potřebuje zpracovat element, vytvoří objekt `HandlerInvocation` obsahující všechny zaregistrované handlery pro tento typ prvku. **Váš handler se zavolá jako první** a může: + +- **Delegovat** na další handler voláním `$invocation->proceed()` +- **Upravit vstup** voláním `proceed()` s modifikovanými parametry +- **Upravit výstup** zpracováním výsledku z `proceed()` +- **Přerušit řetěz** vrácením vlastního výsledku bez volání `proceed()` + +Metoda `proceed()` posune zpracování na další handler v řetězu. Pokud už žádný vlastní handler není, zavolá se výchozí implementace z modulu. To znamená, že váš handler má absolutní kontrolu - může rozhodnout, zda se vůbec zavolá výchozí logika. + +Tento mechanismus se nazývá **chain of responsibility** (řetěz zodpovědnosti): + +```php +$texy->addHandler('image', function( + Texy\HandlerInvocation $invocation, + Texy\Image $image, + ?Texy\Link $link, +) { + // 1. Upravíme vstupní data před zpracováním + $image->modifier->title = 'Modified title'; + + // 2. Zavoláme další handler nebo výchozí zpracování + $element = $invocation->proceed($image, $link); + + // 3. Upravíme výsledný HTML element + $element->attrs['loading'] = 'lazy'; + + return $element; +}); +``` + +Pořadí vykonávání je od **posledně registrovaného k prvnímu**. Pokud modul zaregistruje svůj výchozí handler při konstrukci a vy pak zaregistrujete vlastní handler, váš handler se zavolá první. To vám umožňuje přepsat nebo obalit výchozí chování. + + +Výchozí elementy +================ + +Texy poskytuje několik předpřipravených elementů, pro které můžete registrovat vlastní handlery. Zde je jejich kompletní seznam s parametry, které dostává handler. + + +image +----- + +Zpracovává obrázky. + +```php +function( + Texy\HandlerInvocation $invocation, + Texy\Image $image, + ?Texy\Link $link, +): Texy\HtmlElement|string|null +``` + +Parametr `$image` obsahuje URL, rozměry a modifikátory. Parametr `$link` je zadán, pokud je obrázek odkazem (syntaxe `[* img *]:url`). + + +linkReference +------------- + +Zpracovává referenční odkazy typu `[ref]`. + +```php +function( + Texy\HandlerInvocation $invocation, + Texy\Link $link, + string $content, +): Texy\HtmlElement|string|null +``` + +Parametr `$link` obsahuje URL a modifikátory načtené z definice reference. Parametr `$content` je HTML obsah odkazu (již zpracovaný parsováním inline syntaxí). + + +linkEmail +--------- + +Zpracovává automaticky rozpoznané emailové adresy v textu. + +```php +function( + Texy\HandlerInvocation $invocation, + Texy\Link $link, +): Texy\HtmlElement|string|null +``` + +Parametr `$link` obsahuje emailovou adresu v property `URL`. + + +linkURL +------- + +Zpracovává automaticky rozpoznané URL v textu. + +```php +function( + Texy\HandlerInvocation $invocation, + Texy\Link $link, +): Texy\HtmlElement|string|null +``` + +Parametr `$link` obsahuje nalezenou URL. + + +phrase +------ + +Zpracovává inline formátování. + +```php +function( + Texy\HandlerInvocation $invocation, + string $phrase, + string $content, + Texy\Modifier $modifier, + ?Texy\Link $link, +): Texy\HtmlElement|string|null +``` + +Parametr `$phrase` je název syntaxe jako `phrase/strong` nebo `phrase/em`. Parametr `$content` je text uvnitř formátování. Parametr `$modifier` obsahuje CSS třídy, styly a další modifikátory. Parametr `$link` je zadán, pokud má formátování připojený odkaz. + + +newReference +------------ + +Volá se, když parser najde referenci, která není definovaná. + +```php +function( + Texy\HandlerInvocation $invocation, + string $name, +): Texy\HtmlElement|string|null +``` + +Parametr `$name` je název reference. Handler může vytvořit odkaz dynamicky nebo vrátit `null` pro odmítnutí. + + +htmlComment +----------- + +Zpracovává HTML komentáře. + +```php +function( + Texy\HandlerInvocation $invocation, + string $content, +): string +``` + +Parametr `$content` je text mezi `<!--` a `-->`. + + +htmlTag +------- + +Zpracovává HTML tagy v textu. + +```php +function( + Texy\HandlerInvocation $invocation, + Texy\HtmlElement $el, + bool $isStart, + ?bool $forceEmpty, +): Texy\HtmlElement|string|null +``` + +Parametr `$el` je element s názvem a atributy. Parametr `$isStart` určuje, zda jde o otevírací tag. Parametr `$forceEmpty` vynutí prázdný element. + + +script +------ + +Zpracovává skripty `{{command: args}}`. + +```php +function( + Texy\HandlerInvocation $invocation, + string $command, + array $args, + ?string $raw, +): Texy\HtmlElement|string|null +``` + +Parametr `$command` je název příkazu. Parametr `$args` je pole argumentů. Parametr `$raw` je původní neparsovaný řetězec argumentů. + + +figure +------ + +Zpracovává obrázky s popiskou. + +```php +function( + Texy\HandlerInvocation $invocation, + Texy\Image $image, + ?Texy\Link $link, + string $content, + Texy\Modifier $modifier, +): Texy\HtmlElement|null +``` + +Parametr `$content` je text popisky pod obrázkem. + + +heading +------- + +Zpracovává nadpisy. + +```php +function( + Texy\HandlerInvocation $invocation, + int $level, + string $content, + Texy\Modifier $modifier, + bool $isSurrounded, +): Texy\HtmlElement +``` + +Parametr `$level` je úroveň nadpisu (0-6). Parametr `$content` je text nadpisu. Parametr `$isSurrounded` určuje, zda jde o ohraničený nadpis (`###`) nebo podtržený. + + +horizline +--------- + +Zpracovává horizontální čáry. + +```php +function( + Texy\HandlerInvocation $invocation, + string $type, + Texy\Modifier $modifier, +): Texy\HtmlElement +``` + +Parametr `$type` je řetězec znaků použitých pro čáru (`---` nebo `***`). + + +block +----- + +Zpracovává speciální bloky `/--type` až `\--`. + +```php +function( + Texy\HandlerInvocation $invocation, + string $blocktype, + string $content, + ?string $param, + Texy\Modifier $modifier, +): Texy\HtmlElement|string +``` + +Parametr `$blocktype` je typ bloku s prefixem `block/`, např. `block/code` nebo `block/html`. Parametr `$content` je obsah bloku. Parametr `$param` je volitelný parametr za typem (např. jazyk u kódu). + + +emoticon +-------- + +Zpracovává emotikony (smajlíky). + +```php +function( + Texy\HandlerInvocation $invocation, + string $emoticon, + string $raw, +): Texy\HtmlElement|string +``` + +Parametr `$emoticon` je rozpoznaný emotikon (např. `:-)` nebo `:-(` ). Parametr `$raw` je původní text včetně případných opakujících se znaků (např. `:-)))))` ). + +.[note] +Emotikony jsou ve výchozím nastavení **vypnuté**. Zapnete je pomocí `$texy->allowed['emoticon'] = true;` + + +Výchozí eventy +============== + +Texy poskytuje několik předpřipravených eventů, pro které můžete registrovat handlery. Říká se jim **notification handlery**. Na rozdíl od element handlerů tyto handlery **nic nevrací**. Používají se pro vedlejší efekty jako logování, sběr statistik nebo úpravy již vytvořeného DOM stromu. + + +beforeParse +----------- + +Volá se před začátkem parsování textu. Umožňuje provést předzpracování nebo načíst definice. + +```php +function( + Texy\Texy $texy, + string &$text, + bool $isSingleLine, +): void +``` + +Parametr `$text` je předán referencí, takže ho můžete upravit. Parametr `$isSingleLine` určuje, zda se parsuje jeden řádek nebo celý dokument. + + +afterParse +---------- + +Volá se po dokončení parsování, před konverzí DOM stromu na HTML. Umožňuje upravit vytvořený DOM. + +```php +function( + Texy\Texy $texy, + Texy\HtmlElement $DOM, + bool $isSingleLine, +): void +``` + +Parametr `$DOM` je kořenový element dokumentu, který můžete procházet a upravovat. + + +afterList +--------- + +Volá se po vytvoření seznamu (číslovaného nebo nečíslovaného). + +```php +function( + Texy\BlockParser $parser, + Texy\HtmlElement $element, + Texy\Modifier $modifier, +): void +``` + +Parametr `$element` je vytvořený element `<ul>` nebo `<ol>`. Parametr `$modifier` obsahuje modifikátory aplikované na celý seznam. + + +afterDefinitionList +------------------- + +Volá se po vytvoření definičního seznamu. + +```php +function( + Texy\BlockParser $parser, + Texy\HtmlElement $element, + Texy\Modifier $modifier, +): void +``` + +Parametr `$element` je vytvořený element `<dl>`. + + +afterTable +---------- + +Volá se po vytvoření tabulky. + +```php +function( + Texy\BlockParser $parser, + Texy\HtmlElement $element, + Texy\Modifier $modifier, +): void +``` + +Parametr `$element` je vytvořený element `<table>`. + + +afterBlockquote +--------------- + +Volá se po vytvoření citace. + +```php +function( + Texy\BlockParser $parser, + Texy\HtmlElement $element, + Texy\Modifier $modifier, +): void +``` + +Parametr `$element` je vytvořený element `<blockquote>`. + + +Základní použití +================ + +Nejjednodušší element handler jen deleguje na výchozí zpracování: + +```php +$texy->addHandler('image', function( + Texy\HandlerInvocation $invocation, + Texy\Image $image, + ?Texy\Link $link, +) { + return $invocation->proceed(); +}); +``` + +Tento handler nic nemění, ale ukazuje základní kostru. Všechny parametry předá dál a vrátí výsledek. + + +Úprava vstupních dat +-------------------- + +Handler může upravit data před jejich zpracováním: + +```php +$texy->addHandler('image', function( + Texy\HandlerInvocation $invocation, + Texy\Image $image, + ?Texy\Link $link, +) { + // přidáme default rozměry, pokud nejsou zadané + $image->width ??= 800; + $image->height ??= 600; + return $invocation->proceed(); +}); +``` + +Změny provedené na objektech `$image` nebo `$link` se projeví v dalším zpracování, včetně výchozího handleru. + + +Úprava výstupního elementu +-------------------------- + +Handler může upravit HTML element vrácený z `proceed()`: + +```php +$texy->addHandler('image', function( + Texy\HandlerInvocation $invocation, + Texy\Image $image, + ?Texy\Link $link, +) { + $element = $invocation->proceed(); + + if ($element) { + // přidáme lazy loading + $element->attrs['loading'] = 'lazy'; + + // přidáme CSS třídu + $element->attrs['class'][] = 'responsive'; + } + + return $element; +}); +``` + + +Podmíněné zpracování +-------------------- + +Handler může zpracovat pouze určité případy a ostatní delegovat: + +```php +$texy->addHandler('image', function( + Texy\HandlerInvocation $invocation, + Texy\Image $image, + ?Texy\Link $link, +) { + // speciální zpracování pro YouTube videa + if (str_starts_with($image->URL, 'youtube:')) { + $id = substr($image->URL, 8); + $iframe = sprintf( + '<iframe src="https://youtube.com/embed/%s"></iframe>', + htmlspecialchars($id) + ); + return $invocation->getTexy() + ->protect($iframe, Texy\Texy::CONTENT_BLOCK); + } + + // ostatní obrázky zpracujeme standardně + return $invocation->proceed(); +}); +``` + + +Přerušení zpracování +-------------------- + +Handler může odmítnout zpracování vrácením `null`: + +```php +$texy->addHandler('image', function( + Texy\HandlerInvocation $invocation, + Texy\Image $image, + ?Texy\Link $link, +) { + // zakážeme externí obrázky + if (str_contains($image->URL, '://')) { + return null; + } + + return $invocation->proceed(); +}); +``` + + +Praktické příklady +================== + +Následující příklady ukazují reálné use-case pro element handlery. + + +YouTube embed +------------- + +Převod speciální syntaxe na embedded video: + +```php +$texy->addHandler('image', function( + Texy\HandlerInvocation $invocation, + Texy\Image $image, + ?Texy\Link $link, +) { + if (str_starts_with($image->URL, 'youtube:')) { + $id = substr($image->URL, 8); + $width = $image->width ?: 560; + $height = $image->height ?: 315; + + $iframe = sprintf( + '<iframe width="%d" height="%d" ' + . 'src="https://youtube.com/embed/%s" ' + . 'frameborder="0" allowfullscreen></iframe>', + $width, $height, htmlspecialchars($id) + ); + + $texy = $invocation->getTexy(); + return $texy->protect($iframe, $texy::CONTENT_BLOCK); + } + + return $invocation->proceed(); +}); +``` + +Použití v textu: + +```texy +[* youtube:dQw4w9WgXcQ 640x360 *] +``` + + +Galerie obrázků +--------------- + +Obalení obrázků do speciálního divu pro lightbox: + +```php +$texy->addHandler('image', function( + Texy\HandlerInvocation $invocation, + Texy\Image $image, + ?Texy\Link $link, +) { + $element = $invocation->proceed(); + + // pokud má obrázek třídu 'gallery' + if (isset($image->modifier->classes['gallery'])) { + // obalíme do divu s lightbox atributy + $wrapper = new Texy\HtmlElement('div'); + $wrapper->attrs['class'][] = 'lightbox-item'; + $wrapper->attrs['data-src'] = $image->URL; + $wrapper->add($element); + + return $wrapper; + } + + return $element; +}); +``` + +Použití: + +```texy +[* image.jpg .[gallery] *] +``` + + +Validace odkazů +--------------- + +Kontrola, zda odkazy nalezené v textu vedou na povolené domény: + +```php +$allowedDomains = ['example.com', 'trusted.org']; + +$texy->addHandler('linkURL', function( + Texy\HandlerInvocation $invocation, + Texy\Link $link, +) use ($allowedDomains) { + $host = parse_url($link->URL, PHP_URL_HOST); + + // pokud doména není v whitelistu, nepovolíme odkaz + if ($host && !in_array($host, $allowedDomains, true)) { + return null; + } + + return $invocation->proceed(); +}); +``` + + +Automatické rel="nofollow" +-------------------------- + +Přidání `nofollow` všem externím odkazům nalezeným v textu: + +```php +$texy->addHandler('linkURL', function( + Texy\HandlerInvocation $invocation, + Texy\Link $link, +) { + $element = $invocation->proceed(); + + // pokud odkaz obsahuje // (tedy je externí) + if (str_contains($link->URL, '://')) { + $element->attrs['rel'] = 'nofollow'; + } + + return $element; +}); +``` + + +Syntax highlighting +------------------- + +Integrace knihovny pro zvýraznění syntaxe: + +```php +$texy->addHandler('block', function( + Texy\HandlerInvocation $invocation, + string $blocktype, + string $content, + ?string $param, + Texy\Modifier $modifier, +) { + // zpracujeme pouze bloky typu 'code' + if ($blocktype !== 'block/code') { + return $invocation->proceed(); + } + + // aplikujeme syntax highlighting + $highlighter = new MyHighlighter(); + $highlighted = $highlighter->highlight($content, $param); + + $el = new Texy\HtmlElement('pre'); + $modifier->decorate($invocation->getTexy(), $el); + $el->attrs['class'][] = 'language-' . $param; + + $code = new Texy\HtmlElement('code'); + $code->add($highlighted); + $el->add($code); + + return $el; +}); +``` + + +Lazy loading +------------ + +Projdeme všechny obrázky a přidáme lazy loading: + +```php +$texy->addHandler('afterParse', function( + Texy\Texy $texy, + Texy\HtmlElement $DOM, + bool $isSingleLine, +) { + foreach ($DOM->getIterator() as $child) { + if ($child instanceof Texy\HtmlElement + && $child->getName() === 'img' + ) { + $child->attrs['loading'] = 'lazy'; + } + } +}); +``` + + +Logování použitých prvků +------------------------ + +Sběr statistik o použitých prvcích v dokumentu: + +```php +$stats = []; + +$texy->addHandler('beforeParse', function( + Texy\Texy $texy, + string &$text, + bool $isSingleLine, +) use (&$stats) { + $stats = ['images' => 0, 'links' => 0, 'headings' => 0]; +}); + +$texy->addHandler('image', function( + Texy\HandlerInvocation $invocation, + Texy\Image $image, + ?Texy\Link $link, +) use (&$stats) { + $stats['images']++; + return $invocation->proceed(); +}); + +$texy->addHandler('linkURL', function( + Texy\HandlerInvocation $invocation, + Texy\Link $link, +) use (&$stats) { + $stats['links']++; + return $invocation->proceed(); +}); + +$texy->addHandler('heading', function( + Texy\HandlerInvocation $invocation, + int $level, + string $content, + Texy\Modifier $modifier, + bool $isSurrounded, +) use (&$stats) { + $stats['headings']++; + return $invocation->proceed(); +}); +``` + + +Pomocné třídy +============= + +Při práci s handlery budete pracovat s několika důležitými třídami. Zde je jejich přehled s nejdůležitějšími vlastnostmi. + + +Texy\Image +---------- + +Reprezentuje obrázek s jeho parametry: + +```php +$image->URL; // string - cesta k obrázku +$image->linkedURL; // ?string - URL odkazu (pokud je obrázek odkazem) +$image->width; // ?int - šířka v pixelech +$image->height; // ?int - výška v pixelech +$image->asMax; // bool - zda jsou rozměry maximální +$image->modifier; // Modifier - CSS třídy, styly, atributy +$image->name; // ?string - název reference +``` + + +Texy\Link +--------- + +Reprezentuje odkaz s jeho parametry: + +```php +$link->URL; // string - cílová URL +$link->raw; // string - původní URL (před normalizací) +$link->modifier; // Modifier - CSS třídy, styly, atributy +$link->type; // string - typ odkazu (COMMON, BRACKET, IMAGE) +$link->label; // ?string - text odkazu (u referencí) +$link->name; // ?string - název reference +``` + +Konstanty pro typ odkazu: + +```php +Texy\Link::COMMON; // běžný odkaz +Texy\Link::BRACKET; // referenční odkaz [ref] +Texy\Link::IMAGE; // odkaz z obrázku [* img *] +``` + + +Texy\HtmlElement +---------------- + +Reprezentuje HTML element s jeho atributy a obsahem: + +```php +$el = new Texy\HtmlElement('div'); + +// práce s názvem elementu +$el->getName(); // vrací 'div' +$el->setName('section'); // změní na 'section' + +// práce s atributy +$el->attrs['id'] = 'main'; +$el->attrs['class'][] = 'container'; +$el->attrs['style']['color'] = 'red'; + +// práce s obsahem +$el->setText('text'); // nastaví textový obsah +$el->getText(); // vrací textový obsah +$el->add($child); // přidá potomka +$el->insert(0, $child); // vloží potomka na pozici + +// parsování obsahu +$el->parseLine($texy, $text); // parsuje inline text +$el->parseBlock($texy, $text); // parsuje blokový text + +// konverze na HTML +$el->toString($texy); // internal reprezentace +$el->toHtml($texy); // finální HTML +``` + + +Texy\Modifier +------------- + +Reprezentuje modifikátory CSS tříd, stylů a atributů: + +```php +$mod->id; // ?string - HTML id +$mod->classes; // array - pole CSS tříd +$mod->styles; // array - pole CSS stylů +$mod->attrs; // array - HTML atributy +$mod->hAlign; // ?string - horizontální zarovnání (left, right, center, justify) +$mod->vAlign; // ?string - vertikální zarovnání (top, middle, bottom) +$mod->title; // ?string - title atribut nebo alt pro obrázky + +// aplikace modifikátoru na element +$mod->decorate($texy, $element); +``` diff --git a/texy/cs/custom-syntax.texy b/texy/cs/custom-syntax.texy new file mode 100644 index 0000000000..f8f7634b5c --- /dev/null +++ b/texy/cs/custom-syntax.texy @@ -0,0 +1,519 @@ +Přidání vlastní syntaxe +*********************** + +.[perex] +Tato kapitola popisuje, jak přidat do Texy **zcela nové markup konstrukce**, které standardně neexistují. Pokud chcete pouze změnit chování existujících prvků (například upravit zpracování obrázků nebo odkazů), přečtěte si kapitolu [Úprava chování prvků |custom-handlers]. + +Představte si, že chcete v dokumentaci automaticky vytvářet odkazy na uživatelské profily zápisem `@@username`. Nebo potřebujete speciální bloky pro upozornění typu `:::warning`. Texy tyto konstrukce nezná a nemůžete je vytvořit úpravou existujících prvků. + +Vlastní syntaxe vám umožní definovat nové markup konstrukce. Zadáte, jak má konstrukce vypadat (pomocí regulárního výrazu), a napíšete funkci, která ji zpracuje. Texy pak vaši syntaxi rozpozná stejně jako své standardní konstrukce. + + +Registrace syntaxe +================== + +Texy poskytuje dvě metody pro registraci vlastní syntaxe podle toho, zda jde o inline nebo blokový prvek. + + +Line syntaxe +------------ + +Line syntaxe slouží pro inline konstrukce uvnitř řádků textu. Registrujete ji metodou `registerLinePattern()`: + +```php +$texy->registerLinePattern( + callable $handler, + string $pattern, + string $name, + ?string $againTest = null, +); +``` + +**Parametr `$handler`** je callback funkce, která se zavolá při nálezu syntaxe. Může to být název funkce, anonymní funkce nebo pole `[$object, 'method']`. + +**Parametr `$pattern`** je regulární výraz (PCRE), který definuje, jak vaše syntaxe vypadá v textu. Pattern by **neměl být kotvený** na začátek řádku (`^`), protože se hledá kdekoliv v textu. Použijte capturing groups pro zachycení dat, která potřebujete zpracovat. + +**Parametr `$name`** je unikátní název syntaxe. Používá se v poli `$texy->allowed` pro zapnutí/vypnutí a předává se do handleru pro identifikaci. Doporučujeme používat prefixový styl jako `custom/username` nebo `myapp/profile`. + +**Parametr `$againTest`** je volitelný regex pro optimalizaci. Pokud je zadán, Texy nejprve zkontroluje, zda text vůbec obsahuje něco, co by mohlo matchnout váš pattern. Teprve pokud `$againTest` uspěje, spustí se komplexnější pattern. To výrazně zrychlí zpracování, pokud máte složitý pattern a používá se jen zřídka. + +Příklad registrace: + +```php +$texy->registerLinePattern( + 'usernameHandler', + '#@@([a-z0-9_]+)#i', + 'custom/username', +); +``` + + +Block syntaxe +------------- + +Block syntaxe slouží pro víceřádkové blokové konstrukce. Registrujete ji metodou `registerBlockPattern()`: + +```php +$texy->registerBlockPattern( + callable $handler, + string $pattern, + string $name, +); +``` + +Parametry `$handler` a `$name` mají stejný význam jako u line syntaxí. + +**Parametr `$pattern`** je regulární výraz, který **musí být kotvený** na začátek řádku (`^`) a často i na konec (`$`). BlockParser automaticky přidá modifikátory `Am` (anchored, multiline), takže je do patternu nepřidávejte. Pattern by měl matchnout celý blok nebo alespoň jeho začátek. + +Příklad registrace: + +```php +$texy->registerBlockPattern( + 'alertHandler', + '#^:::(warning|info|danger)\n(.+)$#s', + 'custom/alert', +); +``` + + +Syntax handler +============== + +Syntax handler je funkce volaná parserem, když najde výskyt vaší syntaxe v textu. Jeho úkolem je zpracovat nalezená data a vrátit HTML element nebo řetězec. + +Podrobné vysvětlení role syntax handleru v architektuře Texy najdete v kapitole [Architektura a principy |architecture#syntax-handler]. + + +Pro line syntaxe +---------------- + +Signatura syntax handleru pro line syntaxe: + +```php +function( + Texy\LineParser $parser, + array $matches, + string $name, +): Texy\HtmlElement|string|null +``` + +**Parametr `$parser`** poskytuje přístup k parseru a Texy objektu. Nejčastěji použijete `$parser->getTexy()` pro získání Texy instance. + +**Parametr `$matches`** obsahuje výsledky regex matche. `$matches[0]` je celý matchnutý řetězec, `$matches[1]`, `$matches[2]` atd. jsou capturing groups z vašeho patternu. + +**Parametr `$name`** je název syntaxe, který jste zadali při registraci. Užitečné, pokud jeden handler zpracovává více syntaxí. + +**Návratová hodnota** může být `Texy\HtmlElement` pro strukturovaný HTML výstup, `string` pro přímý HTML kód (který musíte protectovat), nebo `null` pro odmítnutí zpracování. + +Handler může nastavit `$parser->again = true`, pokud chce, aby se obsah vytvořeného elementu znovu parsoval pro nalezení vnořených syntaxí. + + +Pro block syntaxe +----------------- + +Signatura syntax handleru pro block syntaxe: + +```php +function( + Texy\BlockParser $parser, + array $matches, + string $name, +): Texy\HtmlElement|string|null +``` + +Parametry mají stejný význam jako u line syntaxí, jen dostáváte `Texy\BlockParser` místo `LineParser`. + +BlockParser poskytuje metody pro práci s víceřádkovými strukturami: + +- **`$parser->next($pattern, &$matches)`** - matchne další řádek proti patternu a vrátí true/false +- **`$parser->moveBackward($lines)`** - vrátí se o zadaný počet řádků zpět +- **`$parser->isIndented()`** - vrací true, pokud je aktuální blok odsazený + + +LineParser API +============== + +Při práci s line syntaxemi máte k dispozici několik užitečných vlastností a metod. + +**Property `$again`** řídí, zda se má právě zpracovaná syntaxe hledat znovu na stejné pozici po zpracování. Výchozí hodnota je `false`. Nastavte na `true`, pokud vytváříte element s obsahem, který může obsahovat další syntaxe: + +```php +function( + Texy\LineParser $parser, + array $matches, + string $name, +): Texy\HtmlElement +{ + $el = new Texy\HtmlElement('span'); + $el->setText($matches[1]); + + // obsah může obsahovat další formátování + $parser->again = true; + + return $el; +} +``` + +**Metoda `getTexy()`** vrací instanci Texy objektu, což potřebujete pro práci s `protect()` nebo přístup ke konfiguraci. + + +BlockParser API +=============== + +Při práci s block syntaxemi máte k dispozici metody pro práce s víceřádkovými strukturami. + +**Metoda `next($pattern, &$matches)`** zkusí matchnout další řádek v textu proti zadanému patternu. Pokud uspěje, naplní `$matches` výsledkem a posune interní pozici za tento řádek. Vrací `true` při úspěchu, `false` při neúspěchu: + +```php +while ($parser->next('#^\-\s+(.+)$#', $matches)) { + // zpracuj další položku seznamu + $item = $matches[1]; +} +``` + +**Metoda `moveBackward($lines = 1)`** vrátí interní pozici o zadaný počet řádků zpět. Užitečné, když váš pattern matchnul víc než začátek bloku a chcete se vrátit na začátek: + +```php +// pattern matchnul 3 řádky, ale chceme číst od prvního +$parser->moveBackward(2); +``` + +**Metoda `isIndented()`** vrací `true`, pokud je aktuální blok odsazený (začíná mezerou nebo tabulátorem). To naznačuje, že jde o vnořený obsah. + + +Praktické příklady +================== + +Následující příklady ukazují reálné use-case pro vlastní syntaxe. + + +Uživatelské profily +------------------- + +Automatické vytváření odkazů na profily zápisem `@@username`: + +```php +$texy->registerLinePattern( + function( + Texy\LineParser $parser, + array $matches, + string $name, + ): Texy\HtmlElement + { + $username = $matches[1]; + + $el = new Texy\HtmlElement('a'); + $el->attrs['href'] = '/user/' . urlencode($username); + $el->attrs['class'][] = 'user-profile'; + $el->setText('@' . $username); + + return $el; + }, + '#@@([a-z0-9_]+)#i', + 'custom/username' +); +``` + +Použití v textu: + +```texy +Podívejte se na profil @@johndoe nebo @@jane_smith. +``` + + +Alert boxy +---------- + +Speciální bloky pro upozornění s různými typy: + +```php +$texy->registerBlockPattern( + function( + Texy\BlockParser $parser, + array $matches, + string $name, + ): Texy\HtmlElement + { + $type = $matches[1]; // warning, info, danger + $content = $matches[2]; + + $el = new Texy\HtmlElement('div'); + $el->attrs['class'][] = 'alert'; + $el->attrs['class'][] = 'alert-' . $type; + + $texy = $parser->getTexy(); + $el->parseBlock($texy, trim($content)); + + return $el; + }, + '#^:::(warning|info|danger)\n(.+?)(?=\n:::|$)#s', + 'custom/alert' +); +``` + +Použití v textu: + +```texy +:::warning +Toto je důležité upozornění! +::: + +:::info +Pro informaci: aktualizace proběhne zítra. +::: +``` + + +Hashtagy +-------- + +Automatické vytváření odkazů z hashtagů: + +```php +$texy->registerLinePattern( + function( + Texy\LineParser $parser, + array $matches, + string $name, + ): Texy\HtmlElement + { + $tag = $matches[1]; + + $el = new Texy\HtmlElement('a'); + $el->attrs['href'] = '/tag/' . urlencode($tag); + $el->attrs['class'][] = 'hashtag'; + $el->setText('#' . $tag); + + return $el; + }, + '#\#([a-z0-9_]+)#i', + 'custom/hashtag', + '#\##' // optimalizace - hledej jen pokud je # v textu +); +``` + +Použití: + +```texy +Článek o #php a #webdesign. +``` + + +Zkratky +------- + +Automatické rozbalení zkratek s vysvětlením: + +```php +$abbreviations = [ + 'HTML' => 'HyperText Markup Language', + 'CSS' => 'Cascading Style Sheets', + 'PHP' => 'PHP: Hypertext Preprocessor', +]; + +$texy->registerLinePattern( + function( + Texy\LineParser $parser, + array $matches, + string $name + ) use ($abbreviations): ?Texy\HtmlElement + { + $abbr = $matches[1]; + + if (!isset($abbreviations[$abbr])) { + return null; // neznámá zkratka + } + + $el = new Texy\HtmlElement('abbr'); + $el->attrs['title'] = $abbreviations[$abbr]; + $el->setText($abbr); + + return $el; + }, + '#\b([A-Z]{2,})\b#', + 'custom/abbreviation' +); +``` + + +Inline ikony +------------ + +Vkládání ikon pomocí speciální syntaxe: + +```php +$texy->registerLinePattern( + function( + Texy\LineParser $parser, + array $matches, + string $name, + ): Texy\HtmlElement + { + $icon = $matches[1]; + + $el = new Texy\HtmlElement('i'); + $el->attrs['class'][] = 'icon'; + $el->attrs['class'][] = 'icon-' . $icon; + $el->attrs['aria-hidden'] = 'true'; + + return $el; + }, + '#:icon-([a-z-]+):#', + 'custom/icon' +); +``` + +Použití: + +```texy +Klikněte na tlačítko :icon-download: pro stažení. +``` + + +Poznámkový blok +--------------- + +Blok pro poznámky pod čarou: + +```php +$texy->registerBlockPattern( + function( + Texy\BlockParser $parser, + array $matches, + string $name + ): Texy\HtmlElement + { + $parser->moveBackward(); + + $content = ''; + while ($parser->next('#^NOTE:\s*(.+)$#', $matches)) { + $content .= $matches[1] . "\n"; + } + + $el = new Texy\HtmlElement('aside'); + $el->attrs['class'][] = 'note'; + + $texy = $parser->getTexy(); + $el->parseBlock($texy, trim($content)); + + return $el; + }, + '#^NOTE:\s*(.+)$#m', + 'custom/note' +); +``` + +Použití: + +```texy +NOTE: Toto je důležitá poznámka. +NOTE: Může být víceřádková. +``` + + +Vlastní citace s autorem +------------------------ + +Rozšířená syntaxe pro citace s uvedením autora: + +```php +$texy->registerBlockPattern( + function( + Texy\BlockParser $parser, + array $matches, + string $name, + ): Texy\HtmlElement + { + $author = $matches[1]; + $quote = $matches[2]; + + $blockquote = new Texy\HtmlElement('blockquote'); + + $texy = $parser->getTexy(); + $blockquote->parseBlock($texy, trim($quote)); + + $cite = new Texy\HtmlElement('cite'); + $cite->setText($author); + $blockquote->add($cite); + + return $blockquote; + }, + '#^QUOTE\[([^\]]+)\]:\n(.+?)(?=\n\n|$)#s', + 'custom/quote' +); +``` + +Použití: + +```texy +QUOTE[Albert Einstein]: +Fantazie je důležitější než vědění, +protože vědění je omezené. +``` + + +Galerie obrázků +--------------- + +Speciální blok pro vytvoření galerie z více obrázků: + +```php +$texy->registerBlockPattern( + function( + Texy\BlockParser $parser, + array $matches, + string $name, + ): Texy\HtmlElement + { + $parser->moveBackward(); + + $gallery = new Texy\HtmlElement('div'); + $gallery->attrs['class'][] = 'gallery'; + + while ($parser->next('#^\[G\]\s*(.+)$#', $matches)) { + $img = new Texy\HtmlElement('img'); + $img->attrs['src'] = trim($matches[1]); + $img->attrs['loading'] = 'lazy'; + $gallery->add($img); + } + + return $gallery; + }, + '#^\[G\]\s*(.+)$#m', + 'custom/gallery' +); +``` + +Použití: + +```texy +[G] image1.jpg +[G] image2.jpg +[G] image3.jpg +``` + + +Kolize syntaxí +============== + +Když registrujete vlastní syntaxi, musíte dávat pozor, aby nekolidovala s existujícími syntaxemi Texy nebo s jinými vlastními syntaxemi. + +**Pořadí registrace záleží.** Line syntaxe se hledají v pořadí, jak byly registrovány. Pokud více syntaxí může matchnout na stejné pozici, vyhrává ta, která byla registrována dříve. Proto registrujte specifičtější syntaxe před obecnějšími. + +**Buďte specifičtí v patterns.** Čím konkrétnější je váš pattern, tím menší je riziko kolize. Pattern `#\#\w+#` matchne i `#hashtag`, což by mohlo kolidovat s nadpisy. Lepší je `#(?<=\s)\#[a-z0-9_]+#i`, který vyžaduje mezeru před hashtagem. + +**Testujte kombinace.** Vyzkoušejte, jak vaše syntaxe funguje v kombinaci s existujícími konstrukcemi. Co se stane, když je váš markup uvnitř odkazu? Co když je uvnitř code bloku? + +**Používejte prefixované názvy.** Místo `username` použijte `custom/username` nebo `myapp/username`. To zabrání konfliktům, pokud by Texy v budoucnu přidalo syntaxi stejného názvu. + + +Best practices +============== + +**Vracejte `null` při neúspěchu.** Pokud handler zjistí, že nemůže nebo nechce zpracovat daný match (například neznámá zkratka), vraťte `null`. Parser pak zkusí další syntaxe. + +**Používejte `protect()` pro HTML.** Pokud vracíte raw HTML string místo `HtmlElement`, musíte ho protectovat pomocí `$texy->protect($html, Texy::CONTENT_...)`. Jinak bude escapován. + +**Nastavte `$parser->again` správně.** Pro line syntaxe, které vytváří element s textovým obsahem, který může obsahovat další syntaxe (formátování, odkazy), nastavte `$parser->again = true`. + +**Respektujte `$texy->allowed`.** Pokud vytváříte modul s více syntaxemi, kontrolujte `$texy->allowed[$name]` před registrací patternu nebo v handleru před zpracováním. diff --git a/texy/cs/develop.texy b/texy/cs/develop.texy new file mode 100644 index 0000000000..cc388cd830 --- /dev/null +++ b/texy/cs/develop.texy @@ -0,0 +1,35 @@ +Pro programátory +**************** + +.[perex] +Vítejte v programátorské dokumentaci Texy! Tato sekce vás provede od základního použití až po pokročilé techniky rozšíření a vlastní syntaxe. + + +[Rychlý start | quickstart] +--------------------------- + +Instalace, první použití a základní konfigurace. Za 5 minut budete mít Texy funkční. + + +[Konfigurace | configuration] +----------------------------- + +Kompletní přehled všech modulů, jejich vlastností a konfiguračních možností. Nastavení bezpečnosti, povolených značek, stylů a tříd. + + +[Úprava chování prvků | custom-handlers] +---------------------------------------- + +Naučte se měnit chování existující syntaxe. YouTube embedování, syntax highlighting, custom validace. + + +[Přidání vlastní syntaxe | custom-syntax] +----------------------------------------- + +Vytvoření zcela nových syntaktických prvků. + + +[Architektura a principy | architecture] +---------------------------------------- + +Pochopení toho, jak Texy interně funguje. Parsing flow, moduly, pattern matching, protect/unprotect mechanismus. diff --git a/texy/cs/priklady-vyuziti.texy b/texy/cs/priklady-vyuziti.texy deleted file mode 100644 index f71b9616dc..0000000000 --- a/texy/cs/priklady-vyuziti.texy +++ /dev/null @@ -1,26 +0,0 @@ -Příklady využití -**************** - - -Běžní uživatelé .[#bfu] ------------------------ - -Texy původně vznikl jako nástroj, který umožnil i uživatelům neznalým HTML **snadno editovat obsah** webových stránek. Záměrem bylo vytvořit silnou **alternativu k WYSIWYG** editorům, které se v praxi [ukazují jako neefektivní | texy-vs-wysiwyg]. - -Běžný uživatel se může plně věnovat psaní "čistého textu .(například v Poznámkovém bloku)[about]", který si formátuje velmi [přirozeným způsobem | syntax]. A nemusí se téměř nic nového učit. - - -Zkušení pisatelé .[#experienced] --------------------------------- - -Zkušení tvůrci internetového obsahu, jakými jsou například bloggeři, často jazyk HTML znají. Ale psát články přímo v něm je nepříjemné a proto si zjednodušují práci používáním chytrých editorů. Jedním z nich je i Texy Je navíc dostupný i přes webové rozhraní a nabízí **neobvykle vysoký konfort**. - -Díky Texy se autor může plně věnovat obsahu dokumentu a nemusí uvažovat nad HTML nebo typografickou úpravou. Texy dokáže psaní výrazně zjednodušit, přitom pokročilého uživatele nijak neomezuje - nabízí mu **vkládat i HTML značky** a CSS formátování. - - -Komentáře a diskuzní fóra .[#comments] --------------------------------------- - -Texy počítá i s nasazením jako formátovač příspěvků v diskuzních fórech a komentářích. Přispívatelé mohou používat jednotnou a **intuitivní syntaxi** a programátorům **odpadne náročná práce** na vlastním formátovači. - -Tato oblast použití je charakteristická tím, že vyžaduje mnohem **přísnější kontrolu** vstupů. Texy proto obsahuje mechanismy, které zakáží nebo omezí použití určitých HTML značek (a jejich atributů), kaskádových stylů a tříd atd. diff --git a/texy/cs/quickstart.texy b/texy/cs/quickstart.texy new file mode 100644 index 0000000000..8c16245ab4 --- /dev/null +++ b/texy/cs/quickstart.texy @@ -0,0 +1,205 @@ +Rychlý start +************ + +.[perex] +Naučte se pracovat s Texy za pár minut. Tato stránka vás provede instalací, prvním použitím a základní konfigurací. + + +Instalace +========= + +Texy využívá moderních vlastností PHP a vyžaduje minimálně verzi 8.1. + +Nejjednodušší způsob instalace je přes Composer: + +```bash +composer require texy/texy +``` + +Composer automaticky stáhne Texy a všechny závislosti. + + +První použití +============= + + +Základní zpracování textu +------------------------- + +Vytvoření instance Texy a zpracování textu je extrémně jednoduché: + +```php +require __DIR__ . '/vendor/autoload.php'; + +$texy = new Texy\Texy; + +$text = 'Toto je **tučný text** a toto //kurzíva//.'; +$html = $texy->process($text); + +echo $html; +``` + +Výstup: +```latte +<p>Toto je <strong>tučný text</strong> a toto <em>kurzíva</em>.</p> +``` + +Metoda `process()` zpracuje celý text včetně blokových elementů (odstavce, nadpisy, seznamy, tabulky...). + + +Jednořádkový text +----------------- + +Pokud zpracováváte pouze jednořádkový text bez blokových elementů (například nadpisy v databázi, krátké popisky): + +```php +$texy = new Texy\Texy; + +$text = 'Odkaz na "homepage":https://example.com'; +$html = $texy->processLine($text); + +echo $html; +``` + +Výstup: +```latte +Odkaz na <a href="https://example.com">homepage</a> +``` + +Metoda `processLine()` nezabaluje výstup do odstavce `<p>` a zpracuje pouze inline elementy. + + +Základní konfigurace +==================== + +Texy funguje "out of the box", ale často budete chtít upravit základní nastavení. + + +Nastavení cest k obrázkům +------------------------- + +Pokud používáte relativní cesty k obrázkům, nastavte kořenový adresář: + +```php +$texy = new Texy\Texy; + +// Cesta na webu (přidá se před relativní URL) +$texy->imageModule->root = '/images/'; + +// Fyzická cesta na disku (pro zjištění rozměrů) +$texy->imageModule->fileRoot = __DIR__ . '/public/images/'; +``` + +Teď když napíšete `[* photo.jpg *]`, Texy vygeneruje `<img src="/images/photo.jpg">` a automaticky zjistí rozměry obrázku. + + +Nastavení cest k odkazům +------------------------ + +Podobně můžete nastavit kořenový adresář pro odkazy: + +```php +$texy->linkModule->root = '/articles/'; +``` + + +Povolení a zakázání syntaxí +--------------------------- + +Každá část Texy syntaxe lze vypnout nebo zapnout pomocí pole `$allowed`: + +```php +$texy = new Texy\Texy; + +// Vypnout obrázky +$texy->allowed['image'] = false; + +// Vypnout HTML značky ve vstupu +$texy->allowed['html/tag'] = false; + +// Povolit emotikony (ve výchozím stavu vypnuté) +$texy->allowed['emoticon'] = true; +``` + +Kompletní seznam syntaxí najdete v [konfiguraci | configuration#allowed]. + + +Bezpečný režim pro uživatelský obsah +------------------------------------ + +Pokud zpracováváte obsah od uživatelů (komentáře, příspěvky na fóru), použijte bezpečný režim: + +```php +$texy = new Texy\Texy; +Texy\Configurator::safeMode($texy); + +$userInput = $_POST['comment']; +$html = $texy->process($userInput); +``` + +SafeMode: +- Povolí jen **bezpečné HTML značky** (`<strong>`, `<em>`, `<a>`, ...) +- Zakáže **třídy a ID** +- Zakáže **inline styly** +- Zakáže **obrázky** +- Přidá `rel="nofollow"` ke všem odkazům +- Filtruje **URL schémata** (jen `http:`, `https:`, `ftp:`, `mailto:`) + +Více o bezpečnosti v kapitole [Konfigurace – Bezpečnost |configuration#Bezpečnost]. + + +Kompletní příklad +================= + +```php +require __DIR__ . '/vendor/autoload.php'; + +$texy = new Texy\Texy; + +// Konfigurace +$texy->imageModule->root = '/images/'; +$texy->linkModule->root = '/'; +$texy->allowed['html/tag'] = false; + +// Text k zpracování +$text = ' + + +Nadpis článku +============= + +Toto je **úvodní odstavec** s odkazem na "homepage":https://example.com. + +- První položka +- Druhá položka +- Třetí položka + +[* photo.jpg .(Fotografie) *] +'; + +// Zpracování +$html = $texy->process($text); + +// Výstup +echo $html; + +// Dodatečné informace +echo "Titulek stránky: " . $texy->headingModule->title; +print_r($texy->summary['links']); +print_r($texy->summary['images']); +``` + +Po zpracování máte k dispozici: +- `$texy->headingModule->title` – první nadpis (vhodné pro `<title>`) +- `$texy->summary['links']` – pole všech použitých odkazů +- `$texy->summary['images']` – pole všech použitých obrázků + + +Další kroky +=========== + +Teď už víte, jak Texy používat. Pokračujte: + +- **[Konfigurace | configuration]** – podrobné nastavení všech modulů +- **[Syntaxe | syntax]** – naučte se Texy markup +- **[Architektura | architecture]** – pochopte, jak Texy funguje uvnitř diff --git a/texy/cs/syntax-podrobne.texy b/texy/cs/syntax-podrobne.texy deleted file mode 100644 index d10b62068c..0000000000 --- a/texy/cs/syntax-podrobne.texy +++ /dev/null @@ -1,889 +0,0 @@ -Podrobný popis syntaxe -********************** - - -- [#Filozofie] -- [#Odstavce textu] -- [#Titulky] -- [#Horizontální čáry] -- [#Kód] -- [#Vypnutí Texy] -- [#Citace] -- [#Odkazy] -- [#Obrázky] -- [#Fráze] -- [#Přímé HTML] -- [#Seznamy] -- [#Modifikátory] -- [#Typografie] -- [#Rozdělení velmi dlouhých slov] -- [#Tabulky] - - -Filozofie -========= - -Nástroj Texy vznikl proto, aby nezkušeným uživatelům umožnil snadno editovat obsah webových stránek. Proto je i syntaxe maximálně intuitivní. Záměrem je, aby text v čisté (nezformátované) formě byl přehledný a jeho formát tušitelný. - -Dnes Texy výborně slouží i zkušeným znalcům jazyka HTML. Dovoluje volně kombinovat Texy zápis s HTML značkami. Zkušení uživatelé se tedy nemusí učit nový meta-jazyk a plně využít svých znalostí. Texy jim pouze zjednodušuje práci. - -Prvotní logikou syntaxe je **žádnou syntaxi nepoužívat**. Jen psát čistý text. Vkládání rozšířených informací, jako třeba CSS třídy nebo odkazy, nenaruší tok textu. A zapíší se způsobem, který snadno pochopí i netechnicky založení uživatelé. - - -Odstavce textu -============== - -Za odstavec se považuje jeden nebo více bezprostředně za sebou následujících řádků textu. Odstavečky jsou od sebe oddělené prázdným řádkem. - -/--code texy -První odstavec lorem ipsum dolor sit amet. - -Druhý odstavec, který tvoří jeden řádek. -A druhý řádek textu. Texy je spojí. -\-- - -/--texysource -První odstavec lorem ipsum dolor sit amet. - -Druhý odstavec, který tvoří jeden řádek. -A druhý řádek textu. Texy je spojí. -\-- - -*V editačním políčku webové stránky (textarea) není rozdělení odstavce na dva řádky patrné. Proto je i Texy považuje za jeden odstavec.* - -Zalomení řádku v odstavci docílíte vložením jedné mezery vlevo: - -/--code texy -Kdoví jestli - jestli jsou na měsíci vůbec nějaký stopy - a proč kope kolem sebe kdo se topí - jakej sval to Zemí otáčí -\-- - -/--texysource -Kdoví jestli - jestli jsou na měsíci vůbec nějaký stopy - a proč kope kolem sebe kdo se topí - jakej sval to Zemí otáčí -\-- - - -Titulky -======= - -Titulky je možné zapsat hned dvěma způsoby: **podtržením** nebo **předsazením**. - -Každý titulek má svůj stupeň. V případě **podtržení** o důležitosti titulku rozhoduje podtrhávací znak. Od nejvyšší po nejnižší jsou to tyto: `#` `*` `=` `-` - -/--code texy -Hlavní titulek -************** - - -Podtitulek -========== -\-- - -/--texysource -Hlavní titulek -************** - - -Podtitulek -========== -\-- - -U titulků zapsaných **předsazením** určuje úroveň počet předsazených znaků. A ty mohou být `#` nebo `=` - -Platí: čím více znaků, tím důležitější titulek (minimum jsou dva znaky, maximum sedm). - -/--code texy -=== Hlavní titulek === - -## Podtitulek -\-- - -Jak vidíte v případě podtitulku, znaky vpravo je možné vynechat. - -*Stupně titulků jsou vždy jen relativní! Tedy Texy najde nejvyšší použitý titulek a ostatní titulky relativně od něj odstupňuje.* - - -Horizontální čáry -================= - -Texy zná tyto způsoby zápisu: - - -/--code texy ------------- - -******** -\-- - - -/--texysource -------------- - -******** -\-- - - -Kód -=== - -Používá se pro vložení zdrojového kódu. Použitím přídavného modulu lze aktivovat i zvýrazňování syntaxe. - -/--code texy - /---code php - function reImage($matches) { - $content = $matches[1]; - $align = $matches[5]; - $href = $matches[6]; - } - \--- -\-- - -/--texysource - /---code php - function reImage($matches) { - $content = $matches[1]; - $align = $matches[5]; - $href = $matches[6]; - } - \--- -\-- - -*Všimněte si slova `php` pro označení jazyka.* - - -Vypnutí Texy -============ - -Klíčové slovo `html` nebo `text` ovlivňuje, jestli obsah bude chápán jako HTML (včetně značek), nebo prostý text. - -/--code texy - /---html - <em>příklad</em>: **this is not strong** - \--- - - - /---text - <em>příklad</em>: **this is not strong** - \--- -\-- - -Pro inline vypnutí Texy je možné použít dvojitý apostrof `''` a obalit s ním část textu, který nemá být Texy zpracováván. - -/--code texy - Příklad: ''**this is not strong**'' -\-- - - -Rozdělování do bloků (div) -========================== - -Tuto schopnost využijete při tvorbě složitějších dokumentů. - -/--code texy - /---div .[header] - - content of div - - \--- -\-- - -/--texysource - /---div .[header] - - content of div - - \--- -\-- - - -Je možné bloky i vnořovat: - -/--code texy - /---div .[header] - - ## This is a header. - - /---div - vnořený div - \--- - - Texy je sexy! - - \--- -\-- - -/--texysource - /---div .[header] - - ## This is a header. - - /---div - vnořený div - \--- - - Texy je sexy! - - \--- -\-- - - -Citace -====== - -Citace jsou odsazené, podobně jako v emailech, znakem `>` - -/--code texy -> This is a blockquote with two paragraphs. -> -> 640 K should be enough for everyone -\-- - -/--texysource -> This is a blockquote with two paragraphs. -> -> 640 K should be enough for everyone -\-- - - -Odkazy -====== - -Odkazy se zapisují tak, že odkazující text uzavřete do uvozovek a následujete dvojtečkou a URL. Texy se snaží inteligentně odhadnout konec URL. Můžete mu i pomoci tím, že URI uzavřete do hranatých závorek. Část `http://` není povinná. - -Jako odkaz je možné vkládat i emaily, Texy je transformuje do podoby, která by měla zmást spamboty. - -/--code texy -Look at homepage:[https://texy.info]. - -Do you know "La Trine":https://www.latrine.cz? - -"Write me":me@example.com -\-- - -/--texysource -Look at homepage:[https://texy.info]. - -Do you know "La Trine":https://www.latrine.cz? - -"Write me":me@example.com -\-- - - -Reference ---------- - -Aby se tok textu "neznečišťoval" vkládáním URL, je možné všechny adresy uvést na jednom místě a pak se na ně jen odkazovat. Tomu se říká reference. Kromě adresy je možné doplnit i text odkazu a [modifikátor | #modifier]. - -/--code texy - [homepage]: https://texy.info/ Texy .(homepage) - [nette]: http://nette.org - -This is [homepage] - -Look at "this site":[nette] -\-- - - -Obrázky -======= - -Zapisují se mezi hranaté závorky s hvězdičkou: - -/--code texy -[* image.gif *] -\-- - -/--texysource line -[* image.gif *] -\-- - -V textových odstavcích je často třeba zvolit, má-li být obrázek zarovnán k levému nebo pravému kraji. Toho docílíte pomocí znaku `<` a `>` použitého před pravou závorkou: - -/--code texy -[* image.gif <] Left-aligned image - -[* image.gif >] Right-aligned image -\-- - -/--texysource -[* image.gif <] Left-aligned image - -[* image.gif >] Right-aligned image -\-- - -*Poznámka: V uvedeném příkladu Texy použil pro zarovnání přímý styl. Je možné systém nakonfigurovat tak, aby místo přiřadil obrázkům zvolenou třídu.* - -*Poznámka: pro všechny (relativní) URL obrázků je možné nastavit výchozí adresář. V uvedeným příkladech to byl `images/`, proto v Texy není adresář uveden, zatímco ve vygenerovaném HTML ano.* - -*Poznámka: pokud není implicitně určen alternativní text (jak na to viz níže), použije Texy výchozí. Zde je to prosté `image`* - - -Rozměry -------- - -U lokálních obrázků Texy zjistí rozměry automaticky. Pokud je chcete určit ručně, zapište je takto: - -/--code texy -[* image.gif 10x20 *] -\-- - -/--texysource line -[* image.gif 10x20 *] -\-- - - -Modifikátory ------------- - -O nich se více dozvíte v [jiné kapitole | #modifier], ale neuškodí si ukázat, jak se u obrázků zapisují. Zkusme si modifikátor pro určení alternativního textu a třídy: - -/--code texy -[* image.gif .(alt text)[foto] *] -\-- - -/--texysource line -[* image.gif .(alt text)[foto] *] -\-- - - -Reference ---------- - -Ze stejných důvodů, jako u odkazů, je i obrázky možné zapisovat pomocí referencí. Je třeba definovat URL (nebo více URL oddělených `|`) a případně i modifikátory. - -/--code texy -What a beautiful girl [* picture*] ! - -[* picture*]: image.gif .(my girl) -\-- - -/--texysource -What a beautiful girl [* picture*] ! - -[* picture*]: image.gif .(my girl) -\-- - - -Obrázek s popiskou ------------------- - -Za obrázkem uveďte tři hvězdičky a následuje popiska: - - -/--code texy -[* image.gif *] *** Toto je *popiska* pod obrázkem -\-- - -/--texysource -[* image.gif *] *** Toto je *popiska* pod obrázkem -\-- - - -Fráze -===== - -Asi nejpoužívanější syntax v Texy. Téměř ve všech případech se používá zdvojený znak. - -/--code texy -//kurzíva// - -*taky kurzíva* - -**tučné** - -superscript^2 vs. subscript_2 -\-- - -/--texysource -//kurzíva// - -*taky kurzíva* - -**tučné** - -superscript^2 vs. subscript_2 -\-- - -/--div .[output] -//kurzíva// - -*taky kurzíva* - -**tučné** - -***nejsilněji zdůrazněné*** - -superscript^2 vs. subscript_2 -\-- - -Speciálním případem fráze je tzv. kód. Od ostatních se liší tím, že jeho obsah nebude nadále formátován a zobrazí se doslovně: - -/--code texy -Odstraňte `<br />` a entitu `&ndash` -\-- - -/--texysource -Odstraňte `<br />` a entitu `&ndash` -\-- - -*Poznámka: jestli se použije element `<code>` nebo jiný (případně žádný) je možné rozhodnout pouhou konfigurací Texy* - - -S modifikátorem ---------------- - -Je možné jej vložit do každé fráze, vždy těsně před uzavírací znak: - -/--code texy -**silný a zelený .{color:green}** jako Hulk -\-- - -/--texysource -**silný a zelený .{color:green}** jako Hulk -\-- - -/--div .[output] -**silný a zelený .{color:green}** jako Hulk -\-- - - -Přímé HTML -========== - -Texy není náhrada za HTML. Nehledá ani alternativní způsoby zápisu HTML. Cílem je zjednodušit psaní obsahu. Pokud se Vám zdá jednodušší zapsat některou strukturu přímo v HTML, můžete tak učinit. HTML značky jsou plně podporované. - -/--code texy -This <strong class=info>is strong</strong> text. -<br> This is not. -\-- - -/--texysource -This <strong class=info>is strong</strong> text. -<br> This is not. -\-- - -*Poznámka: všimněte si, že Texy upraví zápis atributů a značek tak, aby byly validní (i pro XHTML výstup). Stejně tak dbá na **well-formed zápis**!* - -*Poznámka: Rozhodování, která značky a které atributy můžou být v textu použity, je plně uživatelsky ovladatelné. Demonstruje to jeden příklad z distribuce.* - - -Seznamy -======= - -Odrážkové seznamy zapisujeme pomocí `*` `+` nebo `-`. Musí být zapsán hned na začátku řádku a za ním musí následovat mezera. - -/--code texy -- Red -- Green -- Blue -\-- - -/--texysource -- Red -- Green -- Blue -\-- - -/--div .[output] -- Red -- Green -- Blue -\-- - - -Číslované seznamy ------------------ - -Texy zná těchto pět způsobů zápisu (první dva jsou ekvivalentní): - -/--code texy -1) Učit se -2) Učit se -3) Učit se - -a) Dlouhý -b) Široký -c) Krátkozraký - -A) DOS -B) Windows -C) Linux - -I) Yesterday -II) Today -III) Tomorrow -\-- - -/--texysource -1) Učit se -2) Učit se -3) Učit se - -a) Dlouhý -b) Široký -c) Krátkozraký - -A) DOS -B) Windows -C) Linux - -I) Yesterday -II) Today -III) Tomorrow -\-- - -/--div .[output] -1) Učit se -2) Učit se -3) Učit se - -a) Dlouhý -b) Široký -c) Krátkozraký - -A) DOS -B) Windows -C) Linux - -I) Yesterday -II) Today -III) Tomorrow -\-- - - -Vnořené seznamy ---------------- - -/--code texy -a) Bird - I) Bird - - Red - - Green - - Blue - II) McHale - III) Parish -b) McHale -c) Parish - 1) Bird - 2) McHale - 3) Parish -\-- - -/--texysource -a) Bird - I) Bird - - Red - - Green - - Blue - II) McHale - III) Parish -b) McHale -c) Parish - 1) Bird - 2) McHale - 3) Parish -\-- - - -Definiční seznam ----------------- - -/--code texy -Koncert Divokej Bill: - - termín: 9. 12. 2004 - - místo: Hala Vodová, Brno - - Cena: 260 Kč -\-- - -/--texysource -Koncert Divokej Bill: - - termín: 9. 12. 2004 - - místo: Hala Vodová, Brno - - Cena: 260 Kč -\-- - -/--div .[output] -Koncert Divokej Bill: - - termín: 9. 12. 2004 - - místo: Hala Vodová, Brno - - Cena: 260 Kč -\-- - - -S modifikátorem ---------------- - -Modifikátor, který ovlivňuje celý seznam, se uvádí na řádku před ním. Ostatní (klasicky) na konci řádku: - -/--code texy -.{color:red} -triangl: .{color:blue} - - trojúhelník .{color:green} - - neladěný bicí hudební nástroj - - tringulační věž -\-- - -/--div .[output] -.{color:red} -triangl: .{color:blue} - - trojúhelník .{color:green} - - neladěný bicí hudební nástroj - - tringulační věž -\-- - - -Modifikátory -============ - -Nejsilnější zbraň Texy Lze použít tyto druhy modifikátorů: - -- (titulek) popisné, přidají objektu titulek (nebo alternativní text obrázkům) -- `[class1 class2 #id]` určující třídu a / nebo ID prvku -- {class:blue} přímý zápis stylu -- {target:_blank} nebo přímý zápis HTML atributů -- horizontální zarovnání: - - doleva < - - doprava > - - vycentrovaný <> - - do bloku = - -- vertikální zarovnání: (jen u tabulek) - - nahoru ^ - - na střed - - - dolů _ - -Modifikátory se zapisují spojitě (bez mezer) a **musí jim předcházet tečka**. Takže třeba `.(popis)[left]` nastavuje atribut title na `popis` a třídu na `left`. - -**Modifikátory je vždy zapisují zcela doprava**. - -Příklad použití modifikátoru na odstavci textu: - -/--code texy -Vycentrováno modifikátorem .<> - -Obarveno modifikátorem .{color:blue; lang: cs} -\-- - -/--texysource -Vycentrováno modifikátorem .<> - -Obarveno modifikátorem .{color:blue; lang: cs} -\-- - - -Typografie -========== - -Sem patří všechny úpravy a náhrady textu, které upravují jeho vzhled v souladu s typografickými pravidly a podobně: - -/--code texy -- "české" 'typografické' uvozovky -- pomlčka vs. spojovník: 10-15 vs. česko-slovenský -- pomlčka: jedna -- dvě -- typografický křížek u rozměrů 10 x 20 -- šipky <- a -> a <-> ; -- tři tečky... -- zachování HTML entit & -- náhrady(TM) nebo(R) za příslušné entity(C) -\-- - -/--div .[output] -- "české" 'typografické' uvozovky -- pomlčka vs. spojovník: 10-15 vs. česko-slovenský -- pomlčka: jedna -- dvě -- typografický křížek u rozměrů 10 x 20 -- šipky <- a -> a <-> ; -- tři tečky... -- zachování HTML entit & -- náhrady(TM) nebo(R) za příslušné (C)entity -\-- - -práce s mezerami: - -/--code texy -- vkládání nezalomitelných mezer za jednopísmenné předložky (v autě u okna) -- nedělitelné mezery u telefonních čísel +420 776 552 046 -\-- - -/--code html -vkládání nezalomitelných mezer za jednopísmenné předložky (v autě u okna) - -nedělitelné mezery u telefonních čísel +420 776 552 046 -\-- - -*Poznámka: Nahrazování se obvykle řídí dalšími pravidly, které určují, kdy -symbol nahradit a kdy ne. Například šipka `->` nemůže být na konci řádku atd. Proto nebuďte překvapeni, když v některých případech Texy náhradu neprovede. Pokud to považujete za chybu, dejte mi vědět.* - - -Zkratky, akronymy ------------------ - -Používá se zápisu s dvojitou kulatou závorkou: - -/--code texy -jednoslovné: NATO((North Atlantic Treaty Organisation)) - -víceslovné: "et al."((a další)) -\-- - -/--texysource -jednoslovné: NATO((North Atlantic Treaty Organisation)) - -víceslovné: "et al."((a další)) -\-- - - -Klikatelné URI --------------- - -Automatický převod URI do klikatelné formy (včetně emailů) - -/--code texy -další informace na www.texy.info a také ... -\-- - -/--div .[output] -další informace na www.texy.info a také ... -\-- - - -Rozdělení velmi dlouhých slov -============================= - -Velmi zajímavá a důležitá funkce Texy. Dlouhá slova mohou narušit vzhled stránky, proto je vhodné prohlížeči naznačit, kde je může zalomit. Texy tyto místa hledá s přihlédnutím k národním zvyklostem, tedy slovo rozděluje podle slabik: - -/--code texy -nejneobhospodařovávatelnějšími -\-- - -/--code html -nejneobhospoda­řovávatelnější­mi</p -\-- - -*Poznámka: limit délky slova je volitelný* - -*Poznámka: současné prohlížeče na jádru Gecko (Mozilla, Firefox) jsou k naznačenému dělení slepí. Doufám, že vývojáři tento nedostatek brzy odstraní. Nebo zkuste [tohle | https://forum.texy.info/cs/viewtopic.php?id=36]* - - -Tabulky -======= - -Příklad jednoduché tabulky, sloupce se oddělují znakem `|` - -/--code texy -| first col | second col | third col -| Adam | Eva | Franta -\-- - -A výsledek je: - -| first col | second col | third col -| Adam | Eva | Franta - - -Hlavičku tabulky můžeme definovat tímto zápisem: - -/--code texy -|----------------------------- -| First Name | Last Name | Age -|---------------------------- -| Jesus | Christ | 33 -| Cecilie | Svobodova | 74 -\-- - -|----------------------------- -| First Name | Last Name | Age -|---------------------------- -| Jesus | Christ | 33 -| Cecilie | Svobodova | 74 - -Pokud hlavičku netvoří řádek (řádky), můžeme ji definovat na úrovni buněk. Stačí vložit hvězdičku ihned po znaku `|` - - -/--code texy -|* First Name | Jesus | Cecilie -|* Last Name | Christ | Svobodova -|* Age | 33 | 74 -\-- - - -|* First Name | Jesus | Cecilie -|* Last Name | Christ | Svobodova -|* Age | 33 | 74 - - -Sloučení sloupců ----------------- - -všimněte si zdvojeného || - -/--code texy -|----------------------------- -| Name || Age -|---------------------------- -| Jesus | Christ | 33 -\-- - -|----------------------------- -| Name || Age -|---------------------------- -| Jesus | Christ | 33 - - -Sloučení řádků --------------- - -Všimněte si znaku `^` symbolizujícího směr nahoru: - - -/--code texy -|----------------------------- -| First Name | Last Name | Age -|---------------------------- -| Bill || 50 -| ^| 52 -| Jim | Beam | 70 -\-- - -|----------------------------- -| First Name | Last Name | Age -|---------------------------- -| Bill || 50 -| ^| 52 -| Jim | Beam | 70 - - -Modifikátory ------------- - -Platí tato pravidla: -- modifikátor ovlivňující celou tabulku se vkládá bezprostředně před tabulku -- ovlivňující řádek se vkládá na konec řádku -- ovlivňující sloupec se vkládá na začátek buňky (vlevo v buňce) -- a nakonec ovlivňující buňku se vkládá na konec buňky (pravo v buňce) - -Podívejte se na příklad. - -/--code texy -.(people) -| .{color: green} first col | second col .>| third col | .{font-style:italic} -| Adam | Eva .{color: blue}| Franta | -\-- - -Zde je: -- `.(people)` modifikátor tabulky -- `.{color: green}` modifikátor sloupce -- `.{font-style:italic}` modifikátor řádku -- `.{color: blue}` a také `.>` modifikátor buňky - -Takže výsledná tabulka vypadá takto: - - -.(people) -| .{color: green} first col | second col .>| third col | .{font-style:italic} -| Adam | Eva .{color: blue}| Franta | diff --git a/texy/cs/syntax.texy b/texy/cs/syntax.texy index 9a430f8080..a75396973c 100644 --- a/texy/cs/syntax.texy +++ b/texy/cs/syntax.texy @@ -1,464 +1,891 @@ Syntaxe ******* ---> "Podrobný popis syntaxe":syntax-podrobne +.[perex] +Texy vznikl proto, aby nezkušeným uživatelům umožnil snadno editovat obsah webových stránek. Proto je i syntaxe intuitivní a přehledná. + + +Cheat Sheet +=========== + +| [#Formátování textu] | Syntax +|----------------------------------------------- +| [Tučný text |#Formátování textu] | .[text-code] ''**tučný text**'' +| [Kurzíva |#Formátování textu] | ''*kurzíva*'' nebo ''//kurzíva//'' +| [Inline code |#Formátování textu] | ''`kód`'' +| [#Odkazy] | ''"text":URL'' nebo ''[text](URL)'' +| [#Obrázky] | ''[* image.jpg *]'' +| [#Vypnutí formátování] | ''specialní znaky'' +|----------------------------------------------- +| Elementy +|----------------------------------------------- +| [#Podtržené nadpisy] | H1 <br> === +| [#Ohraničené nadpisy] | ''### H1'' <br> ## H2 +| [#Odrážkové seznamy] | ''- první'' <br> ''- druhá'' +| [#Číslované seznamy] | ''1) první'' <br> ''2) druhá'' +| [#Seznamy definic] | term: <br>   ''- první'' +| [#Citace] | ''> blockquote'' +| [#Horizontální čáry] | ''---'' +| [#Tabulky] | ''\| buňka \| buňka \|'' +| [Bloky kódu|#Předformátovaný text] | ''/--'' <br> ... <br> ''\--'' +|----------------------------------------------- +| Modifikátory .[#toc-modifikatory] +|-------------------------------------------------------- +| titulek | ''.(titulek)'' +| CSS třída | ''.[btn btn-primary]'' +| ID | ''.[#id]'' +| CSS styl nebo HTML atribut | ''.{color: blue}'' nebo ''.{target: _blank}'' +| horizontální zarovnání | ''.< .> .<> .='' +| vertikální zarovnání | ''.^ .- ._'' + + +Odstavce textu +============== + +Za odstavec považuje Texy jeden nebo více řádků textu, které následují těsně za sebou. Jakmile mezi nimi necháte **jeden prázdný řádek**, Texy automaticky pochopí, že má začít nový odstavec. + +To znamená, že Texy spojí řádky, které patří k sobě. Nemusíte se tak bát, že se vám věta zalomí uprostřed, když si zmenšíte okno editoru. + +```texy +Toto je první odstavec. Může mít klidně více řádků +a Texy je spojí do jednoho souvislého bloku textu. + +Až tady, po prázdném řádku, začíná úplně nový, druhý odstavec. +``` + +Spojování řádků lze nicméně vypnout v konfiguraci a pak se každý řádek považuje za samostatný odstavec: + +/--php +$texy->mergeLines = false; +\-- + + +Zalomení řádků +-------------- +Co když ale potřebujete text jen odřádkovat, aniž byste vytvářeli celý nový odstavec? To se typicky hodí u básní, textů písní nebo při psaní adresy. **Začněte nový řádek jednou mezerou**. -Nástroj Texy vznikl proto, aby nezkušeným uživatelům umožnil snadno editovat obsah webových stránek. Proto je i syntaxe maximálně intuitivní. Záměrem je, aby text v čisté (nezformátované) formě byl přehledný a jeho formát tušitelný. +```texy +Karel Novák, + U Tiché pošty 5 + 150 00 Praha 5 +``` -Dnes Texy výborně slouží i zkušeným znalcům jazyka HTML. Dovoluje volně kombinovat Texy zápis s HTML značkami. Zkušení uživatelé se tedy nemusí učit nový meta-jazyk a plně využít svých znalostí. Texy jim pouze zjednodušuje práci. -Prvotní logikou syntaxe je **žádnou syntaxi nepoužívat**. Jen psát čistý text. Vkládání rozšířených informací, jako třeba CSS třídy nebo odkazy, nenaruší tok textu. A zapíší se způsobem, který snadno pochopí i netechnicky založení uživatelé. +Stylování odstavců +------------------ +Někdy potřebujete celý odstavec nějak odlišit – například z něj udělat úvodní perex článku, vycentrovat ho nebo mu přiřadit specifický styl pro rámeček. K tomu slouží [#modifikátory], které můžete umístit buď na samostatný řádek **před** odstavec, nebo na konec jeho posledního řádku. -Odstavce textu .[#paragraph] -============================ +```texy +.[perex] +Toto je úvodní odstavec článku, který díky modifikátoru +dostane CSS třídu "perex" a může tak vypadat jinak než zbytek textu. -Za odstavec se považuje jeden nebo více bezprostředně za sebou následujících řádků textu. Odstavečky jsou od sebe oddělené prázdným řádkem. +Tento odstavec má zase přiřazené unikátní ID. .[#sekce-uvod] -/--code texy -První odstavec lorem ipsum dolor sit amet. +A tento odstavec bude vycentrován. .<> +``` -Druhý odstavec, který tvoří jeden řádek. -A druhý řádek textu. Texy je spojí. -\-- -Zalomení řádku v odstavci docílíte vložením jedné mezery vlevo: +Formátování textu +================= -/--code texy -Kdoví jestli - jestli jsou na měsíci vůbec nějaký stopy - a proč kope kolem sebe kdo se topí - jakej sval to Zemí otáčí +| syntax | výstup | ID syntaxe +|----------------------------------------------------------------------------- +| .[text-code] ''**tučný text**'' | **tučný text** | `phrase/strong` +| ''*kurzíva* nebo //kurzíva//'' | *kurzíva* | `phrase/em-alt`, `phrase/em` +| ''***tučná kurzíva***'' | ***tučná kurzíva*** | `phrase/strong+em` +| ''`inline kód`'' | `inline kód` | `phrase/code` +| ''x^2 … O_2'' | x^2 … O_2 | `phrase/sup-alt`, `phrase/sub-alt` +| ''x^^2^^ … O__2__'' | x^2 … O_2 | `phrase/sup`🔸, `phrase/sup`🔸 +| ''++vložený text++'' | <ins>vložený text</ins> | `phrase/ins`🔸 +| ''--smazaný text--'' | <del>smazaný text</del> | `phrase/del`🔸 +| ''>>citovaný text<<'' | >>citovaný text<< | `phrase/quote` +| ''"modrý text .{color: blue}"'' | "modrý text .{color: blue}" | `phrase/span` +| ''~modrý text .{color: blue}~'' | ~modrý text .{color: blue}~ | `phrase/span-alt` +| ''"et al."((a další))'' | "et al."((a další)) | `phrase/acronym` +| ''NBA((National Basketball Association))'' | NBA((National Basketball Association)) | `phrase/acronym-alt` + +Syntaxe označené 🔸 nejsou ve výchozím stavu povolené a musíte je zapnout. Příklad: + +/--php +$texy->allowed['phrase/ins'] = true; \-- +Pro jednoduché číselné indexy můžete použít zkrácenou syntaxi `x^2` a `O_2`, ale pro složitější případy je robustnější varianta s dvojitými znaky, nebo můžete použít HTML značky `<sup>` a `<sub>`. -Titulky .[#heading] -=================== +Uvnitř syntaktických znaků **nesmí být mezery**: -Titulky je možné zapsat hned dvěma způsoby: **podtržením** nebo **předsazením**. +```texy +Špatně: ** toto nebude tučné ** +Správně: **toto bude tučné** +``` -Každý titulek má svůj stupeň. V případě **podtržení** o důležitosti titulku rozhoduje podtrhávací znak. Od nejvyšší po nejnižší jsou to tyto: `#` `*` `=` `-` -/--code texy -Hlavní titulek -************** +Stylování textu +--------------- +Tohle je jedna z nejsilnějších vlastností Texy. Ke každému formátovanému textu můžete "přilepit" [#modifikátory] a přidat mu tak CSS třídu, ID nebo přímý styl. Modifikátor se vždy vkládá **těsně před uzavírací značku**: -Podtitulek -========== -\-- +```texy +Tento text je **silný a zelený .{color:green}** jako Hulk. -U titulků zapsaných **předsazením** určuje úroveň počet předsazených znaků. A ty mohou být `#` nebo `=` +Upozornění: --Tato funkce je zastaralá .[deprecated]-- +``` -Platí: čím více znaků, tím důležitější titulek (minimum jsou dva znaky, maximum sedm). +Pokud chcete aplikovat modifikátor na text, ale nechcete ho zároveň dělat tučným nebo kurzívou, použijte jako obalovací značku uvozovky `"` nebo vlnovky `~`. Texy z toho vytvoří univerzální HTML značku `<span>` s vašimi styly: -/--code texy -=== Hlavní titulek === +```texy +Běžný text, ale "tento kousek je červený .{color: red}", a zbytek už ne. +``` -## Podtitulek -\-- -Jak vidíte v případě podtitulku, znaky vpravo je možné vynechat. +Formátování a odkazy v jednom +----------------------------- +Z formátovaného textu můžete udělat odkaz - jednoduše přidejte dvojtečku a URL adresu: -Horizontální čáry .[#horizline] -=============================== +```texy +Navštivte naši **novou galerii**:https://example.com/gallery +``` -Texy zná tyto způsoby zápisu: +Toto funguje pro tučný text, kurzívu, inline kód. -/--code texy ------------- +Psaní speciálních znaků +----------------------- -******** -\-- +Co když chcete napsat doslova `**text**` včetně hvězdiček, aniž by se z něj stal tučný text? Máte tři možnosti: +- zpětné lomítko je nejrychlejší způsob, jak "zneplatnit" jeden speciální znak `\**text\**` +- dvojité apostrofy [vypnou Texy|#Vypnutí formátování] pro celou frázi `''**text**''` +- můžete použít standardní HTML entity `**text**` -Vypnutí Texy .[#disable-texy] -============================= -Klíčové slovo `html` nebo `text` ovlivňuje, jestli obsah bude chápán jako HTML (včetně značek), nebo prostý text. +Odkazy +====== -/--code texy - /---html - <em>příklad</em>: **this is not strong** - \--- +Odkazy jsou duší internetu. V Texy je jejich tvorba navržena tak, aby byla co nejpřirozenější a nejpřehlednější přímo v textu. +Základní syntaxe pro odkaz je jednoduchá a skvěle čitelná. Odkazovaný text uzavřete do `"` (nebo jiných znaků pro [#formátování textu]) a hned připojíte dvojtečku a cílovou URL adresu: - /---text - <em>příklad</em>: **this is not strong** - \--- -\-- +```texy +Navštivte oficiální stránky projektu "Nette Framework":https://nette.org. -Pro inline vypnutí Texy je možné použít dvojitý apostrof `''` a obalit s ním část textu, který nemá být Texy zpracováván. +Pokud máte dotaz, "napište nám":info@example.com. +``` -/--code texy - Příklad: ''**this is not strong**'' -\-- +Výhodou je, že Texy je inteligentní a samo pozná, kde URL končí. Nemusíte se tedy bát, že by do odkazu omylem zahrnulo tečku nebo čárku na konci věty. Pokud ale URL obsahuje nestandardní znaky, můžete je uzavřít do hranatých závorek a tím přesně řeknete, kde adresa začíná a končí: +```texy +"Přečtěte si náš článek":[https://example.com/novinky?id=1&kategorie=články] +``` -Citace .[#blockquote] -===================== +ID syntaxe `phrase/span`, `phrase/span-alt` | [PhraseModule |configuration#phrasemodule] a [LinkModule |configuration#linkmodule] -Citace jsou odsazené, podobně jako v emailech, znakem `>` -/--code texy -> This is a blockquote with two paragraphs. -> -> 640 K should be enough for everyone -\-- +Alternativní syntaxe odkazů +--------------------------- +Jste zvyklí na formát, který používá Markdown nebo Wikipedia? Texy rozumí i jim. Můžete si vybrat styl, který vám nejvíce vyhovuje. -Odkazy .[#link] -=============== +```texy +[Text odkazu](https://adresa.cz) // Styl známý z Markdownu +[Text odkazu | https://adresa.cz] // Styl známý z MediaWiki +text:[cílová URL nebo reference] // Jednoslovný odkaz +``` -Odkazy se zapisují tak, že odkazující text uzavřete do uvozovek a následujete dvojtečkou a URL. Texy se snaží inteligentně odhadnout konec URL. Můžete mu i pomoci tím, že URI uzavřete do hranatých závorek. Část `http://` není povinná. +ID syntaxe `phrase/markdown`, `phrase/wikilink`, `phrase/quicklink` | [PhraseModule |configuration#phrasemodule] -Jako odkaz je možné vkládat i emaily, Texy je transformuje do podoby, která by měla zmást spamboty. -/--code texy -Look at homepage:[https://texy.info]. +Udržujte si pořádek s referencemi +--------------------------------- -Do you know "La Trine":https://www.latrine.cz? +Při psaní delších textů může být nepohodlné vkládat dlouhé URL adresy přímo do odstavců – zhoršuje to čitelnost a přehlednost. Pro tyto případy má Texy **referenční odkazy**. -"Write me":me@example.com +V textu použijete pouze krátký, snadno zapamatovatelný název reference. A na konci dokumentu pak všechny tyto reference přehledně definujete. -\-- +```texy +Doporučujeme si prostudovat "oficiální dokumentaci":[doc] a projít si "příklady syntaxe":[syntax]. +Celý projekt je postaven na [Nette]. +​[doc]: https://texy.nette.org/cs/ "Dokumentace Texy!" +​[syntax]: https://texy.nette.org/cs/syntax +​[Nette]: https://nette.org +``` -Obrázky .[#image] -================= +ID syntaxe `link/reference`, `link/definition` | [LinkModule |configuration#linkmodule] -Zapisují se mezi hranaté závorky s hvězdičkou: -/--code texy -[* image.gif .(alternativní text) *] -\-- +Automatické odkazy +------------------ + +Kdykoli do textu napíšete URL adresu (začínající na `http://`, `https://`, `www.`) nebo e-mail, Texy ji automaticky rozpozná a převede na klikatelný odkaz. Nemusíte dělat vůbec nic. +```texy +Náš web najdete na adrese www.example.com. +Pro podporu pište na support@example.com. +``` -V textových odstavcích je často třeba zvolit, má-li být obrázek zarovnán k levému nebo pravému kraji. Toho docílíte pomocí znaku `<` a `>` použitého před pravou závorkou: +ID syntaxe `link/url`, `link/email` | [LinkModule |configuration#linkmodule] + + +Stylování odkazů +---------------- -/--code texy -[* image.gif <] Left-aligned image. Lorem ipsum ... +S [#modifikátory] můžete odkazům snadno přidávat další vlastnosti: -[* image.gif >] Right-aligned image. Curabitur quam ... +```texy +"Externí odkaz .[external](Otevře se v novém okně){target:_blank}":https://google.com +``` + +Speciální třída `nofollow` přidá odkazu atribut `rel="nofollow"`, čímž dáváte vyhledávačům signál, aby tento odkaz nesledovaly. To se hodí například u odkazů v komentářích. + +```texy +"Odkaz, kterému nedůvěřuji .[nofollow]":https://example.com +``` + + +Automatické maskování e-mailů +----------------------------- + +Texy automaticky obfuskuje (maskuje) emailové adresy před spamboty: + +```latte +<a href="mailto:info@example.com">info@<!-- -->example.com</a> +``` + +Toto chování můžete vypnout: + +/--php +$texy->obfuscateEmail = false; \-- -Obrázek s popiskou +Přímé HTML +========== + +Texy je navržen tak, abyste HTML nemuseli psát vůbec. Ale co když narazíte na situaci, kdy je přímé vložení HTML značky jednodušší, nebo potřebujete vytvořit něco, na co syntaxe Texy nestačí? Žádný problém. Texy vám dává naprostou svobodu kombinovat oba světy. + +Můžete plynule přecházet mezi Texy syntaxí a čistým HTML, kdykoli se vám to hodí. + +```texy +Toto je **tučný text** v Texy a toto je <strong>tučný text</strong> pomocí HTML. + +<div class="info-box"> + <h3>Můžete vkládat i celé komplexní bloky</h3> +</div> +``` + +Možná si říkáte, že vkládání přímého HTML může být riskantní. Co když uděláte chybu nebo někdo vloží škodlivý kód? Texy na to myslí a funguje jako inteligentní filtr a pomocník: + +- **Opravuje chyby:** Texy zajistí, aby byl výsledný kód vždy validní a nerozbil vám stránku. +- **Hlídá bezpečnost:** Texy má ve výchozím stavu seznam povolených značek a jejich atributů. Pokud se v kódu objeví neznámá značka nebo potenciálně nebezpečný atribut (např. `onclick`), Texy ho bezpečně odstraní. Chrání tak váš web před XSS útoky. +- **Zajišťuje konzistentní výstup:** Bez ohledu na to, jaký HTML kód vložíte, Texy se postará, aby byl výsledek vždy správně strukturovaný (well-formed). + +Tento ochranný štít si můžete přizpůsobit. Pomocí konfigurace `$texy->allowedTags` můžete přesně definovat, které HTML značky a atributy jsou na vašem webu povoleny a které ne. + +Máte tak plnou kontrolu nad tím, jaké HTML mohou například redaktoři používat, a zajišťujete tak konzistenci a bezpečnost celého webu. Více informací naleznete v sekci "konfigurace":configuration#allowedtags. + +ID syntaxe `html/tag`, `html/comment` | [HtmlModule |configuration#htmlmodule] + + +Nadpisy +======= + +Texy vám nabízí dva elegantní a intuitivní způsoby, jak nadpisy vytvářet: **podtržené** a **ohraničené**. + + +Podtržené nadpisy +----------------- + +Tento styl připomíná psací stroj. Jednoduše pod nadpis vložte podtržení (alespoň 3 znaky). O důležitosti titulku rozhoduje podtrhávací znak. Od nejvyšší po nejnižší jsou to tyto: `#` `*` `=` `-` + +```texy +Toto je nejdůležitější nadpis celého dokumentu +​################################################ + +A toto je nadpis druhé úrovně +​****************************** +``` + +ID syntaxe `heading/underlined` | [HeadingModule |configuration#headingmodule] + + +Ohraničené nadpisy ------------------ -Za obrázkem uveďte tři hvězdičky a následuje popiska: +Tento způsob je velmi rychlý na psaní. Text nadpisu "zabalíte" mezi znaky `#` nebo `=`. Zde o úrovni nadpisu rozhoduje **počet** použitých znaků (2 až 7). Čím více znaků, tím důležitější nadpis. +```texy +=== Nejdůležitější nadpis (H1) -/--code texy -[* image.gif *] *** Toto je *popiska* pod obrázkem -\-- +== Méně důležitý (H2) +# Ještě méně důležitý (H3) +``` -Fráze .[#phrase] -================ +Můžete použít ohraničení na obou stranách (pro lepší vizuální přehlednost) nebo jen na začátku. Texy si s oběma variantami poradí. -Asi nejpoužívanější syntax v Texy. Téměř ve všech případech se používá zdvojený znak. +ID syntaxe `heading/surrounded` | [HeadingModule |configuration#headingmodule] -/--code texy -//kurzíva// -**tučné** +Stylování nadpisů +----------------- -x^2 + y^3 -\-- +Ke každému nadpisu můžete přidat [#modifikátory]. To vám umožní přiřadit mu konkrétní CSS třídu pro stylování nebo unikátní ID, na které pak můžete odkazovat. +```texy +Nadpis s červenou barvou .[cerveny-nadpis] +​========================================== -/--div .[output] -//kurzíva// +### Nadpis s unikátním ID pro odkazování .[#kontakt] +``` -**tučné** -x^2 + y^3 -\-- +Automatické kotvy pro snadnou navigaci +-------------------------------------- +Nechcete vymýšlet ID pro každý nadpis ručně? Texy to umí udělat za vás! V konfiguraci můžete zapnout automatické generování ID pro všechny nadpisy. To je neuvěřitelně užitečné pro přímé odkazování na konkrétní sekce. -Texy lze i dočasně vypnout - obsah nebude formátován a zobrazí se doslovně: +```php +// Povolit automatické generování ID +$texy->headingModule->generateID = true; -/--code texy -Odstraňte ''<br />'' a entitu ''&ndash'' -\-- +// Volitelně nastavit předponu pro generovaná ID (např. "sekce-") +$texy->headingModule->idPrefix = 'toc-'; +``` +S tímto nastavením nadpis `## Moje kapitola` automaticky dostane například ID `id="toc-moje-kapitola"`, aniž byste museli cokoliv psát navíc. -Přímé HTML .[#html] -=================== -Texy není náhrada za HTML. Nehledá ani alternativní způsoby zápisu HTML. Cílem je zjednodušit psaní obsahu. Pokud se Vám zdá jednodušší zapsat některou strukturu přímo v HTML, můžete tak učinit. HTML značky jsou plně podporované. +Seznamy +======= -/--code texy -This <strong class=info>is strong</strong> text. -<br> This is not. -\-- +Odrážkové seznamy +----------------- -Seznamy .[#list] -================ +Pro rychlý výčet položek, u kterých nezáleží na pořadí, se skvěle hodí odrážkový seznam. Stačí každý řádek začít pomlčkou `-`, hvězdičkou `*` nebo pluskem `+` a mezerou. Všechny tři znaky fungují stejně, takže si můžete vybrat ten, který je vám nejsympatičtější. -Odrážkové seznamy zapisujeme pomocí `*` `+` nebo `-`. Musí být zapsán hned na začátku řádku a za ním musí následovat mezera. +```texy +Co je potřeba nakoupit: -/--code texy -- Red -- Green -- Blue -\-- +- Mléko +- Chleba +* Vejce ++ Máslo +``` + +ID syntaxe `list` | [ListModule |configuration#listmodule] Číslované seznamy ----------------- -Texy zná těchto pět způsobů zápisu (první dva jsou ekvivalentní): +Texy podporuje různé styly číslování: -/--code texy -1) Učit se -2) Učit se -3) Učit se +| `1.` | Arabské číslice (s tečkou) +| `1)` | Arabské číslice (se závorkou) +| `a)` | Malá písmena abecedy +| `A)` | Velká písmena abecedy +| `I)` | Římské číslice -a) Dlouhý -b) Široký -c) Krátkozraký +Kouzlo spočívá v tom, že se vůbec nemusíte starat o správné číslování. I když všechny řádky očíslujete jedničkou, Texy je automaticky přečísluje za vás. To je obrovská výhoda, když později potřebujete nějakou položku přidat, smazat nebo přesunout. -A) DOS -B) Windows -C) Linux -I) Yesterday -II) Today -III) Tomorrow -\-- +Vnořené a kombinované seznamy +----------------------------- + +Síla seznamů se naplno projeví, když je začnete kombinovat a vnořovat. Můžete tak vytvářet přehledné, víceúrovňové struktury. Vnoření vytvoříte jednoduše tak, že daný řádek odsadíte alespoň o **dvě mezery** (nebo jeden tabulátor). + +```texy +1) První kapitola + a) Podkapitola 1.1 + - První bod + - Druhý bod + b) Podkapitola 1.2 +2) Druhá kapitola + - Hlavní myšlenka + - Další poznámka +``` -Vnořené seznamy +Seznamy definic --------------- -/--code texy -a) Bird - I) Bird - - Red - - Green - - Blue - II) McHale - III) Parish -b) McHale -c) Parish - 1) Bird - 2) McHale - 3) Parish -\-- +Pro případy, kdy potřebujete vytvořit slovníček pojmů nebo přehledně vysvětlit několik termínů, je ideální definiční seznam. +Na první řádek napište termín, který chcete definovat, a zakončete ho dvojtečkou. Na další řádky pište jeho definici, přičemž každý řádek odsaďte a začněte pomlčkou `-` -Definiční seznam ----------------- +```texy +HTML: + - Značkovací jazyk pro tvorbu webových stránek. + - Zkratka pro HyperText Markup Language. -Koncert "Divokej Bill":www.divokybill.cz: - - termín: 9. 12. 2004 - - místo: Hala Vodová, Brno - - Cena: 260 Kč +CSS: + - Jazyk pro popis způsobu zobrazení (stylování) stránek. + - Zkratka pro Cascading Style Sheets. +``` -/--code texy -Koncert Divokej Bill: - - termín: 9. 12. 2004 - - místo: Hala Vodová, Brno - - Cena: 260 Kč -\-- +ID syntaxe `list/definition` | [ListModule |configuration#listmodule] -Modifikátory .[#modifier] -========================= +Stylování seznamů +----------------- -Nejsilnější zbraň Texy. Lze použít tyto druhy modifikátorů: +Stejně jako u ostatních prvků v Texy, i seznamům můžete snadno přidávat [#modifikátory] pro změnu vzhledu. -- (titulek) popisné, přidají objektu titulek (nebo alternativní text obrázkům) -- `[class1 class2 #id]` určující třídu a / nebo ID prvku -- {class:blue} přímý zápis stylu -- {target:_blank} nebo přímý zápis HTML atributů -- horizontální zarovnání: - - doleva < - - doprava > - - vycentrovaný <> - - do bloku = +**Celý seznam:** Modifikátor napište na řádek **před** začátkem seznamu. -- vertikální zarovnání: (jen u tabulek) - - nahoru ^ - - na střed - - - dolů _ +```texy +.[barevny-seznam] +- První položka +- Druhá položka +``` -Modifikátory se zapisují spojitě (bez mezer) a **musí jim předcházet tečka**. Takže třeba `.(popis)[left]` nastavuje atribut title na `popis` a třídu na `left`. +**Jednotlivá položka:** Modifikátor přidejte na **konec** řádku dané položky nebo definičního termínu. -**Modifikátory je vždy zapisují zcela doprava**. +```texy +- Běžná položka +- Tato položka je důležitá! .{font-weight: bold} +- Další běžná položka +``` -Příklad použití modifikátoru na odstavci textu: -/--code texy -Vycentrováno modifikátorem .<> +Obrázky +======= -Obarveno modifikátorem .{color:blue; lang: cs} -\-- +Základní syntaxe je velmi jednoduchá. Cestu k obrázku (ať už lokálnímu souboru, nebo URL adrese) stačí uzavřít do hranatých závorek s hvězdičkou: -/--code html -<p style="text-align:center">Vycentrováno modifikátorem</p> +```texy +[* obrazek.jpg *] +[* https://domena.cz/logo.png *] +``` -<p style="color:blue" lang="cs">Obarveno modifikátorem</p> -\-- +Často budete chtít, aby text obrázek obtékal. K tomu slouží jednoduché zarovnávací značky, které se vkládají před uzavírací závorku: +```texy +[* obrazek.jpg <] Tento text bude plynule obtékat obrázek z pravé strany. -Typografie .[#typography] -========================= +[* obrazek.jpg >] V tomto případě bude text naopak obtékat obrázek z levé strany. -Sem patří všechny úpravy a náhrady textu, které upravují jeho vzhled v souladu s typografickými pravidly a podobně: +[* velky-obrazek.jpg <>] +Tento text bude pokračovat až pod vycentrovaným obrázkem. +``` -/--code texy -- "české" 'typografické' uvozovky -- pomlčka vs. spojovník: 10-15 vs. česko-slovenský -- pomlčka: jedna -- dvě -- typografický křížek u rozměrů 10 x 20 -- šipky <- a -> a <-> ; -- tři tečky... -- zachování HTML entit & -- náhrady(TM) nebo(R) za příslušné entity(C) -\-- +Správně vložený obrázek by měl mít i tzv. "alternativní text", který se zobrazí, pokud se obrázek nenačte. Pomocí [modifikátoru|#modifikátory] můžete přidat tento text i další prvky pro stylování. + +```texy +[* fotka-krajiny.jpg .(Krásná horská krajina při západu slunce)[main-photo] *] +``` + + +Rozměry obrázků +--------------- + +Texy umí u lokálních obrázků automaticky zjistit jejich rozměry (pokud je nastavena cesta `$texy->imageModule->fileRoot`) a doplnit je do HTML, což zrychluje načítání stránky. Pokud ale chcete rozměry nastavit ručně, máte několik možností: + +| `[* img.jpg 150x100 *]` | Přesná šířka 150px a výška 100px +| `[* img.jpg 150 *]` | Šířka bude 150px, výška se automaticky dopočítá se zachováním poměru stran +| `[* img.jpg ?x100 *]` | Výška bude 100px, šířka se automaticky dopočítá + + +Klikatelné obrázky +------------------ + +Chcete, aby se po kliknutí na malý náhled zobrazil velký obrázek? Nebo aby obrázek odkazoval na jinou stránku? Stačí za syntaxi obrázku přidat dvojtečku a cílovou URL. + +```texy +[* nahled.jpg *]:velky.jpg +[* logo-nette.png *]:https://nette.org +``` + +Pro galerie existuje i šikovná zkratka `::`. Ta automaticky vytvoří odkaz na stejný soubor umístěný na `$texy->imageModule->linkedRoot`. + + +Viditelný popisek pod obrázkem +------------------------------ + +Pokud chcete pod obrázek přidat viditelný popisek (např. jméno autora nebo popis scény), napište za něj tři hvězdičky `***` a text popisku. Texy z toho automaticky vytvoří sémanticky správnou HTML strukturu `<figure>` a `<figcaption>`. + +```texy +[* fotka.jpg <> *] *** Toto je popisek. Může obsahovat i **další formátování**. +``` + + +Udržujte si pořádek s referencemi +--------------------------------- + +Pokud v textu používáte jeden obrázek vícekrát nebo chcete mít všechny definice obrázků přehledně na jednom místě, můžete použít reference. V textu použijete jen zástupný název a na konci souboru pak definujete, co tento název znamená. + +```texy +V našem logu [* firemni-logo *] je vidět symbol naší vize. + +​[* firemni-logo *]: /images/logo.svg 200x50 .(Logo naší společnosti) +``` + +Tento přístup výrazně zpřehledňuje hlavní text a usnadňuje správu obrázků. + +ID syntaxe `image/definition` | [ImageModule |configuration#imagemodule] -/--div .[output] -- "české" 'typografické' uvozovky -- pomlčka vs. spojovník: 10-15 vs. česko-slovenský -- pomlčka: jedna -- dvě -- typografický křížek u rozměrů 10 x 20 -- šipky <- a -> a <-> ; -- tři tečky... -- zachování HTML entit & -- náhrady(TM) nebo(R) za příslušné (C)entity + +Předformátovaný text +==================== + +V Texy můžete snadno vložit bloky kódu nebo jakýkoli předformátovaný text, u kterého chcete zajistit, aby se zobrazil přesně tak, jak ho napíšete – včetně všech mezer a konců řádků. To je ideální pro ukázky zdrojových kódů, logů nebo ASCII artu. + +Pro vložení takového bloku použijte ohraničení `/--` a `\--`: + +```texy +/-- +function hello() { + echo 'Hello World'; +} \-- +``` -práce s mezerami: +Aby byl váš kód ještě čitelnější, můžete Texy sdělit, v jakém programovacím jazyce je napsaný a vytvořit si handler, který například obarví syntaxi, viz "ukázka":custom-handlers#syntax-highlighting. Stačí za úvodní značku `/--` přidat klíčové slovo `code` a název jazyka: -/--code texy -- vkládání nezalomitelných mezer za jednopísmenné předložky (v autě u okna) -- nedělitelné mezery u telefonních čísel +420 776 552 046 +```texy +/--code javascript +console.log('JavaScript'); \-- /--code html -vkládání nezalomitelných mezer za jednopísmenné předložky (v autě u okna) - -nedělitelné mezery u telefonních čísel +420 776 552 046 +<div>Tohle je HTML kód</div> \-- +``` -*Poznámka: Nahrazování se obvykle řídí dalšími pravidly, které určují, kdy -symbol nahradit a kdy ne. Například šipka `->` nemůže být na konci řádku atd. Proto nebuďte překvapeni, když v některých případech Texy náhradu neprovede.* +Obsahové bloky (divy) +===================== -Zkratky, akronymy .[#acronym] ------------------------------ +Texy umožňuje vytvářet obecné `<div>` bloky, díky kterým můžete snadno seskupovat obsah do logických celků a následně je stylovat:. -Používá se zápisu s dvojitou kulatou závorkou: +Blok vytvoříte pomocí značek `/--div` a `\--`. Navíc můžete snadno přidat [#modifikátory]: -/--code texy -jednoslovné: NATO((North Atlantic Treaty Organisation)) +```texy +/--div .[important] +## Důležité upozornění -víceslovné: "et al."((a další)) +Tento text bude uzavřen v bloku `<div class="important">`. +Díky tomu ho můžete pomocí CSS nastylovat, aby byl výraznější. \-- +``` +Síla `<div>` bloků spočívá také v možnosti je vnořovat do sebe. Tím můžete vytvářet i složitější struktury přímo v Texy, aniž byste museli psát HTML ručně. -Klikatelné webové adresy ------------------------- +```texy +/--div .[outer] + Toto je vnější blok. -Automatický převod webových adres a emailů do klikatelné formy + /--div .[inner] + A toto je vnořený, vnitřní blok. + \-- -/--code texy -další informace na www.texy.info a také ... + Zde jsme opět ve vnějším bloku. \-- +``` +Díky této jednoduché syntaxi můžete udržovat svůj obsah přehledný a sémanticky správně strukturovaný. -/--div .[output] -další informace na www.texy.info a také ... -\-- +Vypnutí formátování +=================== -Rozdělení velmi dlouhých slov .[#longwords] -=========================================== +Někdy se může hodit Texy na chvíli "vypnout" a vložit kus textu, kde nemá Texy zpracovávat své značky. -Velmi zajímavá a důležitá funkce Texy. Dlouhá slova mohou narušit vzhled stránky, proto je vhodné prohlížeči naznačit, kde je může zalomit. Texy tyto místa hledá s přihlédnutím k národním zvyklostem, tedy slovo rozděluje podle slabik: +Pokud potřebujete vložit komplexnější HTML strukturu bez parsování Texy značek, použijte blok `/--html`: -/--code texy -nejneobhospodařovávatelnějšími -\-- +```texy +/--html +<em>Tento text bude zpracován jako HTML, takže bude kurzívou.</em> -/--code html -nejneobhospoda­řovávatelnější­mi</p +**Ale tyto hvězdičky Texy ignoruje, takže tučné nebudou.** \-- +``` -*Poznámka: limit délky slova je volitelný* +V případě, že chcete zobrazit text přesně tak, jak je napsán, a ignorovat veškeré značky (jak Texy, tak HTML), použijte blok `/--text`. Vše uvnitř tohoto bloku se zobrazí jako obyčejný text. +```texy +/--text +<em>Tento text se zobrazí i se značkami, kurzívou ale nebude.</em> -Tabulky .[#table] -================= +**Ani toto nebude tučné.** +\-- +``` -Příklad jednoduché tabulky, sloupce se oddělují znakem `|` +Co když ale nechcete vypínat Texy pro celý blok textu, ale jen pro krátkou frázi uprostřed věty? Pro tyto případy existuje elegantní a rychlé řešení: obalte daný text do **dvojitých apostrofů** `''`: -/--code texy -| first col | second col | third col -| Adam | Eva | Franta -\-- +```texy +Pokud chcete ukázat, jak se píše tučný text, napíšete: Syntaxe je ''**tučný text**''. +``` -A výsledek je: +Výsledkem nebude tučný text, ale doslova se vypíše řetězec `**tučný text**`. -| first col | second col | third col -| Adam | Eva | Franta +Tabulky +======= -Hlavičku tabulky můžeme definovat tímto zápisem: +Pro vytvoření tabulky začněte každý řádek znakem `|` a jednotlivé buňky oddělujte také tímto znakem. Texy si už samo pohlídá zarovnání a správné HTML. -/--code texy -|----------------------------- -| First Name | Last Name | Age -|---------------------------- -| Jesus | Christ | 33 -| Cecilie | Svobodova | 74 -\-- +```texy +| Jan | Novák | Praha +| Eva | Svobodová | Brno +``` -|----------------------------- -| First Name | Last Name | Age -|---------------------------- -| Jesus | Christ | 33 -| Cecilie | Svobodova | 74 +Výsledek bude přehledná a správně naformátovaná tabulka. + +ID syntaxe `table` | [TableModule |configuration#tablemodule] -Sloučení sloupců +Hlavička tabulky ---------------- -všimněte si zdvojeného || +Každá správná tabulka by měla mít hlavičku, která popisuje, co se v jednotlivých sloupcích nachází. Hlavičku vytvoříte tak, že ji od zbytku tabulky oddělíte řádkem obsahujícím pomlčky `-`. -/--code texy -| Name || Age -|---------------------------- -| Jesus | Christ | 33 -\-- +```texy +| Jméno | Věk | Město +|----------|-----|------- +| Jan | 25 | Praha +| Eva | 30 | Brno +``` -| Name || Age -|---------------------------- -| Jesus | Christ | 33 +Alternativně můžete definovat záhlaví pro jednotlivé řádky (například pokud máte v prvním sloupci popisky). Toho dosáhnete přidáním hvězdičky `*` hned za úvodní `|`. +```texy +|* Jméno | Jan | Eva +|* Věk | 25 | 30 +|* Město | Praha | Brno +``` -Sloučení řádků + +Sloučení buněk -------------- -Všimněte si znaku `^` symbolizujícího směr nahoru: +Někdy je potřeba spojit několik buněk dohromady, ať už ve sloupcích nebo v řádcích. +**Sloučení sloupců:** Pro horizontální spojení buněk jednoduše vynechejte oddělovač a místo něj použijte zdvojenou svislou čáru `||`. Buňka napravo se tím sloučí s buňkou nalevo od ní. -/--code texy -| First Name | Last Name | Age +```texy +| Jméno || Věk |---------------------------- -| Bill || 50 -| ^| 52 -| Jim | Beam | 70 -\-- +| Jan | Novák | 25 +``` + +**Sloučení řádků:** Pro vertikální spojení buněk použijte v buňce, kterou chcete připojit k té nad ní, symbol stříšky `^`. Ta Texy říká: "Tuto buňku spoj s tou nad ní." + +```texy +| Měsíc | Prodeje | +|---------|---------- +| Leden | 150 ks | +| Únor | ^| +| Březen | 210 ks | +``` + +V tomto příkladu bude buňka s prodeji pro leden a únor spojená. + +Takto lze sloučit několik buňek napříč řádky a sloupci: +```texy | First Name | Last Name | Age |---------------------------- | Bill || 50 | ^| 52 | Jim | Beam | 70 +``` + + +Stylování tabulek +----------------- + +Stejně jako u jiných prvků v Texy můžete i tabulkám a jejich částem přidávat [#modifikátory] pro změnu vzhledu (např. CSS třídy, styly nebo ID). + +**Celá tabulka:** Modifikátor pro celou tabulku umístěte na samostatný řádek těsně před ni. + +```texy +.[data-table table-striped] +| Hlavička 1 | Hlavička 2 +|------------|------------ +| data | data +``` + +**Jednotlivé řádky:** Chcete-li nastylovat konkrétní řádek, přidejte modifikátor na jeho konec. + +```texy +| Jméno | Stav +|-------|-------------- +| Petr | Schváleno +| Jana | Zamítnuto | .{background: #ffdddd} +``` + +**Jednotlivé sloupce:** Pro nastylování celého sloupce vložte modifikátor na začátek první buňky daného sloupce. + +```texy +| Jméno | .> Cena | Skladem +|----------------|-----------|--------- +| Produkt A | 1 200 Kč | Ano +| Produkt B | 850 Kč | Ne +``` + +**Konkrétní buňka:** Modifikátor pro jednu buňku napište přímo do ní, obvykle na konec jejího obsahu. + +```texy +| Úkol | Status +|----------------------|------------------------------------- +| Připravit podklady | Hotovo +| Zkontrolovat data | Probíhá .{color: orange; font-weight: bold} +``` + + +Citace +====== + +Potřebujete-li ve svém textu zdůraznit myšlenku někoho jiného, ocitovat zdroj nebo jen vizuálně oddělit blok textu, stačí začít řádek znakem `>`. + +```texy +> Toto je citace. Slouží ke zvýraznění důležité myšlenky nebo úryvku z jiného zdroje. +``` + +Citace nemusí být jen jeden odstavec. Pokud chcete pokračovat dalším odstavcem v rámci stejné citace, jednoduše vložte prázdný řádek, který také začíná znakem `>`. + +```texy +> Toto je první odstavec citace. Lorem ipsum dolor sit amet. +> +> A toto je druhý odstavec, který stále patří do stejné citace. +> Tímto způsobem můžete strukturovat i delší texty. +``` + +Texy dokonce podporuje vnořené citace, což se hodí, pokud citujete někoho, kdo sám někoho cituje. Pro každou další úroveň vnoření přidejte další znak `>`. + +```texy +> Toto je vnější, hlavní citace. +> +> > A toto je už vnořená citace druhé úrovně. +> +> Zde se text vrací zpět do hlavní citace. +``` + +Uvnitř citací můžete samozřejmě používat i další formátování, jako je **tučný text** nebo *kurzíva*. + + +Horizontální čáry +================= + +Někdy je potřeba text vizuálně rozdělit. K tomu skvěle slouží horizontální čára. Na samostatný řádek napište tři nebo více pomlček `---` nebo hvězdiček `***`. + +```texy +První část textu o nějakém tématu. + +*** + +Druhá část textu, která začíná po vizuálním oddělení. +``` + +Abyste vytvořili horizontální čáru, **musí jí předcházet prázdný řádek**. Pokud byste ji napsali hned pod text, Texy by si myslelo, že chcete vytvořit podtržený nadpis. + +ID syntaxe `horizline` | [HorizLineModule |configuration#horizlinemodule] + + +Typografie +========== + +Síla Texy nespočívá jen ve formátování, ale také v automatických typografických korekcích. Texy se postará o detaily, které dělají text profesionálním a dobře čitelným, a to vše podle českých typografických pravidel. Vy se tak můžete soustředit jen na obsah. + +**Uvozovky:** Nemusíte řešit, jak na klávesnici napsat správné typografické uvozovky. Texy to udělá za vás. + +Klasické ''"strojopisné uvozovky"'' automaticky převede na správné české „uvozovky“ a vnořené ‚uvozovky‘. Typ uvozovek závisí na nastavení locale: + +```php +$texy->typographyModule->locale = 'cs'; // české +$texy->typographyModule->locale = 'en'; // anglické +``` + +**Pomlčky a spojovníky:** Inteligentně rozpozná, kdy použít krátký spojovník (v dělených slovech), a kdy delší pomlčku – například v rozsazích (10–15) nebo mezi slovy. + +```texy +10-15 → 10–15 (en dash pro rozsahy) +česko-slovenský → česko-slovenský (spojovník zůstává) +slovo -- slovo → slovo – slovo (en dash mezi slovy) +slovo --- slovo → slovo — slovo (em dash) +``` + +**Nezlomitelné mezery**: Jednou z největších výhod je automatické vkládání pevných (nezlomitelných) mezer tam, kde je to potřeba. Tím zabraňuje, aby na konci řádku zůstala osamocená jednopísmenná slova (jako `k`, `s`, `v`, `z`), což je častý typografický prohřešek. + +```texy +// Vy napíšete: +Navštívil jsem hrad v Praze. + +// Texy zajistí, aby "v" nikdy nezůstalo na konci řádku: +Navštívil jsem hrad v Praze. +``` + +Stejně tak se postará o správné mezery v telefonních číslech nebo datech, aby se nezalamovala. + +```texy ++420 776 552 046 → +420 776 552 046 (všechny mezery pevné) +``` + +**Automatické symboly:** Texy vám usnadní i psaní často používaných symbolů. + +| Napíšete | Texy vygeneruje | Popis +|----- +| `...` | … | Výpustka +| `(c)` | © | Copyright +| `(r)` | ® | Registrovaná známka +| `(tm)` | ™ | Trademark +| `10 x 5` | 10 × 5 | Znak násobení +| `+-` | ± | Plus-mínus +| `<-` `->` `<->` | ← → ↔ | Šipky + +Díky těmto automatickým úpravám bude váš text vždy vypadat profesionálně, aniž byste museli znát složité klávesové zkratky nebo HTML entity. + + +Dělení dlouhých slov +-------------------- + +Znáte to – v textu se objeví dlouhé slovo, jako například "nejneobhospodařovávatelnějšími", a na úzké obrazovce mobilního telefonu rozbije celý layout stránky. Texy naštěstí nabízí elegantní řešení: dokáže do slova vložit neviditelné "měkké rozdělovníky" (`­`). Tyto rozdělovníky prohlížeči napoví, na kterých místech (mezi slabikami) může slovo bezpečně zalomit, pokud se na konec řádku nevejde. Pokud se slovo na řádek vejde celé, rozdělovníky zůstanou skryté a nic se nestane. + +```latte +nejneobhospoda­řovávatelnějšími +``` + +Díky tomu se váš text vždy krásně přizpůsobí jakékoliv šířce obrazovky bez nechtěného horizontálního posouvání. + +Protože se tato funkce nehodí pro všechny typy webů, je ve výchozím stavu vypnutá. Aktivovat ji můžete v konfiguraci: + +```php +$texy->allowed['longwords'] = true; + +// Nastavit minimální délku slova, od které se má dělit (např. 20 znaků) +$texy->longWordsModule->wordLimit = 20; +``` + +ID syntaxe `longwords` | [LongWordsModule |configuration#long-wordsmodule] + + +Emotikony +========= + +Texy umí automaticky převádět klasické textové smajlíky na grafické emotikony. Jednoduše napište smajlíka tak, jak jste zvyklí, a Texy se postará o zbytek. + +| Napíšete | Texy vygeneruje +|----- +| `:-)` | 🙂 +| `:-(` | ☹ +| `;-)` | 😉 +| `:-D` | 😀 +| `:-*` | 😘 + +Podle konfigurace může Texy tyto zkratky převádět buď na moderní Unicode emoji (jako v tabulce výše), nebo na malé obrázky (`<img>`). + +Aby se předešlo nechtěným převodům například v technických textech, je tato funkce ve výchozím nastavení vypnutá. Pokud ji chcete používat, stačí ji jednoduše povolit: + +```php +$texy->allowed['emoticon'] = true; +``` + +Více informací o dostupných emotikonech a možnostech nastavení naleznete v [konfiguraci EmoticonModule |configuration#emoticonmodul]. + +ID syntaxe `emoticon` | [EmoticonModule |configuration#emoticonmodule] diff --git a/texy/cs/texy-vs-wysiwyg.texy b/texy/cs/texy-vs-wysiwyg.texy deleted file mode 100644 index c79d99679e..0000000000 --- a/texy/cs/texy-vs-wysiwyg.texy +++ /dev/null @@ -1,23 +0,0 @@ -Texy versus WYSIWYG editory -*************************** - - -WYSIWYG((What You See is What You Get)) editor zobrazuje dokument během editace takové podobě, v jaké bude vytištěn, zobrazen na webu atd. Příkladem takového editoru je Word. - -Tento druh editorů zažil v oblasti správy internetového obsahu skutečný boom. Kdo by také odolal jejich vizuálně atraktivnímu prostředí a myšoidnímu ovládání. Díky programátorům "šikovných komponent .[about](htmlArea, FCKeditor nebo tinyRTE)" se jejich implementace stala hračkou a dnes je nabízí každý CMS((Content Management Systém = Systém na správu obsahu)). V praxi se však ukazuje, jak jsou jejich **přednosti jen zdánlivé**. - - -WYSIWYG se pro web nehodí -------------------------- - -Web má totiž docela **jiná specifika** než tištěný dokument. Zatímco u tiskovin je prioritou vizuálním uspořádání (ze kterého si lidský mozek odvodí strukturu, tj. co je nadpis, co je text a co je popiska obrázku), u webu je základem struktura. - -S vizuálním editorem se vlastně neustále svádí boj. Nejprve bojuje tvůrce administračního rozhraní, který se jej snaží přinutit **generovat použitelný kód**. Poté s ním bojuje samotný uživatel, který se snaží s využitím plné škály dostupných barev a fontů vytvoří hrozivou stránku. Následuje snaha ořezat možnosti editoru, kterou střídá další touha uživatele využít jeho plný potenciál. - -Současné WYSIWYG editory se pro web zkrátka nehodí. Prohlašuji to s vědomím autora několika administračních rozhraní, které jej využívají. Potřeboval jsem přijít s vhodnějším nástrojem a tak vzniklo Texy - - -WYSIWYM -------- - -WYSIWYM znamená What You See Is What You Mean. diff --git a/texy/en/@home.texy b/texy/en/@home.texy index 73a74963b1..27b8c786c9 100644 --- a/texy/en/@home.texy +++ b/texy/en/@home.texy @@ -1,31 +1,120 @@ -What Is Texy ------------- +Texy! is sexy! +************** -Texy allows you to enter content using an **easy to read** [Texy syntax | syntax] which is filtered into *structurally valid* HTML. No knowledge of HTML is required. Texy is one of the most complex formatting tools. It allows adding of images, links, nested lists, tables and has full support for CSS. +.[perex] +Texy is a **powerful and secure markup processor** for PHP that converts simple text into valid HTML. Unlike other markup languages, Texy isn't just another Markdown variant – it's a **fully configurable system** that you can adapt to virtually any syntax. -Texy supports hyphenation of long words (which reflects language rules), clickable emails and URL (emails are obfuscated against spambots), national typographic single and double quotation marks, ellipses, em dashes, dimension sign, nonbreakable spaces (e.g. in phone numbers), acronyms, arrows and many others. -Texy is being developed by David Grudl since 2004. It is written in PHP. +Why Texy? +========= -Texy is licenced by BSD and GNU General Public License. Plugins for several content-management systems are available. +Security as a Priority +---------------------- -Features --------- +Texy is designed with security in mind. It automatically **protects against XSS attacks**, validates URLs, and filters dangerous HTML tags. The built-in `safeMode()` is ideal for processing user-generated content in comments or forums. -- simple, intuitive and human friendy markup -- generate clean and valid HTML code -- may be used together with syntax highlighter -- designed with proper typography in mind -- supports hyphenation +```php +Texy\Configurator::safeMode($texy); +// Texy is now safe for user-generated content +``` -Why Texy --------- +Full Configurability +-------------------- -- bulletproof - ensures the well-formedness of the resulting code -- predectable behaviour -- flexible configuration +Want to use Markdown syntax? Or need completely custom markup? **Texy can handle it.** You can: + +- Disable or enable any parts of the syntax +- Change default behavior using handlers +- Add entirely custom syntax elements +- Configure Texy to process Markdown or any other format + +```php +$texy = new Texy; +$texy->allowed['image'] = false; // disable images +$texy->allowed['phrase/strong'] = false; // disable bold text +``` + + +Advanced Typography +------------------- + +Texy provides **sophisticated typographic processing** that can be tailored to different languages. Depending on the configured locale, it automatically: + +- Inserts **non-breaking spaces** after single-letter prepositions and conjunctions +- Applies **word hyphenation** according to syllable rules +- Uses proper **typographic quotation marks** based on language conventions +- Applies proper **dash and hyphen distinction**: 10–15 (dash) vs. multi-word (hyphen) +- Adds **non-breaking spaces** in phone numbers: +420 776 552 046 + + +Valid and Well-Formed HTML +-------------------------- + +Texy always generates **valid HTML5 code**. It automatically corrects improperly nested tags, closes unclosed elements, and ensures proper document structure. The output is not only valid but also **beautifully formatted** with proper indentation. + + +What is Texy? +============= + +Texy is a **general-purpose markup text processor**. While it has its default syntax (similar to Markdown but much richer), you can completely change or extend it. + +**It's not just a parser** – Texy is a comprehensive system with modular architecture, where each module processes a specific part of the syntax (headings, links, images, tables...). Thanks to the handler system, you can intervene at any point in the processing and modify the result according to your needs. + + +Texy vs. Markdown +================= + +The basic syntax is similar, but Texy offers much more: + +|--------------------------- +| Feature | Markdown | Texy +|--------------------------- +| Bold text | `**text**` | `**text**` +| Italic | `*text*` or `_text_` | `*text*` or `//text//` +| Headings | `# Heading` | `# Heading` or underline +| Images | `![alt](url)` | `[* url *]` +| Tables | limited | full support including merging +| Modifiers | no | yes – `.{color:red}[class]` +| Typography | no | yes – quotes, dashes, spaces +| Word hyphenation | no | yes – by syllables +| Configurability | limited | complete – custom syntax +| Security | depends on impl. | built-in (safeMode) + +**Example of differences:** + +```texy +Markdown: +![Image](image.jpg) + +Texy: +[* image.jpg 300x200 .(Image caption)[photo] <] +``` + +Texy allows you to define dimensions, classes, alignment, and much more directly in the syntax. + + +When to Use Texy? +================= + +Texy is ideal for: + +**CMS systems** Need to safely process content from editors? Texy offers granular control over what users can use. + +**Blogs and documentation** Rich syntax for tables, images with captions, typography, and code with syntax highlighting. + +**Comments and discussion forums** SafeMode ensures users cannot insert dangerous code while still having text formatting available. + +**Projects with custom requirements** Need to embed YouTube videos? Special syntax for your macros? Custom markup language? With Texy, you can create it easily. + + +History +======= + +Texy was created by David Grudl **20 years ago** in 2004 as one of the first markup processors for PHP. Originally developed for **PHP 4**, it has undergone many updates throughout its long history and today fully leverages all the capabilities of **PHP 8**. + +Over two decades of active development mean a **proven and stable** library trusted by hundreds of projects. Texy is now a **mature solution** with extensive history, yet still actively maintained and modern. {{maintitle: Texy – human friendy markup for PHP}} diff --git a/texy/en/@menu.texy b/texy/en/@menu.texy index 080eb567c1..66743bb1f1 100644 --- a/texy/en/@menu.texy +++ b/texy/en/@menu.texy @@ -1,6 +1,6 @@ - [home | @home] -- [syntax briefly | syntax] -- [syntax in detail | syntax-full] -- [fiddle | https://fiddle.nette.org/texy/] -- [API | https://api.nette.org/texy/] -- [GitHub | https://github.com/dg/texy] +- [syntax | syntax] +- [for developers | develop] +- "Playground .[link-external]":https://fiddle.nette.org/texy/ +- "API .[link-external]":https://api.nette.org/texy/ +- "GitHub .[link-external]":https://github.com/dg/texy diff --git a/texy/en/@try.texy b/texy/en/@try.texy deleted file mode 100644 index 77c2fe7dac..0000000000 --- a/texy/en/@try.texy +++ /dev/null @@ -1,15 +0,0 @@ -Welcome! --------- - -You can use Texy if you like: -- **bold** font or *italic* -- and this is how to "link":https://texy.info -- see "syntax":[syntax] for more information - - -But you can also stay with HTML: -- like this <b>HTML</b> -- Or even <b class=xx>totally <i>stupid</b>, Texy will solve it - - -[syntax]: /en/syntax diff --git a/texy/en/architecture.texy b/texy/en/architecture.texy new file mode 100644 index 0000000000..5e8bf97c11 --- /dev/null +++ b/texy/en/architecture.texy @@ -0,0 +1,425 @@ +Architecture and Principles +########################### + +.[perex] +Texy is a tool for converting text written in its own markup language into HTML. Unlike simple converters that process text linearly through a series of replacements, Texy uses a sophisticated system based on parsing, a modular architecture, and the gradual construction of a DOM tree. + +The basic processing flow consists of four main phases: + +1. Text preprocessing - normalization, adjustment of spaces and tabs, calling notification handlers for preparation +2. Parsing - recognizing syntaxes using regular expressions and gradually building the DOM tree +3. Post-processing - typographic adjustments, handling long words, well-forming HTML +4. Final assembly - converting the DOM tree into an HTML string + +The key difference from naive approaches is the separation of the syntax recognition phase from the processing phase. The parser first identifies where each syntactic construct is located in the text, and only then passes the found parts to individual modules for processing. This allows for nesting syntaxes and their gradual expansion. + +*Note: all classes are in the `Texy` namespace, so if the document mentions a class like `HtmlElement`, its full name is `Texy\HtmlElement`. Modules are in the `Texy\Modules` namespace* + + +Key Components +============== + +The Texy architecture consists of several main components, each with a clearly defined responsibility: + +The Texy class acts as the central orchestrator of the entire system. It contains references to all modules, manages registered syntaxes and handlers, maintains the processing state, and coordinates the individual conversion phases. It is the only place where the individual components are interconnected. + +**[Modules|#Moduly]** represent functional units responsible for specific areas of the markup language. Each module, upon its construction, registers the syntaxes it recognizes and the element handlers that process them. For example, PhraseModule handles inline formatting like bold or italic text, while TableModule processes tables. Modules are designed as separate, reusable units with their own configuration accessible through public properties. + +**[Parsers|#Parsery]** exist in two variants depending on the type of content being processed. BlockParser processes block structures like paragraphs, headings, lists, or tables. It goes through the text line by line, looking for the beginnings of block constructs and passing them to *syntax handlers*. LineParser handles inline syntaxes within lines - links, images, text formatting. Unlike BlockParser, it allows for nesting syntaxes and their gradual expansion. + + +Basic Terminology +================= + +To correctly understand how Texy works, it is necessary to distinguish between several key concepts that frequently appear in the documentation. + +**Syntax** refers to a named syntactic construct of the markup language. Each syntax has a unique name, for example, `phrase/strong` for bold text or `image` for images. The syntax name is used to enable or disable it in the `Texy::$allowed` array and is passed as a parameter to syntax handlers to distinguish which specific syntax was found. + +**Pattern** is a regular expression that defines what the syntax looks like in the text. The pattern is an implementation detail of the syntax - the author of the syntax must write a regex that recognizes it, but from the perspective of a Texy user, the syntax name and its meaning are more important. One module typically registers multiple syntaxes with different patterns. + +**Syntax handler** is a function called by the parser when it finds an occurrence of a syntax in the text. It receives the found text and returns an `HtmlElement` or a string, which is inserted in the original place. The syntax handler is where the decision is made about what to do with the found syntax - it typically invokes an element handler for the actual processing. + +**Element** is an item for which an HTML representation is generated. For example, `image` is an element for images, `linkURL` for links, `phrase` for inline formatting. Each element has its default element handler that takes care of standard processing. + +**Element handler** is a function registered for a certain type of element and called through the HandlerInvocation system. A characteristic feature is the use of the `proceed()` method, which allows delegating processing to the next handler in the chain or to the module's default handler. Element handlers are used to modify or replace the default behavior. + +**Notification handler** is a function called to notify about a certain event. Unlike element handlers, it does not return any value and cannot influence the processing result. It is used for data preparation, logging, or modifying the already created DOM tree. + +The difference between the various handlers is key to understanding the architecture. A syntax handler is tightly coupled with the parser and a specific pattern - it addresses the question of *what to do when the parser finds this pattern*. Element handlers are at a higher level of abstraction - they address the question of *how to process this type of element*, regardless of which specific syntax created it. + + +Overall Processing Flow +======================= + +When Texy receives input text, it goes through the following processing procedure. + +During preprocessing, the text is normalized. Line endings are unified to the Unix format, spaces are standardized, and tabs are optionally replaced with spaces. Subsequently, *notification handlers* registered for the `beforeParse` event are invoked. These handlers can perform data preparation, such as loading reference definitions or adjusting the configuration based on the text content. + +The parsing itself begins with the creation of a root `HtmlElement`, which represents the document. Texy then decides whether to process the text as a single line or as a complete document with block structures. In the case of block processing, a BlockParser is created, which sequentially goes through the text and looks for individual block constructs. + +LineParser works differently than BlockParser. It does not traverse the text linearly but progressively searches for the nearest occurrence of any registered syntax. When it finds one, it calls the corresponding syntax handler, which creates the appropriate HTML element. This element is inserted back into the text using special masking, and the parser continues. This allows it to find and process syntaxes nested inside already processed constructs. + +After parsing is complete, a full DOM tree representing the document's structure is created. Texy invokes notification handlers for the `afterParse` event, which can perform final modifications to the tree, such as adding identifiers to headings or building a table of contents. + +Post-processing occurs during the conversion of the DOM tree to an HTML string. Each element is recursively converted to HTML code, during which typographic adjustments like replacing quotes, dashes, or inserting non-breaking spaces are applied. Furthermore, HTML well-forming is performed - automatic closing of tags, correction of improperly nested elements, and formatting and indentation of the code. + +The final phase is decoding all masked parts back to HTML tags, removing helper markers, and assembling the resulting HTML string. + + +Syntax System +************* + +In Texy terminology, a syntax represents a named syntactic construct of the markup language. It is an abstract concept connecting several elements: a unique name, a regular expression for recognition, and a method of processing. The syntax name serves as an identifier throughout the system - it is used in the `Texy::$allowed` array for enabling or disabling, passed to handlers to distinguish the type of construct, and appears in documentation and configuration files. + +Syntax naming conventions follow two main patterns. Simpler syntaxes have a single-word name corresponding to their purpose, for example, `image`, `table`, or `script`. More complex areas use hierarchical naming with a slash, for example, `phrase/strong`, `phrase/em`, or `link/reference`. The slash serves to logically group related syntaxes and facilitates bulk operations with them. + + +Line Syntax +=========== + +Line syntaxes are used to recognize inline elements within lines of text. Typically, this includes formatting like bold or italic text, links, images, or inline code. A characteristic of line syntaxes is that they can be nested within each other, and the parser expands them sequentially. + +A line syntax is registered by calling `Texy::registerLinePattern()` with several parameters. The first is the syntax handler, i.e., the callback called upon finding a match. The second parameter is the regular expression defining the syntax's appearance in the text. The third parameter is the syntax name used throughout the system. An optional fourth parameter is another regex to test if it's even worth searching for the pattern - it's used for optimization to avoid running a complex pattern on text that definitely cannot match. + +The pattern as a regular expression must adhere to certain rules. It must not be anchored to the beginning of the text because it is searched for anywhere in the line. It should be as specific as possible to avoid false matches. + +Inline syntaxes within lines of text are processed by the [LineParser|#LineParser]. When it finds a match, it calls the appropriate syntax handler. This handler receives three parameters. The first is the LineParser instance, which provides access to the Texy object and other contextual information. The second parameter is an array with the results of the regex match, including sub-expressions. The third parameter is the syntax name, which is useful when the same callback handles multiple syntaxes. The handler must return either an `HtmlElement`, a string, or null if it refuses to process. + + +Block Syntax +============ + +Block syntaxes recognize multi-line block constructs such as headings, lists, tables, quotes, or special blocks. Unlike line syntaxes, block syntaxes never overlap - each line of text belongs to at most one block construct. + +Registering a block syntax uses `Texy::registerBlockPattern()` with three parameters: a syntax handler, a regular expression, and the syntax name. The pattern as a regular expression must adhere to certain rules. It must match from the beginning of the line and often contains an anchor for the end of the line. BlockParser automatically adds the `Am` modifiers, so the pattern should not contain them. + +Block syntaxes within a document are processed by the [BlockParser|#BlockParser]. When it finds a match, it calls the appropriate syntax handler. This handler receives similar parameters as with line syntaxes - a BlockParser instance, an array with the match, and the syntax name. It returns an `HtmlElement` representing the entire processed block, or null if it refuses processing. + + +Enabling and Disabling Syntax +============================= + +The `Texy::$allowed` array provides fine-grained control over which syntaxes are active in Texy. It is a simple yet powerful mechanism for configuring behavior without needing to change the modules' code. When you disable the `phrase/strong` syntax with this setting, the parser stops looking for the bold text construct: + +```php +$texy->allowed['phrase/strong'] = false; +``` + +The check is performed once at the beginning of parsing, so dynamically changing `$allowed` during processing has no effect. + +When constructing modules, a default value is set in `$allowed` for most syntaxes. Some syntaxes are enabled by default because they form the basis of the markup language. Others are disabled because they are advanced or potentially dangerous. For example, emoticons are disabled because not every document needs them, while basic formatting is enabled. + +Safe mode is a situation where you are processing untrusted input, such as user comments. You want to allow basic formatting but disable images, scripts, or HTML tags. `Texy\Configurator::safeMode()` sets `$allowed` for a safe combination of syntaxes. It typically disables image, figure, script, and HTML tags, but leaves links and formatting enabled. + + +Parsers +******* + + +Syntax Handler +============== + +As we mentioned in the previous section, LineParser or BlockParser goes through the text and looks for all registered patterns. When it finds a match, it calls the appropriate syntax handler and passes it information about the find - particularly an array with the results of the regex match. + +The syntax handler analyzes the found text and prepares the data for processing. It can extract parts of the text from regex groups, create helper objects like `Link` or `Image`, and parse modifiers. It also decides which element handler to invoke. It calls `Texy::invokeAroundHandlers()` with the element name and the prepared parameters. This begins their execution. The returned result is passed back to the syntax handler, which returns it to the parser. + + +Element Handler +=============== + +Element handlers implement the chain of responsibility pattern, which allows the final behavior to be composed from multiple layers. + +An element handler is registered by calling `Texy::addHandler()` with two parameters - the element name and the handler function. A single element name can have multiple handlers registered, which are then executed in order from the last registered to the first. + +The element name identifies the type of processing, for example, `phrase` for formatting, `image` for images, or `link` for links (note: this is different from syntax names). Sometimes, composite names like `linkReference` or `linkEmail` are used to distinguish different kinds of links. The names are more general than syntax names - while the `phrase/strong` syntax is a specific construct, the `phrase` element covers all kinds of inline formatting. + +Invoking an element handler uses the `Texy::invokeAroundHandlers()` method. This method receives the element name, the parser instance, and an array of parameters. It creates a HandlerInvocation object that encapsulates the entire chain of registered handlers. The first handler in the chain gets control and decides whether to call `HandlerInvocation::proceed()` to continue to the next handler or to return its own result. + +The HandlerInvocation object is key to understanding how the chaining works. It contains a stack of all handlers for the given element and the current position in this stack. When a handler calls `proceed()`, HandlerInvocation moves the position back one place in the stack and calls the next handler. If a handler calls `proceed()` with modified parameters, these new parameters are passed to all subsequent handlers. If a handler does not call `proceed()` at all, the chain is interrupted, and its return value becomes the result of the entire processing. + +The order of handler execution is from the last registered to the first. This means that a user-defined handler registered additionally gets control first and can decide whether to call the module's default handler at all. This order allows users to override the default behavior without needing to change the module's code. + +A typical use of an element handler looks like this. The handler checks the input parameters and decides if it wants to intervene in the processing. If so, it modifies the data, calls `proceed()` with the new parameters, and possibly modifies the returned result further. If the handler wants to completely replace the default processing, it creates its own result and returns it without calling `proceed()`. + + +Notification Handler +==================== + +Notification handlers represent a simpler, one-way communication mechanism. Unlike element handlers, they are not used for data transformation but for performing side actions. + +Registering a notification handler uses the same `Texy::addHandler()` method as element handlers. The difference is in how the handler is used - a notification handler returns no value and does not have access to HandlerInvocation. The first parameter is the event name. Descriptive names like `beforeParse` and `afterParse` are used for global events around parsing, or more specific ones like `afterTable`, `afterList`, `afterBlockquote` for events after a specific structure is created. The before/after prefix clearly indicates the timing of the event. + +Invoking notification handlers uses the `Texy::invokeHandlers()` method. This method simply calls all registered handlers in order and ignores their return values. Notification handlers receive the parameters passed during invocation but cannot change them for other handlers in the chain. + +Typical uses for notification handlers include several scenarios. A handler for the `beforeParse` event can load reference definitions from the text before parsing begins. A handler for `afterParse` can traverse the created DOM tree and add missing attributes or build a table of contents. Handlers like `afterTable` or `afterList` allow modules to perform final adjustments to the created structures. + +An important difference from element handlers is that notification handlers cannot prevent further processing. All registered handlers are always executed; none can break the chain. This is intended behavior - notification handlers are about side effects, not flow control. + + +LineParser +========== + +LineParser processes inline syntaxes within lines of text in a sequential manner that allows for nesting and complex interactions between syntaxes. + +The basic principle lies in finding the first occurrence of any syntax. In each iteration, it goes through all syntaxes and determines which one matches closest to the current position in the text. This syntax *wins* and is processed. If multiple syntaxes match at the same position, the one that was registered earlier wins - this is a priority based on registration order. + +When the parser finds the nearest match, it calls the corresponding syntax handler. This handler returns a result, which can be an `HtmlElement` or a string. This result then overwrites the found match in the text. + +Then, it searches again from the current position. This system ensures that the parser always sees the current state of the text. When we replace a match with new text that may contain other syntaxes, these syntaxes will be found in the next iteration. + +The `$again` property on the LineParser object is used for fine-grained control over whether the just-matched syntax should be searched for again at the same position after processing the current match. The default value is false, which says: *It no longer makes sense to look for this same syntax at this position. Move on.* + +The traversal ends when the parser reaches the end of the text or when no syntax has any more matches. The result is text where all recognizable syntaxes have been processed and replaced with their results, ready for final conversion. + + +Nesting +------- + +The ability to process nested syntaxes is one of the key features of LineParser and presents a fundamental challenge - how to prevent already processed HTML tags from being mistakenly interpreted as another syntax to be processed. + +When the parser processes text containing nested syntaxes, it first finds the outer construct. For example, in the text `"link **bold** text":URL`, the parser first finds the syntax for a link with quotes. The pattern for this syntax matches the entire string from the first quote to the colon and URL. The syntax handler creates an `HtmlElement` for the `<a>` tag, and the content `link **bold** text` is added as a child of the element. This string is inserted back into the text, and the parser continues searching for other syntaxes (`**bold**`, which represents bold text). + +But now it has a problem - there are also HTML tags in the text, which could match as the beginning of another syntax. The parser would start processing the already finished HTML tags as if they were part of the original text. + +We don't want the parser to see HTML tags. We need some way to distinguish already processed parts from parts waiting to be processed. The `Texy::protect()` method solves these problems in an elegant way - it replaces HTML tags with a unique placeholder composed of control characters - special bytes outside of printable ASCII. + +So, when an `HtmlElement` is converted to a string (using `toString()`), the result doesn't look like `<a href="...">link **bold** text</a>`, but for example, like `\x17\x18\x19\x17link **bold** text\x17\x18\x1A\x17`. + +Thus, during parsing, there are never actual HTML tags present in the text. Instead, there are only placeholders. But the inner text remains, and the parser sees it normally and can search for other syntaxes within it. This allows for gradual nesting - the outer syntax is masked, but its content is still accessible for inner syntaxes. + +At the end of processing, the `Texy::unProtect()` method goes through the resulting HTML string and replaces all placeholders with their actual values. Only at this moment do the actual HTML tags get into the output. + + +Masking Levels +-------------- + +Different types of content use different control characters for their placeholders, which allows syntaxes to selectively decide what they can contain. + +- `Patterns::CONTENT_MARKUP` denotes regular HTML markup like tags for formatting or links. It is the most common type and is used by most inline elements. The placeholder begins and ends with `\x17`. +- `Patterns::CONTENT_REPLACED` denotes content that has been replaced by something else, typically images or other replaced elements. It uses `\x16` as a marker. +- `Patterns::CONTENT_TEXTUAL` denotes text that has been escaped or otherwise treated to prevent processing. It is used for constructs like code or notexy, where we want to display the original text including markup symbols, not their interpretation. +- `Patterns::CONTENT_BLOCK` denotes block elements. It is the lowest level in the hierarchy. It uses `\x14` as a marker. + +The hierarchy of these types is not just a convention but has a practical consequence. The constant Patterns::MARK is defined as `\x14-\x1F`, i.e., a range covering all these types plus a reserve. Syntaxes use this constant in their patterns to exclude masked parts. + +Different syntaxes may have different requirements for what placeholders they can contain. A pattern that wants to see only plain text without any masked parts will use the exclusion `[^\x14-\x1F]`. This will reject all placeholders of all types. An example is the pattern for images - an image URL should not contain any HTML tags or blocks. + +A pattern that accepts lower levels but rejects higher ones will use a narrower range. For example, `[^\x17-\x1F]` will only reject `CONTENT_MARKUP` and above, but will accept `CONTENT_BLOCK`, `CONTENT_TEXTUAL`, and `CONTENT_REPLACED`. This is useful if we want to allow blocks but not inline markup. A practical example is TypographyModule, which performs typographic adjustments like replacing quotes or inserting non-breaking spaces. These adjustments should be applied to regular text, but not inside code blocks or preformatted text. + + +Syntax Collisions +----------------- + +A collision occurs when multiple syntaxes can match at the same position, and the system must choose one of them. + +A typical example is different lengths of the same symbol. The `phrase/strong+em` syntax uses three asterisks for a combination of bold and italics. The `phrase/strong` syntax uses two asterisks for bold text alone. The `phrase/em-alt` syntax uses one asterisk for italics. When the parser finds text starting with three asterisks, all three syntaxes can technically match. + +PhraseModule resolves this collision by registering syntaxes in order from longest to shortest. First, it registers `phrase/strong+em` with a pattern for three asterisks. Then `phrase/strong` with a pattern for two asterisks. Finally, `phrase/em-alt` with a pattern for one asterisk. Thanks to this order, when three asterisks are found, `phrase/strong+em` is processed first, and the shorter syntaxes don't get a chance. + +Another example is links in different formats. The `phrase/wikilink` syntax uses a pattern for `[text|url]`. The `link/reference` syntax uses a pattern for `[ref]`. Both start with an opening square bracket. If the text contains `[text|url]`, both patterns can technically start to match. + +The solution, again, is the specificity of the patterns. The pattern for `phrase/wikilink` is more specific - it requires a vertical bar inside the brackets. If the text contains a vertical bar, `phrase/wikilink` will match. If not, the pattern will fail, and `link/reference` gets a chance. The order of registration also plays a role here - `phrase/wikilink` should be registered before `link/reference`. + + +BlockParser +=========== + +BlockParser uses a fundamentally different approach to processing that reflects the nature of block constructs. The basic difference is the absence of intertwining. While LineParser allows syntaxes to be nested within each other and gradually expanded, BlockParser works with the assumption that each block is a separate unit. A single line or a group of lines belongs to at most one block. Blocks do not overlap, cross, or nest at the BlockParser level. + +BlockParser starts by finding all blocks, or rather their beginnings. The parser goes through all registered block syntaxes and finds all their occurrences. If multiple syntaxes match at the same position, the registration order is used - the earlier registered syntax takes precedence. + + +API for Syntax Handler +---------------------- + +BlockParser provides syntax handlers with an API for working with multi-line structures. + +The `BlockParser::moveBackward()` method is used to return to previous lines. It accepts the number of lines to go back. The parser moves its internal position towards the beginning of the text until it passes the specified number of line endings. This allows the callback to start reading from the beginning of the structure, even if the pattern matched in the middle or at the end. + +The `BlockParser::next()` method is used to read the next line matching a certain pattern. It accepts a regex pattern (it automatically adds the `Am` modifiers) and a reference to a variable for the match result. If the next line in the text matches the provided pattern, the method fills the result, moves the internal position past this line, and returns true. If the next line does not match, the method returns false, and the position does not change. + + +Modules +******* + +Modules are the basic organizational unit in the Texy architecture. Each module encapsulates the complete functionality for a specific area of the markup language. + +The primary responsibility of a module is to register syntaxes. In its constructor, the module calls `Texy::registerLinePattern()` or `registerBlockPattern()` for all the syntaxes it wants to process. This tells the parser: *When you find these patterns, call me.* The module thus defines which constructs in the text it recognizes. + +The second responsibility is the implementation of element handlers. The module registers handlers for the elements that its syntaxes invoke. These handlers contain the logic for converting the found constructs into HTML elements. The element handler decides what element to create, what attributes to set, and how to process the content. + +The third responsibility is to provide configuration. Modules have public properties that allow Texy users to modify the module's behavior without needing to change its code. For example, ImageModule has properties for setting the root path to images or the default alt text. + +The fourth responsibility is managing module-specific state. For example, HeadingModule keeps track of all found headings in the TOC array for building a table of contents. LinkModule manages a dictionary of references for links. This state is private to the module, and other parts of the system do not access it directly. + +Modules are designed as independent units. Each module can function on its own and should not depend on the implementation details of other modules. Communication between modules occurs through shared objects like `Link` or `Image`, not through direct method calls. + + +Structure of a Typical Module +============================= + +Most modules in Texy follow a similar structure that reflects their role in the system. + +The module inherits from the base class Module, which provides access to the Texy object via the protected property `$texy`. The module's constructor accepts a Texy instance and stores it. This allows the module to access the configuration and call methods on the Texy object. + +All initialization takes place in the constructor. The module sets the default values of its configuration properties, and possibly sets default values in the `Texy::$allowed` array for its syntaxes. Then it registers its syntaxes by calling `registerLinePattern()` or `registerBlockPattern()`. Each registration associates a pattern, a syntax handler, and a syntax name. Finally, the module registers its element handlers by calling `addHandler()`. + +Syntax handlers are methods of the module that the parser calls when it finds a syntax. These methods typically extract parts from the regex match, create helper objects, and invoke element handlers. The syntax handler decides which element handler to invoke and what parameters to pass. + +Element handlers are methods that implement the actual processing. They receive a HandlerInvocation object as the first parameter, followed by parameters specific to the given element. The element handler creates an `HtmlElement`, applies modifiers, processes the content, and returns the result. This is where the final form of the HTML is decided. + +Public properties serve as the interface for configuration. A Texy user can set these properties to customize the module's behavior. The properties are typically primitive types or arrays, not complex objects, to keep configuration simple. + + +Overview of Key Modules +======================= + +The standard distribution of Texy includes several modules covering various aspects of the markup language. + +- **PhraseModule** processes inline text formatting. It registers syntaxes for bold text, italics, underline, superscript, subscript, code, and more. All these syntaxes invoke a common handler for the `phrase` element, and the handler distinguishes which tag to create based on the syntax name. The module allows configuring which tags are used for each type of formatting. + +- **LinkModule** manages links in the document. It registers syntaxes for various link formats - explicit URLs, email addresses, references to defined links. It provides factory methods for creating `Link` objects and manages a dictionary of references. The module allows configuring the root for relative links, automatic `rel="nofollow"` for external links, and shortening of long URLs. + +- **ImageModule** processes images in a similar way to how LinkModule handles links. It registers syntax for inline images and manages a dictionary of references to defined images. It provides factory methods for creating `Image` objects and automatic detection of image dimensions. Configurable options include paths to images, default alt text, and CSS classes for alignment. + +- **HeadingModule** recognizes headings in various formats - underlined with dashes or equal signs, surrounded by hash marks. It collects all headings into a TOC array for a possible table of contents. It allows configuring the generation of IDs, the top level of headings, and the level balancing mode. + +- **ListModule** processes lists - unordered, ordered, and definition lists. It recognizes different types of bullets and automatically detects nesting based on indentation. It allows configuring which characters serve as bullets and what HTML lists to generate. + +- **TableModule** is one of the most complex modules. It recognizes tables with headers, bodies, captions, and supports colspan and rowspan. It processes modifiers for both rows and cells. + +- **BlockModule** processes special blocks delimited by `/--` and `\--`. It supports various block types - code for code, html for direct HTML, div for a generic container. It allows users to define custom handlers for their own block types. + +- **TypographyModule** performs post-processing for typographic adjustments. It replaces three dots with an ellipsis, double dashes with an en-dash, straight quotes with typographic ones, and inserts non-breaking spaces. It operates at the level of the final string between block elements. + +- **HtmlOutputModule** formats the final HTML output. It ensures well-formed HTML by automatically closing tags, correcting incorrect nesting, indenting the code, and wrapping long lines. It allows configuring the indentation level and line width. + + +Interaction Between Modules +=========================== + +Although modules are designed to be independent, in some cases they need to cooperate. + +Shared objects are the main communication mechanism. A `Link` object created by LinkModule can be passed to ImageModule to create an image link. An `Image` object created by ImageModule can be passed to FigureModule to create an image with a caption. These objects encapsulate all necessary information and provide a common interface. + +The reference system allows separating definition from use. LinkModule provides `addReference()` and `getReference()` methods for managing a dictionary of named links. A user can define a reference in one part of the document and use it in another. ImageModule has an analogous system for image references. Modules using references call factory methods that themselves check whether it is a reference or a direct value. + +Element handlers can call other element handlers. When PhraseModule processes a `phrase/span` with a link, it creates a `Link` object and calls the LinkModule's element handler to create the link. This delegates the responsibility for creating and configuring the link to the specialized module. + +Relationships between modules are typically one-sided. PhraseModule knows about LinkModule and ImageModule because it creates links and images. But LinkModule and ImageModule do not know about PhraseModule. This keeps dependencies simple and allows for easy replacement or extension of modules. + + +DOM Representation +****************** + +`HtmlElement` represents a single node in the DOM tree and provides an interface for its manipulation and processing. + +The basic structure of an element includes a tag name, an associative array of attributes, and an array of children. The children can be other `HtmlElement` instances or simply text strings. This combination allows for representing any HTML structure. + +The element name is set and retrieved via the `setName()` and `getName()` methods. A special value of null as the name means a transparent element, which has no tags, only its content. + +Attributes are publicly accessible via the `$attrs` property as an associative array. Values can be strings, numbers, booleans, or arrays. A boolean `true` means an attribute without a value (like `checked`), while `false` or `null` means the attribute will not be rendered at all. If the value is an array, the different elements are joined according to the attribute type - for `class` with spaces, for `style` with semicolons. The `setAttribute()` method sets the value of an attribute. The `getAttribute()` method returns the value of an attribute or null. + +Children are managed through several methods. The `add()` method adds a child to the end. The `insert()` method inserts a child at a specified position, optionally replacing an existing child. The `create()` method creates a new `HtmlElement` as a child and returns it for further manipulation. The `removeChildren()` method removes all children. + +The element implements the ArrayAccess interface, so children can be worked with like an array. The notation `$el[0]` returns the first child, `$el[0] = $child` sets the first child. This approach is convenient for quick manipulation of specific children. + +The `toString()` method recursively traverses the element and its children and builds a string representation. HTML tags are immediately masked using `Texy::protect()`, so a placeholder is inserted into the result instead of actual HTML characters. + +The `toHtml()` and `toText()` methods return the unmasked result including post-processing. + + +Parsing Content +=============== + +`HtmlElement` can recursively parse its content, allowing for the gradual building of the DOM tree. + +The `parseLine()` method is used to parse inline syntaxes in a string. It creates a new instance of LineParser with the current element as the container. It calls `parse()` on the parser with the provided text. LineParser sequentially finds and processes all inline syntaxes, and the resulting elements or strings are added as children of the current element. The method returns the used LineParser for possible further use. + +The `parseBlock()` method parses text as block content. It creates a BlockParser and calls `parse()` on it. BlockParser finds all block constructs in the text, processes them, and adds them as children of the element. Text between blocks is processed as paragraphs, which internally use LineParser. The method accepts a boolean parameter indicating whether the text comes from an indented block, which affects the processing of paragraphs. + +These parsing methods allow for recursive processing. A syntax handler can create an element, set its basic properties, and then call `parseLine()` or `parseBlock()` to process the content. The result is that the element's content goes through the same parsing process as the main document, including syntax recognition and handler invocation. + + +Validation +========== + +`HtmlElement` provides mechanisms for validating attributes and content according to the HTML DTD (Document Type Definition). + +The DTD is a static array defining for each HTML tag which attributes are allowed and what content it can contain. Texy loads the DTD from a file upon initialization and stores it in a static array. The DTD structure maps a tag name to a pair - an array of allowed attributes and an array of allowed content. + +The `validateAttrs()` method checks the element's attributes against the DTD. For a given tag, it gets the list of allowed attributes. It goes through all the element's attributes and removes those that are not on the list. Special cases are attributes starting with `data-` or `aria-`, which are allowed if a placeholder entry `data-*` or `aria-*` is in the DTD. + +This validation is typically called when applying modifiers with the `decorate()` method. It ensures that even if a user specifies a modifier with an invalid attribute for a given tag, the attribute does not get into the final HTML. This is important for security and HTML correctness. + +The `validateChild()` method checks whether a given child can be the content of the element. It accepts a child (`HtmlElement` or a tag name) and the DTD. If the element is defined in the DTD, the method checks if the child is in the list of allowed content. If so, it returns true. If not, it returns false. + +This validation can be used when dynamically building a DOM tree to ensure a correct structure. For example, a paragraph element must not contain block elements, so `validateChild()` would refuse to add a `div` into a `p`. In practice, Texy uses this validation to a limited extent, as the structure generated by the modules is typically correct by design. + +The combination of `validateAttrs()` and `validateChild()` provides a mechanism for ensuring valid HTML, even if the input contains untrusted data or poorly formed constructs. Texy can be configured for strict validation or can disable validation for maximum flexibility. + + +Modifiers +********* + +Modifiers provide a way to add additional attributes, classes, styles, and alignment to elements without having to write direct HTML. + +The basic format of a modifier is a dot followed by a combination of different parts in round, square, and curly brackets: `.(title)[class1 class2 #id]{style:value}<align>^valign`. The entire modifier is written before or at the end of the construct to which it applies. For example, `"**text** .(Important)[highlight]{color:red}"` creates bold text with the class `highlight`, red color, and a title attribute "Important". + +Round brackets contain the title attribute or alt text. The text inside is used as the value of the title attribute on the resulting element. If the element is an image, it can be used as alt text. Inside the round brackets, it is possible to escape a bracket with a backslash. + +Square brackets contain CSS classes and optionally an ID. Classes are written as words separated by spaces. An ID is written with a hash prefix. For example, `[main-content selected #article-5]` sets two classes and one ID. If an ID is specified multiple times, the last one is used. + +Curly brackets contain CSS styles or HTML attributes. Styles are written in the standard CSS format `property:value`. Multiple styles are separated by semicolons. Some properties are recognized as HTML attributes - for example, `{href:url}` is converted to an `href` attribute, not a CSS style. This allows setting attributes that cannot be expressed otherwise. + +Alignment is specified using special characters. `<` means left, `>` right, `=` for justify, `<>` for center. Vertical alignment uses `^` for top, `-` for middle, and `_` for bottom. These shortcuts are converted to either CSS classes or inline styles depending on the configuration. + +The parts of the modifier can be in any order, and some can be omitted. A modifier containing only classes `.[highlight]`, only a title `.(Note)`, or only a style `.{color:blue}` is valid. The parser recognizes the individual parts by their delimiting characters. + + +Modifier Class +============== + +The `Modifier` class is used to parse and store information from a modifier. + +An instance of `Modifier` is typically created by a syntax handler, which passes the modifier text extracted from a regex match to the constructor. The constructor calls the `setProperties()` method, which parses the text and populates the object's properties. + +Public properties contain the individual parts of the modifier. The `$id` property contains the element's ID as a string or null. The `$classes` property is an associative array where keys are class names and values are true. The `$styles` property is an associative array mapping CSS properties to values. The `$attrs` property is an associative array with HTML attributes that are not styles or classes. + +Two special properties, `$hAlign` and `$vAlign`, contain the horizontal and vertical alignment as strings `left`, `right`, `center`, `justify` or `top`, `middle`, `bottom`. These values are later converted to CSS classes or styles according to the Texy configuration. + +The `$title` property contains the text from the round brackets, which is used as the title attribute or alt text for images. The text is automatically unescaped from HTML entities and stripped of escaped brackets. + + +Application to Elements +======================= + +A `Modifier` object is applied to an `HtmlElement` using the `Modifier::decorate()` method. + +The `decorate()` method accepts a Texy instance and an `HtmlElement` as parameters. It sequentially applies the individual parts of the modifier to the element, taking into account the Texy configuration, which may prohibit or restrict some parts. + +The application of attributes checks which attributes are allowed for the given tag according to the `Texy::$allowedTags` configuration. If all attributes are allowed, all attributes from the `Modifier` are copied to the element. If only a list of specific attributes is allowed, only those that are on the list are copied. + +The title attribute is always applied if it is set, but the text undergoes typographic post-processing to replace quotes and other adjustments. + +The application of classes and ID checks the `Texy::$allowedClasses` configuration. If all classes are allowed, all classes from the `Modifier` are added to the element, and the ID is set. If only a list of specific classes is allowed, only those that are on the list are added. The ID is added only if a string starting with a hash is on the allowed list. + +The application of styles proceeds similarly, with a check of `Texy::$allowedStyles`. Allowed CSS properties are added to the element's style attribute. If the element already had some styles, the modifier's styles are added or overwrite existing ones. + +Alignment is applied either as a CSS class or an inline style. If a mapping is configured in Texy's `Texy::$alignClasses` for the given alignment type, the corresponding CSS class is added. If not, an inline style with the `text-align` or `vertical-align` property is added. + +The result is that the element has all the attributes, classes, styles, and other properties from the modifier, but only those that are allowed by the current Texy configuration. This ensures safety when processing untrusted input. + + +Propagation of Modifiers +======================== + +Modifiers pass through the system in several phases, maintaining flexibility and allowing for modifications at different levels. + +The syntax handler extracts the modifier text from the regex match and creates a new `Modifier` instance, populating its properties. + +The `Modifier` object is passed as a parameter to element handlers. The handler receives the already parsed object, not the raw text. This allows the handler to easily access the individual parts of the modifier - classes, styles, alignment. The handler can modify the modifier before application, for example, by adding more classes or changing styles. + +The element handler creates an `HtmlElement` and passes it to the `Modifier::decorate()` method. At this point, the modifier is applied to the element. The `decorate()` method checks the Texy configurations and ensures that only allowed parts are applied. + +In some cases, a module combines multiple modifiers. For example, TableModule parses modifiers at the table, row, and cell levels. A cell's modifier is actually a clone of the column's modifier, to which additional modifications from the specific cell's modifier are then applied. This allows for default styles for an entire column with the possibility of overriding them in individual cells. diff --git a/texy/en/configuration.texy b/texy/en/configuration.texy new file mode 100644 index 0000000000..eee1a1a890 --- /dev/null +++ b/texy/en/configuration.texy @@ -0,0 +1,719 @@ +Configuration +************* + +.[perex] +A complete guide to configuring Texy. Learn how to control all modules, set up security, and customize Texy to your needs. + +Texy is configured using **public properties** of the main `Texy\Texy` class and its **modules**. Each module is responsible for processing a specific part of the syntax (images, links, headings...). + +Basic approach: + +```php +$texy = new Texy\Texy; + +// Configuration of the main class +$texy->allowedTags = Texy\Texy::NONE; + +// Configuration of a module +$texy->imageModule->root = '/images/'; +``` + + +Texy\Texy Class .[#texy-class] +============================== + +The main class contains global settings and properties affecting the entire processing. + + +Allowed Syntax ($allowed) .{toc: $allowed} +------------------------------------------ + +The `$allowed` array controls which parts of Texy syntax are active: + +```php +// Default: all syntax features allowed (except emoticons) +$texy->allowed['image'] = true; +$texy->allowed['emoticon'] = false; + +// Disable images +$texy->allowed['image'] = false; + +// Disable HTML tags in input +$texy->allowed['html/tag'] = false; +$texy->allowed['html/comment'] = false; + +// Disable various types of links +$texy->allowed['link/reference'] = false; +$texy->allowed['link/email'] = false; +$texy->allowed['link/url'] = false; +``` + +**Complete list of syntax features:** + +|--- +| Key | Default | Description +|--- +| `image` | `true` | Images `[* img.jpg *]` +| `figure` | `true` | Images with caption +| `link/reference` | `true` | References `[ref]` +| `link/email` | `true` | Email addresses +| `link/url` | `true` | Automatic URLs +| `link/definition` | `true` | Reference definitions +| `heading/underlined` | `true` | Underlined headings +| `heading/surrounded` | `true` | Surrounded headings +| `horizline` | `true` | Horizontal lines +| `blockquote` | `true` | Quotes +| `list` | `true` | Lists +| `list/definition` | `true` | Definition lists +| `table` | `true` | Tables +| `phrase/strong` | `true` | Bold text `**text**` +| `phrase/em` | `true` | Italic `//text//` +| `phrase/em-alt` | `true` | Italic `*text*` +| `phrase/code` | `true` | Code ```text``` +| `phrase/ins` | `false` | Inserted text `++text++` +| `phrase/del` | `false` | Deleted text `--text--` +| `phrase/sup` | `false` | Superscript `^^text^^` +| `phrase/sub` | `false` | Subscript `__text__` +| `html/tag` | `true` | HTML tags in input +| `html/comment` | `true` | HTML comments +| `emoticon` | `false` | Emoticons `:-)`, `:-(` +| `blocks` | `true` | Blocks `/-- \--` +| `typography` | `true` | Typographic adjustments +| `longwords` | `true` | Breaking long words + + +Allowed HTML Tags ($allowedTags) .{toc: $allowedTags} +----------------------------------------------------- + +Controls which HTML tags are allowed in output (and input): + +```php +// Default: all valid HTML5 tags allowed +$texy->allowedTags = Texy\Texy::ALL; + +// Disable all HTML tags +$texy->allowedTags = Texy\Texy::NONE; + +// Allow only specific tags +$texy->allowedTags = [ + 'strong' => [], // <strong> without attributes + 'a' => ['href', 'title'], // <a> with attributes + 'img' => Texy\Texy::ALL, // <img> with any attributes +]; +``` + +**Formats:** +- `Texy::ALL` – all tags allowed +- `Texy::NONE` – no tags allowed +- Array – allowed tags as keys, allowed attributes as values + + +Allowed CSS Classes ($allowedClasses) .{toc: $allowedClasses} +------------------------------------------------------------- + +Controls which CSS classes and IDs can be used: + +```php +// Default: all classes and IDs allowed +$texy->allowedClasses = Texy\Texy::ALL; + +// Disable classes and IDs +$texy->allowedClasses = Texy\Texy::NONE; + +// Allow specific classes and IDs +$texy->allowedClasses = [ + 'highlight', + 'important', + '#main', // IDs start with # + '#sidebar', +]; +``` + +Usage: +```texy +Text with class .[highlight] + +Text with ID .{toc: main} +``` + + +Allowed CSS Styles ($allowedStyles) .{toc: $allowedStyles} +---------------------------------------------------------- + +Controls which inline CSS properties can be used: + +```php +// Default: all styles allowed +$texy->allowedStyles = Texy\Texy::ALL; + +// Disable inline styles +$texy->allowedStyles = Texy\Texy::NONE; + +// Allow specific CSS properties +$texy->allowedStyles = [ + 'color', + 'background-color', + 'font-size', +]; +``` + +Usage: +```texy +Text with color .{color: red} +``` + + +CSS Classes for Alignment ($alignClasses) .{toc: $alignClasses} +--------------------------------------------------------------- + +As an alternative to inline styles `style="text-align:left"`, you can use CSS classes: + +```php +// Default: empty array (uses inline styles) +$texy->alignClasses = [ + 'left' => null, + 'right' => null, + 'center' => null, + 'justify' => null, + 'top' => null, + 'middle' => null, + 'bottom' => null, +]; + +// Set classes +$texy->alignClasses['left'] = 'text-left'; +$texy->alignClasses['right'] = 'text-right'; +$texy->alignClasses['center'] = 'text-center'; +``` + +Usage: +```texy +Text aligned to the left . + +Text aligned to the right .> +``` + +With `alignClasses` set, it generates `<p class="text-left">` instead of `<p style="text-align:left">`. + + +Additional Properties +--------------------- + +```php +// Merge lines into paragraphs (default: true) +$texy->mergeLines = true; + +// Tab width (default: 8) +$texy->tabWidth = 8; + +// Obfuscate emails from bots (default: true) +$texy->obfuscateEmail = true; + +// Remove soft hyphens (default: true) +$texy->removeSoftHyphens = true; + +// Element for non-textual paragraphs (default: 'div') +$texy->nontextParagraph = 'div'; +``` + + +Modules +======= + +Each module processes a specific part of the syntax. Modules are accessible as public properties of the `Texy\Texy` class. + + +HeadingModule +------------- + +Processes headings (both underlined and surrounded). + +```php +// Top heading level (default: 1) +$texy->headingModule->top = 1; // <h1> + +// Generate automatic IDs (default: false) +$texy->headingModule->generateID = true; + +// Prefix for generated IDs (default: 'toc-') +$texy->headingModule->idPrefix = 'section-'; + +// More characters = higher heading? (default: true) +$texy->headingModule->moreMeansHigher = true; + +// Balancing mode (default: DYNAMIC) +$texy->headingModule->balancing = Texy\Modules\HeadingModule::DYNAMIC; +``` + +After processing: + +```php +// First heading (for <title>) +echo $texy->headingModule->title; + +// Table of Contents +print_r($texy->headingModule->TOC); +``` + + +PhraseModule +------------ + +Processes inline formatting (bold, italic, links within text...). + +```php +// HTML tags for individual phrases (default: see below) +$texy->phraseModule->tags = [ + 'phrase/strong' => 'strong', + 'phrase/em' => 'em', + 'phrase/code' => 'code', + // ... more +]; + +// Allow links in phrases (default: true) +$texy->phraseModule->linksAllowed = true; +``` + + +LinkModule +---------- + +Processes links, references, and URLs. + +```php +// Root path for links (default: '') +$texy->linkModule->root = '/articles/'; + +// CSS class for image links (default: null) +$texy->linkModule->imageClass = 'image-link'; + +// Always add rel="nofollow" (default: false) +$texy->linkModule->forceNoFollow = false; + +// Shorten URLs to a more readable form (default: true) +$texy->linkModule->shorten = true; +``` + +**References:** + +```php +// Add a reference +$link = new Texy\Link('https://example.com'); +$link->modifier->title = 'Example page'; +$link->label = 'Example'; +$texy->linkModule->addReference('example', $link); +``` + +Usage: +```texy +Link to [example] +``` + + +ImageModule +----------- + +Processes images. + +```php +// Root path for images (default: 'images/') +$texy->imageModule->root = '/assets/images/'; + +// Root path for linked images (default: 'images/') +$texy->imageModule->linkedRoot = '/assets/images/full/'; + +// Physical path on disk (to determine dimensions) +$texy->imageModule->fileRoot = __DIR__ . '/public/images/'; + +// CSS class for floating images (default: null) +$texy->imageModule->leftClass = 'float-left'; +$texy->imageModule->rightClass = 'float-right'; + +// Default alternative text (default: '') +$texy->imageModule->defaultAlt = 'Image'; +``` + +**References:** + +```php +// Add a reference +$image = new Texy\Image; +$image->URL = 'photo.jpg'; +$image->modifier->title = 'Photo'; +$texy->imageModule->addReference('photo', $image); +``` + + +FigureModule +------------ + +Processes images with captions. + +```php +// HTML element (default: 'div') +$texy->figureModule->tagName = 'figure'; + +// CSS class (default: 'figure') +$texy->figureModule->class = 'photo-figure'; + +// Classes for floating images (default: null) +$texy->figureModule->leftClass = 'figure-left'; +$texy->figureModule->rightClass = 'figure-right'; + +// Offset for width calculation (default: 10) +$texy->figureModule->widthDelta = 20; + +// Require caption (default: true) +$texy->figureModule->requireCaption = true; +``` + + +ListModule +---------- + +Processes bulleted, numbered, and definition lists. + +```php +// Patterns for list bullets (default: see source code) +$texy->listModule->bullets = [ + '*' => ['\*[\ \t]', 0, ''], + '-' => ['[\x{2013}-](?![>-])', 0, ''], + // ... more +]; +``` + + +TableModule +----------- + +Processes tables. + +```php +// CSS classes for rows (default: null) +$texy->tableModule->oddClass = 'odd'; +$texy->tableModule->evenClass = 'even'; +``` + +*Note: `oddClass` and `evenClass` are deprecated.* + + +HorizLineModule +--------------- + +Processes horizontal lines. + +```php +// CSS classes by type (default: null) +$texy->horizLineModule->classes = [ + '-' => 'hr-line', + '*' => 'hr-star', +]; +``` + + +TypographyModule +---------------- + +Processes typographic adjustments. + +```php +// Locale (default: 'cs') +$texy->typographyModule->locale = 'en'; +``` + +**Supported locales:** +- `cs` – Czech quotes „text" and ‚text' +- `en` – English quotes "text" and 'text' +- `fr` – French quotes «text» and ‹text› +- `de` – German quotes „text" and ‚text' +- `pl` – Polish quotes „text" and ‚text' + + +LongWordsModule +--------------- + +Breaks long words using `­`. + +```php +// Maximum word length (default: 20) +$texy->longWordsModule->wordLimit = 25; +``` + + +EmoticonModule +-------------- + +Replaces emoticons with images or Unicode characters. + +```php +// CSS class (default: null) +$texy->emoticonModule->class = 'emoji'; + +// Path to images (default: null = uses imageModule->root) +$texy->emoticonModule->root = '/images/smilies/'; +$texy->emoticonModule->fileRoot = __DIR__ . '/public/smilies/'; + +// Emoticon definitions (default: basic set) +$texy->emoticonModule->icons = [ + ':-)' => '🙂', + ':-(' => '☹', + ';-)' => '😉', + // ... or paths to images + ':cool:' => 'cool.gif', +]; +``` + + +HtmlModule +---------- + +Processes HTML tags and comments in the input text. + +```php +// Display HTML comments in output (default: true) +$texy->htmlModule->passComment = true; +``` + + +HtmlOutputModule +---------------- + +Formats the output HTML. + +```php +// Format output with indentation (default: true) +$texy->htmlOutputModule->indent = true; + +// Base indentation level (default: 0) +$texy->htmlOutputModule->baseIndent = 0; + +// Maximum line width (default: 80) +$texy->htmlOutputModule->lineWrap = 100; + +// Preserve whitespace in these elements (default: list shown) +$texy->htmlOutputModule->preserveSpaces = [ + 'textarea', 'pre', 'script', 'code', +]; +``` + + +ScriptModule +------------ + +Processes `{{macro}}` calls. + +```php +// Argument separator (default: ',') +$texy->scriptModule->separator = ';'; +``` + + +Texy\Configurator Class .{toc: Texy\Configurator} +================================================= + +Ready-made configuration sets for common use cases. + + +safeMode() – Safe Mode .{toc: safeMode()} +----------------------------------------- + +Configuration for processing **untrusted content** from users. + +```php +Texy\Configurator::safeMode($texy); +``` + +**What it does:** +- Disables classes and IDs (`$allowedClasses = NONE`) +- Disables inline styles (`$allowedStyles = NONE`) +- Allows only safe HTML tags: + +```php +[ + 'a' => ['href', 'title'], + 'abbr' => ['title'], + 'b' => [], + 'br' => [], + 'cite' => [], + 'code' => [], + 'em' => [], + 'i' => [], + 'strong' => [], + 'sub' => [], + 'sup' => [], + 'q' => [], + 'small' => [], +] +``` + +- Filters URL schemes (only `http:`, `https:`, `ftp:`, `mailto:`) +- Disables images +- Disables reference definitions +- Disables HTML comments +- Adds `rel="nofollow"` to all links + + +disableLinks() – Disable Links .{toc: disableLinks()} +----------------------------------------------------- + +Disables all types of links. + +```php +Texy\Configurator::disableLinks($texy); +``` + +**What it does:** +- Disables all types of links (`link/reference`, `link/email`, `link/url`, `link/definition`) +- Disables links in phrases (`phraseModule->linksAllowed = false`) +- Removes `<a>` from allowed tags + + +disableImages() – Disable Images .{toc: disableImages()} +-------------------------------------------------------- + +Disables all types of images. + +```php +Texy\Configurator::disableImages($texy); +``` + +**What it does:** +- Disables images (`image`, `figure`, `image/definition`) +- Removes `<img>`, `<object>`, `<embed>`, `<applet>` from allowed tags + + +Security +======== + +Texy is designed with security in mind. It automatically protects against common attacks. + + +Protection Against XSS +---------------------- + +Cross-Site Scripting (XSS) is an attack where an attacker injects malicious JavaScript into a page. + +**Examples of attacks that Texy will block:** + +```texy +Attack attempt: <script>alert('XSS')</script> + +Attack attempt: <img src=x onerror="alert('XSS')"> + +Attack attempt: "click":javascript:alert('XSS') + +Attack attempt: [* image.jpg onload="alert('XSS')" *] +``` + +Texy automatically: +- **Validates HTML** – removes disallowed tags and attributes +- **Filters URLs** – allows only safe schemes (`http:`, `https:`, `mailto:`, `ftp:`) +- **Escapes content** – properly escapes text in attributes +- **Sanitizes attributes** – removes event handlers (`onclick`, `onerror`, ...) + +```php +$texy = new Texy\Texy; +Texy\Configurator::safeMode($texy); + +$input = '<script>alert("XSS")</script>'; +$output = $texy->process($input); + +// Output: empty (script tag removed) +``` + + +URL Validation +-------------- + +Texy checks URLs in all links and images: + +```php +$texy = new Texy\Texy; + +// Set allowed schemes (default in safeMode) +$texy->urlSchemeFilters[Texy\Texy::FILTER_ANCHOR] = + '#https?:|ftp:|mailto:#Ai'; +$texy->urlSchemeFilters[Texy\Texy::FILTER_IMAGE] = + '#https?:#Ai'; +``` + +**Examples of blocked URLs:** + +```texy +"attack":javascript:alert('XSS') // blocked +"attack":data:text/html,<script> // blocked +[* javascript:alert() *] // blocked +``` + + +Filtering HTML Tags +------------------- + +Control via `$allowedTags`: + +```php +$texy = new Texy\Texy; + +// Allow only safe tags +$texy->allowedTags = [ + 'p' => [], + 'strong' => [], + 'em' => [], + 'a' => ['href', 'title'], // only these attributes +]; + +$input = '<p>Text <script>alert()</script></p>'; +$output = $texy->process($input); + +// Output: <p>Text alert()</p> +// (script tag removed) +``` + + +Practical Example +----------------- + +```php +function processComment(string $userInput): string +{ + $texy = new Texy\Texy; + + // Safe mode + Texy\Configurator::safeMode($texy); + + // Additional restrictions + $texy->allowed['link/url'] = false; // disable auto-links + $texy->allowed['html/tag'] = false; // disable HTML + + // Process + return $texy->process($userInput); +} + +// Usage +$comment = $_POST['comment']; +$html = processComment($comment); +echo $html; // safe output +``` + + +Best Practices +-------------- + +1. **Always use safeMode()** for user content +2. **Validate input** before passing to Texy (length, format) +3. **Limit HTML tags** as needed +4. **Check output** – even though Texy is safe, double-checking never hurts +5. **Log suspicious attempts** – can help you identify attackers + +```php +$texy = new Texy\Texy; +Texy\Configurator::safeMode($texy); + +// Logging +$texy->addHandler('htmlTag', function($invocation, $el, $isStart) { + if ($el->getName() === 'script') { + error_log('XSS attempt detected!'); + } + return $invocation->proceed(); +}); +``` diff --git a/texy/en/custom-handlers.texy b/texy/en/custom-handlers.texy new file mode 100644 index 0000000000..c5e49dcf8b --- /dev/null +++ b/texy/en/custom-handlers.texy @@ -0,0 +1,850 @@ +Modifying Element Behavior +************************** + +.[perex] +This chapter describes how you can change the behavior of **existing elements** in Texy - for example, modify how images, links or formatting are processed. If you want to add **completely new syntax** that Texy doesn't know by default, read the chapter [Adding Custom Syntax |custom-syntax]. + +Imagine you want the standard image syntax `[* URL *]` to recognize a special address `[* youtube:dQw4w9WgXcQ *]` and create an embedded player instead of a regular image. + +Or you want to colorize source code listings using a syntax highlighter. And so on. This is exactly what **element handlers** are for - functions that Texy calls when processing specific elements. For example, you register a handler for the `image` element that checks the URL, and if it starts with `youtube:`, returns an iframe instead of a standard image. You don't change the syntax, you just modify what happens with the found construct. + + +Elements and Their Handlers +=========================== + +In Texy terminology, an **element** is the name for a type of item that can be processed in a document. For example, `image` is an element for images, `linkURL` for links, see [default elements |#Default Elements]. Each element has its **default handler**, which is implemented in the corresponding module and handles standard processing. + +When you write `[* image.jpg *]` in text, the parser finds this syntax, creates a `Texy\Image` object with data about the image and calls all handlers registered for the `image` element. If there is no custom handler, only the default handler from `ImageModule` is called, which creates an HTML `<img>` tag. + +You register a handler by calling the `addHandler()` method: + +```php +$texy->addHandler('image', function( + Texy\HandlerInvocation $invocation, + Texy\Image $image, + ?Texy\Link $link, +) { + // your logic here +}); +``` + +The first parameter is the element name, the second is a callback function. The callback always receives a `Texy\HandlerInvocation` object as the first parameter, followed by parameters specific to the given element. + +.[note] +A detailed explanation of all handler types can be found in the chapter [Architecture and Principles |architecture]. + + +How Processing Works +==================== + +When Texy needs to process an element, it creates a `HandlerInvocation` object containing all registered handlers for this type of element. **Your handler is called first** and can: + +- **Delegate** to the next handler by calling `$invocation->proceed()` +- **Modify input** by calling `proceed()` with modified parameters +- **Modify output** by processing the result from `proceed()` +- **Break the chain** by returning its own result without calling `proceed()` + +The `proceed()` method moves processing to the next handler in the chain. If there are no more custom handlers, the default implementation from the module is called. This means your handler has absolute control - it can decide whether the default logic is called at all. + +This mechanism is called **chain of responsibility**: + +```php +$texy->addHandler('image', function( + Texy\HandlerInvocation $invocation, + Texy\Image $image, + ?Texy\Link $link, +) { + // 1. Modify input data before processing + $image->modifier->title = 'Modified title'; + + // 2. Call next handler or default processing + $element = $invocation->proceed($image, $link); + + // 3. Modify resulting HTML element + $element->attrs['loading'] = 'lazy'; + + return $element; +}); +``` + +The execution order is from **last registered to first**. If a module registers its default handler during construction and you then register a custom handler, your handler is called first. This allows you to override or wrap the default behavior. + + +Default Elements +================ + +Texy provides several predefined elements for which you can register custom handlers. Here is their complete list with parameters that the handler receives. + + +image +----- + +Processes images. + +```php +function( + Texy\HandlerInvocation $invocation, + Texy\Image $image, + ?Texy\Link $link, +): Texy\HtmlElement|string|null +``` + +The `$image` parameter contains URL, dimensions and modifiers. The `$link` parameter is provided if the image is a link (syntax `[* img *]:url`). + + +linkReference +------------- + +Processes reference links of type `[ref]`. + +```php +function( + Texy\HandlerInvocation $invocation, + Texy\Link $link, + string $content, +): Texy\HtmlElement|string|null +``` + +The `$link` parameter contains the URL and modifiers loaded from the reference definition. The `$content` parameter is the HTML content of the link (already processed by parsing inline syntax). + + +linkEmail +--------- + +Processes automatically recognized email addresses in text. + +```php +function( + Texy\HandlerInvocation $invocation, + Texy\Link $link, +): Texy\HtmlElement|string|null +``` + +The `$link` parameter contains the email address in the `URL` property. + + +linkURL +------- + +Processes automatically recognized URLs in text. + +```php +function( + Texy\HandlerInvocation $invocation, + Texy\Link $link, +): Texy\HtmlElement|string|null +``` + +The `$link` parameter contains the found URL. + + +phrase +------ + +Processes inline formatting. + +```php +function( + Texy\HandlerInvocation $invocation, + string $phrase, + string $content, + Texy\Modifier $modifier, + ?Texy\Link $link, +): Texy\HtmlElement|string|null +``` + +The `$phrase` parameter is the syntax name like `phrase/strong` or `phrase/em`. The `$content` parameter is the text inside the formatting. The `$modifier` parameter contains CSS classes, styles and other modifiers. The `$link` parameter is provided if the formatting has an attached link. + + +newReference +------------ + +Called when the parser finds a reference that is not defined. + +```php +function( + Texy\HandlerInvocation $invocation, + string $name, +): Texy\HtmlElement|string|null +``` + +The `$name` parameter is the reference name. The handler can create a link dynamically or return `null` to reject. + + +htmlComment +----------- + +Processes HTML comments. + +```php +function( + Texy\HandlerInvocation $invocation, + string $content, +): string +``` + +The `$content` parameter is the text between `<!--` and `-->`. + + +htmlTag +------- + +Processes HTML tags in text. + +```php +function( + Texy\HandlerInvocation $invocation, + Texy\HtmlElement $el, + bool $isStart, + ?bool $forceEmpty, +): Texy\HtmlElement|string|null +``` + +The `$el` parameter is an element with name and attributes. The `$isStart` parameter determines whether it is an opening tag. The `$forceEmpty` parameter forces an empty element. + + +script +------ + +Processes scripts `{{command: args}}`. + +```php +function( + Texy\HandlerInvocation $invocation, + string $command, + array $args, + ?string $raw, +): Texy\HtmlElement|string|null +``` + +The `$command` parameter is the command name. The `$args` parameter is an array of arguments. The `$raw` parameter is the original unparsed argument string. + + +figure +------ + +Processes images with captions. + +```php +function( + Texy\HandlerInvocation $invocation, + Texy\Image $image, + ?Texy\Link $link, + string $content, + Texy\Modifier $modifier, +): Texy\HtmlElement|null +``` + +The `$content` parameter is the caption text below the image. + + +heading +------- + +Processes headings. + +```php +function( + Texy\HandlerInvocation $invocation, + int $level, + string $content, + Texy\Modifier $modifier, + bool $isSurrounded, +): Texy\HtmlElement +``` + +The `$level` parameter is the heading level (0-6). The `$content` parameter is the heading text. The `$isSurrounded` parameter determines whether it is a delimited heading (`###`) or underlined. + + +horizline +--------- + +Processes horizontal lines. + +```php +function( + Texy\HandlerInvocation $invocation, + string $type, + Texy\Modifier $modifier, +): Texy\HtmlElement +``` + +The `$type` parameter is the string of characters used for the line (`---` or `***`). + + +block +----- + +Processes special blocks `/--type` to `\--`. + +```php +function( + Texy\HandlerInvocation $invocation, + string $blocktype, + string $content, + ?string $param, + Texy\Modifier $modifier, +): Texy\HtmlElement|string +``` + +The `$blocktype` parameter is the block type with the `block/` prefix, e.g. `block/code` or `block/html`. The `$content` parameter is the block content. The `$param` parameter is an optional parameter after the type (e.g. language for code). + + +emoticon +-------- + +Processes emoticons (smileys). + +```php +function( + Texy\HandlerInvocation $invocation, + string $emoticon, + string $raw, +): Texy\HtmlElement|string +``` + +The `$emoticon` parameter is the recognized emoticon (e.g. `:-)` or `:-(` ). The `$raw` parameter is the original text including any repeating characters (e.g. `:-)))))` ). + +.[note] +Emoticons are **disabled** by default. You can enable them using `$texy->allowed['emoticon'] = true;` + + +Default Events +============== + +Texy provides several predefined events for which you can register handlers. These are called **notification handlers**. Unlike element handlers, these handlers **don't return anything**. They are used for side effects such as logging, collecting statistics, or modifying the already created DOM tree. + + +beforeParse +----------- + +Called before text parsing begins. Allows you to perform preprocessing or load definitions. + +```php +function( + Texy\Texy $texy, + string &$text, + bool $isSingleLine, +): void +``` + +The `$text` parameter is passed by reference, so you can modify it. The `$isSingleLine` parameter determines whether a single line or the entire document is being parsed. + + +afterParse +---------- + +Called after parsing is complete, before converting the DOM tree to HTML. Allows you to modify the created DOM. + +```php +function( + Texy\Texy $texy, + Texy\HtmlElement $DOM, + bool $isSingleLine, +): void +``` + +The `$DOM` parameter is the root element of the document, which you can traverse and modify. + + +afterList +--------- + +Called after a list (numbered or unnumbered) is created. + +```php +function( + Texy\BlockParser $parser, + Texy\HtmlElement $element, + Texy\Modifier $modifier, +): void +``` + +The `$element` parameter is the created `<ul>` or `<ol>` element. The `$modifier` parameter contains modifiers applied to the entire list. + + +afterDefinitionList +------------------- + +Called after a definition list is created. + +```php +function( + Texy\BlockParser $parser, + Texy\HtmlElement $element, + Texy\Modifier $modifier, +): void +``` + +The `$element` parameter is the created `<dl>` element. + + +afterTable +---------- + +Called after a table is created. + +```php +function( + Texy\BlockParser $parser, + Texy\HtmlElement $element, + Texy\Modifier $modifier, +): void +``` + +The `$element` parameter is the created `<table>` element. + + +afterBlockquote +--------------- + +Called after a blockquote is created. + +```php +function( + Texy\BlockParser $parser, + Texy\HtmlElement $element, + Texy\Modifier $modifier, +): void +``` + +The `$element` parameter is the created `<blockquote>` element. + + +Basic Usage +=========== + +The simplest element handler just delegates to the default processing: + +```php +$texy->addHandler('image', function( + Texy\HandlerInvocation $invocation, + Texy\Image $image, + ?Texy\Link $link, +) { + return $invocation->proceed(); +}); +``` + +This handler doesn't change anything, but shows the basic skeleton. It passes all parameters forward and returns the result. + + +Modifying Input Data +-------------------- + +A handler can modify data before processing: + +```php +$texy->addHandler('image', function( + Texy\HandlerInvocation $invocation, + Texy\Image $image, + ?Texy\Link $link, +) { + // add default dimensions if not specified + $image->width ??= 800; + $image->height ??= 600; + return $invocation->proceed(); +}); +``` + +Changes made to `$image` or `$link` objects will be reflected in further processing, including the default handler. + + +Modifying Output Element +------------------------ + +A handler can modify the HTML element returned from `proceed()`: + +```php +$texy->addHandler('image', function( + Texy\HandlerInvocation $invocation, + Texy\Image $image, + ?Texy\Link $link, +) { + $element = $invocation->proceed(); + + if ($element) { + // add lazy loading + $element->attrs['loading'] = 'lazy'; + + // add CSS class + $element->attrs['class'][] = 'responsive'; + } + + return $element; +}); +``` + + +Conditional Processing +---------------------- + +A handler can process only certain cases and delegate others: + +```php +$texy->addHandler('image', function( + Texy\HandlerInvocation $invocation, + Texy\Image $image, + ?Texy\Link $link, +) { + // special processing for YouTube videos + if (str_starts_with($image->URL, 'youtube:')) { + $id = substr($image->URL, 8); + $iframe = sprintf( + '<iframe src="https://youtube.com/embed/%s"></iframe>', + htmlspecialchars($id) + ); + return $invocation->getTexy() + ->protect($iframe, Texy\Texy::CONTENT_BLOCK); + } + + // process other images normally + return $invocation->proceed(); +}); +``` + + +Interrupting Processing +----------------------- + +A handler can refuse processing by returning `null`: + +```php +$texy->addHandler('image', function( + Texy\HandlerInvocation $invocation, + Texy\Image $image, + ?Texy\Link $link, +) { + // disallow external images + if (str_contains($image->URL, '://')) { + return null; + } + + return $invocation->proceed(); +}); +``` + + +Practical Examples +================== + +The following examples show real use cases for element handlers. + + +YouTube Embed +------------- + +Converting special syntax to embedded video: + +```php +$texy->addHandler('image', function( + Texy\HandlerInvocation $invocation, + Texy\Image $image, + ?Texy\Link $link, +) { + if (str_starts_with($image->URL, 'youtube:')) { + $id = substr($image->URL, 8); + $width = $image->width ?: 560; + $height = $image->height ?: 315; + + $iframe = sprintf( + '<iframe width="%d" height="%d" ' + . 'src="https://youtube.com/embed/%s" ' + . 'frameborder="0" allowfullscreen></iframe>', + $width, $height, htmlspecialchars($id) + ); + + $texy = $invocation->getTexy(); + return $texy->protect($iframe, $texy::CONTENT_BLOCK); + } + + return $invocation->proceed(); +}); +``` + +Usage in text: + +```texy +[* youtube:dQw4w9WgXcQ 640x360 *] +``` + + +Image Gallery +------------- + +Wrapping images in a special div for lightbox: + +```php +$texy->addHandler('image', function( + Texy\HandlerInvocation $invocation, + Texy\Image $image, + ?Texy\Link $link, +) { + $element = $invocation->proceed(); + + // if image has 'gallery' class + if (isset($image->modifier->classes['gallery'])) { + // wrap in div with lightbox attributes + $wrapper = new Texy\HtmlElement('div'); + $wrapper->attrs['class'][] = 'lightbox-item'; + $wrapper->attrs['data-src'] = $image->URL; + $wrapper->add($element); + + return $wrapper; + } + + return $element; +}); +``` + +Usage: + +```texy +[* image.jpg .[gallery] *] +``` + + +Link Validation +--------------- + +Checking whether links found in text lead to allowed domains: + +```php +$allowedDomains = ['example.com', 'trusted.org']; + +$texy->addHandler('linkURL', function( + Texy\HandlerInvocation $invocation, + Texy\Link $link, +) use ($allowedDomains) { + $host = parse_url($link->URL, PHP_URL_HOST); + + // if domain is not in whitelist, disallow link + if ($host && !in_array($host, $allowedDomains, true)) { + return null; + } + + return $invocation->proceed(); +}); +``` + + +Automatic rel="nofollow" +------------------------ + +Adding `nofollow` to all external links found in text: + +```php +$texy->addHandler('linkURL', function( + Texy\HandlerInvocation $invocation, + Texy\Link $link, +) { + $element = $invocation->proceed(); + + // if link contains :// (i.e. is external) + if (str_contains($link->URL, '://')) { + $element->attrs['rel'] = 'nofollow'; + } + + return $element; +}); +``` + + +Syntax Highlighting +------------------- + +Integrating a syntax highlighting library: + +```php +$texy->addHandler('block', function( + Texy\HandlerInvocation $invocation, + string $blocktype, + string $content, + ?string $param, + Texy\Modifier $modifier, +) { + // process only 'code' type blocks + if ($blocktype !== 'block/code') { + return $invocation->proceed(); + } + + // apply syntax highlighting + $highlighter = new MyHighlighter(); + $highlighted = $highlighter->highlight($content, $param); + + $el = new Texy\HtmlElement('pre'); + $modifier->decorate($invocation->getTexy(), $el); + $el->attrs['class'][] = 'language-' . $param; + + $code = new Texy\HtmlElement('code'); + $code->add($highlighted); + $el->add($code); + + return $el; +}); +``` + + +Lazy Loading +------------ + +Iterating through all images and adding lazy loading: + +```php +$texy->addHandler('afterParse', function( + Texy\Texy $texy, + Texy\HtmlElement $DOM, + bool $isSingleLine, +) { + foreach ($DOM->getIterator() as $child) { + if ($child instanceof Texy\HtmlElement + && $child->getName() === 'img' + ) { + $child->attrs['loading'] = 'lazy'; + } + } +}); +``` + + +Logging Used Elements +--------------------- + +Collecting statistics about used elements in the document: + +```php +$stats = []; + +$texy->addHandler('beforeParse', function( + Texy\Texy $texy, + string &$text, + bool $isSingleLine, +) use (&$stats) { + $stats = ['images' => 0, 'links' => 0, 'headings' => 0]; +}); + +$texy->addHandler('image', function( + Texy\HandlerInvocation $invocation, + Texy\Image $image, + ?Texy\Link $link, +) use (&$stats) { + $stats['images']++; + return $invocation->proceed(); +}); + +$texy->addHandler('linkURL', function( + Texy\HandlerInvocation $invocation, + Texy\Link $link, +) use (&$stats) { + $stats['links']++; + return $invocation->proceed(); +}); + +$texy->addHandler('heading', function( + Texy\HandlerInvocation $invocation, + int $level, + string $content, + Texy\Modifier $modifier, + bool $isSurrounded, +) use (&$stats) { + $stats['headings']++; + return $invocation->proceed(); +}); +``` + + +Helper Classes +============== + +When working with handlers, you will work with several important classes. Here is an overview with their most important properties. + + +Texy\Image +---------- + +Represents an image with its parameters: + +```php +$image->URL; // string - path to image +$image->linkedURL; // ?string - link URL (if image is a link) +$image->width; // ?int - width in pixels +$image->height; // ?int - height in pixels +$image->asMax; // bool - whether dimensions are maximum +$image->modifier; // Modifier - CSS classes, styles, attributes +$image->name; // ?string - reference name +``` + + +Texy\Link +--------- + +Represents a link with its parameters: + +```php +$link->URL; // string - target URL +$link->raw; // string - original URL (before normalization) +$link->modifier; // Modifier - CSS classes, styles, attributes +$link->type; // string - link type (COMMON, BRACKET, IMAGE) +$link->label; // ?string - link text (for references) +$link->name; // ?string - reference name +``` + +Constants for link type: + +```php +Texy\Link::COMMON; // common link +Texy\Link::BRACKET; // reference link [ref] +Texy\Link::IMAGE; // link from image [* img *] +``` + + +Texy\HtmlElement +---------------- + +Represents an HTML element with its attributes and content: + +```php +$el = new Texy\HtmlElement('div'); + +// working with element name +$el->getName(); // returns 'div' +$el->setName('section'); // changes to 'section' + +// working with attributes +$el->attrs['id'] = 'main'; +$el->attrs['class'][] = 'container'; +$el->attrs['style']['color'] = 'red'; + +// working with content +$el->setText('text'); // sets text content +$el->getText(); // returns text content +$el->add($child); // adds child +$el->insert(0, $child); // inserts child at position + +// parsing content +$el->parseLine($texy, $text); // parses inline text +$el->parseBlock($texy, $text); // parses block text + +// conversion to HTML +$el->toString($texy); // internal representation +$el->toHtml($texy); // final HTML +``` + + +Texy\Modifier +------------- + +Represents modifiers for CSS classes, styles and attributes: + +```php +$mod->id; // ?string - HTML id +$mod->classes; // array - array of CSS classes +$mod->styles; // array - array of CSS styles +$mod->attrs; // array - HTML attributes +$mod->hAlign; // ?string - horizontal alignment (left, right, center, justify) +$mod->vAlign; // ?string - vertical alignment (top, middle, bottom) +$mod->title; // ?string - title attribute or alt for images + +// applying modifier to element +$mod->decorate($texy, $element); +``` diff --git a/texy/en/custom-syntax.texy b/texy/en/custom-syntax.texy new file mode 100644 index 0000000000..9a8365fc43 --- /dev/null +++ b/texy/en/custom-syntax.texy @@ -0,0 +1,519 @@ +Adding Custom Syntax +******************** + +.[perex] +This chapter describes how to add **completely new markup constructs** to Texy that don't exist by default. If you only want to modify the behavior of existing elements (for example, adjust image or link processing), read the chapter [Custom Element Behavior |custom-handlers]. + +Imagine you want to automatically create links to user profiles in documentation by writing `@@username`. Or you need special alert blocks like `:::warning`. Texy doesn't recognize these constructs, and you can't create them by modifying existing elements. + +Custom syntax allows you to define new markup constructs. You specify what the construct should look like (using a regular expression) and write a function to process it. Texy will then recognize your syntax just like its standard constructs. + + +Syntax Registration +=================== + +Texy provides two methods for registering custom syntax, depending on whether it's an inline or block element. + + +Line Syntax +----------- + +Line syntax is used for inline constructs within text lines. You register it using the `registerLinePattern()` method: + +```php +$texy->registerLinePattern( + callable $handler, + string $pattern, + string $name, + ?string $againTest = null, +); +``` + +**The `$handler` parameter** is a callback function that gets called when the syntax is found. It can be a function name, anonymous function, or array `[$object, 'method']`. + +**The `$pattern` parameter** is a regular expression (PCRE) that defines what your syntax looks like in the text. The pattern **should not be anchored** to the start of a line (`^`), since it's searched for anywhere in the text. Use capturing groups to capture the data you need to process. + +**The `$name` parameter** is a unique syntax name. It's used in the `$texy->allowed` array for enabling/disabling and passed to the handler for identification. We recommend using a prefix style like `custom/username` or `myapp/profile`. + +**The `$againTest` parameter** is an optional regex for optimization. If specified, Texy first checks whether the text contains anything that could match your pattern. Only if `$againTest` succeeds does it run the more complex pattern. This significantly speeds up processing if you have a complex pattern that's rarely used. + +Registration example: + +```php +$texy->registerLinePattern( + 'usernameHandler', + '#@@([a-z0-9_]+)#i', + 'custom/username', +); +``` + + +Block Syntax +------------ + +Block syntax is used for multi-line block constructs. You register it using the `registerBlockPattern()` method: + +```php +$texy->registerBlockPattern( + callable $handler, + string $pattern, + string $name, +); +``` + +The `$handler` and `$name` parameters have the same meaning as for line syntax. + +**The `$pattern` parameter** is a regular expression that **must be anchored** to the start of a line (`^`) and often to the end (`$`) as well. BlockParser automatically adds the `Am` modifiers (anchored, multiline), so don't add them to the pattern. The pattern should match the entire block or at least its beginning. + +Registration example: + +```php +$texy->registerBlockPattern( + 'alertHandler', + '#^:::(warning|info|danger)\n(.+)$#s', + 'custom/alert', +); +``` + + +Syntax Handler +============== + +A syntax handler is a function called by the parser when it finds an occurrence of your syntax in the text. Its job is to process the found data and return an HTML element or string. + +A detailed explanation of the syntax handler's role in Texy's architecture can be found in the chapter [Architecture and Principles |architecture#syntax-handler]. + + +For Line Syntax +--------------- + +Syntax handler signature for line syntax: + +```php +function( + Texy\LineParser $parser, + array $matches, + string $name, +): Texy\HtmlElement|string|null +``` + +**The `$parser` parameter** provides access to the parser and Texy object. You'll most often use `$parser->getTexy()` to get the Texy instance. + +**The `$matches` parameter** contains the regex match results. `$matches[0]` is the entire matched string, `$matches[1]`, `$matches[2]` etc. are the capturing groups from your pattern. + +**The `$name` parameter** is the syntax name you specified during registration. Useful if one handler processes multiple syntaxes. + +**The return value** can be `Texy\HtmlElement` for structured HTML output, `string` for direct HTML code (which you must protect), or `null` to refuse processing. + +The handler can set `$parser->again = true` if it wants the content of the created element to be parsed again to find nested syntaxes. + + +For Block Syntax +---------------- + +Syntax handler signature for block syntax: + +```php +function( + Texy\BlockParser $parser, + array $matches, + string $name, +): Texy\HtmlElement|string|null +``` + +The parameters have the same meaning as for line syntax, except you receive `Texy\BlockParser` instead of `LineParser`. + +BlockParser provides methods for working with multi-line structures: + +- **`$parser->next($pattern, &$matches)`** - matches the next line against the pattern and returns true/false +- **`$parser->moveBackward($lines)`** - moves back the specified number of lines +- **`$parser->isIndented()`** - returns true if the current block is indented + + +LineParser API +============== + +When working with line syntax, you have several useful properties and methods available. + +**The `$again` property** controls whether the currently processed syntax should be searched for again at the same position after processing. The default value is `false`. Set to `true` if you're creating an element with content that may contain other syntaxes: + +```php +function( + Texy\LineParser $parser, + array $matches, + string $name, +): Texy\HtmlElement +{ + $el = new Texy\HtmlElement('span'); + $el->setText($matches[1]); + + // content may contain additional formatting + $parser->again = true; + + return $el; +} +``` + +**The `getTexy()` method** returns the Texy object instance, which you need for working with `protect()` or accessing configuration. + + +BlockParser API +=============== + +When working with block syntax, you have methods available for working with multi-line structures. + +**The `next($pattern, &$matches)` method** tries to match the next line in the text against the specified pattern. If successful, it fills `$matches` with the result and moves the internal position past this line. Returns `true` on success, `false` on failure: + +```php +while ($parser->next('#^\-\s+(.+)$#', $matches)) { + // process next list item + $item = $matches[1]; +} +``` + +**The `moveBackward($lines = 1)` method** moves the internal position back the specified number of lines. Useful when your pattern matched more than the block's start and you want to return to the beginning: + +```php +// pattern matched 3 lines, but we want to read from the first +$parser->moveBackward(2); +``` + +**The `isIndented()` method** returns `true` if the current block is indented (starts with a space or tab). This indicates that it's nested content. + + +Practical Examples +================== + +The following examples demonstrate real use cases for custom syntax. + + +User Profiles +------------- + +Automatic creation of profile links by writing `@@username`: + +```php +$texy->registerLinePattern( + function( + Texy\LineParser $parser, + array $matches, + string $name, + ): Texy\HtmlElement + { + $username = $matches[1]; + + $el = new Texy\HtmlElement('a'); + $el->attrs['href'] = '/user/' . urlencode($username); + $el->attrs['class'][] = 'user-profile'; + $el->setText('@' . $username); + + return $el; + }, + '#@@([a-z0-9_]+)#i', + 'custom/username' +); +``` + +Usage in text: + +```texy +Check out the profile of @@johndoe or @@jane_smith. +``` + + +Alert Boxes +----------- + +Special alert blocks with different types: + +```php +$texy->registerBlockPattern( + function( + Texy\BlockParser $parser, + array $matches, + string $name, + ): Texy\HtmlElement + { + $type = $matches[1]; // warning, info, danger + $content = $matches[2]; + + $el = new Texy\HtmlElement('div'); + $el->attrs['class'][] = 'alert'; + $el->attrs['class'][] = 'alert-' . $type; + + $texy = $parser->getTexy(); + $el->parseBlock($texy, trim($content)); + + return $el; + }, + '#^:::(warning|info|danger)\n(.+?)(?=\n:::|$)#s', + 'custom/alert' +); +``` + +Usage in text: + +```texy +:::warning +This is an important warning! +::: + +:::info +For your information: the update will take place tomorrow. +::: +``` + + +Hashtags +-------- + +Automatic creation of links from hashtags: + +```php +$texy->registerLinePattern( + function( + Texy\LineParser $parser, + array $matches, + string $name, + ): Texy\HtmlElement + { + $tag = $matches[1]; + + $el = new Texy\HtmlElement('a'); + $el->attrs['href'] = '/tag/' . urlencode($tag); + $el->attrs['class'][] = 'hashtag'; + $el->setText('#' . $tag); + + return $el; + }, + '#\#([a-z0-9_]+)#i', + 'custom/hashtag', + '#\##' // optimization - search only if # is in text +); +``` + +Usage: + +```texy +Article about #php and #webdesign. +``` + + +Abbreviations +------------- + +Automatic expansion of abbreviations with explanation: + +```php +$abbreviations = [ + 'HTML' => 'HyperText Markup Language', + 'CSS' => 'Cascading Style Sheets', + 'PHP' => 'PHP: Hypertext Preprocessor', +]; + +$texy->registerLinePattern( + function( + Texy\LineParser $parser, + array $matches, + string $name + ) use ($abbreviations): ?Texy\HtmlElement + { + $abbr = $matches[1]; + + if (!isset($abbreviations[$abbr])) { + return null; // unknown abbreviation + } + + $el = new Texy\HtmlElement('abbr'); + $el->attrs['title'] = $abbreviations[$abbr]; + $el->setText($abbr); + + return $el; + }, + '#\b([A-Z]{2,})\b#', + 'custom/abbreviation' +); +``` + + +Inline Icons +------------ + +Inserting icons using special syntax: + +```php +$texy->registerLinePattern( + function( + Texy\LineParser $parser, + array $matches, + string $name, + ): Texy\HtmlElement + { + $icon = $matches[1]; + + $el = new Texy\HtmlElement('i'); + $el->attrs['class'][] = 'icon'; + $el->attrs['class'][] = 'icon-' . $icon; + $el->attrs['aria-hidden'] = 'true'; + + return $el; + }, + '#:icon-([a-z-]+):#', + 'custom/icon' +); +``` + +Usage: + +```texy +Click the button :icon-download: to download. +``` + + +Note Block +---------- + +Block for footnotes: + +```php +$texy->registerBlockPattern( + function( + Texy\BlockParser $parser, + array $matches, + string $name + ): Texy\HtmlElement + { + $parser->moveBackward(); + + $content = ''; + while ($parser->next('#^NOTE:\s*(.+)$#', $matches)) { + $content .= $matches[1] . "\n"; + } + + $el = new Texy\HtmlElement('aside'); + $el->attrs['class'][] = 'note'; + + $texy = $parser->getTexy(); + $el->parseBlock($texy, trim($content)); + + return $el; + }, + '#^NOTE:\s*(.+)$#m', + 'custom/note' +); +``` + +Usage: + +```texy +NOTE: This is an important note. +NOTE: It can be multi-line. +``` + + +Custom Quotations with Author +----------------------------- + +Extended syntax for quotations with author attribution: + +```php +$texy->registerBlockPattern( + function( + Texy\BlockParser $parser, + array $matches, + string $name, + ): Texy\HtmlElement + { + $author = $matches[1]; + $quote = $matches[2]; + + $blockquote = new Texy\HtmlElement('blockquote'); + + $texy = $parser->getTexy(); + $blockquote->parseBlock($texy, trim($quote)); + + $cite = new Texy\HtmlElement('cite'); + $cite->setText($author); + $blockquote->add($cite); + + return $blockquote; + }, + '#^QUOTE\[([^\]]+)\]:\n(.+?)(?=\n\n|$)#s', + 'custom/quote' +); +``` + +Usage: + +```texy +QUOTE[Albert Einstein]: +Imagination is more important than knowledge, +because knowledge is limited. +``` + + +Image Gallery +------------- + +Special block for creating a gallery from multiple images: + +```php +$texy->registerBlockPattern( + function( + Texy\BlockParser $parser, + array $matches, + string $name, + ): Texy\HtmlElement + { + $parser->moveBackward(); + + $gallery = new Texy\HtmlElement('div'); + $gallery->attrs['class'][] = 'gallery'; + + while ($parser->next('#^\[G\]\s*(.+)$#', $matches)) { + $img = new Texy\HtmlElement('img'); + $img->attrs['src'] = trim($matches[1]); + $img->attrs['loading'] = 'lazy'; + $gallery->add($img); + } + + return $gallery; + }, + '#^\[G\]\s*(.+)$#m', + 'custom/gallery' +); +``` + +Usage: + +```texy +[G] image1.jpg +[G] image2.jpg +[G] image3.jpg +``` + + +Syntax Collisions +================= + +When registering custom syntax, you must be careful that it doesn't collide with existing Texy syntaxes or other custom syntaxes. + +**Registration order matters.** Line syntaxes are searched in the order they were registered. If multiple syntaxes can match at the same position, the one registered earlier wins. Therefore, register more specific syntaxes before more general ones. + +**Be specific in patterns.** The more concrete your pattern is, the lower the risk of collision. The pattern `#\#\w+#` also matches `#heading`, which could collide with headings. Better is `#(?<=\s)\#[a-z0-9_]+#i`, which requires a space before the hashtag. + +**Test combinations.** Try how your syntax works in combination with existing constructs. What happens when your markup is inside a link? What if it's inside a code block? + +**Use prefixed names.** Instead of `username`, use `custom/username` or `myapp/username`. This prevents conflicts if Texy adds syntax with the same name in the future. + + +Best Practices +============== + +**Return `null` on failure.** If the handler determines it can't or doesn't want to process the given match (for example, an unknown abbreviation), return `null`. The parser will then try other syntaxes. + +**Use `protect()` for HTML.** If you're returning a raw HTML string instead of `HtmlElement`, you must protect it using `$texy->protect($html, Texy::CONTENT_...)`. Otherwise it will be escaped. + +**Set `$parser->again` correctly.** For line syntaxes that create an element with text content that may contain other syntaxes (formatting, links), set `$parser->again = true`. + +**Respect `$texy->allowed`.** If you're creating a module with multiple syntaxes, check `$texy->allowed[$name]` before registering the pattern or in the handler before processing. diff --git a/texy/en/develop.texy b/texy/en/develop.texy new file mode 100644 index 0000000000..1b3c0eda6c --- /dev/null +++ b/texy/en/develop.texy @@ -0,0 +1,35 @@ +For Developers +************** + +.[perex] +Welcome to the Texy programmer documentation! This section will guide you from basic usage to advanced techniques of extension and custom syntax. + + +[Quick Start | quickstart] +-------------------------- + +Installation, first use and basic configuration. In 5 minutes you will have Texy functional. + + +[Configuration | configuration] +------------------------------- + +Complete overview of all modules, their properties and configuration options. Security settings, allowed tags, styles and classes. + + +[Custom Element Behavior | custom-handlers] +------------------------------------------- + +Learn how to change the behavior of existing syntax. YouTube embedding, syntax highlighting, custom validation. + + +[Adding Custom Syntax | custom-syntax] +-------------------------------------- + +Creating completely new syntactic elements. + + +[Architecture and Principles | architecture] +-------------------------------------------- + +Understanding how Texy works internally. Parsing flow, modules, pattern matching, protect/unprotect mechanism. diff --git a/texy/en/quickstart.texy b/texy/en/quickstart.texy new file mode 100644 index 0000000000..a1214045a6 --- /dev/null +++ b/texy/en/quickstart.texy @@ -0,0 +1,205 @@ +Quick Start +*********** + +.[perex] +Learn how to work with Texy in just a few minutes. This page guides you through installation, first use, and basic configuration. + + +Installation +============ + +Texy leverages modern PHP features and requires at least version 8.1. + +The simplest installation method is via Composer: + +```bash +composer require texy/texy +``` + +Composer will automatically download Texy and all its dependencies. + + +First Use +========= + + +Basic Text Processing +--------------------- + +Creating a Texy instance and processing text is extremely simple: + +```php +require __DIR__ . '/vendor/autoload.php'; + +$texy = new Texy\Texy; + +$text = 'This is **bold text** and this is //italic//.'; +$html = $texy->process($text); + +echo $html; +``` + +Output: +```latte +<p>This is <strong>bold text</strong> and this is <em>italic</em>.</p> +``` + +The `process()` method processes the entire text including block elements (paragraphs, headings, lists, tables...). + + +Single-line Text +---------------- + +If you're processing only single-line text without block elements (such as database headings or short descriptions): + +```php +$texy = new Texy\Texy; + +$text = 'Link to "homepage":https://example.com'; +$html = $texy->processLine($text); + +echo $html; +``` + +Output: +```latte +Link to <a href="https://example.com">homepage</a> +``` + +The `processLine()` method doesn't wrap the output in a `<p>` paragraph and processes only inline elements. + + +Basic Configuration +=================== + +Texy works out of the box, but you'll often want to adjust the basic settings. + + +Setting Image Paths +------------------- + +If you're using relative paths to images, set the root directory: + +```php +$texy = new Texy\Texy; + +// Web path (prepended to relative URLs) +$texy->imageModule->root = '/images/'; + +// Physical disk path (for determining dimensions) +$texy->imageModule->fileRoot = __DIR__ . '/public/images/'; +``` + +Now when you write `[* photo.jpg *]`, Texy will generate `<img src="/images/photo.jpg">` and automatically determine the image dimensions. + + +Setting Link Paths +------------------ + +Similarly, you can set the root directory for links: + +```php +$texy->linkModule->root = '/articles/'; +``` + + +Enabling and Disabling Syntaxes +------------------------------- + +Each part of the Texy syntax can be disabled or enabled using the `$allowed` array: + +```php +$texy = new Texy\Texy; + +// Disable images +$texy->allowed['image'] = false; + +// Disable HTML tags in input +$texy->allowed['html/tag'] = false; + +// Enable emoticons (disabled by default) +$texy->allowed['emoticon'] = true; +``` + +A complete list of syntax options can be found in [configuration | configuration#allowed]. + + +Safe Mode for User Content +-------------------------- + +If you're processing content from users (comments, forum posts), use safe mode: + +```php +$texy = new Texy\Texy; +Texy\Configurator::safeMode($texy); + +$userInput = $_POST['comment']; +$html = $texy->process($userInput); +``` + +SafeMode: +- Allows only **safe HTML tags** (`<strong>`, `<em>`, `<a>`, ...) +- Disables **classes and IDs** +- Disables **inline styles** +- Disables **images** +- Adds `rel="nofollow"` to all links +- Filters **URL schemes** (only `http:`, `https:`, `ftp:`, `mailto:`) + +More about security in the chapter [Configuration – Security |configuration#Security]. + + +Complete Example +================ + +```php +require __DIR__ . '/vendor/autoload.php'; + +$texy = new Texy\Texy; + +// Configuration +$texy->imageModule->root = '/images/'; +$texy->linkModule->root = '/'; +$texy->allowed['html/tag'] = false; + +// Text to process +$text = ' + + +Article Heading +=============== + +This is an **introductory paragraph** with a link to "homepage":https://example.com. + +- First item +- Second item +- Third item + +[* photo.jpg .(Photograph) *] +'; + +// Processing +$html = $texy->process($text); + +// Output +echo $html; + +// Additional information +echo "Page title: " . $texy->headingModule->title; +print_r($texy->summary['links']); +print_r($texy->summary['images']); +``` + +After processing, you have access to: +- `$texy->headingModule->title` – first heading (suitable for `<title>`) +- `$texy->summary['links']` – array of all used links +- `$texy->summary['images']` – array of all used images + + +Next Steps +========== + +Now you know how to use Texy. Continue with: + +- **[Configuration | configuration]** – detailed settings for all modules +- **[Syntax | syntax]** – learn the Texy markup +- **[Architecture | architecture]** – understand how Texy works internally diff --git a/texy/en/syntax-full.texy b/texy/en/syntax-full.texy deleted file mode 100644 index 2df749bac6..0000000000 --- a/texy/en/syntax-full.texy +++ /dev/null @@ -1,889 +0,0 @@ -Detailed Description of Syntax -****************************** - - -- [#Philosophy] -- [#Paragraphs of Text] -- [#Headings] -- [#Horizontal lines] -- [#Code] -- [#Turning off the Texy] -- [#Quotes] -- [#Links] -- [#Images] -- [#Phrases] -- [#Direct HTML] -- [#Lists] -- [#Modifiers] -- [#Typography] -- [#Long Words Hyphenation] -- [#Tables] - - -Philosophy -========== - -The Texy tool was created to allow inexperienced users to easily edit the content of web pages. Therefore, the syntax is maximally intuitive. The intention is that the text in pure (unformatted) form is clear and its format can be guessed. - -Today, Texy also serves well-experienced HTML experts. Allows you to freely combine Texy notation with HTML tags. Thus, experienced users do not have to learn a new meta-language and make full use of their knowledge. Texy only simplifies their work. - -The primary logic of the syntax is ** not to use any syntax **. Just write plain text. Inserting advanced information, such as CSS classes or links, does not disrupt the flow of text. And it is written in a way that even non-technical users can easily understand. - - -Paragraphs of Text -================== - -A paragraph is considered to be one or more consecutive lines of text. The paragraphs are separated by a blank line. - -/--code texy -First paragraph lorem ipsum dolor sit amet. - -Second paragraph, který tvoří jeden řádek. -And second line of paragraph. Texy will join the lines. -\-- - -/--texysource -First paragraph lorem ipsum dolor sit amet. - -Second paragraph, který tvoří jeden řádek. -And second line of paragraph. Texy will join the lines. -\-- - -*In the edit box (textarea) is not a division into two lines of paragraph evident. That's why Texy considers them one paragraph.* - -To wrap a line in a paragraph, insert one space to the left: - -/--code texy -April is the cruellest month, breeding - Lilacs out of the dead land, mixing - Memory and desire, stirring - Dull roots with spring rain. -\-- - -/--texysource -April is the cruellest month, breeding - Lilacs out of the dead land, mixing - Memory and desire, stirring - Dull roots with spring rain. -\-- - - -Headings -======== - -Headings can be written in two ways: **underlined** or **surrounded**. - -Each headline has its own degree. In the case of **underlined**, the importance of the title is decided by the underline character. From the highest to the lowest, these are: `#` `*` `=` `-` - -/--code texy -Head Title -********** - - -Subtitle -======== -\-- - -/--texysource -Head Title -********** - - -Subtitle -======== -\-- - -For **surrounded** titles, the level determines the number of preceding characters. It can be `#` nebo `=` - -The following applies: the more characters, the more important the title (minimum two characters, maximum seven). - -/--code texy -=== Head title === - -## Subtitle -\-- - -As you can see in the case of the subtitle, the characters on the right can be omitted. - -*Subtitle levels are always relative only! So Texy finds the highest caption used and relatively differentiates the other captions.* - - -Horizontal Lines -================ - -Texy knows these notations: - -/--code texy ------------- - -******** -\-- - -/--texysource -------------- - -******** -\-- - - -Code -==== - -Used to insert source code. Syntax highlighting can also be activated using an add-on module. - -/--code texy - /---code php - function reImage($matches) { - $content = $matches[1]; - $align = $matches[5]; - $href = $matches[6]; - } - \--- -\-- - -/--texysource - /---code php - function reImage($matches) { - $content = $matches[1]; - $align = $matches[5]; - $href = $matches[6]; - } - \--- -\-- - -*Note the words `php` to indicate the language.* - - -Turning Off the Texy -==================== - -The keyword `html` or` text` affects whether the content will be understood as HTML (including tags) or plain text. - -/--code texy - /---html - <em>example</em>: **this is not strong** - \--- - - - /---text - <em>example</em>: **this is not strong** - \--- -\-- - -To turn off Texy inline, it is possible to use a double apostrophe `''` and wrap a part of the text that is not to be Texy processed. - -/--code texy - Example: ''**this is not strong**'' -\-- - - -Division into Blocks (Div) -========================== - -Use this ability to create more complex documents. - -/--code texy - /---div .[header] - - content of div - - \--- -\-- - -/--texysource - /---div .[header] - - content of div - - \--- -\-- - - -It is also possible to nest blocks: - -/--code texy - /---div .[header] - - ## This is a header. - - /---div - inner div - \--- - - Texy is sexy! - - \--- -\-- - -/--texysource - /---div .[header] - - ## This is a header. - - /---div - inner div - \--- - - Texy is sexy! - - \--- -\-- - - -Quotes -====== - -Quotes are indented, similarly to emails, by a character `>` - -/--code texy -> This is a blockquote with two paragraphs. -> -> 640 K should be enough for everyone -\-- - -/--texysource -> This is a blockquote with two paragraphs. -> -> 640 K should be enough for everyone -\-- - - -Links -===== - -Links are written by enclosing the referencing text in quotation marks, followed by a colon and a URL. Texy tries to intelligently guess the end of the URL. You can also help it by enclosing the URL in square brackets. The `http://` section is optional. - -It is also possible to insert emails as a link, Texy transforms them into a form that should confuse spambots. - -/--code texy -Look at homepage:[https://texy.info]. - -Do you know "La Trine":https://www.latrine.cz? - -"Write me":me@example.com -\-- - -/--texysource -Look at homepage:[https://texy.info]. - -Do you know "La Trine":https://www.latrine.cz? - -"Write me":me@example.com -\-- - - -References ----------- - -In order not to "pollute" the text flow by inserting URLs, it is possible to list all addresses in one place and then just link to them. This is called a reference. In addition to the address, it is possible to add the text of the link and the [modifier | #modifier]. - -/--code texy - [homepage]: https://texy.info/ Texy .(homepage) - [nette]: http://nette.org - -This is [homepage] - -Look at "this site":[nette] -\-- - - -Images -====== - -They are written between square brackets with an asterisk: - -/--code texy -[* image.gif *] -\-- - -/--texysource line -[* image.gif *] -\-- - -In text paragraphs, you often need to choose whether the image should be left-aligned or right-aligned. To do this, use the `<` and `>` character used before the right parenthesis: - -/--code texy -[* image.gif <] Left-aligned image - -[* image.gif >] Right-aligned image -\-- - -/--texysource -[* image.gif <] Left-aligned image - -[* image.gif >] Right-aligned image -\-- - -*Note: In the example above, Texy used a straight CSS style for alignment. It is possible to configure the system to assign a selected class to images instead.* - -*Note: it is possible to set a default directory for all (relative) image URLs. In the examples given, it was `images/`, so in Texy code the directory is not listed, while in the generated HTML it is.* - -*Note: if no alternative text is specified by default (as shown below), Texy will use the default. Here's a simple `image`* - - -Dimensions ----------- - -For local images, Texy detects the dimensions automatically. If you want to specify them manually, enter them as follows: - -/--code texy -[* image.gif 10x20 *] -\-- - -/--texysource line -[* image.gif 10x20 *] -\-- - - -Modifiers ---------- - -You can learn more about them in [another chapter | #modifier], but it doesn't hurt to show how they're written on images. Let's try a modifier to specify alternate text and class: - -/--code texy -[* image.gif .(alt text)[photo] *] -\-- - -/--texysource line -[* image.gif .(alt text)[photo] *] -\-- - - -Reference ---------- - -For the same reasons as for links, images can also be written using references. You need to define URLs (or multiple URLs separated by `|`) and possibly modifiers. - -/--code texy -What a beautiful girl [* picture*] ! - -[* picture*]: image.gif .(my girl) -\-- - -/--texysource -What a beautiful girl [* picture*] ! - -[* picture*]: image.gif .(my girl) -\-- - - -Figure with Caption -------------------- - -Enter three asterisks after the image, followed by a caption: - - -/--code texy -[* image.gif *] *** This is the *caption* below the image -\-- - -/--texysource -[* image.gif *] *** This is the *caption* below the image -\-- - - -Phrases -======= - -Probably the most used syntax in Texy. In almost all cases, a double character is used. - -/--code texy -//italics// - -*too italics* - -**bold** - -***heavy bold*** - -superscript^2 vs. subscript_2 -\-- - -/--texysource -//italics// - -*too italics* - -**bold** - -***heavy bold*** - -superscript^2 vs. subscript_2 -\-- - -/--div .[output] -//italics// - -*too italics* - -**bold** - -***heavy bold*** - -superscript^2 vs. subscript_2 -\-- - -A special case of a phrase is the so-called code. It differs from the other phrases in that its content will no longer be formatted and will be displayed literally: - -/--code texy -This is `<br />` and entity `&ndash` -\-- - -/--texysource -This is `<br />` and entity `&ndash` -\-- - -*Note: whether the `<code>` element is used or another (or none) can be changed simply by configuring Texy.* - - -With Modifier -------------- - -It is possible to insert it into each phrase, always just before the closing character: - -/--code texy -**strong and green .{color:green}** like Hulk -\-- - -/--texysource -**strong and green .{color:green}** like Hulk -\-- - -/--div .[output] -**strong and green .{color:green}** like Hulk -\-- - - -Direct HTML -=========== - -Texy is not a substitute for HTML. It also doesn't look for alternative ways to write HTML. The goal is to simplify content writing. If you find it easier to write a structure directly in HTML, you can do so. HTML tags are fully supported. - -/--code texy -This <strong class=info>is strong</strong> text. -<br> This is not. -\-- - -/--texysource -This <strong class=info>is strong</strong> text. -<br> This is not. -\-- - -*Note: note that Texy adjusts the notation of attributes and tags to be valid (even for XHTML output). It also pays attention to the **well-formed notation**!* - -*Note: Deciding which tags and which attributes can be used in the text is fully user configurable. This demonstrates one example from the distribution.* - - -Lists -===== - -Bulleted lists are written using `*`, `+` or `-`. It must be written at the very beginning of the line and followed by a space. - -/--code texy -- Red -- Green -- Blue -\-- - -/--texysource -- Red -- Green -- Blue -\-- - -/--div .[output] -- Red -- Green -- Blue -\-- - - -Numbered Lists --------------- - -Texy knows these five ways of writing (the first two are equivalent): - -/--code texy -1) Learn -2) Learn -3) Learn - -a) Long -b) Wide -c) Shortsighted - -A) DOS -B) Windows -C) Linux - -I) Yesterday -II) Today -III) Tomorrow -\-- - -/--texysource -1) Learn -2) Learn -3) Learn - -a) Long -b) Wide -c) Shortsighted - -A) DOS -B) Windows -C) Linux - -I) Yesterday -II) Today -III) Tomorrow -\-- - -/--div .[output] -1) Learn -2) Learn -3) Learn - -a) Long -b) Wide -c) Shortsighted - -A) DOS -B) Windows -C) Linux - -I) Yesterday -II) Today -III) Tomorrow -\-- - - -Nested Lists ------------- - -/--code texy -a) Bird - I) Bird - - Red - - Green - - Blue - II) McHale - III) Parish -b) McHale -c) Parish - 1) Bird - 2) McHale - 3) Parish -\-- - -/--texysource -a) Bird - I) Bird - - Red - - Green - - Blue - II) McHale - III) Parish -b) McHale -c) Parish - 1) Bird - 2) McHale - 3) Parish -\-- - - -Definition List ---------------- - -/--code texy -Wild Bill concert: - - date: 9 December 2004 - - place: Vodová Hall, Brno - - price: 260 CZK -\-- - -/--texysource -Wild Bill concert: - - date: 9 December 2004 - - place: Vodová Hall, Brno - - price: 260 CZK -\-- - -/--div .[output] -Wild Bill concert: - - date: 9 December 2004 - - place: Vodová Hall, Brno - - price: 260 CZK -\-- - - -With Modifiers --------------- - -The modifier that affects the entire list is listed in the line before it. Others (classic) at the end of the line: - -/--code texy -.{color:red} -triangl: .{color:blue} - - triangle .{color:green} - - untuned percussion musical instrument - - tringulation tower -\-- - -/--div .[output] -.{color:red} -triangl: .{color:blue} - - triangle .{color:green} - - untuned percussion musical instrument - - tringulation tower -\-- - - -Modifiers .[#modifier] -====================== - -Texy's most powerful weapon. The following types of modifiers can be used: - -- (caption) adds a title to the object (or alternative text to images) -- `[class1 class2 #id]` specifying the class and / or ID of the element -- {class: blue} direct style notation -- {target: _blank} or direct entry of HTML attributes -- horizontal alignment: - - left < - - right > - - centered <> - - to block = - -- vertical alignment: (only for tables) - - up ^ - - center - - - down _ - -Modifiers are written continuously (without spaces) and **must be preceded by a dot**. So for example `.(description)[left]` sets the title attribute to `description` and the class to `left`. - -**Modifiers are always written rightmost**. - -Example of applying a modifier to a paragraph of text: - -/--code texy -Centered with a modifier .<> - -Colored by a modifier .{color:blue; lang: cs} -\-- - -/--texysource -Centered with a modifier .<> - -Colored by a modifier .{color:blue; lang: cs} -\-- - - -Typography .[#typography] -========================= - -This includes all modifications and replacements of the text that modify its appearance in accordance with typographic rules and the like: - -/--code texy -- "English" 'typographic' quotation marks -- dash vs. hyphen: 10-15 vs. česko-slovenský -- dash: one -- two -- typographic cross for dimensions 10 x 20 -- arrows <- and -> and <-> ; -- three dots... -- preservation of HTML entities & -- replacing (TM) or (R) with the relevant entities (C) -\-- - -/--div .[output] -- "English" 'typographic' quotation marks -- dash vs. hyphen: 10-15 vs. česko-slovenský -- dash: one -- two -- typographic cross for dimensions 10 x 20 -- arrows <- and -> and <-> ; -- three dots... -- preservation of HTML entities & -- replacing (TM) or (R) with the relevant entities (C) -\-- - -Spaces handling: - -/--code texy -- inserting unbreakable spaces for one-letter prepositions (a car) -- unbreakable spaces for telephone numbers +420 776 552 046 -\-- - -/--code html -inserting unbreakable spaces for one-letter prepositions (a car) - -unbreakable spaces for telephone numbers +420 776 552 046 -\-- - -*Note: Replacements are usually governed by other rules that determine when -symbol replace and when not. For example, the arrow `->` cannot be at the end of a line, etc. So don't be surprised if in some cases Texy doesn't make the substitution.* - - -Abbreviations, Acronyms ------------------------ - -Double parenthetical notation is used: - -/--code texy -one word: NATO((North Atlantic Treaty Organisation)) - -multiword: "et al."((and more)) -\-- - -/--texysource -one word: NATO((North Atlantic Treaty Organisation)) - -multiword: "et al."((and more)) -\-- - - -Clickable Web Addresses ------------------------ - -Automatic conversion of web addresses and emails into a clickable form - -/--code texy -more information at www.texy.info and also ... -\-- - -/--div .[output] -more information at www.texy.info and also ... -\-- - - -Long Words Hyphenation -====================== - -Very interesting and important function of Texy. Long words can disrupt the appearance of the page, so it's a good idea to tell your browser where to wrap them. Texy searches for these places taking into account national customs, so he divides the word according to syllables: - -/--code texy -nejneobhospodařovávatelnějšími -\-- - -/--code html -nejneobhospoda­řovávatelnější­mi</p -\-- - -*Note: the word length limit is optional* - - -Tables .[#table] -================ - -Example of a simple table, columns are separated by a character `|` - -/--code texy -| first col | second col | third col -| Adam | Eva | Franta -\-- - -And the result is: - -| first col | second col | third col -| Adam | Eva | Franta - - -The table header can be defined with this notation: - -/--code texy -|----------------------------- -| First Name | Last Name | Age -|---------------------------- -| Jesus | Christ | 33 -| Cecilie | Svobodova | 74 -\-- - -|----------------------------- -| First Name | Last Name | Age -|---------------------------- -| Jesus | Christ | 33 -| Cecilie | Svobodova | 74 - -If the header does not form a row (rows), we can define it at the cell level. Just insert an asterisk immediately after the `|` character - - -/--code texy -|* First Name | Jesus | Cecilie -|* Last Name | Christ | Svobodova -|* Age | 33 | 74 -\-- - - -|* First Name | Jesus | Cecilie -|* Last Name | Christ | Svobodova -|* Age | 33 | 74 - - -Merging Columns ---------------- - -Notice the double `||`: - -/--code texy -|----------------------------- -| Name || Age -|---------------------------- -| Jesus | Christ | 33 -\-- - -|----------------------------- -| Name || Age -|---------------------------- -| Jesus | Christ | 33 - - -Merging Rows ------------- - -Notice the `^` character symbolizing the upward direction: - - -/--code texy -|----------------------------- -| First Name | Last Name | Age -|---------------------------- -| Bill || 50 -| ^| 52 -| Jim | Beam | 70 -\-- - -|----------------------------- -| First Name | Last Name | Age -|---------------------------- -| Bill || 50 -| ^| 52 -| Jim | Beam | 70 - - -Modifiers ---------- - -The following rules apply: -- a modifier affecting the whole table is inserted immediately before the table -- the modifier affecting the line is inserted at the end of the line -- the modifier affecting the column is inserted at the beginning of the cell (left in the cell) -- and finally the modifier affecting the cell is inserted at the end of the cell (right in the cell) - -Take a look at an example. - -/--code texy -.(people) -| .{color: green} first col | second col .>| third col | .{font-style:italic} -| Adam | Eva .{color: blue}| Franta | -\-- - -There is: -- `.(people)` table modifier -- `.{color: green}` column modifier -- `.{font-style:italic}` line modifier -- `.{color: blue}` a také `.>` cell modifier - -So the resulting table looks like this: - - -.(people) -| .{color: green} first col | second col .>| third col | .{font-style:italic} -| Adam | Eva .{color: blue}| Franta | diff --git a/texy/en/syntax.texy b/texy/en/syntax.texy index 2e07405d68..5ad42c4062 100644 --- a/texy/en/syntax.texy +++ b/texy/en/syntax.texy @@ -1,463 +1,891 @@ Syntax ****** ---> "Detailed syntax description":syntax-full +.[perex] +Texy was created to allow inexperienced users to easily edit website content. Therefore, its syntax is intuitive and clear. + + +Cheat Sheet +=========== + +| [Text Formatting |#Text formatting] | Syntax +|----------------------------------------------- +| [Bold text |#Text formatting] | .[text-code] ''**bold text**'' +| [Italics |#Text formatting] | ''*italics*'' or ''//italics//'' +| [Inline code |#Text formatting] | ''`code`'' +| [#Links] | ''"text":URL'' or ''[text](URL)'' +| [#Images] | ''[* image.jpg *]'' +| [#Disabling Formatting] | ''special characters'' +|----------------------------------------------- +| Elements +|----------------------------------------------- +| [#Underlined Headings] | H1 <br> === +| [#Surrounded Headings] | ''### H1'' <br> ## H2 +| [#Bulleted Lists] | ''- first'' <br> ''- second'' +| [#Numbered Lists] | ''1) first'' <br> ''2) second'' +| [#Definition Lists] | term: <br>   ''- first'' +| [#Blockquotes] | ''> blockquote'' +| [#Horizontal Rules] | ''---'' +| [#Tables] | ''\| cell \| cell \|'' +| [Code Blocks |#Preformatted text] | ''/--'' <br> ... <br> ''\--'' +|----------------------------------------------- +| Modifiers .[#toc-modifiers] +|-------------------------------------------------------- +| title | ''.(title)'' +| CSS class | ''.[btn btn-primary]'' +| ID | ''.[#id]'' +| CSS style or HTML attribute | ''.{color: blue}'' or ''.{target: _blank}'' +| horizontal alignment | ''.< .> .<> .='' +| vertical alignment | ''.^ .- ._'' + + +Paragraphs of text +================== +Texy considers a paragraph to be one or more consecutive lines of text. As soon as you leave **one blank line** between them, Texy automatically understands that it should start a new paragraph. -The Texy tool was created to allow inexperienced users to easily edit the content of web pages. Therefore, the syntax is maximally intuitive. The intention is that the text in pure (unformatted) form is clear and its format can be guessed. +This means that Texy will join lines that belong together. You don't have to worry about a sentence breaking in the middle when you shrink the editor window. -Today, Texy also serves well-experienced HTML experts. Allows you to freely combine Texy notation with HTML tags. Thus, experienced users do not have to learn a new meta-language and make full use of their knowledge. Texy only simplifies their work. +```texy +This is the first paragraph. It can easily have multiple lines, +and Texy will join them into one continuous block of text. -The primary logic of the syntax is **not to use any syntax**. Just write plain text. Inserting advanced information, such as CSS classes or links, does not disrupt the flow of text. And it is written in a way that even non-technical users can easily understand. +Only here, after a blank line, does a completely new, second paragraph begin. +``` +However, line merging can be disabled in the configuration, after which each line is considered a separate paragraph: -Paragraphs .[#paragraph] -======================== +/--php +$texy->mergeLines = false; +\-- -A paragraph is considered to be one or more consecutive lines of text. The paragraphs are separated by a blank line. -/--code texy -First paragraph lorem ipsum dolor sit amet. +Line Breaks +----------- -Second paragraph, který tvoří jeden řádek. -And second line of paragraph. Texy will join the lines. -\-- +But what if you just need to break a line without creating a whole new paragraph? This is typically useful for poems, song lyrics, or when writing an address. **Start the new line with a single space**. -To wrap a line in a paragraph, insert one space to the left: +```texy +Karel Novák, + U Tiché pošty 5 + 150 00 Praha 5 +``` -/--code texy -April is the cruellest month, breeding - Lilacs out of the dead land, mixing - Memory and desire, stirring - Dull roots with spring rain. -\-- +Styling Paragraphs +------------------ -Headings .[#heading] -==================== +Sometimes you need to distinguish an entire paragraph—for example, to make it a lead paragraph of an article, center it, or assign it a specific style for a border. This is where [#modifiers] come in, which you can place either on a separate line **before** the paragraph or at the end of its last line. -Headings can be written in two ways: **underlined** or **surrounded**. +```texy +.[perex] +This is the lead paragraph of the article, which, thanks to the modifier, +will get the CSS class "perex" and can thus look different from the rest of the text. -Each headline has its own degree. In the case of **underlined**, the importance of the title is decided by the underline character. From the highest to the lowest, these are: `#` `*` `=` `-` +This paragraph, in turn, has a unique ID assigned. .[#section-intro] -/--code texy -Head title -********** +And this paragraph will be centered. .<> +``` -Subtitle -======== +Text formatting +=============== + +| syntax | output | Syntax ID +|----------------------------------------------------------------------------- +| .[text-code] ''**bold text**'' | **bold text** | `phrase/strong` +| ''*italics* or //italics//'' | *italics* | `phrase/em-alt`, `phrase/em` +| ''***bold italics***'' | ***bold italics*** | `phrase/strong+em` +| ''`inline code`'' | `inline code` | `phrase/code` +| ''x^2 … O_2'' | x^2 … O_2 | `phrase/sup-alt`, `phrase/sub-alt` +| ''x^^2^^ … O__2__'' | x^2 … O_2 | `phrase/sup`🔸, `phrase/sup`🔸 +| ''++inserted text++'' | <ins>inserted text</ins> | `phrase/ins`🔸 +| ''--deleted text--'' | <del>deleted text</del> | `phrase/del`🔸 +| ''>>quoted text<<'' | >>quoted text<< | `phrase/quote` +| ''"blue text .{color: blue}"'' | "blue text .{color: blue}" | `phrase/span` +| ''~blue text .{color: blue}~'' | ~blue text .{color: blue}~ | `phrase/span-alt` +| ''"et al."((and others))'' | "et al."((and others)) | `phrase/acronym` +| ''NBA((National Basketball Association))'' | NBA((National Basketball Association)) | `phrase/acronym-alt` + +Syntaxes marked with 🔸 are not enabled by default and you must turn them on. For example: + +/--php +$texy->allowed['phrase/ins'] = true; \-- -For **surrounded** titles, the level determines the number of preceding characters. It can be `#` nebo `=` +For simple numerical indices, you can use the shorthand syntax `x^2` and `O_2`, but for more complex cases, the double-character variant is more robust, or you can use the HTML tags `<sup>` and `<sub>`. -The following applies: the more characters, the more important the title (minimum two characters, maximum seven). +There **must not be spaces** inside the syntax characters: -/--code texy -=== Head title === +```texy +Wrong: ** this will not be bold ** +Correct: **this will be bold** +``` -## Subtitle -\-- -As you can see in the case of the subtitle, the characters on the right can be omitted. +Styling Text +------------ +This is one of Texy's most powerful features. You can "attach" [#modifiers] to any formatted text to add a CSS class, ID, or direct style. The modifier is always inserted **just before the closing tag**: -Horizontal Lines .[#horizline] -============================== +```texy +This text is **strong and green .{color:green}** like the Hulk. -Texy knows these notations: +Warning: --This feature is deprecated .[deprecated]-- +``` +If you want to apply a modifier to text without making it bold or italic, use quotation marks `"` or tildes `~` as the enclosing characters. Texy will then create a universal HTML `<span>` tag with your styles: -/--code texy ------------- +```texy +Regular text, but "this piece is red .{color: red}", and the rest is not. +``` -******** -\-- +Formatting and Links in One +--------------------------- -Turning Off the Texy .[#disable-Texy] -===================================== +You can turn formatted text into a link - simply add a colon and the URL: -The keyword `html` or` text` affects whether the content will be understood as HTML (including tags) or plain text. +```texy +Visit our **new gallery**:https://example.com/gallery +``` -/--code texy - /---html - <em>example</em>: **this is not strong** - \--- +This works for bold text, italics, and inline code. - /---text - <em>example</em>: **this is not strong** - \--- -\-- +Writing Special Characters +-------------------------- -To turn off Texy inline, it is possible to use a double apostrophe `''` and wrap a part of the text that is not to be Texy processed. +What if you want to write `**text**` literally, including the asterisks, without it becoming bold text? You have three options: -/--code texy - Example: ''**this is not strong**'' -\-- +- a backslash is the quickest way to escape a single special character `\**text\**` +- double apostrophes [disable Texy|#Disabling Formatting] for the entire phrase `''**text**''` +- you can use standard HTML entities `**text**` -Quotes .[#blockquote] -===================== +Links +===== -Quotes are indented, similarly to emails, by a character `>` +Links are the soul of the internet. In Texy, their creation is designed to be as natural and clear as possible directly within the text. -/--code texy -> This is a blockquote with two paragraphs. -> -> 640 K should be enough for everyone -\-- +The basic syntax for a link is simple and highly readable. Enclose the linked text in `"` (or other characters for [#text formatting]) and immediately append a colon and the target URL: +```texy +Visit the official website of the "Nette Framework":https://nette.org. -Links .[#link] -============== +If you have a question, "email us":info@example.com. +``` -Links are written by enclosing the referencing text in quotation marks, followed by a colon and a URL. Texy tries to intelligently guess the end of the URL. You can also help it by enclosing the URL in square brackets. The `http://` section is optional. +The advantage is that Texy is intelligent and automatically recognizes where the URL ends. So you don't have to worry about it accidentally including a period or comma at the end of a sentence in the link. However, if the URL contains non-standard characters, you can enclose it in square brackets to precisely define the start and end of the address: -It is also possible to insert emails as a link, Texy transforms them into a form that should confuse spambots. +```texy +"Read our article":[https://example.com/news?id=1&category=articles] +``` -/--code texy -Look at homepage:[https://texy.info]. +Syntax ID `phrase/span`, `phrase/span-alt` | [PhraseModule |configuration#phrasemodule] and [LinkModule |configuration#linkmodule] -Do you know "La Trine":https://www.latrine.cz? -"Write me":me@example.com -\-- +Alternative Link Syntax +----------------------- +Are you used to the format used by Markdown or Wikipedia? Texy understands them too. You can choose the style that suits you best. -Images .[#image] -================ +```texy +[Link text](https://address.com) // Style known from Markdown +[Link text | https://address.com] // Style known from MediaWiki +text:[target URL or reference] // Single-word link +``` -They are written between square brackets with an asterisk: +Syntax ID `phrase/markdown`, `phrase/wikilink`, `phrase/quicklink` | [PhraseModule |configuration#phrasemodule] -/--code texy -[* image.gif .(alternative text) *] -\-- +Organizing Links with References +-------------------------------- + +When writing longer texts, it can be inconvenient to insert long URLs directly into paragraphs—it can harm readability and clarity. For these cases, Texy has **reference links**. + +In the text, you use only a short, easily memorable reference name. And at the end of the document, you define all these references clearly. + +```texy +We recommend studying the "official documentation":[doc] and going through the "syntax examples":[syntax]. +The entire project is built on [Nette]. + +​[doc]: https://texy.nette.org/en/ "Texy Documentation!" +​[syntax]: https://texy.nette.org/en/syntax +​[Nette]: https://nette.org +``` -In text paragraphs, you often need to choose whether the image should be left-aligned or right-aligned. To do this, use the `<` and `>` character used before the right parenthesis: +Syntax ID `link/reference`, `link/definition` | [LinkModule |configuration#linkmodule] -/--code texy -[* image.gif <] Left-aligned image. Lorem ipsum ... -[* image.gif >] Right-aligned image. Curabitur quam ... +Automatic Links +--------------- + +Whenever you write a URL (starting with `http://`, `https://`, `www.`) or an email address in the text, Texy will automatically recognize it and convert it into a clickable link. You don't have to do anything at all. + +```texy +You can find our website at www.example.com. +For support, write to support@example.com. +``` + +Syntax ID `link/url`, `link/email` | [LinkModule |configuration#linkmodule] + + +Styling Links +------------- + +With [#modifiers], you can easily add other properties to links: + +```texy +"External link .[external](Opens in a new window){target:_blank}":https://google.com +``` + +The special class `nofollow` adds the `rel="nofollow"` attribute to the link, signaling to search engines not to follow this link. This is useful, for example, for links in comments. + +```texy +"A link I don't trust .[nofollow]":https://example.com +``` + + +Automatic Email Masking +----------------------- + +Texy automatically obfuscates (masks) email addresses from spambots: + +```latte +<a href="mailto:info@example.com">info@<!-- -->example.com</a> +``` + +You can disable this behavior: + +/--php +$texy->obfuscateEmail = false; \-- -Figure with Caption +Direct HTML +=========== + +Texy is designed so that you don't have to write HTML at all. But what if you encounter a situation where inserting a direct HTML tag is simpler, or you need to create something that Texy's syntax doesn't cover? No problem. Texy gives you complete freedom to combine both worlds. + +You can seamlessly switch between Texy syntax and pure HTML whenever it suits you. + +```texy +This is **bold text** in Texy and this is <strong>bold text</strong> using HTML. + +<div class="info-box"> + <h3>You can also insert entire complex blocks</h3> +</div> +``` + +You might think that inserting direct HTML can be risky. What if you make a mistake or someone inserts malicious code? Texy thinks about this and acts as an intelligent filter and helper: + +- **Corrects errors:** Texy ensures that the resulting code is always valid and won't break your page. +- **Monitors security:** By default, Texy has a list of allowed tags and their attributes. If an unknown tag or a potentially dangerous attribute (e.g., `onclick`) appears in the code, Texy will safely remove it. This protects your website from XSS attacks. +- **Ensures a consistent output:** No matter what HTML code you insert, Texy will make sure the result is always well-formed. + +You can customize this protective shield. Using the `$texy->allowedTags` configuration, you can precisely define which HTML tags and attributes are allowed on your website and which are not. + +This gives you full control over what HTML, for example, editors can use, ensuring the consistency and security of the entire site. For more information, see the "configuration":configuration#allowedtags section. + +Syntax ID `html/tag`, `html/comment` | [HtmlModule |configuration#htmlmodule] + + +Headings +======== + +Texy offers you two elegant and intuitive ways to create headings: **underlined** and **surrounded**. + + +Underlined Headings ------------------- -Enter three asterisks after the image, followed by a caption: +This style is reminiscent of a typewriter. Simply place an underline (at least 3 characters) below the heading. The importance of the title is determined by the underlining character. From highest to lowest, these are: `#` `*` `=` `-` +```texy +This is the most important heading of the entire document +​################################################ -/--code texy -[* image.gif *] *** This is the *caption* below the image -\-- +And this is a second-level heading +​****************************** +``` +Syntax ID `heading/underlined` | [HeadingModule |configuration#headingmodule] -Phrases .[#phrase] -================== -Probably the most used syntax in Texy. In almost all cases, a double character is used. +Surrounded Headings +------------------- -/--code texy -//italics// +This method is very quick to write. You "wrap" the heading text between `#` or `=` characters. Here, the level of the heading is determined by the **number** of characters used (2 to 7). The more characters, the more important the heading. -**bold** +```texy +=== Most important heading (H1) -x^2 + y^3 -\-- +== Less important (H2) +# Even less important (H3) +``` -/--div .[output] -//italics// +You can use borders on both sides (for better visual clarity) or just at the beginning. Texy can handle both variants. -**bold** +Syntax ID `heading/surrounded` | [HeadingModule |configuration#headingmodule] -x^2 + y^3 -\-- +Styling Headings +---------------- -Texts can also be temporarily turned off - the content will not be formatted and will be displayed literally: +You can add [#modifiers] to any heading. This allows you to assign it a specific CSS class for styling or a unique ID that you can then link to. -/--code texy -Remove ''<br />'' and entity ''&ndash'' -\-- +```texy +Heading with red color .[red-heading] +​========================================== +### Heading with a unique ID for linking .[#contact] +``` -Direct HTML .[#html] -==================== -Texy is not a substitute for HTML. It also doesn't look for alternative ways to write HTML. The goal is to simplify content writing. If you find it easier to write a structure directly in HTML, you can do so. HTML tags are fully supported. +Automatic Anchors for Easy Navigation +------------------------------------- -/--code texy -This <strong class=info>is strong</strong> text. -<br> This is not. -\-- +Don't want to come up with an ID for every heading manually? Texy can do it for you! In the configuration, you can enable automatic ID generation for all headings. This is incredibly useful for directly linking to specific sections. +```php +// Enable automatic ID generation +$texy->headingModule->generateID = true; -Lists .[#list] -============== +// Optionally set a prefix for generated IDs (e.g., "toc-") +$texy->headingModule->idPrefix = 'toc-'; +``` -Bulleted lists are written using `*`, `+` or `-`. It must be written at the very beginning of the line and followed by a space. +With this setting, the heading `## My Chapter` will automatically get an ID like `id="toc-my-chapter"` without you having to write anything extra. -/--code texy -- Red -- Green -- Blue -\-- + +Lists +===== + + +Bulleted Lists +-------------- + +For a quick list of items where the order doesn't matter, a bulleted list is perfect. Just start each line with a hyphen `-`, an asterisk `*`, or a plus sign `+`, followed by a space. All three characters work the same, so you can choose the one you prefer. + +```texy +What needs to be bought: + +- Milk +- Bread +* Eggs ++ Butter +``` + +ID syntaxe `list` | [ListModule |configuration#listmodule] Numbered Lists -------------- -Texy knows these five ways of writing (the first two are equivalent): +Texy supports various numbering styles: -/--code texy -1) Learn -2) Learn -3) Learn +| `1.` | Arabic numerals (with a period) +| `1)` | Arabic numerals (with a parenthesis) +| `a)` | Lowercase letters of the alphabet +| `A)` | Uppercase letters of the alphabet +| `I)` | Roman numerals -a) Long -b) Wide -c) Shortsighted +The beauty of this is that you don't have to worry about correct numbering at all. Even if you number all the lines with a one, Texy will automatically renumber them for you. This is a huge advantage when you later need to add, delete, or move an item. -A) DOS -B) Windows -C) Linux -I) Yesterday -II) Today -III) Tomorrow -\-- +Nested and Combined Lists +------------------------- +The power of lists truly shines when you combine and nest them. This allows you to create clear, multi-level structures. You create nesting simply by indenting the line by at least **two spaces** (or one tab). -Nested Lists ------------- +```texy +1) First chapter + a) Subchapter 1.1 + - First point + - Second point + b) Subchapter 1.2 +2) Second chapter + - Main idea + - Another note +``` -/--code texy -a) Bird - I) Bird - - Red - - Green - - Blue - II) McHale - III) Parish -b) McHale -c) Parish - 1) Bird - 2) McHale - 3) Parish -\-- +Definition Lists +---------------- -Definition List ---------------- +For cases where you need to create a glossary of terms or clearly explain several terms, a definition list is ideal. -Wild Bill concert: - - date: 9 December 2004 - - place: Vodová Hall, Brno - - price: 260 CZK +On the first line, write the term you want to define and end it with a colon. On the following lines, write its definition, indenting each line and starting it with a hyphen `-`. -/--code texy -Wild Bill concert: - - date: 9 December 2004 - - place: Vodová Hall, Brno - - price: 260 CZK -\-- +```texy +HTML: + - Markup language for creating web pages. + - Abbreviation for HyperText Markup Language. +CSS: + - Language for describing the presentation (styling) of pages. + - Abbreviation for Cascading Style Sheets. +``` -Modifiers .[#modifier] -====================== +Syntax ID `list/definition` | [ListModule |configuration#listmodule] -Texy's most powerful weapon. The following types of modifiers can be used: -- (caption) adds a title to the object (or alternative text to images) -- `[class1 class2 #id]` specifying the class and / or ID of the element -- {class: blue} direct style notation -- {target: _blank} or direct entry of HTML attributes -- horizontal alignment: - - left < - - right > - - centered <> - - to block = +Styling Lists +------------- -- vertical alignment: (only for tables) - - up ^ - - center - - - down _ +Just like with other elements in Texy, you can easily add [#modifiers] to lists to change their appearance. -Modifiers are written continuously (without spaces) and **must be preceded by a dot**. So for example `.(description)[left]` sets the title attribute to `description` and the class to `left`. +**Entire list:** Write the modifier on the line **before** the start of the list. -**Modifiers are always written rightmost**. +```texy +.[colored-list] +- First item +- Second item +``` -Example of applying a modifier to a paragraph of text: +**Individual item:** Add the modifier to the **end** of the line of the given item or definition term. -/--code texy -Centered with a modifier .<> +```texy +- Regular item +- This item is important! .{font-weight: bold} +- Another regular item +``` -Colored by a modifier .{color:blue; lang: cs} -\-- -/--code html -<p style="text-align:center">Centered with a modifier</p> +Images +====== -<p style="color:blue" lang="cs">Colored by a modifier</p> -\-- +The basic syntax is very simple. Just enclose the path to the image (whether a local file or a URL) in square brackets with an asterisk: +```texy +[* image.jpg *] +[* https://domain.com/logo.png *] +``` -Typography .[#typography] -========================= +Often you will want the text to wrap around the image. For this, there are simple alignment tags that are inserted before the closing bracket: -This includes all modifications and replacements of the text that modify its appearance in accordance with typographic rules and the like: +```texy +[* image.jpg <] This text will flow smoothly around the image from the right side. -/--code texy -- "English" 'typographic' quotation marks -- dash vs. hyphen: 10-15 vs. česko-slovenský -- dash: one -- two -- typographic cross for dimensions 10 x 20 -- arrows <- and -> and <-> ; -- three dots... -- preservation of HTML entities & -- replacing (TM) or (R) with the relevant entities (C) -\-- +[* image.jpg >] In this case, the text will instead flow around the image from the left side. + +[* large-image.jpg <>] +This text will continue below the centered image. +``` + +A properly inserted image should also have "alternative text," which is displayed if the image fails to load. Using a [modifier|#modifiers], you can add this text and other elements for styling. + +```texy +[* landscape-photo.jpg .(A beautiful mountain landscape at sunset)[main-photo] *] +``` + + +Image Dimensions +---------------- + +Texy can automatically detect the dimensions of local images (if the `$texy->imageModule->fileRoot` path is set) and add them to the HTML, which speeds up page loading. However, if you want to set the dimensions manually, you have several options: + +| `[* img.jpg 150x100 *]` | Exact width 150px and height 100px +| `[* img.jpg 150 *]` | Width will be 150px, height will be automatically calculated while maintaining the aspect ratio +| `[* img.jpg ?x100 *]` | Height will be 100px, width will be automatically calculated + + +Clickable Images +---------------- + +Do you want a large image to be displayed when a small thumbnail is clicked? Or for an image to link to another page? Just add a colon and the target URL after the image syntax. + +```texy +[* thumbnail.jpg *]:large.jpg +[* nette-logo.png *]:https://nette.org +``` + +For galleries, there is also a handy shortcut `::`. This automatically creates a link to the same file located at `$texy->imageModule->linkedRoot`. + + +Visible Caption Below the Image +------------------------------- + +If you want to add a visible caption under an image (e.g., the author's name or a description of the scene), write three asterisks `***` and the caption text after it. Texy will automatically create a semantically correct HTML structure `<figure>` and `<figcaption>` from this. + +```texy +[* photo.jpg <> *] *** This is a caption. It can also contain **other formatting**. +``` + + +Organizing Images with References +--------------------------------- + +If you use one image multiple times in the text or want to have all image definitions neatly in one place, you can use references. In the text, you use only a placeholder name, and at the end of the file, you define what this name means. + +```texy +In our logo [* company-logo *] you can see the symbol of our vision. -/--div .[output] -- "English" 'typographic' quotation marks -- dash vs. hyphen: 10-15 vs. česko-slovenský -- dash: one -- two -- typographic cross for dimensions 10 x 20 -- arrows <- and -> and <-> ; -- three dots... -- preservation of HTML entities & -- replacing (TM) or (R) with the relevant entities (C) +​[* company-logo *]: /images/logo.svg 200x50 .(Our company logo) +``` + +This approach significantly clarifies the main text and simplifies image management. + +Syntax ID `image/definition` | [ImageModule |configuration#imagemodule] + + +Preformatted text +================= + +In Texy, you can easily insert blocks of code or any preformatted text where you want to ensure it is displayed exactly as you write it—including all spaces and line breaks. This is ideal for examples of source code, logs, or ASCII art. + +To insert such a block, use the `/--` and `\--` delimiters: + +```texy +/-- +function hello() { + echo 'Hello World'; +} \-- +``` -Spaces handling: +To make your code even more readable, you can tell Texy which programming language it is written in and create a handler that, for example, syntax highlights it, see the "example":custom-handlers#syntax-highlighting. Just add the keyword `code` and the language name after the initial `/--` tag: -/--code texy -- inserting unbreakable spaces for one-letter prepositions (a car) -- unbreakable spaces for telephone numbers +420 776 552 046 +```texy +/--code javascript +console.log('JavaScript'); \-- /--code html -inserting unbreakable spaces for one-letter prepositions (a car) - -unbreakable spaces for telephone numbers +420 776 552 046 +<div>This is HTML code</div> \-- +``` -*Note: Replacements are usually governed by other rules that determine when -symbol replace and when not. For example, the arrow `->` cannot be at the end of a line, etc. So don't be surprised if in some cases Texy doesn't make the substitution.* +Content Blocks (divs) +===================== -Abbreviations, Acronyms .[#acronym] ------------------------------------ +Texy allows you to create generic `<div>` blocks, thanks to which you can easily group content into logical units and then style them. -Double parenthetical notation is used: +You create a block using the `/--div` and `\--` tags. In addition, you can easily add [#modifiers]: -/--code texy -one word: NATO((North Atlantic Treaty Organisation)) +```texy +/--div .[important] +## Important Notice -multiword: "et al."((and more)) +This text will be enclosed in a `<div class="important">` block. +This allows you to style it with CSS to make it stand out. \-- +``` +The power of `<div>` blocks also lies in the ability to nest them. This allows you to create even more complex structures directly in Texy without having to write HTML manually. -Clickable Web Addresses ------------------------ +```texy +/--div .[outer] + This is the outer block. -Automatic conversion of web addresses and emails into a clickable form + /--div .[inner] + And this is a nested, inner block. + \-- -/--code texy -more information at www.texy.info and also ... + Here we are back in the outer block. \-- +``` +Thanks to this simple syntax, you can keep your content clear and semantically well-structured. -/--div .[output] -more information at www.texy.info and also ... -\-- +Disabling Formatting +==================== + +Sometimes it can be useful to "turn off" Texy for a moment and insert a piece of text where Texy should not process its tags. -Long Words Hyphenation .[#longwords] -==================================== +If you need to insert a more complex HTML structure without Texy parsing the tags, use the `/--html` block: -Very interesting and important function of Texy. Long words can disrupt the appearance of the page, so it's a good idea to tell your browser where to wrap them. Texy searches for these places taking into account national customs, so he divides the word according to syllables: +```texy +/--html +<em>This text will be processed as HTML, so it will be in italics.</em> -/--code texy -nejneobhospodařovávatelnějšími +**But Texy ignores these asterisks, so they won't be bold.** \-- +``` -/--code html -nejneobhospoda­řovávatelnější­mi</p +If you want to display text exactly as it is written, ignoring all tags (both Texy and HTML), use the `/--text` block. Everything inside this block will be displayed as plain text. + +```texy +/--text +<em>This text will be displayed with the tags, but it will not be in italics.</em> + +**This won't be bold either.** \-- +``` -*Note: the word length limit is optional* +But what if you don't want to disable Texy for an entire block of text, but just for a short phrase in the middle of a sentence? For these cases, there is an elegant and quick solution: wrap the text in **double apostrophes** `''`: +```texy +If you want to show how to write bold text, you would write: The syntax is ''**bold text**''. +``` -Tables .[#table] -================ +The result will not be bold text; instead, the string `**bold text**` will be printed literally. -Example of a simple table, columns are separated by a character `|` -/--code texy -| first col | second col | third col -| Adam | Eva | Franta -\-- +Tables +====== -And the result is: +To create a table, start each row with a `|` character and also separate the individual cells with this character. Texy will take care of the alignment and correct HTML on its own. -| first col | second col | third col -| Adam | Eva | Franta +```texy +| Jan | Novák | Praha +| Eva | Svobodová | Brno +``` +The result will be a clear and correctly formatted table. -The table header can be defined with this notation: +Syntax ID `table` | [TableModule |configuration#tablemodule] -/--code texy -|----------------------------- -| First Name | Last Name | Age -|---------------------------- -| Jesus | Christ | 33 -| Cecilie | Svobodova | 74 -\-- -|----------------------------- -| First Name | Last Name | Age -|---------------------------- -| Jesus | Christ | 33 -| Cecilie | Svobodova | 74 +Table Header +------------ +Every proper table should have a header that describes what is in each column. You create the header by separating it from the rest of the table with a line containing hyphens `-`. -Merging Columns ---------------- +```texy +| Name | Age | City +|----------|-----|------- +| Jan | 25 | Prague +| Eva | 30 | Brno +``` -Notice the double `||`: +Alternatively, you can define headers for individual rows (for example, if you have labels in the first column). You achieve this by adding an asterisk `*` immediately after the initial `|`. -/--code texy -| Name || Age -|---------------------------- -| Jesus | Christ | 33 -\-- +```texy +|* Name | Jan | Eva +|* Age | 25 | 30 +|* City | Praha | Brno +``` + + +Merging Cells +------------- + +Sometimes it is necessary to merge several cells together, either in columns or in rows. -| Name || Age +**Merging columns:** For horizontal cell merging, simply omit the separator and use a double vertical bar `||` instead. The cell to the right will be merged with the cell to its left. + +```texy +| First Name || Age |---------------------------- -| Jesus | Christ | 33 +| Jan | Novák | 25 +``` +**Merging rows:** For vertical cell merging, use the caret symbol `^` in the cell you want to attach to the one above it. This tells Texy: "Merge this cell with the one above it." -Merging Rows ------------- +```texy +| Month | Sales | +|---------|---------- +| January | 150 pcs | +| February | ^| +| March | 210 pcs | +``` -Notice the `^` character symbolizing the upward direction: +In this example, the cell with sales for January and February will be merged. +This way, several cells can be merged across rows and columns: -/--code texy +```texy | First Name | Last Name | Age |---------------------------- | Bill || 50 | ^| 52 | Jim | Beam | 70 -\-- +``` -| First Name | Last Name | Age -|---------------------------- -| Bill || 50 -| ^| 52 -| Jim | Beam | 70 + +Styling Tables +-------------- + +As with other elements in Texy, you can also add [#modifiers] to tables and their parts to change their appearance (e.g., CSS classes, styles, or IDs). + +**Entire table:** Place the modifier for the entire table on a separate line just before it. + +```texy +.[data-table table-striped] +| Header 1 | Header 2 +|------------|------------ +| data | data +``` + +**Individual rows:** If you want to style a specific row, add the modifier to its end. + +```texy +| Name | Status +|-------|-------------- +| Petr | Approved +| Jana | Rejected | .{background: #ffdddd} +``` + +**Individual columns:** To style an entire column, insert the modifier at the beginning of the first cell of that column. + +```texy +| Name | .> Price | In Stock +|----------------|-----------|--------- +| Product A | 1 200 Kč | Yes +| Product B | 850 Kč | No +``` + +**Specific cell:** Write the modifier for a single cell directly in it, usually at the end of its content. + +```texy +| Task | Status +|----------------------|------------------------------------- +| Prepare documents | Done +| Check data | In progress .{color: orange; font-weight: bold} +``` + + +Blockquotes +=========== + +If you need to emphasize someone else's idea in your text, cite a source, or just visually separate a block of text, simply start the line with the `>` character. + +```texy +> This is a blockquote. It serves to highlight an important idea or an excerpt from another source. +``` + +A blockquote doesn't have to be just one paragraph. If you want to continue with another paragraph within the same blockquote, simply insert a blank line that also starts with the `>` character. + +```texy +> This is the first paragraph of the blockquote. Lorem ipsum dolor sit amet. +> +> And this is the second paragraph, which still belongs to the same blockquote. +> This way you can structure even longer texts. +``` + +Texy even supports nested blockquotes, which is useful if you are quoting someone who is quoting someone else. For each additional level of nesting, add another `>` character. + +```texy +> This is the outer, main blockquote. +> +> > And this is a nested, second-level blockquote. +> +> Here the text returns to the main blockquote. +``` + +Inside blockquotes, you can of course use other formatting, such as **bold text** or *italics*. + + +Horizontal Rules +================ + +Sometimes it is necessary to visually divide the text. A horizontal rule is great for this. On a separate line, write three or more hyphens `---` or asterisks `***`. + +```texy +The first part of the text on a certain topic. + +*** + +The second part of the text, which begins after the visual separation. +``` + +To create a horizontal rule, it **must be preceded by a blank line**. If you were to write it immediately after the text, Texy would think you wanted to create an underlined heading. + +Syntax ID `horizline` | [HorizLineModule |configuration#horizlinemodule] + + +Typography +========== + +The power of Texy lies not only in formatting, but also in automatic typographic corrections. Texy takes care of the details that make text professional and easy to read, all according to Czech typographic rules. This allows you to focus solely on the content. + +**Quotes:** You don't have to worry about how to type correct typographic quotes on the keyboard. Texy will do it for you. + +It automatically converts classic ''"typewriter quotes"'' into the correct English “quotes” and nested ‘quotes’. The type of quotes depends on the locale setting: + +```php +$texy->typographyModule->locale = 'cs'; // Czech +$texy->typographyModule->locale = 'en'; // English +``` + +**Dashes and hyphens:** It intelligently recognizes when to use a short hyphen (in hyphenated words) and when to use a longer en dash—for example, in ranges (10–15) or between words. + +```texy +10-15 → 10–15 (en dash for ranges) +czech-slovak → czech-slovak (hyphen remains) +word -- word → word – word (en dash between words) +word --- word → word — word (em dash) +``` + +**Non-breaking spaces**: One of the biggest advantages is the automatic insertion of non-breaking spaces where needed. This prevents single-letter words (like `a` or `I`) from being left alone at the end of a line, which is a common typographic error. + +```texy +// You write: +I visited a castle in Prague. + +// Texy ensures that "a" never remains at the end of a line: +I visited a castle in Prague. +``` + +It also takes care of correct spacing in phone numbers or dates to prevent them from breaking. + +```texy ++420 776 552 046 → +420 776 552 046 (all spaces non-breaking) +``` + +**Automatic symbols:** Texy also makes it easier for you to write frequently used symbols. + +| You write | Texy generates | Description +|----- +| `...` | … | Ellipsis +| `(c)` | © | Copyright +| `(r)` | ® | Registered trademark +| `(tm)` | ™ | Trademark +| `10 x 5` | 10 × 5 | Multiplication sign +| `+-` | ± | Plus-minus +| `<-` `->` `<->` | ← → ↔ | Arrows + +Thanks to these automatic adjustments, your text will always look professional without you having to know complex keyboard shortcuts or HTML entities. + + +Hyphenation of Long Words +------------------------- + +You know it—a long word appears in the text, such as "antidisestablishmentarianism," and on a narrow mobile phone screen, it breaks the entire page layout. Fortunately, Texy offers an elegant solution: it can insert invisible "soft hyphens" (`­`) into the word. These hyphens tell the browser where (between syllables) it can safely break the word if it doesn't fit at the end of the line. If the word fits on the line, the hyphens remain hidden and nothing happens. + +```latte +antidisestablish­mentarianism +``` + +Thanks to this, your text will always adapt beautifully to any screen width without unwanted horizontal scrolling. + +Because this feature is not suitable for all types of websites, it is disabled by default. You can activate it in the configuration: + +```php +$texy->allowed['longwords'] = true; + +// Set the minimum word length from which to hyphenate (e.g., 20 characters) +$texy->longWordsModule->wordLimit = 20; +``` + +Syntax ID `longwords` | [LongWordsModule |configuration#long-wordsmodule] + + +Emoticons +========= + +Texy can automatically convert classic text smileys into graphical emoticons. Simply type the smiley as you are used to, and Texy will take care of the rest. + +| You write | Texy generates +|----- +| `:-)` | 🙂 +| `:-(` | ☹ +| `;-)` | 😉 +| `:-D` | 😀 +| `:-*` | 😘 + +Depending on the configuration, Texy can convert these shortcuts either to modern Unicode emoji (as in the table above) or to small images (`<img>`). + +To prevent unwanted conversions, for example in technical texts, this feature is disabled by default. If you want to use it, you just need to enable it: + +```php +$texy->allowed['emoticon'] = true; +``` + +More information about available emoticons and configuration options can be found in the [EmoticonModule configuration |configuration#emoticonmodul]. + +Syntax ID `emoticon` | [EmoticonModule |configuration#emoticonmodule] From 800e3c5e888c99ee1cf49d3ed53fc6a894edd506 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Fri, 31 Oct 2025 03:02:48 +0100 Subject: [PATCH 04/50] removed null as an array offset --- application/bg/routing.texy | 2 +- application/cs/routing.texy | 4 ++-- application/de/routing.texy | 2 +- application/el/routing.texy | 2 +- application/en/routing.texy | 4 ++-- application/es/routing.texy | 2 +- application/fr/routing.texy | 2 +- application/hu/routing.texy | 2 +- application/it/routing.texy | 2 +- application/ja/routing.texy | 2 +- application/pl/routing.texy | 2 +- application/pt/routing.texy | 2 +- application/ro/routing.texy | 2 +- application/ru/routing.texy | 2 +- application/sl/routing.texy | 2 +- application/tr/routing.texy | 2 +- application/uk/routing.texy | 2 +- utils/bg/arrays.texy | 4 ++-- utils/cs/arrays.texy | 4 ++-- utils/de/arrays.texy | 4 ++-- utils/el/arrays.texy | 4 ++-- utils/en/arrays.texy | 4 ++-- utils/es/arrays.texy | 4 ++-- utils/fr/arrays.texy | 4 ++-- utils/hu/arrays.texy | 4 ++-- utils/it/arrays.texy | 4 ++-- utils/ja/arrays.texy | 4 ++-- utils/pl/arrays.texy | 4 ++-- utils/pt/arrays.texy | 4 ++-- utils/ro/arrays.texy | 4 ++-- utils/ru/arrays.texy | 4 ++-- utils/sl/arrays.texy | 4 ++-- utils/tr/arrays.texy | 4 ++-- utils/uk/arrays.texy | 4 ++-- 34 files changed, 53 insertions(+), 53 deletions(-) diff --git a/application/bg/routing.texy b/application/bg/routing.texy index f6d0f09e15..d3a66e32fa 100644 --- a/application/bg/routing.texy +++ b/application/bg/routing.texy @@ -314,7 +314,7 @@ use Nette\Routing\Route; $router->addRoute('<presenter>/<action>', [ 'presenter' => 'Home', 'action' => 'default', - null => [ + '' => [ Route::FilterIn => function (array $params): array { /* ... */ }, Route::FilterOut => function (array $params): array { /* ... */ }, ], diff --git a/application/cs/routing.texy b/application/cs/routing.texy index 826bed4363..3a2e753731 100644 --- a/application/cs/routing.texy +++ b/application/cs/routing.texy @@ -306,7 +306,7 @@ Parametry `presenter`, `action` a `module` už mají předdefinované filtry, kt Obecné filtry ------------- -Vedle filtrů určených pro konkrétní parametry můžeme definovat též obecné filtry, které obdrží asociativní pole všech parametrů, které mohou jakkoliv modifikovat a poté je vrátí. Obecné filtry definujeme pod klíčem `null`. +Vedle filtrů určených pro konkrétní parametry můžeme definovat též obecné filtry, které obdrží asociativní pole všech parametrů, které mohou jakkoliv modifikovat a poté je vrátí. Obecné filtry definujeme pod prázdným klíčem. ```php use Nette\Routing\Route; @@ -314,7 +314,7 @@ use Nette\Routing\Route; $router->addRoute('<presenter>/<action>', [ 'presenter' => 'Home', 'action' => 'default', - null => [ + '' => [ Route::FilterIn => function (array $params): array { /* ... */ }, Route::FilterOut => function (array $params): array { /* ... */ }, ], 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('<presenter>/<action>', [ 'presenter' => 'Home', 'action' => 'default', - null => [ + '' => [ Route::FilterIn => function (array $params): array { /* ... */ }, Route::FilterOut => function (array $params): array { /* ... */ }, ], diff --git a/application/el/routing.texy b/application/el/routing.texy index 4886294f8b..31800ef023 100644 --- a/application/el/routing.texy +++ b/application/el/routing.texy @@ -314,7 +314,7 @@ use Nette\Routing\Route; $router->addRoute('<presenter>/<action>', [ 'presenter' => 'Home', 'action' => 'default', - null => [ + '' => [ Route::FilterIn => function (array $params): array { /* ... */ }, Route::FilterOut => function (array $params): array { /* ... */ }, ], diff --git a/application/en/routing.texy b/application/en/routing.texy index daa1c181d8..4b83f317f2 100644 --- a/application/en/routing.texy +++ b/application/en/routing.texy @@ -306,7 +306,7 @@ The parameters `presenter`, `action`, and `module` already have predefined filte General Filters --------------- -Besides filters intended for specific parameters, we can also define general filters that receive an associative array of all parameters, which they can modify in any way and then return. General filters are defined under the key `null`. +Besides filters intended for specific parameters, we can also define general filters that receive an associative array of all parameters, which they can modify in any way and then return. General filters are defined under the empty key. ```php use Nette\Routing\Route; @@ -314,7 +314,7 @@ use Nette\Routing\Route; $router->addRoute('<presenter>/<action>', [ 'presenter' => 'Home', 'action' => 'default', - null => [ + '' => [ Route::FilterIn => function (array $params): array { /* ... */ }, Route::FilterOut => function (array $params): array { /* ... */ }, ], 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('<presenter>/<action>', [ 'presenter' => 'Home', 'action' => 'default', - null => [ + '' => [ Route::FilterIn => function (array $params): array { /* ... */ }, Route::FilterOut => function (array $params): array { /* ... */ }, ], diff --git a/application/fr/routing.texy b/application/fr/routing.texy index 41a575cac4..66bfebc31b 100644 --- a/application/fr/routing.texy +++ b/application/fr/routing.texy @@ -314,7 +314,7 @@ use Nette\Routing\Route; $router->addRoute('<presenter>/<action>', [ 'presenter' => 'Home', 'action' => 'default', - null => [ + '' => [ Route::FilterIn => function (array $params): array { /* ... */ }, Route::FilterOut => function (array $params): array { /* ... */ }, ], diff --git a/application/hu/routing.texy b/application/hu/routing.texy index 0887f12764..4fb937eba5 100644 --- a/application/hu/routing.texy +++ b/application/hu/routing.texy @@ -314,7 +314,7 @@ use Nette\Routing\Route; $router->addRoute('<presenter>/<action>', [ 'presenter' => 'Home', 'action' => 'default', - null => [ + '' => [ Route::FilterIn => function (array $params): array { /* ... */ }, Route::FilterOut => function (array $params): array { /* ... */ }, ], diff --git a/application/it/routing.texy b/application/it/routing.texy index c308d57f62..36b8f5968c 100644 --- a/application/it/routing.texy +++ b/application/it/routing.texy @@ -314,7 +314,7 @@ use Nette\Routing\Route; $router->addRoute('<presenter>/<action>', [ 'presenter' => 'Home', 'action' => 'default', - null => [ + '' => [ Route::FilterIn => function (array $params): array { /* ... */ }, Route::FilterOut => function (array $params): array { /* ... */ }, ], diff --git a/application/ja/routing.texy b/application/ja/routing.texy index d3c524f7ab..4dd36be16c 100644 --- a/application/ja/routing.texy +++ b/application/ja/routing.texy @@ -314,7 +314,7 @@ use Nette\Routing\Route; $router->addRoute('<presenter>/<action>', [ 'presenter' => 'Home', 'action' => 'default', - null => [ + '' => [ Route::FilterIn => function (array $params): array { /* ... */ }, Route::FilterOut => function (array $params): array { /* ... */ }, ], diff --git a/application/pl/routing.texy b/application/pl/routing.texy index 49f68aa093..34577ae078 100644 --- a/application/pl/routing.texy +++ b/application/pl/routing.texy @@ -314,7 +314,7 @@ use Nette\Routing\Route; $router->addRoute('<presenter>/<action>', [ 'presenter' => 'Home', 'action' => 'default', - null => [ + '' => [ Route::FilterIn => function (array $params): array { /* ... */ }, Route::FilterOut => function (array $params): array { /* ... */ }, ], diff --git a/application/pt/routing.texy b/application/pt/routing.texy index 659307ca93..6becfb0d3b 100644 --- a/application/pt/routing.texy +++ b/application/pt/routing.texy @@ -314,7 +314,7 @@ use Nette\Routing\Route; $router->addRoute('<presenter>/<action>', [ 'presenter' => 'Home', 'action' => 'default', - null => [ + '' => [ Route::FilterIn => function (array $params): array { /* ... */ }, Route::FilterOut => function (array $params): array { /* ... */ }, ], diff --git a/application/ro/routing.texy b/application/ro/routing.texy index e0b8840500..0d580d0565 100644 --- a/application/ro/routing.texy +++ b/application/ro/routing.texy @@ -314,7 +314,7 @@ use Nette\Routing\Route; $router->addRoute('<presenter>/<action>', [ 'presenter' => 'Home', 'action' => 'default', - null => [ + '' => [ Route::FilterIn => function (array $params): array { /* ... */ }, Route::FilterOut => function (array $params): array { /* ... */ }, ], diff --git a/application/ru/routing.texy b/application/ru/routing.texy index dbe0c6a228..4e2896a131 100644 --- a/application/ru/routing.texy +++ b/application/ru/routing.texy @@ -314,7 +314,7 @@ use Nette\Routing\Route; $router->addRoute('<presenter>/<action>', [ 'presenter' => 'Home', 'action' => 'default', - null => [ + '' => [ Route::FilterIn => function (array $params): array { /* ... */ }, Route::FilterOut => function (array $params): array { /* ... */ }, ], diff --git a/application/sl/routing.texy b/application/sl/routing.texy index dbdd549664..06c2ccee69 100644 --- a/application/sl/routing.texy +++ b/application/sl/routing.texy @@ -314,7 +314,7 @@ use Nette\Routing\Route; $router->addRoute('<presenter>/<action>', [ 'presenter' => 'Home', 'action' => 'default', - null => [ + '' => [ Route::FilterIn => function (array $params): array { /* ... */ }, Route::FilterOut => function (array $params): array { /* ... */ }, ], diff --git a/application/tr/routing.texy b/application/tr/routing.texy index 5b0b81e30a..8fccd6c0b1 100644 --- a/application/tr/routing.texy +++ b/application/tr/routing.texy @@ -314,7 +314,7 @@ use Nette\Routing\Route; $router->addRoute('<presenter>/<action>', [ 'presenter' => 'Home', 'action' => 'default', - null => [ + '' => [ Route::FilterIn => function (array $params): array { /* ... */ }, Route::FilterOut => function (array $params): array { /* ... */ }, ], diff --git a/application/uk/routing.texy b/application/uk/routing.texy index a9db693215..ab3b132ccd 100644 --- a/application/uk/routing.texy +++ b/application/uk/routing.texy @@ -314,7 +314,7 @@ use Nette\Routing\Route; $router->addRoute('<presenter>/<action>', [ 'presenter' => 'Home', 'action' => 'default', - null => [ + '' => [ Route::FilterIn => function (array $params): array { /* ... */ }, Route::FilterOut => function (array $params): array { /* ... */ }, ], diff --git a/utils/bg/arrays.texy b/utils/bg/arrays.texy index d73bfc5b6e..c2f5884283 100644 --- a/utils/bg/arrays.texy +++ b/utils/bg/arrays.texy @@ -360,8 +360,8 @@ pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method] Връща и премахва стойността на елемент от масива. Ако не съществува, хвърля изключение или връща стойността `$default`, ако е посочена. ```php -$array = [1 => 'foo', null => 'bar']; -$a = Arrays::pick($array, null); +$array = [1 => 'foo', 'x' => 'bar']; +$a = Arrays::pick($array, 'x'); // $a = 'bar' $b = Arrays::pick($array, 'not-exists', 'foobar'); // $b = 'foobar' diff --git a/utils/cs/arrays.texy b/utils/cs/arrays.texy index 9351bba355..baa1c82d10 100644 --- a/utils/cs/arrays.texy +++ b/utils/cs/arrays.texy @@ -360,8 +360,8 @@ pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method] Vrátí a odstraní hodnotu prvku z pole. Pokud neexistuje, vyhodí výjimku, nebo vrátí hodnotu `$default`, pokud je uvedena. ```php -$array = [1 => 'foo', null => 'bar']; -$a = Arrays::pick($array, null); +$array = [1 => 'foo', 'x' => 'bar']; +$a = Arrays::pick($array, 'x'); // $a = 'bar' $b = Arrays::pick($array, 'not-exists', 'foobar'); // $b = 'foobar' diff --git a/utils/de/arrays.texy b/utils/de/arrays.texy index 9167248df2..472f4b1c8e 100644 --- a/utils/de/arrays.texy +++ b/utils/de/arrays.texy @@ -360,8 +360,8 @@ pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method] Gibt den Wert eines Elements aus dem Array zurück und entfernt ihn. Wenn er nicht existiert, wird eine Ausnahme geworfen, oder der Wert `$default` zurückgegeben, falls angegeben. ```php -$array = [1 => 'foo', null => 'bar']; -$a = Arrays::pick($array, null); +$array = [1 => 'foo', 'x' => 'bar']; +$a = Arrays::pick($array, 'x'); // $a = 'bar' $b = Arrays::pick($array, 'not-exists', 'foobar'); // $b = 'foobar' diff --git a/utils/el/arrays.texy b/utils/el/arrays.texy index 835c2658eb..8fdc7e0860 100644 --- a/utils/el/arrays.texy +++ b/utils/el/arrays.texy @@ -360,8 +360,8 @@ pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method] Επιστρέφει και αφαιρεί την τιμή του στοιχείου από τον πίνακα. Αν δεν υπάρχει, ρίχνει μια εξαίρεση, ή επιστρέφει την τιμή `$default`, αν έχει καθοριστεί. ```php -$array = [1 => 'foo', null => 'bar']; -$a = Arrays::pick($array, null); +$array = [1 => 'foo', 'x' => 'bar']; +$a = Arrays::pick($array, 'x'); // $a = 'bar' $b = Arrays::pick($array, 'not-exists', 'foobar'); // $b = 'foobar' diff --git a/utils/en/arrays.texy b/utils/en/arrays.texy index a14be68d17..c6abf68903 100644 --- a/utils/en/arrays.texy +++ b/utils/en/arrays.texy @@ -360,8 +360,8 @@ pick(array &$array, string|int $key, mixed $default=null): mixed .[method] Returns and removes the value of an item with key `$key` from an array. If the item does not exist, it throws an exception, or returns `$default` if provided. ```php -$array = [1 => 'foo', null => 'bar']; -$a = Arrays::pick($array, null); +$array = [1 => 'foo', 'x' => 'bar']; +$a = Arrays::pick($array, 'x'); // $a = 'bar' $b = Arrays::pick($array, 'not-exists', 'foobar'); // $b = 'foobar' diff --git a/utils/es/arrays.texy b/utils/es/arrays.texy index 062f6a39d4..39497de06e 100644 --- a/utils/es/arrays.texy +++ b/utils/es/arrays.texy @@ -360,8 +360,8 @@ pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method] Devuelve y elimina el valor de un elemento del array. Si no existe, lanza una excepción, o devuelve el valor `$default` si se especifica. ```php -$array = [1 => 'foo', null => 'bar']; -$a = Arrays::pick($array, null); +$array = [1 => 'foo', 'x' => 'bar']; +$a = Arrays::pick($array, 'x'); // $a = 'bar' $b = Arrays::pick($array, 'not-exists', 'foobar'); // $b = 'foobar' diff --git a/utils/fr/arrays.texy b/utils/fr/arrays.texy index a084df7709..140b2e2cc8 100644 --- a/utils/fr/arrays.texy +++ b/utils/fr/arrays.texy @@ -360,8 +360,8 @@ pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method] Retourne et supprime la valeur de l'élément du tableau. S'il n'existe pas, lève une exception, ou retourne la valeur `$default` si elle est spécifiée. ```php -$array = [1 => 'foo', null => 'bar']; -$a = Arrays::pick($array, null); +$array = [1 => 'foo', 'x' => 'bar']; +$a = Arrays::pick($array, 'x'); // $a = 'bar' $b = Arrays::pick($array, 'not-exists', 'foobar'); // $b = 'foobar' diff --git a/utils/hu/arrays.texy b/utils/hu/arrays.texy index 2a76d0ea3b..a25bf3e74f 100644 --- a/utils/hu/arrays.texy +++ b/utils/hu/arrays.texy @@ -360,8 +360,8 @@ pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method] Visszaadja és eltávolítja az elem értékét a tömbből. Ha nem létezik, kivételt dob, vagy visszaadja a `$default` értéket, ha meg van adva. ```php -$array = [1 => 'foo', null => 'bar']; -$a = Arrays::pick($array, null); +$array = [1 => 'foo', 'x' => 'bar']; +$a = Arrays::pick($array, 'x'); // $a = 'bar' $b = Arrays::pick($array, 'not-exists', 'foobar'); // $b = 'foobar' diff --git a/utils/it/arrays.texy b/utils/it/arrays.texy index 1d60931cee..c2b6c5ae5c 100644 --- a/utils/it/arrays.texy +++ b/utils/it/arrays.texy @@ -360,8 +360,8 @@ pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method] Restituisce e rimuove il valore di un elemento dall'array. Se non esiste, lancia un'eccezione o restituisce il valore `$default`, se specificato. ```php -$array = [1 => 'foo', null => 'bar']; -$a = Arrays::pick($array, null); +$array = [1 => 'foo', 'x' => 'bar']; +$a = Arrays::pick($array, 'x'); // $a = 'bar' $b = Arrays::pick($array, 'not-exists', 'foobar'); // $b = 'foobar' diff --git a/utils/ja/arrays.texy b/utils/ja/arrays.texy index adb4a9385c..090e2f6646 100644 --- a/utils/ja/arrays.texy +++ b/utils/ja/arrays.texy @@ -360,8 +360,8 @@ pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method] 配列から要素の値を返して削除します。存在しない場合は例外をスローするか、`$default` が指定されている場合はその値を返します。 ```php -$array = [1 => 'foo', null => 'bar']; -$a = Arrays::pick($array, null); +$array = [1 => 'foo', 'x' => 'bar']; +$a = Arrays::pick($array, 'x'); // $a = 'bar' $b = Arrays::pick($array, 'not-exists', 'foobar'); // $b = 'foobar' diff --git a/utils/pl/arrays.texy b/utils/pl/arrays.texy index 03b7309a65..7273b72ee4 100644 --- a/utils/pl/arrays.texy +++ b/utils/pl/arrays.texy @@ -360,8 +360,8 @@ pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method] Zwraca i usuwa wartość elementu z tablicy. Jeśli nie istnieje, rzuca wyjątek lub zwraca wartość `$default`, jeśli jest podana. ```php -$array = [1 => 'foo', null => 'bar']; -$a = Arrays::pick($array, null); +$array = [1 => 'foo', 'x' => 'bar']; +$a = Arrays::pick($array, 'x'); // $a = 'bar' $b = Arrays::pick($array, 'not-exists', 'foobar'); // $b = 'foobar' diff --git a/utils/pt/arrays.texy b/utils/pt/arrays.texy index a5081dbad6..bef58ccebb 100644 --- a/utils/pt/arrays.texy +++ b/utils/pt/arrays.texy @@ -360,8 +360,8 @@ pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method] Retorna e remove o valor de um elemento do array. Se não existir, lança uma exceção ou retorna o valor `$default`, se fornecido. ```php -$array = [1 => 'foo', null => 'bar']; -$a = Arrays::pick($array, null); +$array = [1 => 'foo', 'x' => 'bar']; +$a = Arrays::pick($array, 'x'); // $a = 'bar' $b = Arrays::pick($array, 'not-exists', 'foobar'); // $b = 'foobar' diff --git a/utils/ro/arrays.texy b/utils/ro/arrays.texy index 2f998eb83a..cae59f62dd 100644 --- a/utils/ro/arrays.texy +++ b/utils/ro/arrays.texy @@ -360,8 +360,8 @@ pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method] Returnează și elimină valoarea unui element din array. Dacă nu există, aruncă o excepție sau returnează valoarea `$default`, dacă este specificată. ```php -$array = [1 => 'foo', null => 'bar']; -$a = Arrays::pick($array, null); +$array = [1 => 'foo', 'x' => 'bar']; +$a = Arrays::pick($array, 'x'); // $a = 'bar' $b = Arrays::pick($array, 'not-exists', 'foobar'); // $b = 'foobar' diff --git a/utils/ru/arrays.texy b/utils/ru/arrays.texy index 4ba819ae5b..dec3f21649 100644 --- a/utils/ru/arrays.texy +++ b/utils/ru/arrays.texy @@ -360,8 +360,8 @@ pick(array &$array, string|int $key, mixed $default=null): mixed .[method] Возвращает и удаляет значение элемента из массива. Если он не существует, выбрасывает исключение, или возвращает значение `$default`, если оно указано. ```php -$array = [1 => 'foo', null => 'bar']; -$a = Arrays::pick($array, null); +$array = [1 => 'foo', 'x' => 'bar']; +$a = Arrays::pick($array, 'x'); // $a = 'bar' $b = Arrays::pick($array, 'not-exists', 'foobar'); // $b = 'foobar' diff --git a/utils/sl/arrays.texy b/utils/sl/arrays.texy index c9c044f98c..9c82a7842c 100644 --- a/utils/sl/arrays.texy +++ b/utils/sl/arrays.texy @@ -360,8 +360,8 @@ pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method] Vrne in odstrani vrednost elementa iz polja. Če ne obstaja, sproži izjemo ali vrne vrednost `$default`, če je podana. ```php -$array = [1 => 'foo', null => 'bar']; -$a = Arrays::pick($array, null); +$array = [1 => 'foo', 'x' => 'bar']; +$a = Arrays::pick($array, 'x'); // $a = 'bar' $b = Arrays::pick($array, 'not-exists', 'foobar'); // $b = 'foobar' diff --git a/utils/tr/arrays.texy b/utils/tr/arrays.texy index aa7941b653..e47a08a863 100644 --- a/utils/tr/arrays.texy +++ b/utils/tr/arrays.texy @@ -360,8 +360,8 @@ pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method] Bir öğenin değerini diziden döndürür ve kaldırır. Eğer mevcut değilse, istisna fırlatır veya belirtilmişse `$default` değerini döndürür. ```php -$array = [1 => 'foo', null => 'bar']; -$a = Arrays::pick($array, null); +$array = [1 => 'foo', 'x' => 'bar']; +$a = Arrays::pick($array, 'x'); // $a = 'bar' $b = Arrays::pick($array, 'not-exists', 'foobar'); // $b = 'foobar' diff --git a/utils/uk/arrays.texy b/utils/uk/arrays.texy index 6d3a4bf31f..2a0e7fc547 100644 --- a/utils/uk/arrays.texy +++ b/utils/uk/arrays.texy @@ -360,8 +360,8 @@ pick(array &$array, string|int $key, ?mixed $default=null): mixed .[method] Повертає та видаляє значення елемента з масиву. Якщо він не існує, викликає виняток або повертає значення `$default`, якщо воно вказане. ```php -$array = [1 => 'foo', null => 'bar']; -$a = Arrays::pick($array, null); +$array = [1 => 'foo', 'x' => 'bar']; +$a = Arrays::pick($array, 'x'); // $a = 'bar' $b = Arrays::pick($array, 'not-exists', 'foobar'); // $b = 'foobar' From 013e82769b82d267ab9db889e5ad29f129447579 Mon Sep 17 00:00:00 2001 From: Jan Tojnar <jtojnar@gmail.com> Date: Sun, 28 Sep 2025 01:44:13 +0200 Subject: [PATCH 05/50] typo [Closes #1081] --- latte/bg/type-system.texy | 4 ++-- latte/cs/type-system.texy | 4 ++-- latte/de/type-system.texy | 4 ++-- latte/el/type-system.texy | 4 ++-- latte/en/type-system.texy | 4 ++-- latte/es/type-system.texy | 4 ++-- latte/fr/type-system.texy | 4 ++-- latte/hu/type-system.texy | 4 ++-- latte/it/type-system.texy | 4 ++-- latte/ja/type-system.texy | 4 ++-- latte/pl/type-system.texy | 4 ++-- latte/pt/type-system.texy | 4 ++-- latte/ro/type-system.texy | 4 ++-- latte/ru/type-system.texy | 4 ++-- latte/sl/type-system.texy | 4 ++-- latte/tr/type-system.texy | 4 ++-- latte/uk/type-system.texy | 4 ++-- 17 files changed, 34 insertions(+), 34 deletions(-) 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/type-system.texy b/latte/cs/type-system.texy index 0454b2743d..7dcf6e8dce 100644 --- a/latte/cs/type-system.texy +++ b/latte/cs/type-system.texy @@ -21,7 +21,7 @@ Jak začít používat typy? Vytvořte si třídu šablony, např. `CatalogTempl 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( )); ``` -A dále na začátek šablony vložte značku `{templateType}` s plným názvem třídy (včetně namespace). To definuje, že v šabloně jsou proměnné `$langs` a `$products` včetně příslušných typů. Typy lokálních proměnných můžete uvést pomocí značek [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Definice]. +A dále na začátek šablony vložte značku `{templateType}` s plným názvem třídy (včetně namespace). To definuje, že v šabloně jsou proměnné `$lang` a `$products` včetně příslušných typů. Typy lokálních proměnných můžete uvést pomocí značek [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Definice]. Od té chvíle vám může IDE správně našeptávat. 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/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/type-system.texy b/latte/en/type-system.texy index 8b7dfd642e..eac2758138 100644 --- a/latte/en/type-system.texy +++ b/latte/en/type-system.texy @@ -21,7 +21,7 @@ How to start using types? Create a template class, e.g., `CatalogTemplateParamet 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( )); ``` -Then insert the `{templateType}` tag with the full class name (including the namespace) at the beginning of the template. This defines that the variables `$langs` and `$products` exist in the template, including their respective types. You can also specify the types of local variables using the [`{var}` |tags#var-default], `{varType}`, and [`{define}` |template-inheritance#Definitions] tags. +Then insert the `{templateType}` tag with the full class name (including the namespace) at the beginning of the template. This defines that the variables `$lang` and `$products` exist in the template, including their respective types. You can also specify the types of local variables using the [`{var}` |tags#var-default], `{varType}`, and [`{define}` |template-inheritance#Definitions] tags. From this point on, your IDE can correctly provide autocompletion. 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/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/type-system.texy b/latte/hu/type-system.texy index b2dcceee31..b2e09d3024 100644 --- a/latte/hu/type-system.texy +++ b/latte/hu/type-system.texy @@ -21,7 +21,7 @@ Hogyan kezdjük el használni a típusokat? Hozzon létre egy sablonosztályt, p 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( )); ``` -Ezután a sablon elejére illessze be a `{templateType}` taget az osztály teljes nevével (beleértve a névteret is). Ez definiálja, hogy a sablonban a `$langs` és `$products` változók a megfelelő típusokkal együtt léteznek. A lokális változók típusait a [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Definíciók define] tagekkel adhatja meg. +Ezután a sablon elejére illessze be a `{templateType}` taget az osztály teljes nevével (beleértve a névteret is). Ez definiálja, hogy a sablonban a `$lang` és `$products` változók a megfelelő típusokkal együtt léteznek. A lokális változók típusait a [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Definíciók define] tagekkel adhatja meg. Ettől kezdve az IDE helyesen tud súgni. diff --git a/latte/it/type-system.texy b/latte/it/type-system.texy index ae98829c21..a5fb971b3c 100644 --- a/latte/it/type-system.texy +++ b/latte/it/type-system.texy @@ -21,7 +21,7 @@ Come iniziare a usare i tipi? Create una classe di template, ad es. `CatalogTemp 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( )); ``` -Quindi, all'inizio del template, inserite il tag `{templateType}` con il nome completo della classe (incluso il namespace). Questo definisce che nel template ci sono le variabili `$langs` e `$products` con i rispettivi tipi. Potete specificare i tipi delle variabili locali usando i tag [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Definizioni define]. +Quindi, all'inizio del template, inserite il tag `{templateType}` con il nome completo della classe (incluso il namespace). Questo definisce che nel template ci sono le variabili `$lang` e `$products` con i rispettivi tipi. Potete specificare i tipi delle variabili locali usando i tag [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Definizioni define]. Da quel momento, l'IDE può suggerire correttamente. diff --git a/latte/ja/type-system.texy b/latte/ja/type-system.texy index 74a8f15022..0f93ddc900 100644 --- a/latte/ja/type-system.texy +++ b/latte/ja/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}` タグを挿入します。これにより、テンプレート内に変数 `$langs` と `$products` が、対応する型とともに定義されます。ローカル変数の型は、[`{var}` |tags#var default]、`{varType}`、[`{define}` |template-inheritance#Definitions] タグを使用して指定できます。 +次に、テンプレートの先頭に、クラスの完全な名前(名前空間を含む)を持つ `{templateType}` タグを挿入します。これにより、テンプレート内に変数 `$lang` と `$products` が、対応する型とともに定義されます。ローカル変数の型は、[`{var}` |tags#var default]、`{varType}`、[`{define}` |template-inheritance#Definitions] タグを使用して指定できます。 その時点から、IDEは正しく補完できるようになります。 diff --git a/latte/pl/type-system.texy b/latte/pl/type-system.texy index 3715e6a9d5..9f19e935d9 100644 --- a/latte/pl/type-system.texy +++ b/latte/pl/type-system.texy @@ -21,7 +21,7 @@ Jak zacząć używać typów? Utwórz klasę szablonu, np. `CatalogTemplateParam 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( )); ``` -A następnie na początku szablonu wstaw tag `{templateType}` z pełną nazwą klasy (włącznie z namespace). To definiuje, że w szablonie są zmienne `$langs` i `$products` wraz z odpowiednimi typami. Typy zmiennych lokalnych możesz podać za pomocą tagów [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Definicje define]. +A następnie na początku szablonu wstaw tag `{templateType}` z pełną nazwą klasy (włącznie z namespace). To definiuje, że w szablonie są zmienne `$lang` i `$products` wraz z odpowiednimi typami. Typy zmiennych lokalnych możesz podać za pomocą tagów [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Definicje define]. Od tego momentu IDE może poprawnie podpowiadać. diff --git a/latte/pt/type-system.texy b/latte/pt/type-system.texy index 110047b4b4..9baf8bb9f8 100644 --- a/latte/pt/type-system.texy +++ b/latte/pt/type-system.texy @@ -21,7 +21,7 @@ Como começar a usar tipos? Crie uma classe de template, por exemplo, `CatalogTe 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( )); ``` -E, em seguida, no início do template, insira a tag `{templateType}` com o nome completo da classe (incluindo o namespace). Isso define que no template existem as variáveis `$langs` e `$products`, incluindo os tipos correspondentes. Você pode especificar os tipos de variáveis locais usando as tags [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Definições]. +E, em seguida, no início do template, insira a tag `{templateType}` com o nome completo da classe (incluindo o namespace). Isso define que no template existem as variáveis `$lang` e `$products`, incluindo os tipos correspondentes. Você pode especificar os tipos de variáveis locais usando as tags [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Definições]. A partir desse momento, o IDE pode sugerir corretamente. diff --git a/latte/ro/type-system.texy b/latte/ro/type-system.texy index fc64e5ef84..508abcd9ee 100644 --- a/latte/ro/type-system.texy +++ b/latte/ro/type-system.texy @@ -21,7 +21,7 @@ Cum să începeți să utilizați tipurile? Creați o clasă de șablon, de exem 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( )); ``` -Și apoi, la începutul șablonului, introduceți tag-ul `{templateType}` cu numele complet al clasei (inclusiv namespace). Acest lucru definește că în șablon există variabilele `$langs` și `$products` inclusiv tipurile corespunzătoare. Tipurile variabilelor locale pot fi specificate folosind tag-urile [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Definiții define]. +Și apoi, la începutul șablonului, introduceți tag-ul `{templateType}` cu numele complet al clasei (inclusiv namespace). Acest lucru definește că în șablon există variabilele `$lang` și `$products` inclusiv tipurile corespunzătoare. Tipurile variabilelor locale pot fi specificate folosind tag-urile [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Definiții define]. Din acel moment, IDE-ul vă poate oferi sugestii corecte. diff --git a/latte/ru/type-system.texy b/latte/ru/type-system.texy index 875667cde2..ab6a5a5d6f 100644 --- a/latte/ru/type-system.texy +++ b/latte/ru/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}` с полным именем класса (включая пространство имен). Это определяет, что в шаблоне есть переменные `$langs` и `$products` с соответствующими типами. Типы локальных переменных можно указать с помощью тегов [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Определения]. +А затем в начало шаблона вставьте тег `{templateType}` с полным именем класса (включая пространство имен). Это определяет, что в шаблоне есть переменные `$lang` и `$products` с соответствующими типами. Типы локальных переменных можно указать с помощью тегов [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Определения]. С этого момента IDE сможет правильно подсказывать. diff --git a/latte/sl/type-system.texy b/latte/sl/type-system.texy index 09f661778b..e814b63fd0 100644 --- a/latte/sl/type-system.texy +++ b/latte/sl/type-system.texy @@ -21,7 +21,7 @@ Kako začeti uporabljati tipe? Ustvarite si razred predloge, npr. `CatalogTempla 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( )); ``` -Nato na začetek predloge vstavite značko `{templateType}` s polnim imenom razreda (vključno z imenskim prostorom). To definira, da so v predlogi spremenljivke `$langs` in `$products` vključno z ustreznimi tipi. Tipe lokalnih spremenljivk lahko navedete s pomočjo značk [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Definicije]. +Nato na začetek predloge vstavite značko `{templateType}` s polnim imenom razreda (vključno z imenskim prostorom). To definira, da so v predlogi spremenljivke `$lang` in `$products` vključno z ustreznimi tipi. Tipe lokalnih spremenljivk lahko navedete s pomočjo značk [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Definicije]. Od takrat vam lahko IDE pravilno predlaga. diff --git a/latte/tr/type-system.texy b/latte/tr/type-system.texy index 005ce71f91..eaf4424ee5 100644 --- a/latte/tr/type-system.texy +++ b/latte/tr/type-system.texy @@ -21,7 +21,7 @@ Tipleri kullanmaya nasıl başlanır? İletilen parametreleri, tiplerini ve muht 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( )); ``` -Ve ardından şablonun başına `{templateType}` etiketini sınıfın tam adıyla (ad alanı dahil) ekleyin. Bu, şablonda `$langs` ve `$products` değişkenlerinin ilgili tipleriyle birlikte bulunduğunu tanımlar. Yerel değişkenlerin tiplerini [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Tanımlar] etiketlerini kullanarak belirtebilirsiniz. +Ve ardından şablonun başına `{templateType}` etiketini sınıfın tam adıyla (ad alanı dahil) ekleyin. Bu, şablonda `$lang` ve `$products` değişkenlerinin ilgili tipleriyle birlikte bulunduğunu tanımlar. Yerel değişkenlerin tiplerini [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Tanımlar] etiketlerini kullanarak belirtebilirsiniz. O andan itibaren IDE size doğru önerilerde bulunabilir. diff --git a/latte/uk/type-system.texy b/latte/uk/type-system.texy index 9d6c08535b..14ea265b99 100644 --- a/latte/uk/type-system.texy +++ b/latte/uk/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}` з повною назвою класу (включаючи простір імен). Це визначає, що в шаблоні є змінні `$langs` та `$products` з відповідними типами. Типи локальних змінних можна вказати за допомогою тегів [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Визначення]. +А далі на початку шаблону вставте тег `{templateType}` з повною назвою класу (включаючи простір імен). Це визначає, що в шаблоні є змінні `$lang` та `$products` з відповідними типами. Типи локальних змінних можна вказати за допомогою тегів [`{var}` |tags#var default], `{varType}`, [`{define}` |template-inheritance#Визначення]. З цього моменту ваше IDE може правильно підказувати. From 9ed9b6392bbd6b10dc3e517b4d58e05235c1f0f8 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Wed, 26 Nov 2025 14:24:57 +0100 Subject: [PATCH 06/50] latte 3.1.0 --- application/cs/templates.texy | 2 +- application/en/templates.texy | 2 +- latte/cs/@left-menu.texy | 1 + latte/cs/cookbook/@home.texy | 1 + .../cs/cookbook/migration-from-latte-30.texy | 109 +++++++++++++ latte/cs/custom-filters.texy | 24 --- latte/cs/custom-tags.texy | 2 +- latte/cs/develop.texy | 32 +++- latte/cs/extending-latte.texy | 7 - latte/cs/filters.texy | 41 +++++ latte/cs/html-attributes.texy | 151 ++++++++++++++++++ latte/cs/syntax.texy | 39 ++++- latte/cs/tags.texy | 19 ++- latte/en/@left-menu.texy | 1 + latte/en/cookbook/@home.texy | 1 + .../en/cookbook/migration-from-latte-30.texy | 110 +++++++++++++ latte/en/custom-filters.texy | 24 --- latte/en/custom-tags.texy | 2 +- latte/en/develop.texy | 32 +++- latte/en/extending-latte.texy | 7 - latte/en/filters.texy | 41 +++++ latte/en/html-attributes.texy | 151 ++++++++++++++++++ latte/en/syntax.texy | 39 ++++- latte/en/tags.texy | 21 ++- latte/files/html-attributes.webp | Bin 0 -> 11126 bytes 25 files changed, 772 insertions(+), 87 deletions(-) create mode 100644 latte/cs/cookbook/migration-from-latte-30.texy create mode 100644 latte/cs/html-attributes.texy create mode 100644 latte/en/cookbook/migration-from-latte-30.texy create mode 100644 latte/en/html-attributes.texy create mode 100644 latte/files/html-attributes.webp diff --git a/application/cs/templates.texy b/application/cs/templates.texy index 4ded503e34..feb0346ea4 100644 --- a/application/cs/templates.texy +++ b/application/cs/templates.texy @@ -215,7 +215,7 @@ public function beforeRender(): void // nebo konfigurujeme přímo objekt Latte\Engine $latte = $this->template->getLatte(); - $latte->addFilterLoader(/* ... */); + $latte->setFeature(Latte\Feature::MigrationWarnings); } ``` diff --git a/application/en/templates.texy b/application/en/templates.texy index 2950a8f35c..90f641d221 100644 --- a/application/en/templates.texy +++ b/application/en/templates.texy @@ -215,7 +215,7 @@ public function beforeRender(): void // or configure the Latte\Engine object directly $latte = $this->template->getLatte(); - $latte->addFilterLoader(/* ... */); + $latte->setFeature(Latte\Feature::MigrationWarnings); } ``` 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 +<div class="{$var|accept}"></div> +``` + +Pokud chcete atribut zachovat jako prázdný (např. `title=""`) místo jeho vynechání, použijte null coalescing operátor: + +```latte +<div title={$var ?? ''}></div> +``` + +Nebo, pokud striktně vyžadujete staré chování (např. `"1"` pro `true`), explicitně přetypujte hodnotu na string: + +```latte +<div data-foo={(string) $bool}></div> +``` + +**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 `<div n:if={$cond}>` bez uvozovek. +- **Toggle filtr:** Použijte `|toggle` pro ruční ovládání boolean atributů. diff --git a/latte/cs/custom-filters.texy b/latte/cs/custom-filters.texy index 562d8fd802..7f7cab0c0c 100644 --- a/latte/cs/custom-filters.texy +++ b/latte/cs/custom-filters.texy @@ -117,30 +117,6 @@ $latte->addExtension(new App\Latte\MyLatteExtension); Tento přístup udrží logiku vašeho filtru zapouzdřenou a registraci jednoduchou. -Použití načítače filtrů ------------------------ - -Latte umožňuje registrovat načítač filtrů pomocí `addFilterLoader()`. Jde o jediné volatelné callable, které Latte požádá o jakýkoliv neznámý název filtru během kompilace. Načítač vrací PHP callable filtru nebo `null`. - -```php -$latte = new Latte\Engine; - -// Načítač může dynamicky vytvářet/získávat callable filtry -$latte->addFilterLoader(function (string $name): ?callable { - if ($name === 'myLazyFilter') { - // Představte si zde náročnou inicializaci... - $service = get_some_expensive_service(); - return fn($value) => $service->process($value); - } - return null; -}); -``` - -Tato metoda byla primárně určena pro líné načítání filtrů s velmi **náročnou inicializací**. Avšak moderní praktiky vkládání závislostí (dependency injection) obvykle zvládají líné služby efektivněji. - -Načítače filtrů přidávají složitost a obecně se nedoporučují ve prospěch přímé registrace pomocí `addFilter()` nebo v rámci rozšíření pomocí `getFilters()`. Používejte načítače pouze pokud máte závažný, specifický důvod související s výkonnostními problémy při inicializaci filtrů, které nelze řešit jinak. - - Filtry používající třídu s atributy ----------------------------------- diff --git a/latte/cs/custom-tags.texy b/latte/cs/custom-tags.texy index bb55513f56..7d41e7799d 100644 --- a/latte/cs/custom-tags.texy +++ b/latte/cs/custom-tags.texy @@ -1004,7 +1004,7 @@ Zástupné symboly `PrintContext::format()` - `$argsNode = new ArrayNode([...]);` - `$context->format('myFunc(%args);', $argsNode)` -> `myFunc(1, name: 'Joe');` - **`%line`**: Argument musí být objekt `Position` (obvykle `$this->position`). Vkládá PHP komentář `/* line X */` indikující číslo řádku zdroje. - - `$context->format('echo "Hi" %line;', $this->position)` -> `echo "Hi" /* line 42 */;` + - `$context->format('echo "Hi" %line;', $this->position)` -> `echo "Hi" /* line 42:1 */;` - **`%escape(...)`**: Generuje PHP kód, který *za běhu* escapuje vnitřní výraz pomocí aktuálních kontextově uvědomělých pravidel escapování. - `$context->format('echo %escape(%node);', $variableNode)` - **`%modify(...)`**: Argument musí být `ModifierNode`. Generuje PHP kód, který aplikuje filtry specifikované v `ModifierNode` na vnitřní obsah, včetně kontextově uvědomělého escapování, pokud není zakázáno pomocí `|noescape`. diff --git a/latte/cs/develop.texy b/latte/cs/develop.texy index 273e85ad47..28f0d64892 100644 --- a/latte/cs/develop.texy +++ b/latte/cs/develop.texy @@ -15,7 +15,8 @@ Podporované verze PHP (platí pro poslední setinkové verze Latte): | verze | kompatibilní s PHP |-----------------|------------------- -| Latte 3.0 | PHP 8.0 – 8.2 +| Latte 3.1 | PHP 8.2 – 8.5 +| Latte 3.0 | PHP 8.0 – 8.5 Jak vykreslit šablonu @@ -193,6 +194,27 @@ $latte = new Latte\Engine; $latte->setStrictTypes(); ``` +.[note] +Od verze Latte 3.1 jsou strict types povoleny ve výchozím nastavení. Můžete je deaktivovat pomocí `$latte->setStrictTypes(false)`. + + +Migrační varování .{data-version:3.1} +===================================== + +Latte 3.1 mění chování některých [HTML atributů|html-attributes]. Například hodnoty `null` nyní odstraní atribut namísto vypsání prázdného řetězce. Abyste snadno našli místa, kde tato změna ovlivňuje vaše šablony, můžete zapnout varování o migraci: + +```php +$latte->setFeature(Latte\Feature::MigrationWarnings); +``` + +Pokud je toto zapnuto, Latte kontroluje vykreslované atributy a vyvolá uživatelské varování (`E_USER_WARNING`), pokud se výstup liší od toho, co by Latte 3.0 vygenerovalo. Když narazíte na varování, použijte jedno z těchto řešení: + +1. Pokud je nový výstup pro váš případ použití správný (např. preferujete, aby atribut zmizel při `null`), potlačte varování přidáním filtru `|accept` +2. Pokud chcete, aby byl atribut vykreslen jako prázdný (např. `title=""`) namísto odstranění, když je proměnná `null`, poskytněte prázdný řetězec jako zálohu: `title={$val ?? ''}` +3. Pokud striktně vyžadujete staré chování (např. vypsání `"1"` pro `true` namísto `"true"`), explicitně přetypujte hodnotu na řetězec: `data-foo={(string) $val}` + +Jakmile jsou všechna varování vyřešena, vypněte varování o migraci a **odstraňte všechny** filtry `|accept` ze svých šablon, protože již nejsou potřeba. + Překládání v šablonách .{toc: TranslatorExtension} ================================================== @@ -266,7 +288,9 @@ Jelikož Latte kompiluje šablony do přehledného PHP kódu, můžete je pohodl 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: +Ke kontrole všech šablon slouží nástroj **Linter**. Jeho úkolem je projít zadané soubory a ověřit, že neobsahují syntaktické chyby ani odkazy na neexistující značky, filtry, funkce, třídy apod. + +Linter se spouští z příkazové řádky: ```shell vendor/bin/latte-lint <cesta> @@ -274,7 +298,7 @@ vendor/bin/latte-lint <cesta> Parametrem `--strict` aktivujete [#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, filtry nebo další rozšíření Latte, je potřeba vytvořit si vlastní variantu Linteru, například `custom-latte-lint`. V té zaregistrujete všechna potřebná rozšíření ještě před samotnou validací šablon: ```php #!/usr/bin/env php @@ -302,6 +326,8 @@ $latte = new Latte\Engine; $linter = new Latte\Tools\Linter(engine: $latte); ``` +Takto přizpůsobený linter pak můžete používat stejným způsobem jako standardní nástroj, ale s plnou znalostí vašich vlastních rozšíření. + Načítání šablon z řetězce ========================= diff --git a/latte/cs/extending-latte.texy b/latte/cs/extending-latte.texy index e155953867..a378ff8cf0 100644 --- a/latte/cs/extending-latte.texy +++ b/latte/cs/extending-latte.texy @@ -44,13 +44,6 @@ $latte->addFilter('truncate', $myTruncate); // Použití v šabloně: {$text|truncate} nebo {$text|truncate:100} ``` -Můžete také zaregistrovat **Filter Loader**, funkci, která dynamicky poskytuje volatelné objekty filtrů podle požadovaného názvu: - -```php -$latte->addFilterLoader(fn(string $name) => /* vrátí volatelný objekt nebo null */); -``` - - Pro registraci funkce použitelné ve výrazech šablony použijte `addFunction()`. ```php diff --git a/latte/cs/filters.texy b/latte/cs/filters.texy index f7159ffd25..bcce55ae3e 100644 --- a/latte/cs/filters.texy +++ b/latte/cs/filters.texy @@ -55,6 +55,11 @@ V šablonách můžeme používat funkce, které pomáhají upravit nebo přefor | `floor` | [zaokrouhlí číslo dolů na danou přesnost |#floor] | `round` | [zaokrouhlí číslo na danou přesnost |#round] +.[table-latte-filters] +|## HTML atributy +| `accept` | [potvrzuje nové chování chytrých atributů |#accept] +| `toggle` | [přepíná přítomnost HTML atributu |#toggle] + .[table-latte-filters] |## Escapování | `escapeUrl` | [escapuje parametr v URL |#escapeUrl] @@ -117,10 +122,31 @@ V šabloně se potom volá takto: ``` +Nullsafe filtry .{data-version:3.1} +----------------------------------- + +Jakýkoliv filtr lze učinit nullsafe použitím `?|` místo `|`. Pokud je hodnota `null`, filtr se nevykoná a vrátí se `null`. Filtry následující v řetězci jsou také přeskočeny. + +To je užitečné v kombinaci s HTML atributy, které jsou vynechány, pokud je hodnota `null`. + +```latte +<div title={$title?|upper}> +{* Pokud je $title null: <div> *} +{* Pokud je $title 'hello': <div title="HELLO"> *} +``` + + Filtry ====== +accept .[filter]{data-version:3.1} +---------------------------------- +Filtr se používá při [migraci z Latte 3.0|cookbook/migration-from-latte-30] k potvrzení, že jste zkontrolovali změnu chování atributu a akceptujete ji. Nemění hodnotu. + +Jde o dočasný nástroj. Jakmile je migrace dokončena a varování při migraci jsou vypnuta, měli byste tento filtr ze svých šablon odstranit. + + 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. @@ -827,6 +853,21 @@ Extrahuje část řetězce. Tento filtr byl nahrazen filtrem [#slice]. ``` +toggle .[filter]{data-version:3.1} +---------------------------------- +Filtr `toggle` ovládá přítomnost atributu na základě boolean hodnoty. Pokud je hodnota truthy, atribut je přítomen; pokud je falsy, atribut je zcela vynechán: + +```latte +<div uk-grid={$isGrid|toggle}> +{* Pokud je $isGrid truthy: <div uk-grid> *} +{* Pokud je $isGrid falsy: <div> *} +``` + +Tento filtr je užitečný pro vlastní atributy nebo atributy JavaScriptových knihoven, které vyžadují kontrolu přítomnosti/nepřítomnosti podobně jako HTML boolean atributy. + +Filtr lze použít pouze uvnitř HTML atributů. + + translate(...$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]. diff --git a/latte/cs/html-attributes.texy b/latte/cs/html-attributes.texy new file mode 100644 index 0000000000..e9632b2586 --- /dev/null +++ b/latte/cs/html-attributes.texy @@ -0,0 +1,151 @@ +Chytré HTML atributy +******************** + +.[perex] +Latte 3.1 přichází se sadou vylepšení, která se zaměřuje na jednu z nejčastějších činností v šablonách – vypisování HTML atributů. Přináší více pohodlí, flexibility a bezpečnosti. + + +Boolean atributy +================ + +HTML používá speciální atributy jako `checked`, `disabled`, `selected` nebo `hidden`, u kterých nezáleží na konkrétní hodnotě – pouze na jejich přítomnosti. Fungují jako jednoduché příznaky. + +Latte je zpracovává automaticky. Atributu můžete předat jakýkoliv výraz. Pokud je pravdivý (truthy), atribut se vykreslí. Pokud je nepravdivý (falsey - např. `false`, `null`, `0` nebo prázdný řetězec), atribut se zcela vynechá. + +To znamená, že se můžete rozloučit se složitými podmínkami nebo `n:attr` a jednoduše použít: + +```latte +<input type="text" disabled={$isDisabled} readonly={$isReadOnly}> +``` + +Pokud `$isDisabled` je `false` a `$isReadOnly` je `true`, vykreslí se: + +```latte +<input type="text" readonly> +``` + +Pokud potřebujete přepínací chování pro standardní atributy, které nemají toto automatické zpracování (tedy např. atributy `data-` nebo `aria-`), použijte filtr [toggle |filters#toggle]. + + +Hodnoty null +============ + +Toto je jedna z nejpříjemnějších změn. Dříve, pokud byla proměnná `null`, vypsala se jako prázdný řetězec `""`. To často vedlo k prázdným atributům v HTML jako `class=""` nebo `title=""`. + +V Latte 3.1 platí nové univerzální pravidlo: **Hodnota `null` znamená, že atribut neexistuje.** + +```latte +<div title="{$title}"></div> +``` + +Pokud `$title` je `null`, výstupem je `<div></div>`. Pokud obsahuje řetězec, např. "Ahoj", výstupem je `<div title="Ahoj"></div>`. Díky tomu nemusíte obalovat atributy do podmínek. + +Pokud používáte filtry, mějte na paměti, že obvykle převádějí `null` na řetězec (např. prázdný řetězec). Abyste tomu zabránili, použijte [nullsafe filtr |filters#Nullsafe filtry] `?|`: + +```latte +<div title="{$title?|upper}"></div> +``` + + +Třídy (Classes) +=============== + +Atributu `class` můžete předat pole. To je ideální pro podmíněné třídy: pokud je pole asociativní, klíče se použijí jako názvy tříd a hodnoty jako podmínky. Třída se vykreslí pouze v případě, že je podmínka splněna. + +```latte +<button class={[ + btn, + btn-primary, + active => $isActive, +]}>Stiskni mě</button> +``` + +Pokud je `$isActive` true, vykreslí se: + +```latte +<button class="btn btn-primary active">Stiskni mě</button> +``` + +Toto chování není omezeno pouze na `class`. Funguje pro jakýkoliv HTML atribut, který očekává seznam hodnot oddělených mezerou, jako jsou `itemprop`, `rel`, `sandbox` atd. + +```latte +<a rel={[nofollow, noopener, external => $isExternal]}>odkaz</a> +``` + + +Styly (Styles) +============== + +Atribut `style` také podporuje pole. Je to obzvláště užitečné pro podmíněné styly. Pokud položka pole obsahuje klíč (CSS vlastnost) a hodnotu, vlastnost se vykreslí pouze v případě, že hodnota není `null`. + +```latte +<div style={[ + background => lightblue, + display => $isVisible ? block : null, + font-size => '16px', +]}></div> +``` + +Pokud je `$isVisible` false, vykreslí se: + +```latte +<div style="background: lightblue; font-size: 16px"></div> +``` + + +Data atributy +============= + +Často potřebujeme do HTML předat konfiguraci pro JavaScript. Dříve se to dělalo přes `json_encode`. Nyní můžete atributu `data-` jednoduše předat pole nebo objekt stdClass a Latte jej serializuje do JSONu: + +```latte +<div data-config={[ theme: dark, version: 2 ]}></div> +``` + +Vypíše: + +```latte +<div data-config='{"theme":"dark","version":2}'></div> +``` + +Také `true` a `false` se vykreslují jako řetězce `"true"` a `"false"` (tj. validní JSON). + + +Aria atributy +============= + +Specifikace WAI-ARIA vyžaduje textové hodnoty `"true"` a `"false"` pro logické hodnoty. Latte to pro atributy `aria-` řeší automaticky: + +```latte +<button aria-expanded={=true} aria-checked={=false}></button> +``` + +Vypíše: + +```latte +<button aria-expanded="true" aria-checked="false"></button> +``` + + +Typová kontrola +=============== + +Už jste někdy viděli `<input value="Array">` ve svém vygenerovaném HTML? Je to klasická chyba, která často projde bez povšimnutí. Latte zavádí přísnou typovou kontrolu pro HTML atributy, aby byly vaše šablony vůči takovým přehlédnutím odolnější. + +Latte ví, které atributy jsou které a jaké hodnoty očekávají: + +- **Standardní atributy** (jako `href`, `id`, `value`, `placeholder`...) očekávají hodnotu, kterou lze vykreslit jako text. To zahrnuje řetězce, čísla nebo stringable objekty. Také je akceptováno `null` (atribut vynechá). Pokud však omylem předáte pole, boolean nebo obecný objekt, Latte vyvolá varování a neplatnou hodnotu inteligentně ignoruje. +- **Boolean atributy** (jako `checked`, `disabled`...) akceptují jakýkoliv typ, protože jejich přítomnost je určena logikou pravdivý/nepravdivý. +- **Chytré atributy** (jako `class`, `style`, `data-`...) specificky zpracovávají pole jako validní vstupy. + +Tato kontrola zajišťuje, že vaše aplikace nebude produkovat neočekávané HTML. + + +Migrace z Latte 3.0 +=================== + +Protože se změnilo chování `null` (dříve vypisovalo `""`, nyní atribut vynechá) a atributů `data-` (boolean hodnoty vypisovaly `"1"`/`""`, nyní `"true"`/`"false"`), možná budete muset aktualizovat své šablony. + +Pro hladký přechod poskytuje Latte migrační režim, který upozorňuje na rozdíly. Přečtěte si podrobného průvodce [Migrace z Latte 3.0 na 3.1 |cookbook/migration-from-latte-30]. + +[* html-attributes.webp *] diff --git a/latte/cs/syntax.texy b/latte/cs/syntax.texy index 0913d20fc7..1e21ab6dcf 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 `<div n:if="$foo">` můžete použít alternativní syntaxi se složenými závorkami `<div n:if={$foo}>`. Hlavní výhodou je, že uvnitř `{...}` můžete volně používat jednoduché i dvojité uvozovky: + +```latte +<div n:if={str_contains($val, "foo")}> ... </div> +``` + + +Chytré HTML atributy .{data-version:3.1} +======================================== + +Latte dělá práci se standardními HTML atributy neuvěřitelně snadnou. Za vás řeší boolean atributy jako `checked`, odstraňuje atributy obsahující `null` a umožňuje vám skládat hodnoty `class` a `style` pomocí polí. Dokonce automaticky serializuje data pro `data-` atributy do JSON. + +```latte +{* null odstraní atribut *} +<div title={$title}> + +{* boolean ovládá přítomnost boolean atributů *} +<input type="checkbox" checked={$isChecked}> + +{* pole fungují v class *} +<div class={['btn', 'btn-primary', active => $isActive]}> + +{* pole jsou JSON-enkódována v data- atributech *} +<div data-config={[theme: dark, version: 2]}> +``` + +Více informací v samostatné kapitole [Chytré HTML atributy|html-attributes]. + Filtry ====== @@ -148,10 +176,17 @@ Na blok: ``` Nebo přímo na hodnotu (v kombinaci s tagem [`{=expr}` |tags#Vypisování]): + ```latte <h1>{=' Hello world '|trim}<h1> ``` +Pokud může být hodnota `null` a chcete v takovém případě zabránit použití filtru, použijte [nullsafe filter |filters#Nullsafe Filters] `?|`: + +```latte +<h1>{$heading?|upper}</h1> +``` + Dynamické HTML značky .{data-version:3.0.9} =========================================== @@ -204,7 +239,7 @@ Jednoduché řetězce jsou ty, které jsou tvořeny čistě z písmen, číslic, Konstanty --------- -Jelikož lze u jednoduchých řetězců vynechávat uvozovky, doporučujeme pro odlišení zapisovat globální konstanty s lomítkem na začátku: +K rozlišení globálních konstant od jednoduchých řetězců použijte oddělovač globálního jmenného prostoru: ```latte {if \PROJECT_ID === 1} ... {/if} @@ -265,8 +300,6 @@ Historické okénko Latte přišlo v průběhu své historie s celou řadou syntaktických cukříků, které se po pár letech objevily v samotném PHP. Například v Latte bylo možné psát pole jako `[1, 2, 3]` místo `array(1, 2, 3)` nebo používat nullsafe operátor `$obj?->foo` dávno předtím, než to bylo možné v samotném PHP. Latte také zavedlo operátor pro rozbalení pole `(expand) $arr`, který je ekvivalentem dnešního operátoru `...$arr` z PHP. -Undefined-safe operator `??->`, což je obdoba nullsafe operatoru `?->`, který ale nevyvolá chybu, pokud proměnná neexistuje, vznikl z historických důvodů a dnes doporučujeme používat standardní PHP operátor `?->`. - Omezení PHP v Latte =================== diff --git a/latte/cs/tags.texy b/latte/cs/tags.texy index d302666d5a..598b2b73dd 100644 --- a/latte/cs/tags.texy +++ b/latte/cs/tags.texy @@ -16,7 +16,7 @@ Přehled a popis všech tagů (neboli značek či maker) šablonovacího systém | `{ifset}` … `{elseifset}` … `{/ifset}` | [podmínka ifset |#ifset elseifset] | `{ifchanged}` … `{/ifchanged}` | [test jestli došlo ke změně |#ifchanged] | `{switch}` `{case}` `{default}` `{/switch}` | [podmínka switch |#switch case default] -| `n:else` | [alternativní obsah pro podmínky |#n:else] +| `n:else`, `n:elseif` | [alternativní obsah pro podmínky |#n:else] .[table-latte-tags language-latte] |## Cykly @@ -252,14 +252,16 @@ Víte, že k n:atributům můžete připojit prefix `tag-`? Pak se bude podmínk Boží. -`n:else` .{data-version:3.0.11} -------------------------------- +`n:else` `n:elseif` .{data-version:3.0.11} +------------------------------------------ -Pokud podmínku `{if} ... {/if}` zapíšete v podobě [n:attributu |syntax#n:atributy], máte možnost uvést i alternativní větev pomocí `n:else`: +Pokud podmínku `{if} ... {/if}` zapíšete v podobě [n:attributu |syntax#n:atributy], máte možnost uvést i alternativní větev pomocí `n:else` a `n:elseif` (od Latte 3.1): ```latte <strong n:if="$count > 0">Skladem {$count} kusů</strong> +<em n:elseif="$count < 0">Neplatný počet</em> + <em n:else>není dostupné</em> ``` @@ -947,6 +949,9 @@ Pomocníci HTML kodéra n:class ------- +.[note] +Od verze Latte 3.1 získal standardní HTML atribut `class` [stejnou funkcionalitu |html-attributes#třídy-classes]. Není tedy již nutné používat 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`: @@ -997,6 +1002,12 @@ V závislosti na vrácených hodnotách vypíše např.: <input type="checkbox" value="Hello" checked> ``` +Funkce inteligentních atributů v Latte 3.1, jako je vynechání hodnot `null` nebo předávání polí do `class` nebo `style`, fungují také v rámci `n:attr`: + +```latte +<div n:attr="class: [a, b], title: $title"></div> +``` + n:tag ----- 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 +<div class="{$var|accept}"></div> +``` + +If you want to keep the attribute as empty (e.g. `title=""`) instead of dropping it, use the null coalescing operator: + +```latte +<div title={$var ?? ''}></div> +``` + +Or, if you strictly require the old behavior (e.g. `"1"` for `true`), explicitly cast the value to string: + +```latte +<div data-foo={(string) $bool}></div> +``` + +**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 `<div n:if={$cond}>` without quotes. +- **Toggle filter:** Use `|toggle` for manual control over boolean attributes. diff --git a/latte/en/custom-filters.texy b/latte/en/custom-filters.texy index ee38269043..9fc3ea58b6 100644 --- a/latte/en/custom-filters.texy +++ b/latte/en/custom-filters.texy @@ -117,30 +117,6 @@ $latte->addExtension(new App\Latte\MyLatteExtension); This approach keeps your filter logic encapsulated and makes registration straightforward. -Using a Filter Loader ---------------------- - -Latte allows registering a filter loader via `addFilterLoader()`. This is a single callable that Latte asks for any unknown filter name during compilation. The loader returns the filter's PHP callable or `null`. - -```php -$latte = new Latte\Engine; - -// Loader might dynamically create/fetch filter callables -$latte->addFilterLoader(function (string $name): ?callable { - if ($name === 'myLazyFilter') { - // Imagine expensive initialization here... - $service = get_some_expensive_service(); - return fn($value) => $service->process($value); - } - return null; -}); -``` - -This method was primarily intended for lazy loading filters with very **expensive initialization**. However, modern dependency injection practices usually handle lazy services more effectively. - -Filter loaders add complexity and are generally discouraged in favor of direct registration via `addFilter()` or within an Extension using `getFilters()`. Use loaders only if you have a strong, specific reason related to performance bottlenecks in filter initialization that cannot be addressed otherwise. - - Filters Using a Class with Attributes .{toc: Filters Using the Class} --------------------------------------------------------------------- diff --git a/latte/en/custom-tags.texy b/latte/en/custom-tags.texy index ed99d6f014..b427e74a27 100644 --- a/latte/en/custom-tags.texy +++ b/latte/en/custom-tags.texy @@ -1004,7 +1004,7 @@ We've frequently used `PrintContext::format()` to generate PHP code in the `prin - `$argsNode = new ArrayNode([...]);` - `$context->format('myFunc(%args);', $argsNode)` -> `myFunc(1, name: 'Joe');` - **`%line`**: Argument must be a `Position` object (usually `$this->position`). It inserts a PHP comment `/* line X */` indicating the source line number. - - `$context->format('echo "Hi" %line;', $this->position)` -> `echo "Hi" /* line 42 */;` + - `$context->format('echo "Hi" %line;', $this->position)` -> `echo "Hi" /* line 42:1 */;` - **`%escape(...)`**: It generates PHP code that, *at runtime*, will escape the inner expression using the current context-aware escaping rules. - `$context->format('echo %escape(%node);', $variableNode)` - **`%modify(...)`**: Argument must be a `ModifierNode`. It generates PHP code that applies the filters specified in the `ModifierNode` to the inner content, including context-aware escaping if not disabled by `|noescape`. diff --git a/latte/en/develop.texy b/latte/en/develop.texy index a57ec48b11..40262a706f 100644 --- a/latte/en/develop.texy +++ b/latte/en/develop.texy @@ -15,7 +15,8 @@ Supported PHP versions (applies to the latest patch Latte versions): | version | compatible with PHP |-----------------|------------------- -| Latte 3.0 | PHP 8.0 – 8.2 +| Latte 3.1 | PHP 8.2 – 8.5 +| Latte 3.0 | PHP 8.0 – 8.5 How to Render a Template @@ -193,6 +194,27 @@ $latte = new Latte\Engine; $latte->setStrictTypes(); ``` +.[note] +Since Latte 3.1, strict types are enabled by default. You can disable them with `$latte->setStrictTypes(false)`. + + +Migration Warnings .{data-version:3.1} +====================================== + +Latte 3.1 changes the behavior of some [HTML attributes|html-attributes]. For example, `null` values now drop the attribute instead of printing an empty string. To easily find places where this change affects your templates, you can enable migration warnings: + +```php +$latte->setFeature(Latte\Feature::MigrationWarnings); +``` + +When enabled, Latte checks rendered attributes and triggers a user warning (`E_USER_WARNING`) if the output differs from what Latte 3.0 would have produced. When you encounter a warning, apply one of the solutions: + +1. If the new output is correct for your use case (e.g., you prefer the attribute to disappear when `null`), suppress the warning by adding the `|accept` filter +2. If you want the attribute to be rendered as empty (e.g. `title=""`) instead of being dropped when the variable is `null`, provide an empty string as a fallback: `title={$val ?? ''}` +3. If you strictly require the old behavior (e.g., printing `"1"` for `true` instead of `"true"`), explicitly cast the value to a string: `data-foo={(string) $val}` + +Once all warnings are resolved, disable migration warnings and **remove all** `|accept` filters from your templates, as they are no longer needed. + Translation in Templates .{toc: TranslatorExtension} ==================================================== @@ -266,7 +288,9 @@ Since Latte compiles templates into readable PHP code, you can conveniently step Linter: Validating the Template Syntax .{toc: Linter} ===================================================== -The Linter tool will help you go through all templates and check for syntax errors. It is launched from the console: +The **Linter** tool is used to validate all templates. Its purpose is to scan the specified files and ensure that they contain no syntax errors and no references to non-existent tags, filters, functions, classes, or similar constructs. + +The Linter is executed from the command line: ```shell vendor/bin/latte-lint <path> @@ -274,7 +298,7 @@ vendor/bin/latte-lint <path> Use the `--strict` parameter to activate [#strict mode]. -If you use custom tags, also create your customized Linter, e.g. `custom-latte-lint`: +If you use custom tags, filters, or other Latte extensions, you need to create your own variant of the Linter, for example `custom-latte-lint`. In this script, you register all required extensions before the actual template validation takes place: ```php #!/usr/bin/env php @@ -302,6 +326,8 @@ $latte = new Latte\Engine; $linter = new Latte\Tools\Linter(engine: $latte); ``` +The resulting customized linter can then be used in the same way as the standard tool, but with full knowledge of all your custom extensions. + Loading Templates from a String =============================== diff --git a/latte/en/extending-latte.texy b/latte/en/extending-latte.texy index 9f63a3a280..22499f514a 100644 --- a/latte/en/extending-latte.texy +++ b/latte/en/extending-latte.texy @@ -44,13 +44,6 @@ $latte->addFilter('truncate', $myTruncate); // Template usage: {$text|truncate} or {$text|truncate:100} ``` -You can also register a **Filter Loader**, a function that dynamically provides filter callables based on the requested name: - -```php -$latte->addFilterLoader(fn(string $name) => /* return callable or null */); -``` - - Use `addFunction()` to register a function usable within template expressions. ```php diff --git a/latte/en/filters.texy b/latte/en/filters.texy index ef92176edb..c87f8ffceb 100644 --- a/latte/en/filters.texy +++ b/latte/en/filters.texy @@ -55,6 +55,11 @@ In templates, we can use functions that help modify or reformat data into its fi | `floor` | [rounds a number down to a given precision |#floor] | `round` | [rounds a number to a given precision |#round] +.[table-latte-filters] +|## HTML Attributes +| `accept` | [accepts the new behavior of smart attributes |#accept] +| `toggle` | [toggles the presence of an HTML attribute |#toggle] + .[table-latte-filters] |## Escaping | `escapeUrl` | [escapes a parameter in a URL |#escapeUrl] @@ -117,10 +122,31 @@ It is then called in the template like this: ``` +Nullsafe Filters .{data-version:3.1} +------------------------------------ + +Any filter can be made nullsafe by using `?|` instead of `|`. If the value is `null`, the filter is not executed and `null` is returned. Subsequent filters in the chain are also skipped. + +This is useful in combination with HTML attributes, which are omitted if the value is `null`. + +```latte +<div title={$title?|upper}> +{* If $title is null: <div> *} +{* If $title is 'hello': <div title="HELLO"> *} +``` + + Filters ======= +accept .[filter]{data-version:3.1} +---------------------------------- +The filter is used during [migration from Latte 3.0|cookbook/migration-from-latte-30] to acknowledge that you've reviewed the attribute behavior change and accept it. It does not modify the value. + +This is a temporary tool. Once the migration is complete and migration warnings are disabled, you should remove this filter from your templates. + + batch(int $length, mixed $item): array .[filter] ------------------------------------------------ A filter that simplifies listing linear data in a table format. It returns an array of arrays with the specified number of items. If you provide a second parameter, it will be used to fill in missing items in the last row. @@ -827,6 +853,21 @@ Extracts a portion of a string. This filter has been replaced by the [#slice] fi ``` +toggle .[filter]{data-version:3.1} +---------------------------------- +The `toggle` filter controls the presence of an attribute based on a boolean value. If the value is truthy, the attribute is present; if falsy, the attribute is omitted entirely: + +```latte +<div uk-grid={$isGrid|toggle}> +{* If $isGrid is truthy: <div uk-grid> *} +{* If $isGrid is falsy: <div> *} +``` + +This filter is useful for custom attributes or JavaScript library attributes that require presence/absence control similar to HTML boolean attributes. + +The filter can only be used within HTML attributes. + + translate(...$args) .[filter] ----------------------------- Translates expressions into other languages. To make the filter available, you need to [set up the translator |develop#TranslatorExtension]. You can also use the [tags for translation |tags#Translation]. diff --git a/latte/en/html-attributes.texy b/latte/en/html-attributes.texy new file mode 100644 index 0000000000..1107579e99 --- /dev/null +++ b/latte/en/html-attributes.texy @@ -0,0 +1,151 @@ +Smart HTML Attributes +********************* + +.[perex] +Latte 3.1 comes with a set of improvements that focuses on one of the most common activities in templates – printing HTML attributes. It brings more convenience, flexibility and security. + + +Boolean Attributes +================== + +HTML uses special attributes like `checked`, `disabled`, `selected`, or `hidden`, where the specific value is irrelevant—only their presence matters. They act as simple flags. + +Latte handles them automatically. You can pass any expression to the attribute. If it is truthy, the attribute is rendered. If it is falsey (e.g. `false`, `null`, `0`, or an empty string), the attribute is completely omitted. + +This means you can say goodbye to cumbersome macro conditions or `n:attr` and simply use: + +```latte +<input type="text" disabled={$isDisabled} readonly={$isReadOnly}> +``` + +If `$isDisabled` is `false` and `$isReadOnly` is `true`, it renders: + +```latte +<input type="text" readonly> +``` + +If you need this toggling behavior for standard attributes that don't have this automatic handling (like `data-` or `aria-` attributes), use the [toggle |filters#toggle] filter. + + +Null Values +=========== + +This is one of the most pleasant changes. Previously, if a variable was `null`, it printed as an empty string `""`. This often led to empty attributes in HTML like `class=""` or `title=""`. + +In Latte 3.1, a new universal rule applies: **A value of `null` means the attribute does not exist.** + +```latte +<div title="{$title}"></div> +``` + +If `$title` is `null`, the output is `<div></div>`. If it contains a string, e.g. "Hello", the output is `<div title="Hello"></div>`. Thanks to this, you don't have to wrap attributes in conditions. + +If you use filters, keep in mind that they usually convert `null` to a string (e.g. empty string). To prevent this, use the [nullsafe filter |filters#Nullsafe Filters] `?|`: + +```latte +<div title="{$title?|upper}"></div> +``` + + +Classes +======= + +You can pass an array to the `class` attribute. This is perfect for conditional classes: if the array is associative, the keys are used as class names and the values as conditions. The class is rendered only if the condition is true. + +```latte +<button class={[ + btn, + btn-primary, + active => $isActive, +]}>Press me</button> +``` + +If `$isActive` is true, it renders: + +```latte +<button class="btn btn-primary active">Press me</button> +``` + +This behavior is not limited to `class`. It works for any HTML attribute that expects a space-separated list of values, such as `itemprop`, `rel`, `sandbox`, etc. + +```latte +<a rel={[nofollow, noopener, external => $isExternal]}>link</a> +``` + + +Styles +====== + +The `style` attribute also supports arrays. It is especially useful for conditional styles. If an array item contains a key (CSS property) and a value, the property is rendered only if the value is not `null`. + +```latte +<div style={[ + background => lightblue, + display => $isVisible ? block : null, + font-size => '16px', +]}></div> +``` + +If `$isVisible` is false, it renders: + +```latte +<div style="background: lightblue; font-size: 16px"></div> +``` + + +Data Attributes +=============== + +Often we need to pass configuration for JavaScript into HTML. Previously this was done via `json_encode`. Now you can simply pass an array or stdClass object to a `data-` attribute and Latte will serialize it to JSON: + +```latte +<div data-config={[ theme: dark, version: 2 ]}></div> +``` + +Outputs: + +```latte +<div data-config='{"theme":"dark","version":2}'></div> +``` + +Also, `true` and `false` are rendered as strings `"true"` and `"false"` (i.e. valid JSON). + + +Aria Attributes +=============== + +The WAI-ARIA specification requires text values `"true"` and `"false"` for boolean values. Latte handles this automatically for `aria-` attributes: + +```latte +<button aria-expanded={=true} aria-checked={=false}></button> +``` + +Outputs: + +```latte +<button aria-expanded="true" aria-checked="false"></button> +``` + + +Type Checking +============= + +Have you ever seen `<input value="Array">` in your generated HTML? It's a classic bug that often goes unnoticed. Latte introduces strict type checking for HTML attributes to make your templates more resilient against such oversight. + +Latte knows which attributes are which and what values they expect: + +- **Standard attributes** (like `href`, `id`, `value`, `placeholder`...) expect a value that can be rendered as text. This includes strings, numbers, or stringable objects. `null` is also accepted (it drops the attribute). However, if you accidentally pass an array, boolean or a generic object, Latte triggers a warning and intelligently ignores the invalid value. +- **Boolean attributes** (like `checked`, `disabled`...) accept any type, as their presence is determined by truthy/falsey logic. +- **Smart attributes** (like `class`, `style`, `data-`...) specifically handle arrays as valid inputs. + +This check ensures that your application doesn't produce unexpected HTML. + + +Migration from Latte 3.0 +======================== + +Since the behavior of `null` (it used to print `""`, now it drops the attribute) and `data-` attributes (booleans used to print `"1"`/`""`, now `"true"`/`"false"`) has changed, you might need to update your templates. + +For a smooth transition, Latte provides a migration mode that highlights differences. Read the detailed guide [Migration from Latte 3.0 to 3.1|cookbook/migration-from-latte-30]. + +[* html-attributes.webp *] diff --git a/latte/en/syntax.texy b/latte/en/syntax.texy index a65b056772..ef926e75be 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 `<div n:if="$foo">`, you can use alternative syntax with curly braces `<div n:if={$foo}>`. The main advantage is that you can freely use both single and double quotes inside `{...}`: + +```latte +<div n:if={str_contains($val, "foo")}> ... </div> +``` + + +Smart HTML Attributes .{data-version:3.1} +========================================= + +Latte makes working with standard HTML attributes incredibly easy. It handles boolean attributes like `checked` for you, removes attributes containing `null`, and allows you to compose `class` and `style` values using arrays. It even automatically serializes data for `data-` attributes into JSON. + +```latte +{* null removes the attribute *} +<div title={$title}> + +{* boolean controls presence of boolean attributes *} +<input type="checkbox" checked={$isChecked}> + +{* arrays work in class *} +<div class={['btn', 'btn-primary', active => $isActive]}> + +{* arrays are JSON-encoded in data- attributes *} +<div data-config={[theme: dark, version: 2]}> +``` + +Read more in the separate chapter [Smart HTML Attributes|html-attributes]. + Filters ======= @@ -148,10 +176,17 @@ On a block: ``` Or directly on a value (in combination with the [`{=expr}` |tags#Printing] tag): + ```latte <h1>{=' Hello world '|trim}<h1> ``` +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 +<h1>{$heading?|upper}</h1> +``` + Dynamic HTML Tags .{data-version:3.0.9} ======================================= @@ -204,7 +239,7 @@ Simple strings are those composed purely of letters, digits, underscores, hyphen Constants --------- -Since quotes can be omitted for simple strings, we recommend writing global constants with a leading slash to distinguish them: +Use the global namespace separator to distinguish global constants from simple strings: ```latte {if \PROJECT_ID === 1} ... {/if} @@ -265,8 +300,6 @@ A Window into History Over its history, Latte introduced several syntactic sugar features that appeared in PHP itself a few years later. For example, in Latte, it was possible to write arrays as `[1, 2, 3]` instead of `array(1, 2, 3)` or use the nullsafe operator `$obj?->foo` long before it was possible in PHP itself. Latte also introduced the array expansion operator `(expand) $arr`, which is equivalent to today's `...$arr` operator from PHP. -The undefined-safe operator `??->`, which is similar to the nullsafe operator `?->` but does not raise an error if the variable does not exist, was created for historical reasons, and today we recommend using the standard PHP operator `?->`. - PHP Limitations in Latte ======================== diff --git a/latte/en/tags.texy b/latte/en/tags.texy index e9cb9309ae..cfbc94ae6f 100644 --- a/latte/en/tags.texy +++ b/latte/en/tags.texy @@ -16,7 +16,7 @@ An overview and description of all the tags available by default in the Latte te | `{ifset}` … `{elseifset}` … `{/ifset}` | [ifset condition |#ifset elseifset] | `{ifchanged}` … `{/ifchanged}` | [tests if a value has changed |#ifchanged] | `{switch}` `{case}` `{default}` `{/switch}` | [switch condition |#switch case default] -| `n:else` | [alternative content for conditions |#n:else] +| `n:else`, `n:elseif` | [alternative content for conditions |#n:else] .[table-latte-tags language-latte] |## Loops @@ -252,18 +252,20 @@ Did you know you can add the `tag-` prefix to n:attributes? Then the condition w Awesome. -`n:else` .{data-version:3.0.11} -------------------------------- +`n:else` `n:elseif` .{toc: n:else}{data-version:3.0.11} +------------------------------------------------------- -If you write the `{if} ... {/if}` condition in the form of an [n:attribute |syntax#n:attributes], you have the option to specify an alternative branch using `n:else`: +If you write the `{if} ... {/if}` condition in the form of an [n:attribute |syntax#n:attributes], you have the option to specify alternative branches using `n:else` and `n:elseif` (since Latte 3.1): ```latte <strong n:if="$count > 0">In stock {$count} items</strong> +<em n:elseif="$count < 0">Invalid count</em> + <em n:else>not available</em> ``` -The `n:else` attribute can also be used in conjunction with [`n:ifset` |#ifset elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [#`n:ifcontent`], and [`n:ifchanged` |#ifchanged]. +The `n:else` attribute can also be used in conjunction with [`n:ifset` |#ifset elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent`|#nifcontent], and [`n:ifchanged` |#ifchanged]. `{/if $cond}` @@ -947,6 +949,9 @@ HTML Coder Helpers `n:class` --------- +.[note] +Since Latte 3.1, the standard HTML class attribute has gained the [same functionality |html-attributes#classes]. So you don't need to use n:class anymore + Thanks to `n:class`, it's very easy to generate the HTML `class` attribute exactly as needed. Example: I need the active element to have the class `active`: @@ -997,6 +1002,12 @@ Depending on the returned values, it prints, for example: <input type="checkbox" value="Hello" checked> ``` +Smart attribute features in Latte 3.1, such as dropping `null` values or passing arrays into `class` or `style`, also work within `n:attr`: + +```latte +<div n:attr="class: [a, b], title: $title"></div> +``` + `n:tag` ------- diff --git a/latte/files/html-attributes.webp b/latte/files/html-attributes.webp new file mode 100644 index 0000000000000000000000000000000000000000..56e729541b6ca3c84e678b115842be201c429e10 GIT binary patch literal 11126 zcmZ9y1ymeOvoO5);=Z^o7GSXi5AF^jxVyVMi@UpfaDoO6!Ciy9OM*i}fFS=q?{mL< z?|;vk(=}CHHq|vf)zhseCoS#B0sv@9iK}X=@+q3Y?%8dJz5>W)9m(WUYTeuSUY({Z zCogm^a5>=~r%r#h`Hav)lf&pP(XUPc>@&B5XPcWm#-auqLrC`f!(9d%y-DWHyYx_$ zP{UNdF1B~@U-*Ad8fr+v!P)CkhdDSU*~!WE*Do~+ow(MurnsMOPyW!=H4=E$IsSsl z82t`QRU;WOsWrp@gSX<B{Yk6qN})FBqokVSD&th%Bg2mifQAPA6v-T8Dq?4s3F-M6 z3jfmQh?OtNbT+rxd!`+eo_}6y{5H=?@XXgIcV6C9)QD2AZaWn`UWUcf$=nD}oy<7| z<z+zDJx{+}TmRjh^Fbq7QW%6o-31qA=w_p4g=sVBQkHrr4<>RDo0I)$r#uNW+>fXH z^qko%n?lEJV^hA_B_Xsrh3$8U(qPVAM7omlnbF!p0|75d6_rmEJ{#WZ#D0xEWrD$Y zodd^K@I9tw<|<-*M^<bSqH3NYdJn@Jx(f;{ujfcaIoEZ|v|I5nDjd$x`vK6<n&zo2 z$ORYY`VDEy2aej{iFEtS&5Ie|L{Vso0rIL@{JUXloFeN?u{-VkIL=4*;CQ-52Wcoe zYDTB89MO;G8-t7dmL!dJ$4%YbBp_nA>aTTKu8;wMcpo)ZR)VZv(>mGqGEuo~3Zh&} zpR1ezTZ*}<*JaT?OY;3^=wLG{ylhjpc@qDyw%O>5g7La^3f=koc3zEDQk7E0kubt$ z(n@<Wo!ra&mWyXUtrLNRN^vCpSEsw}AX)o$*_0#RZNE#xJvw^XdWSa0nuYWbHI?di ziVZAPc+2c!1a+tsd>J{Ze_?hhz;VE`9sZuU5{M}F?RiiXh{5<pBN*3`BN;@|k_^Qx z*%L4(q~7&f-vuE3qQYC}NugV`yHh8rR5XZxc%KZ@e)kO*mxcxxmzK4L_Q$H69t)Kv zF_bhYnO2rM1eFd)Y=#7={V6Ef#ohmvqS0YrcCF_<$-Q8#{`y_d_m<e#`^5jb5>6>S zeIPIUBCzY2w22ZKS-;gOVp90ro|u?;K7D4OdZ0Qucn+6aGD4AObsz*!IM|)%=5rlq z{polPc>Wzn*1I(5N)^-R{I@#g^Creu_4q%WN-&1TLtP0v;MFuc;^wLV{JI#AjIw#I z1L8=zZs(N4W#`HM>co{gqbztJc_!NsFB+duojx8~o&*(lTiy8Z^mMCdo#GbFBul4< zi`tFR^)<3WIG$olA&~VXWd&uYm8xWgO3iP%)RZF@Bb=)Tqpb9-Nt39I3L$5FKAr>; zsQfC5Kf0a!`OmlR(sMi*%T%8aNr!g!7B7Vy&V2vq1z&NnZhhJSk;H7d&wEJ9%~u1R z`k2wq@V0bwO6@!3S@JQd1m-AYs)~CJ5XQxKb!C~VmUBf5TDFc*tL;Obd)Pp-0lova zaYb^VpHLjfG}EU21acNmeXZ|{-6M{Y`M7FF8eR8;7F$+La-n_`NVoN!(xZM&;-j;R zN}4tvPfktUztt&llgcKJy?^s`(U4Y@a7()C6Q!t)+<j(K%_|fWXD{QZKAVVK#Qjbl zJcYad&`mW}4K+%unU-~AjQ|F7TacGtL%9hSpXt!2e#$1-{CZ;>NtBT!*ti0Z>_$gp zcXxE4o4Nk0|Ei_P+EVygn|apu#5&Mhm}JEzz5m_N!DJo?;qbuO)mw9%Ncl|!o~g(B z@o2y&qFkHZTxxoWZJVRtXKAU(!b+b`En0TJFQJb*YR6-B@1rsMh_mPDoA|o8>c4^e z^g<fO?lyWTC$^Cq&<EX-6^vQiRqpsA<LyY%vkN5nEE`A4T~H@?)&2sei3RFqt1`__ zh9^6APDRv~({YCp=l=F){%*@_{Nq?e<n`eJ`<2yIsq23y=>26THe9esi>K1g%*fT@ zTI&VPKdmd?u>#5c<tsi8mws$u1`gM)px{2CSxdrqP9b?Q0^%uxaBMhUt69WA495E7 zb@8NC%Nmn*s-P#$X=Cf_k&0koyw>E@cqJ*pOuY`Wy#z@+kD)L_RTG$F0A2)Mf}G%C z?E~KX?bb-ptN)OGFN~8IQHJXEZ=X}TIuKY{=K5=Wqm_EgYgp0aeTDY<?fn(aaMx~J z>hS6a%h88q{5gs%yWLXNmlj7_Gazv{mSVo&)Afwg0(eK9jfLgA?FdVT)pZQqJ|;MV z4A!Hwh%`(YRI<{n&S!)fC4DhO^^F}24B3bk^6>Yq3%NYezPVS=0M-8~!>{*pkil5c z5TcqMRMkrfy<1ZvQRWqv1g61b!hd*~%P^-YugpR^fj=HI@FzA`F|)!@)qNC|vwcQM zuckSr6D40ft<c;oBI@lFEn=Wu))DI)IQ1sheYzeY^3!EZ_;dYkFV}Be4wHUX>+)ug zoc;ST$ZtM;z+aL}{^e=!)f<10-_&_GM^r}IUW+i`YVeGanIM8hDy$d7;$y0hByk!I zrDa0P=MQ|Qh!NK%(nw7eE(l2nL*fMpAFE8&q?zKxe}R}06)_~xiU>!=Bcu6`W|NM8 zvLlGSW4}Gy+VIB>wkkDFKeB5?3x-!plVZliuGOj{)g?hGWkOYlzx_a4Y1k=|8{zt~ zbeqahWk&$)yqofVAsP3qIuE-b>sgWpIqQIHMS_d-w$d7ncuHJP?2fBmjFY-d4vERq zmV1bp<7;>?qy@l(MwfsbPTWv!#EX7Q&c1X5U$#cn`=I(kxh({zFVM}vc>bza%!g_s zjW&#^-aAX+t+>JBtr&h|Zo}=Kqg<VFI-;$K`d5V9?g|&o@sdwEit-c^eKJ3DWWvZw z+5(u0kQ(%;uRL}g;@XXf+DbKDi2bRD#gh38e2M%};z?JyYUi`a^t-mx0!Ew$JqN`N zET}SZ3G!n_A8%cR>PH?bqX7nuB`$C=lOl<Q*g*p{;%?KLc_>C8inChYki;PGdp$Z+ z_IKuoeCDpK9O=_SFAm1-?70csz<-n>QEB0|7^1aNawiO&y6OX{8p>RvpR^VAMf7pm zwpfGu{*Iiw^!_cKC4<X<5(kwvS^a)HXL7~e@SvlCf}-i=*vBH~H2&gb2y`C|F_5BK z#$B-cZ7wm5Xe1(RBDcR+QLP@l?)ePprs71&yj4BH1S^vugzFUCE}`~SprBM`;QD7r zGR(*fQml64E+!aFtl$!vSzQ&QaZQAZS#Wa{>hc-Yg+=@s_}fX48;xx_!&Tp(Zhe^R z6cpG#dWy31NJU<+P|j<OlKH@V^7q|<6YfX>p2*W22e-_l{kxIXy=H*8{OX9vVR+o$ z#oyOw|H99I{ysQfRG+;Mq}fO=#$3_(RXoz9<9rNluMl-e<-C4i4*&9=olieA<aU5x zM3Yx<ff&qhIMR7sZ2jGZkA0}Q-=*l+=qbFn2-;T@V}&i=o3#5PO?*3sTJqeuKPYJn z4;FfJcN|{!Gw7X97fKEy&(uECl|9c-8$nygo1Ra@?C&Y~De>IX15O(4LGB3q1#k@& z_fy9#gvvPGR0N|&k%f`V7iy&U(9;jgx0Jo53n1<kStq!i?!3hPD}kM)Q=b_WtQP*Z zcj2!@X})GzDD|r9-rh7S*?wR7*x|RT4sm>BCzth{zScY{i|L&5YqeS?46<leUv-#c za~oYp<~CL{KVV%lHy`dZ8eKYVy}5r8wy?es2xOeaoku=le#9|fg|xe=Z@Bf!o;CQ4 z`lqYKbsS3Aqv&U<^LfH@fxJ9p92>-KnatS&`QazzO|2U^Krh6U7b)+AV^&$oKmbDA z=x+Tp#yxKM@W{~Pv;UXbwVcA{g=KiBj<ZF;Z%C^v&^{{2(T&i|-O+7Epj?J2D*j{k zfZ}a$vxDG%kd0{Q!b2Y`s>qI$+?H^W@8fnm5jXq?!`xDep#lpEEB^;g0}<}fG0Ru7 zNxb6GGx7yNc`<vAoFA083%QAh6J9~K0XfgdY*xXIXa0Tx*kq5|E)T+&-1>50|E?Tm z(VgFCO!ya{_P@#a)FNkT-Nr5k)WA&*#O$2BE6Jf(oW(aK0yLA;Dmz#%W=uu{e-#B! zAs#(r7}YhpYxSfFm1_=9>rT9^<63bHnz^DUQ^xcWy`A)FV=|g3P+Oip(IVC(rYYUt zt0+(WCR|K+N0C!xq@jzX`l#BoV9MXQT-~7?hPTJAVnm167Zbw~P(Ez6n2^GnF0yF7 z+qQF($ssl)l_!q}4=CzqA=JY_NwQS37lQ*NUCG+Y;d7`j<ea$9$%n3rN|sYKf{z3b zhP3#Tsi}>9%%O`k!ATwAix41?IFW2LC5pPGGS`}Wj2USa_s(8Hd4+>_{q6F3r>7c0 zc52mwrUU>wN#$oJ34nqljZgKW%;JdwqDjWN@motY69eZfKY;K6oQ~t-`E97o^v_{s z+RWOYC(ZtNl&<FO;X|HfbsC}phE<e)jwn@-oM?^x7^J?BDpxY|ie}xWfJ-rn@ZxMX z60bCl^gKP)NKTUYAYt%lnvjB6J_|q<PvIIlyreoFvz+$iPcAocuE?U%IvxyB-!f|* zr4&FPntF<QE)VsmxI!HYQ=l$4!!r=Xc}T<Bb0a33Kc}0BXflJBLA*ZXY7g#CX+MFW zB83fOTIhfo;c1W*;uhwzBx6Wo4`std6~3;gyyKbt`eib_t3I2+LK1Ib10(@x`(Tf< za4cC{VSDMz5<1b2i(2G*E2xja-R89<>V0sbr$CLkzR(1GCK%LcRF}aKmsYuHcE-A& zJO9Mi7@=ohF3?)4nhh0j9&+XS^E;;039Da*o@3!+A+X1`>cB_${6iI2ixRye{W0il zdg>`pK79$vN?ed(B1H`?s<JFaH#5DGP0ZK)ZL6Acc|d009N1E@%;HR2jWCw}+HLSx zX&7REK|0uDcR7wZIohBmO+!F^(|0!x)9o{>+ity`XBzHX-z~O&yLn*ZCQYdmb<Pn$ zhOymA(w6j(zfVcjWbG%La_2~bE}$`Y8z{4?MP2DUix>a2h%h!dh=)jSY79KRocEFJ zoN+Y}-TqB6^L2f#-!JGBxp;XlrZ5w=kXlaxD~jzRbIo+gY?d|df!Gd5Sc<BLAuG*y z{@Td;6ru5IB-I996y8b9wn>k!dMV$?0WPVdoT%xv;T_&34RMOYG%l<M9c>z^s729$ z3pH8qRc1$fCPbJE=-*5Fe&XdITz@QL_6t|3v*dQDUGSM94+k(qNK^Gw@%~h+$lUUW z8EfINipS3Bnnn-f-;eR*^TSPe{>BPiGIlI0jd%Pd3$*FK#vEu<6iQVix>ce7+Pv@` zWX0^kL@P*R#gcP0VJfHjjOkn&pRz)BZNrCD-J}4qqF0X!RqoArQV3)i^DzWB@#Dd@ zZi+Pk39l}{Kv;S75Lv1}HI6bFb-ziUWTfqM?vE(e`;;eF75BqFB%$kJm#cLMe!&}a z5M|{t!@uV3t7e(|8TZB-+Tu18>+(Vxt;qiBTt_o6aG1k<FU^D^TFY4=DmF<JP?IUz zsNW}JJvNs&nTs=<HFI>LsFA8hWyTUJgVQHO^*1ge4fEwYBM9~;#?O$jPHyW|3Lxq> z{xoS>xb$*m0;<&J`ssiW$)Hi=QhDfmZ>b}xIAqkpL@79TwS;i-5B3Su>fB677tRSh zVtsk{YiBrH)q3&UwMx{(R!AnZF&0ji@<`Y5yI4884kXIK)oBdEHIZ7kIvCre@vHBG zWZiY-P(&h$zY$p}#?*r1-oBZLe#~e&ANxUF;MxwTgC?o+3-0;vroI6(c=7>FrJ^@8 zqK2(Kjt1wRv(s{jpW)Si;E-nU<nC9Q;3}b0*dhdNh%M6W#Bhrgv~dqvu)5C#SEV7F znMXkRIj?4q$#6Tg>Xaqu!{jq3veux0tnwA@DO-$zBE#W@;qID_@|Ehk{qxy*vF;R! zeWDUF8}iNxHG;l<A8rQRZ1TZDBlkw*EqB4s!#?eoXgD>~pGIz_xuk2}F(%Y!r`dWw zYAS}|Bs*v-Repb`Fc>9?tB+9BAtl6)vwS;^`nzgJi%FBBF_b0a8NzL}aMiUi9bC0w zDGVO3{ma^~&hbaWZ?GbXtEP}h)K`)SN20&PrW7+~fywYUY8m5R+^55LDv_byOp!|> z{iFJoZ+<T2NLn}8MbBkPRf!pR<E_K>G_3xHv_glY{)rEFsv2e;sKe@O*S32*eOe9h zZ6fXcN{kM1IS<WdB_sC<Pt{Kx=OM3-+XGizw#-H0TUP5KUjFu(iTwRYyp}yZ@{R1@ zL<%SQ^rldm7u66=|H7`){GRws0D@Ziu}Xm8Q0={@U!mnI_9q|H)n{Yjr%a@|qGA8m zG0@>RE3~~^PtPDbs1wx_&bgoSi*D46)+OE(+Z8T&UvjsKZ)N#ng}c|kB1&&vyN$)l zzn!0!OXiO&t-=SnGoi39dMh-MV35f(QxqBTjj0!=msQx&iJ@DI6ZQi;rl3yX<ovXF zzb4kRulR$tpr<aE+gWoIB$utv`l;b2Bm(8W7Cd2jbnV7!1{NO)!`hiE(>hSn`NBL? zP(NXE_~pttuyCodhlkFQo?9d{-1bt#UWi;Yo44`z(+cQ&fdZ=yTttj7W2bKIcVnK} zIlU9IK{={NlD>F3X7KXK&B2=P5#@FcHb#0S!VzwY!pc}NmE0Su_z`8CW)0GMUR#b> zT4vNN!R~ST8RxI9Z@wvbUkRSo@n+-aq=V84Fo|5-_>7z+-%Q(k?()e_{F*Et)A~_Z zq?<V~uC&`nE_<qOL<ZtOR{eQhcP<7^Fcc@Wnb4-f?Df|vm7Eb60HhtqWO&da;V=}( zr1`dBavD4hKT<~&dMvM+?o%s2&Q1d>IQgaM$PDuID=lD3t|2LhBjCDyye0l$rKpFc z*DI(cbe`P=EQNjN`t9~5McKUTLWMy?eJynKE&3h%Ncv>#KCDV_{S6YBMXZjWZCVXH z9)+sa^)e4oeH!(aHq=CA*wYufY8O4YCo<|kX>?ZInG_az;4lVQTZPSM#er|)*%aB9 z#1ozToV~Lj-{d7C-!x`Rh{TBnx1SJ(E*<Lz?>QHCf5{l);!?+d6-O^SMxo>KPUrZ! zd+MtCAlEHYceFo$DOTy(jKqwTc09h^Y{68c+W}z@QE9>2TZt@?=8GSD1KvK#8S}6W z9%%~z(8}-NLgud0cwA4G@yGuF<Em0mKbw2%u({!yw0NFOBI=&$PaykWboiW}SHAWw zTPQsI=w_-@xT^E0Ej>>c;LP(t6K%CH%dBy|={{Yb^T!s?%Cw;vWTGM^-Q{8^jq)$G zV_2@T(A#lYohv&1FEaors-)~bMx}1P(~zMf^L!J+<fc)Z>Z*M!qCk<e%)>)BW8GbC zq?~$eF57=*f7&XaBDx%%YC!8(<x}eEhuIm}SdmB_kQu!1(4WX~u)g=CEA~&k75!sm zpUKJf$pXc7l@XdsgsnHOvJLZ>ED8RNUXfo0cgHpdMs~Y}w!-2BEFyW>g|D9f#$^7a zGc~pq(B<JR3|@I#X!h1(E)aP-Lt%o)fgB6jnA4~DNrJCni8T%F_h9F9wugKc+{wvv z%92>#?e6XNKdA$AhkSFlb+9-C(<B)p0<xjVY)F>)R-h^zb27!@Pj9#l{rq>hCb_D; z<{c{m*C~f`B@em30T#1}p*H`nCF6I2Sy(+<oq`pJZTe)m!9ky++b6%uEc2vy_ihws z=T~t)uCm$Nm{HzNjt;)*t^IW@`=h`HA*Ze;r{gS0v45M4=(Vhjfz_j|T|b|#b(S6d zI=64G$GReVg*)c*`$92R>%4qkTXj6nmZgHWrNahS0?NN*h$}I=b|V4sbGP-s=Two3 z*A6?Yzt8}VSa_Biu?9FQ+ca8*oSHA*H2qxNICdZ(+&iacG;K6-jTz<XG@mKg<w<Cp zu@;2r1pf7^ayXbxq)WTJXcw`>^=Z?$gG8{`_MKY_b@jw-l<H~@)<}ysko3**w$kGg z(ODmLu*C?zukQ{k49Z;VtZQiHG2?dtTNr-R0vz%iNMN8&e2V|Vq*md*Xw^a)MV7NE zVG<vz-9_<B62haXj5{WsdDfvmF@1e!qct%`=JF?S<<A(B-g^&bQMh1s+vR|#<DGvd zS`~bKA#Kk{P*R7Z${E_LkVM1Jz1?lKtse?Lx5-?^U4Zk?0xYM>gfBJ<I6E~o#*<S? z7MvNhfA@qNF7`~^Pp$-PW(tG#)wDf>y%0NQJFt5jjymuW@0U@XmA}lx4HAh~h(hIX zIo2St@8p;^6Ss*7N&4xFQMo<V^yBb7Jjs{f2DQL29x+^w9+PIsG+jA?AUMv`C3>s} z*g?$r)1I#dA&Q+m`6G325s-MBqXWv2qSj<hlo=<6$VpUcWHnGsA?i=#iiUVE03`Ov zl9gYL|Lren-`_#JDexZa2VhU(AK7bEVx+#ZwBsGgnhk(93XV~99z2|~N^d2QzFZJ} za;P0)7K^$EhaU-^yb$`qIdtyZv~RC|To*vT{XfJ!=!fjgN1NU51r<AyYn|Q-dw0M! z{U{TTu_|JmQ&wgy6VoBGhhXOjv74bO+c0W`I3rc+Itfq9kX9Qk3|iFx^N8YV<Cs_8 zbXjMyX|XOLjk9AT2f_s(F!uHAA@8C0-~$362NS$>t_5z2nxpDW>3{Qej2!44__*%Y z-zVbux|QYQYss2apntV{Yk4vrmKwfgdue_Akp3Ep!?9)SMfv)$9n@n{`;k3`qd(9A zYz#?|&;CAvqA%@u<%bWqPd`8_)2pojswAq*@p&zadibi?4`zoSKC^Ai5?74Rk7b?- zBO#>~5O-4esS|m2kga-aXZb2g-8F&s8+<y`=z$0Fz~zwEiXBoUjF<ZH%Y}&<6V)w@ zt^du0zyUH&d}9YhmA&6TNsg5Bln(L}Y>ZJ4iZ%P`f(enF(o*sidH1+GG;g2bG0L4) z-q`k(@7uWQKia(~jR)Hf;fT<RmEwBTSI6WV53#Uk2*R|qu|Jzu`-{tChIPGYPiN9d zh8VXOWb07}B9^?K-(x6AaZzl->OioxIb%g%h;5)_xr%<bF53@ggC9PyZEQz?MCS`@ zEhs=vlN9bfT-|g^3~P-)MP_7cm~~eH;mm|`hpaUf8)_vSh5e-?MGCy)eK{+<4biOe zKxE>*+A}5s%zOfv(wwJBDBe|tOD0Q|M4TLQ!TEHMJ+QH29VphHhpl?;Hf3%%%9%<m z{YoECp|p3FLt$SYZy3waBHS1EC8X(?Oip`2syEAk71SuiPAGMb#Di;KMWGh$wb*0R zUaD#0N<WC##KlH$V!xvSsv<IB#L*5a0{Y-`9BIZ%xn{13tJ}@2$F<H$Ezu~5ce#VY z1ne`0%jx2TgnVdC4>ND3$Z`#~$rGX;lVpi=W562K!uPz{EMOD+w+)bXwFjxAIJ&s6 z3_TxEpZ0F<VObu5N*pBdnz~PccO4=P`vH9y>yc+%L2ou^{iIpI4(TeP)?)8CZ5suJ z6n>EN=jj&ElW6yw{;9dGwB_Vw@0im+h{MQbdsu8eeinT1uL&otwf=qrn9y_D1vdfq z$4>vaY9=T{D7`Z{(GxCy2Ze-pYp&Gze<SQi;N)qwKMPupd)=#4o8MT<%6l1fi;T#l zd=rvL*HRS)og-^x>-T;Wd;5{pTYWL+p6gfBt2~E*R;*(DHuFczirq0-LSxdDzGBJk z4Y)}DQqrz+8b|5c=S3EFdNx*y^Nfr=XSePFTuMNJ`@6iuXe@t^OMKqmN~MQ+{&7p3 zOL+4G=UCdzw;f2#G7tdDaG=RL1CP?oFNNo4LUXj_{NF;vLoZPZN2l>24Z2}|@6QsB zcW65jo|Qgkk>bge3=Oa{23Z?Y-xZm@v2k*g2m|gHgQ$JX{^VQApDFf%AEm!73lVR2 z@^{Xub7<UZq=rPtn(jr{?bO&+SB!g@tm2kzK5rCL05&7m*mQhVh~Uf&TE>M&P&yjI zsn?|%!t!XXs}cb6&4U#PHKz`-G-2AdI){3Fu*s_-BqIv$r`t`k-pI=*rnHq7v$=qJ zYF0%7t?sG+_(8zoLyNwY%w#;rdjp`<yCe4Fl`#wUA~etl9R03VE`Jg-7og^cakUu! zvlw1u_PKj+m9eF(a2=>2KH8tB_hjbl)lC1IOWy^wOxf($9(4>y7W}}kl0<D+5T12Z zb-%LA6)q5|6n>$8FwCvQq+0RCE1R6A-?tJ`c}uqEo&yQ;C{5W*s}O9A9!v9bUxlW+ zD9<DOwD98AY%se>?`uP`W+G8V7#WqmW?mg8L?#^Sq-jWf7EnogLqWFAVJjn#sYF|y zt9sp7XM-jM1vd3v^CgN7UrI|U`DLzxCAF~^$%omV=%ggkV`a8wL;HW!vhwC*tl4Pu z>A`2_)7L!@?>qJ^i;U1CR+s%W?hXFDw`!?w;)Z)IO(TL5k=yT!Q0%VKbc={zj7;si z0{A#IGOzTp66NLK0q7bO>AC5T50->R3KSj0b1`s!f=X}85`V1laO29c`xH{(Oa-lX zoL5M<YkuKpqrss^bUhtpp~vtWbIMiYQ%Rz6l70|Y^*Gb;7u?_qw@q>nKK{_j9l~%- zDH%nLZ9zVK5MSFTuGOnV@*NEX+Z0Nu53ba1<`+i@Jo{O7g9c#yN_r2}DpA8?Mg%(j zrs-<%P(V9I)f~hixm%@D;Z-Uo-te>+LOP!mioy}29EYaxevec_BExRUEp;<y&ZsRg zZSA-sAibjfpmM4zgfSGo(@n10&-l#<D$~PxAlOGT)?m*pTws?YE?51%wOJR(u7iEF zRu6{;UWgz#w>x<e<8lGiJcjXD+-}UQnd(I(sg+q-;W4^x|JzMJq*3w%y-IfM5NUCl zom>;dh$n)Ykj#E;&?kh;T}isSiT6O=KW>35+&ZLp2bkm2Tuj!c42?kxy$2yi8Dp1= z+WE|;cp=rXkqIlI3PMMg+?GkR$6<CltXrD8J^BOqC@N|cetj1hgw4Q#*Ug3dc%)dg zA8#IA8?_Vrm>p<FuL&zVSV6^aCF_qJ8nqT2`5Jcw#b`3Zu@qQ6?53*kiK}eTngfDY znROLD!lj;i&KEmu;s|mH0xtSGfp@A%$~V&1L+HsoZ~skFvk6LCPd9gVQS~{E-*??H zkC=TSx~pc;M0<~D!)pDz=7k*+;aKwLz2o+>$br#xL36}7?zhe1)L(}&lGde?WUA)) z8d<HDr|~gRg>4<qbRpodxUVsZ$vK~JFf76|v_~j=nlS@p(pQI6pl&UC4Uqm@)d7vX zgZP83meqGKCx)c}iL8Ecb-AVMXk3Jn8c(-XT?<FFrVl*4ti3W#onO1^s&4dl#>k#~ zrhG1%h5q>+oF6P86Jx<UixP{uc187SG4huzq~{=thw#K0qe9LI%UmV~%DJUp)VveG z$-piV15Nf)A42~o-o#ER2)92iW@I!rO=RXOdMBlV7}x(XcsMQ=hTpi}Nqs<!>-iXb z^e^uF|8UQ@Yzf#-{<3hZM6e<aUImF%jlI)Z=v&m;%Ww}c20G`(Je%e+hxC&s@abn5 z1YUZlN>t*f6jA+g;#F)5tR|~~$8<s}FaiGsbNr`sU|FjPeZdS)y7!GBq4n+W^fRh2 zzX82K;_wQ1hj(n9qCy~J#JG_ZG<PXVMxyDMZSj)=PsA$GOE;7xH1|cv7PpM!?GkNI zja;b9e$POWmaSZL1w+}>NKiJXyl~agb?cx8-F^MwN;7K^NnmI6t5uhXwoP<lFBha} zH^`l5NacbT{!rdb_|T8mkW&=hF#3AXKx0E;HX)Q%W_Ewt!rcuf^z5sK@a`ia7{_VO ztEnyX!_*Ik=^cCN#?BHb)=I(5)k}P~FUew_;~s`6DWV(&GBT3MueZ$nn}a&Nd?kPs zs;1L7d+zv=CFL>ks+;QmG(s>|!3H{@IELp!nUO4RMJ^v6@lVskylaWd9d~@jP(+Z0 zMQVp{?m%iE?viU~v;^Q!MX+39VidQKTBVFnUo}iOoHJEMM8pkk<&itS)_EV<L*lDr z%$Ilzt(FRw|FenwzfL^BzU>DIul4#>YfSqiL9jSId2xC53+puC?%s@rgxq|EgS4j? zLf$ZK|80ZnJ&c8@xiO09sM<LmGNQ}N8|n-mZ;Y#eS`vL{(zTT3l5^wDH_>Lt!NR%# z^rjb@&*Ad9HSh1oLM-u!bT4MXP)*P^HbHL)+`!Vn@2y@Hka}u%-Rtl2^d*U(dAt9L z;kn+IJWMUR1U41bgn8tXL*UPiEpQ82ph)bGOu}<2Aa_EeyGxTp_Za}lKP7Sx|Jhtj z$44i9n|Ixe>UG5UnelNfWY4Xv5K_rThEF%iHxDzDiHV@iv8O7cGpo;oVcZub0TXgt z<$xm5V*O4<nkqL3pd;s>Frs%V*buLjnLU|{#aBg<dQ`%moXz-VxC34r%D<rkA^>su z?CZlpphU`lQjr3XRJQoE0qAeFZc>qu4i8i3`{1>cI+6<^Ck!hEgcyXq@RR8<Rg1{l zd;gp$d3i4}`@avIB%I%0qFqk3i_O0%lCWvCvJC}2ExR%^>?0p7i3u<SGd>ah>H2D& z=@L3rVfxl__J!T?%Kw#w*P4Sq)dit%rvI1QDVBu(Fy<1?@>|CSx{eH&P<px6I5LR* zwE2cHx+qLj7xWzo?+Uy#%nIkmWE@$`1M`~2MiKe~4+(zZ=LxM{wtZwJKw$l+2Y-Ve zG*1#<oMT(djiQOj)`|AMA+Pk9vG%@iuQKe8&LZy|XN_C_LoL|&hrIo#gowAjn1r`| zajRl=Uqs>i0`Myt1Gp&p@1e-c-%lyy;+)amh&Mf1oAFH_uf~jiJ%lxGoos!}2{%ni zj`re}|17(OgMLF1+)eGtD}NKAopcF2Kx*vz;L1A~5+*~<{%JElBna;tg^3P|Xg_Td z(cp#j*k(Br9_7Ch7chw{;6Z+%SE>GZ?mq%ioAD`KG$1-bcptGd$FvR1M(SPMQFL3c zQoy};7pj1rVM%Oo)q#K2x2_NW$L{Zrt`CN@2P~Hd@iA_xLs8zM5~HZZ`yFQYmkWSb zSojRgH=wT;8#^`Q?Qk%>kB5YJCy0die#GKG^diRz7+t7lO=xPm-h>5iU-W4ptp19M z5lC7uB@(z{|JIQM2X21~HYNxrt3QN8*<Qxm+K)Qi8nbe8m4-2q!N%RIuu-FiEwmE< z#s%@M!40|}tUvy>_kofA4@WJG1JHm)edMnfRLF`g*-QM}r7#%)6G?MAy=*=dge_@# zoupqM7f+`2<CsKI|0M?liJf3>6GuU>EmK`W{}-yA@HZ|-P?;@{@LTw-&^Zu>23!DO zZS|&gWGrPI-oFb+xH{y~b~rBh;qR~@h(o&Q5lG?8h+u(%RjDNA8>0UM$jmnYFzo*i zFwHl5iQ&w!VFEDlUw!{2_pg@!#0M!KO|>VE4B9oC>4M-)bpO`zDt2N&2-39=Gs%{% z?-nGKNbs`%jdZ0Qv(flnhJk6!N2&_#MUR>N6&+Tv5t;UPoidLDoo!@D?3K_NrUH!& zz=!Raff1fDX*>|`eYueE7gIpUf~FoT5L*4i^g`{2bZsmLr7qM|0@7|VtQ_H<z^IX< zB2w~%jzeknhekB)dKPZnBns(o<5`o$U*9wL4gGJ!N52SET!!LExP}Tpx6z2hcqpF8 zO#1>MT~E1t$EeVUba>zHdkg+!o<guBG4^@zHyY5{K+`;bt?lLhtQM~RgYIx@RQ)+y zGcBxg-TbH99@Y*0T&4bFJhxf+^6Q!auGczSu2fV5C8-1oMx!wuq)QG-Y`c}OzCvrc zD6Wq|G75lQR}6^I=D^F??AD&J6^ZEN>PsyBPYtLW8YBVnCY?~m?|cu^9P?WGPo<gb z%4f(4oSrC_r!JW2NRc#UY<87U+BY+`br1^!{+i9ny@tJh$qi@i4N#fu-##(L&Bger z;}uR~P~hEcPU7*QQxp=d$*NC4@ETZ<Q`zjBdIC+GQZ6RYvOTd2<rKUk;k5HF%ZDQM z^d|VPgt3OJp8_?q3p99@Db`uFLA!qKiv``+*HkZEQek<}#`l!<JMgct*cIj<T*1QN z?;`=(f%#tfBSO3PHA4I9|H0nBB7-5Y^ekcCI>w@|-uovzU+MU3lzQ7$wk9>iZ-WMc zo-#>FpHpqI^34`Deb93FAC5I%*4H$KJjm!QNOi3rj;sxK!XgT<Lbo-BD3V=5Ey4=o z$h;G)S75;Tzrj5i)|E<0cL*^awWK(k9Z+hK(TGzS#)N@d<zdWO8I4I8nEY>|fAVO% z*demqYJfH=>3C_LrTP$~u<W>o-<32hRS9>#Ed(Co8``YF=J<cVv#_>JOdk&L{{ce4 BGL`@U literal 0 HcmV?d00001 From a90291fd01c28e5afd8322986fe83b43e8f4b691 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Sat, 29 Nov 2025 20:59:05 +0100 Subject: [PATCH 07/50] application: improved info about attributes, added #[Deprecated] --- application/cs/presenters.texy | 8 ++++++++ application/en/presenters.texy | 8 ++++++++ nette/cs/vulnerability-protection.texy | 13 +------------ nette/en/vulnerability-protection.texy | 13 +------------ 4 files changed, 18 insertions(+), 24 deletions(-) diff --git a/application/cs/presenters.texy b/application/cs/presenters.texy index ca1a69f0dd..04cd942e32 100644 --- a/application/cs/presenters.texy +++ b/application/cs/presenters.texy @@ -493,6 +493,14 @@ class MyPresenter extends Nette\Application\UI\Presenter Je důležité zdůraznit, že pokud povolíte metodu `OPTIONS`, musíte ji následně také patřičně obsloužit v rámci svého presenteru. Metoda je často používána jako tzv. preflight request, který prohlížeč automaticky odesílá před skutečným požadavkem, když je potřeba zjistit, zda je požadavek povolený z hlediska CORS (Cross-Origin Resource Sharing) politiky. Pokud metodu povolíte, ale neimplementujete správnou odpověď, může to vést k nekonzistencím a potenciálním bezpečnostním problémům. +Označení zastaralých akcí .{data-version:3.2.3} +----------------------------------------------- + +Atribut `#[Deprecated]` slouží k označení akcí, signálů nebo celých presenterů, které jsou zastaralé a měly by být v budoucnu odstraněny. Při generování odkazů na takto označené části aplikace Nette vyhodí varování, které vývojáře upozorní. + +Atribut lze aplikovat jak na celou třídu presenteru, tak na jednotlivé metody `action<Action>()`, `render<View>()` a `handle<Signal>()`. + + Další četba =========== diff --git a/application/en/presenters.texy b/application/en/presenters.texy index daa9cc87c9..7658686bbf 100644 --- a/application/en/presenters.texy +++ b/application/en/presenters.texy @@ -493,6 +493,14 @@ class MyPresenter extends Nette\Application\UI\Presenter It's important to emphasize that if you enable the `OPTIONS` method, you must subsequently handle it appropriately within your presenter. This method is often used as a so-called preflight request, which the browser automatically sends before the actual request when it's necessary to determine if the request is permissible according to the CORS (Cross-Origin Resource Sharing) policy. If you enable the method but don't implement the correct response, it can lead to inconsistencies and potential security problems. +Marking Deprecated Actions .{data-version:3.2.3} +------------------------------------------------ + +The `#[Deprecated]` attribute marks actions, signals, or entire presenters as deprecated and scheduled for future removal. When generating links to deprecated parts of the application, Nette throws a warning to alert developers. + +You can apply the attribute to either the entire presenter class or to individual `action<Action>()`, `render<View>()`, and `handle<Signal>()` methods. + + Further Reading =============== diff --git a/nette/cs/vulnerability-protection.texy b/nette/cs/vulnerability-protection.texy index d5323d3566..b28e24cf5a 100644 --- a/nette/cs/vulnerability-protection.texy +++ b/nette/cs/vulnerability-protection.texy @@ -48,18 +48,7 @@ Nette Framework **automaticky chrání formuláře a signály v presenterech** p $form->allowCrossOrigin(); ``` -nebo v případě signálu přidejte anotaci `@crossOrigin`: - -```php -/** - * @crossOrigin - */ -public function handleXyz() -{ -} -``` - -V Nette Application 3.2 můžete použít také atributy: +nebo v případě signálu přidejte atribut: ```php use Nette\Application\Attributes\Requires; diff --git a/nette/en/vulnerability-protection.texy b/nette/en/vulnerability-protection.texy index 721d493f5b..ceda856ccc 100644 --- a/nette/en/vulnerability-protection.texy +++ b/nette/en/vulnerability-protection.texy @@ -48,18 +48,7 @@ Nette Framework **automatically protects forms and signals in presenters** again $form->allowCrossOrigin(); ``` -or in the case of a signal, add the `@crossOrigin` annotation: - -```php -/** - * @crossOrigin - */ -public function handleXyz() -{ -} -``` - -In Nette Application 3.2, you can also use attributes: +or in the case of a signal, add the attribute: ```php use Nette\Application\Attributes\Requires; From b633360ed7e7da159042c5fdf9277d692e6d781a Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Sat, 29 Nov 2025 21:41:39 +0100 Subject: [PATCH 08/50] application: improved info about template variables and extensions --- application/cs/templates.texy | 115 +++++++++++++++++++++++--------- application/en/templates.texy | 119 +++++++++++++++++++++++++--------- 2 files changed, 174 insertions(+), 60 deletions(-) diff --git a/application/cs/templates.texy b/application/cs/templates.texy index feb0346ea4..72b2f1e0cf 100644 --- a/application/cs/templates.texy +++ b/application/cs/templates.texy @@ -114,15 +114,34 @@ Soubory, kde se dohledávají šablony layoutu, lze změnit překrytím metody [ Proměnné v šabloně ------------------ -Proměnné do šablony předáváme tak, že je zapíšeme do `$this->template` a potom je máme k dispozici v šabloně jako lokální proměnné: +Proměnné do šablony předáváme zápisem do `$this->template`. V šabloně jsou pak dostupné jako lokální proměnné: ```php $this->template->article = $this->articles->getById($id); ``` -Takto jednoduše můžeme do šablon předat jakékoliv proměnné. Při vývoji robustních aplikací ale bývá užitečnější se omezit. Například tak, že explicitně nadefinujeme výčet proměnných, které šablona očekává, a jejich typů. Díky tomu nám bude moci PHP kontrolovat typy, IDE správně našeptávat a statická analýza odhalovat chyby. -A jak takový výčet nadefinujeme? Jednoduše v podobě třídy a její properties. Pojmenujeme ji podobně jako presenter, jen s `Template` na konci: +Výchozí proměnné +---------------- + +Presentery a komponenty předávají do šablon několik užitečných proměnných automaticky: + +- `$basePath` je absolutní URL cesta ke kořenovému adresáři (např. `/eshop`) +- `$baseUrl` je absolutní URL ke kořenovému adresáři (např. `http://localhost/eshop`) +- `$user` je objekt [reprezentující uživatele |security:authentication] +- `$presenter` je aktuální presenter +- `$control` je aktuální komponenta nebo presenter +- `$flashes` pole [zpráv |presenters#Flash zprávy] zaslaných funkcí `flashMessage()` + +Pokud používáte vlastní třídu šablony, tyto proměnné se předají, pokud pro ně vytvoříte property. + + +Typově bezpečné šablony +----------------------- + +Při vývoji robustních aplikací je užitečné explicitně nadefinovat, jaké proměnné šablona očekává a jakého jsou typu. Získáte tak typovou kontrolu v PHP, chytré našeptávání v IDE a schopnost statické analýzy odhalovat chyby. + +Jak takový výčet nadefinovat? Jednoduše v podobě třídy s properties reprezentujícími proměnné šablony. Pojmenujeme ji podobně jako presenter, jen s `Template` na konci: ```php /** @@ -141,22 +160,22 @@ class ArticleTemplate extends Nette\Bridges\ApplicationLatte\Template } ``` -Objekt `$this->template` v presenteru bude nyní instancí třídy `ArticleTemplate`. Takže PHP bude při zápisu kontrolovat deklarované typy. A počínaje verzí PHP 8.2 upozorní i na zápis do neexistující proměnné, v předchozích verzích lze téhož dosáhnout použitím traity [Nette\SmartObject |utils:smartobject]. +Objekt `$this->template` v presenteru bude nyní instancí třídy `ArticleTemplate`. PHP tak bude při zápisu kontrolovat deklarované typy. -Anotace `@property-read` je určená pro IDE a statickou analýzu, díky ní bude fungovat našeptávání, viz "PhpStorm and code completion for $this⁠-⁠>⁠template":https://blog.nette.org/en/phpstorm-and-code-completion-for-this-template. +Anotace `@property-read` slouží pro IDE a statickou analýzu, díky ní bude fungovat našeptávání, viz "PhpStorm and code completion for $this⁠-⁠>⁠template":https://blog.nette.org/en/phpstorm-and-code-completion-for-this-template. [* phpstorm-completion.webp *] -Luxusu našeptávání si můžete dopřát i v šablonách, stačí do PhpStorm nainstalovat plugin pro Latte a uvést na začátek šablony název třídy, více v článku "Latte: jak na typový systém":https://blog.nette.org/cs/latte-jak-na-typovy-system: +Našeptávání můžete využít i přímo v šablonách. Stačí do PhpStorm nainstalovat plugin pro Latte a uvést na začátek šablony název třídy parametrů šablony, více v článku "Latte: jak na typový systém":https://blog.nette.org/cs/latte-jak-na-typovy-system: ```latte {templateType App\Presentation\Article\ArticleTemplate} ... ``` -Takto fungují i šablony v komponentách, stačí jen dodržet jmennou konvenci a pro komponentu např. `FifteenControl` vytvořit třídu šablony `FifteenTemplate`. +Totéž platí i pro komponenty. Stačí dodržet jmennou konvenci a pro komponentu např. `FifteenControl` vytvořit třídu parametrů `FifteenTemplate`. -Pokud potřebujete vytvořit `$template` jako instanci jiné třídy, využijte metodu `createTemplate()`: +Pokud potřebujete použít jinou třídu parametrů, využijte metodu `createTemplate()`: ```php public function renderDefault(): void @@ -169,21 +188,6 @@ public function renderDefault(): void ``` -Výchozí proměnné ----------------- - -Presentery a komponenty předávají do šablon několik užitečných proměnných automaticky: - -- `$basePath` je absolutní URL cesta ke kořenovému adresáři (např. `/eshop`) -- `$baseUrl` je absolutní URL ke kořenovému adresáři (např. `http://localhost/eshop`) -- `$user` je objekt [reprezentující uživatele |security:authentication] -- `$presenter` je aktuální presenter -- `$control` je aktuální komponenta nebo presenter -- `$flashes` pole [zpráv |presenters#Flash zprávy] zaslaných funkcí `flashMessage()` - -Pokud používáte vlastní třídu šablony, tyto proměnné se předají, pokud pro ně vytvoříte property. - - Vytváření odkazů ---------------- @@ -205,21 +209,67 @@ Více informací najdete v kapitole [Vytváření odkazů URL|creating-links]. Vlastní filtry, značky apod. ---------------------------- -Šablonovací systém Latte lze rozšířit o vlastní filtry, funkce, značky apod. Lze tak učinit přímo v metodě `render<View>` nebo `beforeRender()`: +Šablonovací systém Latte lze rozšířit o vlastní filtry, funkce, značky a další prvky. K dispozici jsou tři způsoby, jak to udělat, od nejrychlejších ad-hoc řešení až po architektonický přístup pro celou aplikaci. + +**Ad-hoc v metodách presenteru** + +Nejrychlejší způsob je přidat filtr nebo funkci přímo v kódu presenteru či komponenty. V presenteru je k tomu vhodná metoda `beforeRender()` nebo `render<View>()`: ```php -public function beforeRender(): void +protected function beforeRender(): void { // přidání filtru - $this->template->addFilter('foo', /* ... */); + $this->template->addFilter('money', fn($val) => round($val) . ' Kč'); + + // přidání funkce + $this->template->addFunction('isWeekend', fn($date) => $date->format('N') >= 6); +} +``` - // nebo konfigurujeme přímo objekt Latte\Engine +V šabloně pak: + +```latte +<p>Cena: {$price|money}</p> + +{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->setFeature(Latte\Feature::MigrationWarnings); } ``` -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: +**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 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 +301,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 +318,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/en/templates.texy b/application/en/templates.texy index 90f641d221..1c4d0315eb 100644 --- a/application/en/templates.texy +++ b/application/en/templates.texy @@ -111,18 +111,37 @@ Using `$this->setLayout(false)` or the `{layout none}` tag inside the template d The files where layout templates are looked up can be changed by overriding the [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()] method, which returns an array of possible file names. -Variables in the Template -------------------------- +Template Variables +------------------ -Variables are passed to the template by writing them to `$this->template`, and then they are available in the template as local variables: +Variables are passed to templates by writing them to `$this->template`. They then become available in the template as local variables: ```php $this->template->article = $this->articles->getById($id); ``` -This way, we can easily pass any variables to templates. However, when developing robust applications, it is often more useful to impose limitations. For example, by explicitly defining a list of variables that the template expects and their types. This allows PHP to perform type checking, the IDE to provide correct autocompletion, and static analysis to detect errors. -And how do we define such a list? Simply in the form of a class and its properties. We name it similarly to the presenter, but with `Template` at the end: +Default Variables +----------------- + +Presenters and components automatically pass several useful variables to templates: + +- `$basePath` is the absolute URL path to the root directory (e.g., `/eshop`) +- `$baseUrl` is the absolute URL to the root directory (e.g., `http://localhost/eshop`) +- `$user` is an object [representing the user |security:authentication] +- `$presenter` is the current presenter +- `$control` is the current component or presenter +- `$flashes` is an array of [messages |presenters#Flash Messages] sent by the `flashMessage()` function + +If you use a custom template class, these variables are passed if you create a property for them. + + +Type-Safe Templates +------------------- + +When developing robust applications, it's useful to explicitly define which variables the template expects and their types. This provides type checking in PHP, smart hints in your IDE, and enables static analysis to catch errors. + +How do you define such a list? Simply as a class with properties representing template variables. Name it similarly to the presenter, just with `Template` at the end: ```php /** @@ -141,22 +160,22 @@ class ArticleTemplate extends Nette\Bridges\ApplicationLatte\Template } ``` -The `$this->template` object in the presenter will now be an instance of the `ArticleTemplate` class. So PHP will check the declared types upon writing. And starting from PHP 8.2, it will also warn about writing to a non-existent variable; in previous versions, the same can be achieved using the [Nette\SmartObject |utils:smartobject] trait. +The `$this->template` object in the presenter will now be an instance of the `ArticleTemplate` class. PHP will thus check the declared types when writing. -The `@property-read` annotation is intended for IDEs and static analysis; thanks to it, autocompletion will work, see "PhpStorm and code completion for $this->template":https://blog.nette.org/en/phpstorm-and-code-completion-for-this-template. +The `@property-read` annotation is for the IDE and static analysis, enabling code completion, see "PhpStorm and code completion for $this⁠-⁠>⁠template":https://blog.nette.org/en/phpstorm-and-code-completion-for-this-template. [* phpstorm-completion.webp *] -You can enjoy the luxury of autocompletion in templates too; just install the Latte plugin for PhpStorm and specify the class name at the beginning of the template, more in the article "Latte: How to Use Type System":https://blog.nette.org/en/latte-how-to-use-type-system: +You can also use code completion directly in templates. Just install the Latte plugin for PhpStorm and specify the template parameter class name at the beginning of the template, more in the article "Latte: how to use the type system":https://blog.nette.org/en/latte-how-to-use-type-system: ```latte {templateType App\Presentation\Article\ArticleTemplate} ... ``` -This is also how templates work in components; just follow the naming convention and create a template class `FifteenTemplate` for a component like `FifteenControl`. +The same applies to components. Just follow the naming convention and create a parameter class `FifteenTemplate` for a component like `FifteenControl`. -If you need to create `$template` as an instance of another class, use the `createTemplate()` method: +If you need to use a different parameter class, use the `createTemplate()` method: ```php public function renderDefault(): void @@ -169,21 +188,6 @@ public function renderDefault(): void ``` -Default Variables ------------------ - -Presenters and components automatically pass several useful variables to templates: - -- `$basePath` is the absolute URL path to the root directory (e.g., `/eshop`) -- `$baseUrl` is the absolute URL to the root directory (e.g., `http://localhost/eshop`) -- `$user` is an object [representing the user |security:authentication] -- `$presenter` is the current presenter -- `$control` is the current component or presenter -- `$flashes` is an array of [messages |presenters#Flash Messages] sent by the `flashMessage()` function - -If you use a custom template class, these variables are passed if you create a property for them. - - Creating Links -------------- @@ -205,21 +209,67 @@ More information can be found in the chapter [Creating URL Links|creating-links] Custom Filters, Tags, etc. -------------------------- -The Latte templating system can be extended with custom filters, functions, tags, etc. This can be done directly in the `render<View>` or `beforeRender()` method: +The Latte templating system can be extended with custom filters, functions, tags, and other elements. There are three approaches available, ranging from quick ad-hoc solutions to architectural patterns for entire applications. + +**Ad-hoc in Presenter Methods** + +The quickest approach is adding filters or functions directly in presenter or component code. In presenters, the `beforeRender()` or `render<View>()` methods work well for this: ```php -public function beforeRender(): void +protected function beforeRender(): void { // adding a filter - $this->template->addFilter('foo', /* ... */); + $this->template->addFilter('money', fn($val) => '$' . number_format($val, 2)); + + // adding a function + $this->template->addFunction('isWeekend', fn($date) => $date->format('N') >= 6); +} +``` + +In the template: + +```latte +<p>Price: {$price|money}</p> + +{if isWeekend($now)} ... {/if} +``` - // or configure the Latte\Engine object directly +For more complex logic, you can configure the `Latte\Engine` object directly: + +```php +protected function beforeRender(): void +{ $latte = $this->template->getLatte(); $latte->setFeature(Latte\Feature::MigrationWarnings); } ``` -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: +**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 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 +301,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 +318,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 ----------- From 797a5fea5036db584372d3002370c60c72e0511d Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Mon, 1 Dec 2025 19:05:14 +0100 Subject: [PATCH 09/50] nette/utils 4.0.10 --- utils/cs/datetime.texy | 14 +++++++++++ utils/cs/helpers.texy | 11 +++++++++ utils/cs/iterables.texy | 21 +++++++++++++++++ utils/cs/type.texy | 51 ++++++++++++++++++++++++++++++++++++++--- utils/en/datetime.texy | 14 +++++++++++ utils/en/helpers.texy | 11 +++++++++ utils/en/iterables.texy | 21 +++++++++++++++++ utils/en/type.texy | 51 ++++++++++++++++++++++++++++++++++++++--- 8 files changed, 188 insertions(+), 6 deletions(-) diff --git a/utils/cs/datetime.texy b/utils/cs/datetime.texy index 6b2788d3e1..f685af7909 100644 --- a/utils/cs/datetime.texy +++ b/utils/cs/datetime.texy @@ -4,6 +4,9 @@ Datum a čas .[perex] [api:Nette\Utils\DateTime] je třída, která rozšiřuje nativní [php:DateTime] o další funkce. +Oproti svému předchůdci je striktní. Zatímco PHP **tiše akceptuje** nesmyslná data jako `0000-00-00` (převede na `-0001-11-30`) nebo `2024-02-31` (převede na `2024-03-02`), `Nette\Utils\DateTime` v takových případech vyhodí výjimku. + +Zároveň **opravuje chování** při přechodu na letní/zimní čas, kdy v nativním PHP může přičtení relativního času (např. `+100 minutes`) "vést k dřívějšímu výslednému času":https://phpfashion.com/cs/100-minut-je-mene-nez-50-paradoxy-php-pri-zmene-casu než přičtení kratšího úseku (např. `+50 minutes`). Nette zajišťuje, že aritmetika funguje intuitivně a `+100 minutes` je vždy více než `+50 minutes`. Instalace: @@ -46,6 +49,17 @@ DateTime::createFromFormat('d.m.Y', '26.02.1994', 'Europe/London'); ``` +static relativeToSeconds(string $str): int .[method]{data-version:4.0.7} +------------------------------------------------------------------------ +Převede relativní časový údaj na sekundy. Hodí se pro převod časů jako `5 minutes` nebo `2 hours` na číselnou hodnotu. + +```php +DateTime::relativeToSeconds('1 minute'); // 60 +DateTime::relativeToSeconds('10 minutes'); // 600 +DateTime::relativeToSeconds('-1 hour'); // -3600 +``` + + modifyClone(string $modify=''): static .[method] ------------------------------------------------ Vytvoří kopii s upraveným časem. diff --git a/utils/cs/helpers.texy b/utils/cs/helpers.texy index 2b5bcbe27e..49e37ebaed 100644 --- a/utils/cs/helpers.texy +++ b/utils/cs/helpers.texy @@ -84,3 +84,14 @@ Helpers::getSuggestion($items, 'fo'); // 'foo' Helpers::getSuggestion($items, 'barr'); // 'bar' Helpers::getSuggestion($items, 'baz'); // 'bar', ne 'baz' ``` + + +splitClassName(string $name): array .[method]{data-version:4.0.10} +------------------------------------------------------------------ + +Rozdělí celý název třídy v PHP na jmenný prostor a zkrácený název třídy. Vrací pole dvou řetězců, kde první prvek je namespace a druhý název třídy. + +```php +Helpers::splitClassName('Nette\Utils\Helpers'); // ['Nette\Utils', 'Helpers'] +Helpers::splitClassName('Foo'); // ['', 'Foo'] +``` diff --git a/utils/cs/iterables.texy b/utils/cs/iterables.texy index 77af7696df..ebf73344b7 100644 --- a/utils/cs/iterables.texy +++ b/utils/cs/iterables.texy @@ -140,6 +140,27 @@ $memoized = Iterables::memoize($iterator); Tato metoda je užitečná v situacích, kdy potřebujete vícekrát projít stejnou sadu dat, ale původní iterátor neumožňuje opakovanou iteraci nebo by opakované procházení bylo nákladné (např. při čtení dat z databáze nebo souboru). +repeatable(callable $factory): IteratorAggregate .[method]{data-version:4.0.10} +------------------------------------------------------------------------------- + +Umožňuje opakovanou iteraci objektů, které to běžně nedovolují, typicky [PHP generátorů |https://www.php.net/manual/en/language.generators.overview.php]. Metoda `repeatable()` tento problém elegantně řeší: místo samotného iterátoru jí předáte funkci, která iterátor vytváří. Tato továrna je pak zavolána automaticky při každém novém průchodu cyklem. + +```php +// Běžný generátor, který nelze projít dvakrát +$generator = function () { + yield 'A'; + yield 'B'; +}; + +$iterator = Iterables::repeatable($generator); + +foreach ($iterator as $v) echo $v; // Vypíše: AB +foreach ($iterator as $v) echo $v; // Vypíše: AB (generátor se spustil znovu) +``` + +Tato metoda je alternativou k [#memoize()] v situacích, kdy pracujete s **velkým objemem dat**, jelikož `repeatable()` si data neukládá, ale při každém průchodu je generuje znovu. + + some(iterable $iterable, callable $predicate): bool .[method] ------------------------------------------------------------- diff --git a/utils/cs/type.texy b/utils/cs/type.texy index d4c539ee67..f2af19e5f8 100644 --- a/utils/cs/type.texy +++ b/utils/cs/type.texy @@ -2,8 +2,13 @@ PHP Typ ******* .[perex] -[api:Nette\Utils\Type] je třída pro práci s datovými typy PHP. +[api:Nette\Utils\Type] reprezentuje datový typ PHP. Slouží k analýze, porovnávání a manipulaci s typy, ať už pocházejí z řetězce nebo z reflexe. +PHP má dnes velmi bohatý typový systém: od skalárních typů (`int`, `string`) přes objekty a rozhraní až po složené typy (union `A|B`, intersection `A&B` nebo disjunktivní normální formy `(A&B)|D`). Navíc existují speciální typy jako `void`, `never`, `mixed` nebo relativní `self` či `static`. + +Práce s těmito typy nativně, zejména přes `ReflectionType`, je často zdlouhavá, protože musíte rekurzivně rozlišovat mezi `ReflectionNamedType`, `ReflectionUnionType` a dalšími objekty. Třída `Nette\Utils\Type` toto vše zapouzdřuje a poskytuje **jednotné a srozumitelné API** pro práci s jakýmkoliv typem, který PHP podporuje. + +Umožňuje například snadno zjistit, zda jeden typ [akceptuje|#allows] druhý (kompatibilita), [rozšiřovat typy|#with] nebo převádět reflexe na čitelný zápis. Instalace: @@ -45,6 +50,25 @@ echo $type; // 'Foo|Bar' ``` +fromValue(mixed $value): Type .[method]{data-version:4.0.10} +------------------------------------------------------------ + +Statická metoda, která vytvoří objekt Type podle typu předané hodnoty. + +```php +$type = Type::fromValue('hello'); // 'string' +$type = Type::fromValue(123); // 'int' +$type = Type::fromValue(new stdClass); // 'stdClass' +``` + +Pro resources vrací `mixed`, protože PHP typ `resource` nezná. U anonymních tříd vrací nejbližšího předka nebo typ `object`. + +```php +$obj = new class extends Foo { }; +$type = Type::fromValue($obj); // 'Foo' +``` + + getNames(): (string|array)[] .[method] -------------------------------------- @@ -183,8 +207,8 @@ $type->isClassKeyword(); // false ``` -allows(string $type): bool .[method] ------------------------------------- +allows(string|Type $type): bool .[method] +----------------------------------------- Metoda `allows()` ověřuje kompatibilitu typů. Například umožní zjistit, jestli hodnota určitého typu by mohla být předaná jako parametr. @@ -197,3 +221,24 @@ $type->allows('Foo'); // false $type = Type::fromString('mixed'); $type->allows('null'); // true ``` + + +with(string|Type $type): Type .[method]{data-version:4.0.10} +------------------------------------------------------------ + +Vrací objekt Type, který akceptuje jak původní typ, tak i nově přidaný. Vytváří tzv. union type. + +Metoda je chytrá a typy zbytečně nezdvojuje. Pokud přidáte typ, který je již obsažen, nebo je nadmnožinou stávajícího typu (např. přidání `mixed` k `string`), vrátí se zjednodušený výsledek. + +```php +$type = Type::fromString('string'); + +// Rozšíření na nullable string +echo $type->with('null'); // '?string' + +// Vytvoření union typu +echo $type->with('int'); // 'string|int' + +// Přidání typu, který "přebije" vše ostatní +echo $type->with('mixed'); // 'mixed' +``` diff --git a/utils/en/datetime.texy b/utils/en/datetime.texy index 3fc7cdf0ac..5b00d789d3 100644 --- a/utils/en/datetime.texy +++ b/utils/en/datetime.texy @@ -4,6 +4,9 @@ Date and Time .[perex] [api:Nette\Utils\DateTime] is a class that extends the native [php:DateTime] with additional useful features. +Compared to the native class, it is strict. While PHP **silently accepts** invalid dates like `0000-00-00` (converts to `-0001-11-30`) or `2024-02-31` (converts to `2024-03-02`), `Nette\Utils\DateTime` throws an exception in such cases. + +It also **fixes the behavior** during Daylight Saving Time (DST) transitions, where in native PHP adding a relative time (e.g., `+100 minutes`) can "result in an earlier time":https://phpfashion.com/en/100-minutes-is-less-than-50-php-paradoxes-during-time-changes than adding a shorter period (e.g., `+50 minutes`). Nette ensures that arithmetic works intuitively and `+100 minutes` is always more than `+50 minutes`. Installation: @@ -46,6 +49,17 @@ DateTime::createFromFormat('d.m.Y', '26.02.1994', 'Europe/London'); // create wi ``` +static relativeToSeconds(string $str): int .[method]{data-version:4.0.7} +------------------------------------------------------------------------ +Converts a relative time string to seconds. It is useful for converting times like `5 minutes` or `2 hours` to a numeric value. + +```php +DateTime::relativeToSeconds('1 minute'); // 60 +DateTime::relativeToSeconds('10 minutes'); // 600 +DateTime::relativeToSeconds('-1 hour'); // -3600 +``` + + modifyClone(string $modify=''): static .[method] ------------------------------------------------ Creates a copy with a modified time. diff --git a/utils/en/helpers.texy b/utils/en/helpers.texy index 280cdb8e4c..4c69556b64 100644 --- a/utils/en/helpers.texy +++ b/utils/en/helpers.texy @@ -84,3 +84,14 @@ Helpers::getSuggestion($items, 'fo'); // 'foo' Helpers::getSuggestion($items, 'barr'); // 'bar' Helpers::getSuggestion($items, 'baz'); // 'bar', not 'baz' ``` + + +splitClassName(string $name): array .[method]{data-version:4.0.10} +------------------------------------------------------------------ + +Splits a PHP class name into a namespace and a short class name. Returns an array of two strings where the first is the namespace and the second is the class name. + +```php +Helpers::splitClassName('Nette\Utils\Helpers'); // ['Nette\Utils', 'Helpers'] +Helpers::splitClassName('Foo'); // ['', 'Foo'] +``` diff --git a/utils/en/iterables.texy b/utils/en/iterables.texy index a5f06f8be0..56c86f60d7 100644 --- a/utils/en/iterables.texy +++ b/utils/en/iterables.texy @@ -140,6 +140,27 @@ $memoized = Iterables::memoize($iterator); This method is useful in situations where you need to iterate over the same dataset multiple times, but the original iterator doesn't allow repeated iteration, or re-traversing would be costly (e.g., reading data from a database or file). +repeatable(callable $factory): IteratorAggregate .[method]{data-version:4.0.10} +------------------------------------------------------------------------------- + +Allows repeated iteration of objects that otherwise do not support it, typically [PHP generators |https://www.php.net/manual/en/language.generators.overview.php]. The `repeatable()` method solves this problem elegantly: instead of passing the iterator itself, you pass a function that creates it. This factory is then called automatically during each iteration loop. + +```php +// A standard generator that cannot be iterated twice +$generator = function () { + yield 'A'; + yield 'B'; +}; + +$iterator = Iterables::repeatable($generator); + +foreach ($iterator as $v) echo $v; // Prints: AB +foreach ($iterator as $v) echo $v; // Prints: AB (generator ran again) +``` + +This method is an alternative to [#memoize()] in situations where you are working with **large amounts of data**, since `repeatable()` does not cache data, but generates it again during each iteration. + + some(iterable $iterable, callable $predicate): bool .[method] ------------------------------------------------------------- diff --git a/utils/en/type.texy b/utils/en/type.texy index 08886b2e91..f462bbb31c 100644 --- a/utils/en/type.texy +++ b/utils/en/type.texy @@ -2,8 +2,13 @@ PHP Type ******** .[perex] -[api:Nette\Utils\Type] is a class for working with PHP data types. +[api:Nette\Utils\Type] represents a PHP data type. It is used for analyzing, comparing, and manipulating types, whether obtained from a string or reflection. +PHP currently has a very rich type system: from scalar types (`int`, `string`), through objects and interfaces, to complex types (union `A|B`, intersection `A&B`, or disjunctive normal forms `(A&B)|D`). Additionally, there are special types like `void`, `never`, `mixed`, or relative types `self` and `static`. + +Working with these types natively, especially via `ReflectionType`, is often cumbersome because you must recursively distinguish between `ReflectionNamedType`, `ReflectionUnionType`, and other objects. The `Nette\Utils\Type` class encapsulates all of this and provides a **unified and intuitive API** for working with any type supported by PHP. + +For example, it allows you to easily check if one type [accepts|#allows] another (compatibility), [extend types|#with], or convert reflections into a readable notation. Installation: @@ -45,6 +50,25 @@ echo $type; // 'Foo|Bar' ``` +fromValue(mixed $value): Type .[method]{data-version:4.0.10} +------------------------------------------------------------ + +Static method that creates a Type object based on the type of the passed value. + +```php +$type = Type::fromValue('hello'); // 'string' +$type = Type::fromValue(123); // 'int' +$type = Type::fromValue(new stdClass); // 'stdClass' +``` + +For resources, it returns `mixed`, as PHP does not support the `resource` type. For anonymous classes, it returns the name of the nearest ancestor or `object`. + +```php +$obj = new class extends Foo { }; +$type = Type::fromValue($obj); // 'Foo' +``` + + getNames(): (string|array)[] .[method] -------------------------------------- @@ -183,8 +207,8 @@ $type->isClassKeyword(); // false ``` -allows(string $type): bool .[method] ------------------------------------- +allows(string|Type $type): bool .[method] +----------------------------------------- The `allows()` method checks type compatibility. For example, it can determine if a value of a certain type could be passed as a parameter to a function expecting this type. @@ -197,3 +221,24 @@ $type->allows('Foo'); // false $type = Type::fromString('mixed'); $type->allows('null'); // true ``` + + +with(string|Type $type): Type .[method]{data-version:4.0.10} +------------------------------------------------------------ + +Returns a Type object that accepts both the original type and the one being added. It creates a so-called union type. + +The method is clever and does not duplicate types unnecessarily. If you add a type that is already present, or is a superset of the current type (e.g., adding `mixed` to `string`), the result is simplified. + +```php +$type = Type::fromString('string'); + +// Extending to nullable string +echo $type->with('null'); // '?string' + +// Creating a union type +echo $type->with('int'); // 'string|int' + +// Adding a type that supersedes everything +echo $type->with('mixed'); // 'mixed' +``` From 73a93e1ff67d68f44ecc8b39c386564722584fb7 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Sat, 29 Nov 2025 20:59:05 +0100 Subject: [PATCH 10/50] nette/application 3.2.9 --- application/cs/templates.texy | 14 ++++++++++++++ application/en/templates.texy | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/application/cs/templates.texy b/application/cs/templates.texy index 72b2f1e0cf..568b40837e 100644 --- a/application/cs/templates.texy +++ b/application/cs/templates.texy @@ -120,6 +120,20 @@ Proměnné do šablony předáváme zápisem do `$this->template`. V šabloně j $this->template->article = $this->articles->getById($id); ``` +Pokud chcete, aby se hodnota určité property automaticky předala do šablony jako proměnná, označte ji atributem `#[TemplateVariable]` a viditelností public nebo protected: .{data-version:3.2.9} + +```php +use Nette\Application\Attributes\TemplateVariable; + +class ArticlePresenter extends Nette\Application\UI\Presenter +{ + #[TemplateVariable] + public string $siteName = 'Můj blog'; +} +``` + +Pokud do šablony vložíte proměnnou se stejným názvem, `#[TemplateVariable]` ji nepřepíše. + Výchozí proměnné ---------------- diff --git a/application/en/templates.texy b/application/en/templates.texy index 1c4d0315eb..6a5ba43fd3 100644 --- a/application/en/templates.texy +++ b/application/en/templates.texy @@ -120,6 +120,20 @@ Variables are passed to templates by writing them to `$this->template`. They the $this->template->article = $this->articles->getById($id); ``` +To automatically pass a property value to the template as a variable, mark it with the `#[TemplateVariable]` attribute and public or protected visibility: .{data-version:3.2.9} + +```php +use Nette\Application\Attributes\TemplateVariable; + +class ArticlePresenter extends Nette\Application\UI\Presenter +{ + #[TemplateVariable] + public string $siteName = 'My blog'; +} +``` + +If you pass a variable with the same name to the template, `#[TemplateVariable]` won’t override it. + Default Variables ----------------- From 3a3bc52c02ed2c55ac8a5b8d5b127bf63c336447 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Sat, 27 Dec 2025 19:02:41 +0100 Subject: [PATCH 11/50] adding missing stuff in nette/http --- http/cs/request.texy | 29 +++++++++++++++++++++++++++++ http/cs/response.texy | 10 +++++----- http/cs/urls.texy | 6 ++++++ http/en/request.texy | 29 +++++++++++++++++++++++++++++ http/en/response.texy | 10 +++++----- http/en/urls.texy | 6 ++++++ nette/cs/glossary.texy | 7 +++++++ nette/en/glossary.texy | 7 +++++++ 8 files changed, 94 insertions(+), 10 deletions(-) diff --git a/http/cs/request.texy b/http/cs/request.texy index 5dc90de308..1827f489e0 100644 --- a/http/cs/request.texy +++ b/http/cs/request.texy @@ -184,6 +184,30 @@ $body = $httpRequest->getRawBody(); ``` +getOrigin(): ?UrlImmutable .[method] +------------------------------------ +Vrací origin, ze kterého požadavek přišel. Origin se skládá z protokolu, hostname a portu - například `https://example.com:8080`. Vrací `null`, pokud hlavička origin není přítomna nebo je nastavena na `'null'`. + +```php +$origin = $httpRequest->getOrigin(); +echo $origin; // https://example.com:8080 +echo $origin?->getHost(); // example.com +``` + +Prohlížeč posílá hlavičku `Origin` v následujících případech: +- Požadavky mezi doménami (AJAX volání na jinou doménu) +- POST, PUT, DELETE a další modifikující požadavky +- Požadavky provedené pomocí Fetch API + +Prohlížeč NEPOSÍLÁ hlavičku `Origin` při: +- Běžných GET požadavcích na stejnou doménu (navigace v rámci téže domény) +- Přímé navigaci zadáním URL do adresního řádku +- Požadavcích z jiných klientů než prohlížeče (pokud není ručně přidána) + +.[note] +Na rozdíl od hlavičky `Referer` obsahuje `Origin` pouze schéma, host a port - nikoli celou cestu URL. To ji činí vhodnější pro bezpečnostní kontroly při zachování soukromí uživatele. Hlavička `Origin` se primárně používá pro validaci [CORS |nette:glossary#Cross-Origin Resource Sharing (CORS)] (Cross-Origin Resource Sharing). + + detectLanguage(array $langs): ?string .[method] ----------------------------------------------- Detekuje jazyk. Jako parametr `$lang` předáme pole s jazyky, které aplikace podporuje, a ona vrátí ten, který by viděl návštěvníkův prohlížeč nejraději. Nejsou to žádná kouzla, jen se využívá hlavičky `Accept-Language`. Pokud nedojde k žádné shodě, vrací `null`. @@ -389,6 +413,11 @@ getTemporaryFile(): string .[method] Vrací cestu k dočasné lokaci uploadovaného souboru. V případě, že upload nebyl úspěšný, vrací `''`. +__toString(): string .[method] +------------------------------ +Vrací cestu k dočasnému umístění nahraného souboru. To umožňuje objekt `FileUpload` použít přímo jako řetězec. + + isImage(): bool .[method] ------------------------- Vrací `true`, pokud nahraný soubor je obrázek ve formátu JPEG, PNG, GIF, WebP nebo AVIF. Detekce probíhá na základě jeho signatury a neověřuje se integrita celého souboru. Zda není obrázek poškozený lze zjistit například pokusem o jeho [načtení |#toImage]. diff --git a/http/cs/response.texy b/http/cs/response.texy index baea11f900..4732bc7a76 100644 --- a/http/cs/response.texy +++ b/http/cs/response.texy @@ -34,9 +34,9 @@ isSent(): bool .[method] Vrací, zda už došlo k odeslání hlaviček ze serveru do prohlížeče, a tedy již není možné odesílat hlavičky či měnit stavový kód. -setHeader(string $name, string $value) .[method] ------------------------------------------------- -Odešle HTTP hlavičku a **přepíše** dříve odeslanou hlavičkou stejného jména. +setHeader(string $name, ?string $value) .[method] +------------------------------------------------- +Odešle HTTP hlavičku a **přepíše** dříve odeslanou hlavičkou stejného jména. Pokud je `$value` `null`, bude záhlaví odstraněno. ```php $httpResponse->setHeader('Pragma', 'no-cache'); @@ -115,8 +115,8 @@ $httpResponse->sendAsFile('faktura.pdf'); ``` -setCookie(string $name, string $value, $time, ?string $path=null, ?string $domain=null, ?bool $secure=null, ?bool $httpOnly=null, ?string $sameSite=null) .[method] -------------------------------------------------------------------------------------------------------------------------------------------------------------------- +setCookie(string $name, string $value, $time, ?string $path=null, ?string $domain=null, ?bool $secure=null, ?bool $httpOnly=null, ?string $sameSite='Lax') .[method] +-------------------------------------------------------------------------------------------------------------------------------------------------------------------- Odešle cookie. Výchozí hodnoty parametrů: | `$path` | `'/'` | cookie má dosah na všechny cesty v (sub)doméně *(konfigurovatelné)* diff --git a/http/cs/urls.texy b/http/cs/urls.texy index 9e722a9d7c..e40a157e18 100644 --- a/http/cs/urls.texy +++ b/http/cs/urls.texy @@ -82,6 +82,7 @@ Můžeme pracovat i s jednotlivými query parametry pomocí: |--------------------------------------------------- | `setQuery(string\|array $query)` | `getQueryParameters(): array` | `setQueryParameter(string $name, $val)` | `getQueryParameter(string $name)` +| `appendQuery(string|array $query)` | getDomain(int $level = 2): string .[method] @@ -107,6 +108,11 @@ $url->isEqual('https://nette.org'); ``` +canonicalize() .[method] +------------------------ +Převede URL do kanonického tvaru. To zahrnuje například seřazení parametrů v query stringu podle abecedy, převod hostname na malá písmena a odstranění nadbytečných znaků. + + Url::isAbsolute(string $url): bool .[method]{data-version:3.3.2} ---------------------------------------------------------------- Ověřuje, zda je URL absolutní. URL je považována za absolutní, pokud začíná schématem (např. http, https, ftp) následovaným dvojtečkou. diff --git a/http/en/request.texy b/http/en/request.texy index ae45438508..47e0232f54 100644 --- a/http/en/request.texy +++ b/http/en/request.texy @@ -184,6 +184,30 @@ $body = $httpRequest->getRawBody(); ``` +getOrigin(): ?UrlImmutable .[method] +------------------------------------ +Returns the origin from which the request came. An origin consists of the scheme (protocol), hostname, and port - for example, `https://example.com:8080`. Returns `null` if the origin header is not present or is set to `'null'`. + +```php +$origin = $httpRequest->getOrigin(); +echo $origin; // https://example.com:8080 +echo $origin?->getHost(); // example.com +``` + +The browser sends the `Origin` header in the following cases: +- Cross-origin requests (AJAX calls to a different domain) +- POST, PUT, DELETE, and other modifying requests +- Requests made using the Fetch API + +The browser does NOT send the `Origin` header for: +- Regular GET requests to the same domain (same-origin navigation) +- Direct navigation by typing a URL into the address bar +- Requests from non-browser clients + +.[note] +Unlike the `Referer` header, `Origin` contains only the scheme, host, and port - not the full URL path. This makes it more suitable for security checks while preserving user privacy. The `Origin` header is primarily used for [CORS |nette:glossary#Cross-Origin Resource Sharing (CORS)] (Cross-Origin Resource Sharing) validation. + + detectLanguage(array $langs): ?string .[method] ----------------------------------------------- Detects the language. Pass an array of languages supported by the application as the `$langs` parameter, and it will return the one preferred by the visitor's browser. It's not magic; it just uses the `Accept-Language` header. If no match is found, it returns `null`. @@ -389,6 +413,11 @@ getTemporaryFile(): string .[method] Returns the path to the temporary location of the uploaded file. If the upload was not successful, it returns `''`. +__toString(): string .[method] +------------------------------ +Returns the path to the temporary location of the uploaded file. This allows the `FileUpload` object to be used directly as a string. + + isImage(): bool .[method] ------------------------- Returns `true` if the uploaded file is a JPEG, PNG, GIF, WebP, or AVIF image. Detection is based on its signature and does not verify the integrity of the entire file. Whether an image is corrupted can be determined, for example, by trying to [load it |#toImage]. diff --git a/http/en/response.texy b/http/en/response.texy index 7654f039e9..7dbd4dca00 100644 --- a/http/en/response.texy +++ b/http/en/response.texy @@ -34,9 +34,9 @@ isSent(): bool .[method] Returns whether headers have already been sent from the server to the browser, meaning it is no longer possible to send headers or change the status code. -setHeader(string $name, string $value) .[method] ------------------------------------------------- -Sends an HTTP header and **overwrites** a previously sent header of the same name. +setHeader(string $name, ?string $value) .[method] +------------------------------------------------- +Sends an HTTP header and **overwrites** a previously sent header of the same name. If `$value` is `null`, the header will be removed. ```php $httpResponse->setHeader('Pragma', 'no-cache'); @@ -115,8 +115,8 @@ $httpResponse->sendAsFile('invoice.pdf'); ``` -setCookie(string $name, string $value, $time, ?string $path=null, ?string $domain=null, ?bool $secure=null, ?bool $httpOnly=null, ?string $sameSite=null) .[method] -------------------------------------------------------------------------------------------------------------------------------------------------------------------- +setCookie(string $name, string $value, $time, ?string $path=null, ?string $domain=null, ?bool $secure=null, ?bool $httpOnly=null, ?string $sameSite='Lax') .[method] +-------------------------------------------------------------------------------------------------------------------------------------------------------------------- Sends a cookie. Default parameter values: | `$path` | `'/'` | cookie is available for all paths within the (sub)domain *(configurable)* diff --git a/http/en/urls.texy b/http/en/urls.texy index 84a947c12f..608fa0064f 100644 --- a/http/en/urls.texy +++ b/http/en/urls.texy @@ -82,6 +82,7 @@ We can also work with individual query parameters using: |--------------------------------------------------- | `setQuery(string\|array $query)` | `getQueryParameters(): array` | `setQueryParameter(string $name, $val)` | `getQueryParameter(string $name)` +| `appendQuery(string|array $query)` | getDomain(int $level = 2): string .[method] @@ -107,6 +108,11 @@ $url->isEqual('https://nette.org'); ``` +canonicalize() .[method] +------------------------ +Converts the URL to canonical form. This includes, for example, sorting the parameters in the query string alphabetically, converting the hostname to lowercase, and removing redundant characters. + + Url::isAbsolute(string $url): bool .[method]{data-version:3.3.2} ---------------------------------------------------------------- Checks if a URL is absolute. A URL is considered absolute if it begins with a scheme (e.g., http, https, ftp) followed by a colon. diff --git a/nette/cs/glossary.texy b/nette/cs/glossary.texy index 05ade5cdbc..7b273ba481 100644 --- a/nette/cs/glossary.texy +++ b/nette/cs/glossary.texy @@ -36,6 +36,13 @@ Cross-Site Request Forgery (CSRF) Nette Framework **automaticky chrání formuláře a signály v presenterech** před tímto typem útoku. A to tím, že zabraňuje jejich odeslání či vyvolání z jiné domény. +Cross-Origin Resource Sharing (CORS) +------------------------------------ +CORS je bezpečnostní mechanismus, který umožňuje webové stránce provádět JavaScriptové požadavky na jinou doménu, než ze které byla stránka načtena. Bez CORS prohlížeče takové požadavky z bezpečnostních důvodů blokují. + +Například pokud vaše webová stránka běží na `https://myapp.com` a pokusí se pomocí JavaScriptu (AJAX, Fetch API) načíst data z `https://api.example.com`, prohlížeč ověří, zda API server tento požadavek mezi doménami povoluje. API server musí odpovědět speciálními HTTP hlavičkami, jako je `Access-Control-Allow-Origin: https://myapp.com`, aby udělil povolení. + + Dependency Injection -------------------- Dependency Injection (DI) je návrhový vzor, který říká, jak oddělit vytváření objektů od jejich závislostí. Tedy že třída není zodpovědná za vytváření nebo inicializaci svých závislostí, ale místo toho jsou jí tyto závislosti poskytovány externím kódem (tím může i [DI kontejner |#Dependency Injection kontejner]). Výhoda spočívá v tom, že umožňuje větší flexibilitu kódu, lepší srozumitelnost a snazší testování aplikace, protože závislosti jsou snadno nahraditelné a izolované od ostatních částí kódu. Více v kapitole [Co je Dependency Injection? |dependency-injection:introduction] diff --git a/nette/en/glossary.texy b/nette/en/glossary.texy index e23d51d384..bc555933a0 100644 --- a/nette/en/glossary.texy +++ b/nette/en/glossary.texy @@ -36,6 +36,13 @@ A Cross-Site Request Forgery attack involves the attacker luring a victim to a p Nette Framework **automatically protects forms and signals in presenters** against this type of attack by preventing them from being submitted or triggered from another domain. +Cross-Origin Resource Sharing (CORS) +------------------------------------ +CORS is a security mechanism that allows a web page to make JavaScript requests to a different domain than the one from which the page was loaded. Without CORS, browsers block such requests for security reasons. + +For example, if your website runs at `https://myapp.com` and tries to fetch data from `https://api.example.com` using JavaScript (AJAX, Fetch API), the browser will check if the API server allows this cross-origin request. The API server must respond with special HTTP headers, such as `Access-Control-Allow-Origin: https://myapp.com`, to grant permission. + + Dependency Injection -------------------- Dependency Injection (DI) is a design pattern that dictates how to separate the creation of objects from their dependencies. This means a class is not responsible for creating or initializing its dependencies; instead, these dependencies are provided by external code (which could be a [DI container |#Dependency Injection Container]). The advantage lies in increased code flexibility, better understandability, and easier application testing, as dependencies are easily replaceable and isolated from other code parts. More in the chapter [What is Dependency Injection? |dependency-injection:introduction] From 7f1fe2c1f4980b7b356d9f8fff19268613ade0df Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Sun, 4 Jan 2026 06:13:49 +0100 Subject: [PATCH 12/50] used first-class callables --- best-practices/cs/creating-editing-form.texy | 16 ++++++++-------- best-practices/cs/form-reuse.texy | 8 ++++---- best-practices/cs/lets-create-contact-form.texy | 4 ++-- best-practices/cs/restore-request.texy | 4 ++-- best-practices/en/creating-editing-form.texy | 16 ++++++++-------- best-practices/en/form-reuse.texy | 8 ++++---- best-practices/en/lets-create-contact-form.texy | 4 ++-- best-practices/en/restore-request.texy | 4 ++-- dependency-injection/cs/services.texy | 2 +- dependency-injection/en/services.texy | 2 +- forms/cs/in-presenter.texy | 14 +++++++------- forms/cs/validation.texy | 4 ++-- forms/en/in-presenter.texy | 16 ++++++++-------- forms/en/validation.texy | 4 ++-- 14 files changed, 53 insertions(+), 53 deletions(-) diff --git a/best-practices/cs/creating-editing-form.texy b/best-practices/cs/creating-editing-form.texy index 8babb5c58c..4530f060d4 100644 --- a/best-practices/cs/creating-editing-form.texy +++ b/best-practices/cs/creating-editing-form.texy @@ -29,11 +29,11 @@ class RecordPresenter extends Nette\Application\UI\Presenter // ... přidáme políčka formuláře ... - $form->onSuccess[] = [$this, 'recordFormSucceeded']; + $form->onSuccess[] = $this->recordFormSucceeded(...); return $form; } - public function recordFormSucceeded(Form $form, array $data): void + private function recordFormSucceeded(Form $form, array $data): void { $this->facade->add($data); // přidání záznamu do databáze $this->flashMessage('Successfully added'); @@ -91,11 +91,11 @@ class RecordPresenter extends Nette\Application\UI\Presenter // ... přidáme políčka formuláře ... $form->setDefaults($this->record); // nastavení výchozích hodnot - $form->onSuccess[] = [$this, 'recordFormSucceeded']; + $form->onSuccess[] = $this->recordFormSucceeded(...); return $form; } - public function recordFormSucceeded(Form $form, array $data): void + private function recordFormSucceeded(Form $form, array $data): void { $this->facade->update($this->record->id, $data); // aktualizace záznamu $this->flashMessage('Successfully updated'); @@ -153,7 +153,7 @@ class RecordPresenter extends Nette\Application\UI\Presenter public function actionAdd(): void { $form = $this->getComponent('recordForm'); - $form->onSuccess[] = [$this, 'addingFormSucceeded']; + $form->onSuccess[] = $this->addingFormSucceeded(...); } public function actionEdit(int $id): void @@ -168,7 +168,7 @@ class RecordPresenter extends Nette\Application\UI\Presenter $form = $this->getComponent('recordForm'); $form->setDefaults($record); // nastavení výchozích hodnot - $form->onSuccess[] = [$this, 'editingFormSucceeded']; + $form->onSuccess[] = $this->editingFormSucceeded(...); } protected function createComponentRecordForm(): Form @@ -185,14 +185,14 @@ class RecordPresenter extends Nette\Application\UI\Presenter return $form; } - public function addingFormSucceeded(Form $form, array $data): void + private function addingFormSucceeded(Form $form, array $data): void { $this->facade->add($data); // přidání záznamu do databáze $this->flashMessage('Successfully added'); $this->redirect('...'); } - public function editingFormSucceeded(Form $form, array $data): void + private function editingFormSucceeded(Form $form, array $data): void { $id = (int) $this->getParameter('id'); $this->facade->update($id, $data); // aktualizace záznamu diff --git a/best-practices/cs/form-reuse.texy b/best-practices/cs/form-reuse.texy index bd6c3b8afd..ac95ca2617 100644 --- a/best-practices/cs/form-reuse.texy +++ b/best-practices/cs/form-reuse.texy @@ -193,11 +193,11 @@ class EditFormFactory $form->addText('title', 'Titulek:'); // zde se přidávají další formulářová pole $form->addSubmit('send', 'Odeslat'); - $form->onSuccess[] = [$this, 'processForm']; + $form->onSuccess[] = $this->processForm(...); return $form; } - public function processForm(Form $form, array $data): void + private function processForm(Form $form, array $data): void { try { // zpracování odeslaných dat @@ -284,12 +284,12 @@ class EditControl extends Nette\Application\UI\Control $form->addText('title', 'Titulek:'); // zde se přidávají další formulářová pole $form->addSubmit('send', 'Odeslat'); - $form->onSuccess[] = [$this, 'processForm']; + $form->onSuccess[] = $this->processForm(...); return $form; } - public function processForm(Form $form, array $data): void + private function processForm(Form $form, array $data): void { try { // zpracování odeslaných dat diff --git a/best-practices/cs/lets-create-contact-form.texy b/best-practices/cs/lets-create-contact-form.texy index ec298951be..e5d44812fa 100644 --- a/best-practices/cs/lets-create-contact-form.texy +++ b/best-practices/cs/lets-create-contact-form.texy @@ -24,11 +24,11 @@ class HomePresenter extends Presenter $form->addTextarea('message', 'Zpráva:') ->setRequired('Zadejte zprávu'); $form->addSubmit('send', 'Odeslat'); - $form->onSuccess[] = [$this, 'contactFormSucceeded']; + $form->onSuccess[] = $this->contactFormSucceeded(...); return $form; } - public function contactFormSucceeded(Form $form, $data): void + private function contactFormSucceeded(Form $form, $data): void { // odeslání emailu } diff --git a/best-practices/cs/restore-request.texy b/best-practices/cs/restore-request.texy index 46a25c7f87..05a54331ae 100644 --- a/best-practices/cs/restore-request.texy +++ b/best-practices/cs/restore-request.texy @@ -41,11 +41,11 @@ class SignPresenter extends Nette\Application\UI\Presenter { $form = new Nette\Application\UI\Form; // ... přidáme políčka formuláře ... - $form->onSuccess[] = [$this, 'signInFormSubmitted']; + $form->onSuccess[] = $this->signInFormSubmitted(...); return $form; } - public function signInFormSubmitted($form) + private function signInFormSubmitted($form) { // ... tady uživatele přihlásíme ... diff --git a/best-practices/en/creating-editing-form.texy b/best-practices/en/creating-editing-form.texy index 9349473ca3..27e0af202b 100644 --- a/best-practices/en/creating-editing-form.texy +++ b/best-practices/en/creating-editing-form.texy @@ -29,11 +29,11 @@ class RecordPresenter extends Nette\Application\UI\Presenter // ... add form fields ... - $form->onSuccess[] = [$this, 'recordFormSucceeded']; + $form->onSuccess[] = $this->recordFormSucceeded(...); return $form; } - public function recordFormSucceeded(Form $form, array $data): void + private function recordFormSucceeded(Form $form, array $data): void { $this->facade->add($data); // add record to the database $this->flashMessage('Successfully added'); @@ -91,11 +91,11 @@ class RecordPresenter extends Nette\Application\UI\Presenter // ... add form fields ... $form->setDefaults($this->record); // set default values - $form->onSuccess[] = [$this, 'recordFormSucceeded']; + $form->onSuccess[] = $this->recordFormSucceeded(...); return $form; } - public function recordFormSucceeded(Form $form, array $data): void + private function recordFormSucceeded(Form $form, array $data): void { $this->facade->update($this->record->id, $data); // update record $this->flashMessage('Successfully updated'); @@ -153,7 +153,7 @@ class RecordPresenter extends Nette\Application\UI\Presenter public function actionAdd(): void { $form = $this->getComponent('recordForm'); - $form->onSuccess[] = [$this, 'addingFormSucceeded']; + $form->onSuccess[] = $this->addingFormSucceeded(...); } public function actionEdit(int $id): void @@ -168,7 +168,7 @@ class RecordPresenter extends Nette\Application\UI\Presenter $form = $this->getComponent('recordForm'); $form->setDefaults($record); // set default values - $form->onSuccess[] = [$this, 'editingFormSucceeded']; + $form->onSuccess[] = $this->editingFormSucceeded(...); } protected function createComponentRecordForm(): Form @@ -185,14 +185,14 @@ class RecordPresenter extends Nette\Application\UI\Presenter return $form; } - public function addingFormSucceeded(Form $form, array $data): void + private function addingFormSucceeded(Form $form, array $data): void { $this->facade->add($data); // add record to the database $this->flashMessage('Successfully added'); $this->redirect('...'); } - public function editingFormSucceeded(Form $form, array $data): void + private function editingFormSucceeded(Form $form, array $data): void { $id = (int) $this->getParameter('id'); $this->facade->update($id, $data); // update record diff --git a/best-practices/en/form-reuse.texy b/best-practices/en/form-reuse.texy index c2027ab6f0..2d91c006fc 100644 --- a/best-practices/en/form-reuse.texy +++ b/best-practices/en/form-reuse.texy @@ -193,11 +193,11 @@ class EditFormFactory $form->addText('title', 'Title:'); // additional form fields are added here $form->addSubmit('send', 'Save'); - $form->onSuccess[] = [$this, 'processForm']; + $form->onSuccess[] = $this->processForm(...); return $form; } - public function processForm(Form $form, array $data): void + private function processForm(Form $form, array $data): void { try { // processing of submitted data @@ -284,12 +284,12 @@ class EditControl extends Nette\Application\UI\Control $form->addText('title', 'Title:'); // additional form fields are added here $form->addSubmit('send', 'Save'); - $form->onSuccess[] = [$this, 'processForm']; + $form->onSuccess[] = $this->processForm(...); return $form; } - public function processForm(Form $form, array $data): void + private function processForm(Form $form, array $data): void { try { // processing of submitted data diff --git a/best-practices/en/lets-create-contact-form.texy b/best-practices/en/lets-create-contact-form.texy index dab7982265..0fd677048d 100644 --- a/best-practices/en/lets-create-contact-form.texy +++ b/best-practices/en/lets-create-contact-form.texy @@ -24,11 +24,11 @@ class HomePresenter extends Presenter $form->addTextarea('message', 'Message:') ->setRequired('Please enter a message'); $form->addSubmit('send', 'Send'); - $form->onSuccess[] = [$this, 'contactFormSucceeded']; + $form->onSuccess[] = $this->contactFormSucceeded(...); return $form; } - public function contactFormSucceeded(Form $form, $data): void + private function contactFormSucceeded(Form $form, $data): void { // sending an email } diff --git a/best-practices/en/restore-request.texy b/best-practices/en/restore-request.texy index 6a95370d1c..cea14d7b66 100644 --- a/best-practices/en/restore-request.texy +++ b/best-practices/en/restore-request.texy @@ -41,11 +41,11 @@ class SignPresenter extends Nette\Application\UI\Presenter { $form = new Nette\Application\UI\Form; // ... add form fields ... - $form->onSuccess[] = [$this, 'signInFormSubmitted']; + $form->onSuccess[] = $this->signInFormSubmitted(...); return $form; } - public function signInFormSubmitted($form) + private function signInFormSubmitted($form) { // ... log the user in here ... diff --git a/dependency-injection/cs/services.texy b/dependency-injection/cs/services.texy index 00a55fed56..8a86b230e9 100644 --- a/dependency-injection/cs/services.texy +++ b/dependency-injection/cs/services.texy @@ -181,7 +181,7 @@ public function createServiceFoo(): Foo { $service = new Foo; $service->value = 123; - $service->onClick[] = [$this->getService('bar'), 'clickHandler']; + $service->onClick[] = $this->getService('bar')->clickHandler(...); return $service; } ``` diff --git a/dependency-injection/en/services.texy b/dependency-injection/en/services.texy index 7b3ad6b364..d724a229cf 100644 --- a/dependency-injection/en/services.texy +++ b/dependency-injection/en/services.texy @@ -181,7 +181,7 @@ public function createServiceFoo(): Foo { $service = new Foo; $service->value = 123; - $service->onClick[] = [$this->getService('bar'), 'clickHandler']; + $service->onClick[] = $this->getService('bar')->clickHandler(...); return $service; } ``` diff --git a/forms/cs/in-presenter.texy b/forms/cs/in-presenter.texy index 33ac7fa95d..2c827d31f7 100644 --- a/forms/cs/in-presenter.texy +++ b/forms/cs/in-presenter.texy @@ -19,7 +19,7 @@ $form = new Form; $form->addText('name', 'Jméno:'); $form->addPassword('password', 'Heslo:'); $form->addSubmit('send', 'Registrovat'); -$form->onSuccess[] = [$this, 'formSucceeded']; +$form->onSuccess[] = $this->formSucceeded(...); ``` a v prohlížeči se zobrazí takto: @@ -42,11 +42,11 @@ class HomePresenter extends Nette\Application\UI\Presenter $form->addText('name', 'Jméno:'); $form->addPassword('password', 'Heslo:'); $form->addSubmit('send', 'Registrovat'); - $form->onSuccess[] = [$this, 'formSucceeded']; + $form->onSuccess[] = $this->formSucceeded(...); return $form; } - public function formSucceeded(Form $form, $data): void + private function formSucceeded(Form $form, $data): void { // tady zpracujeme data odeslaná formulářem // $data->name obsahuje jméno @@ -303,16 +303,16 @@ Pokud má formulář více než jedno tlačítko, potřebujeme zpravidla rozliš ```php $form->addSubmit('save', 'Uložit') - ->onClick[] = [$this, 'saveButtonPressed']; + ->onClick[] = $this->saveButtonPressed(...); $form->addSubmit('delete', 'Smazat') - ->onClick[] = [$this, 'deleteButtonPressed']; + ->onClick[] = $this->deleteButtonPressed(...); ``` Tyto handlery se volají pouze v případě validně vyplněného formuláře, stejně jako v případě události `onSuccess`. Rozdíl je v tom, že jako první parametr se místo formulář může předat odesílací tlačítko, záleží na typu, který uvedete: ```php -public function saveButtonPressed(Nette\Forms\Controls\Button $button, $data) +private function saveButtonPressed(Nette\Forms\Controls\Button $button, $data) { $form = $button->getForm(); // ... @@ -403,7 +403,7 @@ protected function createComponentSignInForm(): Form $form = $this->formFactory->create(); // můžeme formulář pozměnit, zde například měníme popisku na tlačítku $form['send']->setCaption('Pokračovat'); - $form->onSuccess[] = [$this, 'signInFormSuceeded']; // a přidáme handler + $form->onSuccess[] = $this->signInFormSuceeded(...); // a přidáme handler return $form; } ``` diff --git a/forms/cs/validation.texy b/forms/cs/validation.texy index e313be57b9..479e12df74 100644 --- a/forms/cs/validation.texy +++ b/forms/cs/validation.texy @@ -223,11 +223,11 @@ protected function createComponentSignInForm(): Form { $form = new Form; // ... - $form->onValidate[] = [$this, 'validateSignInForm']; + $form->onValidate[] = $this->validateSignInForm(...); return $form; } -public function validateSignInForm(Form $form, \stdClass $data): void +private function validateSignInForm(Form $form, \stdClass $data): void { if ($data->foo > 1 && $data->bar > 5) { $form->addError('Tato kombinace není možná.'); diff --git a/forms/en/in-presenter.texy b/forms/en/in-presenter.texy index a1543bcaa1..b4cde43641 100644 --- a/forms/en/in-presenter.texy +++ b/forms/en/in-presenter.texy @@ -19,14 +19,14 @@ $form = new Form; $form->addText('name', 'Name:'); $form->addPassword('password', 'Password:'); $form->addSubmit('send', 'Sign up'); -$form->onSuccess[] = [$this, 'formSucceeded']; +$form->onSuccess[] = $this->formSucceeded(...); ``` and in the browser, it will be displayed like this: [* form-en.webp *] -A form in a presenter is an object of the `Nette\Application\UI\Form` class; its predecessor `Nette\Forms\Form` is intended for standalone use. We added controls named name, password, and a submit button. Finally, the line `$form->onSuccess[] = [$this, 'formSucceeded'];` states that after submission and successful validation, the method `$this->formSucceeded()` should be called. +A form in a presenter is an object of the `Nette\Application\UI\Form` class; its predecessor `Nette\Forms\Form` is intended for standalone use. We added controls named name, password, and a submit button. Finally, the line `$form->onSuccess` states that after submission and successful validation, the method `$this->formSucceeded()` should be called. From the presenter's perspective, the form is a regular component. Therefore, it is treated as a component and integrated into the presenter using a [factory method |application:components#Factory Methods]. It will look like this: @@ -42,11 +42,11 @@ class HomePresenter extends Nette\Application\UI\Presenter $form->addText('name', 'Name:'); $form->addPassword('password', 'Password:'); $form->addSubmit('send', 'Sign up'); - $form->onSuccess[] = [$this, 'formSucceeded']; + $form->onSuccess[] = $this->formSucceeded(...); return $form; } - public function formSucceeded(Form $form, $data): void + private function formSucceeded(Form $form, $data): void { // here we will process the data sent by the form // $data->name contains name @@ -303,16 +303,16 @@ If the form has more than one button, we usually need to distinguish which one w ```php $form->addSubmit('save', 'Save') - ->onClick[] = [$this, 'saveButtonPressed']; + ->onClick[] = $this->saveButtonPressed(...); $form->addSubmit('delete', 'Delete') - ->onClick[] = [$this, 'deleteButtonPressed']; + ->onClick[] = $this->deleteButtonPressed(...); ``` These handlers are called only if the form is validly filled (unless validation is disabled for the button), just like the `onSuccess` event. The difference is that the first parameter passed can be the submit button object instead of the form, depending on the type hint you specify: ```php -public function saveButtonPressed(Nette\Forms\Controls\Button $button, $data) +private function saveButtonPressed(Nette\Forms\Controls\Button $button, $data) { $form = $button->getForm(); // ... @@ -403,7 +403,7 @@ protected function createComponentSignInForm(): Form $form = $this->formFactory->create(); // we can change the form, here for example we change the label on the button $form['login']->setCaption('Continue'); - $form->onSuccess[] = [$this, 'signInFormSubmitted']; // and add handler + $form->onSuccess[] = $this->signInFormSubmitted(...); // and add handler return $form; } ``` diff --git a/forms/en/validation.texy b/forms/en/validation.texy index 0c32b3bb85..d9a9626cc6 100644 --- a/forms/en/validation.texy +++ b/forms/en/validation.texy @@ -223,11 +223,11 @@ protected function createComponentSignInForm(): Form { $form = new Form; // ... - $form->onValidate[] = [$this, 'validateSignInForm']; + $form->onValidate[] = $this->validateSignInForm(...); return $form; } -public function validateSignInForm(Form $form, \stdClass $data): void +private function validateSignInForm(Form $form, \stdClass $data): void { if ($data->foo > 1 && $data->bar > 5) { $form->addError('This combination is not possible.'); From 77e111a525310bb44bceebf117dbc7f9189a5306 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Tue, 6 Jan 2026 15:54:33 +0100 Subject: [PATCH 13/50] added coding standard section about global functions and constants --- contributing/cs/coding-standard.texy | 17 +++++++++++++++++ contributing/en/coding-standard.texy | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/contributing/cs/coding-standard.texy b/contributing/cs/coding-standard.texy index d9e3cc8c85..aaef617655 100644 --- a/contributing/cs/coding-standard.texy +++ b/contributing/cs/coding-standard.texy @@ -109,6 +109,23 @@ public function find(string $dir, array $options): array ``` +Globální funkce a konstanty +=========================== + +Globální funkce a konstanty se píší bez úvodního zpětného lomítka, tedy `count($arr)` nikoliv `\count($arr)`. Pro funkce, které umí PHP optimalizovat, uvedeme na začátku souboru `use function`, aby je kompilátor mohl přeložit efektivněji. Jedná se zejména o funkce jako `count`, `strlen`, `is_array`, `is_string`, `is_scalar`, `sprintf` aj. Funkce se uvádějí na jednom řádku, aby úvodní blok importů nebyl zbytečně velký: + +```php +use Nette; +use function count, is_array, is_scalar, sprintf; +``` + +Výjimečně takto uvádíme i konstanty, u kterých může znalost hodnoty posloužit kompilátoru: + +```php +use const PHP_OS_FAMILY; +``` + + Tabulátory místo mezer ====================== diff --git a/contributing/en/coding-standard.texy b/contributing/en/coding-standard.texy index e98f821d4d..df9a0a86cb 100644 --- a/contributing/en/coding-standard.texy +++ b/contributing/en/coding-standard.texy @@ -109,6 +109,23 @@ public function find(string $dir, array $options): array ``` +Global Functions and Constants +============================== + +Global functions and constants are written without a leading backslash, i.e., `count($arr)` not `\count($arr)`. For functions that PHP can optimize, add `use function` at the beginning of the file so the compiler can translate them more efficiently. These include functions like `count`, `strlen`, `is_array`, `is_string`, `is_scalar`, `sprintf`, etc. Functions are listed on a single line to keep the import block compact: + +```php +use Nette; +use function count, is_array, is_scalar, sprintf; +``` + +Occasionally, we also import constants whose value knowledge may help the compiler: + +```php +use const PHP_OS_FAMILY; +``` + + Tabs Instead of Spaces ====================== From 10ce072b61d20e26d9477fbb5ffe75a27edc23eb Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Tue, 6 Jan 2026 23:36:00 +0100 Subject: [PATCH 14/50] Tester 2.6: updated documentation for php.ini loading behavior change --- tester/cs/guide.texy | 8 ++++---- tester/cs/running-tests.texy | 27 +++++++++++---------------- tester/en/guide.texy | 8 ++++---- tester/en/running-tests.texy | 27 +++++++++++---------------- 4 files changed, 30 insertions(+), 40 deletions(-) diff --git a/tester/cs/guide.texy b/tester/cs/guide.texy index c2fc76c3fe..bc75c64ec9 100644 --- a/tester/cs/guide.texy +++ b/tester/cs/guide.texy @@ -116,10 +116,9 @@ Výstup může vypadat takto: /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.5.2 + |_| \___ /___) |_| \___ |_|_\ v2.6.0 -Note: No php.ini is used. -PHP 8.3.2 (cli) | php -n | 8 threads +PHP 8.5.2 (cli) | php | 8 threads ........s................<span style="color: #FFF; background-color: #900">F</span>......... @@ -160,7 +159,8 @@ Podporované verze PHP | verze | kompatibilní s PHP |------------------|------------------- -| Tester 2.5 | PHP 8.0 – 8.3 +| Tester 2.6 | PHP 8.0 – 8.5 +| Tester 2.5 | PHP 8.0 – 8.5 | Tester 2.4 | PHP 7.2 – 8.2 | Tester 2.3 | PHP 7.1 – 8.0 | Tester 2.1 – 2.2 | PHP 7.1 – 7.3 diff --git a/tester/cs/running-tests.texy b/tester/cs/running-tests.texy index c2afe8df0a..667d8253de 100644 --- a/tester/cs/running-tests.texy +++ b/tester/cs/running-tests.texy @@ -23,10 +23,9 @@ Výstup může vypadat třeba takto: /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.5.2 + |_| \___ /___) |_| \___ |_|_\ v2.6.0 -Note: No php.ini is used. -PHP 8.3.2 (cli) | php -n | 8 threads +PHP 8.5.2 (cli) | php | 8 threads ........s.......................... @@ -37,9 +36,6 @@ Při opakovaném spuštění nejprve provádí testy, které při předchozím b Pokud žádný test neselže, návratový kód Testeru je nula. Jinak je návratový kód nenulový. -.[warning] -Tester spouští PHP procesy bez `php.ini`. Detailněji v části [#Vlastní php.ini]. - Parametry příkazové řádky ========================= @@ -56,8 +52,8 @@ Usage: Options: -p <path> Specify PHP interpreter to run (default: php). - -c <path> Look for php.ini file (or look in directory) <path>. - -C Use system-wide php.ini. + -c <path> Use custom php.ini, ignore system configuration. + -C With -c, include system configuration as well. -d <key=value>... Define INI entry 'key' with value 'value'. -s Show information about skipped tests. --stop-on-fail Stop execution upon the first failure. @@ -86,12 +82,12 @@ tester -p /home/user/php-7.2.0-beta/php-cgi tests -c <path> .[filter] ------------------- -Určuje, který `php.ini` se bude používat při spouštění testů. Ve výchozím stavu se žádný php.ini nepoužije. Více v části [#Vlastní php.ini]. +Použije vlastní `php.ini` soubor a ignoruje systémovou konfiguraci. Více v části [#Vlastní php.ini]. -C .[filter] ------------ -Použije se systémové `php.ini`. Na UNIXu také všechny příslušné INI soubory `/etc/php/{sapi}/conf.d/*.ini`. Více v části [#Vlastní php.ini]. +Při použití společně s `-c` zachová i systémovou konfiguraci (neignoruje ji). Více v části [#Vlastní php.ini]. -d <key=value> .[filter] @@ -221,11 +217,7 @@ Použijeme současně s volbou `--coverage`. `<path>` je cesta ke zdrojovým kó Vlastní php.ini =============== -Tester spouští PHP procesy s parametrem `-n`, což znamená, že žádné `php.ini` není načteno. V UNIXu ani ty z `/etc/php/conf.d/*.ini`. To zajistí shodné prostředí pro běh testů, ale také vyřadí všechna PHP rozšíření běžně načtená systémovým PHP. - -Chcete-li načítání systémových php.ini souborů zachovat, použijte parametr `-C`. - -Pokud nějaká rozšíření nebo speciální INI nastavení pro testy potřebujete, doporučujeme vytvoření vlastního `php.ini` souboru, který bude distribuován s testy. Tester pak spouštíme s parametrem `-c`, například `tester -c tests/php.ini tests`, kde INI soubor může vypadat takto: +Pro testy můžete použít vlastní `php.ini` soubor. Pokud potřebujete specifická rozšíření nebo speciální INI nastavení, doporučujeme vytvořit vlastní `php.ini`, který bude distribuován s testy. Tester pak spouštíme s parametrem `-c`, například `tester -c tests/php.ini tests`, kde INI soubor může vypadat takto: ```ini [PHP] @@ -236,4 +228,7 @@ extension=php_pdo_pgsql.dll memory_limit=512M ``` -Spuštění Testeru v UNIXu se systémovým `php.ini`, například `tester -c /etc/php/cli/php.ini` nenačte ostatní INI z `/etc/php/conf.d/*.ini`. To je vlastnost PHP, ne Testeru. +Při použití `-c` Tester **ignoruje systémovou konfiguraci** (spouští PHP s příznakem `-n`). Chcete-li zachovat i systémovou konfiguraci, přidejte volbu `-C`: `tester -c tests/php.ini -C tests`. Ani při kombinaci `-c` a `-C` se nenačtou v UNIXu ostatní INI soubory z `/etc/php/conf.d/*.ini`. To je vlastnost PHP, ne Testeru. + +.[note] +Do verze 2.6 Tester bez uvedení `-c` spouštěl PHP s parametrem `-n`, tedy bez php.ini; volba `-C` toto potlačila. Od verze 2.6 se systémové php.ini načítá automaticky. Chování při použití `-c` zůstává stejné. diff --git a/tester/en/guide.texy b/tester/en/guide.texy index ed2dcdd8b8..e5361308ac 100644 --- a/tester/en/guide.texy +++ b/tester/en/guide.texy @@ -116,10 +116,9 @@ The output may look like this: /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.5.2 + |_| \___ /___) |_| \___ |_|_\ v2.6.0 -Note: No php.ini is used. -PHP 8.3.2 (cli) | php -n | 8 threads +PHP 8.5.2 (cli) | php | 8 threads ........s................<span style="color: #FFF; background-color: #900">F</span>......... @@ -160,7 +159,8 @@ Supported PHP versions | Version | Compatible with PHP |------------------|------------------- -| Tester 2.5 | PHP 8.0 – 8.3 +| Tester 2.6 | PHP 8.0 – 8.5 +| Tester 2.5 | PHP 8.0 – 8.5 | Tester 2.4 | PHP 7.2 – 8.2 | Tester 2.3 | PHP 7.1 – 8.0 | Tester 2.1 – 2.2 | PHP 7.1 – 7.3 diff --git a/tester/en/running-tests.texy b/tester/en/running-tests.texy index 553ba3e3be..0f89235870 100644 --- a/tester/en/running-tests.texy +++ b/tester/en/running-tests.texy @@ -23,10 +23,9 @@ The output may look like this: /--pre .[terminal] _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) - |_| \___ /___) |_| \___ |_|_\ v2.5.2 + |_| \___ /___) |_| \___ |_|_\ v2.6.0 -Note: No php.ini is used. -PHP 8.3.2 (cli) | php -n | 8 threads +PHP 8.5.2 (cli) | php | 8 threads ........s.......................... @@ -37,9 +36,6 @@ When run again, it first executes the tests that failed in the previous run, so The Tester's exit code is zero if no test fails. Otherwise, it is non-zero. -.[warning] -The Tester runs PHP processes without `php.ini`. More details in the [#Own php.ini] section. - Command-Line Options ==================== @@ -56,8 +52,8 @@ Usage: Options: -p <path> Specify PHP interpreter to run (default: php). - -c <path> Look for php.ini file (or look in directory) <path>. - -C Use system-wide php.ini. + -c <path> Use custom php.ini, ignore system configuration. + -C With -c, include system configuration as well. -d <key=value>... Define INI entry 'key' with value 'value'. -s Show information about skipped tests. --stop-on-fail Stop execution upon the first failure. @@ -86,12 +82,12 @@ tester -p /home/user/php-7.2.0-beta/php-cgi tests -c <path> .[filter] ------------------- -Specifies which `php.ini` will be used when running tests. By default, no php.ini is used. See [#Own php.ini] for more information. +Uses a custom `php.ini` file and ignores the system configuration. This is useful for running tests with specific settings. See [#Own php.ini] for more information. -C .[filter] ------------ -A system-wide `php.ini` is used. So on UNIX platform, all the `/etc/php/{sapi}/conf.d/*.ini` files too. See [#Own php.ini] section. +When used together with `-c`, includes the system configuration as well (does not ignore it). See [#Own php.ini] section. -d <key=value> .[filter] @@ -221,11 +217,7 @@ Used in conjunction with the `--coverage` option. `<path>` is the path to the so Own php.ini =========== -Tester runs PHP processes with the `-n` option, which means that no `php.ini` is loaded (not even those from `/etc/php/conf.d/*.ini` on UNIX systems). This ensures a consistent environment for running tests, but it also disables all external PHP extensions normally loaded by the system's PHP. - -To preserve the loading of system php.ini files, use the `-C` parameter. - -If you need specific extensions or special INI settings for your tests, we recommend creating your own `php.ini` file and distributing it with your tests. Then, run Tester with the `-c` option, for example, `tester -c tests/php.ini tests`. The INI file might look like this: +You can use a custom `php.ini` file for your tests. If you need specific extensions or special INI settings, we recommend creating your own `php.ini` file and distributing it with your tests. Then, run Tester with the `-c` option, for example, `tester -c tests/php.ini tests`. The INI file might look like this: ```ini [PHP] @@ -236,4 +228,7 @@ extension=php_pdo_pgsql.dll memory_limit=512M ``` -Running Tester on UNIX with a system `php.ini`, like `tester -c /etc/php/cli/php.ini`, does not load other INIs from `/etc/php/conf.d/*.ini`. This is a PHP behavior, not specific to Tester. +When using `-c`, Tester **ignores the system configuration** (runs PHP with `-n` flag). If you want to include system configuration as well, add the `-C` option: `tester -c tests/php.ini -C tests`. Even when combining `-c` and `-C`, other INI files from `/etc/php/conf.d/*.ini` are not loaded on UNIX. This is a PHP behavior, not specific to Tester. + +.[note] +Prior to version 2.6, without `-c`, Tester ran PHP with `-n` flag, i.e., without php.ini; the `-C` option suppressed this. From version 2.6, system php.ini is loaded by default. The behavior when using `-c` remains unchanged. From 2ad63b8b36f0741b4347a76d3530c124fe0a5a53 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Thu, 8 Jan 2026 03:31:42 +0100 Subject: [PATCH 15/50] added ai.nette.org --- ai/cs/@home.texy | 11 + ai/cs/@meta.texy | 1 + ai/en/@home.texy | 11 + ai/en/@left-menu.texy | 5 + ai/en/@meta.texy | 1 + ai/en/claude-code.texy | 269 ++++++++++++++++++++++ ai/en/getting-started.texy | 260 +++++++++++++++++++++ ai/en/guide.texy | 128 +++++++++++ ai/en/mcp-inspector.texy | 448 +++++++++++++++++++++++++++++++++++++ ai/en/tips.texy | 296 ++++++++++++++++++++++++ ai/meta.json | 1 + 11 files changed, 1431 insertions(+) create mode 100644 ai/cs/@home.texy create mode 100644 ai/cs/@meta.texy create mode 100644 ai/en/@home.texy create mode 100644 ai/en/@left-menu.texy create mode 100644 ai/en/@meta.texy create mode 100644 ai/en/claude-code.texy create mode 100644 ai/en/getting-started.texy create mode 100644 ai/en/guide.texy create mode 100644 ai/en/mcp-inspector.texy create mode 100644 ai/en/tips.texy create mode 100644 ai/meta.json 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..6d9e63e82e --- /dev/null +++ b/ai/en/claude-code.texy @@ -0,0 +1,269 @@ +Claude Code Plugin +****************** + +<div class=perex> + +The Nette plugin gives Claude deep knowledge of the framework. Instead of generic PHP advice, you get recommendations that follow Nette conventions – from presenters and forms to Latte templates and database queries. + +The plugin includes: +- A **broad set of skills** covering all major areas of Nette development +- **Automatic validation** that catches errors in Latte, NEON and JavaScript files +- **MCP Inspector integration** for real-time application introspection + +</div> + + +Installation +============ + +If you haven't installed Claude Code yet, see the [complete setup guide |getting-started]. Once Claude Code is running, install the Nette plugin: + +```shell +/plugin marketplace add nette/claude-code +/plugin install nette@nette +``` + + +How Skills Work +=============== + +You don't need to activate skills manually. They turn on automatically based on what you're talking about. + +- Ask about "presenter structure" → the `nette-architecture` skill activates +- Ask about "form validation" → the `nette-forms` skill activates +- Ask about "Latte filters" → the `latte-templates` skill activates +- Ask about a "BlueScreen error" → the `tracy-debugging` skill activates + +This means you get relevant, context-aware help without having to think about which skill you need. + + +Available Skills +================ + +Here's what each skill covers: + + +nette-architecture +------------------ + +When you're designing your application structure, this skill guides you through: + +- **Directory organization** – Where to put presenters, services, entities, and components +- **Module design** – How to split your application into logical modules (Admin, Front, Api) +- **Presenter patterns** – When to use base presenters, how to handle authentication +- **Evolution strategy** – Start minimal, grow organically, refactor when needed + +The key principle: Don't over-engineer. Create subdirectories when you have 5+ related files, not before. + + +nette-configuration +------------------- + +Everything about the DI container and NEON configuration: + +- **Service registration** – How to define services in `services.neon` +- **Autowiring** – When it works automatically and when you need explicit configuration +- **Parameters** – How to use configuration parameters across your application +- **Extensions** – Working with DI extensions from Nette and third parties + + +nette-database +-------------- + +Covers both the raw SQL approach and the Database Explorer: + +- **Database Explorer** – Using `Selection` for queries, `ActiveRow` for entities +- **Entity conventions** – The `Row` suffix pattern, type hints with `@property-read` +- **Relationships** – Navigating foreign keys with colon notation +- **When to use what** – Explorer for CRUD, raw SQL for complex analytics + +Example: Claude knows that `->where('category.slug', $slug)` automatically joins the category table. + + +nette-forms +----------- + +Creating and handling forms the Nette way: + +- **Controls** – All built-in controls from text inputs to file uploads +- **Validation** – Built-in rules, custom validators, conditional validation +- **Rendering** – Manual rendering, Bootstrap integration, custom renderers +- **Patterns** – Create/edit forms, form components, AJAX submissions + + +nette-schema +------------ + +Data validation and normalization with the Schema component: + +- **Expect class** – Building validation schemas for arrays and objects +- **Configuration schemas** – Validating NEON configuration in DI extensions +- **Type coercion** – Automatic conversion of strings to integers, dates, etc. +- **Custom validators** – Adding your own validation rules + +Example: Claude knows how to create schemas like: + +```php +$schema = Expect::structure([ + 'name' => Expect::string()->required(), + 'age' => Expect::int()->min(0)->max(120), + 'email' => Expect::string(), + 'roles' => Expect::listOf('string')->default([]), +]); +``` + + +nette-tester +------------ + +Writing tests with Nette Tester: + +- **Test structure** – The `.phpt` format, `@testCase` annotation, file organization +- **Assertions** – All `Assert::*` methods: `same()`, `equal()`, `exception()`, `match()`, and more +- **Fixtures** – Setting up test data, mocking dependencies, database transactions +- **Running tests** – Command-line options, parallel execution, code coverage + +Example: Claude can generate proper test files: + +```php +/** @testCase */ +class UserServiceTest extends TestCase +{ + public function testCreateUser(): void + { + $service = new UserService($this->mockDatabase()); + $user = $service->create(['name' => 'John']); + Assert::same('John', $user->name); + } +} +``` + + +tracy-debugging +--------------- + +Working with the Tracy debugger: + +- **BlueScreen** – Reading exception details, stack traces, source highlights +- **Tracy Bar** – Interpreting embedded SQL query logs, timing, and memory usage at the bottom of every page +- **`dump()` workflow** – Inserting `dump($variable)` calls and reading the output back through curl or the browser +- **Production logs** – Investigating `log/exception-*.html` snapshots and `log/error.log` +- **Chrome MCP integration** – Pulling Tracy errors out of the browser console with `list_console_messages()` instead of taking screenshots + +Especially useful for 500 errors, blank pages, N+1 query issues, or whenever Claude fetches a local PHP URL and needs to interpret what came back. + + +nette-utils +----------- + +The utility classes that make PHP development easier: + +- **Arrays** – `Nette\Utils\Arrays` with `get()`, `getRef()`, `map()`, `flatten()`, and more +- **Strings** – Unicode-safe operations: `webalize()`, `truncate()`, `contains()`, `startsWith()` +- **Finder** – File system traversal with filtering by name, size, date +- **Image** – Resize, crop, sharpen with automatic format detection +- **Json** – Safe JSON encoding/decoding with proper error handling +- **Validators** – Email, URL, numeric validation helpers +- **DateTime** – Immutable date/time with Czech locale support + + +frontend-development +-------------------- + +Integrating frontend tools with Nette: + +- **Vite** – Setting up Vite for modern JavaScript/TypeScript development, HMR configuration +- **Nette Assets** – Using the asset system for cache-busted URLs in production +- **Tailwind CSS** – Configuration for Tailwind with Latte templates, purging unused styles +- **ESLint & Prettier** – Code quality tools integration +- **Build scripts** – npm/package.json scripts for development and production builds + +Claude can help configure `vite.config.js` to work with Nette's directory structure and generate proper asset references in Latte templates. + + +latte-templates +--------------- + +Everything about the Latte templating engine: + +- **Syntax** – Tags, filters, blocks, and inheritance +- **Security** – Auto-escaping, content-aware output +- **Custom filters** – Creating and registering your own filters +- **Template classes** – Using typed templates for better IDE support + + +neon-format +----------- + +The NEON configuration format: + +- **Syntax** – Mappings, sequences, entities, and multiline strings +- **Common patterns** – Service definitions, parameter references +- **Debugging** – Finding and fixing syntax errors + + +Automatic Validation +==================== + +One of the most useful features is automatic validation. After every file edit, the plugin checks for errors: + +| What | How It Works | +|------|--------------| +| **Latte templates** | Runs `latte-lint` to check syntax after every `.latte` edit | +| **NEON files** | Validates NEON syntax after every `.neon` edit | +| **JavaScript / TypeScript** | Runs `eslint --fix` after every `.js`, `.ts`, `.mjs` or `.mts` edit (only if the project has an ESLint config) | + +If there's a syntax error in your Latte template, Claude knows about it immediately and can suggest a fix. No more discovering errors in the browser. + + +Plugin for Framework Contributors +================================= + +If you're contributing to Nette itself, there's an additional plugin with coding standards: + +```shell +/plugin install nette-dev@nette +``` + +| Skill | What It Covers | +|-------|----------------| +| `php-coding-standards` | Nette's PHP coding style – indentation, naming, structure | +| `php-doc` | PHPDoc conventions – when to document, what format to use | +| `commit-messages` | How to write commit messages for Nette repositories | +| `phpstan-analysis` | How to resolve PHPStan errors – prefer refactoring over phpDoc annotations over ignoring – plus common Nette patterns and baseline management | + + +Automatic PHP Style Fixing +========================== + +For automatic code style fixing after every PHP file edit, install the optional php-fixer plugin: + +```shell +/plugin install php-fixer@nette +/install-php-fixer +``` + +The second command installs `nette/coding-standard` globally. After that, every PHP file you edit will be automatically formatted according to Nette coding standards. + +The plugin also comes with the `php-auto-fixer` skill, which teaches Claude about one subtle pitfall: the fixer removes unused `use` statements, so a `use` added in a separate edit before the code that references it gets stripped. Claude knows to add imports together with the code that uses them. + + +MCP Inspector Integration +========================= + +The plugin works even better with [MCP Inspector |mcp-inspector] – a tool that lets Claude see your actual application state. With MCP Inspector, Claude can: + +- Query your real database schema instead of guessing +- List your registered DI services and their configuration +- Read Tracy error logs for debugging +- Match URLs to presenters using your actual routes + +Install it with a single command: + +```shell +/install-mcp-inspector +``` + +Then restart Claude Code. See the [MCP Inspector documentation |mcp-inspector] for all 20 available tools. + +{{composer: nette/claude-code}} diff --git a/ai/en/getting-started.texy b/ai/en/getting-started.texy new file mode 100644 index 0000000000..fa20b5da1f --- /dev/null +++ b/ai/en/getting-started.texy @@ -0,0 +1,260 @@ +Getting Started +*************** + +<div class=perex> + +Ready to try [vibe coding |guide] with Nette? This guide walks you through the complete setup: + +- Choosing and installing an AI tool +- Setting up MCP Inspector so AI can see your application +- Making your first AI-assisted changes + +The whole process takes about 10 minutes. Let's get started! + +</div> + + +Choosing Your AI Tool +===================== + +Nette AI tools work with any MCP-compatible AI assistant. We recommend **Claude Code** for the best experience – it has a dedicated Nette plugin with deep framework knowledge and automatic code validation. + +Other options include **Cursor**, **VS Code with Continue**, and other MCP-compatible tools. See [Other AI Tools |#other-ai-tools] at the end of this guide. + + +What You'll Need +================ + +Before we begin, make sure you have: + +- **A Nette project** – existing or new (`composer create-project nette/web-project`) +- **PHP 8.2+** – required for MCP Inspector +- **An AI tool** – we'll install Claude Code below (Claude Pro costs $20/month) + + +Installation on macOS and Linux +=============================== + +```shell +curl -fsSL https://claude.ai/install.sh | bash +``` + +On macOS, you can alternatively use Homebrew: + +```shell +brew install --cask claude-code +``` + +After installation, skip to [Starting Claude Code |#starting-claude-code]. + + +Installation on Windows via WSL +=============================== + +Claude Code requires a Unix environment. On Windows, use WSL: + +```shell +wsl --install +``` + +This installs Ubuntu. **Restart your computer** after installation. + +After restart, launch Ubuntu: + +```shell +ubuntu +``` + +First launch will ask for a username and password – you'll need it for `sudo` later. + +Installing Claude Code in WSL in the Ubuntu terminal: + +```shell +curl -fsSL https://claude.ai/install.sh | bash +``` + +Your Windows drives are mounted under `/mnt/`: +- `C:\Users\Jan\Projects` → `/mnt/c/Users/Jan/Projects` +- `D:\Work` → `/mnt/d/Work` + +From Windows, access Linux files via `\\wsl$\Ubuntu\home\username` in Explorer. + + +Starting Claude Code +==================== + +Great, you have Claude Code installed! Let's start it up. + +Navigate to your project directory: + +```shell +# Windows (WSL) +cd /mnt/c/Users/Jan/Projects/my-app + +# macOS/Linux +cd ~/projects/my-app +``` + +Start Claude Code: + +```shell +claude +``` + +The first time you run it, Claude Code will ask you to authenticate. It will open a browser window where you can log in to your Anthropic account. After successful authentication, you'll see the `claude>` prompt and you're ready to go. + +You can also use Claude Code "on the web":https://claude.ai/code or via the "desktop app":https://claude.com/download, but local installation provides the best experience with direct file access. + + +Adding the Nette Plugin +======================= + +Now let's give Claude deep knowledge of Nette. First, add the Nette marketplace and enable auto-updating: + +```shell +/plugin marketplace add nette/claude-code +``` + +Then install the plugin: + +```shell +/plugin install nette@nette +``` + +That's it! The plugin is now active. It includes 10 specialized skills that automatically activate based on what you're working on. When you ask about forms, it knows about Nette Forms. When you ask about templates, it knows about Latte. + + +Setting Up MCP Inspector +======================== + +The final piece is MCP Inspector, which lets Claude see your actual application – your services, database schema, routes, and error logs. + +The easiest way to install it is through Claude Code: + +```shell +/install-mcp-inspector +``` + +This command adds the `nette/mcp-inspector` package to your project and configures everything automatically. + +Alternatively, you can install it manually with Composer: + +```shell +composer require nette/mcp-inspector +``` + +**Important:** After installing MCP Inspector, restart Claude Code (type `/exit` and run `claude` again) to activate the connection. + + +Testing Your Setup +================== + +Let's verify everything works. Try these prompts: + + +Test the Plugin Knowledge +------------------------- + +Type: + +``` +What's the recommended directory structure for a Nette application? +``` + +Claude should respond with detailed information about presenters, models, templates, and configuration – knowledge that comes from the `nette-architecture` skill. + + +Test MCP Inspector +------------------ + +Type: + +``` +What services do I have registered in my DI container? +``` + +If MCP Inspector is working, Claude will call `di_get_services()` and show you the actual services from your application. If you see a list of your real services, congratulations – everything is set up correctly! + + +Test Database Introspection +--------------------------- + +If your application uses a database, try: + +``` +What tables do I have? Show me the columns in the user table. +``` + + +Your First Real Task +==================== + +Now that everything is set up, let's do something useful. Try this prompt: + +``` +I need a simple ArticlePresenter with list and detail actions. +Generate the presenter, templates, and tell me what routes I need. +``` + +Watch as Claude generates a complete, working presenter following Nette conventions. It will: +- Create the presenter class with proper type hints +- Generate Latte templates for both actions +- Suggest the appropriate route configuration + +If you have MCP Inspector set up and an `article` table in your database, try: + +``` +Look at my article table and generate an ArticleRow entity with proper type hints. +``` + + +Other AI Tools +============== + +While we recommend Claude Code for the best Nette experience, MCP Inspector works with any MCP-compatible tool. + + +Cursor +------ + +Cursor is a popular AI-first code editor. To use MCP Inspector with Cursor: + +1. Install MCP Inspector: `composer require nette/mcp-inspector` +2. Create `.cursor/mcp.json` in your project: + +```json +{ + "mcpServers": { + "nette-inspector": { + "command": "php", + "args": ["vendor/bin/mcp-inspector"] + } + } +} +``` + +3. Restart Cursor + +Note: Cursor doesn't have the Nette-specific skills that the Claude Code plugin provides, but MCP Inspector will still give it access to your application's services, database, routes, and logs. + + +VS Code + Continue +------------------ + +Continue is an open-source AI coding assistant for VS Code. Configure MCP Inspector in Continue's settings following their MCP documentation. + + +Other MCP Tools +--------------- + +Any tool supporting the Model Context Protocol can use MCP Inspector. See the [MCP Inspector manual configuration |mcp-inspector#manual-mcp-configuration] for setup instructions. + + +What's Next +=========== + +You're now ready for AI-assisted Nette development! Here's where to go from here: + +- [MCP Inspector |mcp-inspector] – Learn about all 20 introspection tools +- [Claude Code Plugin |claude-code] – Explore all 13 skills (Claude Code users) +- [Tips & Best Practices |tips] – Get the most out of your AI assistant diff --git a/ai/en/guide.texy b/ai/en/guide.texy new file mode 100644 index 0000000000..b0d98486c5 --- /dev/null +++ b/ai/en/guide.texy @@ -0,0 +1,128 @@ +Vibe Coding +*********** + +<div class=perex> + +Vibe coding is a new way of programming where you describe what you want in plain language and AI writes the code for you. Nette is ideal for this style of development – strict dependency injection, strong typing, and clear conventions allow AI to generate precise, working code. + +- **MCP Inspector** – Gives any AI tool real-time access to your application +- **Claude Code Plugin** – Deep Nette knowledge for Claude Code users +- **Best Practices** – Proven patterns for effective AI collaboration + +</div> + + +What is Vibe Coding? +==================== + +"The hottest new programming language is English." + +That's the core idea behind vibe coding – instead of writing every line yourself, you describe your intent and let AI handle the implementation. Want a presenter for managing products? Just say so. Need a form with validation? Describe the fields and rules. + +But here's the important part: **AI doesn't replace programmers**. It's a powerful assistant that accelerates routine work: + +- Generate boilerplate code (presenters, forms, entities) in seconds +- Understand existing code and explain how it works +- Find bugs and suggest fixes +- Write tests based on your implementation + +The catch? AI doesn't truly know your application. It sees only what you show it and guesses the rest based on patterns it learned during training. That's where Nette AI tools come in. + + +Why Nette is Perfect for AI +=========================== + +Not all frameworks work equally well with AI. Nette has properties that make it exceptionally suited for AI-assisted development: + +**Strict Dependency Injection** + +In Nette, all services are registered in the DI container. AI can inspect exactly what services exist and how they're configured – no guessing required. + +**Strong Typing** + +Type hints on methods and properties mean AI generates code that actually works. Fewer runtime errors, less debugging. + +**Clear Conventions** + +Presenters, components, templates – everything has its place. AI can follow these patterns and produce code that looks like it was written by an experienced Nette developer. + +The key principle: + +.**"Without MCP, AI guesses. With MCP, AI knows."** + + +How It Works +============ + +The magic happens through **MCP (Model Context Protocol)** – an open standard for connecting AI assistants to external data sources. Instead of guessing based on training data, AI can query your actual application state. + +Here's the flow: + +1. **You** describe what you want: "Create an entity for the product table" +2. **AI tool** (Claude, Cursor, etc.) needs to know your database schema +3. **MCP Inspector** queries your application and returns the actual schema +4. **AI** generates code that matches your real database + +No hallucinations. No guessing. Just accurate code. + + +Nette AI Tools +============== + + +MCP Inspector +------------- + +The core of Nette's AI integration. MCP Inspector is an MCP server that gives **any compatible AI tool** real-time access to your application: + +| What AI Can See | Examples | +|-----------------|----------| +| **DI Container** | Services, parameters, extensions | +| **Database** | Tables, columns, relationships | +| **Router** | Routes, URL matching, generation | +| **Tracy** | Exceptions, warnings, logs | + +MCP Inspector works with Claude Code, Cursor, VS Code with Continue, and any other tool that supports the MCP protocol. + +[Learn more about MCP Inspector |mcp-inspector] + + +Claude Code Plugin +------------------ + +For users of Claude Code, there's an additional plugin that gives Claude deep knowledge of Nette conventions. It includes 10 specialized "skills" that activate automatically: + +| Skill | What It Covers | +|-------|----------------| +| nette-architecture | Presenters, modules, directory structure | +| nette-database | Database Explorer, entities, queries | +| nette-forms | Controls, validation, rendering | +| latte-templates | Syntax, filters, security | +| + 6 more... | [See complete list |claude-code] | + +The plugin also automatically validates Latte templates and NEON files after every edit. + +[Learn more about Claude Code Plugin |claude-code] + + +Other AI Tools +-------------- + +MCP Inspector works with any MCP-compatible tool. Setup guides for additional tools are coming soon: + +- **Cursor** – Popular AI-first code editor +- **VS Code + Continue** – Open-source AI coding assistant +- **Gemini CLI** – Google's command-line AI tool + + +Getting Started +=============== + +Ready to try vibe coding with Nette? The setup takes about 10 minutes: + +1. **Choose your AI tool** – We recommend Claude Code for the best Nette experience +2. **Install MCP Inspector** – The core that gives AI access to your application +3. **Start coding** – Describe what you want and let AI help + +[Complete setup guide |getting-started] + diff --git a/ai/en/mcp-inspector.texy b/ai/en/mcp-inspector.texy new file mode 100644 index 0000000000..5965a94677 --- /dev/null +++ b/ai/en/mcp-inspector.texy @@ -0,0 +1,448 @@ +MCP Inspector +************* + +<div class=perex> + +MCP Inspector is the bridge between **any AI tool** and your Nette application. It allows AI assistants to look directly at your running app – to see what services you have registered, what your database schema looks like, which routes are defined, and what errors have occurred. + +This is what makes the difference between AI that guesses and AI that knows. + +</div> + + +Supported AI Tools +================== + +MCP Inspector works with any tool that supports the **Model Context Protocol (MCP)**: + +- **[Claude Code |claude-code]** – Full support with dedicated Nette plugin +- **Cursor** – Configure via `.cursor/mcp.json` +- **VS Code + Continue** – Configure via Continue settings +- **Any MCP-compatible tool** – See [manual configuration |#manual-mcp-configuration] + + +Why MCP Matters +=============== + +Imagine you ask your AI: "Generate an entity for the product table." + +Without MCP Inspector, the AI has to guess what columns your table has. It might assume common patterns like `id`, `name`, `price` – but what if your table has different columns? What if `price` is called `unit_price`? What if you have a `currency_id` foreign key? + +With MCP Inspector, the AI doesn't guess. It calls `db_get_columns("product")` and sees your actual schema: + +The result is code that actually works with your database, not code you have to fix. + + +Installation +============ + +If you're using the [Nette plugin for Claude Code |claude-code], installation is simple: + +```shell +/install-mcp-inspector +``` + +This command adds `nette/mcp-inspector` to your project and configures everything automatically. + +For other AI tools or manual installation: + +```shell +composer require nette/mcp-inspector +``` + +Then configure your AI tool to use the MCP server – see [manual configuration |#manual-mcp-configuration] below. + +**Important:** After installation, restart your AI tool. The MCP server only connects when the tool starts. + + +How It Works +============ + +MCP Inspector runs as a background process that your AI tool can communicate with. When AI needs information about your application, it sends a request to MCP Inspector, which: + +1. Loads your application's DI container (using `App\Bootstrap`) +2. Executes the requested query (get services, read database schema, etc.) +3. Returns the result to the AI + +All operations are **read-only**. MCP Inspector can't modify your database, change configuration, or execute commands. + + +DI Container Tools +================== + +These tools let AI explore your service definitions. + + +di_get_services +--------------- + +Lists all registered services. You can filter by name or type. + +When AI asks "What mail services do I have?", it calls: + +``` +di_get_services("mail") +``` + +And gets a list like: + +``` +- mail.mailer (Nette\Mail\Mailer) +- App\Model\QueueMailer +- App\Core\SmtpTransport +``` + + +di_get_service +-------------- + +Gets detailed information about a specific service – how it's created, what setup methods are called, what tags it has. + + +di_get_parameters +----------------- + +Reads configuration parameters. Want to know what your database settings are? + +``` +di_get_parameters("database") +``` + +Note: Sensitive values (passwords, tokens, API keys) are automatically masked. + + +di_find_by_tag +-------------- + +Finds services with a specific tag. Useful for discovering CLI commands: + +``` +di_find_by_tag("console.command") +``` + + +di_find_by_type +--------------- + +Finds services implementing a specific interface: + +``` +di_find_by_type("Nette\\Security\\Authenticator") +``` + + +di_get_extensions +----------------- + +Lists all registered DI extensions with their configuration. + + +Database Tools +============== + +These tools give AI visibility into your database structure. + + +db_get_tables +------------- + +Lists all tables in your database. + + +db_get_columns +-------------- + +Gets detailed column information for a table – types, whether they're nullable, default values, and foreign key relationships. + +``` +db_get_columns("order") +``` + +Returns something like: + +``` +- id: int (PRIMARY KEY) +- customer_id: int (FK → customer.id) +- status: varchar(20) +- total: decimal(10,2) +- created_at: datetime +``` + + +db_get_relationships +-------------------- + +Shows all foreign key relationships in your database – which tables reference which other tables. + + +db_get_indexes +-------------- + +Lists indexes for a specific table. + + +db_explain_query +---------------- + +Runs `EXPLAIN` on a SELECT query to analyze its performance. AI can use this to suggest query optimizations. + + +db_generate_entity +------------------ + +The most useful tool for quick development. Given a table name, it generates a complete PHP entity class with proper type hints: + +``` +db_generate_entity("product") +``` + +Generates: + +```php +/** + * @property-read int $id + * @property-read string $name + * @property-read float $unit_price + * @property-read ?CategoryRow $category + * @property-read DateTimeImmutable $created_at + */ +final class ProductRow extends Table\ActiveRow +{ +} +``` + + +Router Tools +============ + +These tools help AI understand your URL structure. + + +router_get_routes +----------------- + +Lists all registered routes with their masks and default values. + + +router_match_url +---------------- + +Given a URL, finds which presenter and action handles it: + +``` +router_match_url("/admin/products/edit/5") +``` + +Returns: + +``` +Presenter: Admin:Product +Action: edit +Parameters: id=5 +``` + + +router_generate_url +------------------- + +Generates a URL for a given presenter and action: + +``` +router_generate_url("Admin:Product:edit", {"id": 5}) +``` + + +Tracy Tools +=========== + +These tools let AI see error logs and help with debugging. They're incredibly useful when something goes wrong – instead of you describing the error, AI can read it directly. + + +tracy_get_last_exception +------------------------ + +Gets the most recent exception from Tracy's log, including the full stack trace. When something breaks, this is the first thing AI checks. + +``` +tracy_get_last_exception() +``` + +Returns the exception class, message, file, line number, and complete stack trace. AI can analyze this to identify the root cause and suggest a fix. + +Example response: +``` +Exception: Nette\Database\UniqueConstraintViolationException +Message: Duplicate entry 'john@example.com' for key 'email' +File: /app/Model/UserService.php:45 +Stack trace: + #0 /app/Presentation/Admin/UserPresenter.php:32 + #1 /vendor/nette/application/src/... +``` + + +tracy_get_exceptions +-------------------- + +Lists recent exception files from Tracy's log directory. Useful for finding patterns or recurring issues. + +``` +tracy_get_exceptions(5) +``` + +Returns the 5 most recent exception files with timestamps. You can then use `tracy_get_exception_detail` to examine any of them. + + +tracy_get_exception_detail +-------------------------- + +Gets the complete details of a specific exception file. Use this when you want to examine an older exception, not just the latest one. + +``` +tracy_get_exception_detail("exception-2024-01-15-143022-abc123.html") +``` + + +tracy_get_warnings +------------------ + +Shows recent PHP warnings and notices from Tracy's log. These often indicate problems that don't crash the application but should be fixed. + +``` +tracy_get_warnings(10) +``` + +Common warnings AI can help fix: +- Undefined array key +- Deprecated function calls +- Type mismatch warnings + + +tracy_get_log +------------- + +Reads entries from any Tracy log level. Tracy supports multiple log files: `error.log`, `warning.log`, `info.log`, and custom levels. + +``` +tracy_get_log("error", 20) +``` + +This reads the last 20 entries from the error log. Useful for seeing a history of issues, not just the most recent one. + + +Creating Custom Tools +===================== + +You can extend MCP Inspector with your own tools. This is useful if you have application-specific data that AI should be able to query. + +Create a class implementing the `Toolkit` interface: + +```php +use Mcp\Capability\Attribute\McpTool; +use Nette\McpInspector\Toolkit; +use Nette\McpInspector\Bridge\BootstrapBridge; + +class OrderToolkit implements Toolkit +{ + public function __construct( + private BootstrapBridge $bridge, + ) {} + + /** + * Get pending orders count and total value. + */ + #[McpTool(name: 'orders_get_pending_summary')] + public function getPendingSummary(): array + { + $db = $this->bridge->getContainer() + ->getByType(Nette\Database\Explorer::class); + + $result = $db->table('order') + ->where('status', 'pending') + ->select('COUNT(*) AS count, SUM(total) AS total') + ->fetch(); + + return [ + 'count' => $result->count, + 'total' => $result->total, + ]; + } +} +``` + +Register it in `mcp-config.neon`: + +```neon +toolkits: + - App\Mcp\OrderToolkit +``` + +Now AI can call `orders_get_pending_summary()` to get real-time order statistics. + + +Configuration +============= + +MCP Inspector works out of the box with the default Nette project structure. If your setup is different, create `mcp-config.neon` in your project root: + +```neon +# Path to Bootstrap file (if not in default location) +bootstrap: src/Bootstrap.php + +# Bootstrap class name (if different from default) +bootstrapClass: MyApp\Bootstrap + +# Additional custom toolkits +toolkits: + - App\Mcp\OrderToolkit + - App\Mcp\CustomerToolkit +``` + + +Manual MCP Configuration +------------------------ + +For AI tools other than Claude Code (which configures automatically via the plugin), add MCP Inspector to your tool's configuration: + +**For most MCP-compatible tools**, create `.mcp.json` in your project root: + +```json +{ + "mcpServers": { + "nette-inspector": { + "command": "php", + "args": ["vendor/bin/mcp-inspector"] + } + } +} +``` + +**For Cursor**, add to `.cursor/mcp.json`: + +```json +{ + "mcpServers": { + "nette-inspector": { + "command": "php", + "args": ["vendor/bin/mcp-inspector"] + } + } +} +``` + +Consult your AI tool's documentation for the exact configuration location. + + +Security Considerations +======================= + +MCP Inspector is designed for development environments. Here's what you should know: + +**Read-only by design** – All tools only read data, never modify it. + +**Database protection** – The `db_explain_query` tool only accepts SELECT, SHOW, DESCRIBE, and EXPLAIN queries. INSERT, UPDATE, DELETE, and other modifying queries are rejected. + +**Sensitive data masking** – Configuration values containing words like "password", "secret", "token", or "apikey" are automatically masked with `***MASKED***`. + +**Do not expose in production** – MCP Inspector should only run on development machines. It provides detailed information about your application internals that you don't want exposed publicly. + +{{composer: nette/mcp-inspector}} diff --git a/ai/en/tips.texy b/ai/en/tips.texy new file mode 100644 index 0000000000..586f558519 --- /dev/null +++ b/ai/en/tips.texy @@ -0,0 +1,296 @@ +Tips for AI-Assisted Development +******************************** + +<div class=perex> + +AI is a powerful tool, but like any tool, you get better results when you know how to use it well. This page collects practical advice from real-world experience with AI-assisted Nette development. + +- How to write prompts that get better results +- Making the most of MCP Inspector +- Proven workflows for common tasks +- Mistakes to avoid + +</div> + + +Writing Better Prompts +====================== + + +The Art of Being Specific +------------------------- + +The single biggest improvement you can make is being specific. Compare these two prompts: + +**Vague prompt:** + +``` +Create a form +``` + +This gives the AI almost no context. What form? What fields? What validation? The AI has to make assumptions, and those assumptions might not match what you need. + +**Specific prompt:** + +``` +Create a ProductForm with: +- name: text field, required, max 100 characters +- price: float field, required, must be positive +- description: textarea, optional +- category: select from CategoryRow entities + +Use Bootstrap 5 rendering. The form should work for both creating new products and editing existing ones. +``` + +Now the AI knows exactly what you need and can generate code that works on the first try. + + +Point to Existing Patterns +-------------------------- + +Your codebase already has patterns. Instead of explaining them, point the AI to examples: + +``` +Create an OrderPresenter. Follow the same patterns as ProductPresenter – +same structure, same way of handling forms, same template organization. +``` + +The AI will read ProductPresenter and replicate the patterns you're already using. + + +Let MCP Do the Heavy Lifting +---------------------------- + +If you have MCP Inspector installed (and you should!), don't explain your application – let the AI discover it: + +**Instead of:** + +``` +My product table has columns: id (int), name (varchar), price (decimal), +category_id (int, foreign key to category), created_at (datetime)... +``` + +**Just say:** + +``` +Generate an entity for the product table. +``` + +The AI will call `db_get_columns("product")` and see the actual schema. The generated entity will match your real database, including any columns you might have forgotten to mention. + + +Give Context About Your Goals +----------------------------- + +AI can't read your mind. If there's a reason behind your request, share it: + +``` +I need to optimize the product listing page. It's currently loading +all products at once, which is slow when there are thousands of items. +The page needs to support filtering by category and sorting by price or name. +``` + +This helps the AI suggest an appropriate solution (pagination, lazy loading, caching) rather than just blindly implementing what you asked for. + + +Working with MCP Inspector +========================== + +MCP Inspector is most powerful when you use it strategically. + + +Explore Before You Build +------------------------ + +Starting a new feature? Let the AI understand the context first: + +``` +I'm going to add order tracking. Before we start: +1. What services do I have related to orders? +2. What does my order table look like? +3. What routes handle order-related pages? +``` + +This gives the AI context about your existing code, so the new feature fits naturally. + + +Debug Smarter +------------- + +When something goes wrong, don't describe the error – let the AI see it: + +``` +Something broke. Check the Tracy log for the last exception +and tell me what went wrong. +``` + +The AI will call `tracy_get_last_exception()`, read the stack trace, and can often identify the problem faster than you could explain it. + + +Verify Before You Create +------------------------ + +Before adding new routes or links, verify what exists: + +``` +What presenter handles /admin/products/edit? I want to make sure +I'm not creating something that conflicts. +``` + + +Common Workflows +================ + +Here are proven approaches for common tasks. + + +Creating a Complete CRUD +------------------------ + +Don't ask for one piece at a time. Give the AI the full picture: + +``` +Create a complete CRUD for managing products: + +1. ProductPresenter with actions: list, add, edit, delete +2. ProductForm as a component (works for both add and edit) +3. Latte templates for all actions +4. Route suggestions + +Use the actual product table schema. Follow the patterns +in CategoryPresenter if it exists. +``` + + +Adding a New Feature +-------------------- + +Break it down into phases that build on each other: + +``` +I need to add customer reviews to products. + +Phase 1 - Data layer: +- Look at the product table +- Suggest the review table schema +- Create ReviewRow entity + +Phase 2 - Business logic: +- Create ReviewService for CRUD operations +- Add methods to get reviews for a product + +Phase 3 - UI: +- Add review display to ProductPresenter:detail +- Create ReviewForm for submitting reviews +``` + + +Refactoring Existing Code +------------------------- + +Let the AI understand before it changes: + +``` +Analyze the OrderService class. What does each method do? +Are there any code smells or improvements you'd suggest? +``` + +Then: + +``` +The calculateTotal method is doing too much. Split it into +smaller methods while keeping the same public interface. +``` + + +Mistakes to Avoid +================= + + +Not Reviewing Generated Code +---------------------------- + +AI generates code quickly, but that doesn't mean every line is perfect. Always review: + +- **Database queries** – Are they efficient? Do they need indexes? +- **Security** – Is input validated? Are there authorization checks? +- **Edge cases** – What happens with empty data? Null values? + +AI is very good, but it's still an assistant. You're the developer responsible for the final code. + + +Ignoring Validation Feedback +---------------------------- + +If you're using the [Claude Code plugin |claude-code], it validates your Latte templates and NEON files automatically. When it reports an error, the AI knows about it. Instead of manually fixing the error, just say: + +``` +Fix the error you just created. +``` + +The AI will read the validation output and correct the mistake. + + +Forgetting Service Registration +------------------------------- + +When the AI creates a new service class, it sometimes forgets to register it in the DI container. If you get "Service not found" errors, ask: + +``` +What changes do I need in services.neon for the new OrderExportService? +``` + + +Asking for Too Much at Once +--------------------------- + +While AI can handle complex tasks, sometimes it helps to break them down: + +**Too ambitious:** + +``` +Build me a complete e-commerce system with product catalog, +shopping cart, checkout, payments, order tracking, and admin panel. +``` + +**Better approach:** + +``` +Let's build an e-commerce system step by step. Start with the product +catalog – I need to list, view, and admin products. +``` + + +When AI Excels (and When It Doesn't) +==================================== + + +AI is Great For +--------------- + +- **Boilerplate code** – Presenters, forms, entities, basic templates +- **Following patterns** – "Do it like X but for Y" +- **Understanding code** – "What does this method do?" +- **Generating tests** – Given implementation, create tests +- **Refactoring** – Improving code structure while keeping behavior + + +Consider Manual Coding For +-------------------------- + +- **Complex business logic** – Domain rules that require careful thinking +- **Performance-critical code** – Algorithms that need optimization +- **Security-sensitive code** – Authentication, authorization, encryption +- **Novel solutions** – Things that don't follow existing patterns + +AI is a multiplier, not a replacement. It makes good developers faster, but it still needs a good developer guiding it. + + +Final Thoughts +============== + +The best way to learn AI-assisted development is to practice. Start with simple tasks, pay attention to what works, and gradually take on more complex projects. + +And remember: the AI is your assistant. You're still the developer. You make the decisions, you review the code, and you're responsible for the quality of the final product. + +Happy coding! diff --git a/ai/meta.json b/ai/meta.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/ai/meta.json @@ -0,0 +1 @@ +{} From 1a8341b7fdb65f9f9053e8b976abcb32f46a2d01 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Fri, 23 Jan 2026 16:21:31 +0100 Subject: [PATCH 16/50] latte 3.1.2 --- latte/cs/develop.texy | 8 ++++---- latte/en/develop.texy | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/latte/cs/develop.texy b/latte/cs/develop.texy index 28f0d64892..8c96e3c594 100644 --- a/latte/cs/develop.texy +++ b/latte/cs/develop.texy @@ -27,7 +27,7 @@ Jak vykreslit šablonu? Stačí k tomu tento jednoduchý kód: ```php $latte = new Latte\Engine; // adresář pro cache -$latte->setTempDirectory('/path/to/tempdir'); +$latte->setCacheDirectory('/path/to/tempdir'); $params = [ /* proměnné šablony */ ]; // or $params = new TemplateParameters(/* ... */); @@ -184,18 +184,18 @@ Ve striktním režimu parsování Latte kontroluje, zda nechybí uzavírací HTM ```php $latte = new Latte\Engine; -$latte->setStrictParsing(); +$latte->setFeature(Latte\Feature::StrictParsing); ``` Generování šablon s hlavičkou `declare(strict_types=1)` zapnete takto: ```php $latte = new Latte\Engine; -$latte->setStrictTypes(); +$latte->setFeature(Latte\Feature::StrictTypes); ``` .[note] -Od verze Latte 3.1 jsou strict types povoleny ve výchozím nastavení. Můžete je deaktivovat pomocí `$latte->setStrictTypes(false)`. +Od verze Latte 3.1 jsou strict types povoleny ve výchozím nastavení. Můžete je deaktivovat pomocí `$latte->setFeature(Latte\Feature::StrictTypes, false)`. Migrační varování .{data-version:3.1} diff --git a/latte/en/develop.texy b/latte/en/develop.texy index 40262a706f..c32a60010d 100644 --- a/latte/en/develop.texy +++ b/latte/en/develop.texy @@ -27,7 +27,7 @@ How to render a template? Just use this simple code: ```php $latte = new Latte\Engine; // cache directory -$latte->setTempDirectory('/path/to/tempdir'); +$latte->setCacheDirectory('/path/to/tempdir'); $params = [ /* template variables */ ]; // or $params = new TemplateParameters(/* ... */); @@ -184,18 +184,18 @@ In strict parsing mode, Latte checks for missing closing HTML tags and also disa ```php $latte = new Latte\Engine; -$latte->setStrictParsing(); +$latte->setFeature(Latte\Feature::StrictParsing); ``` To generate templates with the `declare(strict_types=1)` header, do the following: ```php $latte = new Latte\Engine; -$latte->setStrictTypes(); +$latte->setFeature(Latte\Feature::StrictTypes); ``` .[note] -Since Latte 3.1, strict types are enabled by default. You can disable them with `$latte->setStrictTypes(false)`. +Since Latte 3.1, strict types are enabled by default. You can disable them with `$latte->setFeature(Latte\Feature::StrictTypes, false)`. Migration Warnings .{data-version:3.1} From ffa8452922ae966f2a250ac3e478b91d80cc5ce3 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Tue, 17 Mar 2026 21:23:48 +0100 Subject: [PATCH 17/50] latte: info about whitespace --- latte/cs/syntax.texy | 33 +++++++++++++++++++++++++++++++++ latte/en/syntax.texy | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/latte/cs/syntax.texy b/latte/cs/syntax.texy index 1e21ab6dcf..b36e9e7c9a 100644 --- a/latte/cs/syntax.texy +++ b/latte/cs/syntax.texy @@ -218,6 +218,39 @@ Uvnitř značek fungují PHP komentáře: ``` +Řízení bílých znaků +=================== + +Latte zachází s bílými znaky inteligentně. Kód můžete volně odsazovat pro čitelnost a výstup zůstane čistý. Když se tag objeví na řádku sám, celý řádek (odsazení i konec řádku) se z výstupu odstraní: + +```latte +<ul> + {foreach $items as $item} + <li>{$item}</li> + {/foreach} +</ul> +``` + +Vypíše: + +```html +<ul> + <li>foo</li> + <li>bar</li> +</ul> +``` + +A co když tag není na řádku sám, ale je tam i další obsah? Bílé znaky před tagem pak patří *dovnitř* tagu: + +```latte +<div> + {if $foo}hello{/if} +</div> +``` + +Odsazení je tedy fakticky uvnitř `{if}`: pokud je `$foo` false, nevypíše se nic – ani odsazení, ani prázdný řádek. Pokud je `$foo` true, výstup přirozeně obsahuje odsazení. Prostě pište přehledně odsazené šablony a výstup bude vždy čistý. + + Syntaktický cukr ================ diff --git a/latte/en/syntax.texy b/latte/en/syntax.texy index ef926e75be..31faaf9fa5 100644 --- a/latte/en/syntax.texy +++ b/latte/en/syntax.texy @@ -218,6 +218,39 @@ 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 +<ul> + {foreach $items as $item} + <li>{$item}</li> + {/foreach} +</ul> +``` + +Outputs: + +```html +<ul> + <li>foo</li> + <li>bar</li> +</ul> +``` + +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 +<div> + {if $foo}hello{/if} +</div> +``` + +The indentation is effectively inside `{if}`: when `$foo` is false, nothing is output – not even the indentation or a blank line. When `$foo` is true, the output naturally includes the indentation. You simply write well-structured templates and the output is always clean. + + Syntactic Sugar =============== From 35e13dcc56578c5ab4167e4c62e7db3006d8679b Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Tue, 23 Dec 2025 22:05:06 +0100 Subject: [PATCH 18/50] latte 3.1.3 --- latte/cs/develop.texy | 64 +++++++++++++++++++++++++++++++++++++++++++ latte/cs/filters.texy | 58 ++++++++++++++++++++++++++++++++++++--- latte/cs/syntax.texy | 2 ++ latte/en/develop.texy | 64 +++++++++++++++++++++++++++++++++++++++++++ latte/en/filters.texy | 58 ++++++++++++++++++++++++++++++++++++--- latte/en/syntax.texy | 2 ++ 6 files changed, 240 insertions(+), 8 deletions(-) diff --git a/latte/cs/develop.texy b/latte/cs/develop.texy index 8c96e3c594..08dd5686f3 100644 --- a/latte/cs/develop.texy +++ b/latte/cs/develop.texy @@ -216,6 +216,70 @@ Pokud je toto zapnuto, Latte kontroluje vykreslované atributy a vyvolá uživat Jakmile jsou všechna varování vyřešena, vypněte varování o migraci a **odstraňte všechny** filtry `|accept` ze svých šablon, protože již nejsou potřeba. +Scopované proměnné cyklu .{data-version:3.1.3} +============================================== + +Ve výchozím nastavení zůstávají proměnné definované v cyklu `{foreach}` (jako `$key` a `$value`) dostupné i po jeho skončení – stejně jako v samotném PHP. To může vést k nechtěnému přepsání proměnných, pokud má proměnná cyklu stejný název jako existující proměnná šablony. + +Funkce `ScopedLoopVariables` omezí platnost proměnných na tělo cyklu. Po jeho skončení se obnoví původní hodnota proměnné (pokud existovala), nebo se proměnná odstraní: + +```php +$latte = new Latte\Engine; +$latte->setFeature(Latte\Feature::ScopedLoopVariables); +``` + +Příklad rozdílu: + +```latte +{var $item = 'original'} +{foreach [1, 2] as $item}{$item}, {/foreach} +{$item} +``` + +Bez `ScopedLoopVariables`: vypíše `1, 2, 2` (proměnná je přepsána) +Se `ScopedLoopVariables`: vypíše `1, 2, original` (proměnná je obnovena) + +Funguje to i s destrukturováním, např. `{foreach $array as [$a, $b]}`. + +.[note] +Proměnné cyklu používající reference (`{foreach $array as &$value}`) nebo přiřazení do vlastností (`{foreach $array as $obj->prop}`) nejsou scopovány, protože by to narušilo jejich účel. + + +Automatické odsazení (Dedent) .{toc: Dedent}{data-version:3.1.3} +================================================================ + +Při používání párových značek jako `{if}`, `{foreach}` nebo `{block}` se vnořený obsah často odsazuje pro lepší čitelnost. Toto odsazení se ale ve výchozím nastavení přenáší do vygenerovaného výstupu. Funkce `Dedent` ho automaticky odstraní, takže výstup zůstane čistý bez ohledu na úroveň zanoření v šabloně: + +```php +$latte = new Latte\Engine; +$latte->setFeature(Latte\Feature::Dedent); +``` + +Příklad: + +```latte +{if true} + Hello + World +{/if} +``` + +Bez `Dedent` by výstup obsahoval odsazení (`\tHello\n\tWorld\n`). S `Dedent` se odsazení odstraní a výstupem je `Hello\nWorld\n`. + +Hlubší odsazení uvnitř bloku zůstává zachováno relativně k základnímu odsazení: + +```latte +{if true} + Hello + Indented +{/if} +``` + +Výstup: `Hello\n\tIndented\n`. + +Odsazení v bloku musí být konzistentní (buď tabulátory, nebo mezery). Pokud se mísí, Latte vyhodí výjimku `Inconsistent indentation`. + + Překládání v šablonách .{toc: TranslatorExtension} ================================================== diff --git a/latte/cs/filters.texy b/latte/cs/filters.texy index bcce55ae3e..edad8271e9 100644 --- a/latte/cs/filters.texy +++ b/latte/cs/filters.texy @@ -10,6 +10,8 @@ V šablonách můžeme používat funkce, které pomáhají upravit nebo přefor | `breakLines` | [Před konce řádku přidá HTML odřádkování |#breakLines] | `bytes` | [formátuje velikost v bajtech |#bytes] | `clamp` | [ohraničí hodnotu do daného rozsahu |#clamp] +| `column` | [extrahuje jeden sloupec z pole |#column] +| `commas` | [spojí pole čárkami |#commas] | `dataStream` | [konverze pro Data URI protokol |#dataStream] | `date` | [formátuje datum a čas |#date] | `explode` | [rozdělí řetězec na pole podle oddělovače |#explode] @@ -259,6 +261,50 @@ Ohraničí hodnotu do daného inkluzivního rozsahu min a max. Existuje také jako [funkce |functions#clamp]. +column(string|int|null $columnKey, string|int|null $indexKey=null) .[filter]{data-version:3.1.3} +------------------------------------------------------------------------------------------------ +Vrátí z vícerozměrného pole hodnoty jednoho sloupce `$columnKey` jako nové pole. Lze použít i na pole objektů pro získání hodnot vlastností. + +```latte +{var $users = [ + [id: 30, name: 'John', age: 30], + [id: 32, name: 'Jane', age: 25], + [id: 33, age: 35], +]} + +{$users|column: 'name'} +{* vrátí ['John', 'Jane'] *} + +{$users|column: 'name', 'id'} +{* vrátí [30 => 'John', 32 => 'Jane'] *} +``` + +Pokud předáte `null` jako klíč sloupce, přeindexuje pole podle `$indexKey`. + + +commas(?string $lastGlue=null) .[filter]{data-version:3.1.3} +------------------------------------------------------------ +Spojí prvky pole čárkou a mezerou (`', '`). Jde o pohodlnou zkratku pro běžný výpis položek v čitelné podobě. + +```latte +{var $items = ['jablka', 'pomeranče', 'banány']} +{$items|commas} +{* vypíše 'jablka, pomeranče, banány' *} +``` + +Lze zadat i vlastní oddělovač pro poslední dvojici položek: + +```latte +{$items|commas: ' a '} +{* vypíše 'jablka, pomeranče a banány' *} + +{=['PHP', 'JavaScript', 'Python']|commas: ', nebo '} +{* vypíše 'PHP, JavaScript, nebo Python' *} +``` + +Viz také [#implode]. + + 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. @@ -407,6 +453,8 @@ Můžete také použít alias `join`: {=[1, 2, 3]|join} {* vypíše '123' *} ``` +Viz také [#commas], [#explode]. + indent(int $level=1, string $char="\t") .[filter] ------------------------------------------------- @@ -637,19 +685,21 @@ Pamatujte, že skutečný vzhled čísel se může lišit podle nastavení země padLeft(int $length, string $pad=' ') .[filter] ----------------------------------------------- -Doplní řetězec do určité délky jiným řetězcem zleva. +Doplní řetězec nebo číslo do určité délky jiným řetězcem zleva. ```latte {='hello'|padLeft: 10, '123'} {* vypíše '12312hello' *} +{=123|padLeft: 5, '0'} {* vypíše '00123' *} ``` padRight(int $length, string $pad=' ') .[filter] ------------------------------------------------ -Doplní řetězec do určité délky jiným řetězcem zprava. +Doplní řetězec nebo číslo do určité délky jiným řetězcem zprava. ```latte {='hello'|padRight: 10, '123'} {* vypíše 'hello12312' *} +{=123|padRight: 5, '0'} {* vypíše '12300' *} ``` @@ -747,14 +797,14 @@ Viz také [#ceil], [#floor]. slice(int $start, ?int $length=null, bool $preserveKeys=false) .[filter] ------------------------------------------------------------------------ -Extrahuje část pole nebo řetězce. +Extrahuje část pole, řetězce nebo iterátoru. ```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. +Filtr funguje jako funkce PHP `array_slice` pro pole nebo `mb_substr` pro řetězce. Pro iterátory vrací generátor – prvky se čtou z původního zdroje jeden po druhém a po dosažení limitu se čtení zastaví. Celý iterátor se do paměti nenačítá. 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. diff --git a/latte/cs/syntax.texy b/latte/cs/syntax.texy index b36e9e7c9a..c5346ba1f8 100644 --- a/latte/cs/syntax.texy +++ b/latte/cs/syntax.texy @@ -250,6 +250,8 @@ A co když tag není na řádku sám, ale je tam i další obsah? Bílé znaky p Odsazení je tedy fakticky uvnitř `{if}`: pokud je `$foo` false, nevypíše se nic – ani odsazení, ani prázdný řádek. Pokud je `$foo` true, výstup přirozeně obsahuje odsazení. Prostě pište přehledně odsazené šablony a výstup bude vždy čistý. +Pro ještě čistší výstup lze aktivovat funkci [Dedent |develop#Dedent], která odstraní i odsazení vzniklé zanořením v párových značkách jako `{if}` nebo `{foreach}`. + Syntaktický cukr ================ diff --git a/latte/en/develop.texy b/latte/en/develop.texy index c32a60010d..bad55da3b4 100644 --- a/latte/en/develop.texy +++ b/latte/en/develop.texy @@ -216,6 +216,70 @@ When enabled, Latte checks rendered attributes and triggers a user warning (`E_U Once all warnings are resolved, disable migration warnings and **remove all** `|accept` filters from your templates, as they are no longer needed. +Scoped Loop Variables .{data-version:3.1.3} +=========================================== + +By default, variables defined in a `{foreach}` loop (like `$key` and `$value`) remain accessible after the loop ends – just like in PHP itself. This can lead to unintended variable overwrites when a loop variable has the same name as an existing template variable. + +The `ScopedLoopVariables` feature limits the scope of loop variables to the loop body. After the loop ends, the original variable value is restored (if it existed before), or the variable is unset: + +```php +$latte = new Latte\Engine; +$latte->setFeature(Latte\Feature::ScopedLoopVariables); +``` + +Example of the difference: + +```latte +{var $item = 'original'} +{foreach [1, 2] as $item}{$item}, {/foreach} +{$item} +``` + +Without `ScopedLoopVariables`: outputs `1, 2, 2` (variable is overwritten) +With `ScopedLoopVariables`: outputs `1, 2, original` (variable is restored) + +This also works with destructuring syntax, e.g. `{foreach $array as [$a, $b]}`. + +.[note] +Loop variables using references (`{foreach $array as &$value}`) or property assignments (`{foreach $array as $obj->prop}`) are not scoped, as this would break their intended purpose. + + +Automatic Dedentation .{toc: Dedent}{data-version:3.1.3} +======================================================== + +When using paired tags like `{if}`, `{foreach}`, or `{block}`, you often indent the nested content for readability. However, this indentation is included in the generated output by default. The `Dedent` feature automatically removes it, so the output stays clean regardless of how deeply you nest your Latte tags: + +```php +$latte = new Latte\Engine; +$latte->setFeature(Latte\Feature::Dedent); +``` + +Example: + +```latte +{if true} + Hello + World +{/if} +``` + +Without `Dedent`, the output would include the indentation (`\tHello\n\tWorld\n`). With `Dedent`, the indentation is stripped and the output is `Hello\nWorld\n`. + +Deeper indentation within a block is preserved relative to the base indentation: + +```latte +{if true} + Hello + Indented +{/if} +``` + +Output: `Hello\n\tIndented\n`. + +Indentation within a block must be consistent (either tabs or spaces). If they are mixed, Latte throws an `Inconsistent indentation` exception. + + Translation in Templates .{toc: TranslatorExtension} ==================================================== diff --git a/latte/en/filters.texy b/latte/en/filters.texy index c87f8ffceb..a6365b3be6 100644 --- a/latte/en/filters.texy +++ b/latte/en/filters.texy @@ -10,6 +10,8 @@ In templates, we can use functions that help modify or reformat data into its fi | `breakLines` | [Inserts HTML line breaks before all newlines |#breakLines] | `bytes` | [formats size in bytes |#bytes] | `clamp` | [clamps a value to the given range |#clamp] +| `column` | [extracts a single column from an array |#column] +| `commas` | [joins an array with commas |#commas] | `dataStream` | [Data URI protocol conversion |#dataStream] | `date` | [formats the date and time |#date] | `explode` | [splits a string into an array by a delimiter |#explode] @@ -259,6 +261,50 @@ Clamps a value to the given inclusive range of min and max. Also exists as a [function |functions#clamp]. +column(string|int|null $columnKey, string|int|null $indexKey=null) .[filter]{data-version:3.1.3} +------------------------------------------------------------------------------------------------ +Returns the values of a single column `$columnKey` from a multidimensional array as a new array. Can also be used on arrays of objects to extract property values. + +```latte +{var $users = [ + [id: 30, name: 'John', age: 30], + [id: 32, name: 'Jane', age: 25], + [id: 33, age: 35], +]} + +{$users|column: 'name'} +{* returns ['John', 'Jane'] *} + +{$users|column: 'name', 'id'} +{* returns [30 => 'John', 32 => 'Jane'] *} +``` + +If you pass `null` as the column key, it will reindex the array according to `$indexKey`. + + +commas(?string $lastGlue=null) .[filter]{data-version:3.1.3} +------------------------------------------------------------ +Joins array elements with a comma and space (`', '`). A convenient shortcut for listing items in a human-readable format. + +```latte +{var $items = ['apples', 'oranges', 'bananas']} +{$items|commas} +{* outputs 'apples, oranges, bananas' *} +``` + +You can also provide a custom separator for the last pair of items: + +```latte +{$items|commas: ' and '} +{* outputs 'apples, oranges and bananas' *} + +{=['PHP', 'JavaScript', 'Python']|commas: ', or '} +{* outputs 'PHP, JavaScript, or Python' *} +``` + +See also [#implode]. + + dataStream(string $mimetype='detect') .[filter] ----------------------------------------------- Converts content to the data URI scheme. This allows embedding images into HTML or CSS without needing to link external files. @@ -407,6 +453,8 @@ You can also use the alias `join`: {=[1, 2, 3]|join} {* outputs '123' *} ``` +See also [#commas], [#explode]. + indent(int $level=1, string $char="\t") .[filter] ------------------------------------------------- @@ -637,19 +685,21 @@ Remember that the actual appearance of numbers may vary depending on the country padLeft(int $length, string $pad=' ') .[filter] ----------------------------------------------- -Pads a string to a certain length with another string from the left. +Pads a string or number to a certain length with another string from the left. ```latte {='hello'|padLeft: 10, '123'} {* outputs '12312hello' *} +{=123|padLeft: 5, '0'} {* outputs '00123' *} ``` padRight(int $length, string $pad=' ') .[filter] ------------------------------------------------ -Pads a string to a certain length with another string from the right. +Pads a string or number to a certain length with another string from the right. ```latte {='hello'|padRight: 10, '123'} {* outputs 'hello12312' *} +{=123|padRight: 5, '0'} {* outputs '12300' *} ``` @@ -747,14 +797,14 @@ See also [#ceil], [#floor]. slice(int $start, ?int $length=null, bool $preserveKeys=false) .[filter] ------------------------------------------------------------------------ -Extracts a slice of an array or a string. +Extracts a slice of an array, string, or iterator. ```latte {='hello'|slice: 1, 2} {* outputs 'el' *} {=['a', 'b', 'c']|slice: 1, 2} {* outputs ['b', 'c'] *} ``` -The filter works like the PHP function `array_slice` for arrays or `mb_substr` for strings, with a fallback to the `iconv_substr` function in UTF‑8 mode. +The filter works like the PHP function `array_slice` for arrays or `mb_substr` for strings. For iterators, it returns a generator – elements are consumed from the source one by one and reading stops once the limit is reached. The entire iterator is never loaded into memory. If `start` is non-negative, the sequence will start at that offset from the beginning of the array/string. If `start` is negative, the sequence will start that far from the end. diff --git a/latte/en/syntax.texy b/latte/en/syntax.texy index 31faaf9fa5..24656e0571 100644 --- a/latte/en/syntax.texy +++ b/latte/en/syntax.texy @@ -250,6 +250,8 @@ What if a tag isn't alone on a line, but appears alongside other content? The wh The indentation is effectively inside `{if}`: when `$foo` is false, nothing is output – not even the indentation or a blank line. When `$foo` is true, the output naturally includes the indentation. You simply write well-structured templates and the output is always clean. +For even cleaner output, you can enable the [Dedent |develop#Dedent] feature, which also removes indentation caused by nesting within paired tags like `{if}` or `{foreach}`. + Syntactic Sugar =============== From 698ba33189b79b68cc250ebea4c89d0f7b9e907b Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Mon, 23 Feb 2026 02:46:24 +0100 Subject: [PATCH 19/50] typo --- application/cs/creating-links.texy | 2 +- application/cs/templates.texy | 2 +- application/en/templates.texy | 2 +- best-practices/cs/creating-editing-form.texy | 1 - .../cs/lets-create-contact-form.texy | 3 --- best-practices/en/creating-editing-form.texy | 1 - .../en/lets-create-contact-form.texy | 3 --- caching/cs/@home.texy | 4 ++-- caching/en/@home.texy | 4 ++-- database/cs/explorer.texy | 2 +- database/en/explorer.texy | 2 +- dependency-injection/cs/faq.texy | 2 +- dependency-injection/cs/global-state.texy | 2 +- dependency-injection/en/faq.texy | 2 +- dependency-injection/en/global-state.texy | 2 +- latte/bg/custom-tags.texy | 2 +- latte/bg/safety-first.texy | 20 +++++++++---------- latte/cs/custom-filters.texy | 2 +- latte/cs/custom-functions.texy | 2 +- latte/cs/custom-tags.texy | 4 ++-- latte/cs/safety-first.texy | 20 +++++++++---------- latte/cs/syntax.texy | 2 +- latte/cs/tags.texy | 2 +- latte/de/custom-tags.texy | 2 +- latte/de/safety-first.texy | 20 +++++++++---------- latte/el/custom-tags.texy | 2 +- latte/el/safety-first.texy | 20 +++++++++---------- latte/en/custom-filters.texy | 2 +- latte/en/custom-functions.texy | 2 +- latte/en/custom-tags.texy | 4 ++-- latte/en/safety-first.texy | 20 +++++++++---------- latte/en/syntax.texy | 2 +- latte/en/tags.texy | 2 +- latte/es/custom-tags.texy | 2 +- latte/es/safety-first.texy | 20 +++++++++---------- latte/fr/custom-tags.texy | 2 +- latte/fr/safety-first.texy | 20 +++++++++---------- latte/hu/custom-tags.texy | 2 +- latte/hu/safety-first.texy | 20 +++++++++---------- latte/it/custom-tags.texy | 2 +- latte/it/safety-first.texy | 20 +++++++++---------- latte/ja/custom-tags.texy | 2 +- latte/ja/safety-first.texy | 20 +++++++++---------- latte/pl/custom-tags.texy | 2 +- latte/pl/safety-first.texy | 20 +++++++++---------- latte/pt/custom-tags.texy | 2 +- latte/pt/safety-first.texy | 20 +++++++++---------- latte/ro/custom-tags.texy | 2 +- latte/ro/safety-first.texy | 20 +++++++++---------- latte/ru/custom-tags.texy | 2 +- latte/ru/safety-first.texy | 20 +++++++++---------- latte/sl/custom-tags.texy | 2 +- latte/sl/safety-first.texy | 20 +++++++++---------- latte/tr/custom-tags.texy | 2 +- latte/tr/safety-first.texy | 20 +++++++++---------- latte/uk/custom-tags.texy | 2 +- latte/uk/safety-first.texy | 20 +++++++++---------- quickstart/cs/@home.texy | 3 +-- quickstart/cs/comments.texy | 2 +- quickstart/en/@home.texy | 3 +-- quickstart/en/comments.texy | 2 +- security/cs/authentication.texy | 2 +- security/en/authentication.texy | 2 +- tracy/cs/guide.texy | 2 +- tracy/cs/stopwatch.texy | 2 +- tracy/en/stopwatch.texy | 2 +- utils/cs/filesystem.texy | 2 +- utils/en/filesystem.texy | 2 +- 68 files changed, 221 insertions(+), 231 deletions(-) diff --git a/application/cs/creating-links.texy b/application/cs/creating-links.texy index 011beea750..8658cb3646 100644 --- a/application/cs/creating-links.texy +++ b/application/cs/creating-links.texy @@ -12,7 +12,7 @@ Tvořit odkazy v Nette je jednoduché, jako ukazovat prstem. Stačí jen namíř </div> -Díky [obousměrnému routování |routing] nebudete nikdy muset do šablon či kódu zapisovat navrdo URL adresy vaší aplikace, které se mohou později měnit, nebo je komplikovaně skládat. V odkazu stačí uvést presenter a akci, předat případné parametry a framework už URL vygeneruje sám. Vlastně je to velice podobné, jako když voláte funkci. To se vám bude líbit. +Díky [obousměrnému routování |routing] nebudete nikdy muset do šablon či kódu zapisovat natvrdo URL adresy vaší aplikace, které se mohou později měnit, nebo je komplikovaně skládat. V odkazu stačí uvést presenter a akci, předat případné parametry a framework už URL vygeneruje sám. Vlastně je to velice podobné, jako když voláte funkci. To se vám bude líbit. V šabloně presenteru diff --git a/application/cs/templates.texy b/application/cs/templates.texy index 568b40837e..5e4452a586 100644 --- a/application/cs/templates.texy +++ b/application/cs/templates.texy @@ -274,7 +274,7 @@ class ArticleTemplate extends Nette\Bridges\ApplicationLatte\Template #[Latte\Attributes\TemplateFunction] public function isWeekend(DateTimeInterface $date): bool { - return $date->format('N') >= 6 + return $date->format('N') >= 6; } } ``` diff --git a/application/en/templates.texy b/application/en/templates.texy index 6a5ba43fd3..c5de1f1484 100644 --- a/application/en/templates.texy +++ b/application/en/templates.texy @@ -274,7 +274,7 @@ class ArticleTemplate extends Nette\Bridges\ApplicationLatte\Template #[Latte\Attributes\TemplateFunction] public function isWeekend(DateTimeInterface $date): bool { - return $date->format('N') >= 6 + return $date->format('N') >= 6; } } ``` diff --git a/best-practices/cs/creating-editing-form.texy b/best-practices/cs/creating-editing-form.texy index 4530f060d4..d43c67faf8 100644 --- a/best-practices/cs/creating-editing-form.texy +++ b/best-practices/cs/creating-editing-form.texy @@ -130,7 +130,6 @@ Záznam si uložíme do property `$record`, abychom jej měli k dispozici v meto $this->facade->update($id, $data); // ... } -} ``` Nicméně, a to by mělo být **nejdůležitejším poznatkem celého kódu**, musíme se při tvorbě formuláře ujistit, že akce je skutečně `edit`. Protože jinak by ověření v metodě `actionEdit()` vůbec neproběhlo! diff --git a/best-practices/cs/lets-create-contact-form.texy b/best-practices/cs/lets-create-contact-form.texy index e5d44812fa..23fde0f0c5 100644 --- a/best-practices/cs/lets-create-contact-form.texy +++ b/best-practices/cs/lets-create-contact-form.texy @@ -48,9 +48,6 @@ Komponentu `contactForm` necháme vykreslit v šabloně `Home/default.latte`: Pro samotné odeslání emailu vytvoříme novou třídu, kterou nazveme `ContactFacade` a umístíme ji do souboru `app/Model/ContactFacade.php`: ```php -<?php -declare(strict_types=1); - namespace App\Model; use Nette\Mail\Mailer; diff --git a/best-practices/en/creating-editing-form.texy b/best-practices/en/creating-editing-form.texy index 27e0af202b..86003dffc6 100644 --- a/best-practices/en/creating-editing-form.texy +++ b/best-practices/en/creating-editing-form.texy @@ -130,7 +130,6 @@ We store the record in the `$record` property, making it available in the `creat $this->facade->update($id, $data); // ... } -} ``` However, and this should be **the most important takeaway from the entire code**, we must ensure the action is indeed `edit` when creating the form. Otherwise, the verification in the `actionEdit()` method would not occur at all! diff --git a/best-practices/en/lets-create-contact-form.texy b/best-practices/en/lets-create-contact-form.texy index 0fd677048d..695985f569 100644 --- a/best-practices/en/lets-create-contact-form.texy +++ b/best-practices/en/lets-create-contact-form.texy @@ -48,9 +48,6 @@ Let's render the `contactForm` component in the `Home/default.latte` template: For sending the email itself, we'll create a new class named `ContactFacade` and place it in the file `app/Model/ContactFacade.php`: ```php -<?php -declare(strict_types=1); - namespace App\Model; use Nette\Mail\Mailer; diff --git a/caching/cs/@home.texy b/caching/cs/@home.texy index 17ddcaa49f..1d3f3eed17 100644 --- a/caching/cs/@home.texy +++ b/caching/cs/@home.texy @@ -125,7 +125,7 @@ Nebo pomocí 3. parametru v metodě `load()`, např: ```php $value = $cache->load($key, function () { - return ...; + return /* ... */; }, [Cache::Expire => '20 minutes']); ``` @@ -293,7 +293,7 @@ Velmi elegantně lze zachytávat a cachovat výstup: ```php if ($capture = $cache->capture($key)) { - echo ... // vypisujeme data + // echo ... vypisujeme data $capture->end(); // uložíme výstup do cache } diff --git a/caching/en/@home.texy b/caching/en/@home.texy index d8a7533643..e3557a0539 100644 --- a/caching/en/@home.texy +++ b/caching/en/@home.texy @@ -125,7 +125,7 @@ Or by using the 3rd parameter of the `load()` method itself, e.g.: ```php $value = $cache->load($key, function () { - return ...; + return /* ... */; }, [Cache::Expire => '20 minutes']); ``` @@ -293,7 +293,7 @@ Output can be captured and cached very elegantly: ```php if ($capture = $cache->capture($key)) { - echo ... // printing some data + // echo ... printing some data $capture->end(); // save the output to the cache } diff --git a/database/cs/explorer.texy b/database/cs/explorer.texy index 24044ef827..646e033f48 100644 --- a/database/cs/explorer.texy +++ b/database/cs/explorer.texy @@ -263,7 +263,7 @@ Usnadňuje stránkování výsledků. Přijímá číslo stránky (počítané o ```php $numOfPages = null; -$table->page(page: 3, itemsPerPage: 10, $numOfPages); +$table->page(page: 3, itemsPerPage: 10, numOfPages: $numOfPages); echo "Celkem stránek: $numOfPages"; ``` diff --git a/database/en/explorer.texy b/database/en/explorer.texy index dc5e7ef7af..d08f43a51e 100644 --- a/database/en/explorer.texy +++ b/database/en/explorer.texy @@ -263,7 +263,7 @@ Facilitates pagination of results. It accepts the page number (starting from 1) ```php $numOfPages = null; -$table->page(page: 3, itemsPerPage: 10, $numOfPages); +$table->page(page: 3, itemsPerPage: 10, numOfPages: $numOfPages); echo "Total pages: $numOfPages"; ``` diff --git a/dependency-injection/cs/faq.texy b/dependency-injection/cs/faq.texy index e9842c0bba..a64b806cbe 100644 --- a/dependency-injection/cs/faq.texy +++ b/dependency-injection/cs/faq.texy @@ -88,7 +88,7 @@ Mějme na paměti [Pravidlo č. 1: nech si to předat |introduction#Pravidlo č. V této ukázce je `%myParameter%` zástupný symbol pro hodnotu parametru `myParameter`, který se předá do konstruktoru třídy `MyClass`: -```php +```neon # config.neon parameters: myParameter: Some value diff --git a/dependency-injection/cs/global-state.texy b/dependency-injection/cs/global-state.texy index d152d69973..2f7ddf5caf 100644 --- a/dependency-injection/cs/global-state.texy +++ b/dependency-injection/cs/global-state.texy @@ -93,7 +93,7 @@ Musíte podrobně procházet kód, abyste zjistili, že objekt `PaymentGateway` ```php $db = new DB('mysql:', 'user', 'password'); -$gateway = new PaymentGateway($db, ...); +$gateway = new PaymentGateway($db, /* ... */); ``` Podobný problém se objevuje i při použití globálního přístupu k databázovému spojení: diff --git a/dependency-injection/en/faq.texy b/dependency-injection/en/faq.texy index b7f65321ba..6f8b836dc9 100644 --- a/dependency-injection/en/faq.texy +++ b/dependency-injection/en/faq.texy @@ -88,7 +88,7 @@ Keep in mind [Rule #1: Let It Be Passed to You |introduction#Rule #1: Let It Be In this example, `%myParameter%` is a placeholder for the value of the `myParameter` parameter, which will be passed to the `MyClass` constructor: -```php +```neon # config.neon parameters: myParameter: Some value diff --git a/dependency-injection/en/global-state.texy b/dependency-injection/en/global-state.texy index f626392831..794f2814b3 100644 --- a/dependency-injection/en/global-state.texy +++ b/dependency-injection/en/global-state.texy @@ -93,7 +93,7 @@ You must meticulously trace the code to discover that the `PaymentGateway` objec ```php $db = new DB('mysql:', 'user', 'password'); -$gateway = new PaymentGateway($db, ...); +$gateway = new PaymentGateway($db, /* ... */); ``` A similar problem arises when using global access to a database connection: diff --git a/latte/bg/custom-tags.texy b/latte/bg/custom-tags.texy index 46bbf08171..23b5b4e001 100644 --- a/latte/bg/custom-tags.texy +++ b/latte/bg/custom-tags.texy @@ -923,7 +923,7 @@ class MyLatteExtension extends Extension Генериран HTML: -```html +```latte <a href="delete.php?id=123" onclick="return confirm("Наистина ли искате да изтриете елемент 123?")">Изтриване</a> ``` diff --git a/latte/bg/safety-first.texy b/latte/bg/safety-first.texy index 56a3b9fd91..6c7b2d9e1f 100644 --- a/latte/bg/safety-first.texy +++ b/latte/bg/safety-first.texy @@ -33,7 +33,7 @@ echo '<p>Резултати от търсенето за <em>' . $search . '</em Нападателят може в полето за търсене и съответно в променливата `$search` да запише произволен низ, т.е. и HTML код като `<script>alert("Hacked!")</script>`. Тъй като изходът не е обработен по никакъв начин, той става част от показаната страница: -```html +```latte <p>Резултати от търсенето за <em><script>alert("Hacked!")</script></em></p> ``` @@ -59,7 +59,7 @@ echo '<img src="' . $imageFile . '" alt="' . $imageAlt . '">'; На нападателя е достатъчно като описание да вмъкне умело съставен низ `" onload="alert('Hacked!')` и ако изписването не е обработено, резултатният код ще изглежда така: -```html +```latte <img src="photo0145.webp" alt="" onload="alert('Hacked!')"> ``` @@ -91,7 +91,7 @@ echo '<img src="' . $imageFile . '" alt="' . $imageAlt . '">'; Какво точно се разбира под думата контекст? Това е място в документа със собствени правила за обработка на извежданите данни. Зависи от типа на документа (HTML, XML, CSS, JavaScript, plain text, ...) и може да се различава в конкретните му части. Например в HTML документ има цяла редица такива места (контексти), където важат много различни правила. Може би ще се изненадате колко са. Ето първите четири: -```html +```latte <p>#текст</p> <img src="#атрибут"> <textarea>#rawtext</textarea> @@ -108,7 +108,7 @@ echo '<img src="' . $imageFile . '" alt="' . $imageAlt . '">'; Контекстите също могат да се наслояват, което се случва, когато вмъкнем JavaScript или CSS в HTML. Това може да се направи по два различни начина, с елемент и с атрибут: -```html +```latte <script>#js-element</script> <img onclick="#js-атрибут"> @@ -132,7 +132,7 @@ echo '<img src="' . $imageFile . '" alt="' . $imageAlt . '">'; Ако го извеждате в HTML текст, точно в този случай не е необходимо да правите никакви замени, защото низът не съдържа нито един знак със специално значение. Друга ситуация възниква, ако го изведете вътре в HTML атрибут, ограден с единични кавички. В такъв случай е необходимо да екранирате кавичките в HTML ентичности: -```html +```latte <div title='Rock'n'Roll'></div> ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Ако този код вмъкнем в HTML документ с помощта на `<script>`, не е необходимо да се променя нищо друго, защото в него не се среща забранената последователност `</script`: -```html +```latte <script> alert('Rock\'n\'Roll'); </script> ``` Ако обаче искахме да го вмъкнем в HTML атрибут, трябва още да екранираме кавичките в HTML ентичности: -```html +```latte <div onclick='alert('Rock\'n\'Roll')'></div> ``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll И когато този низ изведем в атрибут, ще приложим още екраниране според този контекст и ще заменим `&` с `&`: -```html +```latte <a href="https://example.org/?a=Jazz&b=Rock%27n%27Roll"> ``` @@ -314,7 +314,7 @@ Latte вижда шаблона по същия начин като вас. Ра Нападателят като описание на изображението вмъква умело съставен низ `foo onload=alert('Hacked!')`. Вече знаем, че Twig не може да разпознае дали променливата се извежда в потока на HTML текста, вътре в атрибут, HTML коментар и т.н., накратко не разграничава контексти. И само механично преобразува знаците `< > & ' "` в HTML ентичности. Така резултатният код ще изглежда така: -```html +```latte <img src=photo0145.webp alt=foo onload=alert('Hacked!')> ``` @@ -330,7 +330,7 @@ Latte вижда шаблона по същия начин като вас. Ра Latte вижда шаблона по същия начин като вас. За разлика от Twig, разбира HTML и знае, че променливата се извежда като стойност на атрибут, който не е в кавички. Затова ги допълва. Когато нападателят вмъкне същото описание, резултатният код ще изглежда така: -```html +```latte <img src="photo0145.webp" alt="foo onload=alert('Hacked!')"> ``` diff --git a/latte/cs/custom-filters.texy b/latte/cs/custom-filters.texy index 7f7cab0c0c..75aff4b35e 100644 --- a/latte/cs/custom-filters.texy +++ b/latte/cs/custom-filters.texy @@ -111,7 +111,7 @@ class MyLatteExtension extends Extension // Registrace $latte = new Latte\Engine; -$latte->addExtension(new App\Latte\MyLatteExtension); +$latte->addExtension(new MyLatteExtension); ``` Tento přístup udrží logiku vašeho filtru zapouzdřenou a registraci jednoduchou. diff --git a/latte/cs/custom-functions.texy b/latte/cs/custom-functions.texy index 8a1e70f188..bb3677923d 100644 --- a/latte/cs/custom-functions.texy +++ b/latte/cs/custom-functions.texy @@ -95,7 +95,7 @@ class MyLatteExtension extends Extension } // Registrace (předpokládáme, že $container obsahuje DIC) -$extension = $container->getByType(App\Latte\MyLatteExtension::class); +$extension = $container->getByType(MyLatteExtension::class); $latte = new Latte\Engine; $latte->addExtension($extension); ``` diff --git a/latte/cs/custom-tags.texy b/latte/cs/custom-tags.texy index 7d41e7799d..415ed73fdd 100644 --- a/latte/cs/custom-tags.texy +++ b/latte/cs/custom-tags.texy @@ -489,7 +489,7 @@ class MyLatteExtension extends Extension // Při registraci rozšíření: $isDev = true; // Určete toto na základě prostředí vaší aplikace -$latte->addExtension(new App\Latte\MyLatteExtension($isDev)); +$latte->addExtension(new MyLatteExtension($isDev)); ``` A jeho použití v šabloně: @@ -923,7 +923,7 @@ Nyní můžete použít `n:confirm` na odkazech, tlačítkách nebo prvcích for Vygenerované HTML: -```html +```latte <a href="delete.php?id=123" onclick="return confirm("Opravdu chcete smazat položku 123?")">Smazat</a> ``` diff --git a/latte/cs/safety-first.texy b/latte/cs/safety-first.texy index e76142ec39..b718215a1b 100644 --- a/latte/cs/safety-first.texy +++ b/latte/cs/safety-first.texy @@ -33,7 +33,7 @@ echo '<p>Výsledky vyhledávání pro <em>' . $search . '</em></p>'; Ú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 `<script>alert("Hacked!")</script>`. Protože výstup není nijak ošetřen, stane se součástí zobrazené stránky: -```html +```latte <p>Výsledky vyhledávání pro <em><script>alert("Hacked!")</script></em></p> ``` @@ -59,7 +59,7 @@ echo '<img src="' . $imageFile . '" alt="' . $imageAlt . '">'; Útočníkovi stačí jako popisek vložit šikovně sestavený řetězec `" onload="alert('Hacked!')` a když vypsání nebude ošetřeno, výsledný kód bude vypadat takto: -```html +```latte <img src="photo0145.webp" alt="" onload="alert('Hacked!')"> ``` @@ -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 <p>#text</p> <img src="#atribut"> <textarea>#rawtext</textarea> @@ -108,7 +108,7 @@ Zajímavé je to uvnitř HTML komentářů. Tady se totiž k escapování nepou Kontexty se také mohou vrstvit, k čemuž dochází, když vložíme JavaScript nebo CSS do HTML. To lze udělat dvěma odlišnými způsoby, elementem a atributem: -```html +```latte <script>#js-element</script> <img onclick="#js-atribut"> @@ -132,7 +132,7 @@ Mějme ř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: -```html +```latte <div title='Rock'n'Roll'></div> ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Pokud tento kód vložíme do HTML dokumentu pomocí `<script>`, netřeba nic dalšího upravovat, protože se v něm nevyskytuje zakázaná sekvence `</script`: -```html +```latte <script> alert('Rock\'n\'Roll'); </script> ``` Pokud bychom jej však chtěli vložit do HTML atributu, musíme ještě escapovat uvozovky na HTML entity: -```html +```latte <div onclick='alert('Rock\'n\'Roll')'></div> ``` @@ -170,7 +170,7 @@ 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 `&`: -```html +```latte <a href="https://example.org/?a=Jazz&b=Rock%27n%27Roll"> ``` @@ -314,7 +314,7 @@ Všimněte si, že okolo hodnot atributů nejsou uvozovky. Kodér na ně mohl za Ú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: -```html +```latte <img src=photo0145.webp alt=foo onload=alert('Hacked!')> ``` @@ -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 <img src="photo0145.webp" alt="foo onload=alert('Hacked!')"> ``` diff --git a/latte/cs/syntax.texy b/latte/cs/syntax.texy index c5346ba1f8..39f1c621de 100644 --- a/latte/cs/syntax.texy +++ b/latte/cs/syntax.texy @@ -233,7 +233,7 @@ Latte zachází s bílými znaky inteligentně. Kód můžete volně odsazovat p Vypíše: -```html +```latte <ul> <li>foo</li> <li>bar</li> diff --git a/latte/cs/tags.texy b/latte/cs/tags.texy index 598b2b73dd..cb8b03378a 100644 --- a/latte/cs/tags.texy +++ b/latte/cs/tags.texy @@ -137,7 +137,7 @@ Jako výraz můžete zapsat cokoliv, co znáte z PHP. Nemusíte se zkrátka uči ```latte -{='0' . ($num ?? $num * 3) . ', ' . PHP_VERSION} +{='0' . ($num ?? $num * 3) . ', ' . \PHP_VERSION} ``` Prosím, nehledejte v předchozím příkladu žádný smysl, ale kdybyste tam nějaký našli, napište nám :-) diff --git a/latte/de/custom-tags.texy b/latte/de/custom-tags.texy index 483b5f5820..89089b627d 100644 --- a/latte/de/custom-tags.texy +++ b/latte/de/custom-tags.texy @@ -923,7 +923,7 @@ Jetzt können Sie `n:confirm` auf Links, Schaltflächen oder Formularelementen v Generiertes HTML: -```html +```latte <a href="delete.php?id=123" onclick="return confirm("Möchten Sie den Eintrag 123 wirklich löschen?")">Löschen</a> ``` diff --git a/latte/de/safety-first.texy b/latte/de/safety-first.texy index 2f5b0697a1..bdc0cb85fa 100644 --- a/latte/de/safety-first.texy +++ b/latte/de/safety-first.texy @@ -33,7 +33,7 @@ echo '<p>Suchergebnisse für <em>' . $search . '</em></p>'; Ein Angreifer kann in das Suchfeld und somit in die Variable `$search` eine beliebige Zeichenkette eingeben, also auch HTML-Code wie `<script>alert("Gehackt!")</script>`. Da die Ausgabe nicht bereinigt wird, wird sie Teil der angezeigten Seite: -```html +```latte <p>Suchergebnisse für <em><script>alert("Gehackt!")</script></em></p> ``` @@ -59,7 +59,7 @@ echo '<img src="' . $imageFile . '" alt="' . $imageAlt . '">'; Dem Angreifer genügt es, als Beschreibung eine geschickt konstruierte Zeichenkette `" onload="alert('Gehackt!')` einzufügen, und wenn die Ausgabe nicht bereinigt wird, sieht der resultierende Code so aus: -```html +```latte <img src="photo0145.webp" alt="" onload="alert('Gehackt!')"> ``` @@ -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 <p>#text</p> <img src="#attribut"> <textarea>#rawtext</textarea> @@ -108,7 +108,7 @@ Interessant ist es innerhalb von HTML-Kommentaren. Hier wird nämlich kein Escap Kontexte können sich auch verschachteln, was passiert, wenn wir JavaScript oder CSS in HTML einbetten. Dies kann auf zwei verschiedene Arten geschehen, mit einem Element und einem Attribut: -```html +```latte <script>#js-element</script> <img onclick="#js-attribut"> @@ -132,7 +132,7 @@ Nehmen wir die Zeichenkette `Rock'n'Roll`. Wenn Sie sie im HTML-Text ausgeben, müssen in diesem Fall keine Ersetzungen vorgenommen werden, da die Zeichenkette kein Zeichen mit besonderer Bedeutung enthält. Eine andere Situation ergibt sich, wenn Sie sie innerhalb eines HTML-Attributs ausgeben, das in einfache Anführungszeichen eingeschlossen ist. In diesem Fall müssen die Anführungszeichen in HTML-Entitäten escapet werden: -```html +```latte <div title='Rock'n'Roll'></div> ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Wenn wir diesen Code mit `<script>` in ein HTML-Dokument einfügen, muss nichts weiter geändert werden, da die verbotene Sequenz `</script` nicht darin vorkommt: -```html +```latte <script> alert('Rock\'n\'Roll'); </script> ``` Wenn wir ihn jedoch in ein HTML-Attribut einfügen wollten, müssten wir die Anführungszeichen noch in HTML-Entitäten escapen: -```html +```latte <div onclick='alert('Rock\'n\'Roll')'></div> ``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll Und wenn wir diese Zeichenkette in einem Attribut ausgeben, wenden wir noch das Escaping gemäß diesem Kontext an und ersetzen `&` durch `&`: -```html +```latte <a href="https://example.org/?a=Jazz&b=Rock%27n%27Roll"> ``` @@ -314,7 +314,7 @@ Beachten Sie, dass um die Attributwerte keine Anführungszeichen stehen. Der Pro Ein Angreifer fügt als Bildbeschreibung eine geschickt konstruierte Zeichenkette `foo onload=alert('Gehackt!')` ein. Wir wissen bereits, dass Twig nicht erkennen kann, ob die Variable im Fluss des HTML-Textes, innerhalb eines Attributs, eines HTML-Kommentars usw. ausgegeben wird, kurz gesagt, es unterscheidet keine Kontexte. Und konvertiert nur mechanisch die Zeichen `< > & ' "` in HTML-Entitäten. Der resultierende Code sieht also so aus: -```html +```latte <img src=photo0145.webp alt=foo onload=alert('Gehackt!')> ``` @@ -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 <img src="photo0145.webp" alt="foo onload=alert('Gehackt!')"> ``` 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 <a href="delete.php?id=123" onclick="return confirm("Θέλετε πραγματικά να διαγράψετε το στοιχείο 123?")">Διαγραφή</a> ``` 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 '<p>Αποτελέσματα αναζήτησης για <em>' . $search . Ένας εισβολέας μπορεί να γράψει στο πεδίο αναζήτησης και κατ' επέκταση στη μεταβλητή `$search` οποιοδήποτε string, δηλαδή και κώδικα HTML όπως `<script>alert("Hacked!")</script>`. Επειδή η έξοδος δεν επεξεργάζεται με κανέναν τρόπο, γίνεται μέρος της εμφανιζόμενης σελίδας: -```html +```latte <p>Αποτελέσματα αναζήτησης για <em><script>alert("Hacked!")</script></em></p> ``` @@ -59,7 +59,7 @@ echo '<img src="' . $imageFile . '" alt="' . $imageAlt . '">'; Αρκεί ο εισβολέας να εισάγει ως λεζάντα ένα έξυπνα κατασκευασμένο string `" onload="alert('Hacked!')` και αν η εκτύπωση δεν επεξεργαστεί, ο προκύπτων κώδικας θα μοιάζει ως εξής: -```html +```latte <img src="photo0145.webp" alt="" onload="alert('Hacked!')"> ``` @@ -91,7 +91,7 @@ Context-Aware Escaping Τι ακριβώς εννοούμε με τη λέξη context; Πρόκειται για ένα μέρος στο έγγραφο με τους δικούς του κανόνες για την επεξεργασία των εκτυπωμένων δεδομένων. Εξαρτάται από τον τύπο του εγγράφου (HTML, XML, CSS, JavaScript, plain text, ...) και μπορεί να διαφέρει σε συγκεκριμένα μέρη του. Για παράδειγμα, σε ένα έγγραφο HTML, υπάρχουν πολλά τέτοια μέρη (contexts) όπου ισχύουν πολύ διαφορετικοί κανόνες. Ίσως εκπλαγείτε πόσα είναι. Εδώ έχουμε την πρώτη τετράδα: -```html +```latte <p>#κείμενο</p> <img src="#attribute"> <textarea>#rawtext</textarea> @@ -108,7 +108,7 @@ Context-Aware Escaping Τα contexts μπορούν επίσης να στρωματοποιηθούν, κάτι που συμβαίνει όταν ενσωματώνουμε JavaScript ή CSS σε HTML. Αυτό μπορεί να γίνει με δύο διαφορετικούς τρόπους, με στοιχείο και με attribute: -```html +```latte <script>#js-element</script> <img onclick="#js-attribute"> @@ -132,7 +132,7 @@ Context-Aware Escaping Αν το εκτυπώσετε σε κείμενο HTML, σε αυτή τη συγκεκριμένη περίπτωση δεν χρειάζεται να κάνετε καμία αντικατάσταση, επειδή το string δεν περιέχει κανέναν χαρακτήρα με ειδική σημασία. Η κατάσταση αλλάζει αν το εκτυπώσετε μέσα σε ένα attribute HTML που περικλείεται σε απλά εισαγωγικά. Σε αυτή την περίπτωση, πρέπει να κάνετε escape τα εισαγωγικά σε οντότητες HTML: -```html +```latte <div title='Rock'n'Roll'></div> ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Αν εισάγουμε αυτόν τον κώδικα σε ένα έγγραφο HTML χρησιμοποιώντας το `<script>`, δεν χρειάζεται να τροποποιήσουμε τίποτα άλλο, επειδή δεν περιέχει την απαγορευμένη ακολουθία `</script`: -```html +```latte <script> alert('Rock\'n\'Roll'); </script> ``` Αν όμως θέλαμε να το εισάγουμε σε ένα attribute HTML, πρέπει ακόμα να κάνουμε escape τα εισαγωγικά σε οντότητες HTML: -```html +```latte <div onclick='alert('Rock\'n\'Roll')'></div> ``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll Και όταν εκτυπώνουμε αυτό το string σε ένα attribute, εφαρμόζουμε επιπλέον το escaping σύμφωνα με αυτό το context και αντικαθιστούμε το `&` με `&`: -```html +```latte <a href="https://example.org/?a=Jazz&b=Rock%27n%27Roll"> ``` @@ -314,7 +314,7 @@ Latte εναντίον απλοϊκών συστημάτων Ένας εισβολέας εισάγει ως λεζάντα της εικόνας ένα έξυπνα κατασκευασμένο string `foo onload=alert('Hacked!')`. Γνωρίζουμε ήδη ότι το Twig δεν μπορεί να αναγνωρίσει αν η μεταβλητή εκτυπώνεται στη ροή του κειμένου HTML, μέσα σε ένα attribute, σε ένα σχόλιο HTML κ.λπ., με λίγα λόγια δεν διακρίνει τα contexts. Και απλώς μετατρέπει μηχανικά τους χαρακτήρες `< > & ' "` σε οντότητες HTML. Έτσι, ο προκύπτων κώδικας θα μοιάζει ως εξής: -```html +```latte <img src=photo0145.webp alt=foo onload=alert('Hacked!')> ``` @@ -330,7 +330,7 @@ Latte εναντίον απλοϊκών συστημάτων Το Latte βλέπει το πρότυπο όπως εσείς. Σε αντίθεση με το Twig, καταλαβαίνει HTML και ξέρει ότι η μεταβλητή εκτυπώνεται ως τιμή ενός attribute που δεν βρίσκεται σε εισαγωγικά. Γι' αυτό τα συμπληρώνει. Όταν ο εισβολέας εισάγει την ίδια λεζάντα, ο προκύπτων κώδικας θα μοιάζει ως εξής: -```html +```latte <img src="photo0145.webp" alt="foo onload=alert('Hacked!')"> ``` diff --git a/latte/en/custom-filters.texy b/latte/en/custom-filters.texy index 9fc3ea58b6..186caf6fb4 100644 --- a/latte/en/custom-filters.texy +++ b/latte/en/custom-filters.texy @@ -111,7 +111,7 @@ class MyLatteExtension extends Extension // Registration $latte = new Latte\Engine; -$latte->addExtension(new App\Latte\MyLatteExtension); +$latte->addExtension(new MyLatteExtension); ``` This approach keeps your filter logic encapsulated and makes registration straightforward. diff --git a/latte/en/custom-functions.texy b/latte/en/custom-functions.texy index 4c4a4d423d..f4616ceea1 100644 --- a/latte/en/custom-functions.texy +++ b/latte/en/custom-functions.texy @@ -95,7 +95,7 @@ class MyLatteExtension extends Extension } // Registration (assuming $container holds the DIC) -$extension = $container->getByType(App\Latte\MyLatteExtension::class); +$extension = $container->getByType(MyLatteExtension::class); $latte = new Latte\Engine; $latte->addExtension($extension); ``` diff --git a/latte/en/custom-tags.texy b/latte/en/custom-tags.texy index b427e74a27..6fcc3cd9aa 100644 --- a/latte/en/custom-tags.texy +++ b/latte/en/custom-tags.texy @@ -489,7 +489,7 @@ class MyLatteExtension extends Extension // When registering the extension: $isDev = true; // Determine this based on your application's environment -$latte->addExtension(new App\Latte\MyLatteExtension($isDev)); +$latte->addExtension(new MyLatteExtension($isDev)); ``` And use it in a template: @@ -923,7 +923,7 @@ Now you can use `n:confirm` on links, buttons, or form elements: Generated HTML: -```html +```latte <a href="delete.php?id=123" onclick="return confirm("Do you really want to delete item 123?")">Delete</a> ``` diff --git a/latte/en/safety-first.texy b/latte/en/safety-first.texy index 4e2c9480f4..004656ca94 100644 --- a/latte/en/safety-first.texy +++ b/latte/en/safety-first.texy @@ -33,7 +33,7 @@ echo '<p>Search results for <em>' . $search . '</em></p>'; An attacker can enter any string into the search box, and thus into the `$search` variable, including HTML code like `<script>alert("Hacked!")</script>`. Since the output is not sanitized, it becomes part of the displayed page: -```html +```latte <p>Search results for <em><script>alert("Hacked!")</script></em></p> ``` @@ -59,7 +59,7 @@ echo '<img src="' . $imageFile . '" alt="' . $imageAlt . '">'; 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 <img src="photo0145.webp" alt="" onload="alert('Hacked!')"> ``` @@ -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 <p>#text</p> <img src="#attribute"> <textarea>#rawtext</textarea> @@ -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 <script>#js-element</script> <img onclick="#js-attribute"> @@ -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 <div title='Rock'n'Roll'></div> ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); If we insert this code into an HTML document using `<script>`, no further modification is needed because it does not contain the forbidden sequence `</script`: -```html +```latte <script> alert('Rock\'n\'Roll'); </script> ``` However, if we wanted to insert it into an HTML attribute, we still need to escape the quotes into HTML entities: -```html +```latte <div onclick='alert('Rock\'n\'Roll')'></div> ``` @@ -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 <a href="https://example.org/?a=Jazz&b=Rock%27n%27Roll"> ``` @@ -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 <img src=photo0145.webp alt=foo onload=alert('Hacked!')> ``` @@ -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 <img src="photo0145.webp" alt="foo onload=alert('Hacked!')"> ``` diff --git a/latte/en/syntax.texy b/latte/en/syntax.texy index 24656e0571..aa7e274f5f 100644 --- a/latte/en/syntax.texy +++ b/latte/en/syntax.texy @@ -233,7 +233,7 @@ Latte handles whitespace intelligently. You can freely indent your code for read Outputs: -```html +```latte <ul> <li>foo</li> <li>bar</li> diff --git a/latte/en/tags.texy b/latte/en/tags.texy index cfbc94ae6f..ffb90c69c1 100644 --- a/latte/en/tags.texy +++ b/latte/en/tags.texy @@ -137,7 +137,7 @@ You can write anything you know from PHP as an expression. You simply don't have ```latte -{='0' . ($num ?? $num * 3) . ', ' . PHP_VERSION} +{='0' . ($num ?? $num * 3) . ', ' . \PHP_VERSION} ``` Please don't look for any meaning in the previous example, but if you find one, let us know :-) diff --git a/latte/es/custom-tags.texy b/latte/es/custom-tags.texy index f32e309910..fbb0646b5b 100644 --- a/latte/es/custom-tags.texy +++ b/latte/es/custom-tags.texy @@ -923,7 +923,7 @@ Ahora puede usar `n:confirm` en enlaces, botones o elementos de formulario: HTML generado: -```html +```latte <a href="delete.php?id=123" onclick="return confirm("¿Realmente quieres eliminar el elemento 123?")">Eliminar</a> ``` diff --git a/latte/es/safety-first.texy b/latte/es/safety-first.texy index 437dd39aac..6fe173ea9c 100644 --- a/latte/es/safety-first.texy +++ b/latte/es/safety-first.texy @@ -33,7 +33,7 @@ echo '<p>Resultados de la búsqueda para <em>' . $search . '</em></p>'; Un atacante puede escribir en el campo de búsqueda y, por extensión, en la variable `$search` cualquier cadena, incluido código HTML como `<script>alert("Hacked!")</script>`. Dado que la salida no está saneada de ninguna manera, se convierte en parte de la página mostrada: -```html +```latte <p>Resultados de la búsqueda para <em><script>alert("Hacked!")</script></em></p> ``` @@ -59,7 +59,7 @@ echo '<img src="' . $imageFile . '" alt="' . $imageAlt . '">'; 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 <img src="photo0145.webp" alt="" onload="alert('Hacked!')"> ``` @@ -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 <p>#texto</p> <img src="#atributo"> <textarea>#rawtext</textarea> @@ -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 <script>#js-elemento</script> <img onclick="#js-atributo"> @@ -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 <div title='Rock'n'Roll'></div> ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Si insertamos este código en un documento HTML usando `<script>`, no es necesario modificar nada más, porque no contiene la secuencia prohibida `</script`: -```html +```latte <script> alert('Rock\'n\'Roll'); </script> ``` Sin embargo, si quisiéramos insertarlo en un atributo HTML, aún debemos escapar las comillas a entidades HTML: -```html +```latte <div onclick='alert('Rock\'n\'Roll')'></div> ``` @@ -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 <a href="https://example.org/?a=Jazz&b=Rock%27n%27Roll"> ``` @@ -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 <img src=photo0145.webp alt=foo onload=alert('Hacked!')> ``` @@ -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 <img src="photo0145.webp" alt="foo onload=alert('Hacked!')"> ``` 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 <a href="delete.php?id=123" onclick="return confirm("Voulez-vous vraiment supprimer l'élément 123 ?")">Supprimer</a> ``` 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 '<p>Résultats de la recherche pour <em>' . $search . '</em></p>'; Un attaquant peut entrer dans le champ de recherche et donc dans la variable `$search` n'importe quelle chaîne, y compris du code HTML comme `<script>alert("Piraté !")</script>`. Comme la sortie n'est pas traitée, elle devient partie intégrante de la page affichée : -```html +```latte <p>Résultats de la recherche pour <em><script>alert("Piraté !")</script></em></p> ``` @@ -59,7 +59,7 @@ echo '<img src="' . $imageFile . '" alt="' . $imageAlt . '">'; 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 <img src="photo0145.webp" alt="" onload="alert('Piraté !')"> ``` @@ -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 <p>#texte</p> <img src="#attribut"> <textarea>#rawtext</textarea> @@ -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 <script>#js-element</script> <img onclick="#js-attribut"> @@ -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 <div title='Rock'n'Roll'></div> ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Si nous insérons ce code dans un document HTML à l'aide de `<script>`, il n'est pas nécessaire de le modifier davantage, car il ne contient pas la séquence interdite `</script`: -```html +```latte <script> alert('Rock\'n\'Roll'); </script> ``` Cependant, si nous voulions l'insérer dans un attribut HTML, nous devrions encore échapper les guillemets en entités HTML : -```html +```latte <div onclick='alert('Rock\'n\'Roll')'></div> ``` @@ -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 <a href="https://example.org/?a=Jazz&b=Rock%27n%27Roll"> ``` @@ -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 <img src=photo0145.webp alt=foo onload=alert('Piraté !')> ``` @@ -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 <img src="photo0145.webp" alt="foo onload=alert('Piraté !')"> ``` 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 <a href="delete.php?id=123" onclick="return confirm("Valóban törölni szeretné a(z) 123 elemet?")">Törlés</a> ``` 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 '<p>Keresési eredmények erre: <em>' . $search . '</em></p>'; A támadó a keresőmezőbe és ezáltal a `$search` változóba bármilyen stringet beírhat, tehát HTML kódot is, mint `<script>alert("Hacked!")</script>`. Mivel a kimenet nincs semmilyen módon kezelve, a megjelenített oldal részévé válik: -```html +```latte <p>Keresési eredmények erre: <em><script>alert("Hacked!")</script></em></p> ``` @@ -59,7 +59,7 @@ echo '<img src="' . $imageFile . '" alt="' . $imageAlt . '">'; 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 <img src="photo0145.webp" alt="" onload="alert('Hacked!')"> ``` @@ -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 <p>#szöveg</p> <img src="#attribútum"> <textarea>#rawtext</textarea> @@ -108,7 +108,7 @@ Talán meglepő, de speciális szabályok érvényesek a `<textarea>` és `<titl A kontextusok rétegződhetnek is, ami akkor következik be, amikor JavaScriptet vagy CSS-t illesztünk be HTML-be. Ezt két különböző módon lehet megtenni, elemmel és attribútummal: -```html +```latte <script>#js-elem</script> <img onclick="#js-attribútum"> @@ -132,7 +132,7 @@ Vegyünk egy `Rock'n'Roll` stringet. Ha HTML szövegben írja ki, ebben az esetben nincs szükség semmilyen cserére, mert a string nem tartalmaz semmilyen speciális jelentéssel bíró karaktert. Más a helyzet, ha egy aposztrófokkal határolt HTML attribútumon belül írja ki. Ebben az esetben az aposztrófokat HTML entitásokra kell escapelni: -```html +```latte <div title='Rock'n'Roll'></div> ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Ha ezt a kódot a `<script>` segítségével illesztjük be a HTML dokumentumba, nincs szükség további módosításra, mert nem tartalmazza a tiltott `</script` szekvenciát: -```html +```latte <script> alert('Rock\'n\'Roll'); </script> ``` Ha azonban HTML attribútumba szeretnénk beilleszteni, még escapelnünk kell az idézőjeleket HTML entitásokra: -```html +```latte <div onclick='alert('Rock\'n\'Roll')'></div> ``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll És amikor ezt a stringet egy attribútumban írjuk ki, még alkalmazzuk az escapelést ennek a kontextusnak megfelelően, és helyettesítjük az `&`-t `&`-pal: -```html +```latte <a href="https://example.org/?a=Jazz&b=Rock%27n%27Roll"> ``` @@ -314,7 +314,7 @@ Figyelje meg, hogy az attribútumok értékei körül nincsenek idézőjelek. A A támadó a kép leírásaként egy ügyesen összeállított `foo onload=alert('Hacked!')` stringet illeszt be. Már tudjuk, hogy a Twig nem tudja megállapítani, hogy a változó a HTML szövegfolyamban, egy attribútumon belül, HTML kommentárban stb. íródik-e ki, röviden nem különbözteti meg a kontextusokat. És csak mechanikusan alakítja át a `< > & ' "` karaktereket HTML entitásokká. Így az eredményül kapott kód így fog kinézni: -```html +```latte <img src=photo0145.webp alt=foo onload=alert('Hacked!')> ``` @@ -330,7 +330,7 @@ Most nézzük meg, hogyan bánik el ugyanezzel a sablonnal a Latte: A Latte ugyanúgy látja a sablont, mint Ön. A Twiggel ellentétben érti a HTML-t, és tudja, hogy a változó egy attribútum értékeként íródik ki, amely nincs idézőjelek között. Ezért kiegészíti őket. Ha a támadó ugyanazt a leírást illeszti be, az eredményül kapott kód így fog kinézni: -```html +```latte <img src="photo0145.webp" alt="foo onload=alert('Hacked!')"> ``` diff --git a/latte/it/custom-tags.texy b/latte/it/custom-tags.texy index 40b065cc9a..3200404f53 100644 --- a/latte/it/custom-tags.texy +++ b/latte/it/custom-tags.texy @@ -923,7 +923,7 @@ Ora potete usare `n:confirm` su link, pulsanti o elementi del form: HTML generato: -```html +```latte <a href="delete.php?id=123" onclick="return confirm("Vuoi davvero eliminare l'elemento 123?")">Elimina</a> ``` diff --git a/latte/it/safety-first.texy b/latte/it/safety-first.texy index a13fdc6a16..29fc90f37f 100644 --- a/latte/it/safety-first.texy +++ b/latte/it/safety-first.texy @@ -33,7 +33,7 @@ echo '<p>Risultati della ricerca per <em>' . $search . '</em></p>'; Un aggressore può inserire nella casella di ricerca e quindi nella variabile `$search` qualsiasi stringa, quindi anche codice HTML come `<script>alert("Hacked!")</script>`. Poiché l'output non è in alcun modo trattato, diventa parte della pagina visualizzata: -```html +```latte <p>Risultati della ricerca per <em><script>alert("Hacked!")</script></em></p> ``` @@ -59,7 +59,7 @@ echo '<img src="' . $imageFile . '" alt="' . $imageAlt . '">'; All'aggressore basta inserire come didascalia una stringa abilmente costruita `" onload="alert('Hacked!')` e se la stampa non viene trattata, il codice risultante sarà simile a questo: -```html +```latte <img src="photo0145.webp" alt="" onload="alert('Hacked!')"> ``` @@ -91,7 +91,7 @@ Escaping sensibile al contesto Cosa si intende esattamente con la parola contesto? È un luogo nel documento con le proprie regole per il trattamento dei dati stampati. Dipende dal tipo di documento (HTML, XML, CSS, JavaScript, testo semplice, ...) e può differire nelle sue parti specifiche. Ad esempio, in un documento HTML, ci sono molti posti (contesti) in cui si applicano regole molto diverse. Potresti essere sorpreso di quanti ce ne siano. Ecco i primi quattro: -```html +```latte <p>#text</p> <img src="#atribut"> <textarea>#rawtext</textarea> @@ -108,7 +108,7 @@ Potresti essere sorpreso, ma regole speciali si applicano all'interno degli elem I contesti possono anche essere annidati, cosa che accade quando inseriamo JavaScript o CSS in HTML. Questo può essere fatto in due modi diversi, con un elemento e con un attributo: -```html +```latte <script>#js-element</script> <img onclick="#js-atribut"> @@ -132,7 +132,7 @@ Prendiamo la stringa `Rock'n'Roll`. Se la stampi nel testo HTML, proprio in questo caso non è necessario effettuare alcuna sostituzione, perché la stringa non contiene alcun carattere con significato speciale. La situazione cambia se la stampi all'interno di un attributo HTML racchiuso tra apici singoli. In tal caso, è necessario eseguire l'escaping degli apici in entità HTML: -```html +```latte <div title='Rock'n'Roll'></div> ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Se inseriamo questo codice nel documento HTML usando `<script>`, non è necessario modificare nient'altro, perché non contiene la sequenza proibita `</script`: -```html +```latte <script> alert('Rock\'n\'Roll'); </script> ``` Se però volessimo inserirlo in un attributo HTML, dobbiamo ancora eseguire l'escaping degli apici in entità HTML: -```html +```latte <div onclick='alert('Rock\'n\'Roll')'></div> ``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll E quando stampiamo questa stringa in un attributo, applichiamo ancora l'escaping secondo questo contesto e sostituiamo `&` con `&`: -```html +```latte <a href="https://example.org/?a=Jazz&b=Rock%27n%27Roll"> ``` @@ -314,7 +314,7 @@ Notate che non ci sono virgolette attorno ai valori degli attributi. Il codifica Un aggressore inserisce come didascalia dell'immagine una stringa abilmente costruita `foo onload=alert('Hacked!')`. Sappiamo già che Twig non può riconoscere se la variabile viene stampata nel flusso del testo HTML, all'interno di un attributo, di un commento HTML, ecc., in breve non distingue i contesti. E converte meccanicamente solo i caratteri `< > & ' "` in entità HTML. Quindi il codice risultante sarà simile a questo: -```html +```latte <img src=photo0145.webp alt=foo onload=alert('Hacked!')> ``` @@ -330,7 +330,7 @@ Ora vediamo come Latte gestisce lo stesso template: Latte vede il template come lo vedi tu. A differenza di Twig, capisce HTML e sa che la variabile viene stampata come valore di un attributo che non è tra virgolette. Pertanto le aggiunge. Quando l'aggressore inserisce la stessa didascalia, il codice risultante sarà simile a questo: -```html +```latte <img src="photo0145.webp" alt="foo onload=alert('Hacked!')"> ``` diff --git a/latte/ja/custom-tags.texy b/latte/ja/custom-tags.texy index a3114b7964..347975a50b 100644 --- a/latte/ja/custom-tags.texy +++ b/latte/ja/custom-tags.texy @@ -923,7 +923,7 @@ class MyLatteExtension extends Extension 生成されたHTML: -```html +```latte <a href="delete.php?id=123" onclick="return confirm("本当にアイテム 123 を削除しますか?")">削除</a> ``` diff --git a/latte/ja/safety-first.texy b/latte/ja/safety-first.texy index 15f0190eb4..1e2c48e606 100644 --- a/latte/ja/safety-first.texy +++ b/latte/ja/safety-first.texy @@ -33,7 +33,7 @@ echo '<p>検索結果: <em>' . $search . '</em></p>'; 攻撃者は、検索ボックス、ひいては変数 `$search` に任意の文字列、つまり `<script>alert("Hacked!")</script>` のようなHTMLコードを入力できます。出力がサニタイズされていないため、表示されるページの一部になります: -```html +```latte <p>検索結果: <em><script>alert("Hacked!")</script></em></p> ``` @@ -59,7 +59,7 @@ echo '<img src="' . $imageFile . '" alt="' . $imageAlt . '">'; 攻撃者は、説明として巧妙に作成された文字列 `" onload="alert('Hacked!')` を挿入するだけで、出力がサニタイズされていない場合、結果のコードは次のようになります: -```html +```latte <img src="photo0145.webp" alt="" onload="alert('Hacked!')"> ``` @@ -91,7 +91,7 @@ XSSからどのように防御しますか? コンテキストという言葉で正確には何を意味しますか?それは、出力されるデータのサニタイズに関する独自のルールを持つドキュメント内の場所です。それはドキュメントのタイプ(HTML、XML、CSS、JavaScript、プレーンテキストなど)に依存し、その特定の場所によって異なる場合があります。 例えば、HTMLドキュメントには、非常に異なるルールが適用される多くの場所(コンテキスト)があります。いくつあるか驚くかもしれません。ここに最初の4つがあります: -```html +```latte <p>#テキスト</p> <img src="#属性"> <textarea>#rawtext</textarea> @@ -108,7 +108,7 @@ HTMLコメント内では興味深いです。ここでは、エスケープにH コンテキストはネストすることもできます。これは、JavaScriptまたはCSSをHTMLに埋め込むときに発生します。これは2つの異なる方法、要素と属性で行うことができます: -```html +```latte <script>#js-element</script> <img onclick="#js-attribute"> @@ -132,7 +132,7 @@ HTMLコメント内では興味深いです。ここでは、エスケープにH HTMLテキストに出力する場合、この特定のケースでは、文字列に特別な意味を持つ文字が含まれていないため、置換を行う必要はありません。状況は、単一引用符で囲まれたHTML属性内に出力する場合に異なります。その場合、引用符をHTMLエンティティにエスケープする必要があります: -```html +```latte <div title='Rock'n'Roll'></div> ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); このコードを `<script>` を使用してHTMLドキュメントに挿入する場合、禁止されているシーケンス `</script` が含まれていないため、それ以上変更する必要はありません: -```html +```latte <script> alert('Rock\'n\'Roll'); </script> ``` しかし、HTML属性に挿入したい場合は、さらに引用符をHTMLエンティティにエスケープする必要があります: -```html +```latte <div onclick='alert('Rock\'n\'Roll')'></div> ``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll そして、この文字列を属性に出力するとき、このコンテキストに従ってエスケープを適用し、`&` を `&` に置き換えます: -```html +```latte <a href="https://example.org/?a=Jazz&b=Rock%27n%27Roll"> ``` @@ -314,7 +314,7 @@ Latteはテンプレートをあなたと同じように見ます。HTML、XML 攻撃者は、画像の説明として巧妙に作成された文字列 `foo onload=alert('Hacked!')` を挿入します。Twigは、変数がHTMLテキストの流れの中、属性内、HTMLコメント内など、どこに出力されているかを判断できないこと、つまりコンテキストを区別しないことをすでに知っています。そして、文字 `< > & ' "` を機械的にHTMLエンティティに変換するだけです。 したがって、結果のコードは次のようになります: -```html +```latte <img src=photo0145.webp alt=foo onload=alert('Hacked!')> ``` @@ -330,7 +330,7 @@ Latteはテンプレートをあなたと同じように見ます。HTML、XML Latteはテンプレートをあなたと同じように見ます。Twigとは異なり、HTMLを理解し、変数が引用符で囲まれていない属性の値として出力されていることを知っています。したがって、それらを補完します。攻撃者が同じ説明を挿入すると、結果のコードは次のようになります: -```html +```latte <img src="photo0145.webp" alt="foo onload=alert('Hacked!')"> ``` diff --git a/latte/pl/custom-tags.texy b/latte/pl/custom-tags.texy index 50be9f0562..8dd42d7929 100644 --- a/latte/pl/custom-tags.texy +++ b/latte/pl/custom-tags.texy @@ -923,7 +923,7 @@ Teraz możesz użyć `n:confirm` na linkach, przyciskach lub elementach formular Wygenerowany HTML: -```html +```latte <a href="delete.php?id=123" onclick="return confirm("Czy na pewno chcesz usunąć element 123?")">Usuń</a> ``` diff --git a/latte/pl/safety-first.texy b/latte/pl/safety-first.texy index dc1f49265c..d8a666e1d7 100644 --- a/latte/pl/safety-first.texy +++ b/latte/pl/safety-first.texy @@ -33,7 +33,7 @@ echo '<p>Wyniki wyszukiwania dla <em>' . $search . '</em></p>'; Atakujący może w polu wyszukiwania, a tym samym w zmiennej `$search`, wpisać dowolny ciąg znaków, czyli również kod HTML, taki jak `<script>alert("Hacked!")</script>`. Ponieważ wyjście nie jest w żaden sposób oczyszczone, stanie się częścią wyświetlonej strony: -```html +```latte <p>Wyniki wyszukiwania dla <em><script>alert("Hacked!")</script></em></p> ``` @@ -59,7 +59,7 @@ echo '<img src="' . $imageFile . '" alt="' . $imageAlt . '">'; Atakującemu wystarczy jako opis wstawić sprytnie skonstruowany ciąg `" onload="alert('Hacked!')`, a jeśli wyświetlanie nie zostanie oczyszczone, wynikowy kod będzie wyglądał tak: -```html +```latte <img src="photo0145.webp" alt="" onload="alert('Hacked!')"> ``` @@ -91,7 +91,7 @@ Escapowanie kontekstowe Co dokładnie oznacza słowo kontekst? Jest to miejsce w dokumencie z własnymi zasadami oczyszczania wyświetlanych danych. Zależy od typu dokumentu (HTML, XML, CSS, JavaScript, plain text, ...) i może się różnić w jego poszczególnych częściach. Na przykład w dokumencie HTML istnieje wiele takich miejsc (kontekstów), gdzie obowiązują bardzo różne zasady. Być może będziesz zaskoczony, ile ich jest. Oto pierwsza czwórka: -```html +```latte <p>#text</p> <img src="#atrybut"> <textarea>#rawtext</textarea> @@ -108,7 +108,7 @@ Ciekawie jest wewnątrz komentarzy HTML. Tutaj bowiem do escapowania nie używa Konteksty mogą się również nakładać, co ma miejsce, gdy wstawiamy JavaScript lub CSS do HTML. Można to zrobić na dwa różne sposoby, elementem i atrybutem: -```html +```latte <script>#js-element</script> <img onclick="#js-atrybut"> @@ -132,7 +132,7 @@ Miejmy ciąg `Rock'n'Roll`. Jeśli będziesz go wyświetlać w tekście HTML, akurat w tym przypadku nie trzeba dokonywać żadnych zamian, ponieważ ciąg nie zawiera żadnego znaku o specjalnym znaczeniu. Inna sytuacja nastąpi, jeśli wyświetlisz go wewnątrz atrybutu HTML ujętego w pojedyncze cudzysłowy. W takim przypadku trzeba escapować cudzysłowy na encje HTML: -```html +```latte <div title='Rock'n'Roll'></div> ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Jeśli ten kod wstawimy do dokumentu HTML za pomocą `<script>`, nie trzeba niczego więcej modyfikować, ponieważ nie występuje w nim zakazana sekwencja `</script`: -```html +```latte <script> alert('Rock\'n\'Roll'); </script> ``` Jeśli jednak chcielibyśmy go wstawić do atrybutu HTML, musimy jeszcze escapować cudzysłowy na encje HTML: -```html +```latte <div onclick='alert('Rock\'n\'Roll')'></div> ``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll A kiedy ten ciąg wyświetlimy w atrybucie, jeszcze zastosujemy escapowanie zgodnie z tym kontekstem i zastąpimy `&` na `&`: -```html +```latte <a href="https://example.org/?a=Jazz&b=Rock%27n%27Roll"> ``` @@ -314,7 +314,7 @@ Zwróć uwagę, że wokół wartości atrybutów nie ma cudzysłowów. Koder mó Atakujący jako opis obrazka wstawia sprytnie skonstruowany ciąg `foo onload=alert('Hacked!')`. Już wiemy, że Twig nie może rozpoznać, czy zmienna jest wyświetlana w przepływie tekstu HTML, wewnątrz atrybutu, komentarza HTML itp., krótko mówiąc, nie rozróżnia kontekstów. I tylko mechanicznie konwertuje znaki `< > & ' "` na encje HTML. Więc wynikowy kod będzie wyglądał tak: -```html +```latte <img src=photo0145.webp alt=foo onload=alert('Hacked!')> ``` @@ -330,7 +330,7 @@ Teraz zobaczymy, jak z tym samym szablonem poradzi sobie Latte: Latte widzi szablon tak samo jak Ty. W przeciwieństwie do Twiga rozumie HTML i wie, że zmienna jest wyświetlana jako wartość atrybutu, który nie jest w cudzysłowach. Dlatego je uzupełni. Kiedy atakujący wstawi ten sam opis, wynikowy kod będzie wyglądał tak: -```html +```latte <img src="photo0145.webp" alt="foo onload=alert('Hacked!')"> ``` diff --git a/latte/pt/custom-tags.texy b/latte/pt/custom-tags.texy index b080e9e20b..1e523ed866 100644 --- a/latte/pt/custom-tags.texy +++ b/latte/pt/custom-tags.texy @@ -923,7 +923,7 @@ Agora você pode usar `n:confirm` em links, botões ou elementos de formulário: HTML gerado: -```html +```latte <a href="delete.php?id=123" onclick="return confirm("Realmente deseja excluir o item 123?")">Excluir</a> ``` diff --git a/latte/pt/safety-first.texy b/latte/pt/safety-first.texy index 049ff1ae25..5e0351605c 100644 --- a/latte/pt/safety-first.texy +++ b/latte/pt/safety-first.texy @@ -33,7 +33,7 @@ echo '<p>Resultados da pesquisa para <em>' . $search . '</em></p>'; Um atacante pode inserir na caixa de pesquisa e, consequentemente, na variável `$search`, qualquer string, ou seja, também código HTML como `<script>alert("Hacked!")</script>`. Como a saída não é tratada de forma alguma, ela torna-se parte da página exibida: -```html +```latte <p>Resultados da pesquisa para <em><script>alert("Hacked!")</script></em></p> ``` @@ -59,7 +59,7 @@ echo '<img src="' . $imageFile . '" alt="' . $imageAlt . '">'; Basta ao atacante inserir como legenda uma string habilmente construída `" onload="alert('Hacked!')` e, se a exibição não for tratada, o código resultante será assim: -```html +```latte <img src="photo0145.webp" alt="" onload="alert('Hacked!')"> ``` @@ -91,7 +91,7 @@ Escaping sensível ao contexto O que exatamente se entende pela palavra contexto? É um local no documento com as suas próprias regras para o tratamento dos dados exibidos. Depende do tipo de documento (HTML, XML, CSS, JavaScript, texto simples, ...) e pode diferir nas suas partes específicas. Por exemplo, num documento HTML, existem muitos desses locais (contextos), onde regras muito diferentes se aplicam. Pode surpreender-se com quantos existem. Aqui temos os quatro primeiros: -```html +```latte <p>#texto</p> <img src="#atributo"> <textarea>#rawtext</textarea> @@ -108,7 +108,7 @@ Pode surpreender-se, mas regras especiais aplicam-se dentro dos elementos `<text Os contextos também podem ser aninhados, o que ocorre quando inserimos JavaScript ou CSS em HTML. Isso pode ser feito de duas maneiras diferentes, por elemento e por atributo: -```html +```latte <script>#js-elemento</script> <img onclick="#js-atributo"> @@ -132,7 +132,7 @@ Tenha a string `Rock'n'Roll`. Se a exibir em texto HTML, neste caso específico não é necessário fazer nenhuma substituição, pois a string não contém nenhum caractere com significado especial. A situação muda se a exibir dentro de um atributo HTML delimitado por aspas simples. Nesse caso, é necessário escapar as aspas para entidades HTML: -```html +```latte <div title='Rock'n'Roll'></div> ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Se inserirmos este código num documento HTML usando `<script>`, não é necessário modificar mais nada, pois ele não contém a sequência proibida `</script`: -```html +```latte <script> alert('Rock\'n\'Roll'); </script> ``` No entanto, se quiséssemos inseri-lo num atributo HTML, ainda precisaríamos de escapar as aspas para entidades HTML: -```html +```latte <div onclick='alert('Rock\'n\'Roll')'></div> ``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll E quando exibimos esta string num atributo, ainda aplicamos o escaping de acordo com este contexto e substituímos `&` por `&`: -```html +```latte <a href="https://example.org/?a=Jazz&b=Rock%27n%27Roll"> ``` @@ -314,7 +314,7 @@ Observe que não há aspas em torno dos valores dos atributos. O codificador pod Um atacante insere como legenda da imagem uma string habilmente construída `foo onload=alert('Hacked!')`. Já sabemos que o Twig não pode saber se a variável está a ser exibida no fluxo de texto HTML, dentro de um atributo, comentário HTML, etc., em suma, não distingue contextos. E apenas converte mecanicamente os caracteres `< > & ' "` em entidades HTML. Então, o código resultante será assim: -```html +```latte <img src=photo0145.webp alt=foo onload=alert('Hacked!')> ``` @@ -330,7 +330,7 @@ Agora veremos como o Latte lida com o mesmo template: O Latte vê o template da mesma forma que você. Ao contrário do Twig, ele entende HTML e sabe que a variável está a ser exibida como o valor de um atributo que não está entre aspas. Portanto, ele adiciona-as. Quando o atacante insere a mesma legenda, o código resultante será assim: -```html +```latte <img src="photo0145.webp" alt="foo onload=alert('Hacked!')"> ``` diff --git a/latte/ro/custom-tags.texy b/latte/ro/custom-tags.texy index bc12920a37..3c353caabb 100644 --- a/latte/ro/custom-tags.texy +++ b/latte/ro/custom-tags.texy @@ -923,7 +923,7 @@ Acum puteți utiliza `n:confirm` pe linkuri, butoane sau elemente de formular: HTML generat: -```html +```latte <a href="delete.php?id=123" onclick="return confirm("Sigur doriți să ștergeți elementul 123?")">Șterge</a> ``` diff --git a/latte/ro/safety-first.texy b/latte/ro/safety-first.texy index 8140ba61d3..b4948a948d 100644 --- a/latte/ro/safety-first.texy +++ b/latte/ro/safety-first.texy @@ -33,7 +33,7 @@ echo '<p>Rezultatele căutării pentru <em>' . $search . '</em></p>'; Un atacator poate introduce în câmpul de căutare și, implicit, în variabila `$search`, orice șir, deci și cod HTML precum `<script>alert("Hacked!")</script>`. Deoarece ieșirea nu este tratată în niciun fel, aceasta devine parte a paginii afișate: -```html +```latte <p>Rezultatele căutării pentru <em><script>alert("Hacked!")</script></em></p> ``` @@ -59,7 +59,7 @@ echo '<img src="' . $imageFile . '" alt="' . $imageAlt . '">'; Atacatorului îi este suficient să introducă ca descriere un șir inteligent construit `" onload="alert('Hacked!')` și dacă afișarea nu este tratată, codul rezultat va arăta astfel: -```html +```latte <img src="photo0145.webp" alt="" onload="alert('Hacked!')"> ``` @@ -91,7 +91,7 @@ Escapare contextuală sensibilă Ce se înțelege exact prin cuvântul context? Este un loc în document cu propriile reguli pentru tratarea datelor afișate. Depinde de tipul documentului (HTML, XML, CSS, JavaScript, plain text, ...) și poate diferi în părțile sale specifice. De exemplu, într-un document HTML există o serie întreagă de astfel de locuri (contexte) unde se aplică reguli foarte diferite. Poate veți fi surprinși câte sunt. Iată primele patru: -```html +```latte <p>#text</p> <img src="#atribut"> <textarea>#rawtext</textarea> @@ -108,7 +108,7 @@ Interesant este în interiorul comentariilor HTML. Aici, escaparea nu se face fo Contexturile se pot și stratifica, ceea ce se întâmplă când inserăm JavaScript sau CSS în HTML. Acest lucru se poate face în două moduri diferite, prin element și atribut: -```html +```latte <script>#js-element</script> <img onclick="#js-atribut"> @@ -132,7 +132,7 @@ Să avem șirul `Rock'n'Roll`. Dacă îl veți afișa în text HTML, în acest caz particular nu este nevoie de nicio înlocuire, deoarece șirul nu conține niciun caracter cu semnificație specială. Situația se schimbă dacă îl afișați în interiorul unui atribut HTML delimitat de apostrofuri simple. În acest caz, este necesar să escapați apostrofurile în entități HTML: -```html +```latte <div title='Rock'n'Roll'></div> ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Dacă inserăm acest cod într-un document HTML folosind `<script>`, nu mai este nevoie de nicio altă modificare, deoarece nu conține secvența interzisă `</script`: -```html +```latte <script> alert('Rock\'n\'Roll'); </script> ``` Dacă am dori însă să îl inserăm într-un atribut HTML, trebuie să mai escapăm ghilimelele în entități HTML: -```html +```latte <div onclick='alert('Rock\'n\'Roll')'></div> ``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll Și când afișăm acest șir într-un atribut, aplicăm și escaparea conform acestui context și înlocuim `&` cu `&`: -```html +```latte <a href="https://example.org/?a=Jazz&b=Rock%27n%27Roll"> ``` @@ -314,7 +314,7 @@ Observați că în jurul valorilor atributelor nu există ghilimele. Coderul le- Atacatorul introduce ca descriere a imaginii un șir inteligent construit `foo onload=alert('Hacked!')`. Știm deja că Twig nu poate recunoaște dacă variabila se afișează în fluxul textului HTML, în interiorul unui atribut, comentariu HTML etc., pe scurt, nu distinge contextele. Și doar convertesc mecanic caracterele `< > & ' "` în entități HTML. Deci, codul rezultat va arăta astfel: -```html +```latte <img src=photo0145.webp alt=foo onload=alert('Hacked!')> ``` @@ -330,7 +330,7 @@ Acum să vedem cum se descurcă Latte cu același șablon: Latte vede șablonul la fel ca dvs. Spre deosebire de Twig, înțelege HTML și știe că variabila se afișează ca valoare a unui atribut care nu este între ghilimele. De aceea, le completează. Când atacatorul introduce aceeași descriere, codul rezultat va arăta astfel: -```html +```latte <img src="photo0145.webp" alt="foo onload=alert('Hacked!')"> ``` diff --git a/latte/ru/custom-tags.texy b/latte/ru/custom-tags.texy index dc35fdad01..3c0cd691eb 100644 --- a/latte/ru/custom-tags.texy +++ b/latte/ru/custom-tags.texy @@ -923,7 +923,7 @@ class MyLatteExtension extends Extension Сгенерированный HTML: -```html +```latte <a href="delete.php?id=123" onclick="return confirm("Действительно хотите удалить элемент 123?")">Удалить</a> ``` diff --git a/latte/ru/safety-first.texy b/latte/ru/safety-first.texy index 96b91313cc..ffd79d93c4 100644 --- a/latte/ru/safety-first.texy +++ b/latte/ru/safety-first.texy @@ -33,7 +33,7 @@ echo '<p>Результаты поиска для <em>' . $search . '</em></p>'; Злоумышленник может в поле поиска и, соответственно, в переменную `$search` записать любую строку, в том числе и HTML-код, например `<script>alert("Hacked!")</script>`. Поскольку вывод никак не обрабатывается, он станет частью отображаемой страницы: -```html +```latte <p>Результаты поиска для <em><script>alert("Hacked!")</script></em></p> ``` @@ -59,7 +59,7 @@ echo '<img src="' . $imageFile . '" alt="' . $imageAlt . '">'; Злоумышленнику достаточно в качестве описания вставить хитро составленную строку `" onload="alert('Hacked!')`, и если вывод не будет обработан, результирующий код будет выглядеть так: -```html +```latte <img src="photo0145.webp" alt="" onload="alert('Hacked!')"> ``` @@ -91,7 +91,7 @@ echo '<img src="' . $imageFile . '" alt="' . $imageAlt . '">'; Что именно подразумевается под словом контекст? Это место в документе со своими правилами обработки выводимых данных. Зависит от типа документа (HTML, XML, CSS, JavaScript, plain text, ...) и может отличаться в его конкретных частях. Например, в HTML-документе таких мест (контекстов), где действуют очень разные правила, целое множество. Возможно, вы удивитесь, сколько их. Вот первая четверка: -```html +```latte <p>#текст</p> <img src="#атрибут"> <textarea>#rawtext</textarea> @@ -108,7 +108,7 @@ echo '<img src="' . $imageFile . '" alt="' . $imageAlt . '">'; Контексты также могут вкладываться, что происходит, когда мы вставляем JavaScript или CSS в HTML. Это можно сделать двумя разными способами, элементом и атрибутом: -```html +```latte <script>#js-элемент</script> <img onclick="#js-атрибут"> @@ -132,7 +132,7 @@ echo '<img src="' . $imageFile . '" alt="' . $imageAlt . '">'; Если вы будете выводить ее в HTML-тексте, то в данном случае не нужно делать никаких замен, потому что строка не содержит ни одного символа со специальным значением. Другая ситуация возникнет, если вы выведете ее внутри HTML-атрибута, заключенного в одинарные кавычки. В таком случае необходимо экранировать кавычки в HTML-сущности: -```html +```latte <div title='Rock'n'Roll'></div> ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Если этот код вставить в HTML-документ с помощью `<script>`, ничего больше изменять не нужно, потому что в нем не встречается запрещенная последовательность `</script`: -```html +```latte <script> alert('Rock\'n\'Roll'); </script> ``` Однако, если бы мы хотели вставить его в HTML-атрибут, нужно еще экранировать кавычки в HTML-сущности: -```html +```latte <div onclick='alert('Rock\'n\'Roll')'></div> ``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll А когда мы выводим эту строку в атрибуте, еще применяем экранирование в соответствии с этим контекстом и заменяем `&` на `&`: -```html +```latte <a href="https://example.org/?a=Jazz&b=Rock%27n%27Roll"> ``` @@ -314,7 +314,7 @@ Latte видит шаблон так же, как и вы. Он понимает Злоумышленник в качестве описания изображения вставляет хитро составленную строку `foo onload=alert('Hacked!')`. Мы уже знаем, что Twig не может определить, выводится ли переменная в потоке HTML-текста, внутри атрибута, HTML-комментария и т. д., короче говоря, не различает контексты. И просто механически преобразует символы `< > & ' "` в HTML-сущности. Так что результирующий код будет выглядеть так: -```html +```latte <img src=photo0145.webp alt=foo onload=alert('Hacked!')> ``` @@ -330,7 +330,7 @@ Latte видит шаблон так же, как и вы. Он понимает Latte видит шаблон так же, как и вы. В отличие от Twig, он понимает HTML и знает, что переменная выводится как значение атрибута, который не заключен в кавычки. Поэтому он их добавит. Когда злоумышленник вставит то же описание, результирующий код будет выглядеть так: -```html +```latte <img src="photo0145.webp" alt="foo onload=alert('Hacked!')"> ``` diff --git a/latte/sl/custom-tags.texy b/latte/sl/custom-tags.texy index 1066b5eb86..1bb1570146 100644 --- a/latte/sl/custom-tags.texy +++ b/latte/sl/custom-tags.texy @@ -923,7 +923,7 @@ Zdaj lahko uporabite `n:confirm` na povezavah, gumbih ali elementih obrazca: Generirana HTML koda: -```html +```latte <a href="delete.php?id=123" onclick="return confirm("Ali res želite izbrisati element 123?")">Izbriši</a> ``` diff --git a/latte/sl/safety-first.texy b/latte/sl/safety-first.texy index 509802d6c8..29adc447e2 100644 --- a/latte/sl/safety-first.texy +++ b/latte/sl/safety-first.texy @@ -33,7 +33,7 @@ echo '<p>Rezultati iskanja za <em>' . $search . '</em></p>'; Napadalec lahko v iskalno polje in posledično v spremenljivko `$search` zapiše poljuben niz, torej tudi HTML kodo kot `<script>alert("Hacked!")</script>`. Ker izpis ni nikakor obdelan, postane del prikazane strani: -```html +```latte <p>Rezultati iskanja za <em><script>alert("Hacked!")</script></em></p> ``` @@ -59,7 +59,7 @@ echo '<img src="' . $imageFile . '" alt="' . $imageAlt . '">'; Napadalcu zadostuje, da kot opis vstavi spretno sestavljen niz `" onload="alert('Hacked!')` in če izpis ne bo obdelan, bo rezultatna koda izgledala takole: -```html +```latte <img src="photo0145.webp" alt="" onload="alert('Hacked!')"> ``` @@ -91,7 +91,7 @@ Kontekstno občutljivo ubežanje Kaj točno se misli z besedo kontekst? Gre za mesto v dokumentu z lastnimi pravili za obdelavo izpisanih podatkov. Odvisno je od vrste dokumenta (HTML, XML, CSS, JavaScript, navadno besedilo, ...) in se lahko razlikuje v njegovih konkretnih delih. Na primer, v dokumentu HTML je takih mest (kontekstov), kjer veljajo zelo različna pravila, cela vrsta. Morda boste presenečeni, koliko jih je. Tukaj imamo prvo četverico: -```html +```latte <p>#text</p> <img src="#atribut"> <textarea>#rawtext</textarea> @@ -108,7 +108,7 @@ Zanimivo je znotraj komentarjev HTML. Tukaj se namreč za ubežanje ne uporablja Konteksti se lahko tudi plastijo, do česar pride, ko vstavimo JavaScript ali CSS v HTML. To je mogoče storiti na dva različna načina, z elementom in atributom: -```html +```latte <script>#js-element</script> <img onclick="#js-atribut"> @@ -132,7 +132,7 @@ Imejmo niz `Rock'n'Roll`. Če ga boste izpisovali v besedilu HTML, ravno v tem primeru ni treba delati nobenih zamenjav, ker niz ne vsebuje nobenega znaka s posebnim pomenom. Druga situacija nastane, če ga izpišete znotraj atributa HTML, omejenega z enojnimi narekovaji. V takem primeru je treba narekovaje ubežati v HTML entitete: -```html +```latte <div title='Rock'n'Roll'></div> ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Če to kodo vstavimo v dokument HTML s pomočjo `<script>`, ni treba ničesar dodatno urejati, ker se v njej ne pojavlja prepovedano zaporedje `</script`: -```html +```latte <script> alert('Rock\'n\'Roll'); </script> ``` Če pa bi jo želeli vstaviti v atribut HTML, moramo še ubežati narekovaje v HTML entitete: -```html +```latte <div onclick='alert('Rock\'n\'Roll')'></div> ``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll In ko ta niz izpišemo v atributu, še uporabimo ubežanje po tem kontekstu in zamenjamo `&` za `&`: -```html +```latte <a href="https://example.org/?a=Jazz&b=Rock%27n%27Roll"> ``` @@ -314,7 +314,7 @@ Opazite, da okoli vrednosti atributov ni narekovajev. Koder jih je lahko pozabil Napadalec kot opis slike vstavi spretno sestavljen niz `foo onload=alert('Hacked!')`. Že vemo, da Twig ne more prepoznati, ali se spremenljivka izpisuje v toku besedila HTML, znotraj atributa, komentarja HTML, itd., skratka ne razlikuje kontekstov. In samo mehansko pretvarja znake `< > & ' "` v HTML entitete. Torej bo rezultatna koda izgledala takole: -```html +```latte <img src=photo0145.webp alt=foo onload=alert('Hacked!')> ``` @@ -330,7 +330,7 @@ Zdaj si poglejmo, kako se z enako predlogo spopade Latte: Latte vidi predlogo enako kot vi. Za razliko od Twiga razume HTML in ve, da se spremenljivka izpisuje kot vrednost atributa, ki ni v narekovajih. Zato jih dopolni. Ko napadalec vstavi enak opis, bo rezultatna koda izgledala takole: -```html +```latte <img src="photo0145.webp" alt="foo onload=alert('Hacked!')"> ``` diff --git a/latte/tr/custom-tags.texy b/latte/tr/custom-tags.texy index 402e361e28..8f582915f0 100644 --- a/latte/tr/custom-tags.texy +++ b/latte/tr/custom-tags.texy @@ -923,7 +923,7 @@ class MyLatteExtension extends Extension Oluşturulan HTML: -```html +```latte <a href="delete.php?id=123" onclick="return confirm("123 öğesini gerçekten silmek istiyor musunuz?")">Sil</a> ``` diff --git a/latte/tr/safety-first.texy b/latte/tr/safety-first.texy index a4943315fd..9e550024e2 100644 --- a/latte/tr/safety-first.texy +++ b/latte/tr/safety-first.texy @@ -33,7 +33,7 @@ echo '<p><em>' . $search . '</em> için arama sonuçları</p>'; Saldırgan, arama kutusuna ve dolayısıyla `$search` değişkenine `<script>alert("Hacklendiniz!")</script>` gibi HTML kodu da dahil olmak üzere herhangi bir karakter dizisi yazabilir. Çıktı hiçbir şekilde işlenmediği için, görüntülenen sayfanın bir parçası haline gelir: -```html +```latte <p><em><script>alert("Hacklendiniz!")</script></em> için arama sonuçları</p> ``` @@ -59,7 +59,7 @@ echo '<img src="' . $imageFile . '" alt="' . $imageAlt . '">'; Saldırganın açıklama olarak akıllıca oluşturulmuş bir karakter dizisi `" onload="alert('Hacklendiniz!')` eklemesi yeterlidir ve yazdırma işlenmezse, sonuç kodu şöyle görünecektir: -```html +```latte <img src="photo0145.webp" alt="" onload="alert('Hacklendiniz!')"> ``` @@ -91,7 +91,7 @@ Bağlama Duyarlı Kaçış Bağlam kelimesiyle tam olarak ne kastediliyor? Belgenin içinde, yazdırılan verilerin işlenmesi için kendi kuralları olan bir yerdir. Belgenin türüne (HTML, XML, CSS, JavaScript, düz metin, ...) bağlıdır ve belirli bölümlerinde farklılık gösterebilir. Örneğin, bir HTML belgesinde, çok farklı kuralların geçerli olduğu birçok yer (bağlam) vardır. Kaç tane olduğuna şaşırabilirsiniz. İşte ilk dördü: -```html +```latte <p>#metin</p> <img src="#nitelik"> <textarea>#hammetin</textarea> @@ -108,7 +108,7 @@ HTML yorumlarının içi ilginçtir. Burada kaçış için HTML varlıkları kul Bağlamlar ayrıca katmanlanabilir, bu da HTML'e JavaScript veya CSS eklediğimizde olur. Bu iki farklı şekilde yapılabilir, öğe ve nitelik ile: -```html +```latte <script>#js-öğe</script> <img onclick="#js-nitelik"> @@ -132,7 +132,7 @@ Bir Örnek İster misiniz? Bunu HTML metninde yazdırırsanız, bu özel durumda herhangi bir değiştirme yapmaya gerek yoktur, çünkü dize özel anlamı olan hiçbir karakter içermez. Tek tırnak içine alınmış bir HTML niteliği içinde yazdırırsanız durum farklıdır. Bu durumda, tırnak işaretlerini HTML varlıklarına kaçış işlemine tabi tutmak gerekir: -```html +```latte <div title='Rock'n'Roll'></div> ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Bu kodu `<script>` kullanarak HTML belgesine eklersek, başka bir şey ayarlamaya gerek yoktur, çünkü içinde yasaklı `</script` dizisi bulunmaz: -```html +```latte <script> alert('Rock\'n\'Roll'); </script> ``` Ancak bunu bir HTML niteliğine eklemek istersek, tırnak işaretlerini de HTML varlıklarına kaçış işlemine tabi tutmamız gerekir: -```html +```latte <div onclick='alert('Rock\'n\'Roll')'></div> ``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll Ve bu dizeyi bir nitelikte yazdırdığımızda, bu bağlama göre kaçış işlemini de uygular ve `&` yerine `&` yazarız: -```html +```latte <a href="https://example.org/?a=Jazz&b=Rock%27n%27Roll"> ``` @@ -314,7 +314,7 @@ Nitelik değerlerinin etrafında tırnak işareti olmadığına dikkat edin. Kod Saldırgan, resim açıklaması olarak akıllıca oluşturulmuş bir karakter dizisi `foo onload=alert('Hacklendiniz!')` ekler. Twig'in değişkenin HTML metin akışında mı, bir nitelik içinde mi, HTML yorumunda mı vb. yazdırıldığını anlayamayacağını, kısacası bağlamları ayırt etmediğini zaten biliyoruz. Ve yalnızca `< > & ' "` karakterlerini mekanik olarak HTML varlıklarına dönüştürür. Yani sonuç kodu şöyle görünecektir: -```html +```latte <img src=photo0145.webp alt=foo onload=alert('Hacklendiniz!')> ``` @@ -330,7 +330,7 @@ Sahte `onload` niteliği sayfanın bir parçası haline geldi ve tarayıcı resm Latte şablonu sizin gördüğünüz gibi görür. Twig'in aksine, HTML'i anlar ve değişkenin tırnak içinde olmayan bir niteliğin değeri olarak yazdırıldığını bilir. Bu yüzden onları ekler. Saldırgan aynı açıklamayı eklediğinde, sonuç kodu şöyle görünecektir: -```html +```latte <img src="photo0145.webp" alt="foo onload=alert('Hacklendiniz!')"> ``` diff --git a/latte/uk/custom-tags.texy b/latte/uk/custom-tags.texy index 96af747f17..c2e63f4ab1 100644 --- a/latte/uk/custom-tags.texy +++ b/latte/uk/custom-tags.texy @@ -923,7 +923,7 @@ class MyLatteExtension extends Extension Згенерований HTML: -```html +```latte <a href="delete.php?id=123" onclick="return confirm("Справді хочете видалити елемент 123?")">Видалити</a> ``` diff --git a/latte/uk/safety-first.texy b/latte/uk/safety-first.texy index 60ff086270..b5fd634f04 100644 --- a/latte/uk/safety-first.texy +++ b/latte/uk/safety-first.texy @@ -33,7 +33,7 @@ echo '<p>Результати пошуку для <em>' . $search . '</em></p>'; Зловмисник може в поле пошуку і, відповідно, в змінну `$search` записати будь-який рядок, тобто і HTML-код, як `<script>alert("Hacked!")</script>`. Оскільки вивід ніяк не обробляється, він стане частиною відображеної сторінки: -```html +```latte <p>Результати пошуку для <em><script>alert("Hacked!")</script></em></p> ``` @@ -59,7 +59,7 @@ echo '<img src="' . $imageFile . '" alt="' . $imageAlt . '">'; Зловмиснику достатньо як опис вставити хитро складений рядок `" onload="alert('Hacked!')`, і якщо виведення не буде оброблено, кінцевий код виглядатиме так: -```html +```latte <img src="photo0145.webp" alt="" onload="alert('Hacked!')"> ``` @@ -91,7 +91,7 @@ echo '<img src="' . $imageFile . '" alt="' . $imageAlt . '">'; Що саме мається на увазі під словом контекст? Це місце в документі з власними правилами обробки виведених даних. Воно залежить від типу документа (HTML, XML, CSS, JavaScript, plain text, ...) і може відрізнятися в його конкретних частинах. Наприклад, в HTML-документі є ціла низка таких місць (контекстів), де діють дуже різні правила. Можливо, ви будете здивовані, скільки їх є. Ось перша четвірка: -```html +```latte <p>#text</p> <img src="#атрибут"> <textarea>#rawtext</textarea> @@ -108,7 +108,7 @@ echo '<img src="' . $imageFile . '" alt="' . $imageAlt . '">'; Контексти також можуть нашаровуватися, що відбувається, коли ми вставляємо JavaScript або CSS в HTML. Це можна зробити двома різними способами: елементом та атрибутом: -```html +```latte <script>#js-елемент</script> <img onclick="#js-атрибут"> @@ -132,7 +132,7 @@ echo '<img src="' . $imageFile . '" alt="' . $imageAlt . '">'; Якщо ви будете виводити його в HTML-тексті, саме в цьому випадку не потрібно робити жодних замін, оскільки рядок не містить жодного символу зі спеціальним значенням. Інша ситуація виникне, якщо ви виведете його всередині HTML-атрибута, взятого в одинарні лапки. У такому випадку потрібно екранувати лапки на HTML-сутності: -```html +```latte <div title='Rock'n'Roll'></div> ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Якщо цей код вставити в HTML-документ за допомогою `<script>`, не потрібно нічого додатково змінювати, оскільки в ньому не зустрічається заборонена послідовність `</script`: -```html +```latte <script> alert('Rock\'n\'Roll'); </script> ``` Однак, якби ми хотіли вставити його в HTML-атрибут, ми повинні ще екранувати лапки на HTML-сутності: -```html +```latte <div onclick='alert('Rock\'n\'Roll')'></div> ``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll І коли ми виводимо цей рядок в атрибуті, ще застосовуємо екранування відповідно до цього контексту і замінюємо `&` на `&`: -```html +```latte <a href="https://example.org/?a=Jazz&b=Rock%27n%27Roll"> ``` @@ -314,7 +314,7 @@ Latte бачить шаблон так само, як і ви. Розуміє HT Зловмисник як опис зображення вставляє хитро складений рядок `foo onload=alert('Hacked!')`. Ми вже знаємо, що Twig не може розпізнати, чи виводиться змінна в потоці HTML-тексту, всередині атрибута, HTML-коментаря тощо, коротше кажучи, не розрізняє контексти. І лише механічно перетворює символи `< > & ' "` на HTML-сутності. Отже, кінцевий код виглядатиме так: -```html +```latte <img src=photo0145.webp alt=foo onload=alert('Hacked!')> ``` @@ -330,7 +330,7 @@ Latte бачить шаблон так само, як і ви. Розуміє HT Latte бачить шаблон так само, як і ви. На відміну від Twig, він розуміє HTML і знає, що змінна виводиться як значення атрибута, який не взятий у лапки. Тому він їх доповнить. Коли зловмисник вставить той самий опис, кінцевий код виглядатиме так: -```html +```latte <img src="photo0145.webp" alt="foo onload=alert('Hacked!')"> ``` diff --git a/quickstart/cs/@home.texy b/quickstart/cs/@home.texy index 8ed549342e..c704dc7885 100644 --- a/quickstart/cs/@home.texy +++ b/quickstart/cs/@home.texy @@ -89,9 +89,8 @@ Tracy nám ohromně pomůže, až budeme hledat chyby v aplikaci. Také si všim V produkčním módu je Tracy samozřejmě vypnuta a nezobrazuje žádné citlivé informace. Všechny chyby jsou v tomto případě uloženy ve složce `log/`. Pojďme si to vyzkoušet. V souboru `app/Bootstrap.php` odkomentujeme následující řádek a změníme parametr volání na `false`, aby kód vypadal takto: ```php .{file:app/Bootstrap.php} -... +// ... $this->configurator->setDebugMode(false); -... ``` Po obnovení stránky již Tracy neuvidíme. Místo ní se zobrazí uživatelsky přívětivá zpráva: diff --git a/quickstart/cs/comments.texy b/quickstart/cs/comments.texy index a33c122d0c..949ec97bc4 100644 --- a/quickstart/cs/comments.texy +++ b/quickstart/cs/comments.texy @@ -136,7 +136,7 @@ Jak si jistě pamatujete, do šablony jsme předali proměnnou `$post` pomocí m ```php .{file:app/Presentation/Post/PostPresenter.php} public function renderShow(int $id): void { - ... + // ... $this->template->post = $post; $this->template->comments = $post->related('comments')->order('created_at'); } diff --git a/quickstart/en/@home.texy b/quickstart/en/@home.texy index 8fd028c07f..9abc77dc8b 100644 --- a/quickstart/en/@home.texy +++ b/quickstart/en/@home.texy @@ -89,9 +89,8 @@ Tracy will significantly help you when debugging errors. Also, notice the floati In production mode, Tracy is, of course, disabled and does not display any sensitive information. All errors are saved in the `log/` directory instead. Let's try it out. In the `app/Bootstrap.php` file, find the following piece of code, uncomment the line, and change the method call parameter to `false`, so it looks like this: ```php .{file:app/Bootstrap.php} -... +// ... $this->configurator->setDebugMode(false); -... ``` After refreshing the web page, you will no longer see the red screen. Instead, a user-friendly message will be displayed: diff --git a/quickstart/en/comments.texy b/quickstart/en/comments.texy index 9c30a5aacb..fa9ac7ff50 100644 --- a/quickstart/en/comments.texy +++ b/quickstart/en/comments.texy @@ -136,7 +136,7 @@ As you might recall, we passed the `$post` variable to the template in `PostPres ```php .{file:app/Presentation/Post/PostPresenter.php} public function renderShow(int $id): void { - ... + // ... $this->template->post = $post; $this->template->comments = $post->related('comments')->order('created_at'); } diff --git a/security/cs/authentication.texy b/security/cs/authentication.texy index bec4b9f528..689b757bd5 100644 --- a/security/cs/authentication.texy +++ b/security/cs/authentication.texy @@ -212,7 +212,7 @@ final class Authenticator implements { $row = $this->db->fetch('SELECT * FROM user WHERE username = ?', $username); // ověříme heslo - ... + // ... // vrátíme identitu se všemi údaji z databáze return new SimpleIdentity($row->id, null, (array) $row); } diff --git a/security/en/authentication.texy b/security/en/authentication.texy index d15187f3d2..4fbd946ba6 100644 --- a/security/en/authentication.texy +++ b/security/en/authentication.texy @@ -212,7 +212,7 @@ final class Authenticator implements { $row = $this->db->fetch('SELECT * FROM user WHERE username = ?', $username); // verify password - ... + // ... // return the identity with all data from the database return new SimpleIdentity($row->id, null, (array) $row); } diff --git a/tracy/cs/guide.texy b/tracy/cs/guide.texy index 23343cc56a..8ce469764f 100644 --- a/tracy/cs/guide.texy +++ b/tracy/cs/guide.texy @@ -161,7 +161,7 @@ try { } catch (Exception $e) { Debugger::log($e); // logovat lze i výjimku // nebo - Debugger::log($e, Debugger::ERROR); odešle i e-mailovou notifikaci + Debugger::log($e, Debugger::ERROR); // odešle i e-mailovou notifikaci } ``` diff --git a/tracy/cs/stopwatch.texy b/tracy/cs/stopwatch.texy index 8120595cfa..95b8cf24b4 100644 --- a/tracy/cs/stopwatch.texy +++ b/tracy/cs/stopwatch.texy @@ -29,7 +29,7 @@ $pageElapsed = Debugger::timer('page-generating'); ```php Debugger::timer(); // zapne stopky -... // časově náročná operace +// ... časově náročná operace echo Debugger::timer(); // vypíše uplynulý čas v sekundách ``` diff --git a/tracy/en/stopwatch.texy b/tracy/en/stopwatch.texy index 6546ac6e71..7608a61b03 100644 --- a/tracy/en/stopwatch.texy +++ b/tracy/en/stopwatch.texy @@ -29,7 +29,7 @@ $pageElapsed = Debugger::timer('page-generating'); ```php Debugger::timer(); // runs the timer -... // some time-consuming operation +// ... some time-consuming operation echo Debugger::timer(); // elapsed time in seconds ``` diff --git a/utils/cs/filesystem.texy b/utils/cs/filesystem.texy index 1f68e7313b..0b3e31e9ac 100644 --- a/utils/cs/filesystem.texy +++ b/utils/cs/filesystem.texy @@ -209,6 +209,6 @@ class AnyClassUsingFileSystem return $this->fileSystem->read(/* ... */); } - ... + // ... } ``` diff --git a/utils/en/filesystem.texy b/utils/en/filesystem.texy index 7c66d4c3e3..f8e43ddf3e 100644 --- a/utils/en/filesystem.texy +++ b/utils/en/filesystem.texy @@ -209,6 +209,6 @@ class AnyClassUsingFileSystem return $this->fileSystem->read(/* ... */); } - ... + // ... } ``` From 45a37b691006dafd9c2c83d2aa91c48f8eb051f0 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Mon, 13 Apr 2026 16:44:40 +0200 Subject: [PATCH 20/50] latte: changed user template --- latte/cs/custom-filters.texy | 2 +- latte/cs/custom-functions.texy | 2 +- latte/cs/custom-tags.texy | 20 ++++++++++---------- latte/en/custom-filters.texy | 2 +- latte/en/custom-functions.texy | 2 +- latte/en/custom-tags.texy | 20 ++++++++++---------- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/latte/cs/custom-filters.texy b/latte/cs/custom-filters.texy index 75aff4b35e..299d9c1aae 100644 --- a/latte/cs/custom-filters.texy +++ b/latte/cs/custom-filters.texy @@ -84,7 +84,7 @@ Registrace pomocí rozšíření Pro lepší organizaci, zejména při vytváření znovupoužitelných sad filtrů nebo jejich sdílení jako balíčky, je doporučeným způsobem registrovat je v rámci [rozšíření Latte |extending-latte#Latte Extension]: ```php -namespace App\Latte; +namespace App\Templating; use Latte\Extension; diff --git a/latte/cs/custom-functions.texy b/latte/cs/custom-functions.texy index bb3677923d..1bd18de0e3 100644 --- a/latte/cs/custom-functions.texy +++ b/latte/cs/custom-functions.texy @@ -67,7 +67,7 @@ Registrace pomocí rozšíření Pro lepší organizaci a znovupoužitelnost registrujte funkce v rámci [Latte rozšíření |extending-latte#Latte Extension]. Tento přístup je doporučen pro složitější aplikace nebo sdílené knihovny. ```php -namespace App\Latte; +namespace App\Templating; use Latte\Extension; use Nette\Security\Authorizator; diff --git a/latte/cs/custom-tags.texy b/latte/cs/custom-tags.texy index 415ed73fdd..d5ad47f22e 100644 --- a/latte/cs/custom-tags.texy +++ b/latte/cs/custom-tags.texy @@ -117,7 +117,7 @@ Vytvořte soubor (např. `DatetimeNode.php`) a definujte třídu: ```php <?php -namespace App\Latte; +namespace App\Templating; use Latte\Compiler\Nodes\StatementNode; use Latte\Compiler\PrintContext; @@ -173,7 +173,7 @@ Nakonec informujme Latte o novém tagu. Vytvořte [třídu rozšíření |extend ```php <?php -namespace App\Latte; +namespace App\Templating; use Latte\Extension; @@ -197,7 +197,7 @@ Poté zaregistrujte toto rozšíření v Latte Engine: ```php $latte = new Latte\Engine; -$latte->addExtension(new App\Latte\MyLatteExtension); +$latte->addExtension(new App\Templating\MyLatteExtension); ``` Vytvořte šablonu: @@ -255,7 +255,7 @@ S tímto pochopením upravme metodu `create()` v `DatetimeNode` tak, aby parsova ```php <?php -namespace App\Latte; +namespace App\Templating; use Latte\Compiler\Nodes\Php\ExpressionNode; use Latte\Compiler\Nodes\Php\Scalar\StringNode; @@ -383,7 +383,7 @@ Vytvořme třídu `DebugNode` a její metodu `create` využívající `yield`. ```php <?php -namespace App\Latte; +namespace App\Templating; use Latte\Compiler\Nodes\AreaNode; use Latte\Compiler\Nodes\StatementNode; @@ -555,7 +555,7 @@ Upravme `DebugNode::create()` tak, aby očekával `{else}`: ```php <?php -namespace App\Latte; +namespace App\Templating; use Latte\Compiler\Nodes\AreaNode; use Latte\Compiler\Nodes\NopNode; @@ -715,7 +715,7 @@ Pojďme vytvořit třídu uzlu. ```php <?php -namespace App\Latte; +namespace App\Templating; use Latte\CompileException; use Latte\Compiler\Nodes\AreaNode; @@ -797,7 +797,7 @@ Registrace a použití Zaregistrujte tag ve vašem rozšíření: ```php -use App\Latte\RepeatNode; +use App\Templating\RepeatNode; class MyLatteExtension extends Extension { @@ -850,7 +850,7 @@ Potřebujeme třídu Node a parsovací funkci. ```php <?php -namespace App\Latte; +namespace App\Templating; use Latte\Compiler\Nodes\StatementNode; use Latte\Compiler\PrintContext; @@ -1023,7 +1023,7 @@ Zatímco `parseExpression()`, `parseArguments()`, atd., pokrývají mnoho příp ```php <?php -namespace App\Latte; +namespace App\Templating; class YoutubeNode extends StatementNode { diff --git a/latte/en/custom-filters.texy b/latte/en/custom-filters.texy index 186caf6fb4..db6d77bf8d 100644 --- a/latte/en/custom-filters.texy +++ b/latte/en/custom-filters.texy @@ -84,7 +84,7 @@ Registration via Extension For better organization, especially when creating reusable sets of filters or sharing them as packages, the recommended way is to register them within a [Latte Extension |extending-latte#Latte Extension]: ```php -namespace App\Latte; +namespace App\Templating; use Latte\Extension; diff --git a/latte/en/custom-functions.texy b/latte/en/custom-functions.texy index f4616ceea1..eeef7d8008 100644 --- a/latte/en/custom-functions.texy +++ b/latte/en/custom-functions.texy @@ -67,7 +67,7 @@ Registration via Extension For better organization and reusability, register functions within a [Latte Extension |extending-latte#Latte Extension]. This is the recommended approach for non-trivial applications or shared libraries. ```php -namespace App\Latte; +namespace App\Templating; use Latte\Extension; use Nette\Security\Authorizator; diff --git a/latte/en/custom-tags.texy b/latte/en/custom-tags.texy index 6fcc3cd9aa..8d8a7cf7c6 100644 --- a/latte/en/custom-tags.texy +++ b/latte/en/custom-tags.texy @@ -117,7 +117,7 @@ Create a file (e.g., `DatetimeNode.php`) and define the class: ```php <?php -namespace App\Latte; +namespace App\Templating; use Latte\Compiler\Nodes\StatementNode; use Latte\Compiler\PrintContext; @@ -173,7 +173,7 @@ Finally, tell Latte about the new tag. Create an [Extension class |extending-lat ```php <?php -namespace App\Latte; +namespace App\Templating; use Latte\Extension; @@ -197,7 +197,7 @@ Then, register this extension with the Latte Engine: ```php $latte = new Latte\Engine; -$latte->addExtension(new App\Latte\MyLatteExtension); +$latte->addExtension(new App\Templating\MyLatteExtension); ``` Create template: @@ -255,7 +255,7 @@ With that understanding, let's modify the `create()` method in `DatetimeNode` to ```php <?php -namespace App\Latte; +namespace App\Templating; use Latte\Compiler\Nodes\Php\ExpressionNode; use Latte\Compiler\Nodes\Php\Scalar\StringNode; @@ -383,7 +383,7 @@ Let's create the `DebugNode` class and its `create` method using `yield`. ```php <?php -namespace App\Latte; +namespace App\Templating; use Latte\Compiler\Nodes\AreaNode; use Latte\Compiler\Nodes\StatementNode; @@ -555,7 +555,7 @@ Let's modify `DebugNode::create()` to expect `{else}`: ```php <?php -namespace App\Latte; +namespace App\Templating; use Latte\Compiler\Nodes\AreaNode; use Latte\Compiler\Nodes\NopNode; @@ -715,7 +715,7 @@ Let's create the node class. ```php <?php -namespace App\Latte; +namespace App\Templating; use Latte\CompileException; use Latte\Compiler\Nodes\AreaNode; @@ -797,7 +797,7 @@ Registration and Usage Register the tag in your extension: ```php -use App\Latte\RepeatNode; +use App\Templating\RepeatNode; class MyLatteExtension extends Extension { @@ -850,7 +850,7 @@ We need a Node class and a parsing function. ```php <?php -namespace App\Latte; +namespace App\Templating; use Latte\Compiler\Nodes\StatementNode; use Latte\Compiler\PrintContext; @@ -1023,7 +1023,7 @@ While `parseExpression()`, `parseArguments()`, etc., cover many cases, sometimes ```php <?php -namespace App\Latte; +namespace App\Templating; class YoutubeNode extends StatementNode { From df67d9387b1260177624eee0bfe597f00059dbf1 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Mon, 23 Feb 2026 02:46:32 +0100 Subject: [PATCH 21/50] php-generator: v4.2.2 --- php-generator/cs/@home.texy | 16 ++++++++++++---- php-generator/en/@home.texy | 16 ++++++++++++---- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/php-generator/cs/@home.texy b/php-generator/cs/@home.texy index 8100978308..77e0c5083b 100644 --- a/php-generator/cs/@home.texy +++ b/php-generator/cs/@home.texy @@ -512,6 +512,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer public bool $singleParameterOnOneLine = false; // omits namespaces that do not contain any class or function public bool $omitEmptyNamespaces = true; + // umístí declare(strict_types) na stejný řádek jako <?php + public bool $declareOnOpenTag = false; // oddělovač mezi pravou závorkou a návratovým typem funkcí a metod public string $returnTypeColon = ': '; } @@ -727,7 +729,7 @@ $class = $namespace->addClass('Task'); $interface = $namespace->addInterface('Countable'); $trait = $namespace->addTrait('NameAware'); -// nebo vložíme existující třídu do namespace +// nebo vložíme existující třídu nebo funkci do namespace $class = new Nette\PhpGenerator\ClassType('Task'); $namespace->add($class); ``` @@ -840,14 +842,12 @@ echo $file; Výsledek: ```php -<?php +<?php declare(strict_types=1); /** * This file is auto-generated. */ -declare(strict_types=1); - namespace Foo; class A @@ -859,6 +859,14 @@ function foo() } ``` +Do souboru lze vkládat i existující objekty tříd, funkcí a jmenných prostorů pomocí metody `add()`: + +```php +$file = new Nette\PhpGenerator\PhpFile; +$class = new Nette\PhpGenerator\ClassType('Demo'); +$file->add($class); +``` + **Upozornění:** Do souborů není možné přidávat žádný další kód mimo funkce a třídy. diff --git a/php-generator/en/@home.texy b/php-generator/en/@home.texy index 436f8d3fa7..219c18eafe 100644 --- a/php-generator/en/@home.texy +++ b/php-generator/en/@home.texy @@ -512,6 +512,8 @@ class MyPrinter extends Nette\PhpGenerator\Printer public bool $singleParameterOnOneLine = false; // omits namespaces that do not contain any class or function public bool $omitEmptyNamespaces = true; + // places declare(strict_types) on the same line as <?php + public bool $declareOnOpenTag = false; // separator between the right parenthesis and the return type of functions and methods public string $returnTypeColon = ': '; } @@ -727,7 +729,7 @@ $class = $namespace->addClass('Task'); $interface = $namespace->addInterface('Countable'); $trait = $namespace->addTrait('NameAware'); -// or insert an existing class into the namespace +// or insert an existing class or function into the namespace $class = new Nette\PhpGenerator\ClassType('Task'); $namespace->add($class); ``` @@ -840,14 +842,12 @@ echo $file; Result: ```php -<?php +<?php declare(strict_types=1); /** * This file is auto-generated. */ -declare(strict_types=1); - namespace Foo; class A @@ -859,6 +859,14 @@ function foo() } ``` +You can also insert existing class, function, and namespace objects into the file using the `add()` method: + +```php +$file = new Nette\PhpGenerator\PhpFile; +$class = new Nette\PhpGenerator\ClassType('Demo'); +$file->add($class); +``` + **Please note:** No additional code (like `echo 'hello'`) can be added to the files outside of functions, classes, or namespaces. From 69cfed5f29efedeffc8277791e1e5412cf497203 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Thu, 5 Mar 2026 15:50:14 +0100 Subject: [PATCH 22/50] di: documented @Type as service key for modifications --- dependency-injection/cs/services.texy | 10 ++++++++-- dependency-injection/en/services.texy | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/dependency-injection/cs/services.texy b/dependency-injection/cs/services.texy index 8a86b230e9..6f4ec1bacb 100644 --- a/dependency-injection/cs/services.texy +++ b/dependency-injection/cs/services.texy @@ -433,8 +433,14 @@ services: application.application: create: MyApplication alteration: true - setup: - - '$onStartup[]' = [@resource, init] +``` + +Službu nemusíte identifikovat interním názvem, můžete na ni odkázat i jejím typem. Předchozí příklad tak lze zapsat i takto: + +```neon +services: + @Nette\Application\Application: + create: MyApplication ``` Při přepisování služby můžeme chtít odstranit původní argumenty, položky setup nebo tagy, k čemuž slouží `reset`: diff --git a/dependency-injection/en/services.texy b/dependency-injection/en/services.texy index d724a229cf..8da30d74ed 100644 --- a/dependency-injection/en/services.texy +++ b/dependency-injection/en/services.texy @@ -433,8 +433,14 @@ services: application.application: create: MyApplication alteration: true - setup: - - '$onStartup[]' = [@resource, init] +``` + +You don't have to identify a service by its internal name — you can refer to it by type instead. The previous example can also be written as: + +```neon +services: + @Nette\Application\Application: + create: MyApplication ``` When modifying a service, we might want to remove original arguments, setup items, or tags, using the `reset` key: From 943a2f4563170d02354f6de169885993db289628 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Fri, 27 Mar 2026 02:22:12 +0100 Subject: [PATCH 23/50] nette/mail 4.1.0 --- mail/cs/@home.texy | 72 ++++++++++++++++++++++++++++++++++++++++++++++ mail/en/@home.texy | 72 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+) diff --git a/mail/cs/@home.texy b/mail/cs/@home.texy index c2db2cff9a..fb72bf092d 100644 --- a/mail/cs/@home.texy +++ b/mail/cs/@home.texy @@ -176,6 +176,78 @@ V šabloně potom vytváříme odkazy tak, jak jsme zvyklí. Všechny odkazy vyt ``` +Inlinování CSS +============== + +[api:Nette\Mail\CssInliner] převádí CSS pravidla na inline atributy `style`, aby se e-maily zobrazovaly správně ve všech klientech. Zároveň generuje HTML atributy pro kompatibilitu s Outlookem. + +.[note] +Vyžaduje PHP 8.4 nebo novější a rozšíření `dom`. + +Většina e-mailových klientů má omezenou podporu značky `<style>` nebo ji zcela ignoruje. Pro správné zobrazení je proto potřeba převést CSS pravidla na inline atributy `style` u jednotlivých elementů. Stačí HTML předat metodě `inline()`: + +```php +$inliner = new Nette\Mail\CssInliner; +$html = $inliner->inline($html); +``` + +Pokud HTML obsahuje například: + +```latte +<style> +p { margin: 0; color: #333; } +a { color: #a0704e; } +</style> +<p>Hello <a href="#">world</a></p> +``` + +Výsledek po inlinování bude (značka `<style>` se zachová, zde ji vynecháváme pro stručnost): + +```latte +<p style="margin: 0; color: #333">Hello <a href="#" style="color: #a0704e">world</a></p> +``` + +Značka `<style>` zůstane ve výstupu vždy zachována, takže `@media` dotazy a další pravidla, která nelze inlinovat, budou nadále fungovat. + +Kromě extrakce stylů ze značek `<style>` lze CSS dodat i metodou `addCss()`. Inlinování je třeba provést před předáním HTML do `setHtmlBody()`: + +```php +$latte = new Latte\Engine; +$params = [ + 'orderId' => 123, +]; + +$html = $latte->renderToString('/path/to/email.latte', $params); +$html = (new Nette\Mail\CssInliner) + ->addCss(file_get_contents('/path/to/email.css')) + ->inline($html); + +$mail = new Nette\Mail\Message; +$mail->setHtmlBody($html); +``` + +Pokud je stejná CSS vlastnost nastavena z více zdrojů, pozdější přepisují dřívější. Pravidla ze značek `<style>` mají nejnižší prioritu, následují pravidla přidaná přes `addCss()`. Pokud element již má inline atribut `style` v HTML, ten má vždy nejvyšší prioritu. + +At-rules jako `@media` nebo `@font-face` se při inlinování přeskakují. Pseudo-třídy jako `:hover` nelze smysluplně inlinovat, protože inline styly nepodporují dynamické stavy. + + +HTML atributy pro Outlook +------------------------- + +Desktopové verze Microsoft Outlooku používají vykreslovací jádro Wordu, které nerozumí mnoha CSS vlastnostem. Pro zajištění kompatibility `CssInliner` automaticky generuje odpovídající HTML atributy z CSS pravidel vedle inline stylů: + +| CSS vlastnost | HTML atribut | Aplikuje se na +|----------------------------------------------------- +| `background-color` | `bgcolor` | `<table>`, `<td>`, `<th>`, `<body>`, `<tr>` +| `width` | `width` | `<table>`, `<td>`, `<th>`, `<img>` +| `height` | `height` | `<table>`, `<td>`, `<th>`, `<img>` +| `border-spacing` | `cellspacing` | `<table>` + +U `width`, `height` a `cellspacing` se automaticky odstraní jednotka `px` (např. `width: 600px` se převede na `width="600"`). Inline styl i HTML atribut se nastaví vždy společně, takže se e-mail zobrazí správně v moderních klientech i v Outlooku. + +HTML atributy se generují pouze z CSS pravidel zpracovaných třídou `CssInliner`, nikoliv z atributů `style` již přítomných v původním HTML. + + Odeslání e-mailu ================ diff --git a/mail/en/@home.texy b/mail/en/@home.texy index 97ed765b81..f867677234 100644 --- a/mail/en/@home.texy +++ b/mail/en/@home.texy @@ -176,6 +176,78 @@ In the template, you then create links as you are used to. All links created via ``` +CSS Inlining +============ + +[api:Nette\Mail\CssInliner] converts CSS rules into inline `style` attributes so that emails render consistently across all clients. It also generates HTML attributes for Outlook compatibility. + +.[note] +Requires PHP 8.4 or later and the `dom` extension. + +Most email clients have limited support for `<style>` tags or ignore them entirely. To ensure correct rendering, CSS rules need to be converted to inline `style` attributes on individual elements. Simply pass your HTML through `inline()`: + +```php +$inliner = new Nette\Mail\CssInliner; +$html = $inliner->inline($html); +``` + +For example, if the HTML contains: + +```latte +<style> +p { margin: 0; color: #333; } +a { color: #a0704e; } +</style> +<p>Hello <a href="#">world</a></p> +``` + +The result after inlining will be (the `<style>` tag is preserved but omitted here for brevity): + +```latte +<p style="margin: 0; color: #333">Hello <a href="#" style="color: #a0704e">world</a></p> +``` + +The `<style>` tag is always preserved in the output, so `@media` queries and other rules that cannot be inlined keep working. + +In addition to extracting styles from `<style>` tags, you can also provide CSS via the `addCss()` method. You need to inline CSS before passing the HTML to `setHtmlBody()`: + +```php +$latte = new Latte\Engine; +$params = [ + 'orderId' => 123, +]; + +$html = $latte->renderToString('/path/to/email.latte', $params); +$html = (new Nette\Mail\CssInliner) + ->addCss(file_get_contents('/path/to/email.css')) + ->inline($html); + +$mail = new Nette\Mail\Message; +$mail->setHtmlBody($html); +``` + +When the same CSS property is set by multiple sources, later sources override earlier ones. Rules from `<style>` tags have the lowest priority, followed by rules added via `addCss()`. If an element already has an inline `style` attribute in the HTML, it always takes the highest precedence. + +At-rules like `@media` or `@font-face` are skipped during inlining. Note that pseudo-classes like `:hover` cannot be meaningfully inlined, since inline styles do not support dynamic states. + + +HTML Attributes for Outlook +--------------------------- + +Desktop versions of Microsoft Outlook use the Word rendering engine, which doesn't understand many CSS properties. To ensure compatibility, `CssInliner` automatically generates corresponding HTML attributes from CSS rules alongside inline styles: + +| CSS Property | HTML Attribute | Applied To +|----------------------------------------------------- +| `background-color` | `bgcolor` | `<table>`, `<td>`, `<th>`, `<body>`, `<tr>` +| `width` | `width` | `<table>`, `<td>`, `<th>`, `<img>` +| `height` | `height` | `<table>`, `<td>`, `<th>`, `<img>` +| `border-spacing` | `cellspacing` | `<table>` + +For `width`, `height`, and `cellspacing`, the `px` unit is automatically stripped (e.g., `width: 600px` becomes `width="600"`). Both the inline style and the HTML attribute are always set, so the email renders correctly in modern clients and Outlook alike. + +HTML attributes are generated only from CSS rules processed by `CssInliner`, not from `style` attributes already present in the original HTML. + + Sending Emails ============== From 6c05c32194516ee7ff950159235e62e9c921ebff Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Sun, 12 Apr 2026 20:54:51 +0200 Subject: [PATCH 24/50] updated links to PhpStorm plugins --- best-practices/cs/editors-and-tools.texy | 6 +++--- best-practices/en/editors-and-tools.texy | 6 +++--- latte/cs/recipes.texy | 2 +- latte/en/recipes.texy | 2 +- neon/cs/format.texy | 2 +- neon/en/format.texy | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/best-practices/cs/editors-and-tools.texy b/best-practices/cs/editors-and-tools.texy index 13e3d10138..efbbd772ba 100644 --- a/best-practices/cs/editors-and-tools.texy +++ b/best-practices/cs/editors-and-tools.texy @@ -13,9 +13,9 @@ Rozhodně doporučujeme pro vývoj používat plnohodnotné IDE, jako je třeba **NetBeans IDE** má podporu pro Nette, Latte a NEON už vestavěnou. **PhpStorm**: nainstalujte si tyto pluginy v `Settings > Plugins > Marketplace` -- Nette framework helpers -- Latte -- NEON support +- [Nette |https://plugins.jetbrains.com/plugin/28342-nette] +- [Latte |https://plugins.jetbrains.com/plugin/24218-latte-support] nebo [Latte Pro |https://plugins.jetbrains.com/plugin/19661-latte-pro] +- [NEON |https://plugins.jetbrains.com/plugin/28338-neon] nebo [NEON / Nette support |https://plugins.jetbrains.com/plugin/18387-neon-nette-support] - Nette Tester **VS Code**: najděte v marketplace "Nette Latte + Neon" plugin. diff --git a/best-practices/en/editors-and-tools.texy b/best-practices/en/editors-and-tools.texy index c6109dcbab..e81b575eb6 100644 --- a/best-practices/en/editors-and-tools.texy +++ b/best-practices/en/editors-and-tools.texy @@ -13,9 +13,9 @@ We strongly recommend using a full-featured IDE for development, like PhpStorm, **NetBeans IDE** has built-in support for Nette, Latte, and NEON. **PhpStorm**: Install these plugins via `Settings > Plugins > Marketplace`: -- Nette framework helpers -- Latte -- NEON support +- [Nette |https://plugins.jetbrains.com/plugin/28342-nette] +- [Latte |https://plugins.jetbrains.com/plugin/24218-latte-support] or [Latte Pro |https://plugins.jetbrains.com/plugin/19661-latte-pro] +- [NEON |https://plugins.jetbrains.com/plugin/28338-neon] or [NEON / Nette support |https://plugins.jetbrains.com/plugin/18387-neon-nette-support] - Nette Tester **VS Code**: Find the "Nette Latte + Neon" plugin in the marketplace. diff --git a/latte/cs/recipes.texy b/latte/cs/recipes.texy index a11d147a0e..172a222a08 100644 --- a/latte/cs/recipes.texy +++ b/latte/cs/recipes.texy @@ -7,7 +7,7 @@ Editory a IDE Pište šablony v editoru nebo IDE, který má podporu pro Latte. Bude to mnohem příjemnější. -- PhpStorm: nainstalujte v `Settings > Plugins > Marketplace` [plugin Latte|https://plugins.jetbrains.com/plugin/7457-latte] +- PhpStorm: nainstalujte v `Settings > Plugins > Marketplace` [plugin Latte|https://plugins.jetbrains.com/plugin/24218-latte-support] - VS Code: nainstalujte [Nette Latte + Neon|https://marketplace.visualstudio.com/items?itemName=Kasik96.latte], [Nette Latte templates|https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] nebo nejnovější [Nette for VS Code |https://marketplace.visualstudio.com/items?itemName=franken-ui.nette-for-vscode] plugin - NetBeans IDE: nativní podpora Latte je součástí instalace - Sublime Text 3: v Package Control najděte a nainstalujte balíček `Nette` a zvolte Latte ve `View > Syntax` diff --git a/latte/en/recipes.texy b/latte/en/recipes.texy index 37896b3ee5..7547e5b989 100644 --- a/latte/en/recipes.texy +++ b/latte/en/recipes.texy @@ -7,7 +7,7 @@ Editors and IDE Write templates in an editor or IDE that supports Latte. It will be much more pleasant. -- PhpStorm: install the [Latte plugin|https://plugins.jetbrains.com/plugin/7457-latte] in `Settings > Plugins > Marketplace` +- PhpStorm: install the [Latte plugin|https://plugins.jetbrains.com/plugin/24218-latte-support] in `Settings > Plugins > Marketplace` - VS Code: install [Nette Latte + Neon|https://marketplace.visualstudio.com/items?itemName=Kasik96.latte], [Nette Latte templates|https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] or the latest [Nette for VS Code |https://marketplace.visualstudio.com/items?itemName=franken-ui.nette-for-vscode] plugin - NetBeans IDE: native support for Latte is included in the installation - Sublime Text 3: find and install the `Nette` package in Package Control and choose Latte in `View > Syntax` diff --git a/neon/cs/format.texy b/neon/cs/format.texy index f8bf97f6d5..70112f03f5 100644 --- a/neon/cs/format.texy +++ b/neon/cs/format.texy @@ -13,7 +13,7 @@ Integrace ========= - NetBeans (má vestavěnou podporu) -- PhpStorm ([plugin |https://plugins.jetbrains.com/plugin/7060?pr]) +- PhpStorm ([plugin |https://plugins.jetbrains.com/plugin/28338-neon]) - Visual Studio Code ([Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte]) nebo [Nette for VS Code |https://marketplace.visualstudio.com/items?itemName=franken-ui.nette-for-vscode]) - Sublime Text 3 ([plugin |https://github.com/FilipStryk/Nette-Latte-Neon-for-Sublime-Text-3]) - Sublime Text 2 ([plugin |https://github.com/Michal-Mikolas/Nette-package-for-Sublime-Text-2]) diff --git a/neon/en/format.texy b/neon/en/format.texy index 6120dafc6a..856a6156ee 100644 --- a/neon/en/format.texy +++ b/neon/en/format.texy @@ -13,7 +13,7 @@ Integration =========== - NetBeans (has built-in support) -- PhpStorm ([plugin |https://plugins.jetbrains.com/plugin/7060?pr]) +- PhpStorm ([plugin |https://plugins.jetbrains.com/plugin/28338-neon]) - Visual Studio Code ([Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] or [Nette for VS Code |https://marketplace.visualstudio.com/items?itemName=franken-ui.nette-for-vscode]) - Sublime Text 3 ([plugin |https://github.com/FilipStryk/Nette-Latte-Neon-for-Sublime-Text-3]) - Sublime Text 2 ([plugin |https://github.com/Michal-Mikolas/Nette-package-for-Sublime-Text-2]) From bc0383d4e39df60a6e9291960830aeb47fd6eb44 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Sun, 12 Apr 2026 23:43:14 +0200 Subject: [PATCH 25/50] tracy: open-files-in-ide updated Chrome policy to AutoLaunchProtocolsFromOrigins --- tracy/cs/open-files-in-ide.texy | 6 +++--- tracy/en/open-files-in-ide.texy | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tracy/cs/open-files-in-ide.texy b/tracy/cs/open-files-in-ide.texy index 37ce131750..d3b8e22605 100644 --- a/tracy/cs/open-files-in-ide.texy +++ b/tracy/cs/open-files-in-ide.texy @@ -135,10 +135,10 @@ V Google Chrome od verze 77 již neuvidíte zatržítko „Tento typ odkazů vž ``` Windows Registry Editor Version 5.00 -[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Google\Chrome\URLWhitelist] -"123"="editor://*" +[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Google\Chrome] +"AutoLaunchProtocolsFromOrigins"="[{\"allowed_origins\": [\"*\"],\"protocol\": \"editor\"}]" ``` -Importujte jej dvojitým kliknutím a restartujte prohlížeč Chrome. +Importujte jej dvojitým kliknutím a restartujte prohlížeč Chrome. Politika `AutoLaunchProtocolsFromOrigins` úplně potlačí potvrzovací dialog prohlížeče. Skript `install.cmd` toto nastavení provádí automaticky, a to včetně zakomentovaného řádku pro Vivaldi (stejná politika ve větvi `HKLM\SOFTWARE\Policies\Vivaldi`). S případnými dotazy nebo připomínkami se prosím obraťte na [fórum |https://forum.nette.org]. diff --git a/tracy/en/open-files-in-ide.texy b/tracy/en/open-files-in-ide.texy index 2c8d9112ba..53c2b863c7 100644 --- a/tracy/en/open-files-in-ide.texy +++ b/tracy/en/open-files-in-ide.texy @@ -135,10 +135,10 @@ Starting from Google Chrome version 77 you will no longer see the checkbox “Al ``` Windows Registry Editor Version 5.00 -[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Google\Chrome\URLWhitelist] -"123"="editor://*" +[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Google\Chrome] +"AutoLaunchProtocolsFromOrigins"="[{\"allowed_origins\": [\"*\"],\"protocol\": \"editor\"}]" ``` -Import it by double clicking and restart Chrome. +Import it by double clicking and restart Chrome. The `AutoLaunchProtocolsFromOrigins` policy fully suppresses the browser confirmation dialog. The `install.cmd` script sets this automatically, including a commented-out line for Vivaldi (same policy under `HKLM\SOFTWARE\Policies\Vivaldi`). For further questions or suggestions, please visit the [forum |https://forum.nette.org]. From 2cf9236a84eae0e8137b8a96169fd2131ba64185 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Mon, 6 Apr 2026 23:02:16 +0200 Subject: [PATCH 26/50] coding standard: added enums.php convention --- contributing/cs/coding-standard.texy | 2 +- contributing/en/coding-standard.texy | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contributing/cs/coding-standard.texy b/contributing/cs/coding-standard.texy index aaef617655..5bac29274f 100644 --- a/contributing/cs/coding-standard.texy +++ b/contributing/cs/coding-standard.texy @@ -14,7 +14,7 @@ Obecná pravidla - Dva prázdné řádky se používají k oddělení metod pro lepší čitelnost. - Důvod použití shut-up operátoru musí být zdokumentován: `@mkdir($dir); // @ - adresář může existovat`. - Pokud je použit slabě typizovaný operátor porovnání (tj. `==`, `!=`, ...), musí být zdokumentován záměr: `// == přijmout null` -- Do jednoho souboru `exceptions.php` můžete zapsat více výjimek. +- Do jednoho souboru `exceptions.php` můžete zapsat více výjimek, do souboru `enums.php` více enumů. - U rozhraní se nespecifikuje viditelnost metod, protože jsou vždy veřejné. - Každá property, návratová hodnota a parametr musí mít uvedený typ. Naopak u finálních konstant typ nikdy neuvádíme, protože je zjevný. - K ohraničení řetězce by se měly používat jednoduché uvozovky, s výjimkou případů, kdy samotný literál obsahuje apostrofy. diff --git a/contributing/en/coding-standard.texy b/contributing/en/coding-standard.texy index df9a0a86cb..2883d9634d 100644 --- a/contributing/en/coding-standard.texy +++ b/contributing/en/coding-standard.texy @@ -14,7 +14,7 @@ General Rules - Two empty lines are used to separate methods for better readability - The reason for using the shut-up operator (`@`) must be documented: `@mkdir($dir); // @ - directory may exist` - If a weak typed comparison operator is used (i.e., `==`, `!=`, ...), the intention must be documented: `// == to accept null` -- You can write multiple exception classes into a single file named `exceptions.php` +- You can write multiple exception classes into a single file named `exceptions.php`, and multiple enums into `enums.php` - The visibility of methods is not specified for interfaces because they are always public - Each property, return value, and parameter must have a type specified. Conversely, for final constants, we never specify the type because it is obvious - Single quotes should be used to delimit strings, except when the literal itself contains apostrophes From 99bfa00846692f91c4d908efdbe1c902c6779f9e Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Tue, 23 Dec 2025 22:05:06 +0100 Subject: [PATCH 27/50] latte 3.1.4 --- latte/cs/custom-tags.texy | 4 ++-- latte/cs/filters.texy | 16 ++++++++++++++++ latte/en/custom-tags.texy | 4 ++-- latte/en/filters.texy | 16 ++++++++++++++++ 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/latte/cs/custom-tags.texy b/latte/cs/custom-tags.texy index d5ad47f22e..4c35f4c796 100644 --- a/latte/cs/custom-tags.texy +++ b/latte/cs/custom-tags.texy @@ -160,7 +160,7 @@ Když Latte narazí na `{datetime}` v šabloně, zavolá parsovací funkci `crea Metoda `print()` generuje PHP kód, který bude spuštěn při vykreslování šablony. Voláme metodu `$context->format()`, která sestavuje výsledný řetězec PHP kódu pro kompilovanou šablonu. První argument, `'echo date('Y-m-d H:i:s') %line;'`, je maska, do které jsou doplněny následující parametry. Zástupný symbol `%line` říká metodě `format()`, aby použila druhý argument, kterým je `$this->position`, a vložila komentář jako `/* line 15 */`, který propojuje vygenerovaný PHP kód zpět na původní řádek šablony, což je klíčové pro ladění. -Vlastnost `$this->position` je zděděna ze základní třídy `Node` a je automaticky nastavena parserem Latte. Obsahuje objekt [api:Latte\Compiler\Position], který indikuje, kde byl tag nalezen ve zdrojovém souboru `.latte`. +Vlastnost `$this->position` je zděděna ze základní třídy `Node` a je automaticky nastavena parserem Latte. Obsahuje objekt [api:Latte\Compiler\Range] (potomek třídy `Position` rozšířený o vlastnost `length` v bajtech), který udává, kde se tag v souboru `.latte` nachází. U párových tagů pokrývá rozsah od otevíracího po uzavírací tag a potomci `StatementNode` navíc nabízejí pole `$this->tagRanges` s objekty `Range` pro každý dílčí tag (otevírací, mezilehlé jako `{else}`/`{case}` i uzavírací). Metoda `getIterator()` je zásadní pro kompilační průchody. Musí poskytovat všechny dětské uzly, ale náš jednoduchý `DatetimeNode` aktuálně nemá žádné argumenty ani obsah, tedy žádné dětské uzly. Nicméně metoda musí stále existovat a být generátorem, tj. klíčové slovo `yield` musí být nějakým způsobem přítomno v těle metody. @@ -1003,7 +1003,7 @@ Zástupné symboly `PrintContext::format()` - **`%args`**: Argument musí být `Expression\ArrayNode`. Vypíše položky pole formátované jako argumenty pro volání funkce nebo metody (oddělené čárkami, zpracovává pojmenované argumenty, pokud jsou přítomny). - `$argsNode = new ArrayNode([...]);` - `$context->format('myFunc(%args);', $argsNode)` -> `myFunc(1, name: 'Joe');` -- **`%line`**: Argument musí být objekt `Position` (obvykle `$this->position`). Vkládá PHP komentář `/* line X */` indikující číslo řádku zdroje. +- **`%line`**: Argument musí být objekt `Position` (nebo `Range`, obvykle `$this->position`). Vkládá PHP komentář `/* line X */` indikující číslo řádku zdroje. - `$context->format('echo "Hi" %line;', $this->position)` -> `echo "Hi" /* line 42:1 */;` - **`%escape(...)`**: Generuje PHP kód, který *za běhu* escapuje vnitřní výraz pomocí aktuálních kontextově uvědomělých pravidel escapování. - `$context->format('echo %escape(%node);', $variableNode)` diff --git a/latte/cs/filters.texy b/latte/cs/filters.texy index edad8271e9..5a53e646d0 100644 --- a/latte/cs/filters.texy +++ b/latte/cs/filters.texy @@ -12,6 +12,7 @@ V šablonách můžeme používat funkce, které pomáhají upravit nebo přefor | `clamp` | [ohraničí hodnotu do daného rozsahu |#clamp] | `column` | [extrahuje jeden sloupec z pole |#column] | `commas` | [spojí pole čárkami |#commas] +| `limit` | [omezí délku pole, řetězce nebo iterátoru |#limit] | `dataStream` | [konverze pro Data URI protokol |#dataStream] | `date` | [formátuje datum a čas |#date] | `explode` | [rozdělí řetězec na pole podle oddělovače |#explode] @@ -812,6 +813,21 @@ Pokud je zadaný parametr length a je kladný, posloupnost bude obsahovat tolik 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. +Viz také [#limit]. + + +limit(int $length) .[filter]{data-version:3.1.3} +------------------------------------------------ +Omezí délku pole, řetězce nebo iterátoru. U polí a iterátorů zachovává klíče. U řetězců respektuje UTF-8. + +```latte +{foreach ($items|limit: 5) as $item} + ... +{/foreach} + +{$text|limit: 100} +``` + sort(?Closure $comparison, string|int|\Closure|null $by=null, string|int|\Closure|bool $byKey=false) .[filter] -------------------------------------------------------------------------------------------------------------- diff --git a/latte/en/custom-tags.texy b/latte/en/custom-tags.texy index 8d8a7cf7c6..b162bc8e10 100644 --- a/latte/en/custom-tags.texy +++ b/latte/en/custom-tags.texy @@ -160,7 +160,7 @@ When Latte encounters `{datetime}` in a template, it calls the tag parsing funct The `print()` method generates the PHP code that will be executed when the template is rendered. We call the `$context->format()` method, which assembles the resulting PHP code string for the compiled template. The first argument, `'echo date('Y-m-d H:i:s') %line;'`, is the mask into which the subsequent parameters are substituted. The `%line` placeholder tells the `format()` method to take the second following argument, which is `$this->position`, and inserts a comment like `/* line 15 */` that links the generated PHP code back to the original template line, which is crucial for debugging. -Property `$this->position` is inherited from the base `Node` class, and is automatically set by Latte's parser. It holds a [api:Latte\Compiler\Position] object indicating where the tag was found in the source `.latte` file. +Property `$this->position` is inherited from the base `Node` class, and is automatically set by Latte's parser. It holds a [api:Latte\Compiler\Range] object (a subclass of `Position` extended with a `length` in bytes) indicating where the tag is located in the source `.latte` file. For paired tags the range spans from the opening to the closing tag, and `StatementNode` descendants additionally expose `$this->tagRanges` listing the `Range` of every constituent tag (opening, intermediate like `{else}`/`{case}`, and closing). The `getIterator()` method is vital for compiler passes. It must yield all child nodes, but our simple `DatetimeNode` currently has no arguments or content, thus no child nodes. However, the method must still exist and be a generator, i.e. the `yield` keyword must be somehow present in the method body. @@ -1003,7 +1003,7 @@ We've frequently used `PrintContext::format()` to generate PHP code in the `prin - **`%args`**: Argument must be an `Expression\ArrayNode`. It prints the array items formatted as arguments for a function or method call (comma-separated, handling named arguments if present). - `$argsNode = new ArrayNode([...]);` - `$context->format('myFunc(%args);', $argsNode)` -> `myFunc(1, name: 'Joe');` -- **`%line`**: Argument must be a `Position` object (usually `$this->position`). It inserts a PHP comment `/* line X */` indicating the source line number. +- **`%line`**: Argument must be a `Position` (or `Range`) object (usually `$this->position`). It inserts a PHP comment `/* line X */` indicating the source line number. - `$context->format('echo "Hi" %line;', $this->position)` -> `echo "Hi" /* line 42:1 */;` - **`%escape(...)`**: It generates PHP code that, *at runtime*, will escape the inner expression using the current context-aware escaping rules. - `$context->format('echo %escape(%node);', $variableNode)` diff --git a/latte/en/filters.texy b/latte/en/filters.texy index a6365b3be6..813daf354d 100644 --- a/latte/en/filters.texy +++ b/latte/en/filters.texy @@ -12,6 +12,7 @@ In templates, we can use functions that help modify or reformat data into its fi | `clamp` | [clamps a value to the given range |#clamp] | `column` | [extracts a single column from an array |#column] | `commas` | [joins an array with commas |#commas] +| `limit` | [limits the length of an array, string, or iterator |#limit] | `dataStream` | [Data URI protocol conversion |#dataStream] | `date` | [formats the date and time |#date] | `explode` | [splits a string into an array by a delimiter |#explode] @@ -812,6 +813,21 @@ If `length` is given and is positive, then the sequence will have up to that man By default, the filter reorders and resets the integer array keys. This behavior can be changed by setting `preserveKeys` to true. String keys are always preserved, regardless of this parameter. +See also [#limit]. + + +limit(int $length) .[filter]{data-version:3.1.3} +------------------------------------------------ +Limits the length of an array, string, or iterator. For arrays and iterators, keys are preserved. For strings, it respects UTF-8. + +```latte +{foreach ($items|limit: 5) as $item} + ... +{/foreach} + +{$text|limit: 100} +``` + sort(?Closure $comparison, string|int|\Closure|null $by=null, string|int|\Closure|bool $byKey=false) .[filter] -------------------------------------------------------------------------------------------------------------- From d0d4f7a26ae77ab3d81402fd16d5c0f452a8d5fb Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Sat, 25 Apr 2026 14:47:55 +0200 Subject: [PATCH 28/50] latte: develop.texy adds 'Ways to Extend Latte' overview --- latte/cs/develop.texy | 14 ++++++++++++++ latte/en/develop.texy | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/latte/cs/develop.texy b/latte/cs/develop.texy index 08dd5686f3..f900b522b0 100644 --- a/latte/cs/develop.texy +++ b/latte/cs/develop.texy @@ -58,6 +58,20 @@ $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í. +Způsoby rozšíření Latte +======================= + +Latte můžete přizpůsobit hned několika způsoby, od jednoduchých pomocníků až po vlastní jazykové konstrukce. Podrobně se jim věnuje stránka [rozšiřujeme Latte |extending-latte], zde je stručný přehled: + +- **[Vlastní filtry |custom-filters]:** pro formátování nebo transformaci dat ve výstupu šablony (např. `{$var|myFilter}`). +- **[Vlastní funkce |custom-functions]:** pro vlastní logiku, kterou voláte ve výrazech šablony (např. `{myFunction($arg)}`). +- **[Vlastní tagy |custom-tags]:** pro zcela nové jazykové konstrukce (`{mytag}...{/mytag}` nebo `n:mytag`). +- **[Kompilační průchody |compiler-passes]:** funkce, které upravují AST šablony mezi parsováním a generováním PHP kódu (například pro optimalizace nebo bezpečnostní kontroly). +- **[Vlastní loadery |loaders]:** pro změnu způsobu, jakým Latte vyhledává a načítá soubory šablon. + +Pokud chcete svá rozšíření znovu použít v jiných projektech nebo je sdílet s ostatními, zabalte je do třídy [Latte Extension |extending-latte#Latte Extension]. + + Parametry jako třída ==================== diff --git a/latte/en/develop.texy b/latte/en/develop.texy index bad55da3b4..7630fc3c15 100644 --- a/latte/en/develop.texy +++ b/latte/en/develop.texy @@ -58,6 +58,20 @@ $latte->setAutoRefresh(false); When deployed on a production server, the initial cache generation, especially for larger applications, can understandably take a while. Latte has built-in prevention against "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede. This is a situation where server receives a large number of concurrent requests and because Latte's cache does not yet exist, they would all generate it at the same time. Which spikes CPU. Latte is smart, and when there are multiple concurrent requests, only the first thread generates the cache, the others wait and then use it. +Ways to Extend Latte +==================== + +Latte can be customized in several ways, from simple helpers to entirely new language constructs. The page [extending Latte |extending-latte] covers them in detail; here is a quick overview: + +- **[Custom Filters|custom-filters]:** for formatting or transforming data in the template output (e.g., `{$var|myFilter}`). +- **[Custom Functions|custom-functions]:** for custom logic you call within template expressions (e.g., `{myFunction($arg)}`). +- **[Custom Tags|custom-tags]:** for entirely new language constructs (`{mytag}...{/mytag}` or `n:mytag`). +- **[Compiler Passes|compiler-passes]:** functions that modify the template's AST between parsing and PHP code generation (for example, optimizations or security checks). +- **[Custom Loaders|loaders]:** for changing how Latte locates and loads template files. + +If you want to reuse your extensions across projects or share them with others, bundle them into a [Latte Extension |extending-latte#Latte Extension] class. + + Parameters as a Class ===================== From 34708c1492633df7a5bae0ddc1fd73043d4b2991 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Sun, 26 Apr 2026 01:23:58 +0200 Subject: [PATCH 29/50] nette: add emoji icons to documentation home links Each link in the documentation index now has a thematic emoji prepended to make the page more scannable and visually engaging. Applied to all 17 language versions on aligned line numbers. --- nette/bg/@home.texy | 110 ++++++++++++++++++++++---------------------- nette/cs/@home.texy | 110 ++++++++++++++++++++++---------------------- nette/de/@home.texy | 110 ++++++++++++++++++++++---------------------- nette/el/@home.texy | 110 ++++++++++++++++++++++---------------------- nette/en/@home.texy | 110 ++++++++++++++++++++++---------------------- nette/es/@home.texy | 110 ++++++++++++++++++++++---------------------- nette/fr/@home.texy | 110 ++++++++++++++++++++++---------------------- nette/hu/@home.texy | 110 ++++++++++++++++++++++---------------------- nette/it/@home.texy | 110 ++++++++++++++++++++++---------------------- nette/ja/@home.texy | 110 ++++++++++++++++++++++---------------------- nette/pl/@home.texy | 110 ++++++++++++++++++++++---------------------- nette/pt/@home.texy | 110 ++++++++++++++++++++++---------------------- nette/ro/@home.texy | 110 ++++++++++++++++++++++---------------------- nette/ru/@home.texy | 110 ++++++++++++++++++++++---------------------- nette/sl/@home.texy | 110 ++++++++++++++++++++++---------------------- nette/tr/@home.texy | 110 ++++++++++++++++++++++---------------------- nette/uk/@home.texy | 110 ++++++++++++++++++++++---------------------- 17 files changed, 935 insertions(+), 935 deletions(-) diff --git a/nette/bg/@home.texy b/nette/bg/@home.texy index a1ca3795bf..5529dfaf8c 100644 --- a/nette/bg/@home.texy +++ b/nette/bg/@home.texy @@ -8,23 +8,23 @@ Запознаване ----------- -- [Защо да използвате Nette? |www:10-reasons-why-nette] -- [Инсталация |installation] -- [Пишем първото приложение! |quickstart:] +- 🤔 [Защо да използвате Nette? |www:10-reasons-why-nette] +- 📥 [Инсталация |installation] +- 🚀 [Пишем първото приложение! |quickstart:] Общи ---- -- [Списък на пакетите |www:packages] -- [Поддръжка и PHP версии |www:maintenance] -- [Бележки по изданието |https://nette.org/releases] -- [Преминаване към по-нови версии |migrations:en] -- [Отстраняване на проблеми |nette:troubleshooting] -- [Кой създава Nette |https://nette.org/contributors] -- [История на Nette |www:history] -- [Включете се |contributing:] -- [Подкрепете разработката |https://nette.org/cs/donate] -- [API референция |https://api.nette.org/] +- 📚 [Списък на пакетите |www:packages] +- 🔧 [Поддръжка и PHP версии |www:maintenance] +- 📰 [Бележки по изданието |https://nette.org/releases] +- ⬆️ [Преминаване към по-нови версии |migrations:en] +- 🆘 [Отстраняване на проблеми |nette:troubleshooting] +- 👥 [Кой създава Nette |https://nette.org/contributors] +- 📜 [История на Nette |www:history] +- 🤝 [Включете се |contributing:] +- ❤️ [Подкрепете разработката |https://nette.org/cs/donate] +- 📖 [API референция |https://api.nette.org/] </div> @@ -33,18 +33,18 @@ Приложения в Nette ------------------ -- [Как работят приложенията? |application:how-it-works] -- [Bootstrapping |application:Bootstrapping] -- [Presenters |application:presenters] -- [Шаблони |application:templates] -- [Директорийна структура |application:directory-structure] -- [Маршрутизация |application:routing] -- [Създаване на URL връзки |application:creating-links] -- [Интерактивни компоненти |application:components] -- [AJAX & снипети |application:ajax] - - -- [Ръководства и практики |best-practices:] +- 🧭 [Как работят приложенията? |application:how-it-works] +- 🥾 [Bootstrapping |application:Bootstrapping] +- 🎬 [Presenters |application:presenters] +- 📄 [Шаблони |application:templates] +- 📁 [Директорийна структура |application:directory-structure] +- 🗺️ [Маршрутизация |application:routing] +- 🔗 [Създаване на URL връзки |application:creating-links] +- 🎛️ [Интерактивни компоненти |application:components] +- 📡 [AJAX & снипети |application:ajax] + + +- 🎓 [Ръководства и практики |best-practices:] </div> @@ -53,22 +53,22 @@ Основни теми ------------ -- [Конфигурация |nette:configuring] -- [Dependency Injection|dependency-injection:] -- [Latte: шаблони |latte:] -- [Tracy: дебъгване на код |tracy:] -- [Форми |forms:] -- [База данни |database:guide] -- [Вход на потребители |security:authentication] -- [Проверка на права |security:authorization] -- [Сесии |http:Sessions] -- [HTTP request & response|http:] -- [Активи |assets:] -- [Кеш |caching:] -- [Изпращане на имейли |mail:] -- [Schema: валидация на данни |schema:] -- [Генератор на PHP код |php-generator:] -- [Tester: тестване |tester:] +- ⚙️ [Конфигурация |nette:configuring] +- 🧩 [Dependency Injection|dependency-injection:] +- ☕ [Latte: шаблони |latte:] +- 🐞 [Tracy: дебъгване на код |tracy:] +- 📝 [Форми |forms:] +- 🗄️ [База данни |database:guide] +- 🪪 [Вход на потребители |security:authentication] +- 🛡️ [Проверка на права |security:authorization] +- 🍪 [Сесии |http:Sessions] +- 🌐 [HTTP request & response|http:] +- 📦 [Активи |assets:] +- ⚡ [Кеш |caching:] +- ✉️ [Изпращане на имейли |mail:] +- 📐 [Schema: валидация на данни |schema:] +- 🛠️ [Генератор на PHP код |php-generator:] +- 🧪 [Tester: тестване |tester:] </div> @@ -77,20 +77,20 @@ Utilities --------- -- [Масиви |utils:arrays] -- [Файлова система |utils:filesystem] -- [Finder |utils:finder] -- [HTML елементи |utils:html-elements] -- [Изображения |utils:images] -- [JSON |utils:JSON] -- [NEON|neon:] -- [Хеширане на пароли |security:passwords] -- [PHP типове |utils:type] -- [Низове |utils:strings] -- [Валидатори |utils:validators] -- [RobotLoader |robot-loader:] -- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] -- [SafeStream |safe-stream:] +- 🧮 [Масиви |utils:arrays] +- 💾 [Файлова система |utils:filesystem] +- 🔎 [Finder |utils:finder] +- 🏷️ [HTML елементи |utils:html-elements] +- 🖼️ [Изображения |utils:images] +- 📋 [JSON |utils:JSON] +- 💡 [NEON|neon:] +- 🔐 [Хеширане на пароли |security:passwords] +- 🐘 [PHP типове |utils:type] +- 🧵 [Низове |utils:strings] +- ✅ [Валидатори |utils:validators] +- 🤖 [RobotLoader |robot-loader:] +- 🧠 [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] +- 🛟 [SafeStream |safe-stream:] - [...други |utils:] </div> diff --git a/nette/cs/@home.texy b/nette/cs/@home.texy index b07e4cbb99..fef1c2b85b 100644 --- a/nette/cs/@home.texy +++ b/nette/cs/@home.texy @@ -8,23 +8,23 @@ Dokumentace Nette Seznámení --------- -- [Proč používat Nette? |www:10-reasons-why-nette] -- [Instalace |installation] -- [Píšeme první aplikaci! |quickstart:] +- 🤔 [Proč používat Nette? |www:10-reasons-why-nette] +- 📥 [Instalace |installation] +- 🚀 [Píšeme první aplikaci! |quickstart:] Obecné ------ -- [Seznam balíčků |www:packages] -- [Údržba a PHP verze |www:maintenance] -- [Release Notes |https://nette.org/releases] -- [Přechod na novější verze|migrations:] -- [Řešení problémů |nette:troubleshooting] -- [Kdo tvoří Nette |https://nette.org/contributors] -- [Historie Nette |www:history] -- [Zapojte se |contributing:] -- [Podpořte vývoj |https://nette.org/cs/donate] -- [API reference |https://api.nette.org/] +- 📚 [Seznam balíčků |www:packages] +- 🔧 [Údržba a PHP verze |www:maintenance] +- 📰 [Release Notes |https://nette.org/releases] +- ⬆️ [Přechod na novější verze|migrations:] +- 🆘 [Řešení problémů |nette:troubleshooting] +- 👥 [Kdo tvoří Nette |https://nette.org/contributors] +- 📜 [Historie Nette |www:history] +- 🤝 [Zapojte se |contributing:] +- ❤️ [Podpořte vývoj |https://nette.org/cs/donate] +- 📖 [API reference |https://api.nette.org/] </div> @@ -33,18 +33,18 @@ Obecné Aplikace v Nette ---------------- -- [Jak fungují aplikace? |application:how-it-works] -- [application:Bootstrapping] -- [Presentery |application:presenters] -- [Šablony |application:templates] -- [Adresářová struktura |application:directory-structure] -- [Routování |application:routing] -- [Vytváření odkazů URL |application:creating-links] -- [Interaktivní komponenty |application:components] -- [AJAX & snippety |application:ajax] - - -- [Návody a postupy |best-practices:] +- 🧭 [Jak fungují aplikace? |application:how-it-works] +- 🥾 [application:Bootstrapping] +- 🎬 [Presentery |application:presenters] +- 📄 [Šablony |application:templates] +- 📁 [Adresářová struktura |application:directory-structure] +- 🗺️ [Routování |application:routing] +- 🔗 [Vytváření odkazů URL |application:creating-links] +- 🎛️ [Interaktivní komponenty |application:components] +- 📡 [AJAX & snippety |application:ajax] + + +- 🎓 [Návody a postupy |best-practices:] </div> @@ -53,22 +53,22 @@ Aplikace v Nette Hlavní témata ------------- -- [Konfigurace |nette:configuring] -- [Dependency Injection|dependency-injection:] -- [Latte: šablony |latte:] -- [Tracy: ladění kódu |tracy:] -- [Formuláře |forms:] -- [Databáze |database:guide] -- [Přihlašování uživatelů |security:authentication] -- [Ověřování oprávnění |security:authorization] -- [http:Sessions] -- [HTTP request & response|http:] -- [Assety |assets:] -- [Cache |caching:] -- [Odesílání e-mailů |mail:] -- [Schema: validace dat |schema:] -- [Generátor PHP kódu |php-generator:] -- [Tester: testování |tester:] +- ⚙️ [Konfigurace |nette:configuring] +- 🧩 [Dependency Injection|dependency-injection:] +- ☕ [Latte: šablony |latte:] +- 🐞 [Tracy: ladění kódu |tracy:] +- 📝 [Formuláře |forms:] +- 🗄️ [Databáze |database:guide] +- 🪪 [Přihlašování uživatelů |security:authentication] +- 🛡️ [Ověřování oprávnění |security:authorization] +- 🍪 [http:Sessions] +- 🌐 [HTTP request & response|http:] +- 📦 [Assety |assets:] +- ⚡ [Cache |caching:] +- ✉️ [Odesílání e-mailů |mail:] +- 📐 [Schema: validace dat |schema:] +- 🛠️ [Generátor PHP kódu |php-generator:] +- 🧪 [Tester: testování |tester:] </div> @@ -77,20 +77,20 @@ Hlavní témata Utilities --------- -- [Pole |utils:arrays] -- [Souborový systém |utils:filesystem] -- [Finder |utils:finder] -- [HTML elementy |utils:html-elements] -- [Obrázky |utils:images] -- [utils:JSON] -- [NEON|neon:] -- [Hashování hesel |security:passwords] -- [PHP typy |utils:type] -- [Řetězce |utils:strings] -- [Validátory |utils:validators] -- [RobotLoader |robot-loader:] -- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] -- [SafeStream |safe-stream:] +- 🧮 [Pole |utils:arrays] +- 💾 [Souborový systém |utils:filesystem] +- 🔎 [Finder |utils:finder] +- 🏷️ [HTML elementy |utils:html-elements] +- 🖼️ [Obrázky |utils:images] +- 📋 [utils:JSON] +- 💡 [NEON|neon:] +- 🔐 [Hashování hesel |security:passwords] +- 🐘 [PHP typy |utils:type] +- 🧵 [Řetězce |utils:strings] +- ✅ [Validátory |utils:validators] +- 🤖 [RobotLoader |robot-loader:] +- 🧠 [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] +- 🛟 [SafeStream |safe-stream:] - [...další |utils:] </div> diff --git a/nette/de/@home.texy b/nette/de/@home.texy index a77749139f..fd8b79f1ae 100644 --- a/nette/de/@home.texy +++ b/nette/de/@home.texy @@ -8,23 +8,23 @@ Nette Dokumentation Kennenlernen ------------ -- [Warum Nette verwenden? |www:10-reasons-why-nette] -- [Installation |installation] -- [Schreiben wir die erste Anwendung! |quickstart:] +- 🤔 [Warum Nette verwenden? |www:10-reasons-why-nette] +- 📥 [Installation |installation] +- 🚀 [Schreiben wir die erste Anwendung! |quickstart:] Allgemein --------- -- [Paketliste |www:packages] -- [Wartung und PHP-Versionen |www:maintenance] -- [Release Notes |https://nette.org/releases] -- [Übergang zu neueren Versionen |migrations:en] -- [Fehlerbehebung |nette:troubleshooting] -- [Wer erstellt Nette |https://nette.org/contributors] -- [Geschichte von Nette |www:history] -- [Machen Sie mit |contributing:] -- [Unterstützen Sie die Entwicklung |https://nette.org/cs/donate] -- [API-Referenz |https://api.nette.org/] +- 📚 [Paketliste |www:packages] +- 🔧 [Wartung und PHP-Versionen |www:maintenance] +- 📰 [Release Notes |https://nette.org/releases] +- ⬆️ [Übergang zu neueren Versionen |migrations:en] +- 🆘 [Fehlerbehebung |nette:troubleshooting] +- 👥 [Wer erstellt Nette |https://nette.org/contributors] +- 📜 [Geschichte von Nette |www:history] +- 🤝 [Machen Sie mit |contributing:] +- ❤️ [Unterstützen Sie die Entwicklung |https://nette.org/cs/donate] +- 📖 [API-Referenz |https://api.nette.org/] </div> @@ -33,18 +33,18 @@ Allgemein Anwendungen in Nette -------------------- -- [Wie Anwendungen funktionieren |application:how-it-works] -- [application:Bootstrapping] -- [Presenter |application:presenters] -- [Templates |application:templates] -- [Verzeichnisstruktur |application:directory-structure] -- [Routing |application:routing] -- [Erstellen von URL-Links |application:creating-links] -- [Interaktive Komponenten |application:components] -- [AJAX & Snippets |application:ajax] - - -- [Anleitungen und Verfahren |best-practices:] +- 🧭 [Wie Anwendungen funktionieren |application:how-it-works] +- 🥾 [application:Bootstrapping] +- 🎬 [Presenter |application:presenters] +- 📄 [Templates |application:templates] +- 📁 [Verzeichnisstruktur |application:directory-structure] +- 🗺️ [Routing |application:routing] +- 🔗 [Erstellen von URL-Links |application:creating-links] +- 🎛️ [Interaktive Komponenten |application:components] +- 📡 [AJAX & Snippets |application:ajax] + + +- 🎓 [Anleitungen und Verfahren |best-practices:] </div> @@ -53,22 +53,22 @@ Anwendungen in Nette Hauptthemen ----------- -- [Konfiguration |nette:configuring] -- [Dependency Injection |dependency-injection:] -- [Latte: Templates |latte:] -- [Tracy: Code-Debugging |tracy:] -- [Formulare |forms:] -- [Datenbank |database:guide] -- [Benutzeranmeldung |security:authentication] -- [Berechtigungsprüfung |security:authorization] -- [http:Sessions] -- [HTTP-Request & -Response |http:] -- [Aktiva |assets:] -- [Cache |caching:] -- [E-Mails senden |mail:] -- [Schema: Datenvalidierung |schema:] -- [PHP-Code-Generator |php-generator:] -- [Tester: Testen |tester:] +- ⚙️ [Konfiguration |nette:configuring] +- 🧩 [Dependency Injection |dependency-injection:] +- ☕ [Latte: Templates |latte:] +- 🐞 [Tracy: Code-Debugging |tracy:] +- 📝 [Formulare |forms:] +- 🗄️ [Datenbank |database:guide] +- 🪪 [Benutzeranmeldung |security:authentication] +- 🛡️ [Berechtigungsprüfung |security:authorization] +- 🍪 [http:Sessions] +- 🌐 [HTTP-Request & -Response |http:] +- 📦 [Aktiva |assets:] +- ⚡ [Cache |caching:] +- ✉️ [E-Mails senden |mail:] +- 📐 [Schema: Datenvalidierung |schema:] +- 🛠️ [PHP-Code-Generator |php-generator:] +- 🧪 [Tester: Testen |tester:] </div> @@ -77,20 +77,20 @@ Hauptthemen Utilities --------- -- [Arrays |utils:arrays] -- [Dateisystem |utils:filesystem] -- [Finder |utils:finder] -- [HTML-Elemente |utils:html-elements] -- [Bilder |utils:images] -- [utils:JSON] -- [NEON |neon:] -- [Passwort-Hashing |security:passwords] -- [PHP-Typen |utils:type] -- [Zeichenketten |utils:strings] -- [Validatoren |utils:validators] -- [RobotLoader |robot-loader:] -- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] -- [SafeStream |safe-stream:] +- 🧮 [Arrays |utils:arrays] +- 💾 [Dateisystem |utils:filesystem] +- 🔎 [Finder |utils:finder] +- 🏷️ [HTML-Elemente |utils:html-elements] +- 🖼️ [Bilder |utils:images] +- 📋 [utils:JSON] +- 💡 [NEON |neon:] +- 🔐 [Passwort-Hashing |security:passwords] +- 🐘 [PHP-Typen |utils:type] +- 🧵 [Zeichenketten |utils:strings] +- ✅ [Validatoren |utils:validators] +- 🤖 [RobotLoader |robot-loader:] +- 🧠 [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] +- 🛟 [SafeStream |safe-stream:] - [...weitere |utils:] </div> diff --git a/nette/el/@home.texy b/nette/el/@home.texy index c962d94320..2de3b00ad3 100644 --- a/nette/el/@home.texy +++ b/nette/el/@home.texy @@ -8,23 +8,23 @@ Εισαγωγή -------- -- [Γιατί να χρησιμοποιήσετε το Nette; |www:10-reasons-why-nette] -- [Εγκατάσταση |installation] -- [Γράφοντας την πρώτη σας εφαρμογή! |quickstart:] +- 🤔 [Γιατί να χρησιμοποιήσετε το Nette; |www:10-reasons-why-nette] +- 📥 [Εγκατάσταση |installation] +- 🚀 [Γράφοντας την πρώτη σας εφαρμογή! |quickstart:] Γενικά ------ -- [Λίστα πακέτων |www:packages] -- [Συντήρηση και εκδόσεις PHP |www:maintenance] -- [Σημειώσεις έκδοσης |https://nette.org/releases] -- [Μετάβαση σε νεότερες εκδόσεις|migrations:en] -- [Αντιμετώπιση προβλημάτων |nette:troubleshooting] -- [Ποιος δημιουργεί το Nette |https://nette.org/contributors] -- [Ιστορία του Nette |www:history] -- [Συμμετέχετε |contributing:] -- [Υποστηρίξτε την ανάπτυξη |https://nette.org/cs/donate] -- [Αναφορά API |https://api.nette.org/] +- 📚 [Λίστα πακέτων |www:packages] +- 🔧 [Συντήρηση και εκδόσεις PHP |www:maintenance] +- 📰 [Σημειώσεις έκδοσης |https://nette.org/releases] +- ⬆️ [Μετάβαση σε νεότερες εκδόσεις|migrations:en] +- 🆘 [Αντιμετώπιση προβλημάτων |nette:troubleshooting] +- 👥 [Ποιος δημιουργεί το Nette |https://nette.org/contributors] +- 📜 [Ιστορία του Nette |www:history] +- 🤝 [Συμμετέχετε |contributing:] +- ❤️ [Υποστηρίξτε την ανάπτυξη |https://nette.org/cs/donate] +- 📖 [Αναφορά API |https://api.nette.org/] </div> @@ -33,18 +33,18 @@ Εφαρμογές στο Nette ------------------- -- [Πώς λειτουργούν οι εφαρμογές; |application:how-it-works] -- [Bootstrapping |application:Bootstrapping] -- [Presenters |application:presenters] -- [Templates |application:templates] -- [Δομή καταλόγου |application:directory-structure] -- [Δρομολόγηση |application:routing] -- [Δημιουργία συνδέσμων URL |application:creating-links] -- [Διαδραστικά components |application:components] -- [AJAX & snippets |application:ajax] - - -- [Οδηγοί και βέλτιστες πρακτικές |best-practices:] +- 🧭 [Πώς λειτουργούν οι εφαρμογές; |application:how-it-works] +- 🥾 [Bootstrapping |application:Bootstrapping] +- 🎬 [Presenters |application:presenters] +- 📄 [Templates |application:templates] +- 📁 [Δομή καταλόγου |application:directory-structure] +- 🗺️ [Δρομολόγηση |application:routing] +- 🔗 [Δημιουργία συνδέσμων URL |application:creating-links] +- 🎛️ [Διαδραστικά components |application:components] +- 📡 [AJAX & snippets |application:ajax] + + +- 🎓 [Οδηγοί και βέλτιστες πρακτικές |best-practices:] </div> @@ -53,22 +53,22 @@ Κύρια θέματα ------------ -- [Διαμόρφωση |nette:configuring] -- [Dependency Injection|dependency-injection:] -- [Latte: templates |latte:] -- [Tracy: debugging κώδικα |tracy:] -- [Φόρμες |forms:] -- [Βάση δεδομένων |database:guide] -- [Σύνδεση χρηστών |security:authentication] -- [Επαλήθευση αδειών |security:authorization] -- [Sessions |http:Sessions] -- [HTTP request & response|http:] -- [Περιουσιακά στοιχεία |assets:] -- [Cache |caching:] -- [Αποστολή μηνυμάτων ηλεκτρονικού ταχυδρομείου |mail:] -- [Schema: επικύρωση δεδομένων |schema:] -- [Γεννήτρια κώδικα PHP |php-generator:] -- [Tester: testing |tester:] +- ⚙️ [Διαμόρφωση |nette:configuring] +- 🧩 [Dependency Injection|dependency-injection:] +- ☕ [Latte: templates |latte:] +- 🐞 [Tracy: debugging κώδικα |tracy:] +- 📝 [Φόρμες |forms:] +- 🗄️ [Βάση δεδομένων |database:guide] +- 🪪 [Σύνδεση χρηστών |security:authentication] +- 🛡️ [Επαλήθευση αδειών |security:authorization] +- 🍪 [Sessions |http:Sessions] +- 🌐 [HTTP request & response|http:] +- 📦 [Περιουσιακά στοιχεία |assets:] +- ⚡ [Cache |caching:] +- ✉️ [Αποστολή μηνυμάτων ηλεκτρονικού ταχυδρομείου |mail:] +- 📐 [Schema: επικύρωση δεδομένων |schema:] +- 🛠️ [Γεννήτρια κώδικα PHP |php-generator:] +- 🧪 [Tester: testing |tester:] </div> @@ -77,20 +77,20 @@ Utilities --------- -- [Arrays |utils:arrays] -- [Σύστημα αρχείων |utils:filesystem] -- [Finder |utils:finder] -- [Στοιχεία HTML |utils:html-elements] -- [Εικόνες |utils:images] -- [JSON |utils:JSON] -- [NEON|neon:] -- [Κατακερματισμός κωδικών πρόσβασης |security:passwords] -- [Τύποι PHP |utils:type] -- [Strings |utils:strings] -- [Validators |utils:validators] -- [RobotLoader |robot-loader:] -- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] -- [SafeStream |safe-stream:] +- 🧮 [Arrays |utils:arrays] +- 💾 [Σύστημα αρχείων |utils:filesystem] +- 🔎 [Finder |utils:finder] +- 🏷️ [Στοιχεία HTML |utils:html-elements] +- 🖼️ [Εικόνες |utils:images] +- 📋 [JSON |utils:JSON] +- 💡 [NEON|neon:] +- 🔐 [Κατακερματισμός κωδικών πρόσβασης |security:passwords] +- 🐘 [Τύποι PHP |utils:type] +- 🧵 [Strings |utils:strings] +- ✅ [Validators |utils:validators] +- 🤖 [RobotLoader |robot-loader:] +- 🧠 [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] +- 🛟 [SafeStream |safe-stream:] - [...περισσότερα |utils:] </div> diff --git a/nette/en/@home.texy b/nette/en/@home.texy index 0020230ca3..37e40fefbf 100644 --- a/nette/en/@home.texy +++ b/nette/en/@home.texy @@ -8,23 +8,23 @@ Nette Documentation Introduction ------------ -- [Why Use Nette?|www:10-reasons-why-nette] -- [Installation] -- [Create Your First Application! |quickstart:] +- 🤔 [Why Use Nette?|www:10-reasons-why-nette] +- 📥 [Installation] +- 🚀 [Create Your First Application! |quickstart:] General ------- -- [List of Packages |www:packages] -- [Maintenance and PHP Versions |www:maintenance] -- [Release Notes |https://nette.org/releases] -- [Upgrade Guide |migrations:] -- [nette:Troubleshooting] -- [Who Creates Nette |https://nette.org/contributors] -- [History of Nette |www:history] -- [Get Involved |contributing:] -- [Sponsor Development |https://nette.org/en/donate] -- [API Reference |https://api.nette.org/] +- 📚 [List of Packages |www:packages] +- 🔧 [Maintenance and PHP Versions |www:maintenance] +- 📰 [Release Notes |https://nette.org/releases] +- ⬆️ [Upgrade Guide |migrations:] +- 🆘 [nette:Troubleshooting] +- 👥 [Who Creates Nette |https://nette.org/contributors] +- 📜 [History of Nette |www:history] +- 🤝 [Get Involved |contributing:] +- ❤️ [Sponsor Development |https://nette.org/en/donate] +- 📖 [API Reference |https://api.nette.org/] </div> @@ -33,18 +33,18 @@ General Nette Application ----------------- -- [How do Applications Work? |application:how-it-works] -- [application:Bootstrapping] -- [application:Presenters] -- [application:Templates] -- [Directory Structure |application:directory-structure] -- [application:Routing] -- [Creating URL Links |application:creating-links] -- [Interactive Components |application:components] -- [AJAX & Snippets |application:ajax] - - -- [Tutorials and Best Practices |best-practices:] +- 🧭 [How do Applications Work? |application:how-it-works] +- 🥾 [application:Bootstrapping] +- 🎬 [application:Presenters] +- 📄 [application:Templates] +- 📁 [Directory Structure |application:directory-structure] +- 🗺️ [application:Routing] +- 🔗 [Creating URL Links |application:creating-links] +- 🎛️ [Interactive Components |application:components] +- 📡 [AJAX & Snippets |application:ajax] + + +- 🎓 [Tutorials and Best Practices |best-practices:] </div> @@ -53,22 +53,22 @@ Nette Application Main Topics ----------- -- [Configuration |nette:configuring] -- [Dependency Injection|dependency-injection:] -- [Latte: Templates |latte:] -- [Tracy: Debugging Tool |tracy:] -- [Forms|forms:] -- [Database |database:guide] -- [Authenticating Users |security:authentication] -- [Access Control |security:authorization] -- [Sessions |http:Sessions] -- [HTTP Request & Response|http:] -- [Assets |assets:] -- [Caching |caching:] -- [Sending Emails |mail:] -- [Schema: Data Validation |schema:] -- [PHP Code Generator |php-generator:] -- [Tester: Unit Testing |tester:] +- ⚙️ [Configuration |nette:configuring] +- 🧩 [Dependency Injection|dependency-injection:] +- ☕ [Latte: Templates |latte:] +- 🐞 [Tracy: Debugging Tool |tracy:] +- 📝 [Forms|forms:] +- 🗄️ [Database |database:guide] +- 🪪 [Authenticating Users |security:authentication] +- 🛡️ [Access Control |security:authorization] +- 🍪 [Sessions |http:Sessions] +- 🌐 [HTTP Request & Response|http:] +- 📦 [Assets |assets:] +- ⚡ [Caching |caching:] +- ✉️ [Sending Emails |mail:] +- 📐 [Schema: Data Validation |schema:] +- 🛠️ [PHP Code Generator |php-generator:] +- 🧪 [Tester: Unit Testing |tester:] </div> @@ -77,20 +77,20 @@ Main Topics Utilities --------- -- [utils:Arrays] -- [Filesystem |utils:filesystem] -- [Finder |utils:finder] -- [utils:HTML Elements] -- [utils:Images] -- [utils:JSON] -- [NEON|neon:] -- [Password Hashing |security:passwords] -- [PHP Types |utils:type] -- [utils:Strings] -- [Validators |utils:validators] -- [RobotLoader |robot-loader:] -- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] -- [SafeStream |safe-stream:] +- 🧮 [utils:Arrays] +- 💾 [Filesystem |utils:filesystem] +- 🔎 [Finder |utils:finder] +- 🏷️ [utils:HTML Elements] +- 🖼️ [utils:Images] +- 📋 [utils:JSON] +- 💡 [NEON|neon:] +- 🔐 [Password Hashing |security:passwords] +- 🐘 [PHP Types |utils:type] +- 🧵 [utils:Strings] +- ✅ [Validators |utils:validators] +- 🤖 [RobotLoader |robot-loader:] +- 🧠 [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] +- 🛟 [SafeStream |safe-stream:] - [...others |utils:] </div> diff --git a/nette/es/@home.texy b/nette/es/@home.texy index 09e8c28881..87b7cba584 100644 --- a/nette/es/@home.texy +++ b/nette/es/@home.texy @@ -8,23 +8,23 @@ Documentación de Nette Introducción ------------ -- [¿Por qué usar Nette? |www:10-reasons-why-nette] -- [Instalación |installation] -- [¡Escribamos nuestra primera aplicación! |quickstart:] +- 🤔 [¿Por qué usar Nette? |www:10-reasons-why-nette] +- 📥 [Instalación |installation] +- 🚀 [¡Escribamos nuestra primera aplicación! |quickstart:] General ------- -- [Lista de paquetes |www:packages] -- [Mantenimiento y versiones de PHP |www:maintenance] -- [Release Notes |https://nette.org/releases] -- [Migración a versiones más recientes|migrations:en] -- [Solución de problemas |nette:troubleshooting] -- [Quién hace Nette |https://nette.org/contributors] -- [Historia de Nette |www:history] -- [Participa |contributing:] -- [Apoya el desarrollo |https://nette.org/cs/donate] -- [Referencia API |https://api.nette.org/] +- 📚 [Lista de paquetes |www:packages] +- 🔧 [Mantenimiento y versiones de PHP |www:maintenance] +- 📰 [Release Notes |https://nette.org/releases] +- ⬆️ [Migración a versiones más recientes|migrations:en] +- 🆘 [Solución de problemas |nette:troubleshooting] +- 👥 [Quién hace Nette |https://nette.org/contributors] +- 📜 [Historia de Nette |www:history] +- 🤝 [Participa |contributing:] +- ❤️ [Apoya el desarrollo |https://nette.org/cs/donate] +- 📖 [Referencia API |https://api.nette.org/] </div> @@ -33,18 +33,18 @@ General Aplicaciones en Nette --------------------- -- [¿Cómo funcionan las aplicaciones? |application:how-it-works] -- [application:Bootstrapping] -- [Presenters |application:presenters] -- [Plantillas |application:templates] -- [Estructura de directorios |application:directory-structure] -- [Enrutamiento |application:routing] -- [Creación de enlaces URL |application:creating-links] -- [Componentes interactivos |application:components] -- [AJAX y snippets |application:ajax] - - -- [Tutoriales y mejores prácticas |best-practices:] +- 🧭 [¿Cómo funcionan las aplicaciones? |application:how-it-works] +- 🥾 [application:Bootstrapping] +- 🎬 [Presenters |application:presenters] +- 📄 [Plantillas |application:templates] +- 📁 [Estructura de directorios |application:directory-structure] +- 🗺️ [Enrutamiento |application:routing] +- 🔗 [Creación de enlaces URL |application:creating-links] +- 🎛️ [Componentes interactivos |application:components] +- 📡 [AJAX y snippets |application:ajax] + + +- 🎓 [Tutoriales y mejores prácticas |best-practices:] </div> @@ -53,22 +53,22 @@ Aplicaciones en Nette Temas principales ----------------- -- [Configuración |nette:configuring] -- [Inyección de Dependencias|dependency-injection:] -- [Latte: plantillas |latte:] -- [Tracy: depuración de código |tracy:] -- [Formularios |forms:] -- [Base de datos |database:guide] -- [Inicio de sesión de usuarios |security:authentication] -- [Verificación de permisos |security:authorization] -- [http:Sessions] -- [Petición y respuesta HTTP|http:] -- [Activos |assets:] -- [Caché |caching:] -- [Envío de correos electrónicos |mail:] -- [Schema: validación de datos |schema:] -- [Generador de código PHP |php-generator:] -- [Tester: pruebas |tester:] +- ⚙️ [Configuración |nette:configuring] +- 🧩 [Inyección de Dependencias|dependency-injection:] +- ☕ [Latte: plantillas |latte:] +- 🐞 [Tracy: depuración de código |tracy:] +- 📝 [Formularios |forms:] +- 🗄️ [Base de datos |database:guide] +- 🪪 [Inicio de sesión de usuarios |security:authentication] +- 🛡️ [Verificación de permisos |security:authorization] +- 🍪 [http:Sessions] +- 🌐 [Petición y respuesta HTTP|http:] +- 📦 [Activos |assets:] +- ⚡ [Caché |caching:] +- ✉️ [Envío de correos electrónicos |mail:] +- 📐 [Schema: validación de datos |schema:] +- 🛠️ [Generador de código PHP |php-generator:] +- 🧪 [Tester: pruebas |tester:] </div> @@ -77,20 +77,20 @@ Temas principales Utilidades ---------- -- [Arrays |utils:arrays] -- [Sistema de archivos |utils:filesystem] -- [Finder |utils:finder] -- [Elementos HTML |utils:html-elements] -- [Imágenes |utils:images] -- [utils:JSON] -- [NEON|neon:] -- [Hashing de contraseñas |security:passwords] -- [Tipos PHP |utils:type] -- [Cadenas |utils:strings] -- [Validadores |utils:validators] -- [RobotLoader |robot-loader:] -- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] -- [SafeStream |safe-stream:] +- 🧮 [Arrays |utils:arrays] +- 💾 [Sistema de archivos |utils:filesystem] +- 🔎 [Finder |utils:finder] +- 🏷️ [Elementos HTML |utils:html-elements] +- 🖼️ [Imágenes |utils:images] +- 📋 [utils:JSON] +- 💡 [NEON|neon:] +- 🔐 [Hashing de contraseñas |security:passwords] +- 🐘 [Tipos PHP |utils:type] +- 🧵 [Cadenas |utils:strings] +- ✅ [Validadores |utils:validators] +- 🤖 [RobotLoader |robot-loader:] +- 🧠 [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] +- 🛟 [SafeStream |safe-stream:] - [...más |utils:] </div> diff --git a/nette/fr/@home.texy b/nette/fr/@home.texy index d1e0fd5d94..308cba0545 100644 --- a/nette/fr/@home.texy +++ b/nette/fr/@home.texy @@ -8,23 +8,23 @@ Documentation Nette Introduction ------------ -- [Pourquoi utiliser Nette ? |www:10-reasons-why-nette] -- [Installation |installation] -- [Écrivons notre première application ! |quickstart:] +- 🤔 [Pourquoi utiliser Nette ? |www:10-reasons-why-nette] +- 📥 [Installation |installation] +- 🚀 [Écrivons notre première application ! |quickstart:] Général ------- -- [Liste des paquets |www:packages] -- [Maintenance et versions PHP |www:maintenance] -- [Notes de version |https://nette.org/releases] -- [Passer aux versions plus récentes|migrations:en] -- [Résolution de problèmes |nette:troubleshooting] -- [Qui fait Nette |https://nette.org/contributors] -- [Histoire de Nette |www:history] -- [Contribuer |contributing:] -- [Soutenir le développement |https://nette.org/fr/donate] -- [Référence API |https://api.nette.org/] +- 📚 [Liste des paquets |www:packages] +- 🔧 [Maintenance et versions PHP |www:maintenance] +- 📰 [Notes de version |https://nette.org/releases] +- ⬆️ [Passer aux versions plus récentes|migrations:en] +- 🆘 [Résolution de problèmes |nette:troubleshooting] +- 👥 [Qui fait Nette |https://nette.org/contributors] +- 📜 [Histoire de Nette |www:history] +- 🤝 [Contribuer |contributing:] +- ❤️ [Soutenir le développement |https://nette.org/fr/donate] +- 📖 [Référence API |https://api.nette.org/] </div> @@ -33,18 +33,18 @@ Général Applications Nette ------------------ -- [Comment fonctionnent les applications ? |application:how-it-works] -- [application:Bootstrapping] -- [Presenters |application:presenters] -- [Templates |application:templates] -- [Structure des répertoires |application:directory-structure] -- [Routage |application:routing] -- [Création de liens URL |application:creating-links] -- [Composants interactifs |application:components] -- [AJAX & snippets |application:ajax] - - -- [Tutoriels et bonnes pratiques |best-practices:] +- 🧭 [Comment fonctionnent les applications ? |application:how-it-works] +- 🥾 [application:Bootstrapping] +- 🎬 [Presenters |application:presenters] +- 📄 [Templates |application:templates] +- 📁 [Structure des répertoires |application:directory-structure] +- 🗺️ [Routage |application:routing] +- 🔗 [Création de liens URL |application:creating-links] +- 🎛️ [Composants interactifs |application:components] +- 📡 [AJAX & snippets |application:ajax] + + +- 🎓 [Tutoriels et bonnes pratiques |best-practices:] </div> @@ -53,22 +53,22 @@ Applications Nette Sujets principaux ----------------- -- [Configuration |nette:configuring] -- [Injection de dépendances|dependency-injection:] -- [Latte : templates |latte:] -- [Tracy : débogage de code |tracy:] -- [Formulaires |forms:] -- [Base de données |database:guide] -- [Connexion des utilisateurs |security:authentication] -- [Vérification des autorisations |security:authorization] -- [http:Sessions] -- [Requête & réponse HTTP|http:] -- [Actifs |assets:] -- [Cache |caching:] -- [Envoi d'e-mails |mail:] -- [Schema : validation de données |schema:] -- [Générateur de code PHP |php-generator:] -- [Tester : tests |tester:] +- ⚙️ [Configuration |nette:configuring] +- 🧩 [Injection de dépendances|dependency-injection:] +- ☕ [Latte : templates |latte:] +- 🐞 [Tracy : débogage de code |tracy:] +- 📝 [Formulaires |forms:] +- 🗄️ [Base de données |database:guide] +- 🪪 [Connexion des utilisateurs |security:authentication] +- 🛡️ [Vérification des autorisations |security:authorization] +- 🍪 [http:Sessions] +- 🌐 [Requête & réponse HTTP|http:] +- 📦 [Actifs |assets:] +- ⚡ [Cache |caching:] +- ✉️ [Envoi d'e-mails |mail:] +- 📐 [Schema : validation de données |schema:] +- 🛠️ [Générateur de code PHP |php-generator:] +- 🧪 [Tester : tests |tester:] </div> @@ -77,20 +77,20 @@ Sujets principaux Utilitaires ----------- -- [Tableaux |utils:arrays] -- [Système de fichiers |utils:filesystem] -- [Finder |utils:finder] -- [Éléments HTML |utils:html-elements] -- [Images |utils:images] -- [utils:JSON] -- [NEON|neon:] -- [Hachage de mots de passe |security:passwords] -- [Types PHP |utils:type] -- [Chaînes de caractères |utils:strings] -- [Validateurs |utils:validators] -- [RobotLoader |robot-loader:] -- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] -- [SafeStream |safe-stream:] +- 🧮 [Tableaux |utils:arrays] +- 💾 [Système de fichiers |utils:filesystem] +- 🔎 [Finder |utils:finder] +- 🏷️ [Éléments HTML |utils:html-elements] +- 🖼️ [Images |utils:images] +- 📋 [utils:JSON] +- 💡 [NEON|neon:] +- 🔐 [Hachage de mots de passe |security:passwords] +- 🐘 [Types PHP |utils:type] +- 🧵 [Chaînes de caractères |utils:strings] +- ✅ [Validateurs |utils:validators] +- 🤖 [RobotLoader |robot-loader:] +- 🧠 [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] +- 🛟 [SafeStream |safe-stream:] - [...autres |utils:] </div> diff --git a/nette/hu/@home.texy b/nette/hu/@home.texy index 4a115c9ffd..17186e62a8 100644 --- a/nette/hu/@home.texy +++ b/nette/hu/@home.texy @@ -8,23 +8,23 @@ Nette Dokumentáció Ismerkedés ---------- -- [Miért használja a Nette-t? |www:10-reasons-why-nette] -- [Telepítés |installation] -- [Írjuk meg az első alkalmazást! |quickstart:] +- 🤔 [Miért használja a Nette-t? |www:10-reasons-why-nette] +- 📥 [Telepítés |installation] +- 🚀 [Írjuk meg az első alkalmazást! |quickstart:] Általános --------- -- [Csomagok listája |www:packages] -- [Karbantartás és PHP verziók |www:maintenance] -- [Kiadási megjegyzések |https://nette.org/releases] -- [Frissítés újabb verziókra|migrations:en] -- [Hibaelhárítás |nette:troubleshooting] -- [Ki alkotja a Nette-t |https://nette.org/contributors] -- [A Nette története |www:history] -- [Csatlakozzon |contributing:] -- [Támogassa a fejlesztést |https://nette.org/cs/donate] -- [API referencia |https://api.nette.org/] +- 📚 [Csomagok listája |www:packages] +- 🔧 [Karbantartás és PHP verziók |www:maintenance] +- 📰 [Kiadási megjegyzések |https://nette.org/releases] +- ⬆️ [Frissítés újabb verziókra|migrations:en] +- 🆘 [Hibaelhárítás |nette:troubleshooting] +- 👥 [Ki alkotja a Nette-t |https://nette.org/contributors] +- 📜 [A Nette története |www:history] +- 🤝 [Csatlakozzon |contributing:] +- ❤️ [Támogassa a fejlesztést |https://nette.org/cs/donate] +- 📖 [API referencia |https://api.nette.org/] </div> @@ -33,18 +33,18 @@ Ismerkedés Nette alkalmazások ------------------ -- [Hogyan működnek az alkalmazások? |application:how-it-works] -- [Bootstrapping |application:Bootstrapping] -- [Presenterek |application:presenters] -- [Sablonok |application:templates] -- [Könyvtárstruktúra |application:directory-structure] -- [Útválasztás |application:routing] -- [URL linkek létrehozása |application:creating-links] -- [Interaktív komponensek |application:components] -- [AJAX & Snippetek |application:ajax] - - -- [Útmutatók és eljárások |best-practices:] +- 🧭 [Hogyan működnek az alkalmazások? |application:how-it-works] +- 🥾 [Bootstrapping |application:Bootstrapping] +- 🎬 [Presenterek |application:presenters] +- 📄 [Sablonok |application:templates] +- 📁 [Könyvtárstruktúra |application:directory-structure] +- 🗺️ [Útválasztás |application:routing] +- 🔗 [URL linkek létrehozása |application:creating-links] +- 🎛️ [Interaktív komponensek |application:components] +- 📡 [AJAX & Snippetek |application:ajax] + + +- 🎓 [Útmutatók és eljárások |best-practices:] </div> @@ -53,22 +53,22 @@ Nette alkalmazások Fő témák -------- -- [Konfiguráció |nette:configuring] -- [Dependency Injection|dependency-injection:] -- [Latte: sablonok |latte:] -- [Tracy: kód debuggolás |tracy:] -- [Űrlapok |forms:] -- [Adatbázis |database:guide] -- [Felhasználói bejelentkezés |security:authentication] -- [Jogosultság ellenőrzés |security:authorization] -- [Munkamenetek |http:Sessions] -- [HTTP kérés & válasz|http:] -- [Eszközök |assets:] -- [Cache |caching:] -- [E-mailek küldése |mail:] -- [Schema: adat validáció |schema:] -- [PHP kód generátor |php-generator:] -- [Tester: tesztelés |tester:] +- ⚙️ [Konfiguráció |nette:configuring] +- 🧩 [Dependency Injection|dependency-injection:] +- ☕ [Latte: sablonok |latte:] +- 🐞 [Tracy: kód debuggolás |tracy:] +- 📝 [Űrlapok |forms:] +- 🗄️ [Adatbázis |database:guide] +- 🪪 [Felhasználói bejelentkezés |security:authentication] +- 🛡️ [Jogosultság ellenőrzés |security:authorization] +- 🍪 [Munkamenetek |http:Sessions] +- 🌐 [HTTP kérés & válasz|http:] +- 📦 [Eszközök |assets:] +- ⚡ [Cache |caching:] +- ✉️ [E-mailek küldése |mail:] +- 📐 [Schema: adat validáció |schema:] +- 🛠️ [PHP kód generátor |php-generator:] +- 🧪 [Tester: tesztelés |tester:] </div> @@ -77,20 +77,20 @@ Fő témák Utilities --------- -- [Tömbök |utils:arrays] -- [Fájlrendszer |utils:filesystem] -- [Finder |utils:finder] -- [HTML elemek |utils:html-elements] -- [Képek |utils:images] -- [JSON |utils:JSON] -- [NEON|neon:] -- [Jelszó hashelés |security:passwords] -- [PHP típusok |utils:type] -- [Stringek |utils:strings] -- [Validátorok |utils:validators] -- [RobotLoader |robot-loader:] -- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] -- [SafeStream |safe-stream:] +- 🧮 [Tömbök |utils:arrays] +- 💾 [Fájlrendszer |utils:filesystem] +- 🔎 [Finder |utils:finder] +- 🏷️ [HTML elemek |utils:html-elements] +- 🖼️ [Képek |utils:images] +- 📋 [JSON |utils:JSON] +- 💡 [NEON|neon:] +- 🔐 [Jelszó hashelés |security:passwords] +- 🐘 [PHP típusok |utils:type] +- 🧵 [Stringek |utils:strings] +- ✅ [Validátorok |utils:validators] +- 🤖 [RobotLoader |robot-loader:] +- 🧠 [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] +- 🛟 [SafeStream |safe-stream:] - [...továbbiak |utils:] </div> diff --git a/nette/it/@home.texy b/nette/it/@home.texy index 44b674e5d2..83005d95ce 100644 --- a/nette/it/@home.texy +++ b/nette/it/@home.texy @@ -8,23 +8,23 @@ Documentazione Nette Introduzione ------------ -- [Perché usare Nette? |www:10-reasons-why-nette] -- [Installazione |nette:installation] -- [Scriviamo la prima applicazione! |quickstart:] +- 🤔 [Perché usare Nette? |www:10-reasons-why-nette] +- 📥 [Installazione |nette:installation] +- 🚀 [Scriviamo la prima applicazione! |quickstart:] Generale -------- -- [Elenco dei pacchetti |www:packages] -- [Manutenzione e versioni PHP |www:maintenance] -- [Note di rilascio |https://nette.org/releases] -- [Passaggio a versioni più recenti|migrations:en] -- [Risoluzione dei problemi |nette:troubleshooting] -- [Chi crea Nette |https://nette.org/contributors] -- [Storia di Nette |www:history] -- [Partecipa |contributing:] -- [Sostieni lo sviluppo |https://nette.org/cs/donate] -- [Riferimento API |https://api.nette.org/] +- 📚 [Elenco dei pacchetti |www:packages] +- 🔧 [Manutenzione e versioni PHP |www:maintenance] +- 📰 [Note di rilascio |https://nette.org/releases] +- ⬆️ [Passaggio a versioni più recenti|migrations:en] +- 🆘 [Risoluzione dei problemi |nette:troubleshooting] +- 👥 [Chi crea Nette |https://nette.org/contributors] +- 📜 [Storia di Nette |www:history] +- 🤝 [Partecipa |contributing:] +- ❤️ [Sostieni lo sviluppo |https://nette.org/cs/donate] +- 📖 [Riferimento API |https://api.nette.org/] </div> @@ -33,18 +33,18 @@ Generale Applicazioni in Nette --------------------- -- [Come funzionano le applicazioni? |application:how-it-works] -- [Bootstrapping |application:Bootstrapping] -- [Presenter |application:presenters] -- [Template |application:templates] -- [Struttura delle directory |application:directory-structure] -- [Routing |application:routing] -- [Creazione di link URL |application:creating-links] -- [Componenti interattivi |application:components] -- [AJAX & snippet |application:ajax] - - -- [Guide e procedure |best-practices:] +- 🧭 [Come funzionano le applicazioni? |application:how-it-works] +- 🥾 [Bootstrapping |application:Bootstrapping] +- 🎬 [Presenter |application:presenters] +- 📄 [Template |application:templates] +- 📁 [Struttura delle directory |application:directory-structure] +- 🗺️ [Routing |application:routing] +- 🔗 [Creazione di link URL |application:creating-links] +- 🎛️ [Componenti interattivi |application:components] +- 📡 [AJAX & snippet |application:ajax] + + +- 🎓 [Guide e procedure |best-practices:] </div> @@ -53,22 +53,22 @@ Applicazioni in Nette Argomenti principali -------------------- -- [Configurazione |nette:configuring] -- [Dependency Injection|dependency-injection:] -- [Latte: template |latte:] -- [Tracy: debug del codice |tracy:] -- [Form |forms:] -- [Database |database:guide] -- [Login degli utenti |security:authentication] -- [Verifica delle autorizzazioni |security:authorization] -- [Sessioni |http:sessions] -- [HTTP request & response|http:] -- [Attività |assets:] -- [Cache |caching:] -- [Invio di e-mail |mail:] -- [Schema: validazione dei dati |schema:] -- [Generatore di codice PHP |php-generator:] -- [Tester: testing |tester:] +- ⚙️ [Configurazione |nette:configuring] +- 🧩 [Dependency Injection|dependency-injection:] +- ☕ [Latte: template |latte:] +- 🐞 [Tracy: debug del codice |tracy:] +- 📝 [Form |forms:] +- 🗄️ [Database |database:guide] +- 🪪 [Login degli utenti |security:authentication] +- 🛡️ [Verifica delle autorizzazioni |security:authorization] +- 🍪 [Sessioni |http:sessions] +- 🌐 [HTTP request & response|http:] +- 📦 [Attività |assets:] +- ⚡ [Cache |caching:] +- ✉️ [Invio di e-mail |mail:] +- 📐 [Schema: validazione dei dati |schema:] +- 🛠️ [Generatore di codice PHP |php-generator:] +- 🧪 [Tester: testing |tester:] </div> @@ -77,20 +77,20 @@ Argomenti principali Utilities --------- -- [Array |utils:arrays] -- [File system |utils:filesystem] -- [Finder |utils:finder] -- [Elementi HTML |utils:html-elements] -- [Immagini |utils:images] -- [JSON |utils:JSON] -- [NEON|neon:] -- [Hashing delle password |security:passwords] -- [Tipi PHP |utils:type] -- [Stringhe |utils:strings] -- [Validatori |utils:validators] -- [RobotLoader |robot-loader:] -- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] -- [SafeStream |safe-stream:] +- 🧮 [Array |utils:arrays] +- 💾 [File system |utils:filesystem] +- 🔎 [Finder |utils:finder] +- 🏷️ [Elementi HTML |utils:html-elements] +- 🖼️ [Immagini |utils:images] +- 📋 [JSON |utils:JSON] +- 💡 [NEON|neon:] +- 🔐 [Hashing delle password |security:passwords] +- 🐘 [Tipi PHP |utils:type] +- 🧵 [Stringhe |utils:strings] +- ✅ [Validatori |utils:validators] +- 🤖 [RobotLoader |robot-loader:] +- 🧠 [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] +- 🛟 [SafeStream |safe-stream:] - [...altro |utils:] </div> diff --git a/nette/ja/@home.texy b/nette/ja/@home.texy index dd2a680ec0..8d96f0d111 100644 --- a/nette/ja/@home.texy +++ b/nette/ja/@home.texy @@ -8,23 +8,23 @@ Netteドキュメント はじめに ---- -- [なぜNetteを使うのか? |www:10-reasons-why-nette] -- [インストール |nette:installation] -- [最初のアプリケーションを作成しましょう! |quickstart:] +- 🤔 [なぜNetteを使うのか? |www:10-reasons-why-nette] +- 📥 [インストール |nette:installation] +- 🚀 [最初のアプリケーションを作成しましょう! |quickstart:] 一般 ------ -- [パッケージリスト |www:packages] -- [メンテナンスとPHPバージョン |www:maintenance] -- [リリースノート |https://nette.org/releases] -- [新しいバージョンへの移行|migrations:en] -- [トラブルシューティング |nette:troubleshooting] -- [Netteを作成しているのは誰か |https://nette.org/contributors] -- [Netteの歴史 |www:history] -- [貢献する |contributing:] -- [開発を支援する |https://nette.org/cs/donate] -- [APIリファレンス |https://api.nette.org/] +- 📚 [パッケージリスト |www:packages] +- 🔧 [メンテナンスとPHPバージョン |www:maintenance] +- 📰 [リリースノート |https://nette.org/releases] +- ⬆️ [新しいバージョンへの移行|migrations:en] +- 🆘 [トラブルシューティング |nette:troubleshooting] +- 👥 [Netteを作成しているのは誰か |https://nette.org/contributors] +- 📜 [Netteの歴史 |www:history] +- 🤝 [貢献する |contributing:] +- ❤️ [開発を支援する |https://nette.org/cs/donate] +- 📖 [APIリファレンス |https://api.nette.org/] </div> @@ -33,18 +33,18 @@ Netteドキュメント Nette のアプリケーション --------------- -- [アプリケーションはどのように動作しますか? |application:how-it-works] -- [Bootstrapping |application:Bootstrapping] -- [Presenter |application:presenters] -- [テンプレート |application:templates] -- [ディレクトリ構造 |application:directory-structure] -- [ルーティング |application:routing] -- [URLリンクの作成 |application:creating-links] -- [インタラクティブコンポーネント |application:components] -- [AJAX とスニペット |application:ajax] - - -- [ガイドとベストプラクティス |best-practices:] +- 🧭 [アプリケーションはどのように動作しますか? |application:how-it-works] +- 🥾 [Bootstrapping |application:Bootstrapping] +- 🎬 [Presenter |application:presenters] +- 📄 [テンプレート |application:templates] +- 📁 [ディレクトリ構造 |application:directory-structure] +- 🗺️ [ルーティング |application:routing] +- 🔗 [URLリンクの作成 |application:creating-links] +- 🎛️ [インタラクティブコンポーネント |application:components] +- 📡 [AJAX とスニペット |application:ajax] + + +- 🎓 [ガイドとベストプラクティス |best-practices:] </div> @@ -53,22 +53,22 @@ Nette のアプリケーション 主要なトピック ------- -- [設定 |nette:configuring] -- [依存関係注入|dependency-injection:] -- [Latte: テンプレート |latte:] -- [Tracy: コードデバッグ |tracy:] -- [フォーム |forms:] -- [データベース |database:guide] -- [ユーザーログイン |security:authentication] -- [権限の検証 |security:authorization] -- [セッション |http:Sessions] -- [HTTP リクエストとレスポンス|http:] -- [資産 |assets:] -- [キャッシュ |caching:] -- [メールの送信 |mail:] -- [Schema: データ検証 |schema:] -- [PHP コードジェネレータ |php-generator:] -- [Tester: テスト |tester:] +- ⚙️ [設定 |nette:configuring] +- 🧩 [依存関係注入|dependency-injection:] +- ☕ [Latte: テンプレート |latte:] +- 🐞 [Tracy: コードデバッグ |tracy:] +- 📝 [フォーム |forms:] +- 🗄️ [データベース |database:guide] +- 🪪 [ユーザーログイン |security:authentication] +- 🛡️ [権限の検証 |security:authorization] +- 🍪 [セッション |http:Sessions] +- 🌐 [HTTP リクエストとレスポンス|http:] +- 📦 [資産 |assets:] +- ⚡ [キャッシュ |caching:] +- ✉️ [メールの送信 |mail:] +- 📐 [Schema: データ検証 |schema:] +- 🛠️ [PHP コードジェネレータ |php-generator:] +- 🧪 [Tester: テスト |tester:] </div> @@ -77,20 +77,20 @@ Nette のアプリケーション ユーティリティ ------- -- [配列 |utils:arrays] -- [ファイルシステム |utils:filesystem] -- [Finder |utils:finder] -- [HTML 要素 |utils:html-elements] -- [画像 |utils:images] -- [JSON |utils:JSON] -- [NEON|neon:] -- [パスワードハッシュ化 |security:passwords] -- [PHP 型 |utils:type] -- [文字列 |utils:strings] -- [バリデータ |utils:validators] -- [RobotLoader |robot-loader:] -- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] -- [SafeStream |safe-stream:] +- 🧮 [配列 |utils:arrays] +- 💾 [ファイルシステム |utils:filesystem] +- 🔎 [Finder |utils:finder] +- 🏷️ [HTML 要素 |utils:html-elements] +- 🖼️ [画像 |utils:images] +- 📋 [JSON |utils:JSON] +- 💡 [NEON|neon:] +- 🔐 [パスワードハッシュ化 |security:passwords] +- 🐘 [PHP 型 |utils:type] +- 🧵 [文字列 |utils:strings] +- ✅ [バリデータ |utils:validators] +- 🤖 [RobotLoader |robot-loader:] +- 🧠 [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] +- 🛟 [SafeStream |safe-stream:] - [...その他 |utils:] </div> diff --git a/nette/pl/@home.texy b/nette/pl/@home.texy index 1ce827904d..c698bbb4ef 100644 --- a/nette/pl/@home.texy +++ b/nette/pl/@home.texy @@ -8,23 +8,23 @@ Dokumentacja Nette Wprowadzenie ------------ -- [Dlaczego używać Nette? |www:10-reasons-why-nette] -- [Instalacja |installation] -- [Pisanie pierwszej aplikacji! |quickstart:] +- 🤔 [Dlaczego używać Nette? |www:10-reasons-why-nette] +- 📥 [Instalacja |installation] +- 🚀 [Pisanie pierwszej aplikacji! |quickstart:] Ogólne ------ -- [Lista pakietów |www:packages] -- [Utrzymanie i wersje PHP |www:maintenance] -- [Informacje o wydaniu |https://nette.org/releases] -- [Migracja do nowszych wersji|migrations:en] -- [Rozwiązywanie problemów |nette:troubleshooting] -- [Kto tworzy Nette |https://nette.org/contributors] -- [Historia Nette |www:history] -- [Zaangażuj się |contributing:] -- [Wspieraj rozwój |https://nette.org/cs/donate] -- [Referencja API |https://api.nette.org/] +- 📚 [Lista pakietów |www:packages] +- 🔧 [Utrzymanie i wersje PHP |www:maintenance] +- 📰 [Informacje o wydaniu |https://nette.org/releases] +- ⬆️ [Migracja do nowszych wersji|migrations:en] +- 🆘 [Rozwiązywanie problemów |nette:troubleshooting] +- 👥 [Kto tworzy Nette |https://nette.org/contributors] +- 📜 [Historia Nette |www:history] +- 🤝 [Zaangażuj się |contributing:] +- ❤️ [Wspieraj rozwój |https://nette.org/cs/donate] +- 📖 [Referencja API |https://api.nette.org/] </div> @@ -33,18 +33,18 @@ Ogólne Aplikacje w Nette ----------------- -- [Jak działają aplikacje? |application:how-it-works] -- [Bootstrapping |application:Bootstrapping] -- [Presentery |application:presenters] -- [Szablony |application:templates] -- [Struktura katalogów |application:directory-structure] -- [Routing |application:routing] -- [Tworzenie linków URL |application:creating-links] -- [Komponenty interaktywne |application:components] -- [AJAX & snippety |application:ajax] - - -- [Poradniki i najlepsze praktyki |best-practices:] +- 🧭 [Jak działają aplikacje? |application:how-it-works] +- 🥾 [Bootstrapping |application:Bootstrapping] +- 🎬 [Presentery |application:presenters] +- 📄 [Szablony |application:templates] +- 📁 [Struktura katalogów |application:directory-structure] +- 🗺️ [Routing |application:routing] +- 🔗 [Tworzenie linków URL |application:creating-links] +- 🎛️ [Komponenty interaktywne |application:components] +- 📡 [AJAX & snippety |application:ajax] + + +- 🎓 [Poradniki i najlepsze praktyki |best-practices:] </div> @@ -53,22 +53,22 @@ Aplikacje w Nette Główne tematy ------------- -- [Konfiguracja |nette:configuring] -- [Wstrzykiwanie zależności|dependency-injection:] -- [Latte: szablony |latte:] -- [Tracy: debugowanie kodu |tracy:] -- [Formularze |forms:] -- [Baza danych |database:guide] -- [Logowanie użytkowników |security:authentication] -- [Weryfikacja uprawnień |security:authorization] -- [Sesje |http:Sessions] -- [Żądanie i odpowiedź HTTP|http:] -- [Aktywa |assets:] -- [Cache |caching:] -- [Wysyłanie e-maili |mail:] -- [Schema: walidacja danych |schema:] -- [Generator kodu PHP |php-generator:] -- [Tester: testowanie |tester:] +- ⚙️ [Konfiguracja |nette:configuring] +- 🧩 [Wstrzykiwanie zależności|dependency-injection:] +- ☕ [Latte: szablony |latte:] +- 🐞 [Tracy: debugowanie kodu |tracy:] +- 📝 [Formularze |forms:] +- 🗄️ [Baza danych |database:guide] +- 🪪 [Logowanie użytkowników |security:authentication] +- 🛡️ [Weryfikacja uprawnień |security:authorization] +- 🍪 [Sesje |http:Sessions] +- 🌐 [Żądanie i odpowiedź HTTP|http:] +- 📦 [Aktywa |assets:] +- ⚡ [Cache |caching:] +- ✉️ [Wysyłanie e-maili |mail:] +- 📐 [Schema: walidacja danych |schema:] +- 🛠️ [Generator kodu PHP |php-generator:] +- 🧪 [Tester: testowanie |tester:] </div> @@ -77,20 +77,20 @@ Główne tematy Narzędzia --------- -- [Tablice |utils:arrays] -- [System plików |utils:filesystem] -- [Finder |utils:finder] -- [Elementy HTML |utils:html-elements] -- [Obrazy |utils:images] -- [JSON |utils:JSON] -- [NEON|neon:] -- [Haszowanie haseł |security:passwords] -- [Typy PHP |utils:type] -- [Ciągi znaków |utils:strings] -- [Walidatory |utils:validators] -- [RobotLoader |robot-loader:] -- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] -- [SafeStream |safe-stream:] +- 🧮 [Tablice |utils:arrays] +- 💾 [System plików |utils:filesystem] +- 🔎 [Finder |utils:finder] +- 🏷️ [Elementy HTML |utils:html-elements] +- 🖼️ [Obrazy |utils:images] +- 📋 [JSON |utils:JSON] +- 💡 [NEON|neon:] +- 🔐 [Haszowanie haseł |security:passwords] +- 🐘 [Typy PHP |utils:type] +- 🧵 [Ciągi znaków |utils:strings] +- ✅ [Walidatory |utils:validators] +- 🤖 [RobotLoader |robot-loader:] +- 🧠 [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] +- 🛟 [SafeStream |safe-stream:] - [...więcej |utils:] </div> diff --git a/nette/pt/@home.texy b/nette/pt/@home.texy index 68e4ef34e2..10aa8abd8b 100644 --- a/nette/pt/@home.texy +++ b/nette/pt/@home.texy @@ -8,23 +8,23 @@ Documentação Nette Introdução ---------- -- [Por que usar Nette? |www:10-reasons-why-nette] -- [Instalação |installation] -- [Escrevendo a primeira aplicação! |quickstart:] +- 🤔 [Por que usar Nette? |www:10-reasons-why-nette] +- 📥 [Instalação |installation] +- 🚀 [Escrevendo a primeira aplicação! |quickstart:] Geral ----- -- [Lista de pacotes |www:packages] -- [Manutenção e versões PHP |www:maintenance] -- [Notas de Lançamento |https://nette.org/releases] -- [Migrando para versões mais recentes|migrations:en] -- [Solução de problemas |nette:troubleshooting] -- [Quem faz o Nette |https://nette.org/contributors] -- [História do Nette |www:history] -- [Participe |contributing:] -- [Apoie o desenvolvimento |https://nette.org/pt/donate] -- [Referência da API |https://api.nette.org/] +- 📚 [Lista de pacotes |www:packages] +- 🔧 [Manutenção e versões PHP |www:maintenance] +- 📰 [Notas de Lançamento |https://nette.org/releases] +- ⬆️ [Migrando para versões mais recentes|migrations:en] +- 🆘 [Solução de problemas |nette:troubleshooting] +- 👥 [Quem faz o Nette |https://nette.org/contributors] +- 📜 [História do Nette |www:history] +- 🤝 [Participe |contributing:] +- ❤️ [Apoie o desenvolvimento |https://nette.org/pt/donate] +- 📖 [Referência da API |https://api.nette.org/] </div> @@ -33,18 +33,18 @@ Geral Aplicações em Nette ------------------- -- [Como funcionam as aplicações? |application:how-it-works] -- [Bootstrapping |application:Bootstrapping] -- [Presenters |application:presenters] -- [Templates |application:templates] -- [Estrutura de diretórios |application:directory-structure] -- [Roteamento |application:routing] -- [Criando links URL |application:creating-links] -- [Componentes interativos |application:components] -- [AJAX & snippets |application:ajax] - - -- [Tutoriais e melhores práticas |best-practices:] +- 🧭 [Como funcionam as aplicações? |application:how-it-works] +- 🥾 [Bootstrapping |application:Bootstrapping] +- 🎬 [Presenters |application:presenters] +- 📄 [Templates |application:templates] +- 📁 [Estrutura de diretórios |application:directory-structure] +- 🗺️ [Roteamento |application:routing] +- 🔗 [Criando links URL |application:creating-links] +- 🎛️ [Componentes interativos |application:components] +- 📡 [AJAX & snippets |application:ajax] + + +- 🎓 [Tutoriais e melhores práticas |best-practices:] </div> @@ -53,22 +53,22 @@ Aplicações em Nette Tópicos principais ------------------ -- [Configuração |nette:configuring] -- [Injeção de Dependência|dependency-injection:] -- [Latte: templates |latte:] -- [Tracy: depuração de código |tracy:] -- [Formulários |forms:] -- [Banco de Dados |database:guide] -- [Login de usuários |security:authentication] -- [Verificação de permissões |security:authorization] -- [Sessões |http:Sessions] -- [Requisição & resposta HTTP|http:] -- [Ativos |assets:] -- [Cache |caching:] -- [Enviando e-mails |mail:] -- [Schema: validação de dados |schema:] -- [Gerador de código PHP |php-generator:] -- [Tester: testes |tester:] +- ⚙️ [Configuração |nette:configuring] +- 🧩 [Injeção de Dependência|dependency-injection:] +- ☕ [Latte: templates |latte:] +- 🐞 [Tracy: depuração de código |tracy:] +- 📝 [Formulários |forms:] +- 🗄️ [Banco de Dados |database:guide] +- 🪪 [Login de usuários |security:authentication] +- 🛡️ [Verificação de permissões |security:authorization] +- 🍪 [Sessões |http:Sessions] +- 🌐 [Requisição & resposta HTTP|http:] +- 📦 [Ativos |assets:] +- ⚡ [Cache |caching:] +- ✉️ [Enviando e-mails |mail:] +- 📐 [Schema: validação de dados |schema:] +- 🛠️ [Gerador de código PHP |php-generator:] +- 🧪 [Tester: testes |tester:] </div> @@ -77,20 +77,20 @@ Tópicos principais Utilitários ----------- -- [Arrays |utils:arrays] -- [Sistema de arquivos |utils:filesystem] -- [Finder |utils:finder] -- [Elementos HTML |utils:html-elements] -- [Imagens |utils:images] -- [JSON |utils:JSON] -- [NEON|neon:] -- [Hashing de senhas |security:passwords] -- [Tipos PHP |utils:type] -- [Strings |utils:strings] -- [Validadores |utils:validators] -- [RobotLoader |robot-loader:] -- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] -- [SafeStream |safe-stream:] +- 🧮 [Arrays |utils:arrays] +- 💾 [Sistema de arquivos |utils:filesystem] +- 🔎 [Finder |utils:finder] +- 🏷️ [Elementos HTML |utils:html-elements] +- 🖼️ [Imagens |utils:images] +- 📋 [JSON |utils:JSON] +- 💡 [NEON|neon:] +- 🔐 [Hashing de senhas |security:passwords] +- 🐘 [Tipos PHP |utils:type] +- 🧵 [Strings |utils:strings] +- ✅ [Validadores |utils:validators] +- 🤖 [RobotLoader |robot-loader:] +- 🧠 [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] +- 🛟 [SafeStream |safe-stream:] - [...outros |utils:] </div> diff --git a/nette/ro/@home.texy b/nette/ro/@home.texy index b13f9c97eb..f9114ad972 100644 --- a/nette/ro/@home.texy +++ b/nette/ro/@home.texy @@ -8,23 +8,23 @@ Documentație Nette Introducere ----------- -- [De ce să folosiți Nette? |www:10-reasons-why-nette] -- [Instalare |installation] -- [Scriem prima aplicație! |quickstart:] +- 🤔 [De ce să folosiți Nette? |www:10-reasons-why-nette] +- 📥 [Instalare |installation] +- 🚀 [Scriem prima aplicație! |quickstart:] General ------- -- [Lista pachetelor |www:packages] -- [Mentenanță și versiuni PHP |www:maintenance] -- [Note de lansare |https://nette.org/releases] -- [Trecerea la versiuni mai noi|migrations:en] -- [Rezolvarea problemelor |nette:troubleshooting] -- [Cine creează Nette |https://nette.org/contributors] -- [Istoria Nette |www:history] -- [Implicați-vă |contributing:] -- [Susțineți dezvoltarea |https://nette.org/cs/donate] -- [Referință API |https://api.nette.org/] +- 📚 [Lista pachetelor |www:packages] +- 🔧 [Mentenanță și versiuni PHP |www:maintenance] +- 📰 [Note de lansare |https://nette.org/releases] +- ⬆️ [Trecerea la versiuni mai noi|migrations:en] +- 🆘 [Rezolvarea problemelor |nette:troubleshooting] +- 👥 [Cine creează Nette |https://nette.org/contributors] +- 📜 [Istoria Nette |www:history] +- 🤝 [Implicați-vă |contributing:] +- ❤️ [Susțineți dezvoltarea |https://nette.org/cs/donate] +- 📖 [Referință API |https://api.nette.org/] </div> @@ -33,18 +33,18 @@ General Aplicații în Nette ------------------ -- [Cum funcționează aplicațiile? |application:how-it-works] -- [application:Bootstrapping] -- [Presenteri |application:presenters] -- [Șabloane |application:templates] -- [Structura directoarelor |application:directory-structure] -- [Rutare |application:routing] -- [Crearea linkurilor URL |application:creating-links] -- [Componente interactive |application:components] -- [AJAX & snippete |application:ajax] - - -- [Tutoriale și proceduri |best-practices:] +- 🧭 [Cum funcționează aplicațiile? |application:how-it-works] +- 🥾 [application:Bootstrapping] +- 🎬 [Presenteri |application:presenters] +- 📄 [Șabloane |application:templates] +- 📁 [Structura directoarelor |application:directory-structure] +- 🗺️ [Rutare |application:routing] +- 🔗 [Crearea linkurilor URL |application:creating-links] +- 🎛️ [Componente interactive |application:components] +- 📡 [AJAX & snippete |application:ajax] + + +- 🎓 [Tutoriale și proceduri |best-practices:] </div> @@ -53,22 +53,22 @@ Aplicații în Nette Subiecte principale ------------------- -- [Configurare |nette:configuring] -- [Injecția de dependențe|dependency-injection:] -- [Latte: șabloane |latte:] -- [Tracy: depanare cod |tracy:] -- [Formulare |forms:] -- [Baze de date |database:guide] -- [Autentificarea utilizatorilor |security:authentication] -- [Verificarea permisiunilor |security:authorization] -- [http:Sessions] -- [Cerere & răspuns HTTP|http:] -- [Active |assets:] -- [Cache |caching:] -- [Trimiterea de e-mailuri |mail:] -- [Schema: validarea datelor |schema:] -- [Generator de cod PHP |php-generator:] -- [Tester: testare |tester:] +- ⚙️ [Configurare |nette:configuring] +- 🧩 [Injecția de dependențe|dependency-injection:] +- ☕ [Latte: șabloane |latte:] +- 🐞 [Tracy: depanare cod |tracy:] +- 📝 [Formulare |forms:] +- 🗄️ [Baze de date |database:guide] +- 🪪 [Autentificarea utilizatorilor |security:authentication] +- 🛡️ [Verificarea permisiunilor |security:authorization] +- 🍪 [http:Sessions] +- 🌐 [Cerere & răspuns HTTP|http:] +- 📦 [Active |assets:] +- ⚡ [Cache |caching:] +- ✉️ [Trimiterea de e-mailuri |mail:] +- 📐 [Schema: validarea datelor |schema:] +- 🛠️ [Generator de cod PHP |php-generator:] +- 🧪 [Tester: testare |tester:] </div> @@ -77,20 +77,20 @@ Subiecte principale Utilități --------- -- [Array-uri |utils:arrays] -- [Sistem de fișiere |utils:filesystem] -- [Finder |utils:finder] -- [Elemente HTML |utils:html-elements] -- [Imagini |utils:images] -- [utils:JSON] -- [NEON|neon:] -- [Hash-uirea parolelor |security:passwords] -- [Tipuri PHP |utils:type] -- [Șiruri |utils:strings] -- [Validatori |utils:validators] -- [RobotLoader |robot-loader:] -- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] -- [SafeStream |safe-stream:] +- 🧮 [Array-uri |utils:arrays] +- 💾 [Sistem de fișiere |utils:filesystem] +- 🔎 [Finder |utils:finder] +- 🏷️ [Elemente HTML |utils:html-elements] +- 🖼️ [Imagini |utils:images] +- 📋 [utils:JSON] +- 💡 [NEON|neon:] +- 🔐 [Hash-uirea parolelor |security:passwords] +- 🐘 [Tipuri PHP |utils:type] +- 🧵 [Șiruri |utils:strings] +- ✅ [Validatori |utils:validators] +- 🤖 [RobotLoader |robot-loader:] +- 🧠 [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] +- 🛟 [SafeStream |safe-stream:] - [...altele |utils:] </div> diff --git a/nette/ru/@home.texy b/nette/ru/@home.texy index 5bd1aed09b..dbae3d2158 100644 --- a/nette/ru/@home.texy +++ b/nette/ru/@home.texy @@ -8,23 +8,23 @@ Знакомство ---------- -- [Почему стоит использовать Nette? |www:10-reasons-why-nette] -- [Установка |nette:installation] -- [Пишем первое приложение! |quickstart:] +- 🤔 [Почему стоит использовать Nette? |www:10-reasons-why-nette] +- 📥 [Установка |nette:installation] +- 🚀 [Пишем первое приложение! |quickstart:] Общее ----- -- [Список пакетов |www:packages] -- [Поддержка и версии PHP |www:maintenance] -- [Примечания к выпуску |https://nette.org/releases] -- [Переход на новые версии|migrations:en] -- [Устранение неполадок |nette:troubleshooting] -- [Кто создает Nette |https://nette.org/contributors] -- [История Nette |www:history] -- [Примите участие |contributing:] -- [Поддержите разработку |https://nette.org/ru/donate] -- [Справочник API |https://api.nette.org/] +- 📚 [Список пакетов |www:packages] +- 🔧 [Поддержка и версии PHP |www:maintenance] +- 📰 [Примечания к выпуску |https://nette.org/releases] +- ⬆️ [Переход на новые версии|migrations:en] +- 🆘 [Устранение неполадок |nette:troubleshooting] +- 👥 [Кто создает Nette |https://nette.org/contributors] +- 📜 [История Nette |www:history] +- 🤝 [Примите участие |contributing:] +- ❤️ [Поддержите разработку |https://nette.org/ru/donate] +- 📖 [Справочник API |https://api.nette.org/] </div> @@ -33,18 +33,18 @@ Приложения в Nette ------------------ -- [Как работают приложения? |application:how-it-works] -- [Bootstrapping |application:Bootstrapping] -- [Презентеры |application:presenters] -- [Шаблоны |application:templates] -- [Структура каталогов |application:directory-structure] -- [Маршрутизация |application:routing] -- [Создание URL-ссылок |application:creating-links] -- [Интерактивные компоненты |application:components] -- [AJAX и сниппеты |application:ajax] - - -- [Руководства и лучшие практики |best-practices:] +- 🧭 [Как работают приложения? |application:how-it-works] +- 🥾 [Bootstrapping |application:Bootstrapping] +- 🎬 [Презентеры |application:presenters] +- 📄 [Шаблоны |application:templates] +- 📁 [Структура каталогов |application:directory-structure] +- 🗺️ [Маршрутизация |application:routing] +- 🔗 [Создание URL-ссылок |application:creating-links] +- 🎛️ [Интерактивные компоненты |application:components] +- 📡 [AJAX и сниппеты |application:ajax] + + +- 🎓 [Руководства и лучшие практики |best-practices:] </div> @@ -53,22 +53,22 @@ Основные темы ------------- -- [Конфигурация |nette:configuring] -- [Dependency Injection|dependency-injection:] -- [Latte: шаблоны |latte:] -- [Tracy: отладка кода |tracy:] -- [Формы |forms:] -- [База данных |database:guide] -- [Вход пользователей |security:authentication] -- [Проверка прав доступа |security:authorization] -- [Сессии |http:sessions] -- [HTTP-запрос и ответ|http:] -- [Активы |assets:] -- [Кеш |caching:] -- [Отправка электронной почты |mail:] -- [Schema: валидация данных |schema:] -- [Генератор PHP-кода |php-generator:] -- [Tester: тестирование |tester:] +- ⚙️ [Конфигурация |nette:configuring] +- 🧩 [Dependency Injection|dependency-injection:] +- ☕ [Latte: шаблоны |latte:] +- 🐞 [Tracy: отладка кода |tracy:] +- 📝 [Формы |forms:] +- 🗄️ [База данных |database:guide] +- 🪪 [Вход пользователей |security:authentication] +- 🛡️ [Проверка прав доступа |security:authorization] +- 🍪 [Сессии |http:sessions] +- 🌐 [HTTP-запрос и ответ|http:] +- 📦 [Активы |assets:] +- ⚡ [Кеш |caching:] +- ✉️ [Отправка электронной почты |mail:] +- 📐 [Schema: валидация данных |schema:] +- 🛠️ [Генератор PHP-кода |php-generator:] +- 🧪 [Tester: тестирование |tester:] </div> @@ -77,20 +77,20 @@ Утилиты ------- -- [Массивы |utils:arrays] -- [Файловая система |utils:filesystem] -- [Finder |utils:finder] -- [HTML-элементы |utils:html-elements] -- [Изображения |utils:images] -- [JSON |utils:json] -- [NEON|neon:] -- [Хеширование паролей |security:passwords] -- [Типы PHP |utils:type] -- [Строки |utils:strings] -- [Валидаторы |utils:validators] -- [RobotLoader |robot-loader:] -- [SmartObject |utils:smartobject] & [StaticClass |utils:staticclass] -- [SafeStream |safe-stream:] +- 🧮 [Массивы |utils:arrays] +- 💾 [Файловая система |utils:filesystem] +- 🔎 [Finder |utils:finder] +- 🏷️ [HTML-элементы |utils:html-elements] +- 🖼️ [Изображения |utils:images] +- 📋 [JSON |utils:json] +- 💡 [NEON|neon:] +- 🔐 [Хеширование паролей |security:passwords] +- 🐘 [Типы PHP |utils:type] +- 🧵 [Строки |utils:strings] +- ✅ [Валидаторы |utils:validators] +- 🤖 [RobotLoader |robot-loader:] +- 🧠 [SmartObject |utils:smartobject] & [StaticClass |utils:staticclass] +- 🛟 [SafeStream |safe-stream:] - [...другие |utils:] </div> diff --git a/nette/sl/@home.texy b/nette/sl/@home.texy index f3176c2230..6889d0a232 100644 --- a/nette/sl/@home.texy +++ b/nette/sl/@home.texy @@ -8,23 +8,23 @@ Dokumentacija Nette Spoznavanje ----------- -- [Zakaj uporabljati Nette? |www:10-reasons-why-nette] -- [Namestitev |installation] -- [Napišimo prvo aplikacijo! |quickstart:] +- 🤔 [Zakaj uporabljati Nette? |www:10-reasons-why-nette] +- 📥 [Namestitev |installation] +- 🚀 [Napišimo prvo aplikacijo! |quickstart:] Splošno ------- -- [Seznam paketov |www:packages] -- [Vzdrževanje in različice PHP |www:maintenance] -- [Opombe ob izdaji |https://nette.org/releases] -- [Prehod na novejše različice|migrations:en] -- [Odpravljanje težav |nette:troubleshooting] -- [Kdo ustvarja Nette |https://nette.org/contributors] -- [Zgodovina Nette |www:history] -- [Pridružite se |contributing:] -- [Podprite razvoj |https://nette.org/cs/donate] -- [API reference |https://api.nette.org/] +- 📚 [Seznam paketov |www:packages] +- 🔧 [Vzdrževanje in različice PHP |www:maintenance] +- 📰 [Opombe ob izdaji |https://nette.org/releases] +- ⬆️ [Prehod na novejše različice|migrations:en] +- 🆘 [Odpravljanje težav |nette:troubleshooting] +- 👥 [Kdo ustvarja Nette |https://nette.org/contributors] +- 📜 [Zgodovina Nette |www:history] +- 🤝 [Pridružite se |contributing:] +- ❤️ [Podprite razvoj |https://nette.org/cs/donate] +- 📖 [API reference |https://api.nette.org/] </div> @@ -33,18 +33,18 @@ Splošno Aplikacije v Nette ------------------ -- [Kako delujejo aplikacije? |application:how-it-works] -- [Bootstrapping |application:Bootstrapping] -- [Presenterji |application:presenters] -- [Predloge |application:templates] -- [Struktura imenikov |application:directory-structure] -- [Usmerjanje |application:routing] -- [Ustvarjanje URL povezav |application:creating-links] -- [Interaktivne komponente |application:components] -- [AJAX & odrezki |application:ajax] - - -- [Navodila in postopki |best-practices:] +- 🧭 [Kako delujejo aplikacije? |application:how-it-works] +- 🥾 [Bootstrapping |application:Bootstrapping] +- 🎬 [Presenterji |application:presenters] +- 📄 [Predloge |application:templates] +- 📁 [Struktura imenikov |application:directory-structure] +- 🗺️ [Usmerjanje |application:routing] +- 🔗 [Ustvarjanje URL povezav |application:creating-links] +- 🎛️ [Interaktivne komponente |application:components] +- 📡 [AJAX & odrezki |application:ajax] + + +- 🎓 [Navodila in postopki |best-practices:] </div> @@ -53,22 +53,22 @@ Aplikacije v Nette Glavne teme ----------- -- [Konfiguracija |nette:configuring] -- [Dependency Injection|dependency-injection:] -- [Latte: predloge |latte:] -- [Tracy: razhroščevanje kode |tracy:] -- [Obrazci |forms:] -- [Podatkovna baza |database:guide] -- [Prijava uporabnikov |security:authentication] -- [Preverjanje dovoljenj |security:authorization] -- [Seje |http:Sessions] -- [HTTP zahteva & odgovor|http:] -- [Sredstva |assets:] -- [Predpomnilnik |caching:] -- [Pošiljanje e-pošte |mail:] -- [Schema: validacija podatkov |schema:] -- [Generator PHP kode |php-generator:] -- [Tester: testiranje |tester:] +- ⚙️ [Konfiguracija |nette:configuring] +- 🧩 [Dependency Injection|dependency-injection:] +- ☕ [Latte: predloge |latte:] +- 🐞 [Tracy: razhroščevanje kode |tracy:] +- 📝 [Obrazci |forms:] +- 🗄️ [Podatkovna baza |database:guide] +- 🪪 [Prijava uporabnikov |security:authentication] +- 🛡️ [Preverjanje dovoljenj |security:authorization] +- 🍪 [Seje |http:Sessions] +- 🌐 [HTTP zahteva & odgovor|http:] +- 📦 [Sredstva |assets:] +- ⚡ [Predpomnilnik |caching:] +- ✉️ [Pošiljanje e-pošte |mail:] +- 📐 [Schema: validacija podatkov |schema:] +- 🛠️ [Generator PHP kode |php-generator:] +- 🧪 [Tester: testiranje |tester:] </div> @@ -77,20 +77,20 @@ Glavne teme Pripomočki ---------- -- [Polja |utils:arrays] -- [Datotečni sistem |utils:filesystem] -- [Finder |utils:finder] -- [HTML elementi |utils:html-elements] -- [Slike |utils:images] -- [JSON |utils:JSON] -- [NEON|neon:] -- [Zgoščevanje gesel |security:passwords] -- [PHP tipi |utils:type] -- [Nizi |utils:strings] -- [Validatorji |utils:validators] -- [RobotLoader |robot-loader:] -- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] -- [SafeStream |safe-stream:] +- 🧮 [Polja |utils:arrays] +- 💾 [Datotečni sistem |utils:filesystem] +- 🔎 [Finder |utils:finder] +- 🏷️ [HTML elementi |utils:html-elements] +- 🖼️ [Slike |utils:images] +- 📋 [JSON |utils:JSON] +- 💡 [NEON|neon:] +- 🔐 [Zgoščevanje gesel |security:passwords] +- 🐘 [PHP tipi |utils:type] +- 🧵 [Nizi |utils:strings] +- ✅ [Validatorji |utils:validators] +- 🤖 [RobotLoader |robot-loader:] +- 🧠 [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] +- 🛟 [SafeStream |safe-stream:] - [...ostalo |utils:] </div> diff --git a/nette/tr/@home.texy b/nette/tr/@home.texy index 2043154c6d..65215989d0 100644 --- a/nette/tr/@home.texy +++ b/nette/tr/@home.texy @@ -8,23 +8,23 @@ Nette Dokümantasyonu Tanıtım ------- -- [Neden Nette kullanmalı? |www:10-reasons-why-nette] -- [Kurulum |installation] -- [İlk uygulamamızı yazıyoruz! |quickstart:] +- 🤔 [Neden Nette kullanmalı? |www:10-reasons-why-nette] +- 📥 [Kurulum |installation] +- 🚀 [İlk uygulamamızı yazıyoruz! |quickstart:] Genel ----- -- [Paket listesi |www:packages] -- [Bakım ve PHP sürümleri |www:maintenance] -- [Sürüm Notları |https://nette.org/releases] -- [Daha yeni sürümlere geçiş|migrations:en] -- [Sorun Giderme |nette:troubleshooting] -- [Nette'yi kimler oluşturuyor |https://nette.org/contributors] -- [Nette Tarihçesi |www:history] -- [Katkıda Bulunun |contributing:] -- [Geliştirmeyi Destekleyin |https://nette.org/en/donate] -- [API Referansı |https://api.nette.org/] +- 📚 [Paket listesi |www:packages] +- 🔧 [Bakım ve PHP sürümleri |www:maintenance] +- 📰 [Sürüm Notları |https://nette.org/releases] +- ⬆️ [Daha yeni sürümlere geçiş|migrations:en] +- 🆘 [Sorun Giderme |nette:troubleshooting] +- 👥 [Nette'yi kimler oluşturuyor |https://nette.org/contributors] +- 📜 [Nette Tarihçesi |www:history] +- 🤝 [Katkıda Bulunun |contributing:] +- ❤️ [Geliştirmeyi Destekleyin |https://nette.org/en/donate] +- 📖 [API Referansı |https://api.nette.org/] </div> @@ -33,18 +33,18 @@ Genel Nette Uygulamaları ------------------ -- [Uygulamalar nasıl çalışır? |application:how-it-works] -- [application:Bootstrapping] -- [Presenter'lar |application:presenters] -- [Şablonlar |application:templates] -- [Dizin Yapısı |application:directory-structure] -- [Yönlendirme |application:routing] -- [URL Bağlantıları Oluşturma |application:creating-links] -- [Etkileşimli Bileşenler |application:components] -- [AJAX & Snippet'ler |application:ajax] - - -- [Kılavuzlar ve yöntemler |best-practices:] +- 🧭 [Uygulamalar nasıl çalışır? |application:how-it-works] +- 🥾 [application:Bootstrapping] +- 🎬 [Presenter'lar |application:presenters] +- 📄 [Şablonlar |application:templates] +- 📁 [Dizin Yapısı |application:directory-structure] +- 🗺️ [Yönlendirme |application:routing] +- 🔗 [URL Bağlantıları Oluşturma |application:creating-links] +- 🎛️ [Etkileşimli Bileşenler |application:components] +- 📡 [AJAX & Snippet'ler |application:ajax] + + +- 🎓 [Kılavuzlar ve yöntemler |best-practices:] </div> @@ -53,22 +53,22 @@ Nette Uygulamaları Ana Konular ----------- -- [Yapılandırma |nette:configuring] -- [Bağımlılık Enjeksiyonu|dependency-injection:] -- [Latte: Şablonlar |latte:] -- [Tracy: Kod Hata Ayıklama |tracy:] -- [Formlar |forms:] -- [Veritabanı |database:guide] -- [Kullanıcı Girişi |security:authentication] -- [Yetkilendirme |security:authorization] -- [http:Sessions] -- [HTTP İsteği & Yanıtı|http:] -- [Varlıklar |assets:] -- [Önbellek |caching:] -- [E-posta Gönderme |mail:] -- [Schema: Veri Doğrulama |schema:] -- [PHP Kod Üreteci |php-generator:] -- [Tester: Test Etme |tester:] +- ⚙️ [Yapılandırma |nette:configuring] +- 🧩 [Bağımlılık Enjeksiyonu|dependency-injection:] +- ☕ [Latte: Şablonlar |latte:] +- 🐞 [Tracy: Kod Hata Ayıklama |tracy:] +- 📝 [Formlar |forms:] +- 🗄️ [Veritabanı |database:guide] +- 🪪 [Kullanıcı Girişi |security:authentication] +- 🛡️ [Yetkilendirme |security:authorization] +- 🍪 [http:Sessions] +- 🌐 [HTTP İsteği & Yanıtı|http:] +- 📦 [Varlıklar |assets:] +- ⚡ [Önbellek |caching:] +- ✉️ [E-posta Gönderme |mail:] +- 📐 [Schema: Veri Doğrulama |schema:] +- 🛠️ [PHP Kod Üreteci |php-generator:] +- 🧪 [Tester: Test Etme |tester:] </div> @@ -77,20 +77,20 @@ Ana Konular Yardımcı Programlar ------------------- -- [Diziler |utils:arrays] -- [Dosya Sistemi |utils:filesystem] -- [Finder |utils:finder] -- [HTML Öğeleri |utils:html-elements] -- [Resimler |utils:images] -- [utils:JSON] -- [NEON|neon:] -- [Şifre Hashleme |security:passwords] -- [PHP Tipleri |utils:type] -- [Karakter Dizileri |utils:strings] -- [Doğrulayıcılar |utils:validators] -- [RobotLoader |robot-loader:] -- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] -- [SafeStream |safe-stream:] +- 🧮 [Diziler |utils:arrays] +- 💾 [Dosya Sistemi |utils:filesystem] +- 🔎 [Finder |utils:finder] +- 🏷️ [HTML Öğeleri |utils:html-elements] +- 🖼️ [Resimler |utils:images] +- 📋 [utils:JSON] +- 💡 [NEON|neon:] +- 🔐 [Şifre Hashleme |security:passwords] +- 🐘 [PHP Tipleri |utils:type] +- 🧵 [Karakter Dizileri |utils:strings] +- ✅ [Doğrulayıcılar |utils:validators] +- 🤖 [RobotLoader |robot-loader:] +- 🧠 [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] +- 🛟 [SafeStream |safe-stream:] - [...diğerleri |utils:] </div> diff --git a/nette/uk/@home.texy b/nette/uk/@home.texy index b9daa24f9f..50c8a7b148 100644 --- a/nette/uk/@home.texy +++ b/nette/uk/@home.texy @@ -8,23 +8,23 @@ Знайомство ---------- -- [Чому використовувати Nette? |www:10-reasons-why-nette] -- [Встановлення |installation] -- [Пишемо першу програму! |quickstart:] +- 🤔 [Чому використовувати Nette? |www:10-reasons-why-nette] +- 📥 [Встановлення |installation] +- 🚀 [Пишемо першу програму! |quickstart:] Загальне -------- -- [Список пакетів |www:packages] -- [Підтримка та версії PHP |www:maintenance] -- [Release Notes |https://nette.org/releases] -- [Перехід на новіші версії|migrations:en] -- [Вирішення проблем |nette:troubleshooting] -- [Хто створює Nette |https://nette.org/contributors] -- [Історія Nette |www:history] -- [Долучайтеся |contributing:] -- [Підтримайте розробку |https://nette.org/cs/donate] -- [API reference |https://api.nette.org/] +- 📚 [Список пакетів |www:packages] +- 🔧 [Підтримка та версії PHP |www:maintenance] +- 📰 [Release Notes |https://nette.org/releases] +- ⬆️ [Перехід на новіші версії|migrations:en] +- 🆘 [Вирішення проблем |nette:troubleshooting] +- 👥 [Хто створює Nette |https://nette.org/contributors] +- 📜 [Історія Nette |www:history] +- 🤝 [Долучайтеся |contributing:] +- ❤️ [Підтримайте розробку |https://nette.org/cs/donate] +- 📖 [API reference |https://api.nette.org/] </div> @@ -33,18 +33,18 @@ Програми в Nette ---------------- -- [Як працюють програми? |application:how-it-works] -- [Bootstrapping |application:Bootstrapping] -- [Presenters |application:presenters] -- [Шаблони |application:templates] -- [Структура каталогів |application:directory-structure] -- [Маршрутизація |application:routing] -- [Створення посилань URL |application:creating-links] -- [Інтерактивні компоненти |application:components] -- [AJAX & сніпети |application:ajax] - - -- [Посібники та практики |best-practices:] +- 🧭 [Як працюють програми? |application:how-it-works] +- 🥾 [Bootstrapping |application:Bootstrapping] +- 🎬 [Presenters |application:presenters] +- 📄 [Шаблони |application:templates] +- 📁 [Структура каталогів |application:directory-structure] +- 🗺️ [Маршрутизація |application:routing] +- 🔗 [Створення посилань URL |application:creating-links] +- 🎛️ [Інтерактивні компоненти |application:components] +- 📡 [AJAX & сніпети |application:ajax] + + +- 🎓 [Посібники та практики |best-practices:] </div> @@ -53,22 +53,22 @@ Основні теми ------------ -- [Конфігурація |nette:configuring] -- [Dependency Injection|dependency-injection:] -- [Latte: шаблони |latte:] -- [Tracy: налагодження коду |tracy:] -- [Форми |forms:] -- [База даних |database:guide] -- [Вхід користувачів |security:authentication] -- [Перевірка прав доступу |security:authorization] -- [Сесії |http:Sessions] -- [HTTP запит & відповідь|http:] -- [Активи |assets:] -- [Кеш |caching:] -- [Відправлення електронних листів |mail:] -- [Schema: валідація даних |schema:] -- [Генератор PHP коду |php-generator:] -- [Tester: тестування |tester:] +- ⚙️ [Конфігурація |nette:configuring] +- 🧩 [Dependency Injection|dependency-injection:] +- ☕ [Latte: шаблони |latte:] +- 🐞 [Tracy: налагодження коду |tracy:] +- 📝 [Форми |forms:] +- 🗄️ [База даних |database:guide] +- 🪪 [Вхід користувачів |security:authentication] +- 🛡️ [Перевірка прав доступу |security:authorization] +- 🍪 [Сесії |http:Sessions] +- 🌐 [HTTP запит & відповідь|http:] +- 📦 [Активи |assets:] +- ⚡ [Кеш |caching:] +- ✉️ [Відправлення електронних листів |mail:] +- 📐 [Schema: валідація даних |schema:] +- 🛠️ [Генератор PHP коду |php-generator:] +- 🧪 [Tester: тестування |tester:] </div> @@ -77,20 +77,20 @@ Utilities --------- -- [Масиви |utils:arrays] -- [Файлова система |utils:filesystem] -- [Finder |utils:finder] -- [HTML елементи |utils:html-elements] -- [Зображення |utils:images] -- [JSON |utils:JSON] -- [NEON|neon:] -- [Хешування паролів |security:passwords] -- [PHP типи |utils:type] -- [Рядки |utils:strings] -- [Валідатори |utils:validators] -- [RobotLoader |robot-loader:] -- [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] -- [SafeStream |safe-stream:] +- 🧮 [Масиви |utils:arrays] +- 💾 [Файлова система |utils:filesystem] +- 🔎 [Finder |utils:finder] +- 🏷️ [HTML елементи |utils:html-elements] +- 🖼️ [Зображення |utils:images] +- 📋 [JSON |utils:JSON] +- 💡 [NEON|neon:] +- 🔐 [Хешування паролів |security:passwords] +- 🐘 [PHP типи |utils:type] +- 🧵 [Рядки |utils:strings] +- ✅ [Валідатори |utils:validators] +- 🤖 [RobotLoader |robot-loader:] +- 🧠 [SmartObject |utils:smartobject] & [StaticClass |utils:StaticClass] +- 🛟 [SafeStream |safe-stream:] - [...інше |utils:] </div> From 0254cd2f707abb3128bb8f763b0cdf30a06bd543 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Mon, 11 May 2026 20:26:47 +0200 Subject: [PATCH 30/50] nette/utils 4.1.4 --- nette/cs/@home.texy | 1 + nette/en/@home.texy | 1 + utils/cs/@home.texy | 1 + utils/cs/@left-menu.texy | 1 + utils/cs/filesystem.texy | 12 ++ utils/cs/images.texy | 12 +- utils/cs/process.texy | 382 +++++++++++++++++++++++++++++++++++++++ utils/en/@home.texy | 1 + utils/en/@left-menu.texy | 1 + utils/en/filesystem.texy | 12 ++ utils/en/images.texy | 12 +- utils/en/process.texy | 382 +++++++++++++++++++++++++++++++++++++++ 12 files changed, 806 insertions(+), 12 deletions(-) create mode 100644 utils/cs/process.texy create mode 100644 utils/en/process.texy diff --git a/nette/cs/@home.texy b/nette/cs/@home.texy index fef1c2b85b..73b4844e52 100644 --- a/nette/cs/@home.texy +++ b/nette/cs/@home.texy @@ -79,6 +79,7 @@ Utilities --------- - 🧮 [Pole |utils:arrays] - 💾 [Souborový systém |utils:filesystem] +- 🏃 [Procesy |utils:process] - 🔎 [Finder |utils:finder] - 🏷️ [HTML elementy |utils:html-elements] - 🖼️ [Obrázky |utils:images] diff --git a/nette/en/@home.texy b/nette/en/@home.texy index 37e40fefbf..2c7cfa6d87 100644 --- a/nette/en/@home.texy +++ b/nette/en/@home.texy @@ -79,6 +79,7 @@ Utilities --------- - 🧮 [utils:Arrays] - 💾 [Filesystem |utils:filesystem] +- 🏃 [Process |utils:process] - 🔎 [Finder |utils:finder] - 🏷️ [utils:HTML Elements] - 🖼️ [utils:Images] diff --git a/utils/cs/@home.texy b/utils/cs/@home.texy index ac310407d8..1750c0c855 100644 --- a/utils/cs/@home.texy +++ b/utils/cs/@home.texy @@ -17,6 +17,7 @@ V balíčku `nette/utils` najdete sadu užitečných tříd pro každodenní pou | [Pole |arrays] | Nette\Utils\Arrays | [Pomocné funkce |helpers] | Nette\Utils\Helpers | [Porovnávání floatů |floats] | Nette\Utils\Floats +| [Procesy |process] | Nette\Utils\Process | [Řetězce |strings] | Nette\Utils\Strings | [Souborový systém |filesystem] | Nette\Utils\FileSystem | [Stránkování |paginator] | Nette\Utils\Paginator diff --git a/utils/cs/@left-menu.texy b/utils/cs/@left-menu.texy index dd371e9e34..4ebf81bab6 100644 --- a/utils/cs/@left-menu.texy +++ b/utils/cs/@left-menu.texy @@ -14,6 +14,7 @@ Nette Utils - [PHP typy |type] - [Pole |arrays] - [Pomocné funkce |helpers] +- [Procesy |process] - [Řetězce |strings] - [SmartObject] - [StaticClass] diff --git a/utils/cs/filesystem.texy b/utils/cs/filesystem.texy index 0b3e31e9ac..d52abfe8d5 100644 --- a/utils/cs/filesystem.texy +++ b/utils/cs/filesystem.texy @@ -134,6 +134,18 @@ FileSystem::isAbsolute('C:/backup'); // true ``` +isValidFilename(string $name): bool .[method] +--------------------------------------------- + +Zjišťuje, zda je `$name` platný název souboru bez cesty, který funguje na všech platformách. Odmítne prázdný řetězec, `.` a `..`, řídicí znaky, znaky `<>:"|?*\/`, názvy končící tečkou nebo mezerou a vyhrazené názvy zařízení Windows (`CON`, `NUL`, `COM1`, …). + +```php +FileSystem::isValidFilename('photo.jpg'); // true +FileSystem::isValidFilename('../photo.jpg'); // false +FileSystem::isValidFilename('CON'); // false +``` + + joinPaths(string ...$segments): string .[method] ------------------------------------------------ Spojí všechny segmenty cesty a výsledek normalizuje. diff --git a/utils/cs/images.texy b/utils/cs/images.texy index 9f2317fde3..710d0afb2f 100644 --- a/utils/cs/images.texy +++ b/utils/cs/images.texy @@ -255,14 +255,14 @@ static fromBlank(int $width, int $height, ?ImageColor $color=null): Image .[meth Vytvoří nový true color obrázek daných rozměrů. Výchozí barva je černá. -static fromFile(string $file, int &$detectedFormat=null): Image .[method] -------------------------------------------------------------------------- -Načte obrázek ze souboru a vrací jeho [typ |#Formáty] v `$detectedFormat`. +static fromFile(string $file, int &$detectedFormat=null, string &$warnings=null): Image .[method] +------------------------------------------------------------------------------------------------- +Načte obrázek ze souboru a vrací jeho [typ |#Formáty] v `$detectedFormat`. Pokud předáte `$warnings`, případná nefatální varování dekodéru obrázku se uloží do této proměnné místo toho, aby se vyvolala jako PHP warning; pokud žádná nebyla, zůstane `null`. -static fromString(string $s, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------- -Načte obrázek z řetezce a vrací jeho [typ |#Formáty] v `$detectedFormat`. +static fromString(string $s, int &$detectedFormat=null, string &$warnings=null): Image .[method] +------------------------------------------------------------------------------------------------ +Načte obrázek z řetezce a vrací jeho [typ |#Formáty] v `$detectedFormat`. Pokud předáte `$warnings`, případná nefatální varování dekodéru obrázku se uloží do této proměnné místo toho, aby se vyvolala jako PHP warning; pokud žádná nebyla, zůstane `null`. static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated] diff --git a/utils/cs/process.texy b/utils/cs/process.texy new file mode 100644 index 0000000000..8d975f30f7 --- /dev/null +++ b/utils/cs/process.texy @@ -0,0 +1,382 @@ +Process: Spouštění externích programů .{data-version:4.1.4} +*********************************************************** + +.[perex] +Třída [api:Nette\Utils\Process] umožňuje z PHP spouštět externí programy: posílat jim vstup, číst jejich výstup a reagovat na to, jak skončily. Je to přívětivý obal nad PHP funkcí `proc_open()`, který hlásí chyby vyhazováním výjimek místo vracení `false`. + + +Instalace: + +```shell +composer require nette/utils +``` + +Všechny příklady předpokládají vytvořený alias: + +```php +use Nette\Utils\Process; +``` + + +Nejjednodušší použití +===================== + +Chcete spustit program a přečíst, co vypsal? Stačí tohle: + +```php +$process = Process::runExecutable('git', ['log', '-1', '--format=%H']); +echo $process->getStdOutput(); +``` + +První argument je program, který se má spustit, druhý je seznam jeho argumentů: totéž, co byste napsali na příkazové řádce, jen rozdělené do pole. Metoda `getStdOutput()` počká, až program doběhne, a vrátí vše, co zapsal na svůj standardní výstup. + +To je celá myšlenka: spustíte proces a pak se ho ptáte: běží ještě, co vypsal, jak skončil. Zbytek této stránky probírá tyto otázky jednu po druhé. + + +Spuštění procesu +================ + +Proces lze spustit dvěma způsoby a stojí za to ten rozdíl pochopit. + + +static runExecutable(string $executable, array $arguments=[], ?array $env=null, array $options=[], mixed $stdin='', mixed $stdout=null, mixed $stderr=null, ?string $directory=null, ?float $timeout=60): Process .[method] +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +Spustí **jeden konkrétní program** se seznamem argumentů. Argumenty se programu předají přímo, takže nikdy nemusíte escapovat mezery, uvozovky ani jiné speciální znaky. A protože nevstupuje do hry žádný shell, nehrozí *shell injection*. Tohle je bezpečná volba, zvlášť když část příkazu pochází z uživatelského vstupu: + +```php +$file = $_GET['file']; // může být cokoli, třeba '; rm -rf /' +$process = Process::runExecutable('wc', ['-l', $file]); // naprosto bezpečné +``` + +Pokud neuvedete plnou cestu, program se hledá v systémové proměnné `PATH`. Pro spuštění PHP skriptu se hodí konstanta `PHP_BINARY`: + +```php +$process = Process::runExecutable(PHP_BINARY, ['-v']); +``` + + +static runCommand(string $command, ?array $env=null, array $options=[], mixed $stdin='', mixed $stdout=null, mixed $stderr=null, ?string $directory=null, ?float $timeout=60): Process .[method] +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +Spustí **příkaz zadaný řetězcem přes systémový shell** (`/bin/sh` na Linuxu a macOS, `cmd.exe` na Windows). Tím získáte možnosti shellu: roury `|`, přesměrování `>`, expanzi proměnných, řetězení příkazů přes `&&` a podobně: + +```php +$process = Process::runCommand('git log --oneline | head -n 20'); +``` + +Protože ale shell celý řetězec parsuje, **nikdy nesestavujte řetězec pro `runCommand()` z nedůvěryhodného vstupu**, což je klasická bezpečnostní díra. Když si nejste jisti, použijte raději `runExecutable()`. + +.[note] +Při tolika parametrech je předávejte jako pojmenované argumenty, např. `Process::runExecutable('git', ['pull'], timeout: 30)`. Pole `$options` se předává přímo do `proc_open()` pro pokročilé potřeby, jako třeba `bypass_shell` na Windows. + + +Proces běží na pozadí +===================== + +Po spuštění proces běží **souběžně** s vaším PHP skriptem: `runExecutable()` i `runCommand()` se vrátí okamžitě a nečekají, až proces doběhne. Vy rozhodujete, kdy (a zda) na něj počkáte: + +```php +$process = Process::runExecutable('npm', ['install']); + +// ... tady mezitím dělej jinou práci, zatímco běží npm ... + +$process->wait(); // teď počkej, až doběhne +``` + +V praxi voláte `wait()` přímo jen zřídka, protože `getStdOutput()`, `getExitCode()`, `isSuccess()` i `ensureSuccess()` na proces počkají automaticky, než vám dají odpověď. `wait()` zavolejte explicitně tehdy, když mu chcete předat [callback |#Sledování výstupu naživo]. + + +isRunning(): bool .[method] +--------------------------- + +Vrací `true`, dokud proces běží, a `false`, jakmile doběhl nebo byl ukončen. Hodí se, když chcete mezitím dělat něco jiného: + +```php +while ($process->isRunning()) { + // dělej mezitím něco jiného + usleep(100_000); // 100 ms +} +``` + + +Jak skončil? +============ + +Každý dokončený proces má *návratový kód*: konvenčně `0` znamená úspěch a jakékoli jiné číslo nějaký druh selhání (co přesně, záleží na programu). + + +getExitCode(): int .[method] +---------------------------- + +Vrátí návratový kód; pokud je potřeba, nejprve počká, až proces doběhne: + +```php +$code = Process::runExecutable('git', ['pull'])->getExitCode(); // např. 0 +``` + + +isSuccess(): bool .[method] +--------------------------- + +Zkratka pro "rovná se návratový kód `0`?": + +```php +$process = Process::runExecutable('git', ['pull']); +if (!$process->isSuccess()) { + echo 'git selhal: ' . $process->getStdError(); +} +``` + + +ensureSuccess(): void .[method] +------------------------------- + +Často chcete prostě jen to, aby program uspěl, a jinak hlasitě selhat. `ensureSuccess()` počká na proces a vyhodí `Nette\Utils\ProcessFailedException`, pokud návratový kód není `0`: + +```php +Process::runExecutable('git', ['pull'])->ensureSuccess(); +// dál se pokračuje, jen když git uspěl +``` + + +Čtení výstupu +============= + +Proces má dva oddělené výstupní proudy: **standardní výstup** (běžné výsledky) a **chybový výstup** (kam programy obvykle hlásí problémy a diagnostiku). Nette Utils tyto dva drží odděleně a ve výchozím nastavení oba zachytává do paměti, takže si je můžete přečíst, kdykoli budete chtít. + + +getStdOutput(): string .[method] +-------------------------------- + +Počká, až proces doběhne, a vrátí vše, co zapsal na standardní výstup: + +```php +$process = Process::runExecutable('date'); +echo $process->getStdOutput(); +``` + + +getStdError(): string .[method] +------------------------------- + +Totéž, ale pro chybový výstup: + +```php +$process = Process::runExecutable('some-tool', ['--do-stuff']); +if (!$process->isSuccess()) { + throw new RuntimeException('Nástroj selhal: ' . $process->getStdError()); +} +``` + +.[note] +Pokud výstupní proud [přesměrujete jinam |#Přesměrování výstupu jinam] (do souboru, do resource nebo na `false`), není v paměti co vracet a příslušný getter vyhodí `Nette\InvalidStateException`. + + +consumeStdOutput(): string .[method] +------------------------------------ + +Někdy chcete vidět výstup **tak, jak přichází**, bez čekání na konec procesu, třeba abyste zobrazili průběh. Každé volání vrátí kus standardního výstupu, který se objevil od předchozího volání: + +```php +$process = Process::runExecutable('long-running-tool'); + +while ($process->isRunning()) { + echo $process->consumeStdOutput(); // vypíše, co je nového + usleep(100_000); // 100 ms +} +echo $process->consumeStdOutput(); // poslední kus, vypsaný těsně před koncem +``` + +Volání `consumeStdOutput()` za smyčkou není zbytečné: poslední kus výstupu mohl proces vypsat během poslední pauzy `usleep()`, tedy až po posledním volání uvnitř smyčky, ale ještě než si smyčka jeho konce všimla. (Pokud proces skončil přímo během některého volání uvnitř smyčky, vrátilo to volání zbytek samo a tohle vrátí prázdný řetězec.) Pro chybový výstup existuje obdobné `consumeStdError()`. + + +Sledování výstupu naživo +======================== + +Místo pollování přes `consumeStdOutput()` můžete metodě `wait()` předat callback. Ten se zavolá pokaždé, když se objeví nový výstup, což se hodí pro průběžné logování nebo přeposílání výstupu jinam: + +```php +$process = Process::runExecutable('npm', ['install']); + +$process->wait(function (string $stdOut, string $stdErr) { + echo $stdOut; // přepošli standardní výstup + fwrite(STDERR, $stdErr); // a chybový výstup +}); +``` + +Callback dostane dva řetězce: nová data standardního výstupu a nová data chybového výstupu od předchozího volání (kterýkoli může být prázdný). Když se `wait()` vrátí, proces je dokončený a stále můžete volat `getExitCode()`, `getStdOutput()` a další. + + +Posílání vstupu +=============== + +Parametr `$stdin` říká, co proces čte na svém standardním vstupu. Přijímá několik různých věcí. + +**Řetězec** se stane celým vstupem procesu: + +```php +$process = Process::runExecutable('wc', ['-c'], stdin: 'hello world'); +echo $process->getStdOutput(); // 11 +``` + +**Čitelný resource** (otevřený soubor, stream) se do vstupu zkopíruje: + +```php +$file = fopen('data.csv', 'r'); +$process = Process::runExecutable('sort', stdin: $file); +``` + +**`null`** ponechá vstup otevřený, takže do něj můžete zapisovat postupně (viz níže). + +Výchozí hodnotou je prázdný řetězec, což znamená, že proces dostane prázdný, okamžitě uzavřený vstup. To je rozumné výchozí chování: zabrání tomu, aby programy, které čtou vstup, navždy visely a čekaly na něco, co nikdy nepřijde. + + +writeStdInput(string $string): void .[method] +--------------------------------------------- + +Když proces spustíte s `stdin: null`, vstup zůstane otevřený a vy ho plníte po částech. Až skončíte, zavolejte `closeStdInput()`. Tím programu řeknete, že už žádný vstup nepřijde (pošle se konec souboru, EOF): + +```php +$process = Process::runExecutable('some-repl', stdin: null); +$process->writeStdInput("první příkaz\n"); +$process->writeStdInput("druhý příkaz\n"); +$process->closeStdInput(); +echo $process->getStdOutput(); +``` + +.[note] +Řetězec nebo stream předaný jako `$stdin` se zapíše celý najednou, ještě než se proces pořádně rozběhne. Pokud je tento vstup velký *a zároveň* program produkuje hodně výstupu, aniž by si nejdřív přečetl vstup, mohou obě strany uváznout v čekání na sebe navzájem. V tom (vzácném) případě použijte `stdin: null` a `writeStdInput()`, abyste prokládali zápis čtením. + + +Řetězení procesů (piping) +========================= + +Standardní výstup jednoho procesu můžete napojit přímo na standardní vstup druhého, přesně jako rourou `|` v shellu. Stačí jako `$stdin` předat `Process`: + +```php +$producer = Process::runExecutable('cat', ['big.log']); +$consumer = Process::runExecutable('grep', ['error'], stdin: $producer); + +echo $consumer->getStdOutput(); +``` + +Zřetězit můžete libovolný počet procesů (`a | b | c`). + +.[note] +Řetězení procesů **není podporováno na Windows** (vyhodí `Nette\NotSupportedException`). Na Windows zachyťte výstup prvního procesu pomocí `getStdOutput()` a předejte ho dalšímu jako řetězec. + + +Přesměrování výstupu jinam +========================== + +Ve výchozím nastavení se standardní i chybový výstup zachytávají do paměti. Parametry `$stdout` a `$stderr` umožňují poslat je místo toho jinam. + +**Název souboru** pošle výstup do tohoto souboru: + +```php +Process::runExecutable('mysqldump', ['mydb'], stdout: 'backup.sql') + ->ensureSuccess(); +``` + +**Zapisovatelný resource** pošle výstup do tohoto streamu. Musí být podložený skutečným souborem (ne `php://memory` apod.): + +```php +$log = fopen('build.log', 'a'); +Process::runExecutable('make', stdout: $log, stderr: $log); +``` + +**`false`** výstup úplně zahodí (jde do `/dev/null`, resp. `NUL` na Windows): + +```php +Process::runExecutable('noisy-tool', stderr: false); +``` + +Přesměrování zároveň drží spotřebu paměti nízko: zachytávání do paměti je pohodlné, ale proces, který vypíše gigabajty, by spotřeboval gigabajty RAM, takže takový výstup zapisujte do souboru. + + +Proměnné prostředí +================== + +Parametr `$env` nastavuje proměnné prostředí, které proces uvidí. Ponechte `null` (výchozí), aby zdědil prostředí aktuálního procesu, nebo předejte pole a nastavte si je sami: + +```php +// aktuální prostředí plus jedna proměnná navíc +$process = Process::runExecutable('printenv', ['MY_VAR'], env: ['MY_VAR' => '123'] + getenv()); + +// úplně prázdné prostředí +$process = Process::runExecutable('some-tool', env: []); +``` + + +Pracovní adresář +================ + +Parametr `$directory` nastavuje adresář, ve kterém proces startuje (výchozí je ten aktuální): + +```php +$process = Process::runExecutable('git', ['status'], directory: '/path/to/repo'); +``` + + +Časový limit +============ + +Parametr `$timeout` (v sekundách, výchozí `60`) omezuje, jak dlouho budete na proces čekat. Pokud se limit překročí během toho, co na proces čekáte nebo čtete jeho výstup, proces se zabije a vyhodí se `Nette\Utils\ProcessTimeoutException`. Předáním `null` limit zrušíte: + +```php +$process = Process::runExecutable('slow-tool', timeout: 5.0); +try { + $process->wait(); +} catch (Nette\Utils\ProcessTimeoutException $e) { + echo 'Nástroj běžel příliš dlouho a byl ukončen.'; +} +``` + +Limit se kontroluje jen tehdy, když jste uvnitř `wait()`, `getExitCode()`, getterů výstupu nebo `consume*()`. Proces, který spustíte a pak na něj nikdy nečekáte, jím zabit není. + + +Ukončení procesu +================ + + +terminate(): void .[method] +--------------------------- + +Okamžitě zabije proces, pokud ještě běží; pokud už doběhl, neudělá nic: + +```php +$process = Process::runExecutable('server'); +// ... +$process->terminate(); +``` + +Proces se také ukončí automaticky, když je jeho objekt `Process` zničen (například opustí platnost) a ještě nedoběhl. + +.[note] +Chcete-li proces, který přežije běh PHP skriptu (démon, úloha na pozadí), nespouštějte ho přes `Process`, ale odpojeně přes shell, např. `nohup yourtask >/dev/null 2>&1 &` na POSIXu nebo `start /b yourtask` na Windows. + + +getPid(): ?int .[method] +------------------------ + +Vrátí ID procesu (PID) operačního systému, dokud proces běží, nebo `null`, jakmile doběhl: + +```php +$pid = $process->getPid(); +``` + + +Když se něco pokazí +=================== + +Chyby se vždy hlásí vyhozením výjimky, nikdy návratovou hodnotou: + +| `Nette\Utils\ProcessFailedException` | proces se nepodařilo spustit, nebo byla zavolána `ensureSuccess()` a návratový kód nebyl `0` +| `Nette\Utils\ProcessTimeoutException` | byl překročen limit daný parametrem `$timeout` +| `Nette\InvalidArgumentException` | jako `$stdin`, `$stdout` nebo `$stderr` byla předána neplatná hodnota +| `Nette\IOException` | soubor zadaný jako `$stdout` nebo `$stderr` se nepodařilo otevřít +| `Nette\InvalidStateException` | čtení výstupu, který nebyl zachytáván, nebo zápis do STDIN, který je už zavřený +| `Nette\NotSupportedException` | o řetězení procesů se pokusilo na Windows + +`ProcessFailedException` a `ProcessTimeoutException` dědí z PHP `RuntimeException`. diff --git a/utils/en/@home.texy b/utils/en/@home.texy index e55b0ef0b5..87265f8c7c 100644 --- a/utils/en/@home.texy +++ b/utils/en/@home.texy @@ -18,6 +18,7 @@ In the `nette/utils` package, you will find a set of useful classes for everyday | [Paginator |paginator] | Nette\Utils\Paginator | [PHP Reflection |reflection] | Nette\Utils\Reflection | [PHP Types |type] | Nette\Utils\Type +| [Process] | Nette\Utils\Process | [Random Strings |random] | Nette\Utils\Random | [Strings] | Nette\Utils\Strings | [SmartObject] & [StaticClass] | Nette\SmartObject & Nette\StaticClass diff --git a/utils/en/@left-menu.texy b/utils/en/@left-menu.texy index c614d7a438..ef22611602 100644 --- a/utils/en/@left-menu.texy +++ b/utils/en/@left-menu.texy @@ -14,6 +14,7 @@ Nette Utils - [Paginator] - [PHP Reflection |reflection] - [PHP Types |type] +- [Process] - [Random Strings |random] - [Strings] - [SmartObject] diff --git a/utils/en/filesystem.texy b/utils/en/filesystem.texy index f8e43ddf3e..e2a9367918 100644 --- a/utils/en/filesystem.texy +++ b/utils/en/filesystem.texy @@ -134,6 +134,18 @@ FileSystem::isAbsolute('C:/backup'); // true ``` +isValidFilename(string $name): bool .[method] +--------------------------------------------- + +Checks whether `$name` is a valid cross-platform file name with no path information. Rejects empty strings, `.` and `..`, control characters, the characters `<>:"|?*\/`, names ending with a dot or space, and Windows reserved names (`CON`, `NUL`, `COM1`, …). + +```php +FileSystem::isValidFilename('photo.jpg'); // true +FileSystem::isValidFilename('../photo.jpg'); // false +FileSystem::isValidFilename('CON'); // false +``` + + joinPaths(string ...$segments): string .[method] ------------------------------------------------ Joins all path segments and normalizes the result. diff --git a/utils/en/images.texy b/utils/en/images.texy index 6485f905a3..913fc75479 100644 --- a/utils/en/images.texy +++ b/utils/en/images.texy @@ -255,14 +255,14 @@ static fromBlank(int $width, int $height, ?ImageColor $color=null): Image .[meth Creates a new true color image of the given dimensions. The default color is black. -static fromFile(string $file, int &$detectedFormat=null): Image .[method] -------------------------------------------------------------------------- -Reads an image from a file and returns its [type |#Formats] in `$detectedFormat`. +static fromFile(string $file, int &$detectedFormat=null, string &$warnings=null): Image .[method] +------------------------------------------------------------------------------------------------- +Reads an image from a file and returns its [type |#Formats] in `$detectedFormat`. If you pass `$warnings`, any non-fatal warnings from the image decoder are stored in it instead of being raised as a PHP warning; it stays `null` when there are none. -static fromString(string $s, int &$detectedFormat=null): Image .[method] ------------------------------------------------------------------------- -Reads an image from a string and returns its [type |#Formats] in `$detectedFormat`. +static fromString(string $s, int &$detectedFormat=null, string &$warnings=null): Image .[method] +------------------------------------------------------------------------------------------------ +Reads an image from a string and returns its [type |#Formats] in `$detectedFormat`. If you pass `$warnings`, any non-fatal warnings from the image decoder are stored in it instead of being raised as a PHP warning; it stays `null` when there are none. static rgb(int $red, int $green, int $blue, int $transparency=0): array .[method][deprecated] diff --git a/utils/en/process.texy b/utils/en/process.texy new file mode 100644 index 0000000000..3cd6b877d5 --- /dev/null +++ b/utils/en/process.texy @@ -0,0 +1,382 @@ +Process: Running External Programs .{data-version:4.1.4} +******************************************************** + +.[perex] +[api:Nette\Utils\Process] lets you run external programs from PHP: feed them input, read their output, and react to how they finished. It's a friendly wrapper around PHP's `proc_open()` that reports errors by throwing exceptions instead of returning `false`. + + +Installation: + +```shell +composer require nette/utils +``` + +All examples assume the following alias is defined: + +```php +use Nette\Utils\Process; +``` + + +The Simplest Use +================ + +Do you want to run a program and read what it printed? That's all it takes: + +```php +$process = Process::runExecutable('git', ['log', '-1', '--format=%H']); +echo $process->getStdOutput(); +``` + +The first argument is the program to run, the second is the list of its arguments: the same things you would type on the command line, just split into an array. The `getStdOutput()` method waits for the program to finish and returns everything it wrote to its standard output. + +That's the whole idea: you start a process, and then you ask it questions: is it still running, what did it print, how did it end. The rest of this page goes through those questions one by one. + + +Starting a Process +================== + +There are two ways to start a process, and the difference is worth understanding. + + +static runExecutable(string $executable, array $arguments=[], ?array $env=null, array $options=[], mixed $stdin='', mixed $stdout=null, mixed $stderr=null, ?string $directory=null, ?float $timeout=60): Process .[method] +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +Runs **one specific program** with a list of arguments. The arguments are handed to the program directly, so you never have to escape spaces, quotes, or other special characters. And because no shell is involved, there's no risk of *shell injection*. This is the safe choice, especially when any part of the command comes from user input: + +```php +$file = $_GET['file']; // could be anything, even '; rm -rf /' +$process = Process::runExecutable('wc', ['-l', $file]); // perfectly safe +``` + +The program is looked up in the system `PATH` if you don't give a full path. For running a PHP script, the `PHP_BINARY` constant comes in handy: + +```php +$process = Process::runExecutable(PHP_BINARY, ['-v']); +``` + + +static runCommand(string $command, ?array $env=null, array $options=[], mixed $stdin='', mixed $stdout=null, mixed $stderr=null, ?string $directory=null, ?float $timeout=60): Process .[method] +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +Runs **a command string through the system shell** (`/bin/sh` on Linux and macOS, `cmd.exe` on Windows). That gives you shell features: pipes `|`, redirects `>`, variable expansion, command chaining with `&&`, and so on: + +```php +$process = Process::runCommand('git log --oneline | head -n 20'); +``` + +But because the shell parses the whole string, **never build a `runCommand()` string out of untrusted input**, which is a classic security hole. When in doubt, use `runExecutable()` instead. + +.[note] +With this many parameters, pass them as named arguments, e.g. `Process::runExecutable('git', ['pull'], timeout: 30)`. The `$options` array is forwarded to `proc_open()` for advanced needs, such as `bypass_shell` on Windows. + + +The Process Runs in the Background +================================== + +Once started, the process runs **alongside** your PHP script: `runExecutable()` and `runCommand()` return immediately and don't wait for it to finish. You decide when (and whether) to wait: + +```php +$process = Process::runExecutable('npm', ['install']); + +// ... do other work here while npm runs ... + +$process->wait(); // now block until it's done +``` + +In practice you rarely call `wait()` yourself, because `getStdOutput()`, `getExitCode()`, `isSuccess()`, and `ensureSuccess()` all wait for the process automatically before giving you an answer. Call `wait()` explicitly when you want to pass it a [callback |#Watching the Output Live]. + + +isRunning(): bool .[method] +--------------------------- + +Returns `true` while the process is still running, `false` once it has finished or been terminated. Handy for doing other work in the meantime: + +```php +while ($process->isRunning()) { + // do something else for a while + usleep(100_000); // 100 ms +} +``` + + +How Did It End? +=============== + +Every finished process has an *exit code*: by convention `0` means success and any other number means some kind of failure (what exactly depends on the program). + + +getExitCode(): int .[method] +---------------------------- + +Returns the exit code, waiting for the process to finish first if needed: + +```php +$code = Process::runExecutable('git', ['pull'])->getExitCode(); // e.g. 0 +``` + + +isSuccess(): bool .[method] +--------------------------- + +A shortcut for "did the exit code equal `0`?": + +```php +$process = Process::runExecutable('git', ['pull']); +if (!$process->isSuccess()) { + echo 'git failed: ' . $process->getStdError(); +} +``` + + +ensureSuccess(): void .[method] +------------------------------- + +Often you just want the program to succeed and to fail loudly otherwise. `ensureSuccess()` waits for the process and throws `Nette\Utils\ProcessFailedException` if the exit code isn't `0`: + +```php +Process::runExecutable('git', ['pull'])->ensureSuccess(); +// execution continues only if git succeeded +``` + + +Reading the Output +================== + +A process has two separate output streams: **standard output** (the normal results) and **standard error** (where programs usually report problems and diagnostics). Nette Utils keeps the two apart and, by default, captures both into memory so you can read them whenever you want. + + +getStdOutput(): string .[method] +-------------------------------- + +Waits for the process to finish and returns everything it wrote to standard output: + +```php +$process = Process::runExecutable('date'); +echo $process->getStdOutput(); +``` + + +getStdError(): string .[method] +------------------------------- + +The same, but for standard error: + +```php +$process = Process::runExecutable('some-tool', ['--do-stuff']); +if (!$process->isSuccess()) { + throw new RuntimeException('The tool failed: ' . $process->getStdError()); +} +``` + +.[note] +If you [redirect an output stream |#Redirecting the Output Elsewhere] (to a file, a resource, or `false`), there is nothing in memory to return and the matching getter throws `Nette\InvalidStateException`. + + +consumeStdOutput(): string .[method] +------------------------------------ + +Sometimes you want to see the output **as it arrives**, without waiting for the process to end, for example to show progress. Each call returns the chunk of standard output that has appeared since the previous call: + +```php +$process = Process::runExecutable('long-running-tool'); + +while ($process->isRunning()) { + echo $process->consumeStdOutput(); // prints whatever is new + usleep(100_000); // 100 ms +} +echo $process->consumeStdOutput(); // the final piece, produced just before it ended +``` + +The `consumeStdOutput()` after the loop matters: the process may have written its last output during the final `usleep()`, after the last in-loop call but before the loop noticed it had exited. (If it instead finished during an in-loop call, that call already returned everything and this one returns an empty string.) There's `consumeStdError()` for standard error too. + + +Watching the Output Live +======================== + +Instead of polling with `consumeStdOutput()`, you can hand `wait()` a callback. It will be invoked every time new output appears, which is great for live logging or forwarding the output somewhere: + +```php +$process = Process::runExecutable('npm', ['install']); + +$process->wait(function (string $stdOut, string $stdErr) { + echo $stdOut; // forward standard output + fwrite(STDERR, $stdErr); // and standard error +}); +``` + +The callback gets two strings: the new standard-output data and the new standard-error data since the previous call (either may be empty). When `wait()` returns, the process is finished and you can still call `getExitCode()`, `getStdOutput()`, and the rest. + + +Sending Input +============= + +The `$stdin` parameter says what the process reads on its standard input. It accepts a few different things. + +**A string** becomes the process's entire input: + +```php +$process = Process::runExecutable('wc', ['-c'], stdin: 'hello world'); +echo $process->getStdOutput(); // 11 +``` + +**A readable resource** (an open file, a stream) is copied to the input: + +```php +$file = fopen('data.csv', 'r'); +$process = Process::runExecutable('sort', stdin: $file); +``` + +**`null`** keeps the input open so you can write to it gradually (see below). + +The default is an empty string, which means the process gets an empty, immediately-closed input. That's the sensible default: it stops programs that read input from hanging forever waiting for something that never comes. + + +writeStdInput(string $string): void .[method] +--------------------------------------------- + +When you start the process with `stdin: null`, the input stays open and you feed it piece by piece. Call `closeStdInput()` when you're done. That tells the program no more input is coming (it sends an end-of-file): + +```php +$process = Process::runExecutable('some-repl', stdin: null); +$process->writeStdInput("first command\n"); +$process->writeStdInput("second command\n"); +$process->closeStdInput(); +echo $process->getStdOutput(); +``` + +.[note] +A string or stream passed as `$stdin` is written all at once before the process really gets going. If that input is large *and* the program produces a lot of output without reading its input first, both sides can get stuck waiting for each other. In that (rare) case, use `stdin: null` and `writeStdInput()` to interleave writing with reading. + + +Chaining Processes (Piping) +=========================== + +You can connect one process's standard output straight to another's standard input, exactly like a shell pipe `|`. Just pass a `Process` as the `$stdin`: + +```php +$producer = Process::runExecutable('cat', ['big.log']); +$consumer = Process::runExecutable('grep', ['error'], stdin: $producer); + +echo $consumer->getStdOutput(); +``` + +You can chain as many processes as you like (`a | b | c`). + +.[note] +Piping processes together is **not supported on Windows** (it throws `Nette\NotSupportedException`). On Windows, capture the first process's output with `getStdOutput()` and pass it to the next one as a string. + + +Redirecting the Output Elsewhere +================================ + +By default, standard output and standard error are captured into memory. The `$stdout` and `$stderr` parameters let you send them somewhere else instead. + +**A filename** sends the output to that file: + +```php +Process::runExecutable('mysqldump', ['mydb'], stdout: 'backup.sql') + ->ensureSuccess(); +``` + +**A writable resource** sends the output to that stream. It must be backed by a real file (not `php://memory` and the like): + +```php +$log = fopen('build.log', 'a'); +Process::runExecutable('make', stdout: $log, stderr: $log); +``` + +**`false`** discards the output entirely (it goes to `/dev/null`, or `NUL` on Windows): + +```php +Process::runExecutable('noisy-tool', stderr: false); +``` + +Redirecting also keeps memory usage down: capturing into memory is convenient, but a process that prints gigabytes would use gigabytes of RAM, so write such output to a file. + + +Environment Variables +===================== + +The `$env` parameter sets the environment variables the process will see. Leave it as `null` (the default) to inherit the current process's environment, or pass an array to set them yourself: + +```php +// the current environment plus one extra variable +$process = Process::runExecutable('printenv', ['MY_VAR'], env: ['MY_VAR' => '123'] + getenv()); + +// a completely empty environment +$process = Process::runExecutable('some-tool', env: []); +``` + + +Working Directory +================= + +The `$directory` parameter sets the directory the process starts in (by default it's the current one): + +```php +$process = Process::runExecutable('git', ['status'], directory: '/path/to/repo'); +``` + + +Time Limit +========== + +The `$timeout` parameter (in seconds, `60` by default) caps how long you'll wait for the process. If the limit is reached while you are waiting for it or reading its output, the process is killed and `Nette\Utils\ProcessTimeoutException` is thrown. Pass `null` to remove the limit: + +```php +$process = Process::runExecutable('slow-tool', timeout: 5.0); +try { + $process->wait(); +} catch (Nette\Utils\ProcessTimeoutException $e) { + echo 'The tool took too long and was terminated.'; +} +``` + +The limit is only checked while you're inside `wait()`, `getExitCode()`, the output getters, or `consume*()`. A process you start and then never wait on is not killed by it. + + +Stopping a Process +================== + + +terminate(): void .[method] +--------------------------- + +Kills the process immediately if it's still running; does nothing if it has already finished: + +```php +$process = Process::runExecutable('server'); +// ... +$process->terminate(); +``` + +A process is also terminated automatically when its `Process` object is destroyed (for instance, goes out of scope) before it has finished. + +.[note] +To run a process that should outlive the PHP script (a daemon, a background job), launch it detached via the shell rather than through `Process`, e.g. `nohup yourtask >/dev/null 2>&1 &` on POSIX or `start /b yourtask` on Windows. + + +getPid(): ?int .[method] +------------------------ + +Returns the operating-system process ID (PID) while the process is running, or `null` once it has finished: + +```php +$pid = $process->getPid(); +``` + + +When Something Goes Wrong +========================= + +Errors are always reported by throwing an exception, never by a return value: + +| `Nette\Utils\ProcessFailedException` | the process could not be started, or `ensureSuccess()` was called and the exit code wasn't `0` +| `Nette\Utils\ProcessTimeoutException` | the `$timeout` limit was exceeded +| `Nette\InvalidArgumentException` | an invalid value was passed as `$stdin`, `$stdout`, or `$stderr` +| `Nette\IOException` | a file given as `$stdout` or `$stderr` could not be opened +| `Nette\InvalidStateException` | reading output that wasn't captured, or writing to a STDIN that's already closed +| `Nette\NotSupportedException` | process piping was attempted on Windows + +`ProcessFailedException` and `ProcessTimeoutException` extend PHP's `RuntimeException`. From 120e4fa160dcc2c73348bd0c1a136e0d343b60b4 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Sun, 17 May 2026 21:24:48 +0200 Subject: [PATCH 31/50] nette/database 3.2.9 --- database/cs/exceptions.texy | 5 ++++- database/en/exceptions.texy | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/database/cs/exceptions.texy b/database/cs/exceptions.texy index e78dd0108d..f06d44a561 100644 --- a/database/cs/exceptions.texy +++ b/database/cs/exceptions.texy @@ -10,11 +10,14 @@ Nette Database používá hierarchii výjimek. Základní třídou je `Nette\Dat Z `DriverException` dědí následující specializované výjimky: - `ConnectionException` - signalizuje selhání připojení k databázovému serveru + - `ConnectionLostException` .{data-version:3.2.9} - spojení bylo ztraceno během operace (restart serveru, výpadek sítě, idle timeout); před dalším použitím je potřeba se znovu připojit - `ConstraintViolationException` - základní třída pro porušení databázových omezení, ze které dědí: - `ForeignKeyConstraintViolationException` - porušení cizího klíče - `NotNullConstraintViolationException` - porušení NOT NULL omezení - `UniqueConstraintViolationException` - porušení unikátnosti hodnoty - + - `CheckConstraintViolationException` .{data-version:3.2.9} - porušení CHECK omezení +- `DeadlockException` .{data-version:3.2.9} - deadlock nebo serializační konflikt zjištěný serverem; transakce byla zrušena a operaci lze zopakovat +- `LockTimeoutException` .{data-version:3.2.9} - vypršel časový limit při čekání na zámek; příkaz byl přerušen, okolní transakce obvykle zůstává otevřená Příklad zachytávání výjimky `UniqueConstraintViolationException`, která nastane, když se snažíme vložit uživatele s emailem, který už v databázi existuje (za předpokladu, že sloupec email má unikátní index). diff --git a/database/en/exceptions.texy b/database/en/exceptions.texy index d3780dcacc..dca25c556e 100644 --- a/database/en/exceptions.texy +++ b/database/en/exceptions.texy @@ -10,11 +10,14 @@ Nette Database uses an exception hierarchy. The base class is `Nette\Database\Dr The `DriverException` class is extended by the following specialized exceptions: - `ConnectionException` – indicates a failure to connect to the database server. + - `ConnectionLostException` .{data-version:3.2.9} – the connection was dropped during an operation (server restart, network failure, idle timeout); a reconnect is required before further use. - `ConstraintViolationException` – the base class for database constraint violations, from which the following exceptions inherit: - `ForeignKeyConstraintViolationException` – violation of a foreign key constraint. - `NotNullConstraintViolationException` – violation of a NOT NULL constraint. - `UniqueConstraintViolationException` – violation of a uniqueness constraint. - + - `CheckConstraintViolationException` .{data-version:3.2.9} – violation of a CHECK constraint. +- `DeadlockException` .{data-version:3.2.9} – a deadlock or serialization failure detected by the server; the transaction was rolled back and may be retried. +- `LockTimeoutException` .{data-version:3.2.9} – a lock-wait timeout was exceeded; the statement was aborted, but the surrounding transaction typically remains open. The following example demonstrates how to catch a `UniqueConstraintViolationException`, which occurs when trying to insert a user with an email that already exists in the database (assuming the `email` column has a unique index): From 174c3a3dd07a898f4a22ec55b524c1a7a32d251c Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Sun, 17 May 2026 20:37:25 +0200 Subject: [PATCH 32/50] database: renamed mapping.texy to type-conversion.texy The page contains documentation of automatic type conversion (date, boolean, numeric), not entity mapping. Renaming clarifies the purpose and frees the `mapping` URL for upcoming entity mapping documentation. --- database/bg/@left-menu.texy | 2 +- database/bg/{mapping.texy => type-conversion.texy} | 0 database/cs/@left-menu.texy | 2 +- database/cs/{mapping.texy => type-conversion.texy} | 0 database/de/@left-menu.texy | 2 +- database/de/{mapping.texy => type-conversion.texy} | 0 database/el/@left-menu.texy | 2 +- database/el/{mapping.texy => type-conversion.texy} | 0 database/en/@left-menu.texy | 2 +- database/en/{mapping.texy => type-conversion.texy} | 0 database/es/@left-menu.texy | 2 +- database/es/{mapping.texy => type-conversion.texy} | 0 database/fr/@left-menu.texy | 2 +- database/fr/{mapping.texy => type-conversion.texy} | 0 database/hu/@left-menu.texy | 2 +- database/hu/{mapping.texy => type-conversion.texy} | 0 database/it/@left-menu.texy | 2 +- database/it/{mapping.texy => type-conversion.texy} | 0 database/ja/@left-menu.texy | 2 +- database/ja/{mapping.texy => type-conversion.texy} | 0 database/pl/@left-menu.texy | 2 +- database/pl/{mapping.texy => type-conversion.texy} | 0 database/pt/@left-menu.texy | 2 +- database/pt/{mapping.texy => type-conversion.texy} | 0 database/ro/@left-menu.texy | 2 +- database/ro/{mapping.texy => type-conversion.texy} | 0 database/ru/@left-menu.texy | 2 +- database/ru/{mapping.texy => type-conversion.texy} | 0 database/sl/@left-menu.texy | 2 +- database/sl/{mapping.texy => type-conversion.texy} | 0 database/tr/@left-menu.texy | 2 +- database/tr/{mapping.texy => type-conversion.texy} | 0 database/uk/@left-menu.texy | 2 +- database/uk/{mapping.texy => type-conversion.texy} | 0 34 files changed, 17 insertions(+), 17 deletions(-) rename database/bg/{mapping.texy => type-conversion.texy} (100%) rename database/cs/{mapping.texy => type-conversion.texy} (100%) rename database/de/{mapping.texy => type-conversion.texy} (100%) rename database/el/{mapping.texy => type-conversion.texy} (100%) rename database/en/{mapping.texy => type-conversion.texy} (100%) rename database/es/{mapping.texy => type-conversion.texy} (100%) rename database/fr/{mapping.texy => type-conversion.texy} (100%) rename database/hu/{mapping.texy => type-conversion.texy} (100%) rename database/it/{mapping.texy => type-conversion.texy} (100%) rename database/ja/{mapping.texy => type-conversion.texy} (100%) rename database/pl/{mapping.texy => type-conversion.texy} (100%) rename database/pt/{mapping.texy => type-conversion.texy} (100%) rename database/ro/{mapping.texy => type-conversion.texy} (100%) rename database/ru/{mapping.texy => type-conversion.texy} (100%) rename database/sl/{mapping.texy => type-conversion.texy} (100%) rename database/tr/{mapping.texy => type-conversion.texy} (100%) rename database/uk/{mapping.texy => type-conversion.texy} (100%) diff --git a/database/bg/@left-menu.texy b/database/bg/@left-menu.texy index 928b1f73ea..d0fed337a9 100644 --- a/database/bg/@left-menu.texy +++ b/database/bg/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Трансакции |transactions] - [Изключения |exceptions] - [Рефлексия |reflection] -- [Мапинг |mapping] +- [Мапинг |type-conversion] - [Конфигурация |configuration] - [Рискове за сигурността |security] - [Надграждане |en:upgrading] diff --git a/database/bg/mapping.texy b/database/bg/type-conversion.texy similarity index 100% rename from database/bg/mapping.texy rename to database/bg/type-conversion.texy diff --git a/database/cs/@left-menu.texy b/database/cs/@left-menu.texy index 6cb0892efa..1f70db2700 100644 --- a/database/cs/@left-menu.texy +++ b/database/cs/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Transakce |transactions] - [Výjimky |exceptions] - [Reflexe |reflection] -- [Mapování |mapping] +- [Konverze typů |type-conversion] - [Konfigurace |configuration] - [Bezpečnostní rizika |security] - [Upgrade |upgrading] diff --git a/database/cs/mapping.texy b/database/cs/type-conversion.texy similarity index 100% rename from database/cs/mapping.texy rename to database/cs/type-conversion.texy diff --git a/database/de/@left-menu.texy b/database/de/@left-menu.texy index a174fb97e9..b52d2535b7 100644 --- a/database/de/@left-menu.texy +++ b/database/de/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Transaktionen |transactions] - [Ausnahmen |exceptions] - [Reflexion |reflection] -- [Mapping |mapping] +- [Mapping |type-conversion] - [Konfiguration |configuration] - [Sicherheitsrisiken |security] - [Upgrade |en:upgrading] diff --git a/database/de/mapping.texy b/database/de/type-conversion.texy similarity index 100% rename from database/de/mapping.texy rename to database/de/type-conversion.texy diff --git a/database/el/@left-menu.texy b/database/el/@left-menu.texy index 2bfe03617b..d6e6721261 100644 --- a/database/el/@left-menu.texy +++ b/database/el/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Συναλλαγές |transactions] - [Εξαιρέσεις |exceptions] - [Reflection |reflection] -- [Αντιστοίχιση |mapping] +- [Αντιστοίχιση |type-conversion] - [Διαμόρφωση |configuration] - [Κίνδυνοι ασφαλείας |security] - [Αναβάθμιση |en:upgrading] diff --git a/database/el/mapping.texy b/database/el/type-conversion.texy similarity index 100% rename from database/el/mapping.texy rename to database/el/type-conversion.texy diff --git a/database/en/@left-menu.texy b/database/en/@left-menu.texy index f865f8027e..83c1eb8a7a 100644 --- a/database/en/@left-menu.texy +++ b/database/en/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Transactions] - [Exceptions] - [Reflection] -- [Mapping] +- [Type Conversion |type-conversion] - [Configuration] - [Security Risks |security] - [Upgrading] diff --git a/database/en/mapping.texy b/database/en/type-conversion.texy similarity index 100% rename from database/en/mapping.texy rename to database/en/type-conversion.texy diff --git a/database/es/@left-menu.texy b/database/es/@left-menu.texy index 334a1f0ecd..ac119a7204 100644 --- a/database/es/@left-menu.texy +++ b/database/es/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Transacciones |transactions] - [Excepciones |exceptions] - [Reflexión |reflection] -- [Mapeo |mapping] +- [Mapeo |type-conversion] - [Configuración |configuration] - [Riesgos de seguridad |security] - [Actualización |en:upgrading] diff --git a/database/es/mapping.texy b/database/es/type-conversion.texy similarity index 100% rename from database/es/mapping.texy rename to database/es/type-conversion.texy diff --git a/database/fr/@left-menu.texy b/database/fr/@left-menu.texy index bf2b375e4d..b54d7daab7 100644 --- a/database/fr/@left-menu.texy +++ b/database/fr/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Transactions |transactions] - [Exceptions |exceptions] - [Réflexion |reflection] -- [Mapping |mapping] +- [Mapping |type-conversion] - [Configuration |configuration] - [Risques de sécurité |security] - [Mise à niveau |en:upgrading] diff --git a/database/fr/mapping.texy b/database/fr/type-conversion.texy similarity index 100% rename from database/fr/mapping.texy rename to database/fr/type-conversion.texy diff --git a/database/hu/@left-menu.texy b/database/hu/@left-menu.texy index 6bf3ca54b9..2b9f11fd5e 100644 --- a/database/hu/@left-menu.texy +++ b/database/hu/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Tranzakciók |transactions] - [Kivételek |exceptions] - [Reflexió |reflection] -- [Leképezés |mapping] +- [Leképezés |type-conversion] - [Konfiguráció |configuration] - [Biztonsági kockázatok |security] - [Frissítés |en:upgrading] diff --git a/database/hu/mapping.texy b/database/hu/type-conversion.texy similarity index 100% rename from database/hu/mapping.texy rename to database/hu/type-conversion.texy diff --git a/database/it/@left-menu.texy b/database/it/@left-menu.texy index 58127bb77b..421ffa9bce 100644 --- a/database/it/@left-menu.texy +++ b/database/it/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Transazioni |transactions] - [Eccezioni |exceptions] - [Riflessione |reflection] -- [Mappatura |mapping] +- [Mappatura |type-conversion] - [Configurazione |configuration] - [Rischi per la sicurezza |security] - [Aggiornamento |en:upgrading] diff --git a/database/it/mapping.texy b/database/it/type-conversion.texy similarity index 100% rename from database/it/mapping.texy rename to database/it/type-conversion.texy diff --git a/database/ja/@left-menu.texy b/database/ja/@left-menu.texy index 4b7d6758d8..0103373e5c 100644 --- a/database/ja/@left-menu.texy +++ b/database/ja/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [トランザクション |transactions] - [例外 |exceptions] - [リフレクション |reflection] -- [マッピング |mapping] +- [マッピング |type-conversion] - [設定 |configuration] - [セキュリティリスク |security] - [アップグレード |en:upgrading] diff --git a/database/ja/mapping.texy b/database/ja/type-conversion.texy similarity index 100% rename from database/ja/mapping.texy rename to database/ja/type-conversion.texy diff --git a/database/pl/@left-menu.texy b/database/pl/@left-menu.texy index 635d04210c..65bd87f505 100644 --- a/database/pl/@left-menu.texy +++ b/database/pl/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Transakcje |transactions] - [Wyjątki |exceptions] - [Refleksja |reflection] -- [Mapowanie |mapping] +- [Mapowanie |type-conversion] - [Konfiguracja |configuration] - [Zagrożenia bezpieczeństwa |security] - [Aktualizacja |en:upgrading] diff --git a/database/pl/mapping.texy b/database/pl/type-conversion.texy similarity index 100% rename from database/pl/mapping.texy rename to database/pl/type-conversion.texy diff --git a/database/pt/@left-menu.texy b/database/pt/@left-menu.texy index b1a45ab3c0..2d2896d66b 100644 --- a/database/pt/@left-menu.texy +++ b/database/pt/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Transações |transactions] - [Exceções |exceptions] - [Reflexão |reflection] -- [Mapeamento |mapping] +- [Mapeamento |type-conversion] - [Configuração |configuration] - [Riscos de segurança |security] - [Atualização |en:upgrading] diff --git a/database/pt/mapping.texy b/database/pt/type-conversion.texy similarity index 100% rename from database/pt/mapping.texy rename to database/pt/type-conversion.texy diff --git a/database/ro/@left-menu.texy b/database/ro/@left-menu.texy index 7e37400986..db1ab4a266 100644 --- a/database/ro/@left-menu.texy +++ b/database/ro/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Tranzacții |transactions] - [Excepții |exceptions] - [Reflecție |reflection] -- [Mapare |mapping] +- [Mapare |type-conversion] - [Configurație |configuration] - [Riscuri de securitate |security] - [Actualizare |en:upgrading] diff --git a/database/ro/mapping.texy b/database/ro/type-conversion.texy similarity index 100% rename from database/ro/mapping.texy rename to database/ro/type-conversion.texy diff --git a/database/ru/@left-menu.texy b/database/ru/@left-menu.texy index 91864ddc35..88521f43d7 100644 --- a/database/ru/@left-menu.texy +++ b/database/ru/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Транзакции |transactions] - [Исключения |exceptions] - [Рефлексия |reflection] -- [Маппинг |mapping] +- [Маппинг |type-conversion] - [Конфигурация |configuration] - [Риски безопасности |security] - [Обновление |en:upgrading] diff --git a/database/ru/mapping.texy b/database/ru/type-conversion.texy similarity index 100% rename from database/ru/mapping.texy rename to database/ru/type-conversion.texy diff --git a/database/sl/@left-menu.texy b/database/sl/@left-menu.texy index 280bbea034..0a5b5c42b2 100644 --- a/database/sl/@left-menu.texy +++ b/database/sl/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Transakcije |transactions] - [Izjeme |exceptions] - [Refleksija |reflection] -- [Preslikava |mapping] +- [Preslikava |type-conversion] - [Konfiguracija |configuration] - [Varnostna tveganja |security] - [Nadgradnja |en:upgrading] diff --git a/database/sl/mapping.texy b/database/sl/type-conversion.texy similarity index 100% rename from database/sl/mapping.texy rename to database/sl/type-conversion.texy diff --git a/database/tr/@left-menu.texy b/database/tr/@left-menu.texy index 5a4cd8355f..ac89e59cd1 100644 --- a/database/tr/@left-menu.texy +++ b/database/tr/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [İşlemler |transactions] - [İstisnalar |exceptions] - [Yansıma |reflection] -- [Eşleme |mapping] +- [Eşleme |type-conversion] - [Yapılandırma |configuration] - [Güvenlik Riskleri |security] - [Yükseltme |en:upgrading] diff --git a/database/tr/mapping.texy b/database/tr/type-conversion.texy similarity index 100% rename from database/tr/mapping.texy rename to database/tr/type-conversion.texy diff --git a/database/uk/@left-menu.texy b/database/uk/@left-menu.texy index f8a09afcd7..8425fd5b2d 100644 --- a/database/uk/@left-menu.texy +++ b/database/uk/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Транзакції |transactions] - [Винятки |exceptions] - [Рефлексія |reflection] -- [Мапування |mapping] +- [Мапування |type-conversion] - [Конфігурація |configuration] - [Ризики безпеки |security] - [Оновлення |en:upgrading] diff --git a/database/uk/mapping.texy b/database/uk/type-conversion.texy similarity index 100% rename from database/uk/mapping.texy rename to database/uk/type-conversion.texy From d2e17f2e9c7950af09c82c42c25f9e52ec47f236 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Tue, 19 May 2026 23:26:20 +0200 Subject: [PATCH 33/50] nette/mail 4.1.2 --- mail/cs/@home.texy | 28 ++++++++++++++++++++++++++++ mail/en/@home.texy | 28 ++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/mail/cs/@home.texy b/mail/cs/@home.texy index fb72bf092d..3dde556165 100644 --- a/mail/cs/@home.texy +++ b/mail/cs/@home.texy @@ -310,6 +310,34 @@ $mailer->send($mail); Jako další parametry v konstruktoru můžeme uvést počet opakování a čekací dobu v milisekundách. +Ladění e-mailů .{data-version:4.1.2} +==================================== + +Při vývoji nebo na staging serveru nechcete, aby se nějaký testovací e-mail náhodou dostal k reálnému zákazníkovi. Existují dva způsoby, jak tomu zabránit. + +Pro lokální vývoj doporučujeme spustit u sebe lehký SMTP zachytávač jako "Mailpit":https://mailpit.axllent.org nebo "MailHog":https://github.com/mailhog/MailHog. Přijmou každou zprávu, ukáží ji ve webovém UI a nikdy nic nepředají dál – Nette Mailu jen nastavíte `127.0.0.1:1025`: + +```neon +mail: + smtp: true + host: 127.0.0.1 + port: 1025 +``` + +Pro staging nebo prostředí, kde lokální zachytávač spustit nejde, má Nette Mail vestavěný redirect. Nastavte cílovou adresu v konfiguraci a každý příjemce v `To`, `Cc` i `Bcc` bude nahrazen touto adresou. Nette Mail uloží originály do hlaviček `X-Original-*`, takže pořád vidíte, komu měl e-mail dorazit, a do předmětu lze přidat značku: + +```neon +mail: + redirect: + to: dev@example.com + subjectPrefix: '[debug]' # volitelný +``` + +Zkrácený zápis `redirect: dev@example.com` postačí, když nepotřebujete prefix v předmětu. V debug módu se automaticky připojí panel v [Tracy Baru |tracy:] s přehledem všech odeslaných e-mailů. + +Interně tohle zajišťuje [api:Nette\Mail\Interceptor], který nabízí ještě událost `$onSent` pro vlastní listenery (audit log, metriky, …). + + DKIM ==== diff --git a/mail/en/@home.texy b/mail/en/@home.texy index f867677234..12173929aa 100644 --- a/mail/en/@home.texy +++ b/mail/en/@home.texy @@ -310,6 +310,34 @@ $mailer->send($mail); Other parameters in the constructor include the number of retries and the waiting time in milliseconds. +Debugging Emails .{data-version:4.1.2} +====================================== + +When developing or running a staging server, you don't want a test email to slip out to a real customer. There are two ways to make sure that never happens. + +The recommended local setup is to run a lightweight SMTP catcher like "Mailpit":https://mailpit.axllent.org or "MailHog":https://github.com/mailhog/MailHog on your machine. They accept every message, show it in a web UI, and never forward anything – you just point Nette Mail at `127.0.0.1:1025`: + +```neon +mail: + smtp: true + host: 127.0.0.1 + port: 1025 +``` + +For staging or environments where you can't run a local catcher, Nette Mail has a built-in redirect. Set the destination in the configuration and every `To`, `Cc`, and `Bcc` recipient is replaced with it. Nette Mail preserves the originals in `X-Original-*` headers so you can see who the email was meant for, and you can prepend a marker to the subject: + +```neon +mail: + redirect: + to: dev@example.com + subjectPrefix: '[debug]' # optional +``` + +The shortcut form `redirect: dev@example.com` works when you don't need a subject prefix. In debug mode, a [Tracy Bar |tracy:] panel listing all sent emails attaches automatically. + +Internally this is handled by [api:Nette\Mail\Interceptor], which also exposes an `$onSent` event for custom listeners (audit logs, metrics, …). + + DKIM ==== From 1be209f05c47b4910c1cae8c7983a378c1a0d733 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Wed, 20 May 2026 05:29:25 +0200 Subject: [PATCH 34/50] best-practices: add 'Pretty URLs with Slugs' guide --- application/cs/presenters.texy | 2 + application/cs/routing.texy | 2 + application/en/presenters.texy | 2 + application/en/routing.texy | 2 + best-practices/cs/@home.texy | 1 + best-practices/cs/pretty-urls.texy | 204 +++++++++++++++++++++++++++++ best-practices/en/@home.texy | 1 + best-practices/en/pretty-urls.texy | 204 +++++++++++++++++++++++++++++ 8 files changed, 418 insertions(+) create mode 100644 best-practices/cs/pretty-urls.texy create mode 100644 best-practices/en/pretty-urls.texy diff --git a/application/cs/presenters.texy b/application/cs/presenters.texy index 04cd942e32..f00a645bba 100644 --- a/application/cs/presenters.texy +++ b/application/cs/presenters.texy @@ -393,6 +393,8 @@ public function actionShow(int $id, ?string $slug = null): void } ``` +Kompletní vzor, který kombinuje routovací filtry s `canonicalize()` pro generování SEO-friendly URL, najdete v návodu [Hezké URL se slugem |best-practices:pretty-urls]. + Události -------- diff --git a/application/cs/routing.texy b/application/cs/routing.texy index 3a2e753731..b5a7648612 100644 --- a/application/cs/routing.texy +++ b/application/cs/routing.texy @@ -325,6 +325,8 @@ Obecné filtry dávají možnost upravit chování routy naprosto jakýmkoliv zp Pokud má parametr definovaný vlastní filtr a současně existuje obecný filtr, provede se vlastní `FilterIn` před obecným a naopak obecný `FilterOut` před vlastním. Tedy uvnitř obecného filtru jsou hodnoty parametrů `presenter` resp. `action` zapsané ve stylu PascalCase resp. camelCase. +Praktické využití těchto filtrů — generování SEO-friendly URL typu `/clanek/123-jak-upect-chleba` bez zásahu do šablon — najdete v návodu [Hezké URL se slugem |best-practices:pretty-urls]. + Jednosměrky OneWay ------------------ diff --git a/application/en/presenters.texy b/application/en/presenters.texy index 7658686bbf..272c3216f9 100644 --- a/application/en/presenters.texy +++ b/application/en/presenters.texy @@ -393,6 +393,8 @@ public function actionShow(int $id, ?string $slug = null): void } ``` +For a complete pattern that combines route filters with `canonicalize()` to produce SEO-friendly URLs, see [Pretty URLs with Slugs |best-practices:pretty-urls]. + Events ------ diff --git a/application/en/routing.texy b/application/en/routing.texy index 4b83f317f2..8cf31e3c99 100644 --- a/application/en/routing.texy +++ b/application/en/routing.texy @@ -325,6 +325,8 @@ General filters provide the ability to modify the route's behavior in absolutely If a parameter has its own filter defined and a general filter also exists, the custom `FilterIn` is executed before the general one, and conversely, the general `FilterOut` is executed before the custom one. Thus, inside the general filter, the values of the parameters `presenter` and `action` are written in PascalCase or camelCase style, respectively. +See [Pretty URLs with Slugs |best-practices:pretty-urls] for a practical use of these filters — generating SEO-friendly URLs like `/article/123-how-to-bake-bread` without modifying any templates. + OneWay Flag ----------- diff --git a/best-practices/cs/@home.texy b/best-practices/cs/@home.texy index 612d75048f..38118d8894 100644 --- a/best-practices/cs/@home.texy +++ b/best-practices/cs/@home.texy @@ -19,6 +19,7 @@ Nette Aplikace - [Dynamické snippety |dynamic-snippets] - [Jak používat atribut #Requires |attribute-requires] - [Jak správně používat POST odkazy |post-links] +- [Hezké URL se slugem |pretty-urls] </div> <div> diff --git a/best-practices/cs/pretty-urls.texy b/best-practices/cs/pretty-urls.texy new file mode 100644 index 0000000000..b910f35371 --- /dev/null +++ b/best-practices/cs/pretty-urls.texy @@ -0,0 +1,204 @@ +Hezké URL se slugem +******************* + +.[perex] +URL jako `/clanek/123-jak-upect-chleba` vypadá lépe než `/clanek/123` a pomáhá uživatelům i vyhledávačům pochopit, co na stránce čeká. Tento návod ukazuje, jak je generovat čistě v routeru — bez zásahu do jediné šablony — a jak zařídit, aby každý návštěvník skončil na kanonické URL. + + +Proč slug v URL +=============== + +Porovnejte tyto dvě adresy: + +``` +/clanek/123 +/clanek/123-jak-upect-chleba +``` + +Druhá uživateli (a Googlu) prozradí, co ho po kliknutí čeká. To je dobré pro SEO, dělá odkazy čitelné v chatu nebo e-mailu a dá smysl i URL liště. + +Slug ale není skutečný identifikátor. Stránku určuje ID. Slug je jen dekorace, kterou aplikace generuje z titulku. Když se titulek změní, slug by se měl změnit taky. A když někdo URL ručně upraví nebo přijde po starém odkazu, aplikace by stejně měla najít správnou stránku. + + +Cíl +=== + +Chceme routu, která zvládne všechny tyto případy: + +``` +/clanek/123 → otevře článek 123, přesměruje na kanonickou URL +/clanek/123-jak-upect-chleba → otevře článek 123 přímo +/clanek/123-cokoli-co-nekdo-napsal → otevře článek 123, přesměruje na kanonickou URL +/clanek/ → 404 (chybí ID) +``` + +A chceme, aby každé `n:href` a `link()` napříč aplikací automaticky vyrobilo `/clanek/123-jak-upect-chleba` — **bez přepisování jediné šablony**. + + +Maska routy +=========== + +Trik spočívá v označení slugu v masce jako **nepovinného** pomocí hranatých závorek: + +```php +$router->addRoute('clanek/<id [0-9]+>[-<slug>]', 'Article:detail'); +``` + +Maska `[-<slug>]` říká: po ID může (ale nemusí) následovat pomlčka a slug. Routa přijímá `/clanek/123` i `/clanek/123-cokoli`. + +Poznámka k parametru `<slug>`: defaultně matchuje libovolné znaky **kromě lomítka** — přesně to, co chceme. Pokud napíšete `<slug .+>`, parametr bude matchovat i lomítka, takže `/clanek/123-neco/jineho` by se naparsovalo jako jediný slug obsahující `/`. Pokud nechcete lomítka ve slugu, zůstaňte u defaultního `<slug>`. + +URL se teď parsuje správně, ale generované odkazy slug neobsahují. Dalším krokem je routu naučit, jak slug doplnit. + + +Generování slugu bez zásahu do šablon +===================================== + +Tohle je hlavní varianta. Stávající `n:href="Article:detail, $id"` volání zůstávají beze změny napříč celou aplikací — router si titulek vyhledá sám. + +Použijeme **obecný filtr** pod klíčem prázdného stringu — ten vidí všechny parametry najednou a může slug doplnit: + +```php +use Nette\Routing\Route; +use Nette\Utils\Strings; + +$router->addRoute('clanek/<id [0-9]+>[-<slug>]', [ + 'presenter' => 'Article', + 'action' => 'detail', + '' => [ + Route::FilterOut => function (array $params) use ($slugProvider): array { + if (isset($params['id']) && empty($params['slug'])) { + $params['slug'] = $slugProvider->getSlug((int) $params['id']); + } + return $params; + }, + ], +]); +``` + +`FilterOut` se spustí pokaždé, když router **generuje** URL. Pokud slug nebyl předán, filtr titulek dohledá a doplní. + +Slugy můžete nasadit napříč celou aplikací jedinou změnou — jednou definicí routy. Každý odkaz v každé šabloně začne automaticky produkovat `/clanek/123-jak-upect-chleba`. Žádný grep, žádné hledání po šablonách, žádný přehlédnutý case. + + +Cache pro vyhledávání +===================== + +Jedno volání odkazu znamená jeden DB dotaz, ale typická stránka jich má hodně — výpisy, drobečková navigace, „naposledy prohlížené", související články. Stejné ID článku se v rámci jednoho requestu objeví v několika odkazech a nechceme do DB chodit pokaždé. + +Stačí drobná per-request cache. Obalte DB volání malou službou: + +```php +final class SlugProvider +{ + /** @var array<int, string> */ + private array $cache = []; + + public function __construct( + private Nette\Database\Explorer $db, + ) { + } + + public function getSlug(int $id): string + { + return $this->cache[$id] ??= Strings::webalize(Strings::truncate( + (string) $this->db->fetchField('SELECT title FROM article WHERE id = ?', $id), + 100, '' + )); + } +} +``` + +To stačí — jeden DB dotaz na unikátní ID za request. + + +Předání titulku ze šablony (volitelná rychlá cesta) +=================================================== + +Pokud máte titulek v šabloně po ruce, můžete se DB dotazu úplně vyhnout. Předejte titulek jako pojmenovaný parametr: + +```latte +<a n:href="Article:detail, $article->id, slug => $article->title">{$article->title}</a> +``` + +…a přidejte per-parametrový `FilterOut`, který titulek převede na URL-bezpečný tvar: + +```php +$router->addRoute('clanek/<id [0-9]+>[-<slug>]', [ + 'presenter' => 'Article', + 'action' => 'detail', + 'slug' => [ + Route::FilterOut => fn($title) => Strings::webalize(Strings::truncate($title, 100, '')), + ], + '' => [/* fallback s vyhledáním z předchozí ukázky */], +]); +``` + +Oba filtry spolupracují. Per-parametrový `FilterOut` proběhne první a předaný titulek převede na slug. Obecný filtr pak vidí, že slug je už vyplněn, a vyhledání v DB přeskočí. Šablony, které titulek nepředávají, dál fungují — projdou cestou s vyhledáváním. + +Použijte to jen tam, kde to opravdu hraje roli (velké výpisy renderované stokrát za request). Pro většinu aplikace cachované vyhledávání stačí. + + +Kanonizace: přesměrování na správnou URL +======================================== + +Umíme teď generovat `/clanek/123-jak-upect-chleba`, ale routa pořád přijímá `/clanek/123` i `/clanek/123-cokoli-co-nekdo-napsal`. To je záměr — chceme krátké URL (viz níže) a chceme, aby staré nebo ručně napsané odkazy fungovaly. Ale nechceme, aby vyhledávače indexovaly stejný článek pod několika adresami. + +Řešením je [kanonizace |application:presenters#kanonizace]: když uživatel přijde po nekanonické URL, aplikace ho přesměruje 301 na správnou. Stará se o to metoda `canonicalize()`: + +```php +public function actionDetail(int $id, ?string $slug = null): void +{ + $article = $this->facade->getArticle($id); + if (!$article) { + $this->error(); + } + + // vygeneruje kanonickou URL přes stejný FilterOut + // a pokud se liší od současné URL, přesměruje HTTP 301 + $this->canonicalize('detail', ['id' => $id]); + + $this->template->article = $article; +} +``` + +`canonicalize()` vygeneruje kanonickou URL stejným způsobem jako `link()` (takže projde stejným `FilterOut`) a porovná ji s aktuální URL. Pokud se liší, přesměruje HTTP 301. Návštěvník skončí na správné URL, vyhledávače vidí jen jednu kanonickou verzi. + + +Jedno místo, které určuje, jak slug vypadá +========================================== + +Všimněte si, že `Strings::webalize(Strings::truncate(..., 100, ''))` žije na **jediném místě** — uvnitř `SlugProvider` (nebo v per-parametrovém `FilterOut`). Stejná logika vyrobí odkaz v šabloně, URL v `redirect()` i kanonický tvar v `canonicalize()`. + +Když budete chtít pravidla později změnit (jiný limit délky, jiná transliterace, vyhazování dalších znaků), upravíte jeden řádek. Bez tohoto byste riskovali, že `redirect()` vygeneruje `/clanek/123-jak-upect-chleba`, zatímco `canonicalize()` bude očekávat `/clanek/123-jak-upect-chl` (protože někde někdo použil jiný `truncate`), a aplikace by se přesměrovávala donekonečna. + + +Bonus: krátké URL stále fungují +=============================== + +Protože je slug nepovinný, fungují i adresy bez něj: + +``` +/clanek/123 +``` + +To se hodí pro: +- **QR kódy** — kratší URL znamená méně hustý a lépe skenovatelný kód +- **SMS a chat** — vejde se do tweetu, vypadá úhledně +- **Tištěné materiály** — krátkou URL se rychleji napíše + +Když uživatel takovou URL otevře, `canonicalize()` ho přesměruje 301 na plnou verzi se slugem, takže vyhledávače stejně uvidí jen kanonický tvar. Můžete mít krátkost i SEO zároveň. + + +Shrnutí +======= + +- Maska `<id>[-<slug>]` dělá slug nepovinným. Defaultní `<slug>` nematchuje `/`; `<slug .+>` použijte jen tehdy, když opravdu chcete lomítka ve slugu. +- Obecný `FilterOut` pod klíčem `''` dohledá titulek podle ID — **bez zásahu do šablon kdekoli v aplikaci**. +- Vyhledávání obalte drobnou per-request cache; jeden DB dotaz na unikátní ID stačí. +- Volitelně může per-parametrový `FilterOut` umožnit šablonám titulek předat přímo a vyhledávání přeskočit. +- `$this->canonicalize()` v action přesměruje nekanonické URL na správnou s HTTP 301. +- Vzorec pro slug (`webalize` + `truncate`) žije na jednom místě — změníte ho jednou, projeví se všude. +- Krátké URL jen s ID dál fungují, což se hodí pro QR kódy a SMS. + +Více o filtrech a kanonizaci najdete v dokumentaci [routování |application:routing#obecne-filtry] a [presenterů |application:presenters#kanonizace]. diff --git a/best-practices/en/@home.texy b/best-practices/en/@home.texy index 04508b55aa..d41a3f0212 100644 --- a/best-practices/en/@home.texy +++ b/best-practices/en/@home.texy @@ -19,6 +19,7 @@ Nette Application - [Dynamic Snippets |dynamic-snippets] - [How to Use the #Requires Attribute |attribute-requires] - [How to Properly Use POST Links |post-links] +- [Pretty URLs with Slugs |pretty-urls] </div> <div> diff --git a/best-practices/en/pretty-urls.texy b/best-practices/en/pretty-urls.texy new file mode 100644 index 0000000000..8a2591101d --- /dev/null +++ b/best-practices/en/pretty-urls.texy @@ -0,0 +1,204 @@ +Pretty URLs with Slugs +********************** + +.[perex] +URLs like `/article/123-how-to-bake-bread` look better than `/article/123` and help both users and search engines understand what's on the page. This guide shows how to generate them entirely in the router — without touching a single template — and how to make sure every visitor lands on the canonical URL. + + +Why Slugs in URLs +================= + +Compare these two addresses: + +``` +/article/123 +/article/123-how-to-bake-bread +``` + +The second one tells the user (and Google) what awaits after the click. It's good for SEO, makes links readable in chat or e-mail, and gives the URL bar some meaning. + +The slug isn't a real identifier, though. The page is determined by the ID. The slug is decoration that the application generates from the title. If the title changes, the slug should change too. And if someone hand-edits the URL or follows an old link, the application should still find the right page. + + +The Goal +======== + +We want a route that handles all of these: + +``` +/article/123 → opens article 123, redirects to canonical URL +/article/123-how-to-bake-bread → opens article 123 directly +/article/123-anything-someone-typed → opens article 123, redirects to canonical URL +/article/ → 404 (no ID) +``` + +And we want every `n:href` and `link()` call across the application to automatically produce `/article/123-how-to-bake-bread` — **without rewriting a single template**. + + +The Route Mask +============== + +The trick is to mark the slug as **optional** in the mask using square brackets: + +```php +$router->addRoute('article/<id [0-9]+>[-<slug>]', 'Article:detail'); +``` + +The mask `[-<slug>]` says: there may be a hyphen and a slug after the ID, but it's not required. The route accepts both `/article/123` and `/article/123-anything`. + +A note on the parameter `<slug>`: by default it matches any characters **except a slash** — exactly what we want. If you write `<slug .+>`, the parameter will match slashes too, so `/article/123-something/else` would parse as a single slug containing `/`. Stay with the default `<slug>` unless you really need that. + +So far the URL is parsed correctly, but generated links won't contain the slug. The next step is to teach the route how to fill the slug in. + + +Generating the Slug Without Touching Templates +============================================== + +This is the killer variant. Existing `n:href="Article:detail, $id"` calls keep working unchanged across the whole application — the router looks the title up by itself. + +We do this with a **general filter** under the empty-string key — it sees all parameters at once and can add the slug: + +```php +use Nette\Routing\Route; +use Nette\Utils\Strings; + +$router->addRoute('article/<id [0-9]+>[-<slug>]', [ + 'presenter' => 'Article', + 'action' => 'detail', + '' => [ + Route::FilterOut => function (array $params) use ($slugProvider): array { + if (isset($params['id']) && empty($params['slug'])) { + $params['slug'] = $slugProvider->getSlug((int) $params['id']); + } + return $params; + }, + ], +]); +``` + +`FilterOut` runs every time the router **generates** a URL. If the slug wasn't passed in, the filter looks the title up and adds it. + +You can deploy slugs across a whole application in a single change — just one route definition. Every link in every template starts producing `/article/123-how-to-bake-bread` automatically. No grep, no template hunt, no missed corner case. + + +Cache the Lookup +================ + +One link generates one DB query, but a typical page has many — listings, breadcrumbs, "last viewed", related articles. The same article ID often appears in several links during a single request, and you don't want to hit the database every time. + +A tiny per-request cache solves this. Wrap the DB call in a small service: + +```php +final class SlugProvider +{ + /** @var array<int, string> */ + private array $cache = []; + + public function __construct( + private Nette\Database\Explorer $db, + ) { + } + + public function getSlug(int $id): string + { + return $this->cache[$id] ??= Strings::webalize(Strings::truncate( + (string) $this->db->fetchField('SELECT title FROM article WHERE id = ?', $id), + 100, '' + )); + } +} +``` + +That's enough — one DB hit per unique ID per request. + + +Passing the Title from the Template (Optional Fast Path) +======================================================== + +When the title is already at hand in the template, you can skip the DB lookup entirely. Pass the title as a named parameter: + +```latte +<a n:href="Article:detail, $article->id, slug => $article->title">{$article->title}</a> +``` + +…and add a per-parameter `FilterOut` that turns the title into a URL-safe string: + +```php +$router->addRoute('article/<id [0-9]+>[-<slug>]', [ + 'presenter' => 'Article', + 'action' => 'detail', + 'slug' => [ + Route::FilterOut => fn($title) => Strings::webalize(Strings::truncate($title, 100, '')), + ], + '' => [/* the lookup-fallback from above */], +]); +``` + +The two filters cooperate. The per-parameter `FilterOut` runs first and turns the supplied title into a slug. The general filter then sees the slug is already filled and skips the DB lookup. Templates that don't pass the title still work — they go through the lookup path. + +Use this only where it matters (large listings rendered hundreds of times per request). For most of the application the cached lookup is fast enough. + + +Canonization: Redirect to the Right URL +======================================= + +We can now generate `/article/123-how-to-bake-bread`, but the route still accepts `/article/123` and `/article/123-anything-someone-wrote`. That's deliberate — we want short URLs (more on that below) and we want old or hand-typed links to keep working. But we don't want search engines to index the same article under multiple addresses. + +The solution is [canonization |application:presenters#canonization]: when the user arrives via a non-canonical URL, the application 301-redirects them to the correct one. The `canonicalize()` method handles this: + +```php +public function actionDetail(int $id, ?string $slug = null): void +{ + $article = $this->facade->getArticle($id); + if (!$article) { + $this->error(); + } + + // generates the canonical URL through the same FilterOut + // and redirects with HTTP 301 if it differs from the current URL + $this->canonicalize('detail', ['id' => $id]); + + $this->template->article = $article; +} +``` + +`canonicalize()` generates the canonical URL the same way `link()` would (so it runs through the same `FilterOut`) and compares it to the current URL. If they differ, it redirects with HTTP 301. Visitors land on the right URL, search engines see only one canonical version. + + +One Place That Decides What the Slug Looks Like +=============================================== + +Notice that the `Strings::webalize(Strings::truncate(..., 100, ''))` call lives in a single place — inside `SlugProvider` (or the per-parameter `FilterOut`). The same logic produces the link in the template, the URL in `redirect()`, and the canonical form in `canonicalize()`. + +If you want to change the rules later (different length limit, different transliteration, stripping extra characters), you change one line. Without this, you'd risk `redirect()` generating `/article/123-how-to-bake-bread` while `canonicalize()` expects `/article/123-how-to-bake-bre` (because someone applied a different `truncate` length elsewhere), and the application would redirect in a loop. + + +Bonus: Short URLs Still Work +============================ + +Because the slug is optional, addresses without it still work: + +``` +/article/123 +``` + +This is useful for: +- **QR codes** — shorter URL means a less dense, more scannable code +- **SMS and chat** — fits in a tweet, looks tidy +- **Printed materials** — a short URL is faster to type + +When a user opens such a URL, `canonicalize()` 301-redirects them to the full version with the slug, so search engines still see only the canonical form. You can have shortness and SEO at the same time. + + +Summary +======= + +- Mask `<id>[-<slug>]` makes the slug optional. The default `<slug>` doesn't match `/`; use `<slug .+>` only if you really want slashes in the slug. +- A general `FilterOut` under the `''` key looks the title up by ID — **no template changes anywhere in the application**. +- Wrap the lookup in a tiny per-request cache; one DB query per unique ID is plenty. +- Optionally, a per-parameter `FilterOut` lets templates pass the title directly and skip the lookup. +- `$this->canonicalize()` in the action redirects non-canonical URLs to the right one with HTTP 301. +- The slug formula (`webalize` + `truncate`) lives in one place — change it once, take effect everywhere. +- Short ID-only URLs keep working, which is handy for QR codes and SMS. + +You'll find more about filters and canonization in the [routing |application:routing#general-filters] and [presenters |application:presenters#canonization] documentation. From 1fd57d901511fec2f5d2e85eed6d1e7d0e85c727 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Fri, 22 May 2026 14:21:17 +0200 Subject: [PATCH 35/50] latte: improve and clarify the grouping cookbook --- latte/cs/cookbook/grouping.texy | 54 +++++++++++++++++---------------- latte/en/cookbook/grouping.texy | 54 +++++++++++++++++---------------- 2 files changed, 56 insertions(+), 52 deletions(-) diff --git a/latte/cs/cookbook/grouping.texy b/latte/cs/cookbook/grouping.texy index bdb563efb5..34e1a2cff8 100644 --- a/latte/cs/cookbook/grouping.texy +++ b/latte/cs/cookbook/grouping.texy @@ -2,15 +2,17 @@ Všechno, co jste kdy chtěli vědět o seskupování *********************************************** .[perex] -Při práci s daty ve šablonách můžete často narazit na potřebu jejich seskupování nebo specifického zobrazení podle určitých kritérií. Latte pro tento účel nabízí hned několik silných nástrojů. +Při práci s daty ve šablonách často potřebujete položky seskupit, rozdělit do dávek nebo je procházet podle podmínky. Latte k tomu nabízí tři nástroje, z nichž každý se hodí na trochu jinou situaci. -Filtr a funkce `|group` umožňují efektivní seskupení dat podle zadaného kritéria, filtr `|batch` zase usnadňuje rozdělení dat do pevně daných dávek a značka `{iterateWhile}` poskytuje možnost složitějšího řízení průběhu cyklů s podmínkami. Každá z těchto značek nabízí specifické možnosti pro práci s daty, čímž se stávají nepostradatelnými nástroji pro dynamické a strukturované zobrazení informací v Latte šablonách. +Filtr `|group` a funkce `group()` seskupí položky podle zadaného kritéria, filtr `|batch` je rozdělí do dávek pevné velikosti a značka `{iterateWhile}` prochází data postupně a sama si určuje, kdy přerušit vnitřní smyčku. V textu si je postupně projdeme. Filtr a funkce `group` .{data-version:3.0.16} ============================================= -Představte si databázovou tabulku `items` s položkami rozdělenou do kategorií: +Nástroj lze používat ve dvou tvarech: jako filtr `$items|group: …` nebo jako funkci `group($items, …)`. Sémanticky jsou ekvivalentní, vyberte si podle čitelnosti. + +Představte si databázovou tabulku `items`, jejíž položky patří do různých kategorií: | id | categoryId | name |------------------ @@ -62,19 +64,17 @@ Pokud bychom ale chtěli, aby položky byly uspořádány do skupin podle katego {/foreach} ``` -Filtr lze v Latte použít i jako funkci, což nám dává alternativní syntaxi: `{foreach group($items, categoryId) ...}`. - -Chcete-li seskupovat položky podle složitějších kritérií, můžete v parametru filtru použít funkci. Například, seskupení položek podle délky názvu by vypadalo takto: +Chcete-li seskupovat položky podle složitějších kritérií, můžete v parametru filtru použít funkci. Klíčem každé skupiny pak bude návratová hodnota funkce — například při seskupení podle délky názvu to bude počet znaků: ```latte -{foreach ($items|group: fn($item) => strlen($item->name)) as $items} +{foreach ($items|group: fn($item) => strlen($item->name)) as $length => $group} ... {/foreach} ``` -Je důležité si uvědomit, že `$categoryItems` není běžné pole, ale objekt, který se chová jako iterátor. Pro přístup k první položce skupiny můžete použít funkci [`first()` |latte:functions#first]. +Je důležité si uvědomit, že každá skupina (tedy i `$categoryItems`) není běžné pole, ale objekt chovající se jako iterátor — nelze proto použít `$categoryItems[0]` ani `count($categoryItems)`. Pro přístup k první položce skupiny použijte funkci [`first()` |latte:functions#first]. -Tato flexibilita v seskupování dat činí `group` výjimečně užitečným nástrojem pro prezentaci dat v šablonách Latte. +Tato flexibilita činí `|group` výjimečně užitečným nástrojem pro prezentaci dat. Vnořené smyčky @@ -97,8 +97,8 @@ Představme si, že máme databázovou tabulku s dalším sloupcem `subcategoryI ``` -Spojení s Nette Database ------------------------- +Společně s Nette Database +------------------------- Pojďme si ukázat, jak efektivně využít seskupování dat v kombinaci s Nette Database. Předpokládejme, že pracujeme s tabulkou `items` z úvodního příkladu, která je prostřednictvím sloupce `categoryId` spojená s touto tabulkou `categories`: @@ -121,24 +121,24 @@ Data z tabulky `items` načteme pomocí Nette Database Explorer příkazem `$ite {/foreach} ``` -V tomto případě používáme filtr `|group` k seskupení podle propojeného řádku `$item->category`, nikoliv jen dle sloupce `categoryId`. Díky tomu v proměnné klíči přímo `ActiveRow` dané kategorie, což nám umožňuje přímo vypisovat její název pomocí `{$category->name}`. Toto je praktický příklad, jak může seskupování zpřehlednit šablony a usnadnit práci s daty. +V tomto případě používáme filtr `|group` k seskupení podle propojeného řádku `$item->category`, nikoliv jen dle sloupce `categoryId`. Díky tomu je v klíči (`$category`) rovnou `ActiveRow` dané kategorie, což nám umožňuje vypisovat její název pomocí `{$category->name}` a přistupovat k libovolnému dalšímu sloupci, aniž bychom museli dělat zvláštní dotaz na `categories`. Filtr `|batch` ============== -Filtr umožňuje rozdělit seznam prvků do skupin s předem určeným počtem prvků. Tento filtr je ideální pro situace, kdy chcete data prezentovat ve více menších skupinách, například pro lepší přehlednost nebo vizuální uspořádání na stránce. +Filtr rozdělí seznam prvků do dávek o pevně daném počtu. Hodí se třeba pro grid layout, sloupcové rozložení nebo jakékoli vizuální seskupení. -Představme si, že máme seznam položek a chceme je zobrazit v seznamech, kde každý obsahuje maximálně tři položky. Použití filtru `|batch` je v takovém případě velmi praktické: +Představme si, že chceme zobrazit položky v seznamech, kde každý obsahuje maximálně tři položky: ```latte -<ul> {foreach ($items|batch: 3) as $batch} - {foreach $batch as $item} - <li>{$item->name}</li> - {/foreach} + <ul> + {foreach $batch as $item} + <li>{$item->name}</li> + {/foreach} + </ul> {/foreach} -</ul> ``` V tomto příkladu je seznam `$items` rozdělen do menších skupin, přičemž každá skupina (`$batch`) obsahuje až tři položky. Každá skupina je poté zobrazena v samostatném `<ul>` seznamu. @@ -155,9 +155,9 @@ Pokud poslední skupina neobsahuje dostatek prvků k dosažení požadovaného p Značka `{iterateWhile}` ======================= -Stejné úkoly, jako jsme řešili s filtrem `|group`, si ukážeme s použitím značky `{iterateWhile}`. Hlavní rozdíl mezi oběma přístupy je v tom, že `group` nejprve zpracuje a seskupí všechna vstupní data, zatímco `{iterateWhile}` řídí průběhu cyklů s podmínkami, takže iterace probíhá postupně. +Stejné úkoly, jako jsme řešili s filtrem `|group`, si ukážeme s použitím značky `{iterateWhile}`. Hlavní rozdíl mezi oběma přístupy je v tom, že `|group` nejprve zpracuje a seskupí všechna vstupní data, zatímco `{iterateWhile}` řídí průběh cyklu pomocí podmínky a iterace probíhá postupně. -Nejprve vykreslíme tabulku s kategoriemi pomocí iterateWhile: +Nejprve vykreslíme tabulku s kategoriemi pomocí `{iterateWhile}`: ```latte {foreach $items as $item} @@ -169,7 +169,7 @@ Nejprve vykreslíme tabulku s kategoriemi pomocí iterateWhile: {/foreach} ``` -Zatímco `{foreach}` označuje vnější část cyklu, tedy vykreslování seznamů pro každou kategorii, tak značka `{iterateWhile}` označuje vnitřní část, tedy jednotlivé položky. Podmínka v koncové značce říká, že opakování bude probíhat do té doby, dokud aktuální i následující prvek patří do stejné kategorie (`$iterator->nextValue` je [následující položka |/tags#iterator]). +Zatímco `{foreach}` označuje vnější část cyklu, tedy vykreslování seznamů pro každou kategorii, tak značka `{iterateWhile}` označuje vnitřní část, tedy jednotlivé položky. Podmínka v koncové značce říká, že opakování bude probíhat do té doby, dokud aktuální i následující prvek patří do stejné kategorie (`$iterator->nextValue` je [následující položka |/tags#iterator]; u posledního prvku je `null` a porovnání pak vyjde false, takže vnitřní cyklus přirozeně skončí). Kdyby podmínka byla splněná vždy, tak se ve vnitřním cyklu vykreslí všechny prvky: @@ -196,11 +196,11 @@ Výsledek bude vypadat takto: </ul> ``` -K čemu je takové použití iterateWhile dobré? Když bude tabulka prázdná a nebude obsahovat žádné prvky, nevypíše se prázdné `<ul></ul>`. +K čemu je takové použití `{iterateWhile}` dobré? Tím, že je `<ul>` uvnitř vnějšího `{foreach}`, se při prázdném vstupu nevykreslí vůbec nic — žádný osamělý `<ul></ul>`. Bez `{iterateWhile}` byste totéž museli ošetřit `{if}` před otevřením tagu nebo přes `{foreachelse}`. Pokud uvedeme podmínku v otevírací značce `{iterateWhile}`, tak se chování změní: podmínka (a přechod na další prvek) se vykoná už na začátku vnitřního cyklu, nikoliv na konci. Tedy zatímco do `{iterateWhile}` bez podmínky se vstoupí vždy, do `{iterateWhile $cond}` jen při splnění podmínky `$cond`. A zároveň se s tím do `$item` zapíše následující prvek. -Což se hodí například v situaci, kdy budeme chtít první prvek v každé kategorii vykreslit jiným způsobem, například takto: +Hodí se to v situaci, kdy chceme první prvek v každé kategorii vykreslit jiným způsobem než ty ostatní, například takto: ```latte <h1>Apple</h1> @@ -219,6 +219,8 @@ Což se hodí například v situaci, kdy budeme chtít první prvek v každé ka </ul> ``` +(Prázdné `<ul></ul>` u kategorie PHP je tu jen ilustrací mechaniky — v reálném kódu byste vykreslení `<ul>` ošetřili `{if}`.) + Původní kód upravíme tak, že nejprve vykreslíme první položku a poté ve vnitřním cyklu `{iterateWhile}` vykreslíme další položky ze stejné kategorie: ```latte @@ -232,9 +234,9 @@ Původní kód upravíme tak, že nejprve vykreslíme první položku a poté ve {/foreach} ``` -V rámci jednoho cyklu můžeme vytvářet více vnitřních smyček a dokonce je zanořovat. Takto by se daly seskupovat třeba podkategorie atd. +V rámci jednoho cyklu můžeme vytvářet více vnitřních smyček a dokonce je zanořovat. Tímto způsobem lze seskupovat na více úrovních současně — třeba podkategorie pod kategoriemi. -Dejme tomu, že v tabulce bude ještě další sloupec `subcategoryId` a kromě toho, že každá kategorie bude v samostatném `<ul>`, každá každý podkategorie samostatném `<ol>`: +Dejme tomu, že v tabulce bude ještě další sloupec `subcategoryId` a kromě toho, že každá kategorie bude v samostatném `<ul>`, každá podkategorie bude v samostatném `<ol>`: ```latte {foreach $items as $item} diff --git a/latte/en/cookbook/grouping.texy b/latte/en/cookbook/grouping.texy index 7a8458bb0c..1d4b7bf049 100644 --- a/latte/en/cookbook/grouping.texy +++ b/latte/en/cookbook/grouping.texy @@ -2,15 +2,17 @@ Everything You Always Wanted to Know About Grouping *************************************************** .[perex] -When working with data in templates, you often encounter the need to group them or display them specifically according to certain criteria. Latte offers several powerful tools for this purpose. +When working with data in templates, you often need to group items, split them into batches, or iterate through them based on a condition. Latte offers three tools for this, each suited to a slightly different situation. -The filter and function `|group` allow for efficient data grouping based on specified criteria, the `|batch` filter facilitates splitting data into fixed-size batches, and the `{iterateWhile}` tag provides the ability to control loop progression with more complex conditions. Each of these features offers specific options for working with data, making them indispensable tools for dynamic and structured display of information in Latte templates. +The `|group` filter groups items by a given criterion, the `|batch` filter splits them into batches of fixed size, and the `{iterateWhile}` tag iterates through data step by step and decides for itself when to break the inner loop. We'll walk through them one by one. Filter and Function `group` .{data-version:3.0.16} ================================================== -Imagine a database table `items` with items divided into categories: +The tool can be used in two forms: as a filter `$items|group: …` or as a function `group($items, …)`. Semantically they are equivalent — choose based on readability. + +Imagine a database table `items` whose items belong to various categories: | id | categoryId | name |-----|------------|-------- @@ -62,19 +64,17 @@ This task can be easily and elegantly solved using `|group`. We specify `categor {/foreach} ``` -The filter can also be used as a function in Latte, providing an alternative syntax: `{foreach group($items, categoryId) ...}`. - -If you want to group items based on more complex criteria, you can use a function in the filter parameter. For example, grouping items by the length of their name would look like this: +If you want to group items based on more complex criteria, you can use a function in the filter parameter. The key of each group will then be the return value of the function — for example, when grouping by name length, it will be the number of characters: ```latte -{foreach ($items|group: fn($item) => strlen($item->name)) as $items} +{foreach ($items|group: fn($item) => strlen($item->name)) as $length => $group} ... {/foreach} ``` -It’s important to note that `$categoryItems` is not a regular array, but an object that behaves like an iterator. To access the first item in the group, you can use the [`first()` |latte:functions#first] function. +It's important to note that each group (including `$categoryItems`) is not a regular array, but an object that behaves like an iterator — so you cannot use `$categoryItems[0]` or `count($categoryItems)`. To access the first item in the group, use the [`first()` |latte:functions#first] function. -This flexibility in data grouping makes `group` an exceptionally useful tool for presenting data in Latte templates. +This flexibility makes `|group` an exceptionally useful tool for presenting data. Nested Loops @@ -97,8 +97,8 @@ Let's imagine our database table has an additional column `subcategoryId`, defin ``` -Integration with Nette Database -------------------------------- +Together with Nette Database +---------------------------- Let's demonstrate how to effectively use data grouping in combination with Nette Database. Assume we are working with the `items` table from the introductory example, connected via the `categoryId` column to this `categories` table: @@ -121,24 +121,24 @@ We load data from the `items` table using Nette Database Explorer with the comma {/foreach} ``` -In this case, we use the `|group` filter to group by the related row object `$item->category`, not just the `categoryId` column. As a result, the key variable `$category` directly holds the `ActiveRow` object for that category, allowing us to display its name directly using `{$category->name}`. This is a practical example of how grouping can simplify templates and facilitate working with related data. +In this case, we use the `|group` filter to group by the related row `$item->category`, not just the `categoryId` column. As a result, the key (`$category`) directly holds the `ActiveRow` object for that category, allowing us to display its name using `{$category->name}` and access any other column without making a separate query to `categories`. Filter `|batch` =============== -The `|batch` filter allows you to divide a list of items into groups (batches) with a predetermined number of items. This filter is ideal for situations where you want to present data in several smaller chunks, for example, for better clarity or visual layout on the page. +The filter splits a list of items into batches of a fixed size. It's handy for grid layouts, column arrangements, or any kind of visual grouping. -Imagine we have a list of items and want to display them in lists, where each list contains a maximum of three items. Using the `|batch` filter is very practical in such a case: +Imagine we want to display items in lists where each list contains a maximum of three items: ```latte -<ul> {foreach ($items|batch: 3) as $batch} - {foreach $batch as $item} - <li>{$item->name}</li> - {/foreach} + <ul> + {foreach $batch as $item} + <li>{$item->name}</li> + {/foreach} + </ul> {/foreach} -</ul> ``` In this example, the `$items` list is divided into smaller groups, where each group (`$batch`) contains up to three items. Each batch is then displayed in a separate `<ul>` list. @@ -155,9 +155,9 @@ If the last group does not contain enough elements to reach the desired number, Tag `{iterateWhile}` ==================== -We will demonstrate the same tasks addressed with the `|group` filter using the `{iterateWhile}` tag. The main difference between the two approaches is that `|group` first processes and groups all input data, whereas `{iterateWhile}` controls the loop's progression based on conditions, allowing iteration to proceed sequentially. +We will demonstrate the same tasks addressed with the `|group` filter using the `{iterateWhile}` tag. The main difference between the two approaches is that `|group` first processes and groups all input data, whereas `{iterateWhile}` controls the loop's progression via a condition and iteration proceeds sequentially. -First, let's render the table with categories using `iterateWhile`: +First, let's render the table with categories using `{iterateWhile}`: ```latte {foreach $items as $item} @@ -169,7 +169,7 @@ First, let's render the table with categories using `iterateWhile`: {/foreach} ``` -While `{foreach}` marks the outer part of the cycle, i.e., drawing lists for each category, the `{iterateWhile}` tag marks the inner part, i.e., individual items. The condition in the end tag says that repetition will continue as long as the current and next element belong to the same category (`$iterator->nextValue` is the [next item |/tags#iterator]). +While `{foreach}` marks the outer part of the cycle, i.e., drawing lists for each category, the `{iterateWhile}` tag marks the inner part, i.e., individual items. The condition in the end tag says that repetition will continue as long as the current and next element belong to the same category (`$iterator->nextValue` is the [next item |/tags#iterator]; for the last element it is `null` and the comparison then evaluates to false, so the inner loop naturally ends). If the condition were always true, all elements would be rendered within the first `<ul>`: @@ -196,11 +196,11 @@ The result would look like this: </ul> ``` -What's the benefit of using `iterateWhile` like this? If the `$items` array is empty, no empty `<ul></ul>` tags will be printed. +What's the benefit of using `{iterateWhile}` like this? Because the `<ul>` is inside the outer `{foreach}`, nothing is rendered at all when the input is empty — no lone `<ul></ul>`. Without `{iterateWhile}` you would have to handle the same case with an `{if}` before opening the tag or via `{foreachelse}`. If we specify the condition in the opening `{iterateWhile}` tag, the behavior changes: the condition (and transition to the next element) is performed at the beginning of the inner cycle, not at the end. Thus, while you always enter `{iterateWhile}` without conditions, you enter `{iterateWhile $cond}` only when the condition `$cond` is met. And at the same time, the next element is written into `$item`. -This is useful, for instance, when you want to render the first item in each category differently, like this: +This is useful in situations where we want to render the first item in each category differently from the others, for example like this: ```latte <h1>Apple</h1> @@ -219,6 +219,8 @@ This is useful, for instance, when you want to render the first item in each cat </ul> ``` +(The empty `<ul></ul>` for the PHP category is just an illustration of the mechanics — in real code you would handle the `<ul>` rendering with an `{if}`.) + We modify the original code to first render the item as a heading, and then use the inner `{iterateWhile}` loop to render subsequent items from the same category as list items: ```latte @@ -232,9 +234,9 @@ We modify the original code to first render the item as a heading, and then use {/foreach} ``` -Within a single `{foreach}` loop, you can create multiple inner `{iterateWhile}` loops and even nest them. This could be used, for example, to group subcategories. +Within a single loop, we can create multiple inner loops and even nest them. This way you can group on multiple levels at once — for example, subcategories under categories. -Let's assume the table has another column `subcategoryId`, and besides having each category in a separate `<ul>`, each subcategory should be in a separate `<ol>`: +Let's assume the table has another column `subcategoryId`, and besides each category being in a separate `<ul>`, each subcategory will be in a separate `<ol>`: ```latte {foreach $items as $item} From 54a49d25f9f3f81043f2a714ec1f7b2172525918 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Sat, 23 May 2026 05:00:19 +0200 Subject: [PATCH 36/50] nette/security 3.2.4 --- security/cs/authentication.texy | 32 +++++++++++++++++++++++++++++++- security/cs/authorization.texy | 2 +- security/cs/configuration.texy | 3 +++ security/en/authentication.texy | 32 +++++++++++++++++++++++++++++++- security/en/authorization.texy | 2 +- security/en/configuration.texy | 3 +++ 6 files changed, 70 insertions(+), 4 deletions(-) diff --git a/security/cs/authentication.texy b/security/cs/authentication.texy index 689b757bd5..846a82e86a 100644 --- a/security/cs/authentication.texy +++ b/security/cs/authentication.texy @@ -166,6 +166,9 @@ Co je důležité, tak že při odhlášení pomocí `$user->logout()` **se iden Díky tomu můžete nadále předpokládat, který uživatel je u počítače a například mu v e-shopu zobrazovat personalizované nabídky, nicméně zobrazit mu jeho osobní údaje můžete až po přihlášení. +.{data-version:3.2.4} +Kromě smazání identity u konkrétního volání pomocí `logout(true)` lze její uchovávání vypnout úplně vlastností `$persistIdentity`. Když ji nastavíte na `false`, identita se zahodí při každém odhlášení i při expiraci, takže `getIdentity()` pak vrací `null`. Uchování identity navíc závisí na úložišti: cookie úložiště ji po odhlášení neuchová, protože cookie vždy smaže. + Identita je objekt implementující rozhraní [api:Nette\Security\IIdentity], výchozí implementací je [api:Nette\Security\SimpleIdentity]. A jak bylo zmíněno, udržuje se v session, takže pokud tedy například změníme roli některého z přihlášených uživatelů, zůstanou stará data v jeho identitě až do jeho opětovného přihlášení. @@ -174,7 +177,7 @@ Identita je objekt implementující rozhraní [api:Nette\Security\IIdentity], v Dvě základní informace o uživateli, tedy zda-li je přihlášen a jeho [#identita], se zpravidla přenášejí v session. Což lze změnit. Ukládání těchto informací má na starosti objekt implementující rozhraní `Nette\Security\UserStorage`. K dispozici jsou dvě standardní implementace, první přenáší data v session a druhá v cookie. Jde o třídy `Nette\Bridges\SecurityHttp\SessionStorage` a `CookieStorage`. Zvolit si uložiště a nakonfigurovat jej můžete velmi pohodlně v konfiguraci [security › authentication |configuration#Úložiště]. -Dále můžete ovlivnit, jak přesně bude probíhat ukládání identity (*sleep*) a obnovování (*wakeup*). Stačí, aby authenticator implementoval rozhraní `Nette\Security\IdentityHandler`. To má dvě metody: `sleepIdentity()` se volá před zápisem identity do úložiště a `wakeupIdentity()` po jejím přečtení. Metody mohou obsah identity upravit, případně ji nahradit novým objektem, který vrátí. Metoda `wakeupIdentity()` může dokonce vrátit `null`, čímž uživatele jej odhlásí. +Dále můžete ovlivnit, jak přesně bude probíhat ukládání identity (*sleep*) a obnovování (*wakeup*). Stačí, aby authenticator implementoval rozhraní `Nette\Security\IdentityHandler`. Metoda `sleepIdentity()` se volá před zápisem identity do úložiště a `wakeupIdentity()` po jejím přečtení. Metody mohou obsah identity upravit, případně ji nahradit novým objektem, který vrátí. Metoda `wakeupIdentity()` může dokonce vrátit `null`, čímž uživatele jej odhlásí. Rozhraní deklaruje i metodu `getGuestIdentity()`, viz [#Identita hosta]. Jako příklad si ukážeme řešení časté otázky, jak aktualizovat role v identitě hned po načtení ze session. V metodě `wakeupIdentity()` předáme do identity aktuální role např. z databáze: @@ -196,6 +199,12 @@ final class Authenticator implements $identity->setRoles($this->facade->getUserRoles($userId)); return $identity; } + + public function getGuestIdentity(): ?IIdentity + { + // identitu hosta zde nepoužíváme + return null; + } ``` A nyní se vrátíme k úložišti na bázi cookies. Dovoluje vám vytvořit web, kde se mohou přihlašovat uživatelé a přitom nepotřebuje sessions. Tedy nepotřebuje zapisovat na disk. Ostatně tak funguje i web, který právě čtete, včetně fóra. V tomto případě je implementace `IdentityHandler` nutností. Do cookie totiž budeme ukládat jen náhodný token reprezentující přihlášeného uživatele. @@ -231,9 +240,30 @@ final class Authenticator implements ? new SimpleIdentity($row->id, null, (array) $row) : null; } + + public function getGuestIdentity(): ?IIdentity + { + // identitu hosta zde nepoužíváme + return null; + } +} +``` + + +Identita hosta .{data-version:3.2.4} +==================================== + +Někdy se hodí, aby měli identitu i nepřihlášení návštěvníci, například abyste jim přiřadili výchozí sadu rolí nebo jim předali nějaká data. Pokud autentikátor implementuje `IdentityHandler`, může ji poskytnout přes metodu `getGuestIdentity()`, která se použije vždy, když není nikdo přihlášený. Metody `getIdentity()`, `getId()` a `getRoles()` se pak na ni odkážou, takže hosté mohou mít vlastní role místo pouhé role `guest`. Pokud identitu hosta nechcete, vraťte `null`. + +```php +public function getGuestIdentity(): ?IIdentity +{ + return new SimpleIdentity('guest', ['guest'], ['name' => 'Guest']); } ``` +Identita hosta se nikdy neukládá do úložiště a přihlášení ji vždy nahradí. + Více nezávislých přihlášení =========================== diff --git a/security/cs/authorization.texy b/security/cs/authorization.texy index 7e91555fef..ab9a0ba4e1 100644 --- a/security/cs/authorization.texy +++ b/security/cs/authorization.texy @@ -30,7 +30,7 @@ if ($user->isInRole('admin')) { // je uživatel v roli admina? } ``` -Jak už víte, po odhlášení uživatele se nemusí smazat jeho identita. Tedy i nadále metoda `getIdentity()` vrací objekt `SimpleIdentity`, včetně všech udělených rolí. Nette Framework vyznává princip „less code, more security“, kdy méně psaní vede k více zabezpečenému kódu, proto při zjišťování rolí nemusíte ještě ověřovat, zda je uživatel přihlášený. Metoda `isInRole()` pracuje s **efektivními rolemi,** tj. pokud je uživatel přihlášen, vychází z rolí uvedených v identitě, pokud přihlášen není, má automaticky speciální roli `guest`. +Jak už víte, po odhlášení uživatele se nemusí smazat jeho identita. Tedy i nadále metoda `getIdentity()` vrací objekt `SimpleIdentity`, včetně všech udělených rolí. Nette Framework vyznává princip „less code, more security“, kdy méně psaní vede k více zabezpečenému kódu, proto při zjišťování rolí nemusíte ještě ověřovat, zda je uživatel přihlášený. Metoda `isInRole()` pracuje s **efektivními rolemi,** tj. pokud je uživatel přihlášen, vychází z rolí uvedených v identitě, pokud přihlášen není, má automaticky speciální roli `guest` (nebo role [identity hosta |authentication#Identita hosta], pokud je nějaká poskytnuta). Autorizátor diff --git a/security/cs/configuration.texy b/security/cs/configuration.texy index 6405e97b07..5876cacc5d 100644 --- a/security/cs/configuration.texy +++ b/security/cs/configuration.texy @@ -53,6 +53,9 @@ security: # kam ukládat informace o přihlášeném uživateli storage: session # (session|cookie) výchozí je session + + # zachovat identitu i po odhlášení a expiraci + persistIdentity: true # (bool) výchozí je true ``` Pokud zvolíte jako úložiště `cookie`, můžete nastavit ještě tyto volby: diff --git a/security/en/authentication.texy b/security/en/authentication.texy index 4fbd946ba6..7716d0f236 100644 --- a/security/en/authentication.texy +++ b/security/en/authentication.texy @@ -166,6 +166,9 @@ What's important is that when logging out using `$user->logout()`, **the identit Thanks to this, you can still assume which user is at the computer and, for example, display personalized offers in an e-shop, but you can only display their personal information after they log in. +.{data-version:3.2.4} +Besides clearing the identity per call with `logout(true)`, you can disable its retention entirely using the `$persistIdentity` property. When set to `false`, the identity is discarded on every logout and on expiration, so `getIdentity()` then returns `null`. Keeping the identity also depends on the storage: the cookie storage cannot retain it after logout, because it always deletes the cookie. + An identity is an object implementing the [api:Nette\Security\IIdentity] interface. The default implementation is [api:Nette\Security\SimpleIdentity]. And as mentioned, it is maintained in the session, so if, for example, we change the role of one of the logged-in users, the old data will remain in their identity until they log in again. @@ -174,7 +177,7 @@ Storage for Logged-in User The two basic information about the user, namely whether they are logged in and their [#identity], are usually transmitted in the session. Which can be changed. An object implementing the `Nette\Security\UserStorage` interface is responsible for storing this information. Two standard implementations are available: `Nette\Bridges\SecurityHttp\SessionStorage`, which transmits data in the session, and `CookieStorage`, which transmits data in a cookie. You can choose the storage and configure it very conveniently in the [security › authentication |configuration#User Storage] configuration. -Furthermore, you can influence how exactly the identity saving (*sleep*) and restoring (*wakeup*) will proceed. All that is needed is for the authenticator to implement the `Nette\Security\IdentityHandler` interface. This interface has two methods: `sleepIdentity()` is called before the identity is written to storage, and `wakeupIdentity()` after it's read. These methods can modify the identity content, or replace it with a new object that it returns. The `wakeupIdentity()` method can even return `null`, which logs the user out. +Furthermore, you can influence how exactly the identity saving (*sleep*) and restoring (*wakeup*) will proceed. All that is needed is for the authenticator to implement the `Nette\Security\IdentityHandler` interface. The `sleepIdentity()` method is called before the identity is written to storage, and `wakeupIdentity()` after it's read. These methods can modify the identity content, or replace it with a new object that it returns. The `wakeupIdentity()` method can even return `null`, which logs the user out. The interface also declares the `getGuestIdentity()` method, see [#Guest Identity]. As an example, let's show a solution to the frequent question of how to update roles in the identity right after loading from the session. In the `wakeupIdentity()` method, we pass the current roles, e.g., from a database, into the identity: @@ -196,6 +199,12 @@ final class Authenticator implements $identity->setRoles($this->facade->getUserRoles($userId)); return $identity; } + + public function getGuestIdentity(): ?IIdentity + { + // no guest identity is used here + return null; + } ``` Now let's return to storage based on cookies. It allows you to create a website where users can log in while not needing sessions. Thus, it does not need to write to the disk. This is how the website you are currently reading works, including the forum. In this case, the implementation of `IdentityHandler` is a necessity. We will only store a random token representing the logged-in user in the cookie. @@ -231,9 +240,30 @@ final class Authenticator implements ? new SimpleIdentity($row->id, null, (array) $row) : null; } + + public function getGuestIdentity(): ?IIdentity + { + // no guest identity is used here + return null; + } +} +``` + + +Guest Identity .{data-version:3.2.4} +==================================== + +Sometimes it is handy for visitors who are not logged in to have an identity too, for example to give them a default set of roles or some data. If the authenticator implements `IdentityHandler`, it can supply one through the `getGuestIdentity()` method, which is used whenever nobody is logged in. Then `getIdentity()`, `getId()` and `getRoles()` fall back to it, so guests can have their own roles instead of just the plain `guest` role. Return `null` if you don't want a guest identity. + +```php +public function getGuestIdentity(): ?IIdentity +{ + return new SimpleIdentity('guest', ['guest'], ['name' => 'Guest']); } ``` +The guest identity is never saved to storage, and logging in always replaces it. + Multiple Independent Logins =========================== diff --git a/security/en/authorization.texy b/security/en/authorization.texy index dfcb3a37ba..b6ca2df44e 100644 --- a/security/en/authorization.texy +++ b/security/en/authorization.texy @@ -30,7 +30,7 @@ if ($user->isInRole('admin')) { // is the user in the admin role? } ``` -As you already know, logging out the user does not have to delete their identity. Thus, the `getIdentity()` method still returns the `SimpleIdentity` object, including all granted roles. Nette Framework espouses the principle "less code, more security," where less writing leads to more secure code. Therefore, when checking roles, you do not need to verify whether the user is logged in. The `isInRole()` method works with **effective roles**: if the user is logged in, it is based on the roles specified in the identity; if not logged in, they automatically have the special role `guest`. +As you already know, logging out the user does not have to delete their identity. Thus, the `getIdentity()` method still returns the `SimpleIdentity` object, including all granted roles. Nette Framework espouses the principle "less code, more security," where less writing leads to more secure code. Therefore, when checking roles, you do not need to verify whether the user is logged in. The `isInRole()` method works with **effective roles**: if the user is logged in, it is based on the roles specified in the identity; if not logged in, they automatically have the special role `guest` (or the roles of the [guest identity |authentication#Guest Identity], if one is provided). Authorizer diff --git a/security/en/configuration.texy b/security/en/configuration.texy index a6de366f55..7c3c505e5c 100644 --- a/security/en/configuration.texy +++ b/security/en/configuration.texy @@ -53,6 +53,9 @@ security: # where to store information about the logged-in user storage: session # (session|cookie) default is session + + # keep the identity available after logout and expiration + persistIdentity: true # (bool) defaults to true ``` If you choose `cookie` as the storage, you can also set these options: From 02884fa94658b9d1d0495a7cc0ba0bdd3f1a47bf Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Sat, 6 Jun 2026 14:58:54 +0200 Subject: [PATCH 37/50] added tools --- nette/bg/@home.texy | 1 + nette/cs/@home.texy | 1 + nette/de/@home.texy | 1 + nette/el/@home.texy | 1 + nette/en/@home.texy | 1 + nette/es/@home.texy | 1 + nette/fr/@home.texy | 1 + nette/hu/@home.texy | 1 + nette/it/@home.texy | 1 + nette/ja/@home.texy | 1 + nette/pl/@home.texy | 1 + nette/pt/@home.texy | 1 + nette/ro/@home.texy | 1 + nette/ru/@home.texy | 1 + nette/sl/@home.texy | 1 + nette/tr/@home.texy | 1 + nette/uk/@home.texy | 1 + tools/bg/@home.texy | 33 +++++++++++++++++++++++++++++++++ tools/bg/@meta.texy | 2 ++ tools/cs/@home.texy | 33 +++++++++++++++++++++++++++++++++ tools/cs/@meta.texy | 2 ++ tools/de/@home.texy | 33 +++++++++++++++++++++++++++++++++ tools/de/@meta.texy | 2 ++ tools/el/@home.texy | 33 +++++++++++++++++++++++++++++++++ tools/el/@meta.texy | 2 ++ tools/en/@home.texy | 33 +++++++++++++++++++++++++++++++++ tools/en/@meta.texy | 2 ++ tools/es/@home.texy | 33 +++++++++++++++++++++++++++++++++ tools/es/@meta.texy | 2 ++ tools/fr/@home.texy | 33 +++++++++++++++++++++++++++++++++ tools/fr/@meta.texy | 2 ++ tools/hu/@home.texy | 33 +++++++++++++++++++++++++++++++++ tools/hu/@meta.texy | 2 ++ tools/it/@home.texy | 33 +++++++++++++++++++++++++++++++++ tools/it/@meta.texy | 2 ++ tools/ja/@home.texy | 33 +++++++++++++++++++++++++++++++++ tools/ja/@meta.texy | 2 ++ tools/meta.json | 1 + tools/pl/@home.texy | 33 +++++++++++++++++++++++++++++++++ tools/pl/@meta.texy | 2 ++ tools/pt/@home.texy | 33 +++++++++++++++++++++++++++++++++ tools/pt/@meta.texy | 2 ++ tools/ro/@home.texy | 33 +++++++++++++++++++++++++++++++++ tools/ro/@meta.texy | 2 ++ tools/ru/@home.texy | 33 +++++++++++++++++++++++++++++++++ tools/ru/@meta.texy | 2 ++ tools/sl/@home.texy | 33 +++++++++++++++++++++++++++++++++ tools/sl/@meta.texy | 2 ++ tools/tr/@home.texy | 33 +++++++++++++++++++++++++++++++++ tools/tr/@meta.texy | 2 ++ tools/uk/@home.texy | 33 +++++++++++++++++++++++++++++++++ tools/uk/@meta.texy | 2 ++ www/bg/@menu-common.texy | 1 + www/cs/@menu-common.texy | 1 + www/de/@menu-common.texy | 1 + www/el/@menu-common.texy | 1 + www/en/@menu-common.texy | 1 + www/es/@menu-common.texy | 1 + www/fr/@menu-common.texy | 1 + www/hu/@menu-common.texy | 1 + www/it/@menu-common.texy | 1 + www/ja/@menu-common.texy | 1 + www/pl/@menu-common.texy | 1 + www/pt/@menu-common.texy | 1 + www/ro/@menu-common.texy | 1 + www/ru/@menu-common.texy | 1 + www/sl/@menu-common.texy | 1 + www/tr/@menu-common.texy | 1 + www/uk/@menu-common.texy | 1 + 69 files changed, 630 insertions(+) create mode 100644 tools/bg/@home.texy create mode 100644 tools/bg/@meta.texy create mode 100644 tools/cs/@home.texy create mode 100644 tools/cs/@meta.texy create mode 100644 tools/de/@home.texy create mode 100644 tools/de/@meta.texy create mode 100644 tools/el/@home.texy create mode 100644 tools/el/@meta.texy create mode 100644 tools/en/@home.texy create mode 100644 tools/en/@meta.texy create mode 100644 tools/es/@home.texy create mode 100644 tools/es/@meta.texy create mode 100644 tools/fr/@home.texy create mode 100644 tools/fr/@meta.texy create mode 100644 tools/hu/@home.texy create mode 100644 tools/hu/@meta.texy create mode 100644 tools/it/@home.texy create mode 100644 tools/it/@meta.texy create mode 100644 tools/ja/@home.texy create mode 100644 tools/ja/@meta.texy create mode 100644 tools/meta.json create mode 100644 tools/pl/@home.texy create mode 100644 tools/pl/@meta.texy create mode 100644 tools/pt/@home.texy create mode 100644 tools/pt/@meta.texy create mode 100644 tools/ro/@home.texy create mode 100644 tools/ro/@meta.texy create mode 100644 tools/ru/@home.texy create mode 100644 tools/ru/@meta.texy create mode 100644 tools/sl/@home.texy create mode 100644 tools/sl/@meta.texy create mode 100644 tools/tr/@home.texy create mode 100644 tools/tr/@meta.texy create mode 100644 tools/uk/@home.texy create mode 100644 tools/uk/@meta.texy diff --git a/nette/bg/@home.texy b/nette/bg/@home.texy index 5529dfaf8c..161ae341a3 100644 --- a/nette/bg/@home.texy +++ b/nette/bg/@home.texy @@ -45,6 +45,7 @@ - 🎓 [Ръководства и практики |best-practices:] +- 🧰 [Инструменти |tools:] </div> diff --git a/nette/cs/@home.texy b/nette/cs/@home.texy index 73b4844e52..c3af97e01c 100644 --- a/nette/cs/@home.texy +++ b/nette/cs/@home.texy @@ -45,6 +45,7 @@ Aplikace v Nette - 🎓 [Návody a postupy |best-practices:] +- 🧰 [Nástroje |tools:] </div> diff --git a/nette/de/@home.texy b/nette/de/@home.texy index fd8b79f1ae..68bcffd7d8 100644 --- a/nette/de/@home.texy +++ b/nette/de/@home.texy @@ -45,6 +45,7 @@ Anwendungen in Nette - 🎓 [Anleitungen und Verfahren |best-practices:] +- 🧰 [Werkzeuge |tools:] </div> diff --git a/nette/el/@home.texy b/nette/el/@home.texy index 2de3b00ad3..2ee26cefb1 100644 --- a/nette/el/@home.texy +++ b/nette/el/@home.texy @@ -45,6 +45,7 @@ - 🎓 [Οδηγοί και βέλτιστες πρακτικές |best-practices:] +- 🧰 [Εργαλεία |tools:] </div> diff --git a/nette/en/@home.texy b/nette/en/@home.texy index 2c7cfa6d87..28c20d65f7 100644 --- a/nette/en/@home.texy +++ b/nette/en/@home.texy @@ -45,6 +45,7 @@ Nette Application - 🎓 [Tutorials and Best Practices |best-practices:] +- 🧰 [Tools |tools:] </div> diff --git a/nette/es/@home.texy b/nette/es/@home.texy index 87b7cba584..670c00b142 100644 --- a/nette/es/@home.texy +++ b/nette/es/@home.texy @@ -45,6 +45,7 @@ Aplicaciones en Nette - 🎓 [Tutoriales y mejores prácticas |best-practices:] +- 🧰 [Herramientas |tools:] </div> diff --git a/nette/fr/@home.texy b/nette/fr/@home.texy index 308cba0545..a71e9109ac 100644 --- a/nette/fr/@home.texy +++ b/nette/fr/@home.texy @@ -45,6 +45,7 @@ Applications Nette - 🎓 [Tutoriels et bonnes pratiques |best-practices:] +- 🧰 [Outils |tools:] </div> diff --git a/nette/hu/@home.texy b/nette/hu/@home.texy index 17186e62a8..ccb79281e3 100644 --- a/nette/hu/@home.texy +++ b/nette/hu/@home.texy @@ -45,6 +45,7 @@ Nette alkalmazások - 🎓 [Útmutatók és eljárások |best-practices:] +- 🧰 [Eszközök |tools:] </div> diff --git a/nette/it/@home.texy b/nette/it/@home.texy index 83005d95ce..7629df038e 100644 --- a/nette/it/@home.texy +++ b/nette/it/@home.texy @@ -45,6 +45,7 @@ Applicazioni in Nette - 🎓 [Guide e procedure |best-practices:] +- 🧰 [Strumenti |tools:] </div> diff --git a/nette/ja/@home.texy b/nette/ja/@home.texy index 8d96f0d111..cae5e6580e 100644 --- a/nette/ja/@home.texy +++ b/nette/ja/@home.texy @@ -45,6 +45,7 @@ Nette のアプリケーション - 🎓 [ガイドとベストプラクティス |best-practices:] +- 🧰 [ツール |tools:] </div> diff --git a/nette/pl/@home.texy b/nette/pl/@home.texy index c698bbb4ef..829d6c2f5c 100644 --- a/nette/pl/@home.texy +++ b/nette/pl/@home.texy @@ -45,6 +45,7 @@ Aplikacje w Nette - 🎓 [Poradniki i najlepsze praktyki |best-practices:] +- 🧰 [Narzędzia |tools:] </div> diff --git a/nette/pt/@home.texy b/nette/pt/@home.texy index 10aa8abd8b..9cb047f76e 100644 --- a/nette/pt/@home.texy +++ b/nette/pt/@home.texy @@ -45,6 +45,7 @@ Aplicações em Nette - 🎓 [Tutoriais e melhores práticas |best-practices:] +- 🧰 [Ferramentas |tools:] </div> diff --git a/nette/ro/@home.texy b/nette/ro/@home.texy index f9114ad972..dbcdf4e9b6 100644 --- a/nette/ro/@home.texy +++ b/nette/ro/@home.texy @@ -45,6 +45,7 @@ Aplicații în Nette - 🎓 [Tutoriale și proceduri |best-practices:] +- 🧰 [Instrumente |tools:] </div> diff --git a/nette/ru/@home.texy b/nette/ru/@home.texy index dbae3d2158..37e34518bb 100644 --- a/nette/ru/@home.texy +++ b/nette/ru/@home.texy @@ -45,6 +45,7 @@ - 🎓 [Руководства и лучшие практики |best-practices:] +- 🧰 [Инструменты |tools:] </div> diff --git a/nette/sl/@home.texy b/nette/sl/@home.texy index 6889d0a232..c8230f9b51 100644 --- a/nette/sl/@home.texy +++ b/nette/sl/@home.texy @@ -45,6 +45,7 @@ Aplikacije v Nette - 🎓 [Navodila in postopki |best-practices:] +- 🧰 [Orodja |tools:] </div> diff --git a/nette/tr/@home.texy b/nette/tr/@home.texy index 65215989d0..02ec266f50 100644 --- a/nette/tr/@home.texy +++ b/nette/tr/@home.texy @@ -45,6 +45,7 @@ Nette Uygulamaları - 🎓 [Kılavuzlar ve yöntemler |best-practices:] +- 🧰 [Araçlar |tools:] </div> diff --git a/nette/uk/@home.texy b/nette/uk/@home.texy index 50c8a7b148..13d74d1c2e 100644 --- a/nette/uk/@home.texy +++ b/nette/uk/@home.texy @@ -45,6 +45,7 @@ - 🎓 [Посібники та практики |best-practices:] +- 🧰 [Інструменти |tools:] </div> diff --git a/tools/bg/@home.texy b/tools/bg/@home.texy new file mode 100644 index 0000000000..08c54d83e5 --- /dev/null +++ b/tools/bg/@home.texy @@ -0,0 +1,33 @@ +Инструменти +*********** + +.[perex] +Помощни инструменти, които улесняват разработката с Nette. + + +Среда за разработка +------------------- +- [Редактори и IDE |ide] препоръчвани редактори и плъгини за комфортна работа с Nette, Latte и NEON. +- [Composer |best-practices:composer] практични съвети за работа с мениджъра на зависимости на PHP: инсталация, версия на PHP, автоматично зареждане и още. + + +Качество на кода +---------------- +- [Code Checker |code-checker] проверява изходните ви файлове за формални недостатъци като невидим BOM, контролни знаци, повредено кодиране или невалиден синтаксис на PHP, Latte, NEON, JSON и YAML файлове и може да ги поправи автоматично. + + +Изкуствен интелект +------------------ +- [Claude Code plugin |ai:en:claude-code] учи Claude Code на конвенциите на Nette: умения, автоматична валидация на Latte/NEON/JS и MCP интеграция. +- [MCP Inspector |ai:en:mcp-inspector] дава на AI реалното състояние на вашето приложение: DI услуги, схема на базата данни, маршрути и Tracy логове. + + +Frontend +-------- +- [Vite plugin |assets:vite] свързва инструмента за компилиране Vite с Nette Assets: HMR по време на разработка и оптимизирани продукционни компилации. +- [ESLint plugin |https://github.com/nette/eslint-plugin] добавя ESLint правила и конфигурация за JS/TS в Nette проекти, включително линтване на JS вътре в Latte шаблони. + + +Миграция към Latte +------------------ +- Конвертирайте шаблони [от PHP |latte:cookbook/migration-from-php] и [от Twig |latte:cookbook/migration-from-twig] с помощта на инструмента latte-tools. diff --git a/tools/bg/@meta.texy b/tools/bg/@meta.texy new file mode 100644 index 0000000000..12c266a1fd --- /dev/null +++ b/tools/bg/@meta.texy @@ -0,0 +1,2 @@ +{{sitename: Инструменти}} +{{leftbar: www:@menu-common}} diff --git a/tools/cs/@home.texy b/tools/cs/@home.texy new file mode 100644 index 0000000000..1654095a08 --- /dev/null +++ b/tools/cs/@home.texy @@ -0,0 +1,33 @@ +Nástroje +******** + +.[perex] +Pomocné nástroje, které vám usnadní vývoj s Nette. + + +Vývojové prostředí +------------------ +- [Editory a IDE |ide] doporučené editory a pluginy pro pohodlnou práci s Nette, Latte a NEON. +- [Composer |best-practices:composer] praktické tipy pro práci se správcem závislostí v PHP: instalace, verze PHP, autoloading a další. + + +Kvalita kódu +------------ +- [Code Checker |code-checker] zkontroluje vaše zdrojové soubory a najde v nich formální nedostatky, jako je neviditelný BOM, kontrolní znaky, chybné kódování nebo neplatná syntaxe souborů PHP, Latte, NEON, JSON a YAML, a umí je automaticky opravit. + + +Umělá inteligence +----------------- +- [Claude Code plugin |ai:en:claude-code] naučí Claude Code konvence Nette: skills, automatická validace Latte/NEON/JS a integrace MCP. +- [MCP Inspector |ai:en:mcp-inspector] zpřístupní AI reálný stav aplikace: DI služby, schéma databáze, routy i Tracy logy. + + +Frontend +-------- +- [Vite plugin |assets:vite] propojí build nástroj Vite s Nette Assets: HMR při vývoji a optimalizované produkční buildy. +- [ESLint plugin |https://github.com/nette/eslint-plugin] přidá ESLintu pravidla a konfiguraci pro JS/TS v Nette projektech, včetně kontroly JS uvnitř Latte šablon. + + +Migrace na Latte +---------------- +- Převod šablon [z PHP |latte:cookbook/migration-from-php] a [z Twigu |latte:cookbook/migration-from-twig] pomocí nástroje latte-tools. diff --git a/tools/cs/@meta.texy b/tools/cs/@meta.texy new file mode 100644 index 0000000000..743f498512 --- /dev/null +++ b/tools/cs/@meta.texy @@ -0,0 +1,2 @@ +{{sitename: Nástroje}} +{{leftbar: www:@menu-common}} diff --git a/tools/de/@home.texy b/tools/de/@home.texy new file mode 100644 index 0000000000..027f5f3cc4 --- /dev/null +++ b/tools/de/@home.texy @@ -0,0 +1,33 @@ +Werkzeuge +********* + +.[perex] +Hilfswerkzeuge, die die Entwicklung mit Nette erleichtern. + + +Entwicklungsumgebung +-------------------- +- [Editoren und IDEs |ide] empfohlene Editoren und Plugins für komfortables Arbeiten mit Nette, Latte und NEON. +- [Composer |best-practices:composer] praktische Tipps für die Arbeit mit dem PHP-Abhängigkeitsmanager: Installation, PHP-Version, Autoloading und mehr. + + +Code-Qualität +------------- +- [Code Checker |code-checker] überprüft Ihre Quelldateien auf formale Mängel wie ein unsichtbares BOM, Steuerzeichen, fehlerhafte Kodierung oder ungültige Syntax von PHP-, Latte-, NEON-, JSON- und YAML-Dateien und kann diese automatisch beheben. + + +Künstliche Intelligenz +---------------------- +- [Claude Code plugin |ai:en:claude-code] bringt Claude Code die Nette-Konventionen bei: Skills, automatische Validierung von Latte/NEON/JS und MCP-Integration. +- [MCP Inspector |ai:en:mcp-inspector] gibt der KI den realen Zustand Ihrer Anwendung: DI-Dienste, Datenbankschema, Routen und Tracy-Logs. + + +Frontend +-------- +- [Vite plugin |assets:vite] verbindet das Build-Tool Vite mit Nette Assets: HMR während der Entwicklung und optimierte Produktions-Builds. +- [ESLint plugin |https://github.com/nette/eslint-plugin] fügt ESLint-Regeln und -Konfiguration für JS/TS in Nette-Projekten hinzu, einschließlich Linting von JS in Latte-Templates. + + +Migration zu Latte +------------------ +- Konvertieren Sie Templates [von PHP |latte:cookbook/migration-from-php] und [von Twig |latte:cookbook/migration-from-twig] mit dem Tool latte-tools. diff --git a/tools/de/@meta.texy b/tools/de/@meta.texy new file mode 100644 index 0000000000..f9077c78aa --- /dev/null +++ b/tools/de/@meta.texy @@ -0,0 +1,2 @@ +{{sitename: Werkzeuge}} +{{leftbar: www:@menu-common}} diff --git a/tools/el/@home.texy b/tools/el/@home.texy new file mode 100644 index 0000000000..716a1dc628 --- /dev/null +++ b/tools/el/@home.texy @@ -0,0 +1,33 @@ +Εργαλεία +******** + +.[perex] +Βοηθητικά εργαλεία που διευκολύνουν την ανάπτυξη με το Nette. + + +Περιβάλλον ανάπτυξης +-------------------- +- [Επεξεργαστές και IDE |ide] συνιστώμενοι επεξεργαστές και πρόσθετα για άνετη εργασία με Nette, Latte και NEON. +- [Composer |best-practices:composer] πρακτικές συμβουλές για την εργασία με τον διαχειριστή εξαρτήσεων της PHP: εγκατάσταση, έκδοση PHP, autoloading και άλλα. + + +Ποιότητα κώδικα +--------------- +- [Code Checker |code-checker] ελέγχει τα πηγαία αρχεία σας για τυπικά σφάλματα, όπως ένα αόρατο BOM, χαρακτήρες ελέγχου, κατεστραμμένη κωδικοποίηση ή μη έγκυρη σύνταξη αρχείων PHP, Latte, NEON, JSON και YAML, και μπορεί να τα διορθώσει αυτόματα. + + +Τεχνητή νοημοσύνη +----------------- +- [Claude Code plugin |ai:en:claude-code] διδάσκει στο Claude Code τις συμβάσεις του Nette: δεξιότητες, αυτόματη επικύρωση Latte/NEON/JS και ενσωμάτωση MCP. +- [MCP Inspector |ai:en:mcp-inspector] δίνει στην AI την πραγματική κατάσταση της εφαρμογής σας: υπηρεσίες DI, σχήμα βάσης δεδομένων, routes και logs του Tracy. + + +Frontend +-------- +- [Vite plugin |assets:vite] συνδέει το εργαλείο build Vite με το Nette Assets: HMR κατά την ανάπτυξη και βελτιστοποιημένα production builds. +- [ESLint plugin |https://github.com/nette/eslint-plugin] προσθέτει κανόνες και ρυθμίσεις ESLint για JS/TS σε έργα Nette, συμπεριλαμβανομένου του ελέγχου JS μέσα σε πρότυπα Latte. + + +Μετάβαση στο Latte +------------------ +- Μετατρέψτε πρότυπα [από PHP |latte:cookbook/migration-from-php] και [από Twig |latte:cookbook/migration-from-twig] χρησιμοποιώντας το εργαλείο latte-tools. diff --git a/tools/el/@meta.texy b/tools/el/@meta.texy new file mode 100644 index 0000000000..1d83644d18 --- /dev/null +++ b/tools/el/@meta.texy @@ -0,0 +1,2 @@ +{{sitename: Εργαλεία}} +{{leftbar: www:@menu-common}} diff --git a/tools/en/@home.texy b/tools/en/@home.texy new file mode 100644 index 0000000000..7c83f9d102 --- /dev/null +++ b/tools/en/@home.texy @@ -0,0 +1,33 @@ +Tools +***** + +.[perex] +Helper tools that make development with Nette easier. + + +Development Environment +----------------------- +- [Editors and IDEs |ide] recommended editors and plugins for comfortable work with Nette, Latte and NEON. +- [Composer |best-practices:composer] practical tips for working with the PHP dependency manager: installation, PHP version, autoloading and more. + + +Code Quality +------------ +- [Code Checker |code-checker] checks your source files for formal flaws such as an invisible BOM, control characters, broken encoding, or invalid syntax of PHP, Latte, NEON, JSON and YAML files, and can fix them automatically. + + +Artificial Intelligence +----------------------- +- [Claude Code plugin |ai:en:claude-code] teaches Claude Code the Nette conventions: skills, automatic validation of Latte/NEON/JS, and MCP integration. +- [MCP Inspector |ai:en:mcp-inspector] gives AI the real state of your application: DI services, database schema, routes and Tracy logs. + + +Frontend +-------- +- [Vite plugin |assets:vite] connects the Vite build tool with Nette Assets: HMR during development and optimized production builds. +- [ESLint plugin |https://github.com/nette/eslint-plugin] adds ESLint rules and configuration for JS/TS in Nette projects, including linting JS inside Latte templates. + + +Migrating to Latte +------------------ +- Convert templates [from PHP |latte:cookbook/migration-from-php] and [from Twig |latte:cookbook/migration-from-twig] using the latte-tools tool. diff --git a/tools/en/@meta.texy b/tools/en/@meta.texy new file mode 100644 index 0000000000..29fd7cd65d --- /dev/null +++ b/tools/en/@meta.texy @@ -0,0 +1,2 @@ +{{sitename: Tools}} +{{leftbar: www:@menu-common}} diff --git a/tools/es/@home.texy b/tools/es/@home.texy new file mode 100644 index 0000000000..55010c1a22 --- /dev/null +++ b/tools/es/@home.texy @@ -0,0 +1,33 @@ +Herramientas +************ + +.[perex] +Herramientas auxiliares que facilitan el desarrollo con Nette. + + +Entorno de desarrollo +--------------------- +- [Editores e IDEs |ide] editores y plugins recomendados para trabajar cómodamente con Nette, Latte y NEON. +- [Composer |best-practices:composer] consejos prácticos para trabajar con el gestor de dependencias de PHP: instalación, versión de PHP, autoloading y más. + + +Calidad del código +------------------ +- [Code Checker |code-checker] comprueba sus archivos fuente en busca de defectos formales como un BOM invisible, caracteres de control, codificación dañada o sintaxis inválida de archivos PHP, Latte, NEON, JSON y YAML, y puede corregirlos automáticamente. + + +Inteligencia artificial +----------------------- +- [Claude Code plugin |ai:en:claude-code] enseña a Claude Code las convenciones de Nette: skills, validación automática de Latte/NEON/JS e integración con MCP. +- [MCP Inspector |ai:en:mcp-inspector] da a la IA el estado real de su aplicación: servicios de DI, esquema de la base de datos, rutas y registros de Tracy. + + +Frontend +-------- +- [Vite plugin |assets:vite] conecta la herramienta de compilación Vite con Nette Assets: HMR durante el desarrollo y compilaciones de producción optimizadas. +- [ESLint plugin |https://github.com/nette/eslint-plugin] añade reglas y configuración de ESLint para JS/TS en proyectos Nette, incluido el análisis de JS dentro de plantillas Latte. + + +Migración a Latte +----------------- +- Convierta plantillas [desde PHP |latte:cookbook/migration-from-php] y [desde Twig |latte:cookbook/migration-from-twig] usando la herramienta latte-tools. diff --git a/tools/es/@meta.texy b/tools/es/@meta.texy new file mode 100644 index 0000000000..f0b01d6c2b --- /dev/null +++ b/tools/es/@meta.texy @@ -0,0 +1,2 @@ +{{sitename: Herramientas}} +{{leftbar: www:@menu-common}} diff --git a/tools/fr/@home.texy b/tools/fr/@home.texy new file mode 100644 index 0000000000..24e4cb619c --- /dev/null +++ b/tools/fr/@home.texy @@ -0,0 +1,33 @@ +Outils +****** + +.[perex] +Des outils qui facilitent le développement avec Nette. + + +Environnement de développement +------------------------------ +- [Éditeurs et IDE |ide] éditeurs et plugins recommandés pour un travail confortable avec Nette, Latte et NEON. +- [Composer |best-practices:composer] conseils pratiques pour travailler avec le gestionnaire de dépendances de PHP : installation, version de PHP, autoloading et plus encore. + + +Qualité du code +--------------- +- [Code Checker |code-checker] vérifie vos fichiers sources et y détecte des défauts formels tels qu'un BOM invisible, des caractères de contrôle, un encodage incorrect ou une syntaxe invalide des fichiers PHP, Latte, NEON, JSON et YAML, et peut les corriger automatiquement. + + +Intelligence artificielle +------------------------- +- [Claude Code plugin |ai:en:claude-code] enseigne à Claude Code les conventions de Nette : skills, validation automatique de Latte/NEON/JS et intégration MCP. +- [MCP Inspector |ai:en:mcp-inspector] donne à l'IA l'état réel de votre application : services DI, schéma de base de données, routes et logs Tracy. + + +Frontend +-------- +- [Vite plugin |assets:vite] connecte l'outil de build Vite avec Nette Assets : HMR pendant le développement et builds de production optimisés. +- [ESLint plugin |https://github.com/nette/eslint-plugin] ajoute des règles et une configuration ESLint pour JS/TS dans les projets Nette, y compris le linting du JS à l'intérieur des templates Latte. + + +Migration vers Latte +-------------------- +- Convertissez les templates [depuis PHP |latte:cookbook/migration-from-php] et [depuis Twig |latte:cookbook/migration-from-twig] à l'aide de l'outil latte-tools. diff --git a/tools/fr/@meta.texy b/tools/fr/@meta.texy new file mode 100644 index 0000000000..665893ea04 --- /dev/null +++ b/tools/fr/@meta.texy @@ -0,0 +1,2 @@ +{{sitename: Outils}} +{{leftbar: www:@menu-common}} diff --git a/tools/hu/@home.texy b/tools/hu/@home.texy new file mode 100644 index 0000000000..1d581dbe3b --- /dev/null +++ b/tools/hu/@home.texy @@ -0,0 +1,33 @@ +Eszközök +******** + +.[perex] +Segédeszközök, amelyek megkönnyítik a fejlesztést a Nette-tel. + + +Fejlesztői környezet +-------------------- +- [Szerkesztők és IDE-k |ide] ajánlott szerkesztők és bővítmények a Nette, Latte és NEON kényelmes használatához. +- [Composer |best-practices:composer] gyakorlati tippek a PHP függőségkezelővel való munkához: telepítés, PHP verzió, autoloading és további. + + +Kódminőség +---------- +- [Code Checker |code-checker] ellenőrzi a forrásfájljaidat, és olyan formai hibákat keres bennük, mint a láthatatlan BOM, a vezérlő karakterek, a hibás kódolás vagy a PHP, Latte, NEON, JSON és YAML fájlok érvénytelen szintaxisa, és képes automatikusan kijavítani őket. + + +Mesterséges intelligencia +------------------------- +- [Claude Code plugin |ai:en:claude-code] megtanítja a Claude Code-nak a Nette konvencióit: skillek, a Latte/NEON/JS automatikus validálása és MCP integráció. +- [MCP Inspector |ai:en:mcp-inspector] megadja az AI-nak az alkalmazásod valós állapotát: DI szolgáltatások, adatbázis-séma, route-ok és Tracy naplók. + + +Frontend +-------- +- [Vite plugin |assets:vite] összeköti a Vite build eszközt a Nette Assets-szel: HMR a fejlesztés során és optimalizált éles buildek. +- [ESLint plugin |https://github.com/nette/eslint-plugin] ESLint szabályokat és konfigurációt ad a JS/TS-hez Nette projektekben, beleértve a Latte sablonokon belüli JS lintelését. + + +Migrálás Latte-ra +----------------- +- Sablonok konvertálása [PHP-ből |latte:cookbook/migration-from-php] és [Twig-ből |latte:cookbook/migration-from-twig] a latte-tools eszközzel. diff --git a/tools/hu/@meta.texy b/tools/hu/@meta.texy new file mode 100644 index 0000000000..0487619690 --- /dev/null +++ b/tools/hu/@meta.texy @@ -0,0 +1,2 @@ +{{sitename: Eszközök}} +{{leftbar: www:@menu-common}} diff --git a/tools/it/@home.texy b/tools/it/@home.texy new file mode 100644 index 0000000000..56dc4927fe --- /dev/null +++ b/tools/it/@home.texy @@ -0,0 +1,33 @@ +Strumenti +********* + +.[perex] +Strumenti di supporto che semplificano lo sviluppo con Nette. + + +Ambiente di sviluppo +-------------------- +- [Editor e IDE |ide] editor e plugin consigliati per lavorare comodamente con Nette, Latte e NEON. +- [Composer |best-practices:composer] consigli pratici per lavorare con il gestore di dipendenze di PHP: installazione, versione di PHP, autoloading e altro. + + +Qualità del codice +------------------ +- [Code Checker |code-checker] controlla i tuoi file sorgente alla ricerca di difetti formali come un BOM invisibile, caratteri di controllo, codifica errata o sintassi non valida nei file PHP, Latte, NEON, JSON e YAML, e può correggerli automaticamente. + + +Intelligenza artificiale +------------------------ +- [Claude Code plugin |ai:en:claude-code] insegna a Claude Code le convenzioni di Nette: skill, validazione automatica di Latte/NEON/JS e integrazione MCP. +- [MCP Inspector |ai:en:mcp-inspector] fornisce all'AI lo stato reale della tua applicazione: servizi DI, schema del database, route e log di Tracy. + + +Frontend +-------- +- [Vite plugin |assets:vite] collega lo strumento di build Vite con Nette Assets: HMR durante lo sviluppo e build di produzione ottimizzate. +- [ESLint plugin |https://github.com/nette/eslint-plugin] aggiunge regole e configurazione ESLint per JS/TS nei progetti Nette, incluso il linting del JS all'interno dei template Latte. + + +Migrazione a Latte +------------------ +- Converti i template [da PHP |latte:cookbook/migration-from-php] e [da Twig |latte:cookbook/migration-from-twig] usando lo strumento latte-tools. diff --git a/tools/it/@meta.texy b/tools/it/@meta.texy new file mode 100644 index 0000000000..f1a17db2cb --- /dev/null +++ b/tools/it/@meta.texy @@ -0,0 +1,2 @@ +{{sitename: Strumenti}} +{{leftbar: www:@menu-common}} diff --git a/tools/ja/@home.texy b/tools/ja/@home.texy new file mode 100644 index 0000000000..674cfee9df --- /dev/null +++ b/tools/ja/@home.texy @@ -0,0 +1,33 @@ +ツール +*** + +.[perex] +Nette での開発を容易にする補助ツール。 + + +開発環境 +---- +- [エディタと IDE |ide] は、Nette・Latte・NEON で快適に作業するためのおすすめエディタとプラグインです。 +- [Composer |best-practices:composer] PHP の依存関係マネージャーを扱うための実践的なヒント:インストール、PHP バージョン、オートローディングなど。 + + +コード品質 +----- +- [Code Checker |code-checker] は、目に見えない BOM、制御文字、壊れたエンコーディング、PHP・Latte・NEON・JSON・YAML ファイルの不正な構文といった形式的な欠陥がないかソースファイルをチェックし、自動的に修正できます。 + + +人工知能 +---- +- [Claude Code plugin |ai:en:claude-code] は、Claude Code に Nette の規約を教えます:スキル、Latte/NEON/JS の自動検証、MCP 連携。 +- [MCP Inspector |ai:en:mcp-inspector] は、AI にアプリケーションの実際の状態を伝えます:DI サービス、データベーススキーマ、ルート、Tracy のログ。 + + +フロントエンド +------- +- [Vite plugin |assets:vite] は、ビルドツール Vite を Nette Assets と連携させます:開発中の HMR と最適化された本番ビルド。 +- [ESLint plugin |https://github.com/nette/eslint-plugin] は、Nette プロジェクトの JS/TS 向けに ESLint のルールと設定を追加し、Latte テンプレート内の JS のリントにも対応します。 + + +Latte への移行 +---------- +- [PHP から |latte:cookbook/migration-from-php] および [Twig から |latte:cookbook/migration-from-twig] テンプレートを latte-tools ツールで変換します。 diff --git a/tools/ja/@meta.texy b/tools/ja/@meta.texy new file mode 100644 index 0000000000..18862645be --- /dev/null +++ b/tools/ja/@meta.texy @@ -0,0 +1,2 @@ +{{sitename: ツール}} +{{leftbar: www:@menu-common}} diff --git a/tools/meta.json b/tools/meta.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/tools/meta.json @@ -0,0 +1 @@ +{} diff --git a/tools/pl/@home.texy b/tools/pl/@home.texy new file mode 100644 index 0000000000..3dc205b0f6 --- /dev/null +++ b/tools/pl/@home.texy @@ -0,0 +1,33 @@ +Narzędzia +********* + +.[perex] +Narzędzia pomocnicze, które ułatwiają programowanie z Nette. + + +Środowisko programistyczne +-------------------------- +- [Edytory i IDE |ide] zalecane edytory i wtyczki do komfortowej pracy z Nette, Latte i NEON. +- [Composer |best-practices:composer] praktyczne wskazówki dotyczące pracy z menedżerem zależności PHP: instalacja, wersja PHP, autoloading i więcej. + + +Jakość kodu +----------- +- [Code Checker |code-checker] sprawdza Twoje pliki źródłowe pod kątem formalnych usterek, takich jak niewidoczny BOM, znaki kontrolne, błędne kodowanie czy nieprawidłowa składnia plików PHP, Latte, NEON, JSON i YAML, oraz potrafi je automatycznie naprawić. + + +Sztuczna inteligencja +--------------------- +- [Claude Code plugin |ai:en:claude-code] uczy Claude Code konwencji Nette: skille, automatyczna walidacja Latte/NEON/JS oraz integracja MCP. +- [MCP Inspector |ai:en:mcp-inspector] daje AI rzeczywisty stan Twojej aplikacji: usługi DI, schemat bazy danych, trasy i logi Tracy. + + +Frontend +-------- +- [Vite plugin |assets:vite] łączy narzędzie budujące Vite z Nette Assets: HMR podczas programowania i zoptymalizowane buildy produkcyjne. +- [ESLint plugin |https://github.com/nette/eslint-plugin] dodaje reguły i konfigurację ESLint dla JS/TS w projektach Nette, w tym lintowanie JS wewnątrz szablonów Latte. + + +Migracja do Latte +----------------- +- Konwertuj szablony [z PHP |latte:cookbook/migration-from-php] i [z Twig |latte:cookbook/migration-from-twig] za pomocą narzędzia latte-tools. diff --git a/tools/pl/@meta.texy b/tools/pl/@meta.texy new file mode 100644 index 0000000000..8ae9964df2 --- /dev/null +++ b/tools/pl/@meta.texy @@ -0,0 +1,2 @@ +{{sitename: Narzędzia}} +{{leftbar: www:@menu-common}} diff --git a/tools/pt/@home.texy b/tools/pt/@home.texy new file mode 100644 index 0000000000..e8bfb50671 --- /dev/null +++ b/tools/pt/@home.texy @@ -0,0 +1,33 @@ +Ferramentas +*********** + +.[perex] +Ferramentas auxiliares que facilitam o desenvolvimento com o Nette. + + +Ambiente de Desenvolvimento +--------------------------- +- [Editores e IDEs |ide] editores recomendados e plugins para um trabalho confortável com Nette, Latte e NEON. +- [Composer |best-practices:composer] dicas práticas para trabalhar com o gerenciador de dependências do PHP: instalação, versão do PHP, autoloading e mais. + + +Qualidade do Código +------------------- +- [Code Checker |code-checker] verifica seus arquivos de origem em busca de falhas formais, como um BOM invisível, caracteres de controle, codificação corrompida ou sintaxe inválida de arquivos PHP, Latte, NEON, JSON e YAML, e pode corrigi-los automaticamente. + + +Inteligência Artificial +----------------------- +- [Claude Code plugin |ai:en:claude-code] ensina ao Claude Code as convenções do Nette: skills, validação automática de Latte/NEON/JS e integração com MCP. +- [MCP Inspector |ai:en:mcp-inspector] dá à IA o estado real da sua aplicação: serviços DI, esquema do banco de dados, rotas e logs do Tracy. + + +Frontend +-------- +- [Vite plugin |assets:vite] conecta a ferramenta de build Vite com o Nette Assets: HMR durante o desenvolvimento e builds de produção otimizados. +- [ESLint plugin |https://github.com/nette/eslint-plugin] adiciona regras e configuração do ESLint para JS/TS em projetos Nette, incluindo a verificação de JS dentro de templates Latte. + + +Migração para o Latte +--------------------- +- Converta templates [do PHP |latte:cookbook/migration-from-php] e [do Twig |latte:cookbook/migration-from-twig] usando a ferramenta latte-tools. diff --git a/tools/pt/@meta.texy b/tools/pt/@meta.texy new file mode 100644 index 0000000000..874af6f9be --- /dev/null +++ b/tools/pt/@meta.texy @@ -0,0 +1,2 @@ +{{sitename: Ferramentas}} +{{leftbar: www:@menu-common}} diff --git a/tools/ro/@home.texy b/tools/ro/@home.texy new file mode 100644 index 0000000000..157319a7f8 --- /dev/null +++ b/tools/ro/@home.texy @@ -0,0 +1,33 @@ +Instrumente +*********** + +.[perex] +Instrumente ajutătoare care ușurează dezvoltarea cu Nette. + + +Mediu de dezvoltare +------------------- +- [Editoare și IDE-uri |ide] editoare și pluginuri recomandate pentru o lucrare confortabilă cu Nette, Latte și NEON. +- [Composer |best-practices:composer] sfaturi practice pentru lucrul cu managerul de dependențe PHP: instalare, versiunea PHP, autoloading și altele. + + +Calitatea codului +----------------- +- [Code Checker |code-checker] verifică fișierele sursă pentru defecte formale precum un BOM invizibil, caractere de control, codificare deteriorată sau sintaxă invalidă a fișierelor PHP, Latte, NEON, JSON și YAML și le poate corecta automat. + + +Inteligență artificială +----------------------- +- [Claude Code plugin |ai:en:claude-code] învață Claude Code convențiile Nette: skill-uri, validare automată a Latte/NEON/JS și integrare MCP. +- [MCP Inspector |ai:en:mcp-inspector] oferă AI-ului starea reală a aplicației tale: servicii DI, schema bazei de date, rute și loguri Tracy. + + +Frontend +-------- +- [Vite plugin |assets:vite] conectează instrumentul de build Vite cu Nette Assets: HMR în timpul dezvoltării și build-uri de producție optimizate. +- [ESLint plugin |https://github.com/nette/eslint-plugin] adaugă reguli și configurare ESLint pentru JS/TS în proiectele Nette, inclusiv lintarea JS în interiorul șabloanelor Latte. + + +Migrarea la Latte +----------------- +- Convertește șabloane [din PHP |latte:cookbook/migration-from-php] și [din Twig |latte:cookbook/migration-from-twig] folosind instrumentul latte-tools. diff --git a/tools/ro/@meta.texy b/tools/ro/@meta.texy new file mode 100644 index 0000000000..0d7efe0a23 --- /dev/null +++ b/tools/ro/@meta.texy @@ -0,0 +1,2 @@ +{{sitename: Instrumente}} +{{leftbar: www:@menu-common}} diff --git a/tools/ru/@home.texy b/tools/ru/@home.texy new file mode 100644 index 0000000000..180ab37a00 --- /dev/null +++ b/tools/ru/@home.texy @@ -0,0 +1,33 @@ +Инструменты +*********** + +.[perex] +Вспомогательные инструменты, которые упрощают разработку с Nette. + + +Среда разработки +---------------- +- [Редакторы и IDE |ide] рекомендуемые редакторы и плагины для комфортной работы с Nette, Latte и NEON. +- [Composer |best-practices:composer] практические советы по работе с менеджером зависимостей PHP: установка, версия PHP, автозагрузка и многое другое. + + +Качество кода +------------- +- [Code Checker |code-checker] проверяет ваши исходные файлы и находит в них формальные недочёты, такие как невидимый BOM, управляющие символы, неправильную кодировку или некорректный синтаксис файлов PHP, Latte, NEON, JSON и YAML, и умеет их автоматически исправлять. + + +Искусственный интеллект +----------------------- +- [Claude Code plugin |ai:en:claude-code] обучает Claude Code соглашениям Nette: навыки, автоматическую проверку Latte/NEON/JS и интеграцию с MCP. +- [MCP Inspector |ai:en:mcp-inspector] даёт ИИ реальное состояние вашего приложения: сервисы DI, схему базы данных, маршруты и логи Tracy. + + +Frontend +-------- +- [Vite plugin |assets:vite] связывает инструмент сборки Vite с Nette Assets: HMR во время разработки и оптимизированные сборки для продакшена. +- [ESLint plugin |https://github.com/nette/eslint-plugin] добавляет правила и конфигурацию ESLint для JS/TS в проектах Nette, включая проверку JS внутри шаблонов Latte. + + +Переход на Latte +---------------- +- Конвертируйте шаблоны [с PHP |latte:cookbook/migration-from-php] и [с Twig |latte:cookbook/migration-from-twig] с помощью инструмента latte-tools. diff --git a/tools/ru/@meta.texy b/tools/ru/@meta.texy new file mode 100644 index 0000000000..a303edaa11 --- /dev/null +++ b/tools/ru/@meta.texy @@ -0,0 +1,2 @@ +{{sitename: Инструменты}} +{{leftbar: www:@menu-common}} diff --git a/tools/sl/@home.texy b/tools/sl/@home.texy new file mode 100644 index 0000000000..ec982ded75 --- /dev/null +++ b/tools/sl/@home.texy @@ -0,0 +1,33 @@ +Orodja +****** + +.[perex] +Pomožna orodja, ki olajšajo razvoj z Nette. + + +Razvojno okolje +--------------- +- [Urejevalniki in IDE-ji |ide] priporočeni urejevalniki in vtičniki za udobno delo z Nette, Latte in NEON. +- [Composer |best-practices:composer] praktični nasveti za delo z upravljalnikom odvisnosti za PHP: namestitev, različica PHP, samodejno nalaganje in še več. + + +Kakovost kode +------------- +- [Code Checker |code-checker] preveri vaše izvorne datoteke in v njih poišče formalne pomanjkljivosti, kot so neviden BOM, kontrolni znaki, pokvarjeno kodiranje ali neveljavna sintaksa datotek PHP, Latte, NEON, JSON in YAML, ter jih zna samodejno popraviti. + + +Umetna inteligenca +------------------ +- [Claude Code plugin |ai:en:claude-code] nauči Claude Code konvencij Nette: spretnosti, samodejno validacijo Latte/NEON/JS in integracijo MCP. +- [MCP Inspector |ai:en:mcp-inspector] daje AI dejansko stanje vaše aplikacije: storitve DI, shemo baze podatkov, poti in dnevnike Tracy. + + +Frontend +-------- +- [Vite plugin |assets:vite] poveže orodje za gradnjo Vite z Nette Assets: HMR med razvojem in optimizirane produkcijske gradnje. +- [ESLint plugin |https://github.com/nette/eslint-plugin] doda pravila in konfiguracijo ESLint za JS/TS v projektih Nette, vključno z lintanjem JS znotraj predlog Latte. + + +Migracija na Latte +------------------ +- Pretvorite predloge [iz PHP |latte:cookbook/migration-from-php] in [iz Twig |latte:cookbook/migration-from-twig] z orodjem latte-tools. diff --git a/tools/sl/@meta.texy b/tools/sl/@meta.texy new file mode 100644 index 0000000000..a26fd928e5 --- /dev/null +++ b/tools/sl/@meta.texy @@ -0,0 +1,2 @@ +{{sitename: Orodja}} +{{leftbar: www:@menu-common}} diff --git a/tools/tr/@home.texy b/tools/tr/@home.texy new file mode 100644 index 0000000000..2b84564bad --- /dev/null +++ b/tools/tr/@home.texy @@ -0,0 +1,33 @@ +Araçlar +******* + +.[perex] +Nette ile geliştirmeyi kolaylaştıran yardımcı araçlar. + + +Geliştirme Ortamı +----------------- +- [Editörler ve IDE'ler |ide] Nette, Latte ve NEON ile rahat çalışmak için önerilen editörler ve eklentiler. +- [Composer |best-practices:composer] PHP bağımlılık yöneticisiyle çalışmak için pratik ipuçları: kurulum, PHP sürümü, otomatik yükleme ve daha fazlası. + + +Kod Kalitesi +------------ +- [Code Checker |code-checker] kaynak dosyalarınızı görünmez bir BOM, kontrol karakterleri, bozuk kodlama veya PHP, Latte, NEON, JSON ve YAML dosyalarının geçersiz söz dizimi gibi biçimsel kusurlara karşı denetler ve bunları otomatik olarak düzeltebilir. + + +Yapay Zekâ +---------- +- [Claude Code plugin |ai:en:claude-code] Claude Code'a Nette kurallarını öğretir: beceriler, Latte/NEON/JS'in otomatik doğrulanması ve MCP entegrasyonu. +- [MCP Inspector |ai:en:mcp-inspector] yapay zekâya uygulamanızın gerçek durumunu verir: DI servisleri, veritabanı şeması, rotalar ve Tracy günlükleri. + + +Frontend +-------- +- [Vite plugin |assets:vite] Vite derleme aracını Nette Assets ile bağlar: geliştirme sırasında HMR ve optimize edilmiş üretim derlemeleri. +- [ESLint plugin |https://github.com/nette/eslint-plugin] Nette projelerinde JS/TS için ESLint kuralları ve yapılandırması ekler, Latte şablonlarının içindeki JS'in denetlenmesi dahil. + + +Latte'ye Geçiş +-------------- +- Şablonları latte-tools aracıyla [PHP'den |latte:cookbook/migration-from-php] ve [Twig'den |latte:cookbook/migration-from-twig] dönüştürün. diff --git a/tools/tr/@meta.texy b/tools/tr/@meta.texy new file mode 100644 index 0000000000..fa623c1e3b --- /dev/null +++ b/tools/tr/@meta.texy @@ -0,0 +1,2 @@ +{{sitename: Araçlar}} +{{leftbar: www:@menu-common}} diff --git a/tools/uk/@home.texy b/tools/uk/@home.texy new file mode 100644 index 0000000000..0ad9c700b4 --- /dev/null +++ b/tools/uk/@home.texy @@ -0,0 +1,33 @@ +Інструменти +*********** + +.[perex] +Допоміжні інструменти, які спрощують розробку з Nette. + + +Середовище розробки +------------------- +- [Редактори та IDE |ide] рекомендовані редактори та плагіни для комфортної роботи з Nette, Latte та NEON. +- [Composer |best-practices:composer] практичні поради щодо роботи з менеджером залежностей PHP: встановлення, версія PHP, автозавантаження тощо. + + +Якість коду +----------- +- [Code Checker |code-checker] перевіряє ваші вихідні файли на формальні недоліки, такі як невидимий BOM, керуючі символи, пошкоджене кодування або неправильний синтаксис файлів PHP, Latte, NEON, JSON та YAML, і вміє виправляти їх автоматично. + + +Штучний інтелект +---------------- +- [Claude Code plugin |ai:en:claude-code] навчає Claude Code конвенцій Nette: навички, автоматична валідація Latte/NEON/JS та інтеграція з MCP. +- [MCP Inspector |ai:en:mcp-inspector] надає AI реальний стан вашого застосунку: DI сервіси, схему бази даних, маршрути та логи Tracy. + + +Frontend +-------- +- [Vite plugin |assets:vite] з'єднує інструмент збірки Vite з Nette Assets: HMR під час розробки та оптимізовані продакшн-збірки. +- [ESLint plugin |https://github.com/nette/eslint-plugin] додає правила та конфігурацію ESLint для JS/TS у проєктах Nette, включно з лінтингом JS всередині шаблонів Latte. + + +Міграція на Latte +----------------- +- Перетворюйте шаблони [з PHP |latte:cookbook/migration-from-php] та [з Twig |latte:cookbook/migration-from-twig] за допомогою інструмента latte-tools. diff --git a/tools/uk/@meta.texy b/tools/uk/@meta.texy new file mode 100644 index 0000000000..455e973546 --- /dev/null +++ b/tools/uk/@meta.texy @@ -0,0 +1,2 @@ +{{sitename: Інструменти}} +{{leftbar: www:@menu-common}} diff --git a/www/bg/@menu-common.texy b/www/bg/@menu-common.texy index c73571ce15..9ee57639ac 100644 --- a/www/bg/@menu-common.texy +++ b/www/bg/@menu-common.texy @@ -18,5 +18,6 @@ - [Подкрепете разработката |https://nette.org/cs/donate] - [API референция |https://api.nette.org/] - [Ръководства и практики |best-practices:] +- [Инструменти |tools:] - [Сигурността преди всичко |nette:vulnerability-protection] diff --git a/www/cs/@menu-common.texy b/www/cs/@menu-common.texy index 57bc422743..a6ee3bb7c2 100644 --- a/www/cs/@menu-common.texy +++ b/www/cs/@menu-common.texy @@ -18,5 +18,6 @@ Obecné témata - [Podpořte vývoj |https://nette.org/cs/donate] - [API reference |https://api.nette.org/] - [Návody a postupy |best-practices:] +- [Nástroje |tools:] - [Bezpečnost především |nette:vulnerability-protection] diff --git a/www/de/@menu-common.texy b/www/de/@menu-common.texy index 50f7f5e016..65585ea217 100644 --- a/www/de/@menu-common.texy +++ b/www/de/@menu-common.texy @@ -18,5 +18,6 @@ Allgemeine Themen - [Unterstützen Sie die Entwicklung |https://nette.org/cs/donate] - [API-Referenz |https://api.nette.org/] - [Anleitungen und Verfahren |best-practices:] +- [Werkzeuge |tools:] - [Sicherheit zuerst |nette:vulnerability-protection] diff --git a/www/el/@menu-common.texy b/www/el/@menu-common.texy index 7131ba95b4..8015d2a320 100644 --- a/www/el/@menu-common.texy +++ b/www/el/@menu-common.texy @@ -18,5 +18,6 @@ - [Υποστηρίξτε την ανάπτυξη |https://nette.org/cs/donate] - [Αναφορά API |https://api.nette.org/] - [Οδηγοί και βέλτιστες πρακτικές |best-practices:] +- [Εργαλεία |tools:] - [Η ασφάλεια πάνω απ' όλα |nette:vulnerability-protection] diff --git a/www/en/@menu-common.texy b/www/en/@menu-common.texy index 6b8259699e..171b54ab3d 100644 --- a/www/en/@menu-common.texy +++ b/www/en/@menu-common.texy @@ -18,5 +18,6 @@ General Topics - [Sponsor Development |https://nette.org/en/donate] - [API Reference |https://api.nette.org/] - [Tutorials and Best Practices |best-practices:] +- [Tools |tools:] - [Security First |nette:vulnerability-protection] diff --git a/www/es/@menu-common.texy b/www/es/@menu-common.texy index edc149d1d1..f863d9de49 100644 --- a/www/es/@menu-common.texy +++ b/www/es/@menu-common.texy @@ -18,5 +18,6 @@ Temas generales - [Apoya el desarrollo |https://nette.org/cs/donate] - [Referencia API |https://api.nette.org/] - [Tutoriales y mejores prácticas |best-practices:] +- [Herramientas |tools:] - [La seguridad es lo primero |nette:vulnerability-protection] diff --git a/www/fr/@menu-common.texy b/www/fr/@menu-common.texy index edb861f0df..f5777a0dbf 100644 --- a/www/fr/@menu-common.texy +++ b/www/fr/@menu-common.texy @@ -18,5 +18,6 @@ Sujets généraux - [Soutenir le développement |https://nette.org/fr/donate] - [Référence API |https://api.nette.org/] - [Tutoriels et bonnes pratiques |best-practices:] +- [Outils |tools:] - [La sécurité avant tout |nette:vulnerability-protection] diff --git a/www/hu/@menu-common.texy b/www/hu/@menu-common.texy index b0c976258c..ebbd25643e 100644 --- a/www/hu/@menu-common.texy +++ b/www/hu/@menu-common.texy @@ -18,5 +18,6 @@ Ismerkedés - [Támogassa a fejlesztést |https://nette.org/cs/donate] - [API referencia |https://api.nette.org/] - [Útmutatók és eljárások |best-practices:] +- [Eszközök |tools:] - [Biztonság mindenekelőtt |nette:vulnerability-protection] diff --git a/www/it/@menu-common.texy b/www/it/@menu-common.texy index d8495db569..b37b973bb5 100644 --- a/www/it/@menu-common.texy +++ b/www/it/@menu-common.texy @@ -18,5 +18,6 @@ Argomenti generali - [Sostieni lo sviluppo |https://nette.org/cs/donate] - [Riferimento API |https://api.nette.org/] - [Guide e procedure |best-practices:] +- [Strumenti |tools:] - [La sicurezza prima di tutto |nette:vulnerability-protection] diff --git a/www/ja/@menu-common.texy b/www/ja/@menu-common.texy index b1e59054ea..fec59cb2f0 100644 --- a/www/ja/@menu-common.texy +++ b/www/ja/@menu-common.texy @@ -18,5 +18,6 @@ - [開発を支援する |https://nette.org/cs/donate] - [APIリファレンス |https://api.nette.org/] - [ガイドとベストプラクティス |best-practices:] +- [ツール |tools:] - [セキュリティ第一 |nette:vulnerability-protection] diff --git a/www/pl/@menu-common.texy b/www/pl/@menu-common.texy index 2553daf369..232a9e91af 100644 --- a/www/pl/@menu-common.texy +++ b/www/pl/@menu-common.texy @@ -18,5 +18,6 @@ Ogólne tematy - [Wspieraj rozwój |https://nette.org/cs/donate] - [Referencja API |https://api.nette.org/] - [Poradniki i najlepsze praktyki |best-practices:] +- [Narzędzia |tools:] - [Bezpieczeństwo przede wszystkim |nette:vulnerability-protection] diff --git a/www/pt/@menu-common.texy b/www/pt/@menu-common.texy index d77e16dbc2..2458a9b451 100644 --- a/www/pt/@menu-common.texy +++ b/www/pt/@menu-common.texy @@ -18,5 +18,6 @@ Tópicos gerais - [Apoie o desenvolvimento |https://nette.org/pt/donate] - [Referência da API |https://api.nette.org/] - [Tutoriais e melhores práticas |best-practices:] +- [Ferramentas |tools:] - [Segurança em primeiro lugar |nette:vulnerability-protection] diff --git a/www/ro/@menu-common.texy b/www/ro/@menu-common.texy index d2b027f02a..7c69189f7b 100644 --- a/www/ro/@menu-common.texy +++ b/www/ro/@menu-common.texy @@ -18,5 +18,6 @@ Subiecte generale - [Susțineți dezvoltarea |https://nette.org/cs/donate] - [Referință API |https://api.nette.org/] - [Ghiduri și proceduri |best-practices:] +- [Instrumente |tools:] - [Securitatea înainte de toate |nette:vulnerability-protection] diff --git a/www/ru/@menu-common.texy b/www/ru/@menu-common.texy index b3e9b34774..940d27eea3 100644 --- a/www/ru/@menu-common.texy +++ b/www/ru/@menu-common.texy @@ -18,5 +18,6 @@ - [Поддержите разработку |https://nette.org/ru/donate] - [Справочник API |https://api.nette.org/] - [Руководства и лучшие практики |best-practices:] +- [Инструменты |tools:] - [Безопасность прежде всего |nette:vulnerability-protection] diff --git a/www/sl/@menu-common.texy b/www/sl/@menu-common.texy index a871acd113..9f704bdc34 100644 --- a/www/sl/@menu-common.texy +++ b/www/sl/@menu-common.texy @@ -18,5 +18,6 @@ Splošne teme - [Podprite razvoj |https://nette.org/cs/donate] - [API reference |https://api.nette.org/] - [Navodila in postopki |best-practices:] +- [Orodja |tools:] - [Varnost na prvem mestu |nette:vulnerability-protection] diff --git a/www/tr/@menu-common.texy b/www/tr/@menu-common.texy index 4375d1cd3e..c2250cdaf8 100644 --- a/www/tr/@menu-common.texy +++ b/www/tr/@menu-common.texy @@ -18,5 +18,6 @@ Genel Konular - [Geliştirmeyi Destekleyin |https://nette.org/en/donate] - [API Referansı |https://api.nette.org/] - [Kılavuzlar ve yöntemler |best-practices:] +- [Araçlar |tools:] - [Önce Güvenlik |nette:vulnerability-protection] diff --git a/www/uk/@menu-common.texy b/www/uk/@menu-common.texy index 44ddbcd3d8..3e542b9855 100644 --- a/www/uk/@menu-common.texy +++ b/www/uk/@menu-common.texy @@ -18,5 +18,6 @@ - [Підтримайте розробку |https://nette.org/cs/donate] - [API reference |https://api.nette.org/] - [Посібники та практики |best-practices:] +- [Інструменти |tools:] - [Безпека перш за все |nette:vulnerability-protection] From f8ba863c73d0df91df2981e27be52ff33fd15e81 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Sat, 6 Jun 2026 14:46:12 +0200 Subject: [PATCH 38/50] moved code-checker to tools --- best-practices/bg/editors-and-tools.texy | 2 +- best-practices/cs/editors-and-tools.texy | 2 +- best-practices/de/editors-and-tools.texy | 2 +- best-practices/el/editors-and-tools.texy | 2 +- best-practices/en/editors-and-tools.texy | 2 +- best-practices/es/editors-and-tools.texy | 2 +- best-practices/fr/editors-and-tools.texy | 2 +- best-practices/hu/editors-and-tools.texy | 2 +- best-practices/it/editors-and-tools.texy | 2 +- best-practices/ja/editors-and-tools.texy | 2 +- best-practices/pl/editors-and-tools.texy | 2 +- best-practices/pt/editors-and-tools.texy | 2 +- best-practices/ro/editors-and-tools.texy | 2 +- best-practices/ru/editors-and-tools.texy | 2 +- best-practices/sl/editors-and-tools.texy | 2 +- best-practices/tr/editors-and-tools.texy | 2 +- best-practices/uk/editors-and-tools.texy | 2 +- contributing/bg/documentation.texy | 2 +- contributing/cs/documentation.texy | 2 +- contributing/de/documentation.texy | 2 +- contributing/el/documentation.texy | 2 +- contributing/en/documentation.texy | 2 +- contributing/es/documentation.texy | 2 +- contributing/fr/documentation.texy | 2 +- contributing/hu/documentation.texy | 2 +- contributing/it/documentation.texy | 2 +- contributing/ja/documentation.texy | 2 +- contributing/pl/documentation.texy | 2 +- contributing/pt/documentation.texy | 2 +- contributing/ro/documentation.texy | 2 +- contributing/ru/documentation.texy | 2 +- contributing/sl/documentation.texy | 2 +- contributing/tr/documentation.texy | 2 +- contributing/uk/documentation.texy | 2 +- nette/bg/glossary.texy | 4 ++-- nette/cs/glossary.texy | 4 ++-- nette/de/glossary.texy | 4 ++-- nette/el/glossary.texy | 4 ++-- nette/en/glossary.texy | 4 ++-- nette/es/glossary.texy | 4 ++-- nette/fr/glossary.texy | 4 ++-- nette/hu/glossary.texy | 4 ++-- nette/it/glossary.texy | 4 ++-- nette/ja/glossary.texy | 4 ++-- nette/pl/glossary.texy | 4 ++-- nette/pt/glossary.texy | 4 ++-- nette/ro/glossary.texy | 4 ++-- nette/ru/glossary.texy | 4 ++-- nette/sl/glossary.texy | 4 ++-- nette/tr/glossary.texy | 4 ++-- nette/uk/glossary.texy | 4 ++-- code-checker/bg/@home.texy => tools/bg/code-checker.texy | 2 -- code-checker/cs/@home.texy => tools/cs/code-checker.texy | 1 - code-checker/de/@home.texy => tools/de/code-checker.texy | 2 -- code-checker/el/@home.texy => tools/el/code-checker.texy | 2 -- code-checker/en/@home.texy => tools/en/code-checker.texy | 1 - code-checker/es/@home.texy => tools/es/code-checker.texy | 2 -- code-checker/fr/@home.texy => tools/fr/code-checker.texy | 2 -- code-checker/hu/@home.texy => tools/hu/code-checker.texy | 2 -- code-checker/it/@home.texy => tools/it/code-checker.texy | 2 -- code-checker/ja/@home.texy => tools/ja/code-checker.texy | 2 -- code-checker/pl/@home.texy => tools/pl/code-checker.texy | 2 -- code-checker/pt/@home.texy => tools/pt/code-checker.texy | 2 -- code-checker/ro/@home.texy => tools/ro/code-checker.texy | 2 -- code-checker/ru/@home.texy => tools/ru/code-checker.texy | 2 -- code-checker/sl/@home.texy => tools/sl/code-checker.texy | 2 -- code-checker/tr/@home.texy => tools/tr/code-checker.texy | 2 -- code-checker/uk/@home.texy => tools/uk/code-checker.texy | 2 -- 68 files changed, 68 insertions(+), 100 deletions(-) rename code-checker/bg/@home.texy => tools/bg/code-checker.texy (98%) rename code-checker/cs/@home.texy => tools/cs/code-checker.texy (98%) rename code-checker/de/@home.texy => tools/de/code-checker.texy (98%) rename code-checker/el/@home.texy => tools/el/code-checker.texy (98%) rename code-checker/en/@home.texy => tools/en/code-checker.texy (98%) rename code-checker/es/@home.texy => tools/es/code-checker.texy (98%) rename code-checker/fr/@home.texy => tools/fr/code-checker.texy (98%) rename code-checker/hu/@home.texy => tools/hu/code-checker.texy (98%) rename code-checker/it/@home.texy => tools/it/code-checker.texy (98%) rename code-checker/ja/@home.texy => tools/ja/code-checker.texy (98%) rename code-checker/pl/@home.texy => tools/pl/code-checker.texy (98%) rename code-checker/pt/@home.texy => tools/pt/code-checker.texy (98%) rename code-checker/ro/@home.texy => tools/ro/code-checker.texy (98%) rename code-checker/ru/@home.texy => tools/ru/code-checker.texy (98%) rename code-checker/sl/@home.texy => tools/sl/code-checker.texy (98%) rename code-checker/tr/@home.texy => tools/tr/code-checker.texy (98%) rename code-checker/uk/@home.texy => tools/uk/code-checker.texy (98%) diff --git a/best-practices/bg/editors-and-tools.texy b/best-practices/bg/editors-and-tools.texy index 89751ce259..b1d0e84b88 100644 --- a/best-practices/bg/editors-and-tools.texy +++ b/best-practices/bg/editors-and-tools.texy @@ -59,7 +59,7 @@ vendor/bin/phpstan analyse app Code Checker ============ -[Code Checker|code-checker:] проверява и евентуално коригира някои от формалните грешки във вашия изходен код: +[Code Checker|tools:code-checker] проверява и евентуално коригира някои от формалните грешки във вашия изходен код: - премахва [BOM |nette:glossary#BOM] - проверява валидността на [Latte |latte:] шаблоните diff --git a/best-practices/cs/editors-and-tools.texy b/best-practices/cs/editors-and-tools.texy index efbbd772ba..1c2d4d8fad 100644 --- a/best-practices/cs/editors-and-tools.texy +++ b/best-practices/cs/editors-and-tools.texy @@ -59,7 +59,7 @@ Vyčerpávající dokumentaci najdete přímo na [stránkách PHPStan |https://p Code Checker ============ -[Code Checker|code-checker:] zkontroluje a případně opraví některé z formálních chyb ve vašich zdrojových kódech: +[Code Checker|tools:code-checker] zkontroluje a případně opraví některé z formálních chyb ve vašich zdrojových kódech: - odstraňuje [BOM |nette:glossary#BOM] - kontroluje validitu [Latte |latte:] šablon diff --git a/best-practices/de/editors-and-tools.texy b/best-practices/de/editors-and-tools.texy index bda0c9c7fb..488b213f91 100644 --- a/best-practices/de/editors-and-tools.texy +++ b/best-practices/de/editors-and-tools.texy @@ -59,7 +59,7 @@ Eine ausführliche Dokumentation finden Sie direkt auf den [PHPStan-Seiten |http Code Checker ============ -Der [Code Checker|code-checker:] überprüft und korrigiert gegebenenfalls einige formale Fehler in Ihren Quellcodes: +Der [Code Checker|tools:code-checker] überprüft und korrigiert gegebenenfalls einige formale Fehler in Ihren Quellcodes: - entfernt [BOM |nette:glossary#BOM] - überprüft die Gültigkeit von [Latte |latte:]-Templates diff --git a/best-practices/el/editors-and-tools.texy b/best-practices/el/editors-and-tools.texy index a5d46f739c..4aa507357e 100644 --- a/best-practices/el/editors-and-tools.texy +++ b/best-practices/el/editors-and-tools.texy @@ -59,7 +59,7 @@ vendor/bin/phpstan analyse app Code Checker ============ -Ο [Code Checker|code-checker:] ελέγχει και ενδεχομένως διορθώνει ορισμένα από τα τυπικά σφάλματα στους πηγαίους κώδικές σας: +Ο [Code Checker|tools:code-checker] ελέγχει και ενδεχομένως διορθώνει ορισμένα από τα τυπικά σφάλματα στους πηγαίους κώδικές σας: - αφαιρεί το [BOM |nette:glossary#BOM] - ελέγχει την εγκυρότητα των templates [Latte |latte:] diff --git a/best-practices/en/editors-and-tools.texy b/best-practices/en/editors-and-tools.texy index e81b575eb6..7430f5893d 100644 --- a/best-practices/en/editors-and-tools.texy +++ b/best-practices/en/editors-and-tools.texy @@ -59,7 +59,7 @@ You can find comprehensive documentation directly on the [PHPStan website |https Code Checker ============ -[Code Checker|code-checker:] checks and potentially fixes some formal errors in your source code: +[Code Checker|tools:code-checker] checks and potentially fixes some formal errors in your source code: - removes [BOM |nette:glossary#BOM] - checks the validity of [Latte |latte:] templates diff --git a/best-practices/es/editors-and-tools.texy b/best-practices/es/editors-and-tools.texy index 36d9c62866..31bcbd3953 100644 --- a/best-practices/es/editors-and-tools.texy +++ b/best-practices/es/editors-and-tools.texy @@ -59,7 +59,7 @@ Encontrarás documentación exhaustiva directamente en el [sitio web de PHPStan Code Checker ============ -[Code Checker|code-checker:] comprueba y, opcionalmente, corrige algunos de los errores formales en tus códigos fuente: +[Code Checker|tools:code-checker] comprueba y, opcionalmente, corrige algunos de los errores formales en tus códigos fuente: - elimina [BOM |nette:glossary#BOM] - comprueba la validez de las plantillas [Latte |latte:] diff --git a/best-practices/fr/editors-and-tools.texy b/best-practices/fr/editors-and-tools.texy index f80342f3fe..ea29942514 100644 --- a/best-practices/fr/editors-and-tools.texy +++ b/best-practices/fr/editors-and-tools.texy @@ -59,7 +59,7 @@ Vous trouverez une documentation exhaustive directement sur le [site web de PHPS Code Checker ============ -[Code Checker|code-checker:] vérifie et corrige éventuellement certaines erreurs formelles dans vos codes sources : +[Code Checker|tools:code-checker] vérifie et corrige éventuellement certaines erreurs formelles dans vos codes sources : - supprime le [BOM |nette:glossary#BOM] - vérifie la validité des templates [Latte |latte:] diff --git a/best-practices/hu/editors-and-tools.texy b/best-practices/hu/editors-and-tools.texy index 7104666da7..4ff8d1307e 100644 --- a/best-practices/hu/editors-and-tools.texy +++ b/best-practices/hu/editors-and-tools.texy @@ -59,7 +59,7 @@ Kimerítő dokumentációt találsz közvetlenül a [PHPStan oldalán |https://p Code Checker ============ -A [Code Checker|code-checker:] ellenőrzi és szükség esetén kijavítja a forráskódok néhány formai hibáját: +A [Code Checker|tools:code-checker] ellenőrzi és szükség esetén kijavítja a forráskódok néhány formai hibáját: - eltávolítja a [BOM |nette:glossary#BOM]-ot - ellenőrzi a [Latte |latte:] sablonok érvényességét diff --git a/best-practices/it/editors-and-tools.texy b/best-practices/it/editors-and-tools.texy index 9386b93f8e..70ad5a31ef 100644 --- a/best-practices/it/editors-and-tools.texy +++ b/best-practices/it/editors-and-tools.texy @@ -59,7 +59,7 @@ Troverete una documentazione esaustiva direttamente sul [sito web di PHPStan |ht Code Checker ============ -[Code Checker|code-checker:] controlla ed eventualmente corregge alcuni errori formali nei vostri codici sorgente: +[Code Checker|tools:code-checker] controlla ed eventualmente corregge alcuni errori formali nei vostri codici sorgente: - rimuove il [BOM |nette:glossary#BOM] - controlla la validità dei template [Latte |latte:] diff --git a/best-practices/ja/editors-and-tools.texy b/best-practices/ja/editors-and-tools.texy index 36e72f6ea2..25ae2c5845 100644 --- a/best-practices/ja/editors-and-tools.texy +++ b/best-practices/ja/editors-and-tools.texy @@ -59,7 +59,7 @@ vendor/bin/phpstan analyse app Code Checker ============ -[Code Checker|code-checker:] は、ソースコード内の一部の形式的なエラーをチェックし、場合によっては修正します: +[Code Checker|tools:code-checker] は、ソースコード内の一部の形式的なエラーをチェックし、場合によっては修正します: - [BOM |nette:glossary#BOM] を削除します - [Latte |latte:] テンプレートの有効性をチェックします diff --git a/best-practices/pl/editors-and-tools.texy b/best-practices/pl/editors-and-tools.texy index 7488231779..70e1791cfa 100644 --- a/best-practices/pl/editors-and-tools.texy +++ b/best-practices/pl/editors-and-tools.texy @@ -59,7 +59,7 @@ Wyczerpującą dokumentację znajdziesz bezpośrednio na [stronie PHPStan |https Code Checker ============ -[Code Checker|code-checker:] sprawdza i ewentualnie poprawia niektóre błędy formalne w twoich kodach źródłowych: +[Code Checker|tools:code-checker] sprawdza i ewentualnie poprawia niektóre błędy formalne w twoich kodach źródłowych: - usuwa [BOM |nette:glossary#BOM] - sprawdza poprawność szablonów [Latte |latte:] diff --git a/best-practices/pt/editors-and-tools.texy b/best-practices/pt/editors-and-tools.texy index 6d841136f7..6b10da25b7 100644 --- a/best-practices/pt/editors-and-tools.texy +++ b/best-practices/pt/editors-and-tools.texy @@ -59,7 +59,7 @@ Você encontrará documentação completa diretamente no [site do PHPStan |https Code Checker ============ -O [Code Checker|code-checker:] verifica e, opcionalmente, corrige alguns erros formais em seus códigos-fonte: +O [Code Checker|tools:code-checker] verifica e, opcionalmente, corrige alguns erros formais em seus códigos-fonte: - remove [BOM |nette:glossary#BOM] - verifica a validade dos templates [Latte |latte:] diff --git a/best-practices/ro/editors-and-tools.texy b/best-practices/ro/editors-and-tools.texy index 7c44d258a6..4923cc5bd7 100644 --- a/best-practices/ro/editors-and-tools.texy +++ b/best-practices/ro/editors-and-tools.texy @@ -59,7 +59,7 @@ Documentația exhaustivă o găsiți direct pe [site-ul PHPStan |https://phpstan Code Checker ============ -[Code Checker |code-checker:] verifică și, eventual, corectează unele dintre erorile formale din codurile sursă: +[Code Checker |tools:code-checker] verifică și, eventual, corectează unele dintre erorile formale din codurile sursă: - elimină [BOM |nette:glossary#BOM] - verifică validitatea șabloanelor [Latte |latte:] diff --git a/best-practices/ru/editors-and-tools.texy b/best-practices/ru/editors-and-tools.texy index 7508f40017..bc6a4282a4 100644 --- a/best-practices/ru/editors-and-tools.texy +++ b/best-practices/ru/editors-and-tools.texy @@ -59,7 +59,7 @@ vendor/bin/phpstan analyse app Code Checker ============ -[Code Checker|code-checker:] проверяет и, при необходимости, исправляет некоторые формальные ошибки в ваших исходных кодах: +[Code Checker|tools:code-checker] проверяет и, при необходимости, исправляет некоторые формальные ошибки в ваших исходных кодах: - удаляет [BOM |nette:glossary#BOM] - проверяет валидность шаблонов [Latte |latte:] diff --git a/best-practices/sl/editors-and-tools.texy b/best-practices/sl/editors-and-tools.texy index 9ac5d2ff3c..ec48ae25ea 100644 --- a/best-practices/sl/editors-and-tools.texy +++ b/best-practices/sl/editors-and-tools.texy @@ -59,7 +59,7 @@ Izčrpno dokumentacijo najdete neposredno na [straneh PHPStan |https://phpstan.o Code Checker ============ -[Code Checker|code-checker:] preveri in po potrebi popravi nekatere formalne napake v vaši izvorni kodi: +[Code Checker|tools:code-checker] preveri in po potrebi popravi nekatere formalne napake v vaši izvorni kodi: - odstranjuje [BOM |nette:glossary#BOM] - preverja veljavnost predlog [Latte |latte:] diff --git a/best-practices/tr/editors-and-tools.texy b/best-practices/tr/editors-and-tools.texy index e1822a4311..9a0c49ad71 100644 --- a/best-practices/tr/editors-and-tools.texy +++ b/best-practices/tr/editors-and-tools.texy @@ -59,7 +59,7 @@ Kapsamlı belgeleri doğrudan [PHPStan web sitesinde |https://phpstan.org] bulab Code Checker ============ -[Code Checker|code-checker:] kaynak kodlarınızdaki bazı biçimsel hataları kontrol eder ve gerekirse düzeltir: +[Code Checker|tools:code-checker] kaynak kodlarınızdaki bazı biçimsel hataları kontrol eder ve gerekirse düzeltir: - [BOM |nette:glossary#BOM] kaldırır - [Latte |latte:] şablonlarının geçerliliğini kontrol eder diff --git a/best-practices/uk/editors-and-tools.texy b/best-practices/uk/editors-and-tools.texy index 86380ff279..ff87bafe2c 100644 --- a/best-practices/uk/editors-and-tools.texy +++ b/best-practices/uk/editors-and-tools.texy @@ -59,7 +59,7 @@ vendor/bin/phpstan analyse app Code Checker ============ -[Code Checker|code-checker:] перевіряє та, за потреби, виправляє деякі формальні помилки у ваших вихідних кодах: +[Code Checker|tools:code-checker] перевіряє та, за потреби, виправляє деякі формальні помилки у ваших вихідних кодах: - видаляє [BOM |nette:glossary#BOM] - перевіряє валідність шаблонів [Latte |latte:] diff --git a/contributing/bg/documentation.texy b/contributing/bg/documentation.texy index 4f03aca70a..0bf4828e7d 100644 --- a/contributing/bg/documentation.texy +++ b/contributing/bg/documentation.texy @@ -52,7 +52,7 @@ 1) В GitHub си създайте [fork |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] на хранилището [nette/docs |https://github.com/nette/docs] 2) [Клонирайте |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] това хранилище на своя компютър 3) След това в [съответния branch |#Структура на документацията] направете промените -4) Проверете за излишни интервали в текста с помощта на инструмента [Code-Checker |code-checker:] +4) Проверете за излишни интервали в текста с помощта на инструмента [Code-Checker |tools:code-checker] 4) Запазете промените (commit) 6) Ако сте доволни от промените, изпратете ги (push) в GitHub към вашия fork 7) Оттам ги изпратете към хранилището `nette/docs`, като създадете [pull request|https://help.github.com/articles/creating-a-pull-request] (PR) diff --git a/contributing/cs/documentation.texy b/contributing/cs/documentation.texy index c02587a359..130bbc6d31 100644 --- a/contributing/cs/documentation.texy +++ b/contributing/cs/documentation.texy @@ -52,7 +52,7 @@ Dokumentaci upravujte tímto způsobem: 1) na GitHubu si vytvořte [fork |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] repositáře [nette/docs |https://github.com/nette/docs] 2) tento repositář [naklonujete |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] na svůj počítač 3) poté v [příslušné větvi |#Struktura dokumentace] proveďte změny -4) zkontroluje přebytečné mezery v textu pomocí nástroje [Code-Checker |code-checker:] +4) zkontroluje přebytečné mezery v textu pomocí nástroje [Code-Checker |tools:code-checker] 4) změny uložte (commitněte) 6) pokud jste se změnami spokojeni, odešlete (pushněte) je na GitHub do vašeho forku 7) odtud je odešlete do repositáře `nette/docs` vytvořením [pull request|https://help.github.com/articles/creating-a-pull-request] (PR) diff --git a/contributing/de/documentation.texy b/contributing/de/documentation.texy index 1461cd05c5..58a2bc6fd7 100644 --- a/contributing/de/documentation.texy +++ b/contributing/de/documentation.texy @@ -52,7 +52,7 @@ Bearbeiten Sie die Dokumentation auf diese Weise: 1) Erstellen Sie auf GitHub einen [Fork |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] des Repositorys [nette/docs |https://github.com/nette/docs]. 2) [Klonen |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] Sie dieses Repository auf Ihren Computer. 3) Nehmen Sie dann im [entsprechenden Branch |#Struktur der Dokumentation] die Änderungen vor. -4) Überprüfen Sie überflüssige Leerzeichen im Text mit dem Werkzeug [Code-Checker |code-checker:]. +4) Überprüfen Sie überflüssige Leerzeichen im Text mit dem Werkzeug [Code-Checker |tools:code-checker]. 5) Speichern (committen) Sie die Änderungen. 6) Wenn Sie mit den Änderungen zufrieden sind, senden (pushen) Sie sie auf GitHub in Ihren Fork. 7) Senden Sie sie von dort an das Repository `nette/docs`, indem Sie einen [Pull Request|https://help.github.com/articles/creating-a-pull-request] (PR) erstellen. diff --git a/contributing/el/documentation.texy b/contributing/el/documentation.texy index 28e360e165..40c2eeaab6 100644 --- a/contributing/el/documentation.texy +++ b/contributing/el/documentation.texy @@ -52,7 +52,7 @@ 1) Στο GitHub, δημιουργήστε ένα [fork |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] του αποθετηρίου [nette/docs |https://github.com/nette/docs]. 2) [Κλωνοποιήστε |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] αυτό το αποθετήριο στον υπολογιστή σας. 3) Στη συνέχεια, στον [κατάλληλο κλάδο |#Δομή της Τεκμηρίωσης] πραγματοποιήστε τις αλλαγές. -4) Ελέγξτε για περιττά κενά στο κείμενο χρησιμοποιώντας το εργαλείο [Code-Checker |code-checker:]. +4) Ελέγξτε για περιττά κενά στο κείμενο χρησιμοποιώντας το εργαλείο [Code-Checker |tools:code-checker]. 5) Αποθηκεύστε τις αλλαγές (commit). 6) Αν είστε ικανοποιημένοι με τις αλλαγές, στείλτε (push) τις στο GitHub στο δικό σας fork. 7) Από εκεί, υποβάλετέ τις στο αποθετήριο `nette/docs` δημιουργώντας ένα [pull request |https://help.github.com/articles/creating-a-pull-request] (PR). diff --git a/contributing/en/documentation.texy b/contributing/en/documentation.texy index 3d2353444b..2406cf78b5 100644 --- a/contributing/en/documentation.texy +++ b/contributing/en/documentation.texy @@ -52,7 +52,7 @@ Edit the documentation as follows: 1) On GitHub, create a [fork |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] of the [nette/docs |https://github.com/nette/docs] repository. 2) [Clone |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] this repository to your computer. 3) Then, make changes in the [appropriate branch |#Documentation Structure]. -4) Check for extra spaces in the text using the [Code-Checker |code-checker:] tool. +4) Check for extra spaces in the text using the [Code-Checker |tools:code-checker] tool. 5) Save (commit) the changes. 6) If you are satisfied with the changes, push them to GitHub to your fork. 7) From there, submit them to the `nette/docs` repository by creating a [pull request|https://help.github.com/articles/creating-a-pull-request] (PR). diff --git a/contributing/es/documentation.texy b/contributing/es/documentation.texy index f3e0e63004..ae4f4a4d34 100644 --- a/contributing/es/documentation.texy +++ b/contributing/es/documentation.texy @@ -52,7 +52,7 @@ Modifica la documentación de esta manera: 1) en GitHub, crea un [fork |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] del repositorio [nette/docs |https://github.com/nette/docs] 2) [clona |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] este repositorio en tu ordenador 3) luego, en la [rama apropiada |#Estructura de la documentación], realiza los cambios -4) comprueba si hay espacios sobrantes en el texto usando la herramienta [Code-Checker |code-checker:] +4) comprueba si hay espacios sobrantes en el texto usando la herramienta [Code-Checker |tools:code-checker] 5) guarda los cambios (haz commit) 6) si estás satisfecho con los cambios, envíalos (haz push) a GitHub a tu fork 7) desde allí, envíalos al repositorio `nette/docs` creando una [pull request|https://help.github.com/articles/creating-a-pull-request] (PR) diff --git a/contributing/fr/documentation.texy b/contributing/fr/documentation.texy index 87d2fa6640..0ce553fc8a 100644 --- a/contributing/fr/documentation.texy +++ b/contributing/fr/documentation.texy @@ -52,7 +52,7 @@ Modifiez la documentation de cette manière : 1) Sur GitHub, créez un [fork |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] du dépôt [nette/docs |https://github.com/nette/docs]. 2) [Clonez |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] ce dépôt sur votre ordinateur. 3) Ensuite, dans la [branche appropriée |#Structure de la documentation], effectuez les modifications. -4) Vérifiez les espaces superflus dans le texte à l'aide de l'outil [Code-Checker |code-checker:]. +4) Vérifiez les espaces superflus dans le texte à l'aide de l'outil [Code-Checker |tools:code-checker]. 5) Enregistrez (commitez) les changements. 6) Si vous êtes satisfait des changements, envoyez-les (pushez) sur GitHub vers votre fork. 7) De là, envoyez-les au dépôt `nette/docs` en créant une [pull request|https://help.github.com/articles/creating-a-pull-request] (PR). diff --git a/contributing/hu/documentation.texy b/contributing/hu/documentation.texy index 7ca946186c..82e5bb4a63 100644 --- a/contributing/hu/documentation.texy +++ b/contributing/hu/documentation.texy @@ -52,7 +52,7 @@ A dokumentációt a következő módon szerkessze: 1) a GitHubon hozzon létre egy [forkot |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] a [nette/docs |https://github.com/nette/docs] repository-ból 2) ezt a repository-t [klónozza |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] a számítógépére 3) ezután a [megfelelő ágban |#Dokumentáció struktúrája] végezze el a változtatásokat -4) ellenőrizze a felesleges szóközöket a szövegben a [Code-Checker |code-checker:] eszközzel +4) ellenőrizze a felesleges szóközöket a szövegben a [Code-Checker |tools:code-checker] eszközzel 5) mentse el a változtatásokat (commitolja) 6) ha elégedett a változtatásokkal, küldje el (pusholja) őket a GitHubra a saját forkjába 7) onnan küldje el őket a `nette/docs` repository-ba egy [pull request |https://help.github.com/articles/creating-a-pull-request] (PR) létrehozásával diff --git a/contributing/it/documentation.texy b/contributing/it/documentation.texy index 93d0597b18..cdbebb2317 100644 --- a/contributing/it/documentation.texy +++ b/contributing/it/documentation.texy @@ -52,7 +52,7 @@ Modificate la documentazione in questo modo: 1) su GitHub, create un [fork |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] del repository [nette/docs |https://github.com/nette/docs] 2) [clonate |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] questo repository sul vostro computer 3) successivamente, nel [ramo appropriato |#Struttura della documentazione], apportate le modifiche -4) controllate gli spazi superflui nel testo tramite lo strumento [Code-Checker |code-checker:] +4) controllate gli spazi superflui nel testo tramite lo strumento [Code-Checker |tools:code-checker] 4) salvate (committate) le modifiche 6) se siete soddisfatti delle modifiche, inviatele (push) su GitHub al vostro fork 7) da lì, inviatele al repository `nette/docs` creando una [pull request|https://help.github.com/articles/creating-a-pull-request] (PR) diff --git a/contributing/ja/documentation.texy b/contributing/ja/documentation.texy index 052c6485fd..cf0fae0bcd 100644 --- a/contributing/ja/documentation.texy +++ b/contributing/ja/documentation.texy @@ -52,7 +52,7 @@ GitHubインターフェースを利用するよりも、Gitバージョン管 1) GitHubで、[nette/docs |https://github.com/nette/docs] リポジトリの [フォーク |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] を作成します 2) このリポジトリを自分のコンピュータに [クローン |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] します 3) 次に、[関連するブランチ |#ドキュメントの構造] で変更を行います -4) [Code-Checker |code-checker:] ツールを使用して、テキスト内の余分なスペースをチェックします +4) [Code-Checker |tools:code-checker] ツールを使用して、テキスト内の余分なスペースをチェックします 4) 変更を保存(コミット)します 6) 変更に満足したら、GitHubの自分のフォークに送信(プッシュ)します 7) そこから、[プルリクエスト |https://help.github.com/articles/creating-a-pull-request] (PR) を作成して `nette/docs` リポジトリに送信します diff --git a/contributing/pl/documentation.texy b/contributing/pl/documentation.texy index d34ecbffc2..dc9560d3bd 100644 --- a/contributing/pl/documentation.texy +++ b/contributing/pl/documentation.texy @@ -52,7 +52,7 @@ Dokumentację modyfikuj w ten sposób: 1) na GitHubie utwórz [fork |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] repozytorium [nette/docs |https://github.com/nette/docs] 2) to repozytorium [sklonujesz |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] na swój komputer 3) następnie w [odpowiedniej gałęzi |#Struktura dokumentacji] wprowadź zmiany -4) sprawdź zbędne spacje w tekście za pomocą narzędzia [Code-Checker |code-checker:] +4) sprawdź zbędne spacje w tekście za pomocą narzędzia [Code-Checker |tools:code-checker] 4) zmiany zapisz (commituj) 6) jeśli jesteś zadowolony ze zmian, wyślij (pushnij) je na GitHub do swojego forka 7) stamtąd wyślij je do repozytorium `nette/docs`, tworząc [pull request|https://help.github.com/articles/creating-a-pull-request] (PR) diff --git a/contributing/pt/documentation.texy b/contributing/pt/documentation.texy index 4cf9f50cbb..55fa484724 100644 --- a/contributing/pt/documentation.texy +++ b/contributing/pt/documentation.texy @@ -52,7 +52,7 @@ Edite a documentação desta forma: 1) No GitHub, crie um [fork |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] do repositório [nette/docs |https://github.com/nette/docs]. 2) [Clone |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] este repositório para o seu computador. 3) Em seguida, no [branch apropriado |#Estrutura da Documentação], faça as alterações. -4) Verifique se há espaços em branco extras no texto usando a ferramenta [Code-Checker |code-checker:]. +4) Verifique se há espaços em branco extras no texto usando a ferramenta [Code-Checker |tools:code-checker]. 5) Salve (commit) as alterações. 6) Se estiver satisfeito com as alterações, envie-as (push) para o GitHub no seu fork. 7) A partir daí, envie-as para o repositório `nette/docs` criando um [pull request|https://help.github.com/articles/creating-a-pull-request] (PR). diff --git a/contributing/ro/documentation.texy b/contributing/ro/documentation.texy index c51ce18e62..59f813f62f 100644 --- a/contributing/ro/documentation.texy +++ b/contributing/ro/documentation.texy @@ -52,7 +52,7 @@ Modificați documentația în acest mod: 1) pe GitHub creați un [fork |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] al depozitului [nette/docs |https://github.com/nette/docs] 2) [clonați |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] acest depozit pe computerul dvs. 3) apoi în [ramura corespunzătoare |#Structura documentației] efectuați modificările -4) verificați spațiile în exces din text folosind instrumentul [Code-Checker |code-checker:] +4) verificați spațiile în exces din text folosind instrumentul [Code-Checker |tools:code-checker] 4) salvați modificările (commit) 6) dacă sunteți mulțumit de modificări, trimiteți-le (push) pe GitHub în fork-ul dvs. 7) de acolo le trimiteți către depozitul `nette/docs` creând un [pull request |https://help.github.com/articles/creating-a-pull-request] (PR) diff --git a/contributing/ru/documentation.texy b/contributing/ru/documentation.texy index dab56db27d..3fd2af6677 100644 --- a/contributing/ru/documentation.texy +++ b/contributing/ru/documentation.texy @@ -52,7 +52,7 @@ 1) на GitHub создайте [форк |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] репозитория [nette/docs |https://github.com/nette/docs] 2) этот репозиторий [клонируйте |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] на свой компьютер 3) затем в [соответствующей ветке |#Структура документации] внесите изменения -4) проверьте лишние пробелы в тексте с помощью инструмента [Code-Checker |code-checker:] +4) проверьте лишние пробелы в тексте с помощью инструмента [Code-Checker |tools:code-checker] 4) сохраните изменения (сделайте коммит) 6) если вы удовлетворены изменениями, отправьте (push) их на GitHub в ваш форк 7) оттуда отправьте их в репозиторий `nette/docs`, создав [pull request|https://help.github.com/articles/creating-a-pull-request] (PR) diff --git a/contributing/sl/documentation.texy b/contributing/sl/documentation.texy index 8ae7191d0c..e452d2c834 100644 --- a/contributing/sl/documentation.texy +++ b/contributing/sl/documentation.texy @@ -52,7 +52,7 @@ Dokumentacijo urejajte na ta način: 1) na GitHubu si ustvarite [fork |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] repozitorija [nette/docs |https://github.com/nette/docs] 2) ta repozitorij [klonirajte |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] na svoj računalnik 3) nato v [ustrezni veji |#Struktura dokumentacije] izvedite spremembe -4) preverite odvečne presledke v besedilu z orodjem [Code-Checker |code-checker:] +4) preverite odvečne presledke v besedilu z orodjem [Code-Checker |tools:code-checker] 4) spremembe shranite (commitnite) 6) če ste s spremembami zadovoljni, jih pošljite (pushnite) na GitHub v vaš fork 7) od tam jih pošljite v repozitorij `nette/docs` z ustvarjanjem [pull requesta|https://help.github.com/articles/creating-a-pull-request] (PR) diff --git a/contributing/tr/documentation.texy b/contributing/tr/documentation.texy index b9efcf74e4..44d6aae888 100644 --- a/contributing/tr/documentation.texy +++ b/contributing/tr/documentation.texy @@ -52,7 +52,7 @@ Dokümantasyonu şu şekilde düzenleyin: 1) GitHub'da [nette/docs |https://github.com/nette/docs] deposunun bir [forkunu |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] oluşturun 2) Bu depoyu bilgisayarınıza [klonlayın |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] 3) Ardından [ilgili dalda |#Dokümantasyon yapısı] değişiklikleri yapın -4) [Code-Checker |code-checker:] aracını kullanarak metindeki fazla boşlukları kontrol edin +4) [Code-Checker |tools:code-checker] aracını kullanarak metindeki fazla boşlukları kontrol edin 5) Değişiklikleri kaydedin (commit) 6) Değişikliklerden memnunsanız, bunları GitHub'daki fork'unuza gönderin (push) 7) Oradan, bir [pull request|https://help.github.com/articles/creating-a-pull-request] (PR) oluşturarak `nette/docs` deposuna gönderin diff --git a/contributing/uk/documentation.texy b/contributing/uk/documentation.texy index 95b53fa278..988d02cbc1 100644 --- a/contributing/uk/documentation.texy +++ b/contributing/uk/documentation.texy @@ -52,7 +52,7 @@ 1) на GitHub створіть [fork |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] репозиторію [nette/docs |https://github.com/nette/docs] 2) цей репозиторій [клонуєте |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] на свій комп'ютер 3) потім у [відповідній гілці |#Структура документації] внесіть зміни -4) перевірте зайві пробіли в тексті за допомогою інструменту [Code-Checker |code-checker:] +4) перевірте зайві пробіли в тексті за допомогою інструменту [Code-Checker |tools:code-checker] 4) збережіть зміни (зробіть коміт) 6) якщо ви задоволені змінами, надішліть (push) їх на GitHub у ваш форк 7) звідти надішліть їх до репозиторію `nette/docs`, створивши [pull request|https://help.github.com/articles/creating-a-pull-request] (PR) diff --git a/nette/bg/glossary.texy b/nette/bg/glossary.texy index d3893a0cfa..5b24f85ce4 100644 --- a/nette/bg/glossary.texy +++ b/nette/bg/glossary.texy @@ -14,7 +14,7 @@ Asynchronous JavaScript and XML - технология за обмен на ин BOM --- -Така нареченият *byte order mark* е специален първи знак във файла, който се използва като индикатор за реда на байтовете в кодирането. Някои редактори го вмъкват във файловете. Той е практически невидим, но причинява проблеми с изпращането на изход и хедъри от PHP. За масово премахване можете да използвате [Code Checker|code-checker:]. +Така нареченият *byte order mark* е специален първи знак във файла, който се използва като индикатор за реда на байтовете в кодирането. Някои редактори го вмъкват във файловете. Той е практически невидим, но причинява проблеми с изпращането на изход и хедъри от PHP. За масово премахване можете да използвате [Code Checker|tools:code-checker]. Controller @@ -73,7 +73,7 @@ JSON Контролни знаци --------------- -Контролните знаци са невидими знаци, които могат да се срещат в текста и евентуално да причиняват проблеми. За масовото им премахване от файлове можете да използвате [Code Checker|code-checker:], а за премахване от променлива - функцията [Strings::normalize() |utils:strings#normalize]. +Контролните знаци са невидими знаци, които могат да се срещат в текста и евентуално да причиняват проблеми. За масовото им премахване от файлове можете да използвате [Code Checker|tools:code-checker], а за премахване от променлива - функцията [Strings::normalize() |utils:strings#normalize]. Събития (events) diff --git a/nette/cs/glossary.texy b/nette/cs/glossary.texy index 7b273ba481..b03a443a0c 100644 --- a/nette/cs/glossary.texy +++ b/nette/cs/glossary.texy @@ -14,7 +14,7 @@ Logická část presenteru, která vykonává jednu akci. Například zobrazí s BOM --- -Tzv. *byte order mark* je speciální první znak v souboru, který se používá jako indikátor pořadí bajtů v kódování. Některé editory ho do souborů vkládají. Je prakticky neviditelný, ale způsobuje problémy s odesíláním výstupu a hlaviček z PHP. K hromadnému odstranění můžete použít [Code Checker|code-checker:]. +Tzv. *byte order mark* je speciální první znak v souboru, který se používá jako indikátor pořadí bajtů v kódování. Některé editory ho do souborů vkládají. Je prakticky neviditelný, ale způsobuje problémy s odesíláním výstupu a hlaviček z PHP. K hromadnému odstranění můžete použít [Code Checker|tools:code-checker]. Controller @@ -80,7 +80,7 @@ Znovupoužitelná součást aplikace. Může to být vizuální část stránky, Kontrolní znaky --------------- -Kontrolní znaky jsou neviditelné znaky, které se mohou vyskytovat v textu a případně i způsobovat problémy. K jejich hromadnému odstranění ze souborů můžete použít [Code Checker|code-checker:] a k odstranění z proměnné funkci [Strings::normalize() |utils:strings#normalize]. +Kontrolní znaky jsou neviditelné znaky, které se mohou vyskytovat v textu a případně i způsobovat problémy. K jejich hromadnému odstranění ze souborů můžete použít [Code Checker|tools:code-checker] a k odstranění z proměnné funkci [Strings::normalize() |utils:strings#normalize]. Eventy (události) .{toc: události} diff --git a/nette/de/glossary.texy b/nette/de/glossary.texy index beb74632cd..9b03ed9dca 100644 --- a/nette/de/glossary.texy +++ b/nette/de/glossary.texy @@ -14,7 +14,7 @@ Logischer Teil des Presenters, der eine Aktion ausführt. Zum Beispiel zeigt er BOM --- -Die sogenannte *Byte Order Mark* ist ein spezielles erstes Zeichen in einer Datei, das als Indikator für die Byte-Reihenfolge in der Kodierung verwendet wird. Einige Editoren fügen es in Dateien ein. Es ist praktisch unsichtbar, verursacht aber Probleme beim Senden der Ausgabe und der Header von PHP. Zur Massenentfernung können Sie den [Code Checker|code-checker:] verwenden. +Die sogenannte *Byte Order Mark* ist ein spezielles erstes Zeichen in einer Datei, das als Indikator für die Byte-Reihenfolge in der Kodierung verwendet wird. Einige Editoren fügen es in Dateien ein. Es ist praktisch unsichtbar, verursacht aber Probleme beim Senden der Ausgabe und der Header von PHP. Zur Massenentfernung können Sie den [Code Checker|tools:code-checker] verwenden. Controller @@ -73,7 +73,7 @@ Wiederverwendbarer Teil der Anwendung. Es kann ein visueller Teil der Seite sein Steuerzeichen ------------- -Steuerzeichen sind unsichtbare Zeichen, die im Text vorkommen und möglicherweise auch Probleme verursachen können. Zur Massenentfernung aus Dateien können Sie den [Code Checker|code-checker:] verwenden und zur Entfernung aus einer Variablen die Funktion [Strings::normalize() |utils:strings#normalize]. +Steuerzeichen sind unsichtbare Zeichen, die im Text vorkommen und möglicherweise auch Probleme verursachen können. Zur Massenentfernung aus Dateien können Sie den [Code Checker|tools:code-checker] verwenden und zur Entfernung aus einer Variablen die Funktion [Strings::normalize() |utils:strings#normalize]. Events (Ereignisse) diff --git a/nette/el/glossary.texy b/nette/el/glossary.texy index 972316ee71..8e9397bcb0 100644 --- a/nette/el/glossary.texy +++ b/nette/el/glossary.texy @@ -14,7 +14,7 @@ Action (presenter) BOM --- -Το λεγόμενο *byte order mark* είναι ένας ειδικός πρώτος χαρακτήρας σε ένα αρχείο που χρησιμοποιείται ως δείκτης της σειράς των bytes στην κωδικοποίηση. Ορισμένοι επεξεργαστές τον εισάγουν στα αρχεία. Είναι πρακτικά αόρατος, αλλά προκαλεί προβλήματα με την αποστολή εξόδου και κεφαλίδων από την PHP. Για μαζική αφαίρεση μπορείτε να χρησιμοποιήσετε το [Code Checker|code-checker:]. +Το λεγόμενο *byte order mark* είναι ένας ειδικός πρώτος χαρακτήρας σε ένα αρχείο που χρησιμοποιείται ως δείκτης της σειράς των bytes στην κωδικοποίηση. Ορισμένοι επεξεργαστές τον εισάγουν στα αρχεία. Είναι πρακτικά αόρατος, αλλά προκαλεί προβλήματα με την αποστολή εξόδου και κεφαλίδων από την PHP. Για μαζική αφαίρεση μπορείτε να χρησιμοποιήσετε το [Code Checker|tools:code-checker]. Controller @@ -73,7 +73,7 @@ Component Control characters ------------------ -Οι χαρακτήρες ελέγχου είναι αόρατοι χαρακτήρες που μπορεί να εμφανίζονται στο κείμενο και ενδεχομένως να προκαλούν προβλήματα. Για τη μαζική αφαίρεσή τους από αρχεία μπορείτε να χρησιμοποιήσετε το [Code Checker|code-checker:] και για την αφαίρεσή τους από μια μεταβλητή τη συνάρτηση [Strings::normalize() |utils:strings#normalize]. +Οι χαρακτήρες ελέγχου είναι αόρατοι χαρακτήρες που μπορεί να εμφανίζονται στο κείμενο και ενδεχομένως να προκαλούν προβλήματα. Για τη μαζική αφαίρεσή τους από αρχεία μπορείτε να χρησιμοποιήσετε το [Code Checker|tools:code-checker] και για την αφαίρεσή τους από μια μεταβλητή τη συνάρτηση [Strings::normalize() |utils:strings#normalize]. Events diff --git a/nette/en/glossary.texy b/nette/en/glossary.texy index bc555933a0..b44747dc3d 100644 --- a/nette/en/glossary.texy +++ b/nette/en/glossary.texy @@ -14,7 +14,7 @@ A logical part of a presenter that performs a single action. For example, displa BOM --- -The *byte order mark* is a special first character in a file used as an indicator of byte order in encoding. Some editors insert it into files. It is practically invisible but causes problems with sending output and headers from PHP. You can use [Code Checker|code-checker:] for bulk removal. +The *byte order mark* is a special first character in a file used as an indicator of byte order in encoding. Some editors insert it into files. It is practically invisible but causes problems with sending output and headers from PHP. You can use [Code Checker|tools:code-checker] for bulk removal. Controller @@ -80,7 +80,7 @@ A reusable part of an application. It can be a visual part of a page, as describ Control Characters ------------------ -Control characters are invisible characters that can appear in text and potentially cause problems. To remove them in bulk from files, you can use [Code Checker|code-checker:], and to remove them from a variable, use the [Strings::normalize() |utils:strings#normalize] function. +Control characters are invisible characters that can appear in text and potentially cause problems. To remove them in bulk from files, you can use [Code Checker|tools:code-checker], and to remove them from a variable, use the [Strings::normalize() |utils:strings#normalize] function. Events diff --git a/nette/es/glossary.texy b/nette/es/glossary.texy index 57eb51961d..3f66ed5c3c 100644 --- a/nette/es/glossary.texy +++ b/nette/es/glossary.texy @@ -14,7 +14,7 @@ Parte lógica del presenter que realiza una acción. Por ejemplo, muestra la pá BOM --- -El llamado *byte order mark* es un carácter especial al principio de un archivo que se utiliza como indicador del orden de los bytes en la codificación. Algunos editores lo insertan en los archivos. Es prácticamente invisible, pero causa problemas con el envío de la salida y las cabeceras desde PHP. Para eliminarlo masivamente, puede usar [Code Checker|code-checker:]. +El llamado *byte order mark* es un carácter especial al principio de un archivo que se utiliza como indicador del orden de los bytes en la codificación. Algunos editores lo insertan en los archivos. Es prácticamente invisible, pero causa problemas con el envío de la salida y las cabeceras desde PHP. Para eliminarlo masivamente, puede usar [Code Checker|tools:code-checker]. Controlador @@ -73,7 +73,7 @@ Parte reutilizable de una aplicación. Puede ser una parte visual de la página, Caracteres de control --------------------- -Los caracteres de control son caracteres invisibles que pueden aparecer en el texto y, eventualmente, causar problemas. Para eliminarlos masivamente de los archivos, puede usar [Code Checker|code-checker:] y para eliminarlos de una variable, la función [Strings::normalize() |utils:strings#normalize]. +Los caracteres de control son caracteres invisibles que pueden aparecer en el texto y, eventualmente, causar problemas. Para eliminarlos masivamente de los archivos, puede usar [Code Checker|tools:code-checker] y para eliminarlos de una variable, la función [Strings::normalize() |utils:strings#normalize]. Eventos diff --git a/nette/fr/glossary.texy b/nette/fr/glossary.texy index a049378c3f..c5537252d6 100644 --- a/nette/fr/glossary.texy +++ b/nette/fr/glossary.texy @@ -14,7 +14,7 @@ Partie logique du presenter qui exécute une action. Par exemple, afficher la pa BOM --- -Le *byte order mark* est un caractère spécial au début d'un fichier, utilisé comme indicateur de l'ordre des octets dans l'encodage. Certains éditeurs l'insèrent dans les fichiers. Il est pratiquement invisible, mais cause des problèmes avec l'envoi de la sortie et des en-têtes depuis PHP. Pour une suppression en masse, vous pouvez utiliser [Code Checker|code-checker:]. +Le *byte order mark* est un caractère spécial au début d'un fichier, utilisé comme indicateur de l'ordre des octets dans l'encodage. Certains éditeurs l'insèrent dans les fichiers. Il est pratiquement invisible, mais cause des problèmes avec l'envoi de la sortie et des en-têtes depuis PHP. Pour une suppression en masse, vous pouvez utiliser [Code Checker|tools:code-checker]. Controller @@ -73,7 +73,7 @@ Partie réutilisable de l'application. Il peut s'agir d'une partie visuelle de l Caractères de contrôle ---------------------- -Les caractères de contrôle sont des caractères invisibles qui peuvent apparaître dans le texte et éventuellement causer des problèmes. Pour leur suppression en masse des fichiers, vous pouvez utiliser [Code Checker|code-checker:] et pour la suppression d'une variable, la fonction [Strings::normalize() |utils:strings#normalize]. +Les caractères de contrôle sont des caractères invisibles qui peuvent apparaître dans le texte et éventuellement causer des problèmes. Pour leur suppression en masse des fichiers, vous pouvez utiliser [Code Checker|tools:code-checker] et pour la suppression d'une variable, la fonction [Strings::normalize() |utils:strings#normalize]. Événements (events) diff --git a/nette/hu/glossary.texy b/nette/hu/glossary.texy index c45c6f5d2f..420fdd9261 100644 --- a/nette/hu/glossary.texy +++ b/nette/hu/glossary.texy @@ -14,7 +14,7 @@ A presenter logikai része, amely egy akciót hajt végre. Például megjelenít BOM --- -Az ún. *byte order mark* egy speciális első karakter a fájlban, amelyet a bájtsorrend jelzőjeként használnak a kódolásban. Néhány szerkesztő beilleszti a fájlokba. Gyakorlatilag láthatatlan, de problémákat okoz a kimenet és a fejlécek küldésével PHP-ból. Tömeges eltávolításához használhatja a [Code Checker|code-checker:] eszközt. +Az ún. *byte order mark* egy speciális első karakter a fájlban, amelyet a bájtsorrend jelzőjeként használnak a kódolásban. Néhány szerkesztő beilleszti a fájlokba. Gyakorlatilag láthatatlan, de problémákat okoz a kimenet és a fejlécek küldésével PHP-ból. Tömeges eltávolításához használhatja a [Code Checker|tools:code-checker] eszközt. Controller @@ -73,7 +73,7 @@ Az alkalmazás újrafelhasználható része. Lehet egy oldal vizuális része, a Vezérlő karakterek ------------------ -A vezérlő karakterek láthatatlan karakterek, amelyek előfordulhatnak a szövegben, és esetleg problémákat okozhatnak. Tömeges eltávolításukhoz a fájlokból használhatja a [Code Checker|code-checker:] eszközt, és egy változóból való eltávolításukhoz a [Strings::normalize() |utils:strings#normalize] függvényt. +A vezérlő karakterek láthatatlan karakterek, amelyek előfordulhatnak a szövegben, és esetleg problémákat okozhatnak. Tömeges eltávolításukhoz a fájlokból használhatja a [Code Checker|tools:code-checker] eszközt, és egy változóból való eltávolításukhoz a [Strings::normalize() |utils:strings#normalize] függvényt. Eventek (események) diff --git a/nette/it/glossary.texy b/nette/it/glossary.texy index 86e459362e..18d4cb3615 100644 --- a/nette/it/glossary.texy +++ b/nette/it/glossary.texy @@ -14,7 +14,7 @@ Parte logica del presenter che esegue una singola azione. Ad esempio, visualizza BOM --- -Il cosiddetto *byte order mark* è un carattere speciale iniziale in un file, utilizzato come indicatore dell'ordine dei byte nella codifica. Alcuni editor lo inseriscono nei file. È praticamente invisibile, ma causa problemi con l'invio dell'output e degli header da PHP. Per la rimozione di massa è possibile utilizzare [Code Checker |code-checker:]. +Il cosiddetto *byte order mark* è un carattere speciale iniziale in un file, utilizzato come indicatore dell'ordine dei byte nella codifica. Alcuni editor lo inseriscono nei file. È praticamente invisibile, ma causa problemi con l'invio dell'output e degli header da PHP. Per la rimozione di massa è possibile utilizzare [Code Checker |tools:code-checker]. Controller @@ -73,7 +73,7 @@ Parte riutilizzabile dell'applicazione. Può essere una parte visiva della pagin Caratteri di controllo ---------------------- -I caratteri di controllo sono caratteri invisibili che possono comparire nel testo ed eventualmente causare problemi. Per la loro rimozione di massa dai file è possibile utilizzare [Code Checker |code-checker:] e per la rimozione da una variabile la funzione [Strings::normalize() |utils:strings#normalize]. +I caratteri di controllo sono caratteri invisibili che possono comparire nel testo ed eventualmente causare problemi. Per la loro rimozione di massa dai file è possibile utilizzare [Code Checker |tools:code-checker] e per la rimozione da una variabile la funzione [Strings::normalize() |utils:strings#normalize]. Eventi diff --git a/nette/ja/glossary.texy b/nette/ja/glossary.texy index 17eb925948..5c4648a11d 100644 --- a/nette/ja/glossary.texy +++ b/nette/ja/glossary.texy @@ -14,7 +14,7 @@ Presenterの論理的な部分で、1つのアクションを実行します。 BOM --- -いわゆる*byte order mark*は、ファイルの先頭にある特別な文字で、エンコーディングにおけるバイトオーダーのインジケータとして使用されます。一部のエディタはこの文字をファイルに挿入します。実際には見えませんが、PHPからの出力やヘッダーの送信に問題を引き起こします。一括で削除するには、[Code Checker|code-checker:]を使用できます。 +いわゆる*byte order mark*は、ファイルの先頭にある特別な文字で、エンコーディングにおけるバイトオーダーのインジケータとして使用されます。一部のエディタはこの文字をファイルに挿入します。実際には見えませんが、PHPからの出力やヘッダーの送信に問題を引き起こします。一括で削除するには、[Code Checker|tools:code-checker]を使用できます。 Controller @@ -73,7 +73,7 @@ JavaScriptの構文(そのサブセット)に基づいたデータ交換フ 制御文字 ---- -制御文字は、テキスト中に存在する可能性があり、問題を引き起こす可能性もある目に見えない文字です。ファイルから一括で削除するには[Code Checker|code-checker:]を使用でき、変数から削除するには[Strings::normalize() |utils:strings#normalize]関数を使用できます。 +制御文字は、テキスト中に存在する可能性があり、問題を引き起こす可能性もある目に見えない文字です。ファイルから一括で削除するには[Code Checker|tools:code-checker]を使用でき、変数から削除するには[Strings::normalize() |utils:strings#normalize]関数を使用できます。 イベント diff --git a/nette/pl/glossary.texy b/nette/pl/glossary.texy index 37730d36f0..b30d9b3ff4 100644 --- a/nette/pl/glossary.texy +++ b/nette/pl/glossary.texy @@ -14,7 +14,7 @@ Logiczna część presentera, która wykonuje jedną akcję. Na przykład wyświ BOM --- -Tzw. *byte order mark* to specjalny pierwszy znak w pliku, który jest używany jako wskaźnik kolejności bajtów w kodowaniu. Niektóre edytory wstawiają go do plików. Jest praktycznie niewidoczny, ale powoduje problemy z wysyłaniem danych wyjściowych i nagłówków z PHP. Do masowego usuwania można użyć [Code Checker|code-checker:]. +Tzw. *byte order mark* to specjalny pierwszy znak w pliku, który jest używany jako wskaźnik kolejności bajtów w kodowaniu. Niektóre edytory wstawiają go do plików. Jest praktycznie niewidoczny, ale powoduje problemy z wysyłaniem danych wyjściowych i nagłówków z PHP. Do masowego usuwania można użyć [Code Checker|tools:code-checker]. Controller @@ -73,7 +73,7 @@ Reużywalna część aplikacji. Może to być wizualna część strony, jak opis Znaki kontrolne --------------- -Znaki kontrolne to niewidoczne znaki, które mogą występować w tekście i ewentualnie powodować problemy. Do ich masowego usuwania z plików możesz użyć [Code Checker|code-checker:], a do usuwania ze zmiennej funkcji [Strings::normalize() |utils:strings#normalize]. +Znaki kontrolne to niewidoczne znaki, które mogą występować w tekście i ewentualnie powodować problemy. Do ich masowego usuwania z plików możesz użyć [Code Checker|tools:code-checker], a do usuwania ze zmiennej funkcji [Strings::normalize() |utils:strings#normalize]. Eventy (zdarzenia) diff --git a/nette/pt/glossary.texy b/nette/pt/glossary.texy index f682bd4039..441f806b6e 100644 --- a/nette/pt/glossary.texy +++ b/nette/pt/glossary.texy @@ -14,7 +14,7 @@ Parte lógica do presenter que executa uma ação. Por exemplo, exibe a página BOM --- -O chamado *byte order mark* é um caractere especial no início de um arquivo, usado como indicador da ordem dos bytes na codificação. Alguns editores o inserem nos arquivos. É praticamente invisível, mas causa problemas com o envio de saída e cabeçalhos do PHP. Para remoção em massa, você pode usar o [Code Checker|code-checker:]. +O chamado *byte order mark* é um caractere especial no início de um arquivo, usado como indicador da ordem dos bytes na codificação. Alguns editores o inserem nos arquivos. É praticamente invisível, mas causa problemas com o envio de saída e cabeçalhos do PHP. Para remoção em massa, você pode usar o [Code Checker|tools:code-checker]. Controller @@ -73,7 +73,7 @@ Parte reutilizável da aplicação. Pode ser uma parte visual da página, como d Caracteres de controle ---------------------- -Caracteres de controle são caracteres invisíveis que podem ocorrer no texto e, eventualmente, causar problemas. Para sua remoção em massa de arquivos, você pode usar o [Code Checker|code-checker:] e para remover de uma variável, a função [Strings::normalize() |utils:strings#normalize]. +Caracteres de controle são caracteres invisíveis que podem ocorrer no texto e, eventualmente, causar problemas. Para sua remoção em massa de arquivos, você pode usar o [Code Checker|tools:code-checker] e para remover de uma variável, a função [Strings::normalize() |utils:strings#normalize]. Eventos diff --git a/nette/ro/glossary.texy b/nette/ro/glossary.texy index a90364944b..23a7d26c2f 100644 --- a/nette/ro/glossary.texy +++ b/nette/ro/glossary.texy @@ -14,7 +14,7 @@ Partea logică a presenterului care execută o singură acțiune. De exemplu, af BOM --- -Așa-numitul *byte order mark* este un caracter special la începutul fișierului, care se utilizează ca indicator al ordinii octeților în codificare. Unele editoare îl inserează în fișiere. Este practic invizibil, dar cauzează probleme cu trimiterea ieșirii și a antetelor din PHP. Pentru eliminarea în masă puteți utiliza [Code Checker|code-checker:]. +Așa-numitul *byte order mark* este un caracter special la începutul fișierului, care se utilizează ca indicator al ordinii octeților în codificare. Unele editoare îl inserează în fișiere. Este practic invizibil, dar cauzează probleme cu trimiterea ieșirii și a antetelor din PHP. Pentru eliminarea în masă puteți utiliza [Code Checker|tools:code-checker]. Controller @@ -73,7 +73,7 @@ Parte reutilizabilă a aplicației. Poate fi o parte vizuală a paginii, așa cu Caractere de control -------------------- -Caracterele de control sunt caractere invizibile care pot apărea în text și eventual pot cauza probleme. Pentru eliminarea lor în masă din fișiere puteți utiliza [Code Checker|code-checker:] și pentru eliminarea dintr-o variabilă funcția [Strings::normalize() |utils:strings#normalize]. +Caracterele de control sunt caractere invizibile care pot apărea în text și eventual pot cauza probleme. Pentru eliminarea lor în masă din fișiere puteți utiliza [Code Checker|tools:code-checker] și pentru eliminarea dintr-o variabilă funcția [Strings::normalize() |utils:strings#normalize]. Evenimente diff --git a/nette/ru/glossary.texy b/nette/ru/glossary.texy index ed8ec3d6d6..39b152e9b8 100644 --- a/nette/ru/glossary.texy +++ b/nette/ru/glossary.texy @@ -14,7 +14,7 @@ Asynchronous JavaScript and XML — технология обмена инфор BOM --- -Так называемая *byte order mark* — это специальный первый символ в файле, который используется как индикатор порядка байтов в кодировке. Некоторые редакторы вставляют его в файлы. Он практически невидим, но вызывает проблемы с отправкой вывода и заголовков из PHP. Для массового удаления можно использовать [Code Checker|code-checker:]. +Так называемая *byte order mark* — это специальный первый символ в файле, который используется как индикатор порядка байтов в кодировке. Некоторые редакторы вставляют его в файлы. Он практически невидим, но вызывает проблемы с отправкой вывода и заголовков из PHP. Для массового удаления можно использовать [Code Checker|tools:code-checker]. Контроллер @@ -73,7 +73,7 @@ JSON Управляющие символы ------------------- -Управляющие символы — это невидимые символы, которые могут встречаться в тексте и иногда вызывать проблемы. Для их массового удаления из файлов можно использовать [Code Checker|code-checker:], а для удаления из переменной — функцию [Strings::normalize() |utils:strings#normalize]. +Управляющие символы — это невидимые символы, которые могут встречаться в тексте и иногда вызывать проблемы. Для их массового удаления из файлов можно использовать [Code Checker|tools:code-checker], а для удаления из переменной — функцию [Strings::normalize() |utils:strings#normalize]. События (Events) diff --git a/nette/sl/glossary.texy b/nette/sl/glossary.texy index 1f92bede75..9277528630 100644 --- a/nette/sl/glossary.texy +++ b/nette/sl/glossary.texy @@ -14,7 +14,7 @@ Logični del presenterja, ki izvaja eno akcijo. Na primer prikaže stran izdelka BOM --- -T.i. *byte order mark* (oznaka vrstnega reda bajtov) je poseben prvi znak v datoteki, ki se uporablja kot indikator vrstnega reda bajtov v kodiranju. Nekateri urejevalniki ga vstavljajo v datoteke. Je praktično neviden, vendar povzroča težave s pošiljanjem izpisa in glav iz PHP. Za množično odstranjevanje lahko uporabite [Code Checker|code-checker:]. +T.i. *byte order mark* (oznaka vrstnega reda bajtov) je poseben prvi znak v datoteki, ki se uporablja kot indikator vrstnega reda bajtov v kodiranju. Nekateri urejevalniki ga vstavljajo v datoteke. Je praktično neviden, vendar povzroča težave s pošiljanjem izpisa in glav iz PHP. Za množično odstranjevanje lahko uporabite [Code Checker|tools:code-checker]. Controller @@ -73,7 +73,7 @@ Ponovno uporabna komponenta aplikacije. Lahko je vizualni del strani, kot opisuj Kontrolni znaki --------------- -Kontrolni znaki so nevidni znaki, ki se lahko pojavljajo v besedilu in morebiti tudi povzročajo težave. Za njihovo množično odstranjevanje iz datotek lahko uporabite [Code Checker|code-checker:] in za odstranjevanje iz spremenljivke funkcijo [Strings::normalize() |utils:strings#normalize]. +Kontrolni znaki so nevidni znaki, ki se lahko pojavljajo v besedilu in morebiti tudi povzročajo težave. Za njihovo množično odstranjevanje iz datotek lahko uporabite [Code Checker|tools:code-checker] in za odstranjevanje iz spremenljivke funkcijo [Strings::normalize() |utils:strings#normalize]. Dogodki (eventi) diff --git a/nette/tr/glossary.texy b/nette/tr/glossary.texy index c699b3b2e0..325af3f04e 100644 --- a/nette/tr/glossary.texy +++ b/nette/tr/glossary.texy @@ -14,7 +14,7 @@ Presenter'ın tek bir eylemi gerçekleştiren mantıksal bölümü. Örneğin, b BOM --- -Sözde *byte order mark*, bir dosyadaki, kodlamada bayt sırasının göstergesi olarak kullanılan özel ilk karakterdir. Bazı düzenleyiciler bunu dosyalara ekler. Pratik olarak görünmezdir, ancak PHP'den çıktı ve başlıkların (header) gönderilmesinde sorunlara neden olur. Toplu olarak kaldırmak için [Code Checker |code-checker:] kullanabilirsiniz. +Sözde *byte order mark*, bir dosyadaki, kodlamada bayt sırasının göstergesi olarak kullanılan özel ilk karakterdir. Bazı düzenleyiciler bunu dosyalara ekler. Pratik olarak görünmezdir, ancak PHP'den çıktı ve başlıkların (header) gönderilmesinde sorunlara neden olur. Toplu olarak kaldırmak için [Code Checker |tools:code-checker] kullanabilirsiniz. Controller @@ -73,7 +73,7 @@ Uygulamanın yeniden kullanılabilir bir parçası. [Bileşen Yazma |application Kontrol Karakterleri -------------------- -Kontrol karakterleri, metinde bulunabilen ve muhtemelen sorunlara neden olabilen görünmez karakterlerdir. Bunları dosyalardan toplu olarak kaldırmak için [Code Checker |code-checker:] ve bir değişkenden kaldırmak için [Strings::normalize() |utils:strings#normalize] fonksiyonunu kullanabilirsiniz. +Kontrol karakterleri, metinde bulunabilen ve muhtemelen sorunlara neden olabilen görünmez karakterlerdir. Bunları dosyalardan toplu olarak kaldırmak için [Code Checker |tools:code-checker] ve bir değişkenden kaldırmak için [Strings::normalize() |utils:strings#normalize] fonksiyonunu kullanabilirsiniz. Olaylar (Events) diff --git a/nette/uk/glossary.texy b/nette/uk/glossary.texy index 7ac777d23f..351108d695 100644 --- a/nette/uk/glossary.texy +++ b/nette/uk/glossary.texy @@ -14,7 +14,7 @@ Asynchronous JavaScript and XML - технологія обміну інформ BOM --- -Так звана *byte order mark* - це спеціальний перший символ у файлі, який використовується як індикатор порядку байтів у кодуванні. Деякі редактори вставляють його у файли. Він практично невидимий, але спричиняє проблеми з надсиланням виводу та заголовків з PHP. Для масового видалення можна використовувати [Code Checker|code-checker:]. +Так звана *byte order mark* - це спеціальний перший символ у файлі, який використовується як індикатор порядку байтів у кодуванні. Деякі редактори вставляють його у файли. Він практично невидимий, але спричиняє проблеми з надсиланням виводу та заголовків з PHP. Для масового видалення можна використовувати [Code Checker|tools:code-checker]. Controller @@ -73,7 +73,7 @@ JSON Керуючі символи --------------- -Керуючі символи - це невидимі символи, які можуть зустрічатися в тексті та іноді спричиняти проблеми. Для їх масового видалення з файлів можна використовувати [Code Checker|code-checker:], а для видалення зі змінної - функцію [Strings::normalize() |utils:strings#normalize]. +Керуючі символи - це невидимі символи, які можуть зустрічатися в тексті та іноді спричиняти проблеми. Для їх масового видалення з файлів можна використовувати [Code Checker|tools:code-checker], а для видалення зі змінної - функцію [Strings::normalize() |utils:strings#normalize]. Події (události) diff --git a/code-checker/bg/@home.texy b/tools/bg/code-checker.texy similarity index 98% rename from code-checker/bg/@home.texy rename to tools/bg/code-checker.texy index ab284bfe7e..f0070378d7 100644 --- a/code-checker/bg/@home.texy +++ b/tools/bg/code-checker.texy @@ -61,5 +61,3 @@ php path_to_Nette_tools\Code-Checker\code-checker %* - премахва завършващия `?>` при PHP файлове - премахва десните интервали и излишните редове в края на файла - нормализира разделителите на редове до системните (ако посочите опцията `-l`) - -{{leftbar: www:@menu-common}} diff --git a/code-checker/cs/@home.texy b/tools/cs/code-checker.texy similarity index 98% rename from code-checker/cs/@home.texy rename to tools/cs/code-checker.texy index a4d62f10d6..8fb389565f 100644 --- a/code-checker/cs/@home.texy +++ b/tools/cs/code-checker.texy @@ -62,4 +62,3 @@ Co všechno dělá? - odstraňuje pravostranné mezery a zbytečné řádky na konci souboru - normalizuje oddělovače řádků na systémové (pokud uvedete volbu `-l`) -{{leftbar: www:@menu-common}} diff --git a/code-checker/de/@home.texy b/tools/de/code-checker.texy similarity index 98% rename from code-checker/de/@home.texy rename to tools/de/code-checker.texy index 598b407465..36684e214d 100644 --- a/code-checker/de/@home.texy +++ b/tools/de/code-checker.texy @@ -61,5 +61,3 @@ Was macht es alles? - entfernt das schließende `?>` bei PHP-Dateien - entfernt Leerzeichen am Zeilenende und unnötige Leerzeilen am Dateiende - normalisiert Zeilentrennzeichen auf Systemstandard (wenn Sie die Option `-l` angeben) - -{{leftbar: www:@menu-common}} diff --git a/code-checker/el/@home.texy b/tools/el/code-checker.texy similarity index 98% rename from code-checker/el/@home.texy rename to tools/el/code-checker.texy index de1f6401a0..2c102565e7 100644 --- a/code-checker/el/@home.texy +++ b/tools/el/code-checker.texy @@ -61,5 +61,3 @@ php path_to_Nette_tools\Code-Checker\code-checker %* - αφαιρεί το τελικό `?>` από τα αρχεία PHP - αφαιρεί τα δεξιά κενά και τις περιττές γραμμές στο τέλος του αρχείου - κανονικοποιεί τους διαχωριστές γραμμών σε συστήματος (εάν δώσετε την επιλογή `-l`) - -{{leftbar: www:@menu-common}} diff --git a/code-checker/en/@home.texy b/tools/en/code-checker.texy similarity index 98% rename from code-checker/en/@home.texy rename to tools/en/code-checker.texy index 2bbaba1c33..997dea69e0 100644 --- a/code-checker/en/@home.texy +++ b/tools/en/code-checker.texy @@ -62,4 +62,3 @@ What Does Code Checker Do? - removes trailing whitespace and unnecessary blank lines from the end of a file - normalizes line endings to the system default (with the `-l` parameter) -{{leftbar: www:@menu-common}} diff --git a/code-checker/es/@home.texy b/tools/es/code-checker.texy similarity index 98% rename from code-checker/es/@home.texy rename to tools/es/code-checker.texy index c6770a3010..eff3c64beb 100644 --- a/code-checker/es/@home.texy +++ b/tools/es/code-checker.texy @@ -61,5 +61,3 @@ php path_to_Nette_tools\Code-Checker\code-checker %* - elimina el cierre `?>` de los archivos PHP - elimina los espacios finales y las líneas innecesarias al final del archivo - normaliza los separadores de línea a los del sistema (si especifica la opción `-l`) - -{{leftbar: www:@menu-common}} diff --git a/code-checker/fr/@home.texy b/tools/fr/code-checker.texy similarity index 98% rename from code-checker/fr/@home.texy rename to tools/fr/code-checker.texy index 13c595ee8c..e8d8bdeabe 100644 --- a/code-checker/fr/@home.texy +++ b/tools/fr/code-checker.texy @@ -61,5 +61,3 @@ Que fait-il ? - supprime le `?>` de fin des fichiers PHP - supprime les espaces de fin et les lignes vides inutiles à la fin du fichier - normalise les séparateurs de lignes en séparateurs système (si vous spécifiez l'option `-l`) - -{{leftbar: www:@menu-common}} diff --git a/code-checker/hu/@home.texy b/tools/hu/code-checker.texy similarity index 98% rename from code-checker/hu/@home.texy rename to tools/hu/code-checker.texy index e676665b2f..8fc3e218a4 100644 --- a/code-checker/hu/@home.texy +++ b/tools/hu/code-checker.texy @@ -61,5 +61,3 @@ Mit csinál pontosan? - eltávolítja a záró `?>` taget a PHP fájlokból - eltávolítja a jobb oldali szóközöket és a felesleges sorokat a fájl végéről - normalizálja a sorelválasztókat a rendszer alapértelmezettjére (ha megadja a `-l` opciót) - -{{leftbar: www:@menu-common}} diff --git a/code-checker/it/@home.texy b/tools/it/code-checker.texy similarity index 98% rename from code-checker/it/@home.texy rename to tools/it/code-checker.texy index 4529024b15..c51e6fc4c1 100644 --- a/code-checker/it/@home.texy +++ b/tools/it/code-checker.texy @@ -61,5 +61,3 @@ Cosa fa? - rimuove i tag di chiusura `?>` dai file PHP - rimuove gli spazi finali e le righe vuote alla fine del file - normalizza i separatori di riga a quelli di sistema (se si specifica l'opzione `-l`) - -{{leftbar: www:@menu-common}} diff --git a/code-checker/ja/@home.texy b/tools/ja/code-checker.texy similarity index 98% rename from code-checker/ja/@home.texy rename to tools/ja/code-checker.texy index b01ce40115..93dc4f73bb 100644 --- a/code-checker/ja/@home.texy +++ b/tools/ja/code-checker.texy @@ -61,5 +61,3 @@ php path_to_Nette_tools\Code-Checker\code-checker %* - PHP ファイルの末尾の `?>` を削除します - ファイルの末尾の右側のスペースと不要な行を削除します - (オプション `-l` を指定した場合)改行文字をシステム標準に正規化します - -{{leftbar: www:@menu-common}} diff --git a/code-checker/pl/@home.texy b/tools/pl/code-checker.texy similarity index 98% rename from code-checker/pl/@home.texy rename to tools/pl/code-checker.texy index 23a99c3807..06313c916a 100644 --- a/code-checker/pl/@home.texy +++ b/tools/pl/code-checker.texy @@ -61,5 +61,3 @@ Co wszystko robi? - usuwa kończące `?>` w plikach PHP - usuwa prawostronne spacje i zbędne linie na końcu pliku - normalizuje separatory linii do systemowych (jeśli podasz opcję `-l`) - -{{leftbar: www:@menu-common}} diff --git a/code-checker/pt/@home.texy b/tools/pt/code-checker.texy similarity index 98% rename from code-checker/pt/@home.texy rename to tools/pt/code-checker.texy index c50e0603c1..3cd3257cf9 100644 --- a/code-checker/pt/@home.texy +++ b/tools/pt/code-checker.texy @@ -61,5 +61,3 @@ O que ele faz? - remove `?>` de fechamento em arquivos PHP - remove espaços em branco à direita e linhas desnecessárias no final do arquivo - normaliza os separadores de linha para o padrão do sistema (se você usar a opção `-l`) - -{{leftbar: www:@menu-common}} diff --git a/code-checker/ro/@home.texy b/tools/ro/code-checker.texy similarity index 98% rename from code-checker/ro/@home.texy rename to tools/ro/code-checker.texy index c73570354d..fdf4ad3079 100644 --- a/code-checker/ro/@home.texy +++ b/tools/ro/code-checker.texy @@ -61,5 +61,3 @@ Ce face? - elimină `?>` de la sfârșitul fișierelor PHP - elimină spațiile de la sfârșitul rândului și rândurile goale inutile de la sfârșitul fișierului - normalizează separatorii de rând la cei de sistem (dacă specificați opțiunea `-l`) - -{{leftbar: www:@menu-common}} diff --git a/code-checker/ru/@home.texy b/tools/ru/code-checker.texy similarity index 98% rename from code-checker/ru/@home.texy rename to tools/ru/code-checker.texy index 911ba624aa..64a0ade2b1 100644 --- a/code-checker/ru/@home.texy +++ b/tools/ru/code-checker.texy @@ -61,5 +61,3 @@ php path_to_Nette_tools\Code-Checker\code-checker %* - удаляет завершающий `?>` у PHP-файлов - удаляет пробелы в конце строк и лишние строки в конце файла - нормализует разделители строк до системных (если указана опция `-l`) - -{{leftbar: www:@menu-common}} diff --git a/code-checker/sl/@home.texy b/tools/sl/code-checker.texy similarity index 98% rename from code-checker/sl/@home.texy rename to tools/sl/code-checker.texy index 27cbc98ca0..16d04a8f24 100644 --- a/code-checker/sl/@home.texy +++ b/tools/sl/code-checker.texy @@ -61,5 +61,3 @@ Kaj vse počne? - odstranjuje zaključne `?>` pri PHP datotekah - odstranjuje desne presledke in nepotrebne vrstice na koncu datoteke - normalizira ločila vrstic na sistemske (če navedete opcijo `-l`) - -{{leftbar: www:@menu-common}} diff --git a/code-checker/tr/@home.texy b/tools/tr/code-checker.texy similarity index 98% rename from code-checker/tr/@home.texy rename to tools/tr/code-checker.texy index ea2e1ecb22..49d592bbb0 100644 --- a/code-checker/tr/@home.texy +++ b/tools/tr/code-checker.texy @@ -61,5 +61,3 @@ Ne yapar? - PHP dosyalarındaki kapanış `?>` etiketini kaldırır - Sağdaki boşlukları ve dosyanın sonundaki gereksiz satırları kaldırır - Satır ayırıcılarını sistem varsayılanına normalleştirir (`-l` seçeneğini belirtirseniz) - -{{leftbar: www:@menu-common}} diff --git a/code-checker/uk/@home.texy b/tools/uk/code-checker.texy similarity index 98% rename from code-checker/uk/@home.texy rename to tools/uk/code-checker.texy index 261ea7550c..6063642a48 100644 --- a/code-checker/uk/@home.texy +++ b/tools/uk/code-checker.texy @@ -61,5 +61,3 @@ php шлях_до_Nette_tools\Code-Checker\code-checker %* - видаляє завершальний `?>` у PHP файлах - видаляє пробіли в кінці рядка та зайві рядки в кінці файлу - нормалізує роздільники рядків до системних (якщо вказано опцію `-l`) - -{{leftbar: www:@menu-common}} From 7f8722547e52cb5a4d8dd91dda1fff01c7a6b769 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Sat, 6 Jun 2026 17:45:37 +0200 Subject: [PATCH 39/50] moved editor-and-tools to tools:ide --- best-practices/bg/@home.texy | 1 - best-practices/cs/@home.texy | 1 - best-practices/de/@home.texy | 1 - best-practices/el/@home.texy | 1 - best-practices/en/@home.texy | 1 - best-practices/es/@home.texy | 1 - best-practices/fr/@home.texy | 1 - best-practices/hu/@home.texy | 1 - best-practices/it/@home.texy | 1 - best-practices/ja/@home.texy | 1 - best-practices/pl/@home.texy | 1 - best-practices/pt/@home.texy | 1 - best-practices/ro/@home.texy | 1 - best-practices/ru/@home.texy | 1 - best-practices/sl/@home.texy | 1 - best-practices/tr/@home.texy | 1 - best-practices/uk/@home.texy | 1 - bootstrap/bg/@home.texy | 2 +- bootstrap/cs/@home.texy | 2 +- bootstrap/de/@home.texy | 2 +- bootstrap/el/@home.texy | 2 +- bootstrap/en/@home.texy | 2 +- bootstrap/es/@home.texy | 2 +- bootstrap/fr/@home.texy | 2 +- bootstrap/hu/@home.texy | 2 +- bootstrap/it/@home.texy | 2 +- bootstrap/ja/@home.texy | 2 +- bootstrap/pl/@home.texy | 2 +- bootstrap/pt/@home.texy | 2 +- bootstrap/ro/@home.texy | 2 +- bootstrap/ru/@home.texy | 2 +- bootstrap/sl/@home.texy | 2 +- bootstrap/tr/@home.texy | 2 +- bootstrap/uk/@home.texy | 2 +- dependency-injection/bg/configuration.texy | 2 +- dependency-injection/cs/configuration.texy | 2 +- dependency-injection/de/configuration.texy | 2 +- dependency-injection/el/configuration.texy | 2 +- dependency-injection/en/configuration.texy | 2 +- dependency-injection/es/configuration.texy | 2 +- dependency-injection/fr/configuration.texy | 2 +- dependency-injection/hu/configuration.texy | 2 +- dependency-injection/it/configuration.texy | 2 +- dependency-injection/ja/configuration.texy | 2 +- dependency-injection/pl/configuration.texy | 2 +- dependency-injection/pt/configuration.texy | 2 +- dependency-injection/ro/configuration.texy | 2 +- dependency-injection/ru/configuration.texy | 2 +- dependency-injection/sl/configuration.texy | 2 +- dependency-injection/tr/configuration.texy | 2 +- dependency-injection/uk/configuration.texy | 2 +- nette/bg/configuring.texy | 2 +- nette/cs/configuring.texy | 2 +- nette/de/configuring.texy | 2 +- nette/el/configuring.texy | 2 +- nette/en/configuring.texy | 2 +- nette/es/configuring.texy | 2 +- nette/fr/configuring.texy | 2 +- nette/hu/configuring.texy | 2 +- nette/it/configuring.texy | 2 +- nette/ja/configuring.texy | 2 +- nette/pl/configuring.texy | 2 +- nette/pt/configuring.texy | 2 +- nette/ro/configuring.texy | 2 +- nette/ru/configuring.texy | 2 +- nette/sl/configuring.texy | 2 +- nette/tr/configuring.texy | 2 +- nette/uk/configuring.texy | 2 +- best-practices/bg/editors-and-tools.texy => tools/bg/ide.texy | 0 best-practices/cs/editors-and-tools.texy => tools/cs/ide.texy | 0 best-practices/de/editors-and-tools.texy => tools/de/ide.texy | 0 best-practices/el/editors-and-tools.texy => tools/el/ide.texy | 0 best-practices/en/editors-and-tools.texy => tools/en/ide.texy | 0 best-practices/es/editors-and-tools.texy => tools/es/ide.texy | 0 best-practices/fr/editors-and-tools.texy => tools/fr/ide.texy | 0 best-practices/hu/editors-and-tools.texy => tools/hu/ide.texy | 0 best-practices/it/editors-and-tools.texy => tools/it/ide.texy | 0 best-practices/ja/editors-and-tools.texy => tools/ja/ide.texy | 0 best-practices/pl/editors-and-tools.texy => tools/pl/ide.texy | 0 best-practices/pt/editors-and-tools.texy => tools/pt/ide.texy | 0 best-practices/ro/editors-and-tools.texy => tools/ro/ide.texy | 0 best-practices/ru/editors-and-tools.texy => tools/ru/ide.texy | 0 best-practices/sl/editors-and-tools.texy => tools/sl/ide.texy | 0 best-practices/tr/editors-and-tools.texy => tools/tr/ide.texy | 0 best-practices/uk/editors-and-tools.texy => tools/uk/ide.texy | 0 85 files changed, 51 insertions(+), 68 deletions(-) rename best-practices/bg/editors-and-tools.texy => tools/bg/ide.texy (100%) rename best-practices/cs/editors-and-tools.texy => tools/cs/ide.texy (100%) rename best-practices/de/editors-and-tools.texy => tools/de/ide.texy (100%) rename best-practices/el/editors-and-tools.texy => tools/el/ide.texy (100%) rename best-practices/en/editors-and-tools.texy => tools/en/ide.texy (100%) rename best-practices/es/editors-and-tools.texy => tools/es/ide.texy (100%) rename best-practices/fr/editors-and-tools.texy => tools/fr/ide.texy (100%) rename best-practices/hu/editors-and-tools.texy => tools/hu/ide.texy (100%) rename best-practices/it/editors-and-tools.texy => tools/it/ide.texy (100%) rename best-practices/ja/editors-and-tools.texy => tools/ja/ide.texy (100%) rename best-practices/pl/editors-and-tools.texy => tools/pl/ide.texy (100%) rename best-practices/pt/editors-and-tools.texy => tools/pt/ide.texy (100%) rename best-practices/ro/editors-and-tools.texy => tools/ro/ide.texy (100%) rename best-practices/ru/editors-and-tools.texy => tools/ru/ide.texy (100%) rename best-practices/sl/editors-and-tools.texy => tools/sl/ide.texy (100%) rename best-practices/tr/editors-and-tools.texy => tools/tr/ide.texy (100%) rename best-practices/uk/editors-and-tools.texy => tools/uk/ide.texy (100%) diff --git a/best-practices/bg/@home.texy b/best-practices/bg/@home.texy index 808c4d31b7..31c68a5d23 100644 --- a/best-practices/bg/@home.texy +++ b/best-practices/bg/@home.texy @@ -42,7 +42,6 @@ Nette Приложения - [Защо Nette използва PascalCase нотация за константи? |https://blog.nette.org/bg/for-less-screaming-in-the-code] - [Защо Nette не използва суфикс Interface? |https://blog.nette.org/bg/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: съвети за използване |composer] -- [Съвети за редактори & инструменти |editors-and-tools] - [Въведение в обектно-ориентираното програмиране |nette:introduction-to-object-oriented-programming] </div> diff --git a/best-practices/cs/@home.texy b/best-practices/cs/@home.texy index 38118d8894..e95aa101a3 100644 --- a/best-practices/cs/@home.texy +++ b/best-practices/cs/@home.texy @@ -43,7 +43,6 @@ Obecné - [Proč Nette používá PascalCase notaci konstant? |https://blog.nette.org/cs/za-mene-kriku-v-kodu] - [Proč Nette nepoužívá příponu Interface? |https://blog.nette.org/cs/predpony-a-pripony-do-nazvu-rozhrani-nepatri] - [Composer: tipy pro použití |composer] -- [Tipy na editory & nástroje |editors-and-tools] - [Úvod do objektově orientovaného programování |nette:introduction-to-object-oriented-programming] </div> diff --git a/best-practices/de/@home.texy b/best-practices/de/@home.texy index d855293435..8f253a9392 100644 --- a/best-practices/de/@home.texy +++ b/best-practices/de/@home.texy @@ -42,7 +42,6 @@ Allgemeines - [Warum Nette die PascalCase-Notation für Konstanten verwendet |https://blog.nette.org/de/for-less-screaming-in-the-code] - [Warum Nette das Interface-Suffix nicht verwendet |https://blog.nette.org/de/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: Tipps zur Verwendung |composer] -- [Tipps für Editoren & Werkzeuge |editors-and-tools] - [Einführung in die objektorientierte Programmierung |nette:introduction-to-object-oriented-programming] </div> diff --git a/best-practices/el/@home.texy b/best-practices/el/@home.texy index 0e8088a224..4b0fced2a6 100644 --- a/best-practices/el/@home.texy +++ b/best-practices/el/@home.texy @@ -42,7 +42,6 @@ - [Γιατί το Nette χρησιμοποιεί τη σημειογραφία PascalCase για σταθερές; |https://blog.nette.org/el/for-less-screaming-in-the-code] - [Γιατί το Nette δεν χρησιμοποιεί το επίθημα Interface; |https://blog.nette.org/el/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: συμβουλές χρήσης |composer] -- [Συμβουλές για editors & εργαλεία |editors-and-tools] - [Εισαγωγή στον αντικειμενοστρεφή προγραμματισμό |nette:introduction-to-object-oriented-programming] </div> diff --git a/best-practices/en/@home.texy b/best-practices/en/@home.texy index d41a3f0212..650201c107 100644 --- a/best-practices/en/@home.texy +++ b/best-practices/en/@home.texy @@ -43,7 +43,6 @@ General - [Why Does Nette Use PascalCase Notation for Constants? |https://blog.nette.org/en/for-less-screaming-in-the-code] - [Why Doesn't Nette Use the Interface Suffix? |https://blog.nette.org/en/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: Usage Tips |composer] -- [Tips for Editors & Tools |editors-and-tools] - [Introduction to Object-Oriented Programming |nette:introduction-to-object-oriented-programming] </div> diff --git a/best-practices/es/@home.texy b/best-practices/es/@home.texy index 6a6ee9df47..e8747088c6 100644 --- a/best-practices/es/@home.texy +++ b/best-practices/es/@home.texy @@ -42,7 +42,6 @@ General - [¿Por qué Nette usa la notación PascalCase para las constantes? |https://blog.nette.org/es/for-less-screaming-in-the-code] - [¿Por qué Nette no usa el sufijo Interface? |https://blog.nette.org/es/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: consejos para su uso |composer] -- [Consejos sobre editores y herramientas |editors-and-tools] - [Introducción a la programación orientada a objetos |nette:introduction-to-object-oriented-programming] </div> diff --git a/best-practices/fr/@home.texy b/best-practices/fr/@home.texy index 829741034c..a81b037dcf 100644 --- a/best-practices/fr/@home.texy +++ b/best-practices/fr/@home.texy @@ -42,7 +42,6 @@ Général - [Pourquoi Nette utilise la notation PascalCase pour les constantes ? |https://blog.nette.org/fr/for-less-screaming-in-the-code] - [Pourquoi Nette n'utilise pas le suffixe Interface ? |https://blog.nette.org/fr/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer : conseils d'utilisation |composer] -- [Conseils sur les éditeurs & outils |editors-and-tools] - [Introduction à la programmation orientée objet |nette:introduction-to-object-oriented-programming] </div> diff --git a/best-practices/hu/@home.texy b/best-practices/hu/@home.texy index e1ab1cabd8..e3118f3835 100644 --- a/best-practices/hu/@home.texy +++ b/best-practices/hu/@home.texy @@ -42,7 +42,6 @@ Nette Alkalmazások - [Miért használja a Nette a PascalCase konstans jelölést? |https://blog.nette.org/hu/for-less-screaming-in-the-code] - [Miért nem használja a Nette az Interface utótagot? |https://blog.nette.org/hu/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: használati tippek |composer] -- [Tippek szerkesztőkhöz & eszközökhöz |editors-and-tools] - [Bevezetés az objektumorientált programozásba |nette:introduction-to-object-oriented-programming] </div> diff --git a/best-practices/it/@home.texy b/best-practices/it/@home.texy index 7a11feda65..d4cc303b8b 100644 --- a/best-practices/it/@home.texy +++ b/best-practices/it/@home.texy @@ -42,7 +42,6 @@ Generale - [Perché Nette usa la notazione PascalCase per le costanti? |https://blog.nette.org/it/for-less-screaming-in-the-code] - [Perché Nette non usa il suffisso Interface? |https://blog.nette.org/it/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: suggerimenti per l'uso |composer] -- [Suggerimenti per editor e strumenti |editors-and-tools] - [Introduzione alla programmazione orientata agli oggetti |nette:introduction-to-object-oriented-programming] </div> diff --git a/best-practices/ja/@home.texy b/best-practices/ja/@home.texy index eab0e604fe..12c1bd9707 100644 --- a/best-practices/ja/@home.texy +++ b/best-practices/ja/@home.texy @@ -42,7 +42,6 @@ Netteアプリケーション - [なぜ Nette は定数に PascalCase 記法を使用するのですか? |https://blog.nette.org/en/for-less-screaming-in-the-code] - [なぜ Nette は Interface 接尾辞を使用しないのですか? |https://blog.nette.org/en/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: 使用のヒント |composer] -- [エディタとツールのヒント |editors-and-tools] - [オブジェクト指向プログラミング入門 |nette:introduction-to-object-oriented-programming] </div> diff --git a/best-practices/pl/@home.texy b/best-practices/pl/@home.texy index 64470576e1..1f1d0231b0 100644 --- a/best-practices/pl/@home.texy +++ b/best-practices/pl/@home.texy @@ -42,7 +42,6 @@ Ogólne - [Dlaczego Nette używa notacji PascalCase dla stałych? |https://blog.nette.org/pl/for-less-screaming-in-the-code] - [Dlaczego Nette nie używa przyrostka Interface? |https://blog.nette.org/pl/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: wskazówki dotyczące użycia |composer] -- [Wskazówki dotyczące edytorów i narzędzi |editors-and-tools] - [Wprowadzenie do programowania obiektowego |nette:introduction-to-object-oriented-programming] </div> diff --git a/best-practices/pt/@home.texy b/best-practices/pt/@home.texy index ff77ce2b7f..3deee7f759 100644 --- a/best-practices/pt/@home.texy +++ b/best-practices/pt/@home.texy @@ -42,7 +42,6 @@ Geral - [Por que o Nette usa a notação PascalCase para constantes? |https://blog.nette.org/pt/for-less-screaming-in-the-code] - [Por que o Nette não usa o sufixo Interface? |https://blog.nette.org/pt/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: dicas de uso |composer] -- [Dicas sobre editores & ferramentas |editors-and-tools] - [Introdução à programação orientada a objetos |nette:introduction-to-object-oriented-programming] </div> diff --git a/best-practices/ro/@home.texy b/best-practices/ro/@home.texy index a742e5d015..13cd0f4a31 100644 --- a/best-practices/ro/@home.texy +++ b/best-practices/ro/@home.texy @@ -42,7 +42,6 @@ Generale - [De ce Nette utilizează notația PascalCase pentru constante? |https://blog.nette.org/ro/for-less-screaming-in-the-code] - [De ce Nette nu utilizează sufixul Interface? |https://blog.nette.org/ro/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: sfaturi de utilizare |composer] -- [Sfaturi pentru editori & instrumente |editors-and-tools] - [Introducere în programarea orientată pe obiecte |nette:introduction-to-object-oriented-programming] </div> diff --git a/best-practices/ru/@home.texy b/best-practices/ru/@home.texy index 1ea3ce7e1e..07d421647a 100644 --- a/best-practices/ru/@home.texy +++ b/best-practices/ru/@home.texy @@ -42,7 +42,6 @@ - [Почему Nette использует PascalCase нотацию для констант? |https://blog.nette.org/ru/for-less-screaming-in-the-code] - [Почему Nette не использует суффикс Interface? |https://blog.nette.org/ru/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: советы по использованию |composer] -- [Советы по редакторам и инструментам |editors-and-tools] - [Введение в объектно-ориентированное программирование |nette:introduction-to-object-oriented-programming] </div> diff --git a/best-practices/sl/@home.texy b/best-practices/sl/@home.texy index a4cf0efbec..930d03f006 100644 --- a/best-practices/sl/@home.texy +++ b/best-practices/sl/@home.texy @@ -42,7 +42,6 @@ Splošno - [Zakaj Nette uporablja PascalCase notacijo konstant? |https://blog.nette.org/sl/for-less-screaming-in-the-code] - [Zakaj Nette ne uporablja pripone Interface? |https://blog.nette.org/sl/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: nasveti za uporabo |composer] -- [Nasveti za urejevalnike & orodja |editors-and-tools] - [Uvod v objektno orientirano programiranje |nette:introduction-to-object-oriented-programming] </div> diff --git a/best-practices/tr/@home.texy b/best-practices/tr/@home.texy index c8b90b9e40..095c54c8f0 100644 --- a/best-practices/tr/@home.texy +++ b/best-practices/tr/@home.texy @@ -42,7 +42,6 @@ Genel - [Nette neden PascalCase sabit gösterimini kullanıyor? |https://blog.nette.org/tr/for-less-screaming-in-the-code] - [Nette neden Interface son ekini kullanmıyor? |https://blog.nette.org/tr/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: kullanım ipuçları |composer] -- [Düzenleyiciler ve araçlar için ipuçları |editors-and-tools] - [Nesne yönelimli programlamaya giriş |nette:introduction-to-object-oriented-programming] </div> diff --git a/best-practices/uk/@home.texy b/best-practices/uk/@home.texy index f9d3510c2b..623e6f8453 100644 --- a/best-practices/uk/@home.texy +++ b/best-practices/uk/@home.texy @@ -42,7 +42,6 @@ - [Чому Nette використовує PascalCase нотацію констант? |https://blog.nette.org/uk/for-less-screaming-in-the-code] - [Чому Nette не використовує суфікс Interface? |https://blog.nette.org/uk/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: поради щодо використання |composer] -- [Поради щодо редакторів та інструментів |editors-and-tools] - [Вступ до об'єктно-орієнтованого програмування |nette:introduction-to-object-oriented-programming] </div> diff --git a/bootstrap/bg/@home.texy b/bootstrap/bg/@home.texy index 3f9b20f4a1..675b61584a 100644 --- a/bootstrap/bg/@home.texy +++ b/bootstrap/bg/@home.texy @@ -7,7 +7,7 @@ Nette Bootstrap .[tip] Ако използвате целия framework, не е необходимо да правите нищо повече. В проекта имате подготвена директория `config/` за конфигурационните файлове и зареждането им се управлява от [зареждащото устройство на приложението |application:bootstrapping#Конфигурация на DI контейнера]. Тази статия е за потребители, които използват само една библиотека на Nette и искат да използват възможностите на конфигурационните файлове. -Конфигурационните файлове обикновено се записват във [формат NEON|neon:format] и най-добре се редактират в [редактори с неговата поддръжка |best-practices:editors-and-tools#IDE редактор]. Могат да се разглеждат като ръководства за **създаване и конфигуриране** на обекти. Следователно, резултатът от зареждането на конфигурацията ще бъде така наречената фабрика, която е обект, който по заявка ще ни създаде други обекти, които искаме да използваме. Например връзка с база данни и т.н. +Конфигурационните файлове обикновено се записват във [формат NEON|neon:format] и най-добре се редактират в [редактори с неговата поддръжка |tools:ide]. Могат да се разглеждат като ръководства за **създаване и конфигуриране** на обекти. Следователно, резултатът от зареждането на конфигурацията ще бъде така наречената фабрика, която е обект, който по заявка ще ни създаде други обекти, които искаме да използваме. Например връзка с база данни и т.н. Тази фабрика се нарича още *dependency injection контейнер* (DI container) и ако се интересувате от подробности, прочетете главата за [dependency injection |dependency-injection:]. diff --git a/bootstrap/cs/@home.texy b/bootstrap/cs/@home.texy index 9e3f2acaa6..fad72a0871 100644 --- a/bootstrap/cs/@home.texy +++ b/bootstrap/cs/@home.texy @@ -7,7 +7,7 @@ Jednotlivé součásti Nette nastavujeme pomocí konfiguračních souborů. Uká .[tip] Pokud používate celý framework, není potřeba nic dalšího dělat. V projektu máte pro konfigurační soubory předpřipravený adresář `config/` a jejich načítání má na starosti [zavaděč aplikace |application:bootstrapping#Konfigurace DI kontejneru]. Tento článek je pro uživatele, kteří používají jen jednu knihovnu Nette a chtějí využít možnosti konfiguračních souborů. -Konfigurační soubory se obvykle zapisují ve [formátu NEON|neon:format] a nejlépe se upravují v [editorech s jeho podporou |best-practices:editors-and-tools#IDE editor]. Lze je chápat jako návody, jak **vytvářet a konfigurovat** objekty. Tedy výsledkem načtení konfigurace bude tzv. továrna, což je objekt, který nám na požádání vytvoří další objekty, které chceme používat. Například databázové spojení apod. +Konfigurační soubory se obvykle zapisují ve [formátu NEON|neon:format] a nejlépe se upravují v [editorech s jeho podporou |tools:ide]. Lze je chápat jako návody, jak **vytvářet a konfigurovat** objekty. Tedy výsledkem načtení konfigurace bude tzv. továrna, což je objekt, který nám na požádání vytvoří další objekty, které chceme používat. Například databázové spojení apod. Této továrně se také říká *dependency injection kontejner* (DI container) a pokud by vás zajímaly podrobnosti, přečtěte si kapitolu o [dependency injection |dependency-injection:]. diff --git a/bootstrap/de/@home.texy b/bootstrap/de/@home.texy index 8f49650c62..82fe54e45b 100644 --- a/bootstrap/de/@home.texy +++ b/bootstrap/de/@home.texy @@ -7,7 +7,7 @@ Einzelne Nette-Komponenten werden über Konfigurationsdateien eingerichtet. Wir .[tip] Wenn Sie das gesamte Framework verwenden, müssen Sie nichts weiter tun. In Ihrem Projekt gibt es ein vorbereitetes Verzeichnis `config/` für Konfigurationsdateien, und deren Laden wird vom [Anwendungs-Bootstrap |application:bootstrapping#Konfiguration des DI-Containers] übernommen. Dieser Artikel richtet sich an Benutzer, die nur eine Nette-Bibliothek verwenden und die Möglichkeiten der Konfigurationsdateien nutzen möchten. -Konfigurationsdateien werden normalerweise im [NEON-Format|neon:format] geschrieben und am besten in [Editoren mit NEON-Unterstützung |best-practices:editors-and-tools#IDE-Editor] bearbeitet. Sie können als Anleitungen zum **Erstellen und Konfigurieren** von Objekten verstanden werden. Das Ergebnis des Ladens der Konfiguration ist also eine sogenannte Factory, ein Objekt, das auf Anfrage weitere Objekte erstellt, die wir verwenden möchten. Zum Beispiel eine Datenbankverbindung usw. +Konfigurationsdateien werden normalerweise im [NEON-Format|neon:format] geschrieben und am besten in [Editoren mit NEON-Unterstützung |tools:ide] bearbeitet. Sie können als Anleitungen zum **Erstellen und Konfigurieren** von Objekten verstanden werden. Das Ergebnis des Ladens der Konfiguration ist also eine sogenannte Factory, ein Objekt, das auf Anfrage weitere Objekte erstellt, die wir verwenden möchten. Zum Beispiel eine Datenbankverbindung usw. Dieser Factory wird auch *Dependency Injection Container* (DI-Container) genannt. Wenn Sie an Details interessiert sind, lesen Sie das Kapitel über [Dependency Injection |dependency-injection:]. diff --git a/bootstrap/el/@home.texy b/bootstrap/el/@home.texy index 8b4cf46446..9eaf9b36a0 100644 --- a/bootstrap/el/@home.texy +++ b/bootstrap/el/@home.texy @@ -7,7 +7,7 @@ Nette Bootstrap .[tip] Αν χρησιμοποιείτε ολόκληρο το framework, δεν χρειάζεται να κάνετε τίποτα άλλο. Στο έργο σας, έχετε έναν προετοιμασμένο κατάλογο `config/` για αρχεία διαμόρφωσης, και η φόρτωσή τους αναλαμβάνεται από τον [φορτωτή της εφαρμογής |application:bootstrapping#Διαμόρφωση του DI Container]. Αυτό το άρθρο είναι για χρήστες που χρησιμοποιούν μόνο μία βιβλιοθήκη Nette και θέλουν να εκμεταλλευτούν τις δυνατότητες των αρχείων διαμόρφωσης. -Τα αρχεία διαμόρφωσης συνήθως γράφονται σε [μορφή NEON |neon:format] και επεξεργάζονται καλύτερα σε [editors με υποστήριξη για αυτό |best-practices:editors-and-tools#IDE editor]. Μπορούν να θεωρηθούν ως οδηγίες για το πώς να **δημιουργείτε και να διαμορφώνετε** αντικείμενα. Έτσι, το αποτέλεσμα της φόρτωσης της διαμόρφωσης θα είναι ένα λεγόμενο factory, το οποίο είναι ένα αντικείμενο που, κατόπιν αιτήματος, θα δημιουργήσει άλλα αντικείμενα που θέλουμε να χρησιμοποιήσουμε. Για παράδειγμα, συνδέσεις βάσης δεδομένων κ.λπ. +Τα αρχεία διαμόρφωσης συνήθως γράφονται σε [μορφή NEON |neon:format] και επεξεργάζονται καλύτερα σε [editors με υποστήριξη για αυτό |tools:ide]. Μπορούν να θεωρηθούν ως οδηγίες για το πώς να **δημιουργείτε και να διαμορφώνετε** αντικείμενα. Έτσι, το αποτέλεσμα της φόρτωσης της διαμόρφωσης θα είναι ένα λεγόμενο factory, το οποίο είναι ένα αντικείμενο που, κατόπιν αιτήματος, θα δημιουργήσει άλλα αντικείμενα που θέλουμε να χρησιμοποιήσουμε. Για παράδειγμα, συνδέσεις βάσης δεδομένων κ.λπ. Αυτό το factory ονομάζεται επίσης *dependency injection container* (DI container) και αν σας ενδιαφέρουν οι λεπτομέρειες, διαβάστε το κεφάλαιο για το [dependency injection |dependency-injection:]. diff --git a/bootstrap/en/@home.texy b/bootstrap/en/@home.texy index 0e80ab16c2..ad053c85de 100644 --- a/bootstrap/en/@home.texy +++ b/bootstrap/en/@home.texy @@ -7,7 +7,7 @@ Individual Nette components are configured using configuration files. We will sh .[tip] If you are using the entire framework, there is no need to do anything else. Your project has a prepared `config/` directory for configuration files, and their loading is handled by the [application loader |application:bootstrapping#DI Container Configuration]. This article is for users who use only a single Nette library and want to take advantage of configuration files. -Configuration files are usually written in [NEON format|neon:format] and are best edited in [editors that support it |best-practices:editors-and-tools#IDE Editor]. They can be thought of as instructions on how to **create and configure** objects. Thus, the result of loading a configuration will be a so-called factory, which is an object that creates on demand other objects you want to use. For example, a database connection, etc. +Configuration files are usually written in [NEON format|neon:format] and are best edited in [editors that support it |tools:ide]. They can be thought of as instructions on how to **create and configure** objects. Thus, the result of loading a configuration will be a so-called factory, which is an object that creates on demand other objects you want to use. For example, a database connection, etc. This factory is also called a *dependency injection container* (DI container), and if you are interested in the details, read the chapter on [dependency injection |dependency-injection:]. diff --git a/bootstrap/es/@home.texy b/bootstrap/es/@home.texy index 25321bada6..e6b3068d34 100644 --- a/bootstrap/es/@home.texy +++ b/bootstrap/es/@home.texy @@ -7,7 +7,7 @@ Configuramos los componentes individuales de Nette usando archivos de configurac .[tip] Si está utilizando todo el framework, no necesita hacer nada más. En su proyecto, tiene un directorio `config/` preparado para archivos de configuración, y la [carga de la aplicación |application:bootstrapping#Configuración del contenedor DI] se encarga de cargarlos. Este artículo es para usuarios que utilizan solo una librería de Nette y desean aprovechar las capacidades de los archivos de configuración. -Los archivos de configuración generalmente se escriben en [formato NEON|neon:format] y se editan mejor en [editores con soporte para él |best-practices:editors-and-tools#Editor IDE]. Pueden verse como instrucciones sobre cómo **crear y configurar** objetos. Por lo tanto, el resultado de cargar la configuración será una llamada fábrica, que es un objeto que creará otros objetos que queremos usar bajo demanda. Por ejemplo, una conexión a la base de datos, etc. +Los archivos de configuración generalmente se escriben en [formato NEON|neon:format] y se editan mejor en [editores con soporte para él |tools:ide]. Pueden verse como instrucciones sobre cómo **crear y configurar** objetos. Por lo tanto, el resultado de cargar la configuración será una llamada fábrica, que es un objeto que creará otros objetos que queremos usar bajo demanda. Por ejemplo, una conexión a la base de datos, etc. Esta fábrica también se llama *contenedor de inyección de dependencias* (contenedor DI) y si está interesado en los detalles, lea el capítulo sobre [inyección de dependencias |dependency-injection:]. diff --git a/bootstrap/fr/@home.texy b/bootstrap/fr/@home.texy index 25f662ac6c..d3e9912a50 100644 --- a/bootstrap/fr/@home.texy +++ b/bootstrap/fr/@home.texy @@ -7,7 +7,7 @@ Les composants individuels de Nette sont configurés à l'aide de fichiers de co .[tip] Si vous utilisez le framework complet, vous n'avez rien d'autre à faire. Votre projet dispose d'un répertoire `config/` préparé pour les fichiers de configuration, et leur chargement est géré par [le chargeur de l'application |application:bootstrapping#Configuration du Conteneur DI]. Cet article s'adresse aux utilisateurs qui n'utilisent qu'une seule bibliothèque Nette et souhaitent profiter des fonctionnalités des fichiers de configuration. -Les fichiers de configuration sont généralement écrits au [format NEON |neon:format] et sont mieux édités dans des [éditeurs qui le prennent en charge |best-practices:editors-and-tools#Éditeur IDE]. Ils peuvent être considérés comme des instructions sur la façon de **créer et configurer** des objets. Ainsi, le résultat du chargement de la configuration sera une soi-disant factory, qui est un objet qui créera d'autres objets que nous voulons utiliser à la demande. Par exemple, une connexion à une base de données, etc. +Les fichiers de configuration sont généralement écrits au [format NEON |neon:format] et sont mieux édités dans des [éditeurs qui le prennent en charge |tools:ide]. Ils peuvent être considérés comme des instructions sur la façon de **créer et configurer** des objets. Ainsi, le résultat du chargement de la configuration sera une soi-disant factory, qui est un objet qui créera d'autres objets que nous voulons utiliser à la demande. Par exemple, une connexion à une base de données, etc. Cette factory est également appelée *conteneur d'injection de dépendances* (conteneur DI), et si vous êtes intéressé par les détails, lisez le chapitre sur [l'injection de dépendances |dependency-injection:]. diff --git a/bootstrap/hu/@home.texy b/bootstrap/hu/@home.texy index 86a0ca10df..51c3a05002 100644 --- a/bootstrap/hu/@home.texy +++ b/bootstrap/hu/@home.texy @@ -7,7 +7,7 @@ A Nette egyes részeit konfigurációs fájlok segítségével állítjuk be. Me .[tip] Ha a teljes keretrendszert használja, nincs szükség további teendőkre. A projektben van egy előkészített `config/` könyvtár a konfigurációs fájlok számára, és ezek betöltéséért az [alkalmazás betöltő |application:bootstrapping#DI konténer konfigurálása] felelős. Ez a cikk azoknak a felhasználóknak szól, akik csak egy Nette könyvtárat használnak, és ki szeretnék használni a konfigurációs fájlok lehetőségeit. -A konfigurációs fájlokat általában [NEON formátumban|neon:format] írják, és a legjobban [az azt támogató szerkesztőkben |best-practices:editors-and-tools#IDE szerkesztő] lehet szerkeszteni. Útmutatóként foghatók fel, hogyan **hozzunk létre és konfiguráljunk** objektumokat. Tehát a konfiguráció betöltésének eredménye egy úgynevezett factory lesz, ami egy olyan objektum, amely kérésre létrehozza számunkra a használni kívánt további objektumokat. Például adatbázis-kapcsolatokat stb. +A konfigurációs fájlokat általában [NEON formátumban|neon:format] írják, és a legjobban [az azt támogató szerkesztőkben |tools:ide] lehet szerkeszteni. Útmutatóként foghatók fel, hogyan **hozzunk létre és konfiguráljunk** objektumokat. Tehát a konfiguráció betöltésének eredménye egy úgynevezett factory lesz, ami egy olyan objektum, amely kérésre létrehozza számunkra a használni kívánt további objektumokat. Például adatbázis-kapcsolatokat stb. Ezt a factory-t *dependency injection konténernek* (DI konténer) is nevezik, és ha érdeklik a részletek, olvassa el a [dependency injection |dependency-injection:] fejezetet. diff --git a/bootstrap/it/@home.texy b/bootstrap/it/@home.texy index 72a8b4d1f0..cbd055400a 100644 --- a/bootstrap/it/@home.texy +++ b/bootstrap/it/@home.texy @@ -7,7 +7,7 @@ Le singole parti di Nette vengono impostate tramite file di configurazione. Vedi .[tip] Se si utilizza l'intero framework, non è necessario fare altro. Nel progetto è presente una directory `config/` preimpostata per i file di configurazione, e il loro caricamento è gestito dal [bootloader dell'applicazione |application:bootstrapping#Configurazione del Container DI]. Questo articolo è per gli utenti che utilizzano solo una libreria Nette e vogliono sfruttare le possibilità dei file di configurazione. -I file di configurazione sono solitamente scritti in [formato NEON|neon:format] e si modificano al meglio negli [editor con supporto per esso |best-practices:editors-and-tools#Editor IDE]. Possono essere visti come istruzioni su come **creare e configurare** oggetti. Quindi, il risultato del caricamento della configurazione sarà una cosiddetta factory, che è un oggetto che, su richiesta, ci creerà altri oggetti che vogliamo utilizzare. Ad esempio, connessioni al database, ecc. +I file di configurazione sono solitamente scritti in [formato NEON|neon:format] e si modificano al meglio negli [editor con supporto per esso |tools:ide]. Possono essere visti come istruzioni su come **creare e configurare** oggetti. Quindi, il risultato del caricamento della configurazione sarà una cosiddetta factory, che è un oggetto che, su richiesta, ci creerà altri oggetti che vogliamo utilizzare. Ad esempio, connessioni al database, ecc. Questa factory è anche chiamata *dependency injection container* (container DI) e se sei interessato ai dettagli, leggi il capitolo sulla [dependency injection |dependency-injection:]. diff --git a/bootstrap/ja/@home.texy b/bootstrap/ja/@home.texy index 80ea76d567..1cbdaf1b1d 100644 --- a/bootstrap/ja/@home.texy +++ b/bootstrap/ja/@home.texy @@ -7,7 +7,7 @@ Nette の個々のコンポーネントは設定ファイルを使用して設 .[tip] フレームワーク全体を使用している場合、追加の作業は必要ありません。プロジェクトには設定ファイル用の `config/` ディレクトリが用意されており、それらの読み込みは[アプリケーションブートローダー |application:bootstrapping#DIコンテナの設定]が担当します。 この記事は、Nette のライブラリを 1 つだけ使用し、設定ファイルの機能を利用したいユーザー向けです。 -設定ファイルは通常[NEON 形式|neon:format]で記述され、[サポートされているエディタ |best-practices:editors-and-tools#IDEエディタ]で編集するのが最適です。これらはオブジェクトを**作成および設定**する方法の指示として理解できます。したがって、設定の読み込み結果はいわゆるファクトリであり、これはリクエストに応じて使用したい他のオブジェクト(データベース接続など)を作成するオブジェクトです。 +設定ファイルは通常[NEON 形式|neon:format]で記述され、[サポートされているエディタ |tools:ide]で編集するのが最適です。これらはオブジェクトを**作成および設定**する方法の指示として理解できます。したがって、設定の読み込み結果はいわゆるファクトリであり、これはリクエストに応じて使用したい他のオブジェクト(データベース接続など)を作成するオブジェクトです。 このファクトリは*依存関係注入コンテナ*(DI コンテナ)とも呼ばれ、詳細に興味がある場合は[依存関係注入 |dependency-injection:]に関する章をお読みください。 diff --git a/bootstrap/pl/@home.texy b/bootstrap/pl/@home.texy index 5089994f3b..cdddd465a8 100644 --- a/bootstrap/pl/@home.texy +++ b/bootstrap/pl/@home.texy @@ -7,7 +7,7 @@ Poszczególne części Nette ustawiamy za pomocą plików konfiguracyjnych. Poka .[tip] Jeśli używasz całego frameworka, nie trzeba nic więcej robić. W projekcie masz przygotowany katalog `config/` na pliki konfiguracyjne, a ich wczytywaniem zajmuje się [bootloader aplikacji |application:bootstrapping#Konfiguracja kontenera DI]. Ten artykuł jest dla użytkowników, którzy używają tylko jednej biblioteki Nette i chcą wykorzystać możliwości plików konfiguracyjnych. -Pliki konfiguracyjne zazwyczaj zapisuje się w [formacie NEON|neon:format] i najlepiej edytuje się je w [edytorach z jego obsługą |best-practices:editors-and-tools#Edytor IDE]. Można je rozumieć jako instrukcje, jak **tworzyć i konfigurować** obiekty. Zatem wynikiem wczytania konfiguracji będzie tzw. fabryka, czyli obiekt, który na żądanie utworzy nam kolejne obiekty, których chcemy używać. Na przykład połączenie z bazą danych itp. +Pliki konfiguracyjne zazwyczaj zapisuje się w [formacie NEON|neon:format] i najlepiej edytuje się je w [edytorach z jego obsługą |tools:ide]. Można je rozumieć jako instrukcje, jak **tworzyć i konfigurować** obiekty. Zatem wynikiem wczytania konfiguracji będzie tzw. fabryka, czyli obiekt, który na żądanie utworzy nam kolejne obiekty, których chcemy używać. Na przykład połączenie z bazą danych itp. Ta fabryka nazywana jest również *kontenerem dependency injection* (kontenerem DI), a jeśli interesują Cię szczegóły, przeczytaj rozdział o [dependency injection |dependency-injection:]. diff --git a/bootstrap/pt/@home.texy b/bootstrap/pt/@home.texy index 0344fc188a..d08859b9a8 100644 --- a/bootstrap/pt/@home.texy +++ b/bootstrap/pt/@home.texy @@ -7,7 +7,7 @@ Os componentes individuais do Nette são configurados usando arquivos de configu .[tip] Se você estiver usando todo o framework, não há necessidade de fazer mais nada. No seu projeto, você tem um diretório `config/` pré-preparado para arquivos de configuração, e o carregamento deles é responsabilidade do [carregador da aplicação |application:bootstrapping#Configuração do contêiner de DI]. Este artigo é para usuários que usam apenas uma biblioteca Nette e desejam aproveitar as opções dos arquivos de configuração. -Os arquivos de configuração são geralmente escritos no [formato NEON|neon:format] e são melhor editados em [editores com suporte a ele |best-practices:editors-and-tools#Editor IDE]. Eles podem ser entendidos como instruções sobre como **criar e configurar** objetos. Ou seja, o resultado do carregamento da configuração será uma chamada fábrica, que é um objeto que, sob demanda, criará outros objetos que queremos usar. Por exemplo, uma conexão de banco de dados, etc. +Os arquivos de configuração são geralmente escritos no [formato NEON|neon:format] e são melhor editados em [editores com suporte a ele |tools:ide]. Eles podem ser entendidos como instruções sobre como **criar e configurar** objetos. Ou seja, o resultado do carregamento da configuração será uma chamada fábrica, que é um objeto que, sob demanda, criará outros objetos que queremos usar. Por exemplo, uma conexão de banco de dados, etc. Essa fábrica também é chamada de *contêiner de injeção de dependência* (contêiner DI) e, se você estiver interessado em detalhes, leia o capítulo sobre [injeção de dependência |dependency-injection:]. diff --git a/bootstrap/ro/@home.texy b/bootstrap/ro/@home.texy index 16606ee9e5..12893d9b60 100644 --- a/bootstrap/ro/@home.texy +++ b/bootstrap/ro/@home.texy @@ -7,7 +7,7 @@ Componentele individuale Nette sunt configurate folosind fișiere de configurare .[tip] Dacă utilizați întregul framework, nu este nevoie să faceți nimic altceva. În proiect aveți un director `config/` pregătit pentru fișierele de configurare, iar încărcarea lor este gestionată de [încărcătorul aplicației |application:bootstrapping#Configurarea containerului DI]. Acest articol este pentru utilizatorii care folosesc doar o singură bibliotecă Nette și doresc să profite de posibilitățile fișierelor de configurare. -Fișierele de configurare sunt de obicei scrise în [formatul NEON|neon:format] și cel mai bine se editează în [editori cu suport pentru acesta |best-practices:editors-and-tools#Editor IDE]. Ele pot fi înțelese ca instrucțiuni despre cum să **creați și configurați** obiecte. Prin urmare, rezultatul încărcării configurației va fi așa-numita fabrică (factory), care este un obiect ce ne va crea la cerere alte obiecte pe care dorim să le folosim. De exemplu, conexiuni la baze de date etc. +Fișierele de configurare sunt de obicei scrise în [formatul NEON|neon:format] și cel mai bine se editează în [editori cu suport pentru acesta |tools:ide]. Ele pot fi înțelese ca instrucțiuni despre cum să **creați și configurați** obiecte. Prin urmare, rezultatul încărcării configurației va fi așa-numita fabrică (factory), care este un obiect ce ne va crea la cerere alte obiecte pe care dorim să le folosim. De exemplu, conexiuni la baze de date etc. Această fabrică se mai numește și *dependency injection container* (container DI) și, dacă sunteți interesat de detalii, citiți capitolul despre [dependency injection |dependency-injection:]. diff --git a/bootstrap/ru/@home.texy b/bootstrap/ru/@home.texy index ec99937fd8..c91184ed5a 100644 --- a/bootstrap/ru/@home.texy +++ b/bootstrap/ru/@home.texy @@ -7,7 +7,7 @@ Nette Bootstrap .[tip] Если вы используете весь фреймворк, вам не нужно ничего делать. В проекте у вас есть подготовленный каталог `config/` для конфигурационных файлов, и их загрузкой занимается [загрузчик приложения |application:bootstrapping#Конфигурация DI-контейнера]. Эта статья предназначена для пользователей, которые используют только одну библиотеку Nette и хотят воспользоваться возможностями конфигурационных файлов. -Конфигурационные файлы обычно пишутся в [формате NEON|neon:format] и лучше всего редактируются в [редакторах с его поддержкой |best-practices:editors-and-tools#IDE редактор]. Их можно рассматривать как инструкции по **созданию и настройке** объектов. Таким образом, результатом загрузки конфигурации будет так называемая фабрика, то есть объект, который по запросу создаст для нас другие объекты, которые мы хотим использовать. Например, соединение с базой данных и т. д. +Конфигурационные файлы обычно пишутся в [формате NEON|neon:format] и лучше всего редактируются в [редакторах с его поддержкой |tools:ide]. Их можно рассматривать как инструкции по **созданию и настройке** объектов. Таким образом, результатом загрузки конфигурации будет так называемая фабрика, то есть объект, который по запросу создаст для нас другие объекты, которые мы хотим использовать. Например, соединение с базой данных и т. д. Эта фабрика также называется *контейнером внедрения зависимостей* (DI container), и если вас интересуют подробности, прочитайте главу о [внедрении зависимостей |dependency-injection:]. diff --git a/bootstrap/sl/@home.texy b/bootstrap/sl/@home.texy index 76641a1cce..23868a18ef 100644 --- a/bootstrap/sl/@home.texy +++ b/bootstrap/sl/@home.texy @@ -7,7 +7,7 @@ Posamezne komponente Nette nastavljamo s pomočjo konfiguracijskih datotek. Poka .[tip] Če uporabljate celotno ogrodje, ni treba storiti ničesar dodatnega. V projektu imate za konfiguracijske datoteke pripravljen imenik `config/` in za njihovo nalaganje skrbi [zavajalec aplikacije |application:bootstrapping#Konfiguracija DI vsebnika]. Ta članek je za uporabnike, ki uporabljajo samo eno knjižnico Nette in želijo izkoristiti možnosti konfiguracijskih datotek. -Konfiguracijske datoteke se običajno pišejo v [formatu NEON|neon:format] in se najbolje urejajo v [urejevalnikih z njegovo podporo |best-practices:editors-and-tools#IDE urejevalnik]. Lahko jih razumemo kot navodila, kako **ustvarjati in konfigurirati** objekte. Torej bo rezultat nalaganja konfiguracije tako imenovana tovarna, kar je objekt, ki nam na zahtevo ustvari druge objekte, ki jih želimo uporabljati. Na primer povezavo s podatkovno bazo itd. +Konfiguracijske datoteke se običajno pišejo v [formatu NEON|neon:format] in se najbolje urejajo v [urejevalnikih z njegovo podporo |tools:ide]. Lahko jih razumemo kot navodila, kako **ustvarjati in konfigurirati** objekte. Torej bo rezultat nalaganja konfiguracije tako imenovana tovarna, kar je objekt, ki nam na zahtevo ustvari druge objekte, ki jih želimo uporabljati. Na primer povezavo s podatkovno bazo itd. Tej tovarni se tudi reče *dependency injection vsebnik* (DI vsebnik) in če vas zanimajo podrobnosti, preberite poglavje o [dependency injection |dependency-injection:]. diff --git a/bootstrap/tr/@home.texy b/bootstrap/tr/@home.texy index 732122fed8..94298ab84a 100644 --- a/bootstrap/tr/@home.texy +++ b/bootstrap/tr/@home.texy @@ -7,7 +7,7 @@ Nette'nin bireysel bileşenlerini yapılandırma dosyaları kullanarak ayarlıyo .[tip] Eğer tüm framework'ü kullanıyorsanız, başka bir şey yapmanıza gerek yoktur. Projenizde yapılandırma dosyaları için önceden hazırlanmış bir `config/` dizini bulunur ve bunların yüklenmesinden [uygulama yükleyicisi |application:bootstrapping#DI Konteyner Yapılandırması] sorumludur. Bu makale, yalnızca bir Nette kütüphanesi kullanan ve yapılandırma dosyalarının olanaklarından yararlanmak isteyen kullanıcılar içindir. -Yapılandırma dosyaları genellikle [NEON formatında|neon:format] yazılır ve en iyi şekilde [destekleyen düzenleyicilerde |best-practices:editors-and-tools#IDE Editörü] düzenlenir. Bunları, nesnelerin **nasıl oluşturulacağı ve yapılandırılacağı** konusunda talimatlar olarak düşünebiliriz. Yani, yapılandırmanın yüklenmesinin sonucu, istek üzerine kullanmak istediğimiz diğer nesneleri (örneğin, veritabanı bağlantısı vb.) oluşturacak olan fabrika olarak adlandırılan bir nesne olacaktır. +Yapılandırma dosyaları genellikle [NEON formatında|neon:format] yazılır ve en iyi şekilde [destekleyen düzenleyicilerde |tools:ide] düzenlenir. Bunları, nesnelerin **nasıl oluşturulacağı ve yapılandırılacağı** konusunda talimatlar olarak düşünebiliriz. Yani, yapılandırmanın yüklenmesinin sonucu, istek üzerine kullanmak istediğimiz diğer nesneleri (örneğin, veritabanı bağlantısı vb.) oluşturacak olan fabrika olarak adlandırılan bir nesne olacaktır. Bu fabrikaya aynı zamanda *dependency injection konteyneri* (DI konteyneri) denir ve ayrıntılarla ilgileniyorsanız, [dependency injection |dependency-injection:] bölümünü okuyun. diff --git a/bootstrap/uk/@home.texy b/bootstrap/uk/@home.texy index 1320bdf9fa..4561b0fe34 100644 --- a/bootstrap/uk/@home.texy +++ b/bootstrap/uk/@home.texy @@ -7,7 +7,7 @@ Nette Bootstrap .[tip] Якщо ви використовуєте весь фреймворк, нічого додаткового робити не потрібно. У проекті є підготовлений каталог `config/` для конфігураційних файлів, а за їх завантаження відповідає [завантажувач застосунку |application:bootstrapping#Конфігурація DI-контейнера]. Ця стаття призначена для користувачів, які використовують лише одну бібліотеку Nette і хочуть скористатися можливостями конфігураційних файлів. -Конфігураційні файли зазвичай записуються у [форматі NEON|neon:format] і найкраще редагуються в [редакторах з його підтримкою |best-practices:editors-and-tools#IDE редактор]. Їх можна розглядати як інструкції щодо **створення та конфігурації** об'єктів. Отже, результатом завантаження конфігурації буде так звана фабрика, тобто об'єкт, який за запитом створить для нас інші об'єкти, які ми хочемо використовувати. Наприклад, з'єднання з базою даних тощо. +Конфігураційні файли зазвичай записуються у [форматі NEON|neon:format] і найкраще редагуються в [редакторах з його підтримкою |tools:ide]. Їх можна розглядати як інструкції щодо **створення та конфігурації** об'єктів. Отже, результатом завантаження конфігурації буде так звана фабрика, тобто об'єкт, який за запитом створить для нас інші об'єкти, які ми хочемо використовувати. Наприклад, з'єднання з базою даних тощо. Ця фабрика також називається *dependency injection контейнером* (DI container), і якщо вас цікавлять подробиці, прочитайте розділ про [dependency injection |dependency-injection:]. diff --git a/dependency-injection/bg/configuration.texy b/dependency-injection/bg/configuration.texy index 3f6bf580ca..fc5cf4c0db 100644 --- a/dependency-injection/bg/configuration.texy +++ b/dependency-injection/bg/configuration.texy @@ -8,7 +8,7 @@ Конфигурационен файл ==================== -Nette DI контейнерът се управлява лесно с помощта на конфигурационни файлове. Те обикновено се записват във [формат NEON|neon:format]. За редактиране препоръчваме [редактори с поддръжка |best-practices:editors-and-tools#IDE редактор] на този формат. +Nette DI контейнерът се управлява лесно с помощта на конфигурационни файлове. Те обикновено се записват във [формат NEON|neon:format]. За редактиране препоръчваме [редактори с поддръжка |tools:ide] на този формат. <pre> "decorator .[prism-token prism-atrule]":[#Decorator]: "Декоратор .[prism-token prism-comment]"<br> diff --git a/dependency-injection/cs/configuration.texy b/dependency-injection/cs/configuration.texy index d89e0ab829..07c89b97b0 100644 --- a/dependency-injection/cs/configuration.texy +++ b/dependency-injection/cs/configuration.texy @@ -8,7 +8,7 @@ Přehled konfiguračních voleb pro Nette DI kontejner. Konfigurační soubor =================== -Nette DI kontejner se snadno ovládá pomocí konfiguračních souborů. Ty se obvykle zapisují ve [formátu NEON|neon:format]. K editaci doporučujeme [editory s podporou |best-practices:editors-and-tools#IDE editor] tohoto formátu. +Nette DI kontejner se snadno ovládá pomocí konfiguračních souborů. Ty se obvykle zapisují ve [formátu NEON|neon:format]. K editaci doporučujeme [editory s podporou |tools:ide] tohoto formátu. <pre> "decorator .[prism-token prism-atrule]":[#decorator]: "Dekorátor .[prism-token prism-comment]"<br> diff --git a/dependency-injection/de/configuration.texy b/dependency-injection/de/configuration.texy index 27e564e3b5..5eeed62bf7 100644 --- a/dependency-injection/de/configuration.texy +++ b/dependency-injection/de/configuration.texy @@ -8,7 +8,7 @@ Konfiguration des DI-Containers Konfigurationsdatei =================== -Der Nette DI Container lässt sich leicht über Konfigurationsdateien steuern. Diese werden normalerweise im [NEON-Format|neon:format] geschrieben. Zur Bearbeitung empfehlen wir [Editoren mit Unterstützung |best-practices:editors-and-tools#IDE-Editor] für dieses Format. +Der Nette DI Container lässt sich leicht über Konfigurationsdateien steuern. Diese werden normalerweise im [NEON-Format|neon:format] geschrieben. Zur Bearbeitung empfehlen wir [Editoren mit Unterstützung |tools:ide] für dieses Format. <pre> "decorator .[prism-token prism-atrule]":[#Decorator]: "Decorator .[prism-token prism-comment]"<br> diff --git a/dependency-injection/el/configuration.texy b/dependency-injection/el/configuration.texy index 03e6ecb64d..a90b11cf1f 100644 --- a/dependency-injection/el/configuration.texy +++ b/dependency-injection/el/configuration.texy @@ -8,7 +8,7 @@ Αρχείο διαμόρφωσης ================== -Το Nette DI Container ελέγχεται εύκολα μέσω αρχείων διαμόρφωσης. Αυτά συνήθως γράφονται σε [μορφή NEON |neon:format]. Για την επεξεργασία, συνιστούμε [editors με υποστήριξη |best-practices:editors-and-tools#IDE editor] αυτής της μορφής. +Το Nette DI Container ελέγχεται εύκολα μέσω αρχείων διαμόρφωσης. Αυτά συνήθως γράφονται σε [μορφή NEON |neon:format]. Για την επεξεργασία, συνιστούμε [editors με υποστήριξη |tools:ide] αυτής της μορφής. <pre> "decorator .[prism-token prism-atrule]":[#decorator]: "Decorator .[prism-token prism-comment]"<br> diff --git a/dependency-injection/en/configuration.texy b/dependency-injection/en/configuration.texy index 7f42e4bc97..ba876eb354 100644 --- a/dependency-injection/en/configuration.texy +++ b/dependency-injection/en/configuration.texy @@ -8,7 +8,7 @@ Overview of configuration options for the Nette DI container. Configuration File ================== -The Nette DI container is easily controlled using configuration files. These are usually written in the [NEON format|neon:format]. We recommend using [editors with support |best-practices:editors-and-tools#IDE Editor] for this format. +The Nette DI container is easily controlled using configuration files. These are usually written in the [NEON format|neon:format]. We recommend using [editors with support |tools:ide] for this format. <pre> "decorator .[prism-token prism-atrule]":[#Decorator]: "Decorator .[prism-token prism-comment]"<br> diff --git a/dependency-injection/es/configuration.texy b/dependency-injection/es/configuration.texy index 8d3c0151ae..c4ab65c181 100644 --- a/dependency-injection/es/configuration.texy +++ b/dependency-injection/es/configuration.texy @@ -8,7 +8,7 @@ Resumen de las opciones de configuración para el contenedor Nette DI. Archivo de configuración ======================== -El contenedor Nette DI se controla fácilmente mediante archivos de configuración. Normalmente se escriben en [formato NEON |neon:format]. Para la edición, recomendamos [editores con soporte |best-practices:editors-and-tools#Editor IDE] para este formato. +El contenedor Nette DI se controla fácilmente mediante archivos de configuración. Normalmente se escriben en [formato NEON |neon:format]. Para la edición, recomendamos [editores con soporte |tools:ide] para este formato. <pre> "decorator .[prism-token prism-atrule]":[#decorator]: "Decorador .[prism-token prism-comment]"<br> diff --git a/dependency-injection/fr/configuration.texy b/dependency-injection/fr/configuration.texy index a5167ac052..8b37bad212 100644 --- a/dependency-injection/fr/configuration.texy +++ b/dependency-injection/fr/configuration.texy @@ -8,7 +8,7 @@ Aperçu des options de configuration pour le conteneur Nette DI. Fichier de configuration ======================== -Le conteneur Nette DI est facilement contrôlé à l'aide de fichiers de configuration. Ceux-ci sont généralement écrits au [format NEON |neon:format]. Pour l'édition, nous recommandons des [éditeurs avec support |best-practices:editors-and-tools#Éditeur IDE] pour ce format. +Le conteneur Nette DI est facilement contrôlé à l'aide de fichiers de configuration. Ceux-ci sont généralement écrits au [format NEON |neon:format]. Pour l'édition, nous recommandons des [éditeurs avec support |tools:ide] pour ce format. <pre> "decorator .[prism-token prism-atrule]":[#Decorator]: "Décorateur .[prism-token prism-comment]"<br> diff --git a/dependency-injection/hu/configuration.texy b/dependency-injection/hu/configuration.texy index a4f889fa85..86547cb880 100644 --- a/dependency-injection/hu/configuration.texy +++ b/dependency-injection/hu/configuration.texy @@ -8,7 +8,7 @@ A Nette DI konténer konfigurációs opcióinak áttekintése. Konfigurációs fájl ================== -A Nette DI konténer könnyen vezérelhető konfigurációs fájlok segítségével. Ezek általában [NEON formátumban|neon:format] íródnak. A szerkesztéshez [támogatással rendelkező szerkesztőket |best-practices:editors-and-tools#IDE szerkesztő] ajánlunk ehhez a formátumhoz. +A Nette DI konténer könnyen vezérelhető konfigurációs fájlok segítségével. Ezek általában [NEON formátumban|neon:format] íródnak. A szerkesztéshez [támogatással rendelkező szerkesztőket |tools:ide] ajánlunk ehhez a formátumhoz. <pre> "decorator .[prism-token prism-atrule]":[#Decorator]: "Dekorátor .[prism-token prism-comment]"<br> diff --git a/dependency-injection/it/configuration.texy b/dependency-injection/it/configuration.texy index 7155ff7ebf..2b484c11b2 100644 --- a/dependency-injection/it/configuration.texy +++ b/dependency-injection/it/configuration.texy @@ -8,7 +8,7 @@ Panoramica delle opzioni di configurazione per il container Nette DI. File di configurazione ====================== -Il container Nette DI è facilmente controllabile tramite file di configurazione. Questi sono solitamente scritti nel [formato NEON|neon:format]. Per la modifica, consigliamo [editor con supporto |best-practices:editors-and-tools#Editor IDE] per questo formato. +Il container Nette DI è facilmente controllabile tramite file di configurazione. Questi sono solitamente scritti nel [formato NEON|neon:format]. Per la modifica, consigliamo [editor con supporto |tools:ide] per questo formato. <pre> "decorator .[prism-token prism-atrule]":[#Decorator]: "Decorator .[prism-token prism-comment]"<br> diff --git a/dependency-injection/ja/configuration.texy b/dependency-injection/ja/configuration.texy index b9510329cf..f6c4f5403e 100644 --- a/dependency-injection/ja/configuration.texy +++ b/dependency-injection/ja/configuration.texy @@ -8,7 +8,7 @@ Nette DIコンテナの設定オプションの概要。 設定ファイル ====== -Nette DIコンテナは、設定ファイルを使用して簡単に制御できます。これらは通常、[NEON形式|neon:format]で記述されます。編集には、この形式を[サポートするエディタ |best-practices:editors-and-tools#IDEエディタ]をお勧めします。 +Nette DIコンテナは、設定ファイルを使用して簡単に制御できます。これらは通常、[NEON形式|neon:format]で記述されます。編集には、この形式を[サポートするエディタ |tools:ide]をお勧めします。 <pre> "decorator .[prism-token prism-atrule]":[#decorator]: "デコレータ .[prism-token prism-comment]"<br> diff --git a/dependency-injection/pl/configuration.texy b/dependency-injection/pl/configuration.texy index d56a300da7..f487322922 100644 --- a/dependency-injection/pl/configuration.texy +++ b/dependency-injection/pl/configuration.texy @@ -8,7 +8,7 @@ Przegląd opcji konfiguracyjnych dla kontenera Nette DI. Plik konfiguracyjny =================== -Kontener Nette DI łatwo się kontroluje za pomocą plików konfiguracyjnych. Zazwyczaj są one zapisywane w [formacie NEON|neon:format]. Do edycji polecamy [edytory z obsługą |best-practices:editors-and-tools#Edytor IDE] tego formatu. +Kontener Nette DI łatwo się kontroluje za pomocą plików konfiguracyjnych. Zazwyczaj są one zapisywane w [formacie NEON|neon:format]. Do edycji polecamy [edytory z obsługą |tools:ide] tego formatu. <pre> "decorator .[prism-token prism-atrule]":[#decorator]: "Dekorator .[prism-token prism-comment]"<br> diff --git a/dependency-injection/pt/configuration.texy b/dependency-injection/pt/configuration.texy index e22c943046..000779a38b 100644 --- a/dependency-injection/pt/configuration.texy +++ b/dependency-injection/pt/configuration.texy @@ -8,7 +8,7 @@ Visão geral das opções de configuração para o contêiner Nette DI. Arquivo de Configuração ======================= -O contêiner Nette DI é facilmente controlado por meio de arquivos de configuração. Eles geralmente são escritos no [formato NEON|neon:format]. Para edição, recomendamos [editores com suporte |best-practices:editors-and-tools#Editor IDE] para este formato. +O contêiner Nette DI é facilmente controlado por meio de arquivos de configuração. Eles geralmente são escritos no [formato NEON|neon:format]. Para edição, recomendamos [editores com suporte |tools:ide] para este formato. <pre> "decorator .[prism-token prism-atrule]":[#decorator]: "Decorador .[prism-token prism-comment]"<br> diff --git a/dependency-injection/ro/configuration.texy b/dependency-injection/ro/configuration.texy index c78aeade7a..250662de49 100644 --- a/dependency-injection/ro/configuration.texy +++ b/dependency-injection/ro/configuration.texy @@ -8,7 +8,7 @@ Prezentare generală a opțiunilor de configurare pentru containerul Nette DI. Fișier de configurare ===================== -Containerul Nette DI este ușor de controlat folosind fișiere de configurare. Acestea sunt de obicei scrise în [formatul NEON |neon:format]. Pentru editare, recomandăm [editoare cu suport |best-practices:editors-and-tools#Editor IDE] pentru acest format. +Containerul Nette DI este ușor de controlat folosind fișiere de configurare. Acestea sunt de obicei scrise în [formatul NEON |neon:format]. Pentru editare, recomandăm [editoare cu suport |tools:ide] pentru acest format. <pre> "decorator .[prism-token prism-atrule]":[#decorator]: "Decorator .[prism-token prism-comment]"<br> diff --git a/dependency-injection/ru/configuration.texy b/dependency-injection/ru/configuration.texy index bc18331de9..c7fad100ee 100644 --- a/dependency-injection/ru/configuration.texy +++ b/dependency-injection/ru/configuration.texy @@ -8,7 +8,7 @@ Файл конфигурации ================= -DI-контейнер Nette легко управляется с помощью файлов конфигурации. Они обычно записываются в [формате NEON |neon:format]. Для редактирования рекомендуем [редакторы с поддержкой |best-practices:editors-and-tools#IDE редактор] этого формата. +DI-контейнер Nette легко управляется с помощью файлов конфигурации. Они обычно записываются в [формате NEON |neon:format]. Для редактирования рекомендуем [редакторы с поддержкой |tools:ide] этого формата. <pre> "decorator .[prism-token prism-atrule]":[#decorator]: "Декоратор .[prism-token prism-comment]"<br> diff --git a/dependency-injection/sl/configuration.texy b/dependency-injection/sl/configuration.texy index d4b773c1a5..f025ad8f51 100644 --- a/dependency-injection/sl/configuration.texy +++ b/dependency-injection/sl/configuration.texy @@ -8,7 +8,7 @@ Pregled konfiguracijskih možnosti za Nette DI vsebnik. Konfiguracijska datoteka ======================== -Nette DI vsebnik se enostavno upravlja s konfiguracijskimi datotekami. Te se običajno zapisujejo v [formatu NEON|neon:format]. Za urejanje priporočamo [urejevalnike s podporo |best-practices:editors-and-tools#IDE urejevalnik] za ta format. +Nette DI vsebnik se enostavno upravlja s konfiguracijskimi datotekami. Te se običajno zapisujejo v [formatu NEON|neon:format]. Za urejanje priporočamo [urejevalnike s podporo |tools:ide] za ta format. <pre> "decorator .[prism-token prism-atrule]":[#decorator]: "Dekorator .[prism-token prism-comment]"<br> diff --git a/dependency-injection/tr/configuration.texy b/dependency-injection/tr/configuration.texy index 41b28cddb2..4745a572c6 100644 --- a/dependency-injection/tr/configuration.texy +++ b/dependency-injection/tr/configuration.texy @@ -8,7 +8,7 @@ Nette DI konteyneri için yapılandırma seçeneklerine genel bakış. Yapılandırma Dosyası ==================== -Nette DI konteyneri, yapılandırma dosyaları aracılığıyla kolayca kontrol edilir. Bunlar genellikle [NEON formatı |neon:format] kullanılarak yazılır. Düzenleme için bu formatı [destekleyen düzenleyiciler |best-practices:editors-and-tools#IDE Editörü] öneririz. +Nette DI konteyneri, yapılandırma dosyaları aracılığıyla kolayca kontrol edilir. Bunlar genellikle [NEON formatı |neon:format] kullanılarak yazılır. Düzenleme için bu formatı [destekleyen düzenleyiciler |tools:ide] öneririz. <pre> "decorator .[prism-token prism-atrule]":[#Dekoratör Decorator]: "Dekoratör .[prism-token prism-comment]"<br> diff --git a/dependency-injection/uk/configuration.texy b/dependency-injection/uk/configuration.texy index be8b7c4869..fecac3fb0c 100644 --- a/dependency-injection/uk/configuration.texy +++ b/dependency-injection/uk/configuration.texy @@ -8,7 +8,7 @@ Конфігураційний файл ==================== -Nette DI-контейнер легко керується за допомогою конфігураційних файлів. Вони зазвичай записуються у [форматі NEON|neon:format]. Для редагування рекомендуємо [редактори з підтримкою |best-practices:editors-and-tools#IDE редактор] цього формату. +Nette DI-контейнер легко керується за допомогою конфігураційних файлів. Вони зазвичай записуються у [форматі NEON|neon:format]. Для редагування рекомендуємо [редактори з підтримкою |tools:ide] цього формату. <pre> "decorator .[prism-token prism-atrule]":[#decorator]: "Декоратор .[prism-token prism-comment]"<br> diff --git a/nette/bg/configuring.texy b/nette/bg/configuring.texy index 1f8be0e9b4..849468fd82 100644 --- a/nette/bg/configuring.texy +++ b/nette/bg/configuring.texy @@ -4,7 +4,7 @@ .[perex] Преглед на всички опции за конфигурация в Nette Framework. -Компонентите на Nette се настройват с помощта на конфигурационни файлове, които обикновено се записват във [формат NEON|neon:format]. Най-добре се редактират в [редактори с неговата поддръжка |best-practices:editors-and-tools#IDE редактор]. Ако използвате целия framework, конфигурацията се [зарежда при стартиране на приложението |application:bootstrapping#Конфигурация на DI контейнера], ако не, прочетете [как да заредите конфигурацията|bootstrap:]. +Компонентите на Nette се настройват с помощта на конфигурационни файлове, които обикновено се записват във [формат NEON|neon:format]. Най-добре се редактират в [редактори с неговата поддръжка |tools:ide]. Ако използвате целия framework, конфигурацията се [зарежда при стартиране на приложението |application:bootstrapping#Конфигурация на DI контейнера], ако не, прочетете [как да заредите конфигурацията|bootstrap:]. <pre> "application .[prism-token prism-atrule]":[application:configuration#Application]: "Приложение .[prism-token prism-comment]"<br> diff --git a/nette/cs/configuring.texy b/nette/cs/configuring.texy index e5ac8533e7..aea1f00f7c 100644 --- a/nette/cs/configuring.texy +++ b/nette/cs/configuring.texy @@ -4,7 +4,7 @@ Konfigurace Nette .[perex] Přehled všech konfiguračních voleb v Nette Frameworku. -Součásti Nette nastavujeme pomocí konfiguračních souborů, které se obvykle zapisují ve [formátu NEON|neon:format]. Nejlépe se upravují v [editorech s jeho podporou |best-practices:editors-and-tools#IDE editor]. Pokud používate celý framework, konfigurace se [načte při zavádění aplikace |application:bootstrapping#Konfigurace DI kontejneru], pokud ne, přečtěte si, [jak konfiguraci načíst|bootstrap:]. +Součásti Nette nastavujeme pomocí konfiguračních souborů, které se obvykle zapisují ve [formátu NEON|neon:format]. Nejlépe se upravují v [editorech s jeho podporou |tools:ide]. Pokud používate celý framework, konfigurace se [načte při zavádění aplikace |application:bootstrapping#Konfigurace DI kontejneru], pokud ne, přečtěte si, [jak konfiguraci načíst|bootstrap:]. <pre> "application .[prism-token prism-atrule]":[application:configuration#Application]: "Application .[prism-token prism-comment]"<br> diff --git a/nette/de/configuring.texy b/nette/de/configuring.texy index 43c2e10075..26df6ea07a 100644 --- a/nette/de/configuring.texy +++ b/nette/de/configuring.texy @@ -4,7 +4,7 @@ Konfiguration von Nette .[perex] Übersicht über alle Konfigurationsoptionen im Nette Framework. -Nette-Komponenten werden über Konfigurationsdateien konfiguriert, die üblicherweise im [NEON-Format|neon:format] geschrieben werden. Am besten bearbeitet man sie in [Editoren mit NEON-Unterstützung |best-practices:editors-and-tools#IDE-Editor]. Wenn Sie das gesamte Framework verwenden, wird die Konfiguration [beim Booten der Anwendung geladen |application:bootstrapping#Konfiguration des DI-Containers], andernfalls lesen Sie, [wie die Konfiguration geladen wird|bootstrap:]. +Nette-Komponenten werden über Konfigurationsdateien konfiguriert, die üblicherweise im [NEON-Format|neon:format] geschrieben werden. Am besten bearbeitet man sie in [Editoren mit NEON-Unterstützung |tools:ide]. Wenn Sie das gesamte Framework verwenden, wird die Konfiguration [beim Booten der Anwendung geladen |application:bootstrapping#Konfiguration des DI-Containers], andernfalls lesen Sie, [wie die Konfiguration geladen wird|bootstrap:]. <pre> "application .[prism-token prism-atrule]":[application:configuration#Application]: "Application .[prism-token prism-comment]"<br> diff --git a/nette/el/configuring.texy b/nette/el/configuring.texy index 96abd9ee39..145f520766 100644 --- a/nette/el/configuring.texy +++ b/nette/el/configuring.texy @@ -4,7 +4,7 @@ .[perex] Επισκόπηση όλων των επιλογών διαμόρφωσης στο Nette Framework. -Ρυθμίζουμε τα στοιχεία του Nette χρησιμοποιώντας αρχεία διαμόρφωσης, τα οποία συνήθως γράφονται σε [μορφή NEON|neon:format]. Ο καλύτερος τρόπος επεξεργασίας τους είναι σε [επεξεργαστές με υποστήριξη για αυτό |best-practices:editors-and-tools#IDE editor]. Αν χρησιμοποιείτε ολόκληρο το framework, η διαμόρφωση [φορτώνεται κατά την εκκίνηση της εφαρμογής |application:bootstrapping#Διαμόρφωση του DI Container], αν όχι, διαβάστε [πώς να φορτώσετε τη διαμόρφωση|bootstrap:]. +Ρυθμίζουμε τα στοιχεία του Nette χρησιμοποιώντας αρχεία διαμόρφωσης, τα οποία συνήθως γράφονται σε [μορφή NEON|neon:format]. Ο καλύτερος τρόπος επεξεργασίας τους είναι σε [επεξεργαστές με υποστήριξη για αυτό |tools:ide]. Αν χρησιμοποιείτε ολόκληρο το framework, η διαμόρφωση [φορτώνεται κατά την εκκίνηση της εφαρμογής |application:bootstrapping#Διαμόρφωση του DI Container], αν όχι, διαβάστε [πώς να φορτώσετε τη διαμόρφωση|bootstrap:]. <pre> "application .[prism-token prism-atrule]":[application:configuration#Application]: "Εφαρμογή .[prism-token prism-comment]"<br> diff --git a/nette/en/configuring.texy b/nette/en/configuring.texy index 4ad1b73150..dd38054fa4 100644 --- a/nette/en/configuring.texy +++ b/nette/en/configuring.texy @@ -4,7 +4,7 @@ Configuring Nette .[perex] An overview of all configuration options in the Nette Framework. -Nette components are configured using configuration files, which are usually written in the [NEON format|neon:format]. They are best edited in [editors that support it |best-practices:editors-and-tools#IDE Editor]. If you are using the full framework, the configuration will be [loaded during application boot |application:bootstrapping#DI Container Configuration]; if not, read [how to load the configuration|bootstrap:]. +Nette components are configured using configuration files, which are usually written in the [NEON format|neon:format]. They are best edited in [editors that support it |tools:ide]. If you are using the full framework, the configuration will be [loaded during application boot |application:bootstrapping#DI Container Configuration]; if not, read [how to load the configuration|bootstrap:]. <pre> "application .[prism-token prism-atrule]":[application:configuration#Application]: "Application .[prism-token prism-comment]"<br> diff --git a/nette/es/configuring.texy b/nette/es/configuring.texy index 1ad6725a1d..2d361272ef 100644 --- a/nette/es/configuring.texy +++ b/nette/es/configuring.texy @@ -4,7 +4,7 @@ Configuración de Nette .[perex] Resumen de todas las opciones de configuración en Nette Framework. -Los componentes de Nette se configuran mediante archivos de configuración, que generalmente se escriben en [formato NEON|neon:format]. Se editan mejor en [editores con soporte para ello |best-practices:editors-and-tools#Editor IDE]. Si utiliza todo el framework, la configuración se [carga al iniciar la aplicación |application:bootstrapping#Configuración del contenedor DI], si no, lea [cómo cargar la configuración|bootstrap:]. +Los componentes de Nette se configuran mediante archivos de configuración, que generalmente se escriben en [formato NEON|neon:format]. Se editan mejor en [editores con soporte para ello |tools:ide]. Si utiliza todo el framework, la configuración se [carga al iniciar la aplicación |application:bootstrapping#Configuración del contenedor DI], si no, lea [cómo cargar la configuración|bootstrap:]. <pre> "application .[prism-token prism-atrule]":[application:configuration#Application]: "Aplicación .[prism-token prism-comment]"<br> diff --git a/nette/fr/configuring.texy b/nette/fr/configuring.texy index 316dd95a69..a2010c540d 100644 --- a/nette/fr/configuring.texy +++ b/nette/fr/configuring.texy @@ -4,7 +4,7 @@ Configuration de Nette .[perex] Aperçu de toutes les options de configuration dans Nette Framework. -Nous configurons les composants Nette à l'aide de fichiers de configuration, qui sont généralement écrits au [format NEON|neon:format]. Il est préférable de les éditer dans des [éditeurs le supportant |best-practices:editors-and-tools#Éditeur IDE]. Si vous utilisez l'ensemble du framework, la configuration est [chargée lors du démarrage de l'application |application:bootstrapping#Configuration du Conteneur DI], sinon, lisez [comment charger la configuration|bootstrap:]. +Nous configurons les composants Nette à l'aide de fichiers de configuration, qui sont généralement écrits au [format NEON|neon:format]. Il est préférable de les éditer dans des [éditeurs le supportant |tools:ide]. Si vous utilisez l'ensemble du framework, la configuration est [chargée lors du démarrage de l'application |application:bootstrapping#Configuration du Conteneur DI], sinon, lisez [comment charger la configuration|bootstrap:]. <pre> "application .[prism-token prism-atrule]":[application:configuration#Application]: "Application .[prism-token prism-comment]"<br> diff --git a/nette/hu/configuring.texy b/nette/hu/configuring.texy index 1c10c22485..bb6015bedb 100644 --- a/nette/hu/configuring.texy +++ b/nette/hu/configuring.texy @@ -4,7 +4,7 @@ Nette Konfiguráció .[perex] A Nette Framework összes konfigurációs opciójának áttekintése. -A Nette komponenseit konfigurációs fájlok segítségével állítjuk be, amelyeket általában [NEON formátumban|neon:format] írunk. Legjobban a [NEON-t támogató szerkesztőkben |best-practices:editors-and-tools#IDE szerkesztő] szerkeszthetők. Ha a teljes keretrendszert használja, a konfiguráció [az alkalmazás indításakor töltődik be |application:bootstrapping#DI konténer konfigurálása], ha nem, olvassa el, [hogyan kell betölteni a konfigurációt|bootstrap:]. +A Nette komponenseit konfigurációs fájlok segítségével állítjuk be, amelyeket általában [NEON formátumban|neon:format] írunk. Legjobban a [NEON-t támogató szerkesztőkben |tools:ide] szerkeszthetők. Ha a teljes keretrendszert használja, a konfiguráció [az alkalmazás indításakor töltődik be |application:bootstrapping#DI konténer konfigurálása], ha nem, olvassa el, [hogyan kell betölteni a konfigurációt|bootstrap:]. <pre> "application .[prism-token prism-atrule]":[application:configuration#Application]: "Application .[prism-token prism-comment]"<br> diff --git a/nette/it/configuring.texy b/nette/it/configuring.texy index 2371ef4a69..bded0deceb 100644 --- a/nette/it/configuring.texy +++ b/nette/it/configuring.texy @@ -4,7 +4,7 @@ Configurazione di Nette .[perex] Panoramica di tutte le opzioni di configurazione in Nette Framework. -Configuriamo i componenti di Nette utilizzando file di configurazione, che di solito sono scritti nel [formato NEON |neon:format]. È meglio modificarli in [editor con supporto |best-practices:editors-and-tools#Editor IDE]. Se si utilizza l'intero framework, la configurazione viene [caricata all'avvio dell'applicazione |application:bootstrapping#Configurazione del Container DI], altrimenti leggete [come caricare la configurazione |bootstrap:]. +Configuriamo i componenti di Nette utilizzando file di configurazione, che di solito sono scritti nel [formato NEON |neon:format]. È meglio modificarli in [editor con supporto |tools:ide]. Se si utilizza l'intero framework, la configurazione viene [caricata all'avvio dell'applicazione |application:bootstrapping#Configurazione del Container DI], altrimenti leggete [come caricare la configurazione |bootstrap:]. <pre> "application .[prism-token prism-atrule]":[application:configuration#Application]: "Applicazione .[prism-token prism-comment]"<br> diff --git a/nette/ja/configuring.texy b/nette/ja/configuring.texy index 842d250bd6..b22e94403b 100644 --- a/nette/ja/configuring.texy +++ b/nette/ja/configuring.texy @@ -4,7 +4,7 @@ Netteの設定 .[perex] Nette Frameworkのすべての設定オプションの概要。 -Netteコンポーネントは、通常[NEON形式 |neon:format]で記述される設定ファイルを使用して設定します。これらを編集する最良の方法は、[サポートされているエディタ |best-practices:editors-and-tools#IDEエディタ]を使用することです。 フレームワーク全体を使用している場合、設定は[アプリケーションのブートストラップ時にロードされます |application:bootstrapping#DIコンテナの設定]。そうでない場合は、[設定をロードする方法 |bootstrap:]をお読みください。 +Netteコンポーネントは、通常[NEON形式 |neon:format]で記述される設定ファイルを使用して設定します。これらを編集する最良の方法は、[サポートされているエディタ |tools:ide]を使用することです。 フレームワーク全体を使用している場合、設定は[アプリケーションのブートストラップ時にロードされます |application:bootstrapping#DIコンテナの設定]。そうでない場合は、[設定をロードする方法 |bootstrap:]をお読みください。 <pre> "application .[prism-token prism-atrule]":[application:configuration#Application]: "アプリケーション .[prism-token prism-comment]"<br> diff --git a/nette/pl/configuring.texy b/nette/pl/configuring.texy index beddca1443..1943f237bf 100644 --- a/nette/pl/configuring.texy +++ b/nette/pl/configuring.texy @@ -4,7 +4,7 @@ Konfiguracja Nette .[perex] Przegląd wszystkich opcji konfiguracyjnych w Nette Framework. -Komponenty Nette konfigurujemy za pomocą plików konfiguracyjnych, które zwykle zapisuje się w [formacie NEON|neon:format]. Najlepiej edytować je w [edytorach z jego obsługą |best-practices:editors-and-tools#Edytor IDE]. Jeśli używasz całego frameworka, konfiguracja zostanie [załadowana podczas uruchamiania aplikacji |application:bootstrapping#Konfiguracja kontenera DI], jeśli nie, przeczytaj, [jak załadować konfigurację|bootstrap:]. +Komponenty Nette konfigurujemy za pomocą plików konfiguracyjnych, które zwykle zapisuje się w [formacie NEON|neon:format]. Najlepiej edytować je w [edytorach z jego obsługą |tools:ide]. Jeśli używasz całego frameworka, konfiguracja zostanie [załadowana podczas uruchamiania aplikacji |application:bootstrapping#Konfiguracja kontenera DI], jeśli nie, przeczytaj, [jak załadować konfigurację|bootstrap:]. <pre> "application .[prism-token prism-atrule]":[application:configuration#Application]: "Aplikacja .[prism-token prism-comment]"<br> diff --git a/nette/pt/configuring.texy b/nette/pt/configuring.texy index f2e874dc10..ddc60c4f98 100644 --- a/nette/pt/configuring.texy +++ b/nette/pt/configuring.texy @@ -4,7 +4,7 @@ Configuração do Nette .[perex] Visão geral de todas as opções de configuração no Nette Framework. -Configuramos os componentes do Nette usando arquivos de configuração, que geralmente são escritos no [formato NEON|neon:format]. A melhor maneira de editá-los é em [editores com suporte |best-practices:editors-and-tools#Editor IDE]. Se você estiver usando o framework completo, a configuração é [carregada durante a inicialização da aplicação |application:bootstrapping#Configuração do contêiner de DI], caso contrário, leia [como carregar a configuração|bootstrap:]. +Configuramos os componentes do Nette usando arquivos de configuração, que geralmente são escritos no [formato NEON|neon:format]. A melhor maneira de editá-los é em [editores com suporte |tools:ide]. Se você estiver usando o framework completo, a configuração é [carregada durante a inicialização da aplicação |application:bootstrapping#Configuração do contêiner de DI], caso contrário, leia [como carregar a configuração|bootstrap:]. <pre> "application .[prism-token prism-atrule]":[application:configuration#Application]: "Aplicação .[prism-token prism-comment]"<br> diff --git a/nette/ro/configuring.texy b/nette/ro/configuring.texy index 750df18f88..b567b5da4d 100644 --- a/nette/ro/configuring.texy +++ b/nette/ro/configuring.texy @@ -4,7 +4,7 @@ Configurarea Nette .[perex] Prezentare generală a tuturor opțiunilor de configurare din Nette Framework. -Componentele Nette sunt configurate folosind fișiere de configurare, care sunt de obicei scrise în [formatul NEON|neon:format]. Cel mai bine se editează în [editoarele cu suport pentru acesta |best-practices:editors-and-tools#Editor IDE]. Dacă utilizați întregul framework, configurația este [încărcată la pornirea aplicației |application:bootstrapping#Configurarea containerului DI], dacă nu, citiți [cum să încărcați configurația|bootstrap:]. +Componentele Nette sunt configurate folosind fișiere de configurare, care sunt de obicei scrise în [formatul NEON|neon:format]. Cel mai bine se editează în [editoarele cu suport pentru acesta |tools:ide]. Dacă utilizați întregul framework, configurația este [încărcată la pornirea aplicației |application:bootstrapping#Configurarea containerului DI], dacă nu, citiți [cum să încărcați configurația|bootstrap:]. <pre> "application .[prism-token prism-atrule]":[application:configuration#Application]: "Aplicație .[prism-token prism-comment]"<br> diff --git a/nette/ru/configuring.texy b/nette/ru/configuring.texy index ccaabbb202..907768efc4 100644 --- a/nette/ru/configuring.texy +++ b/nette/ru/configuring.texy @@ -4,7 +4,7 @@ .[perex] Обзор всех опций конфигурации в Nette Framework. -Компоненты Nette настраиваются с помощью конфигурационных файлов, которые обычно записываются в [формате NEON|neon:format]. Лучше всего их редактировать в [редакторах с его поддержкой |best-practices:editors-and-tools#IDE редактор]. Если вы используете весь фреймворк, конфигурация [загружается при запуске приложения |application:bootstrapping#Конфигурация DI-контейнера], если нет, прочитайте, [как загрузить конфигурацию|bootstrap:]. +Компоненты Nette настраиваются с помощью конфигурационных файлов, которые обычно записываются в [формате NEON|neon:format]. Лучше всего их редактировать в [редакторах с его поддержкой |tools:ide]. Если вы используете весь фреймворк, конфигурация [загружается при запуске приложения |application:bootstrapping#Конфигурация DI-контейнера], если нет, прочитайте, [как загрузить конфигурацию|bootstrap:]. <pre> "application .[prism-token prism-atrule]":[application:configuration#Application]: "Приложение .[prism-token prism-comment]"<br> diff --git a/nette/sl/configuring.texy b/nette/sl/configuring.texy index 212d45b1a7..b6a0a573e2 100644 --- a/nette/sl/configuring.texy +++ b/nette/sl/configuring.texy @@ -4,7 +4,7 @@ Konfiguracija Nette .[perex] Pregled vseh konfiguracijskih možnosti v Nette Frameworku. -Komponente Nette nastavljamo s pomočjo konfiguracijskih datotek, ki se običajno zapisujejo v [formatu NEON|neon:format]. Najbolje se urejajo v [urejevalnikih z njegovo podporo |best-practices:editors-and-tools#IDE urejevalnik]. Če uporabljate celotno ogrodje, se konfiguracija [naloži ob zagonu aplikacije |application:bootstrapping#Konfiguracija DI vsebnika], če ne, preberite, [kako konfiguracijo naložiti|bootstrap:]. +Komponente Nette nastavljamo s pomočjo konfiguracijskih datotek, ki se običajno zapisujejo v [formatu NEON|neon:format]. Najbolje se urejajo v [urejevalnikih z njegovo podporo |tools:ide]. Če uporabljate celotno ogrodje, se konfiguracija [naloži ob zagonu aplikacije |application:bootstrapping#Konfiguracija DI vsebnika], če ne, preberite, [kako konfiguracijo naložiti|bootstrap:]. <pre> "application .[prism-token prism-atrule]":[application:configuration#Application]: "Aplikacija .[prism-token prism-comment]"<br> diff --git a/nette/tr/configuring.texy b/nette/tr/configuring.texy index 347625dcca..94a1e22913 100644 --- a/nette/tr/configuring.texy +++ b/nette/tr/configuring.texy @@ -4,7 +4,7 @@ Nette Yapılandırması .[perex] Nette Framework'teki tüm yapılandırma seçeneklerine genel bakış. -Nette bileşenlerini, genellikle [NEON formatında |neon:format] yazılan yapılandırma dosyaları aracılığıyla ayarlarız. En iyi şekilde [onu destekleyen düzenleyicilerde |best-practices:editors-and-tools#IDE Editörü] düzenlenirler. Tüm framework'ü kullanıyorsanız, yapılandırma [uygulama başlatılırken yüklenir |application:bootstrapping#DI Konteyner Yapılandırması], aksi takdirde [yapılandırmanın nasıl yükleneceği |bootstrap:] bölümünü okuyun. +Nette bileşenlerini, genellikle [NEON formatında |neon:format] yazılan yapılandırma dosyaları aracılığıyla ayarlarız. En iyi şekilde [onu destekleyen düzenleyicilerde |tools:ide] düzenlenirler. Tüm framework'ü kullanıyorsanız, yapılandırma [uygulama başlatılırken yüklenir |application:bootstrapping#DI Konteyner Yapılandırması], aksi takdirde [yapılandırmanın nasıl yükleneceği |bootstrap:] bölümünü okuyun. <pre> "application .[prism-token prism-atrule]":[application:configuration#Application]: "Uygulama .[prism-token prism-comment]"<br> diff --git a/nette/uk/configuring.texy b/nette/uk/configuring.texy index 235090634d..f50226e554 100644 --- a/nette/uk/configuring.texy +++ b/nette/uk/configuring.texy @@ -4,7 +4,7 @@ .[perex] Огляд усіх опцій конфігурації в Nette Framework. -Компоненти Nette налаштовуються за допомогою конфігураційних файлів, які зазвичай записуються у [форматі NEON|neon:format]. Найкраще їх редагувати в [редакторах з його підтримкою |best-practices:editors-and-tools#IDE редактор]. Якщо ви використовуєте весь фреймворк, конфігурація [завантажується під час запуску програми |application:bootstrapping#Конфігурація DI-контейнера], якщо ні, прочитайте, [як завантажити конфігурацію|bootstrap:]. +Компоненти Nette налаштовуються за допомогою конфігураційних файлів, які зазвичай записуються у [форматі NEON|neon:format]. Найкраще їх редагувати в [редакторах з його підтримкою |tools:ide]. Якщо ви використовуєте весь фреймворк, конфігурація [завантажується під час запуску програми |application:bootstrapping#Конфігурація DI-контейнера], якщо ні, прочитайте, [як завантажити конфігурацію|bootstrap:]. <pre> "application .[prism-token prism-atrule]":[application:configuration#Application]: "Додаток .[prism-token prism-comment]"<br> diff --git a/best-practices/bg/editors-and-tools.texy b/tools/bg/ide.texy similarity index 100% rename from best-practices/bg/editors-and-tools.texy rename to tools/bg/ide.texy diff --git a/best-practices/cs/editors-and-tools.texy b/tools/cs/ide.texy similarity index 100% rename from best-practices/cs/editors-and-tools.texy rename to tools/cs/ide.texy diff --git a/best-practices/de/editors-and-tools.texy b/tools/de/ide.texy similarity index 100% rename from best-practices/de/editors-and-tools.texy rename to tools/de/ide.texy diff --git a/best-practices/el/editors-and-tools.texy b/tools/el/ide.texy similarity index 100% rename from best-practices/el/editors-and-tools.texy rename to tools/el/ide.texy diff --git a/best-practices/en/editors-and-tools.texy b/tools/en/ide.texy similarity index 100% rename from best-practices/en/editors-and-tools.texy rename to tools/en/ide.texy diff --git a/best-practices/es/editors-and-tools.texy b/tools/es/ide.texy similarity index 100% rename from best-practices/es/editors-and-tools.texy rename to tools/es/ide.texy diff --git a/best-practices/fr/editors-and-tools.texy b/tools/fr/ide.texy similarity index 100% rename from best-practices/fr/editors-and-tools.texy rename to tools/fr/ide.texy diff --git a/best-practices/hu/editors-and-tools.texy b/tools/hu/ide.texy similarity index 100% rename from best-practices/hu/editors-and-tools.texy rename to tools/hu/ide.texy diff --git a/best-practices/it/editors-and-tools.texy b/tools/it/ide.texy similarity index 100% rename from best-practices/it/editors-and-tools.texy rename to tools/it/ide.texy diff --git a/best-practices/ja/editors-and-tools.texy b/tools/ja/ide.texy similarity index 100% rename from best-practices/ja/editors-and-tools.texy rename to tools/ja/ide.texy diff --git a/best-practices/pl/editors-and-tools.texy b/tools/pl/ide.texy similarity index 100% rename from best-practices/pl/editors-and-tools.texy rename to tools/pl/ide.texy diff --git a/best-practices/pt/editors-and-tools.texy b/tools/pt/ide.texy similarity index 100% rename from best-practices/pt/editors-and-tools.texy rename to tools/pt/ide.texy diff --git a/best-practices/ro/editors-and-tools.texy b/tools/ro/ide.texy similarity index 100% rename from best-practices/ro/editors-and-tools.texy rename to tools/ro/ide.texy diff --git a/best-practices/ru/editors-and-tools.texy b/tools/ru/ide.texy similarity index 100% rename from best-practices/ru/editors-and-tools.texy rename to tools/ru/ide.texy diff --git a/best-practices/sl/editors-and-tools.texy b/tools/sl/ide.texy similarity index 100% rename from best-practices/sl/editors-and-tools.texy rename to tools/sl/ide.texy diff --git a/best-practices/tr/editors-and-tools.texy b/tools/tr/ide.texy similarity index 100% rename from best-practices/tr/editors-and-tools.texy rename to tools/tr/ide.texy diff --git a/best-practices/uk/editors-and-tools.texy b/tools/uk/ide.texy similarity index 100% rename from best-practices/uk/editors-and-tools.texy rename to tools/uk/ide.texy From f2bd79173b3f565c0350b863c924c3bb1efb5dd3 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Sat, 6 Jun 2026 14:46:12 +0200 Subject: [PATCH 40/50] improved code-checker --- tools/bg/code-checker.texy | 75 ++++++++++++++++++++++--------------- tools/cs/code-checker.texy | 72 +++++++++++++++++++++-------------- tools/de/code-checker.texy | 73 ++++++++++++++++++++++-------------- tools/el/code-checker.texy | 73 ++++++++++++++++++++++-------------- tools/en/code-checker.texy | 72 +++++++++++++++++++++-------------- tools/es/code-checker.texy | 71 +++++++++++++++++++++-------------- tools/fr/code-checker.texy | 73 ++++++++++++++++++++++-------------- tools/hu/code-checker.texy | 75 ++++++++++++++++++++++--------------- tools/it/code-checker.texy | 71 +++++++++++++++++++++-------------- tools/ja/code-checker.texy | 77 +++++++++++++++++++++++--------------- tools/pl/code-checker.texy | 75 ++++++++++++++++++++++--------------- tools/pt/code-checker.texy | 73 ++++++++++++++++++++++-------------- tools/ro/code-checker.texy | 71 +++++++++++++++++++++-------------- tools/ru/code-checker.texy | 71 +++++++++++++++++++++-------------- tools/sl/code-checker.texy | 75 ++++++++++++++++++++++--------------- tools/tr/code-checker.texy | 73 ++++++++++++++++++++++-------------- tools/uk/code-checker.texy | 71 +++++++++++++++++++++-------------- 17 files changed, 747 insertions(+), 494 deletions(-) diff --git a/tools/bg/code-checker.texy b/tools/bg/code-checker.texy index f0070378d7..48886e6d1c 100644 --- a/tools/bg/code-checker.texy +++ b/tools/bg/code-checker.texy @@ -2,62 +2,77 @@ Nette Code Checker ****************** .[perex] -Инструментът [Code Checker |https://github.com/nette/code-checker] проверява и евентуално коригира някои от формалните грешки във вашия изходен код. +[Code Checker |https://github.com/nette/code-checker] проверява изходните ви файлове за формални недостатъци като невидим BOM, контролни знаци, повредено кодиране или невалиден синтаксис на PHP, Latte, NEON, JSON и YAML файлове и може да ги поправи автоматично. Инсталация ========== -Code Checker не трябва да се добавя към зависимостите, а да се инсталира като проект. +Инсталирайте го глобално чрез Composer: ```shell -composer create-project nette/code-checker +composer global require nette/code-checker ``` -Или го инсталирайте глобално с помощта на: +Уверете се, че глобалната ви Composer директория `bin` е във [вашия `$PATH` |https://getcomposer.org/doc/03-cli.md#global]. Командата `code-checker` след това е достъпна отвсякъде, на всяка операционна система. + +Като алтернатива го инсталирайте като самостоятелен проект: ```shell -composer global require nette/code-checker +composer create-project nette/code-checker ``` -и се уверете, че вашата глобална директория `vendor/bin` е в [променливата на средата $PATH |https://getcomposer.org/doc/03-cli.md#global]. +Изисква PHP 8.0 или по-нова версия. -Употреба -======== +Използване +========== -``` -Usage: php code-checker [options] +По подразбиране Code Checker работи в режим само за четене и само докладва намерените проблеми: -Options: - -d <path> Folder or file to scan (default: current directory) - -i | --ignore <mask> Files to ignore - -f | --fix Fixes files - -l | --eol Convert newline characters - --no-progress Do not show progress dots - --strict-types Checks whether PHP 7.0 directive strict_types is enabled +```shell +code-checker ``` -Без параметри проверява текущата директория в режим само за четене, с параметъра `-f` коригира файловете. +За да поправите файловете реално, добавете `--fix`. Първо архивирайте файловете си или го стартирайте върху чисто работно дърво, за да можете после да прегледате промените с `git diff`: -Преди да се запознаете с него, определено първо архивирайте файловете си. +```shell +code-checker --fix +``` -За по-лесно стартиране можем да създадем файл `code.bat`: +Можете да ограничите сканирането до конкретен път, да пропуснете файлове или да стартирате по-бърза проверка само на синтаксиса: ```shell -php path_to_Nette_tools\Code-Checker\code-checker %* +code-checker -d src --ignore "temp/*" +code-checker --only-syntax +``` + +В режим само за четене инструментът завършва с код `0`, когато всичко е наред, и `1`, когато бъде намерен какъвто и да е проблем, така че се вписва чудесно в CI процесите. + +Пълен списък на опциите: + +``` +Usage: code-checker [options] + +Options: + -d <path> Folder or file to scan (default: current directory) + -i | --ignore <mask> Files to ignore + -f | --fix Fix the files + -l | --eol Normalize line endings to the system default + --only-syntax Check syntax only (faster) + --no-progress Do not show progress dots + --version Show version ``` -Какво прави всичко това? +Какво прави Code Checker ======================== +- проверява синтаксиса на [Latte |latte:] шаблони и файлове `.php`, `.neon` и `.json` - премахва [BOM |nette:glossary#BOM] -- проверява валидността на [Latte |latte:] шаблони -- проверява валидността на файлове `.neon`, `.php` и `.json` -- проверява за наличието на [контролни знаци |nette:glossary#Контролни знаци] -- проверява дали файлът е кодиран в UTF-8 -- проверява неправилно записани `/* @anotace */` (липсва звездичка) -- премахва завършващия `?>` при PHP файлове -- премахва десните интервали и излишните редове в края на файла -- нормализира разделителите на редове до системните (ако посочите опцията `-l`) +- проверява дали файловете са валиден UTF-8 +- проверява за [контролни знаци |nette:glossary#Контролни знаци] +- разпознава неправилно записани phpDoc коментари (напр. `/* @var` вместо `/** @var`) +- налага отстъп с табулатори във файлове PHP, CSS, JS и TS и с интервали в YAML +- премахва интервалите в края на редовете и празните редове в края на файловете +- нормализира разделителите на редове към системните (с опцията `-l`) diff --git a/tools/cs/code-checker.texy b/tools/cs/code-checker.texy index 8fb389565f..9b0af88f2f 100644 --- a/tools/cs/code-checker.texy +++ b/tools/cs/code-checker.texy @@ -2,63 +2,77 @@ Nette Code Checker ****************** .[perex] -Nástroj [Code Checker |https://github.com/nette/code-checker] zkontroluje a případně opraví některé z formálních chyb ve vašich zdrojových kódech. +[Code Checker |https://github.com/nette/code-checker] zkontroluje vaše zdrojové soubory a najde v nich formální nedostatky, jako je neviditelný BOM, kontrolní znaky, chybné kódování nebo neplatná syntaxe souborů PHP, Latte, NEON, JSON a YAML, a umí je automaticky opravit. Instalace ========= -Code Checker byste neměli přidávat do závislostí, ale instalovat jako projekt. +Nainstalujte jej globálně pomocí Composeru: ```shell -composer create-project nette/code-checker +composer global require nette/code-checker ``` -Nebo jej nainstalujte globálně pomocí: +Ujistěte se, že váš globální Composer adresář `bin` je v [proměnné `$PATH` |https://getcomposer.org/doc/03-cli.md#global]. Příkaz `code-checker` je pak dostupný odkudkoliv, na libovolném operačním systému. + +Případně jej nainstalujte jako samostatný projekt: ```shell -composer global require nette/code-checker +composer create-project nette/code-checker ``` -a ujistěte se, že váš globální adresář `vendor/bin` je v [proměnné prostředí $PATH |https://getcomposer.org/doc/03-cli.md#global]. +Vyžaduje PHP 8.0 nebo vyšší. Použití ======= -``` -Usage: php code-checker [options] +Ve výchozím stavu běží Code Checker v read-only režimu a jen vypíše nalezené problémy: -Options: - -d <path> Folder or file to scan (default: current directory) - -i | --ignore <mask> Files to ignore - -f | --fix Fixes files - -l | --eol Convert newline characters - --no-progress Do not show progress dots - --strict-types Checks whether PHP 7.0 directive strict_types is enabled +```shell +code-checker ``` -Bez parametrů zkontroluje aktuální adresář v read-only režimu, s parametrem `-f` opravuje soubory. +Pro skutečnou opravu souborů přidejte `--fix`. Nejdřív si soubory zazálohujte, nebo nástroj spusťte nad čistým pracovním stromem, ať si změny můžete potom zkontrolovat přes `git diff`: -Než se s ním seznámíte, určitě si soubory nejdřív zazálohujte. +```shell +code-checker --fix +``` -Pro snadnější spouštění si můžeme vytvořit soubor `code.bat`: +Sken můžete omezit na konkrétní cestu, vynechat soubory nebo spustit rychlejší kontrolu jen syntaxe: ```shell -php cesta_k_Nette_tools\Code-Checker\code-checker %* +code-checker -d src --ignore "temp/*" +code-checker --only-syntax +``` + +V read-only režimu skončí nástroj s kódem `0`, když je vše v pořádku, a `1`, když najde jakýkoliv problém, takže se hodí do CI. + +Kompletní seznam voleb: + +``` +Usage: code-checker [options] + +Options: + -d <path> Folder or file to scan (default: current directory) + -i | --ignore <mask> Files to ignore + -f | --fix Fix the files + -l | --eol Normalize line endings to the system default + --only-syntax Check syntax only (faster) + --no-progress Do not show progress dots + --version Show version ``` -Co všechno dělá? -================ +Co Code Checker dělá +==================== +- kontroluje syntaxi [Latte |latte:] šablon a souborů `.php`, `.neon` a `.json` - odstraňuje [BOM |nette:glossary#BOM] -- kontroluje validitu [Latte |latte:] šablon -- kontroluje validitu souborů `.neon`, `.php` a `.json` +- ověřuje, že soubory jsou platné UTF-8 - kontroluje výskyt [kontrolních znaků |nette:glossary#Kontrolní znaky] -- kontroluje, zda je soubor kódován v UTF-8 -- kontroluje chybně zapsané `/* @anotace */` (chybí hvězdička) -- odstraňuje ukončovací `?>` u PHP souborů -- odstraňuje pravostranné mezery a zbytečné řádky na konci souboru -- normalizuje oddělovače řádků na systémové (pokud uvedete volbu `-l`) - +- odhalí chybně zapsané phpDoc komentáře (např. `/* @var` místo `/** @var`) +- vynucuje odsazení tabulátory v souborech PHP, CSS, JS a TS a mezerami v YAML +- odstraňuje pravostranné mezery a prázdné řádky na konci souborů +- normalizuje oddělovače řádků na systémové (s volbou `-l`) diff --git a/tools/de/code-checker.texy b/tools/de/code-checker.texy index 36684e214d..8caefff3d0 100644 --- a/tools/de/code-checker.texy +++ b/tools/de/code-checker.texy @@ -2,62 +2,77 @@ Nette Code Checker ****************** .[perex] -Das Werkzeug [Code Checker |https://github.com/nette/code-checker] überprüft und korrigiert gegebenenfalls einige formale Fehler in Ihrem Quellcode. +[Code Checker |https://github.com/nette/code-checker] überprüft Ihre Quelldateien auf formale Mängel wie ein unsichtbares BOM, Steuerzeichen, fehlerhafte Kodierung oder ungültige Syntax von PHP-, Latte-, NEON-, JSON- und YAML-Dateien und kann diese automatisch beheben. Installation ============ -Code Checker sollten Sie nicht zu Ihren Abhängigkeiten hinzufügen, sondern als Projekt installieren. +Installieren Sie ihn global über Composer: ```shell -composer create-project nette/code-checker +composer global require nette/code-checker ``` -Oder installieren Sie es global mit: +Stellen Sie sicher, dass sich Ihr globales Composer-Verzeichnis `bin` in [Ihrem `$PATH` |https://getcomposer.org/doc/03-cli.md#global] befindet. Der Befehl `code-checker` ist dann von überall aus verfügbar, auf jedem Betriebssystem. + +Alternativ können Sie ihn als eigenständiges Projekt installieren: ```shell -composer global require nette/code-checker +composer create-project nette/code-checker ``` -und stellen Sie sicher, dass Ihr globales Verzeichnis `vendor/bin` in der [Umgebungsvariablen $PATH |https://getcomposer.org/doc/03-cli.md#global] enthalten ist. +Er erfordert PHP 8.0 oder höher. Verwendung ========== -``` -Usage: php code-checker [options] +Standardmäßig läuft Code Checker im read-only-Modus und meldet nur die gefundenen Probleme: -Options: - -d <path> Zu scannender Ordner oder Datei (Standard: aktuelles Verzeichnis) - -i | --ignore <mask> Zu ignorierende Dateien - -f | --fix Korrigiert Dateien - -l | --eol Konvertiert Zeilenumbruchzeichen - --no-progress Keine Fortschrittspunkte anzeigen - --strict-types Prüft, ob die PHP 7.0-Direktive strict_types aktiviert ist +```shell +code-checker ``` -Ohne Parameter prüft es das aktuelle Verzeichnis im schreibgeschützten Modus, mit dem Parameter `-f` korrigiert es die Dateien. +Um die Dateien tatsächlich zu reparieren, fügen Sie `--fix` hinzu. Sichern Sie Ihre Dateien zuvor oder führen Sie ihn über einem sauberen Arbeitsbaum aus, damit Sie die Änderungen anschließend mit `git diff` überprüfen können: -Bevor Sie sich damit vertraut machen, sichern Sie unbedingt zuerst Ihre Dateien. +```shell +code-checker --fix +``` -Für einen einfacheren Start können wir eine Datei `code.bat` erstellen: +Sie können den Scan auf einen bestimmten Pfad beschränken, Dateien überspringen oder schnellere reine Syntaxprüfungen ausführen: ```shell -php pfad_zu_Nette_tools\Code-Checker\code-checker %* +code-checker -d src --ignore "temp/*" +code-checker --only-syntax +``` + +Im read-only-Modus endet das Werkzeug mit dem Code `0`, wenn alles in Ordnung ist, und mit `1`, wenn ein Problem gefunden wird, sodass es sich gut in CI-Pipelines einfügt. + +Vollständige Liste der Optionen: + +``` +Usage: code-checker [options] + +Options: + -d <path> Folder or file to scan (default: current directory) + -i | --ignore <mask> Files to ignore + -f | --fix Fix the files + -l | --eol Normalize line endings to the system default + --only-syntax Check syntax only (faster) + --no-progress Do not show progress dots + --version Show version ``` -Was macht es alles? -=================== +Was Code Checker macht +====================== +- prüft die Syntax von [Latte |latte:]-Templates sowie von `.php`-, `.neon`- und `.json`-Dateien - entfernt das [BOM |nette:glossary#BOM] -- prüft die Gültigkeit von [Latte |latte:]-Templates -- prüft die Gültigkeit von `.neon`-, `.php`- und `.json`-Dateien -- prüft das Vorkommen von [Steuerzeichen |nette:glossary#Steuerzeichen] -- prüft, ob die Datei in UTF-8 kodiert ist -- prüft falsch geschriebene `/* @anotace */` (fehlendes Sternchen) -- entfernt das schließende `?>` bei PHP-Dateien -- entfernt Leerzeichen am Zeilenende und unnötige Leerzeilen am Dateiende -- normalisiert Zeilentrennzeichen auf Systemstandard (wenn Sie die Option `-l` angeben) +- überprüft, ob die Dateien gültiges UTF-8 sind +- prüft auf [Steuerzeichen |nette:glossary#Steuerzeichen] +- erkennt fehlerhaft geschriebene phpDoc-Kommentare (z. B. `/* @var` statt `/** @var`) +- erzwingt die Einrückung mit Tabulatoren in PHP-, CSS-, JS- und TS-Dateien und mit Leerzeichen in YAML +- entfernt nachgestellte Leerzeichen und Leerzeilen am Ende von Dateien +- normalisiert die Zeilenenden auf den Systemstandard (mit dem Parameter `-l`) diff --git a/tools/el/code-checker.texy b/tools/el/code-checker.texy index 2c102565e7..2d357e6025 100644 --- a/tools/el/code-checker.texy +++ b/tools/el/code-checker.texy @@ -2,62 +2,77 @@ Nette Code Checker ****************** .[perex] -Το εργαλείο [Code Checker |https://github.com/nette/code-checker] ελέγχει και ενδεχομένως διορθώνει ορισμένα από τα τυπικά σφάλματα στους πηγαίους κώδικές σας. +Το [Code Checker |https://github.com/nette/code-checker] ελέγχει τα πηγαία αρχεία σας για τυπικά σφάλματα, όπως ένα αόρατο BOM, χαρακτήρες ελέγχου, κατεστραμμένη κωδικοποίηση ή μη έγκυρη σύνταξη αρχείων PHP, Latte, NEON, JSON και YAML, και μπορεί να τα διορθώσει αυτόματα. Εγκατάσταση =========== -Δεν πρέπει να προσθέσετε το Code Checker στις εξαρτήσεις, αλλά να το εγκαταστήσετε ως έργο. +Εγκαταστήστε το καθολικά μέσω του Composer: ```shell -composer create-project nette/code-checker +composer global require nette/code-checker ``` -Ή εγκαταστήστε το καθολικά χρησιμοποιώντας: +Βεβαιωθείτε ότι ο καθολικός σας κατάλογος `bin` του Composer βρίσκεται στο [`$PATH` σας |https://getcomposer.org/doc/03-cli.md#global]. Η εντολή `code-checker` είναι τότε διαθέσιμη από οπουδήποτε, σε οποιοδήποτε λειτουργικό σύστημα. + +Εναλλακτικά, εγκαταστήστε το ως αυτόνομο έργο: ```shell -composer global require nette/code-checker +composer create-project nette/code-checker ``` -και βεβαιωθείτε ότι ο καθολικός σας κατάλογος `vendor/bin` βρίσκεται στη [μεταβλητή περιβάλλοντος $PATH |https://getcomposer.org/doc/03-cli.md#global]. +Απαιτεί PHP 8.0 ή νεότερη έκδοση. Χρήση ===== -``` -Usage: php code-checker [options] +Από προεπιλογή, το Code Checker εκτελείται σε κατάσταση μόνο ανάγνωσης και απλώς αναφέρει τα προβλήματα που βρίσκει: -Options: - -d <path> Folder or file to scan (default: current directory) - -i | --ignore <mask> Files to ignore - -f | --fix Fixes files - -l | --eol Convert newline characters - --no-progress Do not show progress dots - --strict-types Checks whether PHP 7.0 directive strict_types is enabled +```shell +code-checker ``` -Χωρίς παραμέτρους ελέγχει τον τρέχοντα κατάλογο σε κατάσταση μόνο ανάγνωσης, με την παράμετρο `-f` διορθώνει τα αρχεία. +Για να διορθώσετε πραγματικά τα αρχεία, προσθέστε το `--fix`. Δημιουργήστε πρώτα αντίγραφα ασφαλείας των αρχείων σας ή εκτελέστε το σε ένα καθαρό δέντρο εργασίας, ώστε να μπορείτε να ελέγξετε τις αλλαγές στη συνέχεια με το `git diff`: -Πριν εξοικειωθείτε μαζί του, φροντίστε να δημιουργήσετε αντίγραφα ασφαλείας των αρχείων σας πρώτα. +```shell +code-checker --fix +``` -Για ευκολότερη εκτέλεση, μπορούμε να δημιουργήσουμε ένα αρχείο `code.bat`: +Μπορείτε να περιορίσετε τη σάρωση σε μια συγκεκριμένη διαδρομή, να παραλείψετε αρχεία ή να εκτελέσετε ταχύτερους ελέγχους μόνο σύνταξης: ```shell -php path_to_Nette_tools\Code-Checker\code-checker %* +code-checker -d src --ignore "temp/*" +code-checker --only-syntax +``` + +Σε κατάσταση μόνο ανάγνωσης, το εργαλείο τερματίζεται με κωδικό `0` όταν όλα είναι εντάξει και `1` όταν βρεθεί οποιοδήποτε πρόβλημα, οπότε ταιριάζει ωραία σε αγωγούς CI. + +Πλήρης λίστα επιλογών: + +``` +Usage: code-checker [options] + +Options: + -d <path> Folder or file to scan (default: current directory) + -i | --ignore <mask> Files to ignore + -f | --fix Fix the files + -l | --eol Normalize line endings to the system default + --only-syntax Check syntax only (faster) + --no-progress Do not show progress dots + --version Show version ``` -Τι κάνει; -========= +Τι κάνει το Code Checker +======================== +- ελέγχει τη σύνταξη των templates [Latte |latte:] και των αρχείων `.php`, `.neon` και `.json` - αφαιρεί το [BOM |nette:glossary#BOM] -- ελέγχει την εγκυρότητα των templates [Latte |latte:] -- ελέγχει την εγκυρότητα των αρχείων `.neon`, `.php` και `.json` -- ελέγχει την παρουσία [χαρακτήρων ελέγχου |nette:glossary#Control characters] -- ελέγχει εάν το αρχείο είναι κωδικοποιημένο σε UTF-8 -- ελέγχει για λανθασμένα γραμμένα `/* @anotace */` (λείπει ο αστερίσκος) -- αφαιρεί το τελικό `?>` από τα αρχεία PHP -- αφαιρεί τα δεξιά κενά και τις περιττές γραμμές στο τέλος του αρχείου -- κανονικοποιεί τους διαχωριστές γραμμών σε συστήματος (εάν δώσετε την επιλογή `-l`) +- επαληθεύει ότι τα αρχεία είναι έγκυρα UTF-8 +- ελέγχει για [χαρακτήρες ελέγχου |nette:glossary#Control characters] +- εντοπίζει κακοδιατυπωμένα σχόλια phpDoc (π.χ. `/* @var` αντί για `/** @var`) +- επιβάλλει στηλοθέτες για στοίχιση σε αρχεία PHP, CSS, JS και TS, και κενά σε YAML +- αφαιρεί τα τελικά κενά και τις κενές γραμμές στο τέλος των αρχείων +- κανονικοποιεί τους τερματισμούς γραμμών στην προεπιλογή του συστήματος (με την παράμετρο `-l`) diff --git a/tools/en/code-checker.texy b/tools/en/code-checker.texy index 997dea69e0..c09e462661 100644 --- a/tools/en/code-checker.texy +++ b/tools/en/code-checker.texy @@ -2,63 +2,77 @@ Nette Code Checker ****************** .[perex] -The tool called [Code Checker |https://github.com/nette/code-checker] checks and optionally repairs some of the formal errors in your source code. +[Code Checker |https://github.com/nette/code-checker] checks your source files for formal flaws such as an invisible BOM, control characters, broken encoding, or invalid syntax of PHP, Latte, NEON, JSON and YAML files, and can fix them automatically. Installation ============ -Code Checker should be installed as a project, not added as a dependency. +Install it globally via Composer: ```shell -composer create-project nette/code-checker +composer global require nette/code-checker ``` -Or install it globally via: +Make sure your global Composer `bin` directory is in [your `$PATH` |https://getcomposer.org/doc/03-cli.md#global]. The `code-checker` command is then available from anywhere, on any operating system. + +Alternatively, install it as a standalone project: ```shell -composer global require nette/code-checker +composer create-project nette/code-checker ``` -and make sure your global vendor binaries directory is in [your `$PATH` environment variable|https://getcomposer.org/doc/03-cli.md#global]. +It requires PHP 8.0 or higher. Usage ===== -``` -Usage: php code-checker [options] +By default, Code Checker runs in read-only mode and only reports the problems it finds: -Options: - -d <path> Folder or file to scan (default: current directory) - -i | --ignore <mask> Files to ignore - -f | --fix Fixes files - -l | --eol Convert newline characters - --no-progress Do not show progress dots - --strict-types Checks whether PHP 7.0 directive strict_types is enabled +```shell +code-checker ``` -Without parameters, it checks the current working directory in read-only mode; with the `-f` parameter, it fixes files. +To actually repair the files, add `--fix`. Back up your files first, or run it on a clean working tree so you can review the changes afterwards with `git diff`: -Before you get familiar with the tool, be sure to back up your files first. +```shell +code-checker --fix +``` -You can create a batch file, e.g., `code.bat`, for easier execution of Code Checker under Windows: +You can limit the scan to a specific path, skip files, or run faster syntax-only checks: ```shell -php path_to\Nette_tools\Code-Checker\code-checker %* +code-checker -d src --ignore "temp/*" +code-checker --only-syntax +``` + +In read-only mode the tool exits with code `0` when everything is fine and `1` when any problem is found, so it fits nicely into CI pipelines. + +Full list of options: + +``` +Usage: code-checker [options] + +Options: + -d <path> Folder or file to scan (default: current directory) + -i | --ignore <mask> Files to ignore + -f | --fix Fix the files + -l | --eol Normalize line endings to the system default + --only-syntax Check syntax only (faster) + --no-progress Do not show progress dots + --version Show version ``` -What Does Code Checker Do? -========================== +What Code Checker Does +====================== -- removes [BOM |nette:glossary#BOM] -- checks the validity of [Latte |latte:] templates -- checks the validity of `.neon`, `.php`, and `.json` files +- checks the syntax of [Latte |latte:] templates and `.php`, `.neon` and `.json` files +- removes the [BOM |nette:glossary#BOM] +- verifies that files are valid UTF-8 - checks for [control characters |nette:glossary#Control Characters] -- checks whether the file is encoded in UTF-8 -- checks for misspelled `/* @annotations */` (missing second asterisk) -- removes PHP ending tags `?>` in PHP files -- removes trailing whitespace and unnecessary blank lines from the end of a file +- detects malformed phpDoc comments (e.g. `/* @var` instead of `/** @var`) +- enforces tabs for indentation in PHP, CSS, JS and TS files, and spaces in YAML +- removes trailing whitespace and blank lines at the end of files - normalizes line endings to the system default (with the `-l` parameter) - diff --git a/tools/es/code-checker.texy b/tools/es/code-checker.texy index eff3c64beb..b843a84a6e 100644 --- a/tools/es/code-checker.texy +++ b/tools/es/code-checker.texy @@ -2,62 +2,77 @@ Nette Code Checker ****************** .[perex] -La herramienta [Code Checker |https://github.com/nette/code-checker] comprueba y, opcionalmente, corrige algunos de los errores formales en sus códigos fuente. +[Code Checker |https://github.com/nette/code-checker] comprueba sus archivos fuente en busca de defectos formales como un BOM invisible, caracteres de control, codificación dañada o sintaxis inválida de archivos PHP, Latte, NEON, JSON y YAML, y puede corregirlos automáticamente. Instalación =========== -No debe agregar Code Checker a las dependencias, sino instalarlo como un proyecto. +Instálelo globalmente mediante Composer: ```shell -composer create-project nette/code-checker +composer global require nette/code-checker ``` -O instálelo globalmente usando: +Asegúrese de que su directorio global `bin` de Composer esté en [su `$PATH` |https://getcomposer.org/doc/03-cli.md#global]. El comando `code-checker` estará entonces disponible desde cualquier lugar, en cualquier sistema operativo. + +Alternativamente, instálelo como un proyecto independiente: ```shell -composer global require nette/code-checker +composer create-project nette/code-checker ``` -y asegúrese de que su directorio global `vendor/bin` esté en la [variable de entorno $PATH |https://getcomposer.org/doc/03-cli.md#global]. +Requiere PHP 8.0 o superior. Uso === -``` -Usage: php code-checker [options] +De forma predeterminada, Code Checker se ejecuta en modo de solo lectura y solo informa de los problemas que encuentra: -Options: - -d <path> Folder or file to scan (default: current directory) - -i | --ignore <mask> Files to ignore - -f | --fix Fixes files - -l | --eol Convert newline characters - --no-progress Do not show progress dots - --strict-types Checks whether PHP 7.0 directive strict_types is enabled +```shell +code-checker ``` -Sin parámetros, comprueba el directorio actual en modo de solo lectura, con el parámetro `-f` corrige los archivos. +Para reparar realmente los archivos, añada `--fix`. Haga primero una copia de seguridad de sus archivos, o ejecútelo sobre un árbol de trabajo limpio para poder revisar después los cambios con `git diff`: -Antes de familiarizarse con él, asegúrese de hacer una copia de seguridad de sus archivos primero. +```shell +code-checker --fix +``` -Para facilitar la ejecución, podemos crear un archivo `code.bat`: +Puede limitar el análisis a una ruta concreta, omitir archivos o ejecutar comprobaciones más rápidas solo de sintaxis: ```shell -php path_to_Nette_tools\Code-Checker\code-checker %* +code-checker -d src --ignore "temp/*" +code-checker --only-syntax +``` + +En el modo de solo lectura la herramienta finaliza con el código `0` cuando todo está bien y `1` cuando se encuentra algún problema, por lo que encaja perfectamente en los pipelines de CI. + +Lista completa de opciones: + +``` +Usage: code-checker [options] + +Options: + -d <path> Folder or file to scan (default: current directory) + -i | --ignore <mask> Files to ignore + -f | --fix Fix the files + -l | --eol Normalize line endings to the system default + --only-syntax Check syntax only (faster) + --no-progress Do not show progress dots + --version Show version ``` -¿Qué hace todo esto? -==================== +Qué hace Code Checker +===================== +- comprueba la sintaxis de las plantillas [Latte |latte:] y de los archivos `.php`, `.neon` y `.json` - elimina el [BOM |nette:glossary#BOM] -- comprueba la validez de las plantillas [Latte |latte:] -- comprueba la validez de los archivos `.neon`, `.php` y `.json` +- verifica que los archivos sean UTF-8 válido - comprueba la presencia de [caracteres de control |nette:glossary#Caracteres de control] -- comprueba si el archivo está codificado en UTF-8 -- comprueba las `/* @anotaciones */` escritas incorrectamente (falta el asterisco) -- elimina el cierre `?>` de los archivos PHP -- elimina los espacios finales y las líneas innecesarias al final del archivo -- normaliza los separadores de línea a los del sistema (si especifica la opción `-l`) +- detecta comentarios phpDoc mal formados (p. ej. `/* @var` en lugar de `/** @var`) +- impone tabuladores para la sangría en archivos PHP, CSS, JS y TS, y espacios en YAML +- elimina los espacios finales y las líneas en blanco al final de los archivos +- normaliza los separadores de línea a los del sistema (con el parámetro `-l`) diff --git a/tools/fr/code-checker.texy b/tools/fr/code-checker.texy index e8d8bdeabe..9e86472433 100644 --- a/tools/fr/code-checker.texy +++ b/tools/fr/code-checker.texy @@ -2,62 +2,77 @@ Nette Code Checker ****************** .[perex] -L'outil [Code Checker |https://github.com/nette/code-checker] vérifie et corrige éventuellement certaines erreurs formelles dans vos codes sources. +[Code Checker |https://github.com/nette/code-checker] vérifie vos fichiers sources et y détecte des défauts formels tels qu'un BOM invisible, des caractères de contrôle, un encodage incorrect ou une syntaxe invalide des fichiers PHP, Latte, NEON, JSON et YAML, et peut les corriger automatiquement. Installation ============ -Code Checker ne doit pas être ajouté aux dépendances, mais installé en tant que projet. +Installez-le globalement via Composer : ```shell -composer create-project nette/code-checker +composer global require nette/code-checker ``` -Ou installez-le globalement en utilisant : +Assurez-vous que le répertoire `bin` global de Composer est dans [votre `$PATH` |https://getcomposer.org/doc/03-cli.md#global]. La commande `code-checker` est alors disponible de partout, sur n'importe quel système d'exploitation. + +Vous pouvez également l'installer comme projet autonome : ```shell -composer global require nette/code-checker +composer create-project nette/code-checker ``` -et assurez-vous que votre répertoire global `vendor/bin` est dans [la variable d'environnement $PATH |https://getcomposer.org/doc/03-cli.md#global]. +Il nécessite PHP 8.0 ou supérieur. Utilisation =========== -``` -Usage: php code-checker [options] +Par défaut, Code Checker s'exécute en mode lecture seule et se contente de signaler les problèmes qu'il trouve : -Options: - -d <path> Dossier ou fichier à analyser (par défaut : répertoire courant) - -i | --ignore <mask> Fichiers à ignorer - -f | --fix Corrige les fichiers - -l | --eol Convertit les caractères de nouvelle ligne - --no-progress N'affiche pas les points de progression - --strict-types Vérifie si la directive PHP 7.0 strict_types est activée +```shell +code-checker ``` -Sans paramètres, il vérifie le répertoire actuel en mode lecture seule, avec le paramètre `-f`, il corrige les fichiers. +Pour réparer réellement les fichiers, ajoutez `--fix`. Sauvegardez d'abord vos fichiers, ou exécutez-le sur un arbre de travail propre afin de pouvoir examiner les changements ensuite avec `git diff` : -Avant de vous familiariser avec lui, assurez-vous de sauvegarder d'abord vos fichiers. +```shell +code-checker --fix +``` -Pour faciliter l'exécution, nous pouvons créer un fichier `code.bat` : +Vous pouvez limiter l'analyse à un chemin précis, ignorer des fichiers ou exécuter des vérifications de syntaxe plus rapides : ```shell -php chemin_vers_Nette_tools\Code-Checker\code-checker %* +code-checker -d src --ignore "temp/*" +code-checker --only-syntax +``` + +En mode lecture seule, l'outil se termine avec le code `0` quand tout va bien et `1` quand un problème est trouvé, ce qui s'intègre parfaitement dans les pipelines CI. + +Liste complète des options : + +``` +Usage: code-checker [options] + +Options: + -d <path> Folder or file to scan (default: current directory) + -i | --ignore <mask> Files to ignore + -f | --fix Fix the files + -l | --eol Normalize line endings to the system default + --only-syntax Check syntax only (faster) + --no-progress Do not show progress dots + --version Show version ``` -Que fait-il ? -============= +Ce que fait Code Checker +======================== +- vérifie la syntaxe des templates [Latte |latte:] et des fichiers `.php`, `.neon` et `.json` - supprime le [BOM |nette:glossary#BOM] -- vérifie la validité des templates [Latte |latte:] -- vérifie la validité des fichiers `.neon`, `.php` et `.json` -- vérifie la présence de [caractères de contrôle |nette:glossary#Caractères de contrôle] -- vérifie si le fichier est encodé en UTF-8 -- vérifie les `/* @annotations */` mal écrites (étoile manquante) -- supprime le `?>` de fin des fichiers PHP -- supprime les espaces de fin et les lignes vides inutiles à la fin du fichier -- normalise les séparateurs de lignes en séparateurs système (si vous spécifiez l'option `-l`) +- vérifie que les fichiers sont de l'UTF-8 valide +- contrôle la présence de [caractères de contrôle |nette:glossary#Caractères de contrôle] +- détecte les commentaires phpDoc mal formés (par ex. `/* @var` au lieu de `/** @var`) +- impose l'indentation par tabulations dans les fichiers PHP, CSS, JS et TS, et par espaces dans YAML +- supprime les espaces de fin et les lignes vides à la fin des fichiers +- normalise les fins de ligne au format système (avec le paramètre `-l`) diff --git a/tools/hu/code-checker.texy b/tools/hu/code-checker.texy index 8fc3e218a4..01f044b9f9 100644 --- a/tools/hu/code-checker.texy +++ b/tools/hu/code-checker.texy @@ -2,62 +2,77 @@ Nette Code Checker ****************** .[perex] -A [Code Checker |https://github.com/nette/code-checker] eszköz ellenőrzi és szükség esetén kijavítja a forráskódjaiban található néhány formai hibát. +[Code Checker |https://github.com/nette/code-checker] ellenőrzi a forrásfájljaidat, és olyan formai hibákat talál bennük, mint a láthatatlan BOM, a vezérlő karakterek, a hibás kódolás vagy a PHP, Latte, NEON, JSON és YAML fájlok érvénytelen szintaxisa, és képes automatikusan kijavítani őket. Telepítés ========= -A Code Checkert nem szabad a függőségekhez hozzáadni, hanem projektként kell telepíteni. +Telepítsd globálisan a Composer segítségével: ```shell -composer create-project nette/code-checker +composer global require nette/code-checker ``` -Vagy telepítse globálisan a következővel: +Győződj meg róla, hogy a globális Composer `bin` könyvtárad benne van a [`$PATH` változódban |https://getcomposer.org/doc/03-cli.md#global]. A `code-checker` parancs ezután bárhonnan elérhető, bármilyen operációs rendszeren. + +Alternatívaként telepítheted önálló projektként is: ```shell -composer global require nette/code-checker +composer create-project nette/code-checker ``` -és győződjön meg róla, hogy a globális `vendor/bin` könyvtára benne van a [$PATH környezeti változóban |https://getcomposer.org/doc/03-cli.md#global]. +PHP 8.0-s vagy újabb verziót igényel. Használat ========= -``` -Usage: php code-checker [options] +Alapértelmezés szerint a Code Checker read-only módban fut, és csak kiírja a megtalált problémákat: -Options: - -d <path> Szkennelendő mappa vagy fájl (alapértelmezett: aktuális könyvtár) - -i | --ignore <mask> Figyelmen kívül hagyandó fájlok - -f | --fix Javítja a fájlokat - -l | --eol Újsor karakterek konvertálása - --no-progress Ne jelenítse meg a folyamatjelző pontokat - --strict-types Ellenőrzi, hogy a PHP 7.0 strict_types direktíva engedélyezve van-e +```shell +code-checker ``` -Paraméterek nélkül az aktuális könyvtárat ellenőrzi read-only módban, a `-f` paraméterrel javítja a fájlokat. +A fájlok tényleges javításához add hozzá a `--fix` kapcsolót. Előbb készíts biztonsági másolatot a fájljaidról, vagy futtasd egy tiszta munkafán, hogy utána a `git diff` paranccsal átnézhesd a változásokat: -Mielőtt megismerkedne vele, mindenképpen készítsen biztonsági másolatot a fájlokról. +```shell +code-checker --fix +``` -A könnyebb indítás érdekében létrehozhatunk egy `code.bat` fájlt: +A vizsgálatot korlátozhatod egy adott útvonalra, kihagyhatsz fájlokat, vagy gyorsabb, csak szintaxist ellenőrző futtatást indíthatsz: ```shell -php path_to_Nette_tools\Code-Checker\code-checker %* +code-checker -d src --ignore "temp/*" +code-checker --only-syntax +``` + +Read-only módban az eszköz `0` kóddal lép ki, ha minden rendben van, és `1` kóddal, ha bármilyen problémát talál, így remekül beilleszthető a CI folyamatokba. + +A kapcsolók teljes listája: + +``` +Usage: code-checker [options] + +Options: + -d <path> Folder or file to scan (default: current directory) + -i | --ignore <mask> Files to ignore + -f | --fix Fix the files + -l | --eol Normalize line endings to the system default + --only-syntax Check syntax only (faster) + --no-progress Do not show progress dots + --version Show version ``` -Mit csinál pontosan? -==================== +Mit csinál a Code Checker +========================= -- eltávolítja a [BOM |nette:glossary#BOM]-ot -- ellenőrzi a [Latte |latte:] sablonok érvényességét -- ellenőrzi a `.neon`, `.php` és `.json` fájlok érvényességét -- ellenőrzi a [vezérlőkarakterek |nette:glossary#Vezérlő karakterek] előfordulását -- ellenőrzi, hogy a fájl UTF-8 kódolású-e -- ellenőrzi a hibásan írt `/* @anotace */` (hiányzik a csillag) -- eltávolítja a záró `?>` taget a PHP fájlokból -- eltávolítja a jobb oldali szóközöket és a felesleges sorokat a fájl végéről -- normalizálja a sorelválasztókat a rendszer alapértelmezettjére (ha megadja a `-l` opciót) +- ellenőrzi a [Latte |latte:] sablonok, valamint a `.php`, `.neon` és `.json` fájlok szintaxisát +- eltávolítja a [BOM |nette:glossary#BOM] jelet +- ellenőrzi, hogy a fájlok érvényes UTF-8 kódolásúak-e +- ellenőrzi a [vezérlő karakterek |nette:glossary#Vezérlő karakterek] előfordulását +- felderíti a hibásan írt phpDoc kommenteket (pl. `/* @var` a `/** @var` helyett) +- kikényszeríti a tabulátoros behúzást a PHP, CSS, JS és TS fájlokban, illetve a szóközöket a YAML fájlokban +- eltávolítja a sorvégi szóközöket és a fájlok végén lévő üres sorokat +- a sorvégeket a rendszer alapértelmezett formátumára normalizálja (a `-l` kapcsolóval) diff --git a/tools/it/code-checker.texy b/tools/it/code-checker.texy index c51e6fc4c1..80def8b0b7 100644 --- a/tools/it/code-checker.texy +++ b/tools/it/code-checker.texy @@ -2,62 +2,77 @@ Nette Code Checker ****************** .[perex] -Lo strumento [Code Checker |https://github.com/nette/code-checker] controlla e, se necessario, corregge alcuni degli errori formali nei vostri codici sorgente. +[Code Checker |https://github.com/nette/code-checker] controlla i tuoi file sorgente alla ricerca di difetti formali come un BOM invisibile, caratteri di controllo, codifica errata o sintassi non valida nei file PHP, Latte, NEON, JSON e YAML, e può correggerli automaticamente. Installazione ============= -Code Checker non dovrebbe essere aggiunto alle dipendenze, ma installato come progetto. +Installalo globalmente tramite Composer: ```shell -composer create-project nette/code-checker +composer global require nette/code-checker ``` -Oppure installatelo globalmente tramite: +Assicurati che la directory globale `bin` di Composer sia nel [tuo `$PATH` |https://getcomposer.org/doc/03-cli.md#global]. Il comando `code-checker` è quindi disponibile da qualsiasi posizione, su qualsiasi sistema operativo. + +In alternativa, installalo come progetto autonomo: ```shell -composer global require nette/code-checker +composer create-project nette/code-checker ``` -e assicuratevi che la vostra directory globale `vendor/bin` sia nella [variabile d'ambiente $PATH |https://getcomposer.org/doc/03-cli.md#global]. +Richiede PHP 8.0 o superiore. Utilizzo ======== -``` -Usage: php code-checker [options] +Per impostazione predefinita, Code Checker viene eseguito in modalità di sola lettura e segnala solo i problemi che trova: -Options: - -d <path> Folder or file to scan (default: current directory) - -i | --ignore <mask> Files to ignore - -f | --fix Fixes files - -l | --eol Convert newline characters - --no-progress Do not show progress dots - --strict-types Checks whether PHP 7.0 directive strict_types is enabled +```shell +code-checker ``` -Senza parametri, controlla la directory corrente in modalità di sola lettura, con il parametro `-f` corregge i file. +Per riparare effettivamente i file, aggiungi `--fix`. Esegui prima un backup dei file, oppure eseguilo su un albero di lavoro pulito così potrai rivedere le modifiche in seguito con `git diff`: -Prima di familiarizzare con esso, assicuratevi di eseguire il backup dei file. +```shell +code-checker --fix +``` -Per un avvio più semplice, possiamo creare un file `code.bat`: +Puoi limitare la scansione a un percorso specifico, saltare file o eseguire controlli più rapidi solo sulla sintassi: ```shell -php percorso_a_Nette_tools\Code-Checker\code-checker %* +code-checker -d src --ignore "temp/*" +code-checker --only-syntax ``` +In modalità di sola lettura lo strumento esce con codice `0` quando tutto è a posto e `1` quando viene trovato un problema, quindi si integra perfettamente nelle pipeline CI. -Cosa fa? -======== +Elenco completo delle opzioni: + +``` +Usage: code-checker [options] + +Options: + -d <path> Folder or file to scan (default: current directory) + -i | --ignore <mask> Files to ignore + -f | --fix Fix the files + -l | --eol Normalize line endings to the system default + --only-syntax Check syntax only (faster) + --no-progress Do not show progress dots + --version Show version +``` + + +Cosa fa Code Checker +==================== +- controlla la sintassi dei template [Latte |latte:] e dei file `.php`, `.neon` e `.json` - rimuove il [BOM |nette:glossary#BOM] -- controlla la validità dei template [Latte |latte:] -- controlla la validità dei file `.neon`, `.php` e `.json` +- verifica che i file siano UTF-8 validi - controlla la presenza di [caratteri di controllo |nette:glossary#Caratteri di controllo] -- controlla se il file è codificato in UTF-8 -- controlla le annotazioni `/* @anotace */` scritte male (manca l'asterisco) -- rimuove i tag di chiusura `?>` dai file PHP -- rimuove gli spazi finali e le righe vuote alla fine del file -- normalizza i separatori di riga a quelli di sistema (se si specifica l'opzione `-l`) +- rileva commenti phpDoc malformati (es. `/* @var` invece di `/** @var`) +- impone l'indentazione con tabulazioni nei file PHP, CSS, JS e TS, e con spazi in YAML +- rimuove gli spazi finali e le righe vuote alla fine dei file +- normalizza i fine riga al valore predefinito di sistema (con il parametro `-l`) diff --git a/tools/ja/code-checker.texy b/tools/ja/code-checker.texy index 93dc4f73bb..bccbab02c2 100644 --- a/tools/ja/code-checker.texy +++ b/tools/ja/code-checker.texy @@ -2,62 +2,77 @@ Nette Code Checker ****************** .[perex] -[Code Checker |https://github.com/nette/code-checker]ツールは、ソースコード内のいくつかの形式的なエラーをチェックし、必要に応じて修正します。 +[Code Checker |https://github.com/nette/code-checker] は、目に見えない BOM、制御文字、壊れたエンコーディング、PHP・Latte・NEON・JSON・YAML ファイルの不正な構文といった形式的な欠陥がないかソースファイルをチェックし、自動的に修正できます。 インストール ====== -Code Checkerは依存関係に追加するのではなく、プロジェクトとしてインストールする必要があります。 +Composer を使ってグローバルにインストールします: ```shell -composer create-project nette/code-checker +composer global require nette/code-checker ``` -または、次のようにグローバルにインストールします: +グローバルな Composer の `bin` ディレクトリが [`$PATH` に含まれている |https://getcomposer.org/doc/03-cli.md#global] ことを確認してください。そうすれば `code-checker` コマンドは、どのオペレーティングシステムでも、どこからでも利用できます。 + +あるいは、スタンドアロンのプロジェクトとしてインストールすることもできます: ```shell -composer global require nette/code-checker +composer create-project nette/code-checker ``` -そして、グローバルな `vendor/bin` ディレクトリが[$PATH 環境変数 |https://getcomposer.org/doc/03-cli.md#global]に含まれていることを確認してください。 +PHP 8.0 以上が必要です。 -使用法 +使い方 === -``` -Usage: php code-checker [options] +デフォルトでは、Code Checker は読み取り専用モードで動作し、見つかった問題を報告するだけです: -Options: - -d <path> スキャンするフォルダまたはファイル(デフォルト:現在のディレクトリ) - -i | --ignore <mask> 無視するファイル - -f | --fix ファイルを修正 - -l | --eol 改行文字を変換 - --no-progress 進捗ドットを表示しない - --strict-types PHP 7.0 ディレクティブ strict_types が有効かどうかをチェック +```shell +code-checker ``` -パラメータなしでは、現在のディレクトリを読み取り専用モードでチェックします。パラメータ `-f` を指定すると、ファイルを修正します。 +実際にファイルを修復するには `--fix` を追加します。先にファイルをバックアップするか、あとで `git diff` で変更を確認できるよう、クリーンな作業ツリー上で実行してください: -慣れる前に、必ずファイルをバックアップしてください。 +```shell +code-checker --fix +``` -簡単に実行するために、`code.bat` ファイルを作成できます: +スキャンを特定のパスに限定したり、ファイルをスキップしたり、より高速な構文のみのチェックを実行したりできます: ```shell -php path_to_Nette_tools\Code-Checker\code-checker %* +code-checker -d src --ignore "temp/*" +code-checker --only-syntax +``` + +読み取り専用モードでは、すべて問題がなければ終了コード `0`、何らかの問題が見つかれば `1` で終了するため、CI パイプラインにうまく組み込めます。 + +オプションの完全な一覧: + +``` +Usage: code-checker [options] + +Options: + -d <path> Folder or file to scan (default: current directory) + -i | --ignore <mask> Files to ignore + -f | --fix Fix the files + -l | --eol Normalize line endings to the system default + --only-syntax Check syntax only (faster) + --no-progress Do not show progress dots + --version Show version ``` -何をするのですか? -========= +Code Checker の機能 +================ -- [BOM |nette:glossary#BOM]を削除します -- [Latte |latte:] テンプレートの有効性をチェックします -- `.neon`、`.php`、`.json` ファイルの有効性をチェックします -- [制御文字 |nette:glossary#制御文字]の出現をチェックします -- ファイルがUTF-8でエンコードされているかチェックします -- 誤って記述された `/* @anotation */`(アスタリスクが欠けている)をチェックします -- PHP ファイルの末尾の `?>` を削除します -- ファイルの末尾の右側のスペースと不要な行を削除します -- (オプション `-l` を指定した場合)改行文字をシステム標準に正規化します +- [Latte |latte:] テンプレートおよび `.php`、`.neon`、`.json` ファイルの構文をチェックします +- [BOM |nette:glossary#BOM] を除去します +- ファイルが有効な UTF-8 であることを検証します +- [制御文字 |nette:glossary#制御文字] をチェックします +- 不正な形式の phpDoc コメント(例: `/** @var` ではなく `/* @var`)を検出します +- PHP、CSS、JS、TS ファイルではタブによるインデントを、YAML ではスペースを強制します +- 行末の空白とファイル末尾の空行を除去します +- 行末記号をシステムのデフォルトに正規化します(`-l` パラメータ使用時) diff --git a/tools/pl/code-checker.texy b/tools/pl/code-checker.texy index 06313c916a..b297dd7e68 100644 --- a/tools/pl/code-checker.texy +++ b/tools/pl/code-checker.texy @@ -2,62 +2,77 @@ Nette Code Checker ****************** .[perex] -Narzędzie [Code Checker |https://github.com/nette/code-checker] sprawdza i ewentualnie naprawia niektóre formalne błędy w Twoich kodach źródłowych. +[Code Checker |https://github.com/nette/code-checker] sprawdza Twoje pliki źródłowe i znajduje w nich formalne usterki, takie jak niewidoczny BOM, znaki kontrolne, błędne kodowanie czy nieprawidłowa składnia plików PHP, Latte, NEON, JSON i YAML, oraz potrafi je automatycznie naprawić. Instalacja ========== -Code Checker nie powinien być dodawany do zależności, ale instalowany jako projekt. +Zainstaluj go globalnie za pomocą Composera: ```shell -composer create-project nette/code-checker +composer global require nette/code-checker ``` -Lub zainstaluj go globalnie za pomocą: +Upewnij się, że Twój globalny katalog `bin` Composera znajduje się w [zmiennej `$PATH` |https://getcomposer.org/doc/03-cli.md#global]. Polecenie `code-checker` jest wtedy dostępne z dowolnego miejsca, w dowolnym systemie operacyjnym. + +Alternatywnie zainstaluj go jako samodzielny projekt: ```shell -composer global require nette/code-checker +composer create-project nette/code-checker ``` -i upewnij się, że twój globalny katalog `vendor/bin` jest w [zmiennej środowiskowej $PATH |https://getcomposer.org/doc/03-cli.md#global]. +Wymaga PHP 8.0 lub nowszego. -Użycie -====== +Użytkowanie +=========== -``` -Usage: php code-checker [options] +Domyślnie Code Checker działa w trybie tylko do odczytu i jedynie wypisuje znalezione problemy: -Options: - -d <path> Katalog lub plik do skanowania (domyślnie: bieżący katalog) - -i | --ignore <mask> Pliki do ignorowania - -f | --fix Naprawia pliki - -l | --eol Konwertuj znaki nowej linii - --no-progress Nie pokazuj kropek postępu - --strict-types Sprawdza, czy dyrektywa PHP 7.0 strict_types jest włączona +```shell +code-checker ``` -Bez parametrów sprawdza bieżący katalog w trybie tylko do odczytu, z parametrem `-f` naprawia pliki. +Aby faktycznie naprawić pliki, dodaj `--fix`. Najpierw wykonaj kopię zapasową plików lub uruchom narzędzie na czystym drzewie roboczym, abyś mógł później przejrzeć zmiany za pomocą `git diff`: -Zanim się z nim zapoznasz, na pewno najpierw zrób kopię zapasową plików. +```shell +code-checker --fix +``` -Dla łatwiejszego uruchamiania możemy utworzyć plik `code.bat`: +Skanowanie możesz ograniczyć do konkretnej ścieżki, pominąć pliki lub uruchomić szybszą kontrolę samej składni: ```shell -php sciezka_do_Nette_tools\Code-Checker\code-checker %* +code-checker -d src --ignore "temp/*" +code-checker --only-syntax +``` + +W trybie tylko do odczytu narzędzie kończy działanie z kodem `0`, gdy wszystko jest w porządku, oraz `1`, gdy znajdzie jakikolwiek problem, dzięki czemu dobrze pasuje do procesów CI. + +Pełna lista opcji: + +``` +Usage: code-checker [options] + +Options: + -d <path> Folder or file to scan (default: current directory) + -i | --ignore <mask> Files to ignore + -f | --fix Fix the files + -l | --eol Normalize line endings to the system default + --only-syntax Check syntax only (faster) + --no-progress Do not show progress dots + --version Show version ``` -Co wszystko robi? -================= +Co robi Code Checker +==================== +- sprawdza składnię szablonów [Latte |latte:] oraz plików `.php`, `.neon` i `.json` - usuwa [BOM |nette:glossary#BOM] -- sprawdza poprawność szablonów [Latte |latte:] -- sprawdza poprawność plików `.neon`, `.php` i `.json` +- weryfikuje, czy pliki są poprawnym UTF-8 - sprawdza występowanie [znaków kontrolnych |nette:glossary#Znaki kontrolne] -- sprawdza, czy plik jest zakodowany w UTF-8 -- sprawdza błędnie zapisane `/* @adnotacje */` (brakuje gwiazdki) -- usuwa kończące `?>` w plikach PHP -- usuwa prawostronne spacje i zbędne linie na końcu pliku -- normalizuje separatory linii do systemowych (jeśli podasz opcję `-l`) +- wykrywa błędnie zapisane komentarze phpDoc (np. `/* @var` zamiast `/** @var`) +- wymusza wcięcia tabulatorami w plikach PHP, CSS, JS i TS oraz spacjami w YAML +- usuwa końcowe spacje i puste wiersze na końcu plików +- normalizuje końce wierszy do domyślnych dla systemu (za pomocą parametru `-l`) diff --git a/tools/pt/code-checker.texy b/tools/pt/code-checker.texy index 3cd3257cf9..477894a1c8 100644 --- a/tools/pt/code-checker.texy +++ b/tools/pt/code-checker.texy @@ -2,62 +2,77 @@ Nette Code Checker ****************** .[perex] -A ferramenta [Code Checker |https://github.com/nette/code-checker] verifica e, opcionalmente, corrige alguns dos erros formais nos seus códigos-fonte. +[Code Checker |https://github.com/nette/code-checker] verifica seus arquivos de origem em busca de falhas formais, como um BOM invisível, caracteres de controle, codificação corrompida ou sintaxe inválida de arquivos PHP, Latte, NEON, JSON e YAML, e pode corrigi-los automaticamente. Instalação ========== -Você não deve adicionar o Code Checker às suas dependências, mas instalá-lo como um projeto. +Instale-o globalmente via Composer: ```shell -composer create-project nette/code-checker +composer global require nette/code-checker ``` -Ou instale-o globalmente usando: +Certifique-se de que o diretório global `bin` do Composer esteja no [seu `$PATH` |https://getcomposer.org/doc/03-cli.md#global]. O comando `code-checker` fica então disponível de qualquer lugar, em qualquer sistema operacional. + +Como alternativa, instale-o como um projeto independente: ```shell -composer global require nette/code-checker +composer create-project nette/code-checker ``` -e certifique-se de que seu diretório global `vendor/bin` esteja na [variável de ambiente $PATH |https://getcomposer.org/doc/03-cli.md#global]. +Requer PHP 8.0 ou superior. Uso === -``` -Usage: php code-checker [options] +Por padrão, o Code Checker é executado em modo somente leitura e apenas relata os problemas que encontra: -Options: - -d <path> Pasta ou arquivo para escanear (padrão: diretório atual) - -i | --ignore <mask> Arquivos a ignorar - -f | --fix Corrige arquivos - -l | --eol Converte caracteres de nova linha - --no-progress Não mostrar pontos de progresso - --strict-types Verifica se a diretiva strict_types do PHP 7.0 está habilitada +```shell +code-checker ``` -Sem parâmetros, verifica o diretório atual no modo somente leitura; com o parâmetro `-f`, corrige os arquivos. +Para realmente reparar os arquivos, adicione `--fix`. Faça um backup dos seus arquivos primeiro, ou execute-o sobre uma árvore de trabalho limpa para que você possa revisar as alterações depois com `git diff`: -Antes de se familiarizar com ele, certifique-se de fazer backup dos seus arquivos primeiro. +```shell +code-checker --fix +``` -Para facilitar a execução, podemos criar um arquivo `code.bat`: +Você pode limitar a verificação a um caminho específico, ignorar arquivos ou executar verificações mais rápidas apenas de sintaxe: ```shell -php caminho_para_Nette_tools\Code-Checker\code-checker %* +code-checker -d src --ignore "temp/*" +code-checker --only-syntax +``` + +No modo somente leitura, a ferramenta sai com o código `0` quando tudo está bem e `1` quando algum problema é encontrado, então ela se encaixa perfeitamente em pipelines de CI. + +Lista completa de opções: + +``` +Usage: code-checker [options] + +Options: + -d <path> Folder or file to scan (default: current directory) + -i | --ignore <mask> Files to ignore + -f | --fix Fix the files + -l | --eol Normalize line endings to the system default + --only-syntax Check syntax only (faster) + --no-progress Do not show progress dots + --version Show version ``` -O que ele faz? -============== +O que o Code Checker faz +======================== +- verifica a sintaxe de templates [Latte |latte:] e arquivos `.php`, `.neon` e `.json` - remove o [BOM |nette:glossary#BOM] -- verifica a validade dos templates [Latte |latte:] -- verifica a validade dos arquivos `.neon`, `.php` e `.json` -- verifica a ocorrência de [caracteres de controle |nette:glossary#Caracteres de controle] -- verifica se o arquivo está codificado em UTF-8 -- verifica `/* @anotações */` mal escritas (falta asterisco) -- remove `?>` de fechamento em arquivos PHP -- remove espaços em branco à direita e linhas desnecessárias no final do arquivo -- normaliza os separadores de linha para o padrão do sistema (se você usar a opção `-l`) +- verifica se os arquivos são UTF-8 válidos +- procura por [caracteres de controle |nette:glossary#Caracteres de controle] +- detecta comentários phpDoc malformados (ex.: `/* @var` em vez de `/** @var`) +- impõe tabulações para indentação em arquivos PHP, CSS, JS e TS, e espaços em YAML +- remove espaços em branco à direita e linhas em branco no final dos arquivos +- normaliza os finais de linha para o padrão do sistema (com o parâmetro `-l`) diff --git a/tools/ro/code-checker.texy b/tools/ro/code-checker.texy index fdf4ad3079..670af4088c 100644 --- a/tools/ro/code-checker.texy +++ b/tools/ro/code-checker.texy @@ -2,62 +2,77 @@ Nette Code Checker ****************** .[perex] -Instrumentul [Code Checker |https://github.com/nette/code-checker] verifică și, eventual, corectează unele dintre erorile formale din codurile dvs. sursă. +[Code Checker |https://github.com/nette/code-checker] verifică fișierele sursă pentru defecte formale precum un BOM invizibil, caractere de control, codificare deteriorată sau sintaxă invalidă a fișierelor PHP, Latte, NEON, JSON și YAML și le poate corecta automat. Instalare ========= -Code Checker nu ar trebui adăugat la dependențe, ci instalat ca proiect. +Instalați-l global prin Composer: ```shell -composer create-project nette/code-checker +composer global require nette/code-checker ``` -Sau instalați-l global folosind: +Asigurați-vă că directorul global Composer `bin` se află în [`$PATH`-ul dumneavoastră |https://getcomposer.org/doc/03-cli.md#global]. Comanda `code-checker` este apoi disponibilă de oriunde, pe orice sistem de operare. + +Alternativ, instalați-l ca proiect de sine stătător: ```shell -composer global require nette/code-checker +composer create-project nette/code-checker ``` -și asigurați-vă că directorul dvs. global `vendor/bin` se află în [variabila de mediu $PATH |https://getcomposer.org/doc/03-cli.md#global]. +Necesită PHP 8.0 sau o versiune superioară. Utilizare ========= -``` -Usage: php code-checker [options] +În mod implicit, Code Checker rulează în mod read-only și doar raportează problemele pe care le găsește: -Options: - -d <path> Director sau fișier de scanat (implicit: directorul curent) - -i | --ignore <mask> Fișiere de ignorat - -f | --fix Corectează fișierele - -l | --eol Convertește caracterele de sfârșit de linie - --no-progress Nu afișa punctele de progres - --strict-types Verifică dacă directiva PHP 7.0 strict_types este activată +```shell +code-checker ``` -Fără parametri, verifică directorul curent în modul read-only, cu parametrul `-f` corectează fișierele. +Pentru a repara efectiv fișierele, adăugați `--fix`. Faceți mai întâi o copie de rezervă a fișierelor sau rulați-l pe un arbore de lucru curat, ca să puteți examina apoi modificările cu `git diff`: -Înainte de a vă familiariza cu el, asigurați-vă că faceți mai întâi o copie de rezervă a fișierelor. +```shell +code-checker --fix +``` -Pentru o rulare mai ușoară, putem crea un fișier `code.bat`: +Puteți limita scanarea la o cale anume, puteți omite fișiere sau puteți rula verificări mai rapide doar de sintaxă: ```shell -php cale_catre_Nette_tools\Code-Checker\code-checker %* +code-checker -d src --ignore "temp/*" +code-checker --only-syntax +``` + +În modul read-only, instrumentul se încheie cu codul `0` când totul este în regulă și `1` când este găsită vreo problemă, așa că se potrivește perfect în pipeline-urile CI. + +Lista completă de opțiuni: + +``` +Usage: code-checker [options] + +Options: + -d <path> Folder or file to scan (default: current directory) + -i | --ignore <mask> Files to ignore + -f | --fix Fix the files + -l | --eol Normalize line endings to the system default + --only-syntax Check syntax only (faster) + --no-progress Do not show progress dots + --version Show version ``` -Ce face? -======== +Ce face Code Checker +==================== +- verifică sintaxa șabloanelor [Latte |latte:] și a fișierelor `.php`, `.neon` și `.json` - elimină [BOM |nette:glossary#BOM] -- verifică validitatea șabloanelor [Latte |latte:] -- verifică validitatea fișierelor `.neon`, `.php` și `.json` +- verifică dacă fișierele sunt UTF-8 valide - verifică prezența [caracterelor de control |nette:glossary#Caractere de control] -- verifică dacă fișierul este codificat în UTF-8 -- verifică `/* @adnotari */` scrise incorect (lipsește asteriscul) -- elimină `?>` de la sfârșitul fișierelor PHP -- elimină spațiile de la sfârșitul rândului și rândurile goale inutile de la sfârșitul fișierului -- normalizează separatorii de rând la cei de sistem (dacă specificați opțiunea `-l`) +- detectează comentariile phpDoc malformate (de ex. `/* @var` în loc de `/** @var`) +- impune indentarea cu tabulatori în fișierele PHP, CSS, JS și TS și cu spații în YAML +- elimină spațiile de la sfârșit și liniile goale de la finalul fișierelor +- normalizează sfârșiturile de linie la cel implicit al sistemului (cu parametrul `-l`) diff --git a/tools/ru/code-checker.texy b/tools/ru/code-checker.texy index 64a0ade2b1..c99af3f01a 100644 --- a/tools/ru/code-checker.texy +++ b/tools/ru/code-checker.texy @@ -2,62 +2,77 @@ Nette Code Checker ****************** .[perex] -Инструмент [Code Checker |https://github.com/nette/code-checker] проверяет и при необходимости исправляет некоторые формальные ошибки в ваших исходных кодах. +[Code Checker |https://github.com/nette/code-checker] проверяет ваши исходные файлы и находит в них формальные недочёты, такие как невидимый BOM, управляющие символы, неправильную кодировку или некорректный синтаксис файлов PHP, Latte, NEON, JSON и YAML, и умеет их автоматически исправлять. Установка ========= -Code Checker не следует добавлять в зависимости, а устанавливать как проект. +Установите его глобально с помощью Composer: ```shell -composer create-project nette/code-checker +composer global require nette/code-checker ``` -Или установите его глобально с помощью: +Убедитесь, что ваш глобальный Composer каталог `bin` находится в [вашей переменной `$PATH` |https://getcomposer.org/doc/03-cli.md#global]. Команда `code-checker` тогда доступна откуда угодно, в любой операционной системе. + +Либо установите его как отдельный проект: ```shell -composer global require nette/code-checker +composer create-project nette/code-checker ``` -и убедитесь, что ваш глобальный каталог `vendor/bin` находится в [переменной окружения $PATH |https://getcomposer.org/doc/03-cli.md#global]. +Требуется PHP 8.0 или выше. Использование ============= -``` -Usage: php code-checker [options] +По умолчанию Code Checker работает в режиме read-only и только сообщает о найденных проблемах: -Options: - -d <path> Folder or file to scan (default: current directory) - -i | --ignore <mask> Files to ignore - -f | --fix Fixes files - -l | --eol Convert newline characters - --no-progress Do not show progress dots - --strict-types Checks whether PHP 7.0 directive strict_types is enabled +```shell +code-checker ``` -Без параметров проверяет текущий каталог в режиме только для чтения, с параметром `-f` исправляет файлы. +Чтобы действительно исправить файлы, добавьте `--fix`. Сначала сделайте резервную копию файлов или запустите инструмент на чистом рабочем дереве, чтобы потом можно было проверить изменения через `git diff`: -Прежде чем ознакомиться с ним, обязательно сделайте резервную копию файлов. +```shell +code-checker --fix +``` -Для более легкого запуска можно создать файл `code.bat`: +Вы можете ограничить сканирование конкретным путём, пропустить файлы или запустить более быструю проверку только синтаксиса: ```shell -php path_to_Nette_tools\Code-Checker\code-checker %* +code-checker -d src --ignore "temp/*" +code-checker --only-syntax +``` + +В режиме read-only инструмент завершается с кодом `0`, когда всё в порядке, и `1`, когда находит какую-либо проблему, поэтому он отлично вписывается в CI-конвейеры. + +Полный список опций: + +``` +Usage: code-checker [options] + +Options: + -d <path> Folder or file to scan (default: current directory) + -i | --ignore <mask> Files to ignore + -f | --fix Fix the files + -l | --eol Normalize line endings to the system default + --only-syntax Check syntax only (faster) + --no-progress Do not show progress dots + --version Show version ``` -Что он делает? -============== +Что делает Code Checker +======================= +- проверяет синтаксис [Latte |latte:] шаблонов и файлов `.php`, `.neon` и `.json` - удаляет [BOM |nette:glossary#BOM] -- проверяет валидность шаблонов [Latte |latte:] -- проверяет валидность файлов `.neon`, `.php` и `.json` +- проверяет, что файлы являются корректным UTF-8 - проверяет наличие [управляющих символов |nette:glossary#Управляющие символы] -- проверяет, закодирован ли файл в UTF-8 -- проверяет неправильно записанные `/* @anotace */` (отсутствует звездочка) -- удаляет завершающий `?>` у PHP-файлов -- удаляет пробелы в конце строк и лишние строки в конце файла -- нормализует разделители строк до системных (если указана опция `-l`) +- обнаруживает неправильно записанные phpDoc-комментарии (например, `/* @var` вместо `/** @var`) +- требует отступы табуляцией в файлах PHP, CSS, JS и TS и пробелами в YAML +- удаляет завершающие пробелы и пустые строки в конце файлов +- нормализует разделители строк на системные (с параметром `-l`) diff --git a/tools/sl/code-checker.texy b/tools/sl/code-checker.texy index 16d04a8f24..d7ad813c3c 100644 --- a/tools/sl/code-checker.texy +++ b/tools/sl/code-checker.texy @@ -2,62 +2,77 @@ Nette Code Checker ****************** .[perex] -Orodje [Code Checker |https://github.com/nette/code-checker] preveri in po potrebi popravi nekatere formalne napake v vaših izvornih kodah. +[Code Checker |https://github.com/nette/code-checker] preveri vaše izvorne datoteke in v njih poišče formalne pomanjkljivosti, kot so neviden BOM, kontrolni znaki, pokvarjeno kodiranje ali neveljavna sintaksa datotek PHP, Latte, NEON, JSON in YAML, ter jih zna samodejno popraviti. Namestitev ========== -Code Checkerja ne bi smeli dodajati med odvisnosti, ampak ga namestiti kot projekt. +Namestite ga globalno prek Composerja: ```shell -composer create-project nette/code-checker +composer global require nette/code-checker ``` -Ali pa ga namestite globalno s pomočjo: +Prepričajte se, da je vaš globalni Composer imenik `bin` v [vaši `$PATH` |https://getcomposer.org/doc/03-cli.md#global]. Ukaz `code-checker` je nato na voljo od kjerkoli, na katerem koli operacijskem sistemu. + +Lahko ga namestite tudi kot samostojen projekt: ```shell -composer global require nette/code-checker +composer create-project nette/code-checker ``` -in se prepričajte, da je vaš globalni imenik `vendor/bin` v [okoljski spremenljivki $PATH |https://getcomposer.org/doc/03-cli.md#global]. +Zahteva PHP 8.0 ali novejši. Uporaba ======= -``` -Usage: php code-checker [options] +Privzeto se Code Checker zažene v načinu samo za branje in samo izpiše najdene težave: -Options: - -d <path> Folder or file to scan (default: current directory) - -i | --ignore <mask> Files to ignore - -f | --fix Fixes files - -l | --eol Convert newline characters - --no-progress Do not show progress dots - --strict-types Checks whether PHP 7.0 directive strict_types is enabled +```shell +code-checker ``` -Brez parametrov preveri trenutni imenik v načinu samo za branje, s parametrom `-f` popravlja datoteke. +Za dejansko popravljanje datotek dodajte `--fix`. Najprej si datoteke varnostno kopirajte ali pa orodje zaženite nad čistim delovnim drevesom, da boste spremembe lahko nato pregledali z `git diff`: -Preden se z njim seznanite, si vsekakor najprej varnostno kopirajte datoteke. +```shell +code-checker --fix +``` -Za lažje zaganjanje si lahko ustvarimo datoteko `code.bat`: +Skeniranje lahko omejite na določeno pot, izpustite datoteke ali zaženete hitrejše preverjanje samo sintakse: ```shell -php pot_do_Nette_tools\Code-Checker\code-checker %* +code-checker -d src --ignore "temp/*" +code-checker --only-syntax +``` + +V načinu samo za branje se orodje zaključi s kodo `0`, ko je vse v redu, in `1`, ko najde kakršno koli težavo, zato se lepo prilega v CI cevovode. + +Celoten seznam možnosti: + +``` +Usage: code-checker [options] + +Options: + -d <path> Folder or file to scan (default: current directory) + -i | --ignore <mask> Files to ignore + -f | --fix Fix the files + -l | --eol Normalize line endings to the system default + --only-syntax Check syntax only (faster) + --no-progress Do not show progress dots + --version Show version ``` -Kaj vse počne? -============== +Kaj Code Checker počne +====================== -- odstranjuje [BOM |nette:glossary#BOM] -- preverja veljavnost [Latte |latte:] predlog -- preverja veljavnost datotek `.neon`, `.php` in `.json` -- preverja pojav [kontrolnih znakov |nette:glossary#Kontrolni znaki] -- preverja, ali je datoteka kodirana v UTF-8 -- preverja napačno zapisane `/* @anotace */` (manjka zvezdica) -- odstranjuje zaključne `?>` pri PHP datotekah -- odstranjuje desne presledke in nepotrebne vrstice na koncu datoteke -- normalizira ločila vrstic na sistemske (če navedete opcijo `-l`) +- preverja sintakso [Latte |latte:] predlog in datotek `.php`, `.neon` in `.json` +- odstrani [BOM |nette:glossary#BOM] +- preverja, ali so datoteke veljaven UTF-8 +- preverja [kontrolne znake |nette:glossary#Kontrolni znaki] +- odkrije napačno zapisane phpDoc komentarje (npr. `/* @var` namesto `/** @var`) +- vsiljuje zamik s tabulatorji v datotekah PHP, CSS, JS in TS ter s presledki v YAML +- odstrani končne presledke in prazne vrstice na koncu datotek +- normalizira konce vrstic na sistemsko privzete (z možnostjo `-l`) diff --git a/tools/tr/code-checker.texy b/tools/tr/code-checker.texy index 49d592bbb0..19fe7a9571 100644 --- a/tools/tr/code-checker.texy +++ b/tools/tr/code-checker.texy @@ -2,62 +2,77 @@ Nette Code Checker ****************** .[perex] -[Kod Denetleyicisi |https://github.com/nette/code-checker] aracı, kaynak kodlarınızdaki bazı biçimsel hataları kontrol eder ve gerekirse düzeltir. +[Code Checker |https://github.com/nette/code-checker] kaynak dosyalarınızı denetler ve görünmez bir BOM, kontrol karakterleri, bozuk kodlama veya PHP, Latte, NEON, JSON ve YAML dosyalarının geçersiz söz dizimi gibi biçimsel kusurları bulur ve bunları otomatik olarak düzeltebilir. Kurulum ======= -Kod Denetleyicisini bağımlılıklara eklememeli, bir proje olarak kurmalısınız. +Composer ile global olarak kurun: ```shell -composer create-project nette/code-checker +composer global require nette/code-checker ``` -Veya küresel olarak kurun: +Global Composer `bin` dizininizin [your `$PATH` |https://getcomposer.org/doc/03-cli.md#global] içinde olduğundan emin olun. `code-checker` komutu daha sonra herhangi bir işletim sisteminde her yerden kullanılabilir. + +Alternatif olarak, bağımsız bir proje olarak kurun: ```shell -composer global require nette/code-checker +composer create-project nette/code-checker ``` -ve küresel `vendor/bin` dizininizin [$PATH ortam değişkeninde |https://getcomposer.org/doc/03-cli.md#global] olduğundan emin olun. +PHP 8.0 veya üzerini gerektirir. Kullanım ======== -``` -Usage: php code-checker [options] +Varsayılan olarak Code Checker salt okunur modda çalışır ve yalnızca bulduğu sorunları bildirir: -Options: - -d <path> Taranacak klasör veya dosya (varsayılan: geçerli dizin) - -i | --ignore <mask> Yoksayılacak dosyalar - -f | --fix Dosyaları düzeltir - -l | --eol Yeni satır karakterlerini dönüştürür - --no-progress İlerleme noktalarını gösterme - --strict-types PHP 7.0 direktifi strict_types'ın etkin olup olmadığını kontrol eder +```shell +code-checker ``` -Parametresiz olarak geçerli dizini salt okunur modda kontrol eder, `-f` parametresiyle dosyaları düzeltir. +Dosyaları gerçekten onarmak için `--fix` ekleyin. Önce dosyalarınızı yedekleyin ya da onu temiz bir çalışma ağacı üzerinde çalıştırın, böylece değişiklikleri sonradan `git diff` ile gözden geçirebilirsiniz: -Tanışmadan önce dosyalarınızı mutlaka yedekleyin. +```shell +code-checker --fix +``` -Daha kolay çalıştırmak için bir `code.bat` dosyası oluşturabiliriz: +Taramayı belirli bir yola sınırlayabilir, dosyaları atlayabilir veya yalnızca söz dizimini kontrol eden daha hızlı denetimler çalıştırabilirsiniz: ```shell -php nette_araçlarının_yolu\Code-Checker\code-checker %* +code-checker -d src --ignore "temp/*" +code-checker --only-syntax +``` + +Salt okunur modda araç, her şey yolundayken `0` koduyla ve herhangi bir sorun bulunduğunda `1` koduyla çıkar, bu yüzden CI hatlarına güzelce uyar. + +Seçeneklerin tam listesi: + +``` +Usage: code-checker [options] + +Options: + -d <path> Folder or file to scan (default: current directory) + -i | --ignore <mask> Files to ignore + -f | --fix Fix the files + -l | --eol Normalize line endings to the system default + --only-syntax Check syntax only (faster) + --no-progress Do not show progress dots + --version Show version ``` -Ne yapar? -========= +Code Checker Ne Yapar +===================== +- [Latte |latte:] şablonlarının ve `.php`, `.neon` ve `.json` dosyalarının söz dizimini kontrol eder - [BOM |nette:glossary#BOM] kaldırır -- [Latte |latte:] şablonlarının geçerliliğini kontrol eder -- `.neon`, `.php` ve `.json` dosyalarının geçerliliğini kontrol eder -- [Kontrol karakterlerinin |nette:glossary#Kontrol Karakterleri] varlığını kontrol eder -- Dosyanın UTF-8 olarak kodlanıp kodlanmadığını kontrol eder -- Yanlış yazılmış `/* @anotace */` (yıldız eksik) kontrol eder -- PHP dosyalarındaki kapanış `?>` etiketini kaldırır -- Sağdaki boşlukları ve dosyanın sonundaki gereksiz satırları kaldırır -- Satır ayırıcılarını sistem varsayılanına normalleştirir (`-l` seçeneğini belirtirseniz) +- dosyaların geçerli UTF-8 olduğunu doğrular +- [kontrol karakterleri |nette:glossary#Kontrol Karakterleri] olup olmadığını kontrol eder +- hatalı biçimlendirilmiş phpDoc yorumlarını tespit eder (örneğin `/** @var` yerine `/* @var`) +- PHP, CSS, JS ve TS dosyalarında girinti için sekmeleri, YAML dosyalarında ise boşlukları zorunlu kılar +- dosyaların sonundaki sondaki boşlukları ve boş satırları kaldırır +- satır sonlarını sistem varsayılanına normalleştirir (`-l` parametresiyle) diff --git a/tools/uk/code-checker.texy b/tools/uk/code-checker.texy index 6063642a48..9aff576df8 100644 --- a/tools/uk/code-checker.texy +++ b/tools/uk/code-checker.texy @@ -2,62 +2,77 @@ Nette Code Checker ****************** .[perex] -Інструмент [Code Checker |https://github.com/nette/code-checker] перевіряє та, за потреби, виправляє деякі формальні помилки у ваших вихідних кодах. +[Code Checker |https://github.com/nette/code-checker] перевіряє ваші вихідні файли на формальні недоліки, такі як невидимий BOM, керуючі символи, пошкоджене кодування або неправильний синтаксис файлів PHP, Latte, NEON, JSON та YAML, і вміє виправляти їх автоматично. Встановлення ============ -Code Checker не слід додавати до залежностей, а встановлювати як проект. +Встановіть його глобально за допомогою Composer: ```shell -composer create-project nette/code-checker +composer global require nette/code-checker ``` -Або встановіть його глобально за допомогою: +Переконайтеся, що ваш глобальний каталог Composer `bin` знаходиться у [вашому `$PATH` |https://getcomposer.org/doc/03-cli.md#global]. Команда `code-checker` тоді доступна звідусіль, у будь-якій операційній системі. + +Альтернативно, встановіть його як окремий проєкт: ```shell -composer global require nette/code-checker +composer create-project nette/code-checker ``` -і переконайтеся, що ваш глобальний каталог `vendor/bin` знаходиться у [змінній середовища $PATH |https://getcomposer.org/doc/03-cli.md#global]. +Він потребує PHP 8.0 або вище. Використання ============ -``` -Usage: php code-checker [options] +За замовчуванням Code Checker працює в режимі лише для читання і тільки повідомляє про знайдені проблеми: -Options: - -d <path> Папка або файл для сканування (за замовчуванням: поточний каталог) - -i | --ignore <mask> Файли, які слід ігнорувати - -f | --fix Виправляє файли - -l | --eol Перетворює символи нового рядка - --no-progress Не показувати точки прогресу - --strict-types Перевіряє, чи увімкнена директива PHP 7.0 strict_types +```shell +code-checker ``` -Без параметрів перевіряє поточний каталог у режимі лише для читання, з параметром `-f` виправляє файли. +Щоб дійсно виправити файли, додайте `--fix`. Спочатку зробіть резервну копію файлів або запустіть його на чистому робочому дереві, щоб потім переглянути зміни за допомогою `git diff`: -Перш ніж ознайомитися з ним, обов'язково зробіть резервну копію файлів. +```shell +code-checker --fix +``` -Для полегшення запуску можна створити файл `code.bat`: +Ви можете обмежити сканування конкретним шляхом, пропустити файли або запустити швидшу перевірку лише синтаксису: ```shell -php шлях_до_Nette_tools\Code-Checker\code-checker %* +code-checker -d src --ignore "temp/*" +code-checker --only-syntax +``` + +У режимі лише для читання інструмент завершується з кодом `0`, коли все гаразд, і `1`, коли знайдено будь-яку проблему, тож він чудово вписується в CI-конвеєри. + +Повний список опцій: + +``` +Usage: code-checker [options] + +Options: + -d <path> Folder or file to scan (default: current directory) + -i | --ignore <mask> Files to ignore + -f | --fix Fix the files + -l | --eol Normalize line endings to the system default + --only-syntax Check syntax only (faster) + --no-progress Do not show progress dots + --version Show version ``` -Що він робить? -============== +Що робить Code Checker +====================== +- перевіряє синтаксис шаблонів [Latte |latte:] та файлів `.php`, `.neon` і `.json` - видаляє [BOM |nette:glossary#BOM] -- перевіряє валідність [Latte |latte:] шаблонів -- перевіряє валідність файлів `.neon`, `.php` та `.json` +- перевіряє, що файли є коректними UTF-8 - перевіряє наявність [керуючих символів |nette:glossary#Керуючі символи] -- перевіряє, чи файл закодований у UTF-8 -- перевіряє неправильно записані `/* @anotace */` (відсутня зірочка) -- видаляє завершальний `?>` у PHP файлах -- видаляє пробіли в кінці рядка та зайві рядки в кінці файлу -- нормалізує роздільники рядків до системних (якщо вказано опцію `-l`) +- виявляє неправильно записані phpDoc коментарі (напр. `/* @var` замість `/** @var`) +- вимагає відступи табуляцією у файлах PHP, CSS, JS та TS, і пробілами в YAML +- видаляє кінцеві пробіли та порожні рядки в кінці файлів +- нормалізує закінчення рядків на системні (з параметром `-l`) From dba0b388f2841a496834990378521c5604b97721 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Sat, 6 Jun 2026 18:14:46 +0200 Subject: [PATCH 41/50] improved IDE --- tools/bg/ide.texy | 84 -------------------------------------------- tools/cs/ide.texy | 88 +++++++++++++---------------------------------- tools/de/ide.texy | 84 -------------------------------------------- tools/el/ide.texy | 84 -------------------------------------------- tools/en/ide.texy | 88 +++++++++++++---------------------------------- tools/es/ide.texy | 84 -------------------------------------------- tools/fr/ide.texy | 84 -------------------------------------------- tools/hu/ide.texy | 84 -------------------------------------------- tools/it/ide.texy | 84 -------------------------------------------- tools/ja/ide.texy | 84 -------------------------------------------- tools/pl/ide.texy | 84 -------------------------------------------- tools/pt/ide.texy | 84 -------------------------------------------- tools/ro/ide.texy | 84 -------------------------------------------- tools/ru/ide.texy | 84 -------------------------------------------- tools/sl/ide.texy | 84 -------------------------------------------- tools/tr/ide.texy | 84 -------------------------------------------- tools/uk/ide.texy | 84 -------------------------------------------- 17 files changed, 48 insertions(+), 1388 deletions(-) delete mode 100644 tools/bg/ide.texy delete mode 100644 tools/de/ide.texy delete mode 100644 tools/el/ide.texy delete mode 100644 tools/es/ide.texy delete mode 100644 tools/fr/ide.texy delete mode 100644 tools/hu/ide.texy delete mode 100644 tools/it/ide.texy delete mode 100644 tools/ja/ide.texy delete mode 100644 tools/pl/ide.texy delete mode 100644 tools/pt/ide.texy delete mode 100644 tools/ro/ide.texy delete mode 100644 tools/ru/ide.texy delete mode 100644 tools/sl/ide.texy delete mode 100644 tools/tr/ide.texy delete mode 100644 tools/uk/ide.texy diff --git a/tools/bg/ide.texy b/tools/bg/ide.texy deleted file mode 100644 index b1d0e84b88..0000000000 --- a/tools/bg/ide.texy +++ /dev/null @@ -1,84 +0,0 @@ -Редактори & инструменти -*********************** - -.[perex] -Може да сте опитен програмист, но само с добри инструменти ще станете майстор. В тази глава ще намерите съвети за важни инструменти, редактори и плъгини. - - -IDE редактор -============ - -Определено препоръчваме да използвате пълнофункционално IDE за разработка, като PhpStorm, NetBeans, VS Code, а не само текстов редактор с поддръжка на PHP. Разликата е наистина съществена. Няма причина да се задоволявате само с редактор, който може да оцветява синтаксиса, но не достига възможностите на водещо IDE, което точно подсказва, следи за грешки, може да рефакторира код и много повече. Някои IDE са платени, други дори безплатни. - -**NetBeans IDE** има вградена поддръжка за Nette, Latte и NEON. - -**PhpStorm**: инсталирайте тези плъгини в `Settings > Plugins > Marketplace` -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: намерете плъгина "Nette Latte + Neon" в marketplace. - -Свържете също Tracy с редактора си. Когато се покаже страница с грешка, ще можете да кликнете върху имената на файловете и те ще се отворят в редактора с курсор на съответния ред. Прочетете [как да конфигурирате системата |tracy:open-files-in-ide]. - - -PHPStan -======= - -PHPStan е инструмент, който открива логически грешки в кода, преди да го стартирате. - -Инсталираме го с помощта на Composer: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Създаваме конфигурационен файл `phpstan.neon` в проекта: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -И след това го оставяме да анализира класовете в папката `app/`: - -```shell -vendor/bin/phpstan analyse app -``` - -Изчерпателна документация можете да намерите директно на [уебсайта на PHPStan |https://phpstan.org]. - - -Code Checker -============ - -[Code Checker|tools:code-checker] проверява и евентуално коригира някои от формалните грешки във вашия изходен код: - -- премахва [BOM |nette:glossary#BOM] -- проверява валидността на [Latte |latte:] шаблоните -- проверява валидността на файловете `.neon`, `.php` и `.json` -- проверява за наличие на [контролни знаци |nette:glossary#Контролни знаци] -- проверява дали файлът е кодиран в UTF-8 -- проверява за неправилно записани `/* @anotace */` (липсва звездичка) -- премахва затварящия таг `?>` от PHP файловете -- премахва интервалите в края на реда и ненужните редове в края на файла -- нормализира разделителите на редове до системните (ако посочите опцията `-l`) - - -Composer -======== - -[Composer |Composer] е инструмент за управление на зависимости в PHP. Позволява ни да декларираме произволно сложни зависимости на отделни библиотеки и след това ги инсталира вместо нас в нашия проект. - - -Requirements Checker -==================== - -Това беше инструмент, който тестваше средата за изпълнение на сървъра и информираше дали (и до каква степен) е възможно да се използва framework-ът. В момента Nette може да се използва на всеки сървър, който има минималната изисквана версия на PHP. diff --git a/tools/cs/ide.texy b/tools/cs/ide.texy index 1c2d4d8fad..431e6659f5 100644 --- a/tools/cs/ide.texy +++ b/tools/cs/ide.texy @@ -1,84 +1,44 @@ -Editory & nástroje -****************** +Editory a IDE +************* .[perex] -Můžete být zdatný programátor, ale teprve s dobrými nástroji se z vás stane mistr. V této kapitole najdete tipy na důležité nástroje, editory a pluginy. +Dobrý editor vám práci výrazně zpříjemní: obarví syntaxi, našeptává kód a hlídá překlepy. Tady najdete doporučené editory a pluginy pro Nette, Latte a NEON. -IDE editor -========== - -Rozhodně doporučujeme pro vývoj používat plnohodnotné IDE, jako je třeba PhpStorm, NetBeans, VS Code, a nikoliv jen textový editor s podporou PHP. Rozdíl je opravdu zásadní. Není důvod se spokojit s pouhým editorem, který sice umí obarvovat syntaxi, ale nedosahuje možností špičkového IDE, které přesně napovídá, hlídá chyby, umí refaktorovat kód a spoustu dalšího. Některé IDE jsou placené, jiné dokonce zdarma. - -**NetBeans IDE** má podporu pro Nette, Latte a NEON už vestavěnou. +PhpStorm +======== -**PhpStorm**: nainstalujte si tyto pluginy v `Settings > Plugins > Marketplace` +Nainstalujte si tyto pluginy přes `Settings > Plugins > Marketplace`: - [Nette |https://plugins.jetbrains.com/plugin/28342-nette] - [Latte |https://plugins.jetbrains.com/plugin/24218-latte-support] nebo [Latte Pro |https://plugins.jetbrains.com/plugin/19661-latte-pro] - [NEON |https://plugins.jetbrains.com/plugin/28338-neon] nebo [NEON / Nette support |https://plugins.jetbrains.com/plugin/18387-neon-nette-support] -- Nette Tester +- [Nette Tester |https://plugins.jetbrains.com/plugin/8226-nette-tester] -**VS Code**: najděte v marketplace "Nette Latte + Neon" plugin. +Plugin pro Latte je velmi pokročilý a výborně napovídá i PHP kód v šablonách. Aby fungoval optimálně, používejte [typované šablony |latte:type-system]. -Také si propojte Tracy s editorem. Při zobrazení chybové stránky pak půjde kliknout na jména souborů a ty se otevřou v editoru s kurzorem na příslušné řádce. Přečtěte si, [jak systém nakonfigurovat|tracy:open-files-in-ide]. - -PHPStan +VS Code ======= -PHPStan je nástroj, který odhalí logické chyby v kódu dřív, než jej spustíte. - -Nainstalujeme jej pomocí Composeru: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Vytvoříme v projektu konfigurační soubor `phpstan.neon`: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app +V Marketplace najdete několik pluginů: +- [Nette for VS Code |https://marketplace.visualstudio.com/items?itemName=franken-ui.nette-for-vscode] (nejnovější) +- [Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] +- [Nette Latte templates |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] - level: 5 -``` -A následně jej necháme zanalyzovat třídy ve složce `app/`: +Další editory +============= -```shell -vendor/bin/phpstan analyse app -``` - -Vyčerpávající dokumentaci najdete přímo na [stránkách PHPStan |https://phpstan.org]. - - -Code Checker -============ - -[Code Checker|tools:code-checker] zkontroluje a případně opraví některé z formálních chyb ve vašich zdrojových kódech: - -- odstraňuje [BOM |nette:glossary#BOM] -- kontroluje validitu [Latte |latte:] šablon -- kontroluje validitu souborů `.neon`, `.php` a `.json` -- kontroluje výskyt [kontrolních znaků |nette:glossary#Kontrolní znaky] -- kontroluje, zda je soubor kódován v UTF-8 -- kontroluje chybně zapsané `/* @anotace */` (chybí hvězdička) -- odstraňuje ukončovací `?>` u PHP souborů -- odstraňuje pravostranné mezery a zbytečné řádky na konci souboru -- normalizuje oddělovače řádků na systémové (pokud uvedete volbu `-l`) - - -Composer -======== +- NetBeans: vestavěná podpora pro Nette, Latte a NEON +- Sublime Text 3: nainstalujte balíček [Nette Latte Neon |https://github.com/FilipStryk/Nette-Latte-Neon-for-Sublime-Text-3] (dostupný i v Package Control) a pro soubory .latte zvolte Latte ve `View > Syntax` +- VIM: [plugin |https://github.com/fpob/nette.vim] +- Emacs: [plugin pro NEON |https://github.com/Fuco1/neon-mode] +- ve starých editorech použijte pro soubory .latte zvýrazňování Smarty -[Composer] je nástroj na správu závislostí v PHP. Dovoluje nám deklarovat libovolně složité závislosti jednotlivých knihoven a pak je za nás nainstaluje do našeho projektu. +Podporu pro Latte a NEON najdete také ve webovém zvýrazňovači [Prism.js |https://prismjs.com/#supported-languages] a editoru [Ace |https://ace.c9.io]. -Requirements Checker -==================== +Propojení s Tracy +================= -Šlo o nástroj, který testoval běhové prostředí serveru a informoval, zda (a do jaké míry) je možné framework používat. V současnosti je Nette možné používat na každém serveru, který má minimální požadovanou verzi PHP. +Propojte si také Tracy s editorem. Při zobrazení chybové stránky pak půjde kliknout na jména souborů a ty se otevřou v editoru s kurzorem na příslušné řádce. Přečtěte si, [jak systém nakonfigurovat |tracy:open-files-in-ide]. diff --git a/tools/de/ide.texy b/tools/de/ide.texy deleted file mode 100644 index 488b213f91..0000000000 --- a/tools/de/ide.texy +++ /dev/null @@ -1,84 +0,0 @@ -Editoren & Werkzeuge -******************** - -.[perex] -Sie können ein geschickter Programmierer sein, aber erst mit guten Werkzeugen werden Sie zum Meister. In diesem Kapitel finden Sie Tipps zu wichtigen Werkzeugen, Editoren und Plugins. - - -IDE-Editor -========== - -Wir empfehlen dringend, für die Entwicklung eine vollwertige IDE wie PhpStorm, NetBeans, VS Code zu verwenden und nicht nur einen Texteditor mit PHP-Unterstützung. Der Unterschied ist wirklich grundlegend. Es gibt keinen Grund, sich mit einem reinen Editor zufrieden zu geben, der zwar Syntax hervorheben kann, aber nicht die Möglichkeiten einer Spitzen-IDE erreicht, die präzise Vorschläge macht, Fehler überwacht, Code refaktorieren kann und vieles mehr. Einige IDEs sind kostenpflichtig, andere sogar kostenlos. - -**NetBeans IDE** hat bereits integrierte Unterstützung für Nette, Latte und NEON. - -**PhpStorm**: Installieren Sie diese Plugins unter `Settings > Plugins > Marketplace` -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: Suchen Sie im Marketplace nach dem Plugin "Nette Latte + Neon". - -Verbinden Sie auch Tracy mit dem Editor. Bei der Anzeige einer Fehlerseite können Sie dann auf Dateinamen klicken und diese werden im Editor mit dem Cursor an der entsprechenden Zeile geöffnet. Lesen Sie, [wie das System konfiguriert wird|tracy:open-files-in-ide]. - - -PHPStan -======= - -PHPStan ist ein Werkzeug, das logische Fehler im Code aufdeckt, bevor Sie ihn ausführen. - -Wir installieren es mit Composer: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Wir erstellen im Projekt eine Konfigurationsdatei `phpstan.neon`: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -Und lassen es anschließend die Klassen im Ordner `app/` analysieren: - -```shell -vendor/bin/phpstan analyse app -``` - -Eine ausführliche Dokumentation finden Sie direkt auf den [PHPStan-Seiten |https://phpstan.org]. - - -Code Checker -============ - -Der [Code Checker|tools:code-checker] überprüft und korrigiert gegebenenfalls einige formale Fehler in Ihren Quellcodes: - -- entfernt [BOM |nette:glossary#BOM] -- überprüft die Gültigkeit von [Latte |latte:]-Templates -- überprüft die Gültigkeit von `.neon`-, `.php`- und `.json`-Dateien -- überprüft das Vorkommen von [Steuerzeichen |nette:glossary#Steuerzeichen] -- überprüft, ob die Datei in UTF-8 kodiert ist -- überprüft falsch geschriebene `/* @annotation */` (Stern fehlt) -- entfernt abschließende `?>` bei PHP-Dateien -- entfernt Leerzeichen am Zeilenende und unnötige Zeilen am Ende der Datei -- normalisiert Zeilentrenner auf Systemstandard (wenn Sie die Option `-l` angeben) - - -Composer -======== - -[Composer] ist ein Werkzeug zur Verwaltung von Abhängigkeiten in PHP. Es ermöglicht uns, beliebig komplexe Abhängigkeiten einzelner Bibliotheken zu deklarieren und diese dann für uns in unser Projekt zu installieren. - - -Requirements Checker -==================== - -Dies war ein Werkzeug, das die Laufzeitumgebung des Servers testete und informierte, ob (und inwieweit) das Framework verwendet werden kann. Derzeit kann Nette auf jedem Server verwendet werden, der die minimal erforderliche PHP-Version hat. diff --git a/tools/el/ide.texy b/tools/el/ide.texy deleted file mode 100644 index 4aa507357e..0000000000 --- a/tools/el/ide.texy +++ /dev/null @@ -1,84 +0,0 @@ -Επεξεργαστές & εργαλεία -*********************** - -.[perex] -Μπορεί να είστε ένας ικανός προγραμματιστής, αλλά μόνο με καλά εργαλεία γίνεστε μάστορας. Σε αυτό το κεφάλαιο θα βρείτε συμβουλές για σημαντικά εργαλεία, επεξεργαστές και plugins. - - -IDE editor -========== - -Συνιστούμε ανεπιφύλακτα τη χρήση ενός πλήρους IDE για την ανάπτυξη, όπως το PhpStorm, το NetBeans, το VS Code, και όχι απλώς ενός επεξεργαστή κειμένου με υποστήριξη PHP. Η διαφορά είναι πραγματικά θεμελιώδης. Δεν υπάρχει λόγος να αρκεστείτε σε έναν απλό επεξεργαστή που, αν και μπορεί να χρωματίζει τη σύνταξη, δεν φτάνει τις δυνατότητες ενός κορυφαίου IDE, το οποίο προτείνει με ακρίβεια, ελέγχει για σφάλματα, μπορεί να αναδιαμορφώσει τον κώδικα και πολλά άλλα. Ορισμένα IDE είναι επί πληρωμή, άλλα είναι ακόμη και δωρεάν. - -Το **NetBeans IDE** έχει ενσωματωμένη υποστήριξη για Nette, Latte και NEON. - -**PhpStorm**: εγκαταστήστε αυτά τα plugins στο `Settings > Plugins > Marketplace` -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: βρείτε το plugin "Nette Latte + Neon" στο marketplace. - -Συνδέστε επίσης το Tracy με τον επεξεργαστή σας. Όταν εμφανίζεται μια σελίδα σφάλματος, θα μπορείτε να κάνετε κλικ στα ονόματα των αρχείων και αυτά θα ανοίγουν στον επεξεργαστή με τον κέρσορα στην αντίστοιχη γραμμή. Διαβάστε [πώς να διαμορφώσετε το σύστημα |tracy:open-files-in-ide]. - - -PHPStan -======= - -Το PHPStan είναι ένα εργαλείο που εντοπίζει λογικά σφάλματα στον κώδικα πριν τον εκτελέσετε. - -Το εγκαθιστούμε χρησιμοποιώντας το Composer: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Δημιουργούμε στο έργο ένα αρχείο διαμόρφωσης `phpstan.neon`: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -Και στη συνέχεια το αφήνουμε να αναλύσει τις κλάσεις στον φάκελο `app/`: - -```shell -vendor/bin/phpstan analyse app -``` - -Μπορείτε να βρείτε εξαντλητική τεκμηρίωση απευθείας στην [ιστοσελίδα του PHPStan |https://phpstan.org]. - - -Code Checker -============ - -Ο [Code Checker|tools:code-checker] ελέγχει και ενδεχομένως διορθώνει ορισμένα από τα τυπικά σφάλματα στους πηγαίους κώδικές σας: - -- αφαιρεί το [BOM |nette:glossary#BOM] -- ελέγχει την εγκυρότητα των templates [Latte |latte:] -- ελέγχει την εγκυρότητα των αρχείων `.neon`, `.php` και `.json` -- ελέγχει την ύπαρξη [χαρακτήρων ελέγχου |nette:glossary#Control characters] -- ελέγχει αν το αρχείο είναι κωδικοποιημένο σε UTF-8 -- ελέγχει λανθασμένα γραμμένα `/* @anotace */` (λείπει ο αστερίσκος) -- αφαιρεί το τελικό `?>` από τα αρχεία PHP -- αφαιρεί τα δεξιά κενά και τις περιττές γραμμές στο τέλος του αρχείου -- κανονικοποιεί τους διαχωριστές γραμμών σε συστήματος (αν δώσετε την επιλογή `-l`) - - -Composer -======== - -Ο [Composer |Composer] είναι ένα εργαλείο διαχείρισης εξαρτήσεων στο PHP. Μας επιτρέπει να δηλώνουμε αυθαίρετα πολύπλοκες εξαρτήσεις μεμονωμένων βιβλιοθηκών και στη συνέχεια τις εγκαθιστά για εμάς στο έργο μας. - - -Requirements Checker -==================== - -Ήταν ένα εργαλείο που δοκίμαζε το περιβάλλον εκτέλεσης του server και ενημέρωνε αν (και σε ποιο βαθμό) ήταν δυνατό να χρησιμοποιηθεί το framework. Επί του παρόντος, το Nette μπορεί να χρησιμοποιηθεί σε κάθε server που έχει την ελάχιστη απαιτούμενη έκδοση PHP. diff --git a/tools/en/ide.texy b/tools/en/ide.texy index 7430f5893d..fae71603bf 100644 --- a/tools/en/ide.texy +++ b/tools/en/ide.texy @@ -1,84 +1,44 @@ -Editors & Tools -*************** +Editors and IDEs +**************** .[perex] -You might be a skilled programmer, but good tools are what make you a master. This chapter provides tips on essential tools, editors, and plugins. +A good editor makes development much more pleasant: it highlights syntax, autocompletes code, and catches typos. Here are the recommended editors and plugins for Nette, Latte and NEON. -IDE Editor -========== - -We strongly recommend using a full-featured IDE for development, like PhpStorm, NetBeans, or VS Code, rather than just a text editor with PHP support. The difference is truly significant. There's no reason to settle for a basic editor that only offers syntax highlighting when you can have a top-tier IDE providing accurate code suggestions, error checking, refactoring capabilities, and much more. Some IDEs are paid, while others are free. - -**NetBeans IDE** has built-in support for Nette, Latte, and NEON. +PhpStorm +======== -**PhpStorm**: Install these plugins via `Settings > Plugins > Marketplace`: +Install these plugins via `Settings > Plugins > Marketplace`: - [Nette |https://plugins.jetbrains.com/plugin/28342-nette] - [Latte |https://plugins.jetbrains.com/plugin/24218-latte-support] or [Latte Pro |https://plugins.jetbrains.com/plugin/19661-latte-pro] - [NEON |https://plugins.jetbrains.com/plugin/28338-neon] or [NEON / Nette support |https://plugins.jetbrains.com/plugin/18387-neon-nette-support] -- Nette Tester +- [Nette Tester |https://plugins.jetbrains.com/plugin/8226-nette-tester] -**VS Code**: Find the "Nette Latte + Neon" plugin in the marketplace. +The Latte plugin is very advanced and provides excellent PHP code completion in templates. For it to work optimally, use [typed templates |latte:type-system]. -Also, integrate Tracy with your editor. When an error page is displayed, clicking on file names will open them directly in your editor at the corresponding line. Learn [how to configure this feature |tracy:open-files-in-ide]. - -PHPStan +VS Code ======= -PHPStan is a static analysis tool that detects logical errors in your code before you even run it. - -Install it using Composer: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Create a configuration file `phpstan.neon` in your project: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app +There are several plugins in the Marketplace: +- [Nette for VS Code |https://marketplace.visualstudio.com/items?itemName=franken-ui.nette-for-vscode] (newest) +- [Nette Latte + Neon |https://marketplace.visualstudio.com/items?itemName=Kasik96.latte] +- [Nette Latte templates |https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] - level: 5 -``` -Then, let it analyze the classes within the `app/` directory: +Other Editors +============= -```shell -vendor/bin/phpstan analyse app -``` - -You can find comprehensive documentation directly on the [PHPStan website |https://phpstan.org]. - - -Code Checker -============ - -[Code Checker|tools:code-checker] checks and potentially fixes some formal errors in your source code: - -- removes [BOM |nette:glossary#BOM] -- checks the validity of [Latte |latte:] templates -- checks the validity of `.neon`, `.php`, and `.json` files -- checks for [control characters |nette:glossary#Control Characters] -- checks if the file is encoded in UTF-8 -- checks for incorrectly written `/* @annotations */` (missing second asterisk) -- removes trailing `?>` PHP tags from files containing only PHP code -- removes trailing whitespace and unnecessary blank lines at the end of files -- normalizes line endings to the system default (using the `-l` option) - - -Composer -======== +- NetBeans: built-in support for Nette, Latte, and NEON +- Sublime Text 3: install the [Nette Latte Neon |https://github.com/FilipStryk/Nette-Latte-Neon-for-Sublime-Text-3] package (also available in Package Control) and select Latte in `View > Syntax` for .latte files +- VIM: [plugin |https://github.com/fpob/nette.vim] +- Emacs: [NEON plugin |https://github.com/Fuco1/neon-mode] +- in older editors, use Smarty highlighting for .latte files -[Composer] is a tool for dependency management in PHP. It allows you to declare the libraries your project depends on and manages their installation and updates. +Support for Latte and NEON is also available in the web highlighter [Prism.js |https://prismjs.com/#supported-languages] and the [Ace |https://ace.c9.io] editor. -Requirements Checker -==================== +Tracy Integration +================= -This was a tool that tested the server's runtime environment and indicated whether (and to what extent) the framework could be used. Currently, Nette can be used on any server that meets the minimum required PHP version. +Also integrate Tracy with your editor. When an error page is displayed, clicking on file names will open them directly in your editor at the corresponding line. Learn [how to configure this feature |tracy:open-files-in-ide]. diff --git a/tools/es/ide.texy b/tools/es/ide.texy deleted file mode 100644 index 31bcbd3953..0000000000 --- a/tools/es/ide.texy +++ /dev/null @@ -1,84 +0,0 @@ -Editores y herramientas -*********************** - -.[perex] -Puedes ser un programador competente, pero solo con buenas herramientas te convertirás en un maestro. En este capítulo encontrarás consejos sobre herramientas, editores y plugins importantes. - - -Editor IDE -========== - -Recomendamos encarecidamente utilizar un IDE completo para el desarrollo, como PhpStorm, NetBeans, VS Code, y no solo un editor de texto con soporte para PHP. La diferencia es realmente fundamental. No hay razón para conformarse con un simple editor que colorea la sintaxis pero no alcanza las capacidades de un IDE de primer nivel, que sugiere con precisión, detecta errores, puede refactorizar código y mucho más. Algunos IDE son de pago, otros incluso gratuitos. - -**NetBeans IDE** ya tiene soporte integrado para Nette, Latte y NEON. - -**PhpStorm**: instala estos plugins en `Settings > Plugins > Marketplace` -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: busca el plugin "Nette Latte + Neon" en el marketplace. - -También vincula Tracy con tu editor. Cuando se muestre una página de error, podrás hacer clic en los nombres de los archivos y se abrirán en el editor con el cursor en la línea correspondiente. Lee [cómo configurar el sistema|tracy:open-files-in-ide]. - - -PHPStan -======= - -PHPStan es una herramienta que detecta errores lógicos en el código antes de ejecutarlo. - -Lo instalamos usando Composer: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Creamos un archivo de configuración `phpstan.neon` en el proyecto: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -Y luego le pedimos que analice las clases en la carpeta `app/`: - -```shell -vendor/bin/phpstan analyse app -``` - -Encontrarás documentación exhaustiva directamente en el [sitio web de PHPStan |https://phpstan.org]. - - -Code Checker -============ - -[Code Checker|tools:code-checker] comprueba y, opcionalmente, corrige algunos de los errores formales en tus códigos fuente: - -- elimina [BOM |nette:glossary#BOM] -- comprueba la validez de las plantillas [Latte |latte:] -- comprueba la validez de los archivos `.neon`, `.php` y `.json` -- comprueba la presencia de [caracteres de control |nette:glossary#Caracteres de control] -- comprueba si el archivo está codificado en UTF-8 -- comprueba `/* @anotaciones */` mal escritas (falta el asterisco) -- elimina el `?>` final de los archivos PHP -- elimina los espacios finales y las líneas innecesarias al final del archivo -- normaliza los separadores de línea a los del sistema (si se especifica la opción `-l`) - - -Composer -======== - -[Composer |Composer] es una herramienta para gestionar dependencias en PHP. Nos permite declarar dependencias arbitrariamente complejas de bibliotecas individuales y luego las instala por nosotros en nuestro proyecto. - - -Requirements Checker -==================== - -Era una herramienta que probaba el entorno de ejecución del servidor e informaba si (y en qué medida) se podía utilizar el framework. Actualmente, Nette se puede utilizar en cualquier servidor que tenga la versión mínima requerida de PHP. diff --git a/tools/fr/ide.texy b/tools/fr/ide.texy deleted file mode 100644 index ea29942514..0000000000 --- a/tools/fr/ide.texy +++ /dev/null @@ -1,84 +0,0 @@ -Éditeurs & Outils -***************** - -.[perex] -Vous pouvez être un programmeur compétent, mais ce n'est qu'avec de bons outils que vous deviendrez un maître. Dans ce chapitre, vous trouverez des conseils sur les outils, éditeurs et plugins importants. - - -Éditeur IDE -=========== - -Nous recommandons vivement d'utiliser un IDE complet pour le développement, tel que PhpStorm, NetBeans, VS Code, et pas seulement un éditeur de texte avec prise en charge PHP. La différence est vraiment fondamentale. Il n'y a aucune raison de se contenter d'un simple éditeur qui colore la syntaxe mais n'atteint pas les capacités d'un IDE de pointe, qui suggère précisément, surveille les erreurs, peut refactoriser le code et bien plus encore. Certains IDE sont payants, d'autres sont même gratuits. - -**NetBeans IDE** intègre déjà la prise en charge de Nette, Latte et NEON. - -**PhpStorm** : installez ces plugins dans `Settings > Plugins > Marketplace` -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code** : trouvez le plugin "Nette Latte + Neon" dans le marketplace. - -Connectez également Tracy à votre éditeur. Lorsque la page d'erreur s'affiche, vous pourrez cliquer sur les noms de fichiers et ils s'ouvriront dans l'éditeur avec le curseur sur la ligne correspondante. Lisez [comment configurer le système|tracy:open-files-in-ide]. - - -PHPStan -======= - -PHPStan est un outil qui détecte les erreurs logiques dans le code avant même de l'exécuter. - -Nous l'installons à l'aide de Composer : - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Nous créons un fichier de configuration `phpstan.neon` dans le projet : - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -Et ensuite, nous le laissons analyser les classes dans le dossier `app/` : - -```shell -vendor/bin/phpstan analyse app -``` - -Vous trouverez une documentation exhaustive directement sur le [site web de PHPStan |https://phpstan.org]. - - -Code Checker -============ - -[Code Checker|tools:code-checker] vérifie et corrige éventuellement certaines erreurs formelles dans vos codes sources : - -- supprime le [BOM |nette:glossary#BOM] -- vérifie la validité des templates [Latte |latte:] -- vérifie la validité des fichiers `.neon`, `.php` et `.json` -- vérifie la présence de [caractères de contrôle |nette:glossary#Caractères de contrôle] -- vérifie si le fichier est encodé en UTF-8 -- vérifie les `/* @anotace */` mal écrites (manque une étoile) -- supprime les `?>` de fin dans les fichiers PHP -- supprime les espaces de fin de ligne et les lignes vides inutiles à la fin du fichier -- normalise les séparateurs de ligne en séparateurs système (si vous spécifiez l'option `-l`) - - -Composer -======== - -[Composer |best-practices:composer] est un outil de gestion des dépendances en PHP. Il nous permet de déclarer des dépendances arbitrairement complexes de différentes bibliothèques et les installe ensuite pour nous dans notre projet. - - -Requirements Checker -==================== - -C'était un outil qui testait l'environnement d'exécution du serveur et informait si (et dans quelle mesure) le framework pouvait être utilisé. Actuellement, Nette peut être utilisé sur n'importe quel serveur disposant de la version minimale requise de PHP. diff --git a/tools/hu/ide.texy b/tools/hu/ide.texy deleted file mode 100644 index 4ff8d1307e..0000000000 --- a/tools/hu/ide.texy +++ /dev/null @@ -1,84 +0,0 @@ -Szerkesztők és eszközök -*********************** - -.[perex] -Lehetsz ügyes programozó, de csak jó eszközökkel válsz mesterré. Ebben a fejezetben tippeket találsz fontos eszközökhöz, szerkesztőkhöz és bővítményekhez. - - -IDE szerkesztő -============== - -Határozottan javasoljuk, hogy a fejlesztéshez teljes értékű IDE-t használj, mint például a PhpStorm, NetBeans, VS Code, és ne csak egy PHP támogatással rendelkező szövegszerkesztőt. A különbség valóban alapvető. Nincs ok megelégedni egy egyszerű szerkesztővel, amely ugyan tudja színezni a szintaxist, de nem éri el egy csúcskategóriás IDE képességeit, amely pontosan súg, figyeli a hibákat, képes refaktorálni a kódot és sok minden mást. Néhány IDE fizetős, mások pedig ingyenesek. - -A **NetBeans IDE** beépített támogatással rendelkezik a Nette, Latte és NEON számára. - -**PhpStorm**: telepítsd ezeket a bővítményeket a `Settings > Plugins > Marketplace` menüpontban: -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: keresd meg a marketplace-en a "Nette Latte + Neon" bővítményt. - -Kapcsold össze a Tracy-t is a szerkesztővel. Amikor egy hibaoldal jelenik meg, rákattinthatsz a fájlnevekre, és azok megnyílnak a szerkesztőben a megfelelő sorra állított kurzorral. Olvasd el, [hogyan konfiguráld a rendszert |tracy:open-files-in-ide]. - - -PHPStan -======= - -A PHPStan egy eszköz, amely logikai hibákat tár fel a kódban, mielőtt futtatnád azt. - -Telepítsük a Composer segítségével: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Hozzunk létre egy konfigurációs fájlt a projektben `phpstan.neon` néven: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -Majd futtassuk az elemzést az `app/` mappában lévő osztályokon: - -```shell -vendor/bin/phpstan analyse app -``` - -Kimerítő dokumentációt találsz közvetlenül a [PHPStan oldalán |https://phpstan.org]. - - -Code Checker -============ - -A [Code Checker|tools:code-checker] ellenőrzi és szükség esetén kijavítja a forráskódok néhány formai hibáját: - -- eltávolítja a [BOM |nette:glossary#BOM]-ot -- ellenőrzi a [Latte |latte:] sablonok érvényességét -- ellenőrzi a `.neon`, `.php` és `.json` fájlok érvényességét -- ellenőrzi a [vezérlőkarakterek |nette:glossary#Vezérlő karakterek] előfordulását -- ellenőrzi, hogy a fájl UTF-8 kódolású-e -- ellenőrzi a hibásan írt `/* @anotace */` (hiányzik a csillag) -- eltávolítja a záró `?>` PHP fájlokból -- eltávolítja a jobb oldali szóközöket és a felesleges sorokat a fájl végéről -- normalizálja a sorelválasztókat a rendszer alapértelmezettjére (ha megadja a `-l` opciót) - - -Composer -======== - -A [Composer |best-practices:composer] egy függőségkezelő eszköz PHP-hez. Lehetővé teszi számunkra, hogy tetszőlegesen összetett függőségeket deklaráljunk az egyes könyvtárakhoz, majd telepíti őket a projektünkbe. - - -Requirements Checker -==================== - -Ez egy eszköz volt, amely tesztelte a szerver futási környezetét, és tájékoztatott arról, hogy (és milyen mértékben) lehet használni a keretrendszert. Jelenleg a Nette minden olyan szerveren használható, amely rendelkezik a minimálisan szükséges PHP verzióval. diff --git a/tools/it/ide.texy b/tools/it/ide.texy deleted file mode 100644 index 70ad5a31ef..0000000000 --- a/tools/it/ide.texy +++ /dev/null @@ -1,84 +0,0 @@ -Editor e strumenti -****************** - -.[perex] -Potreste essere un programmatore esperto, ma solo con i buoni strumenti diventerete dei maestri. In questo capitolo troverete suggerimenti su strumenti, editor e plugin importanti. - - -Editor IDE -========== - -Consigliamo vivamente di utilizzare un IDE completo per lo sviluppo, come PhpStorm, NetBeans, VS Code, e non solo un editor di testo con supporto PHP. La differenza è davvero fondamentale. Non c'è motivo di accontentarsi di un semplice editor che colora la sintassi ma non raggiunge le capacità di un IDE di alto livello, che suggerisce con precisione, controlla gli errori, sa refattorizzare il codice e molto altro. Alcuni IDE sono a pagamento, altri addirittura gratuiti. - -**NetBeans IDE** ha il supporto per Nette, Latte e NEON già integrato. - -**PhpStorm**: installate questi plugin in `Settings > Plugins > Marketplace` -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: cercate nel marketplace il plugin "Nette Latte + Neon". - -Collegate anche Tracy all'editor. Quando viene visualizzata una pagina di errore, potrete cliccare sui nomi dei file e questi si apriranno nell'editor con il cursore sulla riga corrispondente. Leggete [come configurare il sistema|tracy:open-files-in-ide]. - - -PHPStan -======= - -PHPStan è uno strumento che rileva gli errori logici nel codice prima ancora di eseguirlo. - -Lo installiamo tramite Composer: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Creiamo nel progetto il file di configurazione `phpstan.neon`: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -E successivamente lo facciamo analizzare le classi nella cartella `app/`: - -```shell -vendor/bin/phpstan analyse app -``` - -Troverete una documentazione esaustiva direttamente sul [sito web di PHPStan |https://phpstan.org]. - - -Code Checker -============ - -[Code Checker|tools:code-checker] controlla ed eventualmente corregge alcuni errori formali nei vostri codici sorgente: - -- rimuove il [BOM |nette:glossary#BOM] -- controlla la validità dei template [Latte |latte:] -- controlla la validità dei file `.neon`, `.php` e `.json` -- controlla la presenza di [caratteri di controllo |nette:glossary#Caratteri di controllo] -- controlla se il file è codificato in UTF-8 -- controlla `/* @anotace */` scritti erroneamente (manca l'asterisco) -- rimuove il tag di chiusura `?>` dai file PHP -- rimuove gli spazi finali e le righe vuote alla fine del file -- normalizza i separatori di riga a quelli di sistema (se si specifica l'opzione `-l`) - - -Composer -======== - -[Composer |Composer] è uno strumento per la gestione delle dipendenze in PHP. Ci permette di dichiarare dipendenze arbitrariamente complesse tra le singole librerie e poi le installa per noi nel nostro progetto. - - -Requirements Checker -==================== - -Era uno strumento che testava l'ambiente di runtime del server e informava se (e in che misura) fosse possibile utilizzare il framework. Attualmente, Nette può essere utilizzato su qualsiasi server che abbia la versione minima richiesta di PHP. diff --git a/tools/ja/ide.texy b/tools/ja/ide.texy deleted file mode 100644 index 25ae2c5845..0000000000 --- a/tools/ja/ide.texy +++ /dev/null @@ -1,84 +0,0 @@ -エディタとツール -******** - -.[perex] -あなたは熟練したプログラマかもしれませんが、優れたツールがあってこそマスターになれます。この章では、重要なツール、エディタ、プラグインのヒントを紹介します。 - - -IDEエディタ -======= - -開発には、PhpStorm、NetBeans、VS Codeなどの本格的なIDEを使用することを強くお勧めします。単なるPHPサポート付きのテキストエディタだけではありません。違いは本当に決定的です。構文を色付けできるだけの単なるエディタで満足する理由はありません。それは、正確なヒントを提供し、エラーを監視し、コードをリファクタリングし、その他多くのことができるトップクラスのIDEの能力には及びません。一部のIDEは有料ですが、無料のものもあります。 - -**NetBeans IDE** は、Nette、Latte、NEONのサポートを組み込みで持っています。 - -**PhpStorm**: `Settings > Plugins > Marketplace` でこれらのプラグインをインストールしてください -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: マーケットプレイスで "Nette Latte + Neon" プラグインを見つけてください。 - -また、Tracyをエディタと連携させてください。エラーページが表示されたときに、ファイル名をクリックすると、エディタで該当する行にカーソルがある状態で開くことができます。[システムの設定方法|tracy:open-files-in-ide] を読んでください。 - - -PHPStan -======= - -PHPStanは、コードを実行する前に論理エラーを検出するツールです。 - -Composerを使用してインストールします: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -プロジェクトに設定ファイル `phpstan.neon` を作成します: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -そして、`app/` フォルダ内のクラスを分析させます: - -```shell -vendor/bin/phpstan analyse app -``` - -包括的なドキュメントは、[PHPStanのサイト |https://phpstan.org] で直接見つけることができます。 - - -Code Checker -============ - -[Code Checker|tools:code-checker] は、ソースコード内の一部の形式的なエラーをチェックし、場合によっては修正します: - -- [BOM |nette:glossary#BOM] を削除します -- [Latte |latte:] テンプレートの有効性をチェックします -- `.neon`、`.php`、`.json` ファイルの有効性をチェックします -- [制御文字 |nette:glossary#制御文字] の出現をチェックします -- ファイルがUTF-8でエンコードされているかチェックします -- 誤って書かれた `/* @anotace */` (アスタリスクが欠けている)をチェックします -- PHPファイルの終了タグ `?>` を削除します -- ファイルの末尾にある右側のスペースや不要な行を削除します -- `-l` オプションを指定した場合、行区切り文字をシステムのものに正規化します - - -Composer -======== - -[Composer |best-practices:composer] はPHPの依存関係管理ツールです。これにより、個々のライブラリの任意の複雑な依存関係を宣言し、それらをプロジェクトにインストールすることができます。 - - -Requirements Checker -==================== - -これは、サーバーの実行環境をテストし、フレームワークを使用できるかどうか(およびどの程度まで)を通知するツールでした。現在、Netteは最小限必要なPHPバージョンを持つすべてのサーバーで使用できます。 diff --git a/tools/pl/ide.texy b/tools/pl/ide.texy deleted file mode 100644 index 70e1791cfa..0000000000 --- a/tools/pl/ide.texy +++ /dev/null @@ -1,84 +0,0 @@ -Edytory i narzędzia -******************* - -.[perex] -Możesz być biegłym programistą, ale dopiero z dobrymi narzędziami staniesz się mistrzem. W tym rozdziale znajdziesz wskazówki dotyczące ważnych narzędzi, edytorów i wtyczek. - - -Edytor IDE -========== - -Zdecydowanie zalecamy używanie do programowania pełnoprawnego IDE, takiego jak PhpStorm, NetBeans, VS Code, a nie tylko edytora tekstu z obsługą PHP. Różnica jest naprawdę zasadnicza. Nie ma powodu zadowalać się zwykłym edytorem, który co prawda potrafi kolorować składnię, ale nie dorównuje możliwościom zaawansowanego IDE, które precyzyjnie podpowiada, pilnuje błędów, potrafi refaktoryzować kod i wiele więcej. Niektóre IDE są płatne, inne nawet darmowe. - -**NetBeans IDE** ma wbudowane wsparcie dla Nette, Latte i NEON. - -**PhpStorm**: zainstaluj te wtyczki w `Settings > Plugins > Marketplace` -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: znajdź w marketplace wtyczkę "Nette Latte + Neon". - -Połącz również Tracy z edytorem. Podczas wyświetlania strony błędu będzie można kliknąć na nazwy plików, a te otworzą się w edytorze z kursorem na odpowiedniej linii. Przeczytaj, [jak skonfigurować system|tracy:open-files-in-ide]. - - -PHPStan -======= - -PHPStan to narzędzie, które wykrywa błędy logiczne w kodzie, zanim go uruchomisz. - -Zainstalujemy go za pomocą Composera: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Utworzymy w projekcie plik konfiguracyjny `phpstan.neon`: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -A następnie zlecimy mu analizę klas w folderze `app/`: - -```shell -vendor/bin/phpstan analyse app -``` - -Wyczerpującą dokumentację znajdziesz bezpośrednio na [stronie PHPStan |https://phpstan.org]. - - -Code Checker -============ - -[Code Checker|tools:code-checker] sprawdza i ewentualnie poprawia niektóre błędy formalne w twoich kodach źródłowych: - -- usuwa [BOM |nette:glossary#BOM] -- sprawdza poprawność szablonów [Latte |latte:] -- sprawdza poprawność plików `.neon`, `.php` i `.json` -- sprawdza występowanie [znaków kontrolnych |nette:glossary#Znaki kontrolne] -- sprawdza, czy plik jest kodowany w UTF-8 -- sprawdza błędnie zapisane `/* @anotace */` (brakuje gwiazdki) -- usuwa kończące `?>` w plikach PHP -- usuwa spacje na końcu linii i zbędne linie na końcu pliku -- normalizuje separatory linii do systemowych (jeśli podasz opcję `-l`) - - -Composer -======== - -[Composer|best-practices:composer] to narzędzie do zarządzania zależnościami w PHP. Pozwala nam deklarować dowolnie złożone zależności poszczególnych bibliotek, a następnie instaluje je za nas w naszym projekcie. - - -Requirements Checker -==================== - -Było to narzędzie, które testowało środowisko uruchomieniowe serwera i informowało, czy (i w jakim stopniu) można używać frameworka. Obecnie Nette można używać na każdym serwerze, który ma minimalną wymaganą wersję PHP. diff --git a/tools/pt/ide.texy b/tools/pt/ide.texy deleted file mode 100644 index 6b10da25b7..0000000000 --- a/tools/pt/ide.texy +++ /dev/null @@ -1,84 +0,0 @@ -Editores & Ferramentas -********************** - -.[perex] -Você pode ser um programador habilidoso, mas é com boas ferramentas que você se torna um mestre. Neste capítulo, você encontrará dicas sobre ferramentas importantes, editores e plugins. - - -Editor IDE -========== - -Recomendamos fortemente o uso de um IDE completo para desenvolvimento, como PhpStorm, NetBeans, VS Code, e não apenas um editor de texto com suporte a PHP. A diferença é realmente fundamental. Não há razão para se contentar com um simples editor que, embora possa colorir a sintaxe, não atinge as capacidades de um IDE de ponta, que sugere com precisão, monitora erros, pode refatorar código e muito mais. Alguns IDEs são pagos, outros são até gratuitos. - -**NetBeans IDE** já vem com suporte integrado para Nette, Latte e NEON. - -**PhpStorm**: instale estes plugins em `Settings > Plugins > Marketplace` -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: encontre o plugin "Nette Latte + Neon" no marketplace. - -Conecte também o Tracy ao seu editor. Ao exibir uma página de erro, você poderá clicar nos nomes dos arquivos e eles serão abertos no editor com o cursor na linha correspondente. Leia [como configurar o sistema|tracy:open-files-in-ide]. - - -PHPStan -======= - -PHPStan é uma ferramenta que detecta erros lógicos no código antes mesmo de você executá-lo. - -Instalamos usando o Composer: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Criamos um arquivo de configuração `phpstan.neon` no projeto: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -E, em seguida, deixamos que ele analise as classes na pasta `app/`: - -```shell -vendor/bin/phpstan analyse app -``` - -Você encontrará documentação completa diretamente no [site do PHPStan |https://phpstan.org]. - - -Code Checker -============ - -O [Code Checker|tools:code-checker] verifica e, opcionalmente, corrige alguns erros formais em seus códigos-fonte: - -- remove [BOM |nette:glossary#BOM] -- verifica a validade dos templates [Latte |latte:] -- verifica a validade dos arquivos `.neon`, `.php` e `.json` -- verifica a ocorrência de [caracteres de controle |nette:glossary#Caracteres de controle] -- verifica se o arquivo está codificado em UTF-8 -- verifica `/* @anotações */` escritas incorretamente (falta um asterisco) -- remove `?>` de fechamento em arquivos PHP -- remove espaços em branco à direita e linhas desnecessárias no final do arquivo -- normaliza os separadores de linha para os do sistema (se você usar a opção `-l`) - - -Composer -======== - -[Composer|best-practices:composer] é uma ferramenta para gerenciamento de dependências em PHP. Permite declarar dependências arbitrariamente complexas de bibliotecas individuais e, em seguida, as instala para nós em nosso projeto. - - -Requirements Checker -==================== - -Era uma ferramenta que testava o ambiente de execução do servidor e informava se (e em que medida) o framework poderia ser usado. Atualmente, o Nette pode ser usado em qualquer servidor que tenha a versão mínima exigida do PHP. diff --git a/tools/ro/ide.texy b/tools/ro/ide.texy deleted file mode 100644 index 4923cc5bd7..0000000000 --- a/tools/ro/ide.texy +++ /dev/null @@ -1,84 +0,0 @@ -Editoare & instrumente -********************** - -.[perex] -Poți fi un programator priceput, dar numai cu instrumentele potrivite devii un maestru. În acest capitol vei găsi sfaturi despre instrumente, editoare și plugin-uri importante. - - -Editor IDE -========== - -Recomandăm cu tărie utilizarea unui IDE complet pentru dezvoltare, cum ar fi PhpStorm, NetBeans, VS Code, și nu doar un editor de text cu suport pentru PHP. Diferența este cu adevărat fundamentală. Nu există niciun motiv să te mulțumești cu un simplu editor care colorează sintaxa, dar nu atinge capacitățile unui IDE de top, care oferă sugestii precise, verifică erorile, poate refactoriza codul și multe altele. Unele IDE-uri sunt plătite, altele sunt chiar gratuite. - -**NetBeans IDE** are suport încorporat pentru Nette, Latte și NEON. - -**PhpStorm**: instalează aceste plugin-uri în `Settings > Plugins > Marketplace` -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: găsește pluginul "Nette Latte + Neon" în marketplace. - -Conectează, de asemenea, Tracy la editor. Când se afișează pagina de eroare, vei putea da clic pe numele fișierelor și acestea se vor deschide în editor cu cursorul pe linia corespunzătoare. Citește [cum să configurezi sistemul |tracy:open-files-in-ide]. - - -PHPStan -======= - -PHPStan este un instrument care detectează erorile logice din cod înainte de a-l rula. - -Îl instalăm folosind Composer: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Creăm în proiect fișierul de configurare `phpstan.neon`: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -Și apoi îl lăsăm să analizeze clasele din directorul `app/`: - -```shell -vendor/bin/phpstan analyse app -``` - -Documentația exhaustivă o găsiți direct pe [site-ul PHPStan |https://phpstan.org]. - - -Code Checker -============ - -[Code Checker |tools:code-checker] verifică și, eventual, corectează unele dintre erorile formale din codurile sursă: - -- elimină [BOM |nette:glossary#BOM] -- verifică validitatea șabloanelor [Latte |latte:] -- verifică validitatea fișierelor `.neon`, `.php` și `.json` -- verifică prezența [caracterelor de control |nette:glossary#Caractere de control] -- verifică dacă fișierul este codificat în UTF-8 -- verifică `/* @anotace */` scrise incorect (lipsește asteriscul) -- elimină `?>` de închidere din fișierele PHP -- elimină spațiile de la sfârșitul rândului și rândurile goale inutile de la sfârșitul fișierului -- normalizează delimitatorii de rând la cei de sistem (dacă specificați opțiunea `-l`) - - -Composer -======== - -[Composer |best-practices:composer] este un instrument pentru gestionarea dependențelor în PHP. Ne permite să declarăm dependențe oricât de complexe ale diferitelor biblioteci și apoi le instalează pentru noi în proiectul nostru. - - -Requirements Checker -==================== - -Acesta a fost un instrument care testa mediul de rulare al serverului și informa dacă (și în ce măsură) framework-ul poate fi utilizat. În prezent, Nette poate fi utilizat pe orice server care are versiunea minimă necesară de PHP. diff --git a/tools/ru/ide.texy b/tools/ru/ide.texy deleted file mode 100644 index bc6a4282a4..0000000000 --- a/tools/ru/ide.texy +++ /dev/null @@ -1,84 +0,0 @@ -Редакторы и инструменты -*********************** - -.[perex] -Вы можете быть опытным программистом, но только с хорошими инструментами вы станете мастером. В этой главе вы найдете советы по важным инструментам, редакторам и плагинам. - - -IDE редактор -============ - -Мы настоятельно рекомендуем использовать для разработки полноценную IDE, такую как PhpStorm, NetBeans, VS Code, а не просто текстовый редактор с поддержкой PHP. Разница действительно существенная. Нет причин довольствоваться простым редактором, который хоть и умеет подсвечивать синтаксис, но не достигает возможностей передовой IDE, которая точно подсказывает, отслеживает ошибки, умеет рефакторить код и многое другое. Некоторые IDE платные, другие даже бесплатные. - -**NetBeans IDE** имеет встроенную поддержку Nette, Latte и NEON. - -**PhpStorm**: установите эти плагины в `Settings > Plugins > Marketplace` -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: найдите в marketplace плагин "Nette Latte + Neon". - -Также свяжите Tracy с редактором. При отображении страницы ошибки можно будет кликнуть на имена файлов, и они откроются в редакторе с курсором на соответствующей строке. Прочтите, [как настроить систему|tracy:open-files-in-ide]. - - -PHPStan -======= - -PHPStan — это инструмент, который обнаруживает логические ошибки в коде до его запуска. - -Установим его с помощью Composer: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Создадим в проекте конфигурационный файл `phpstan.neon`: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -А затем позволим ему проанализировать классы в папке `app/`: - -```shell -vendor/bin/phpstan analyse app -``` - -Исчерпывающую документацию вы найдете прямо на [сайте PHPStan |https://phpstan.org]. - - -Code Checker -============ - -[Code Checker|tools:code-checker] проверяет и, при необходимости, исправляет некоторые формальные ошибки в ваших исходных кодах: - -- удаляет [BOM |nette:glossary#BOM] -- проверяет валидность шаблонов [Latte |latte:] -- проверяет валидность файлов `.neon`, `.php` и `.json` -- проверяет наличие [контрольных символов |nette:glossary#Управляющие символы] -- проверяет, закодирован ли файл в UTF-8 -- проверяет неправильно записанные `/* @anotace */` (отсутствует звездочка) -- удаляет завершающие `?>` в PHP файлах -- удаляет пробелы в конце строк и лишние строки в конце файла -- нормализует разделители строк к системным (если указана опция `-l`) - - -Composer -======== - -[Composer] — это инструмент для управления зависимостями в PHP. Он позволяет нам объявлять произвольно сложные зависимости отдельных библиотек и затем устанавливает их для нас в наш проект. - - -Requirements Checker -==================== - -Это был инструмент, который тестировал среду выполнения сервера и сообщал, можно ли (и в какой степени) использовать фреймворк. В настоящее время Nette можно использовать на любом сервере, имеющем минимально требуемую версию PHP. diff --git a/tools/sl/ide.texy b/tools/sl/ide.texy deleted file mode 100644 index ec48ae25ea..0000000000 --- a/tools/sl/ide.texy +++ /dev/null @@ -1,84 +0,0 @@ -Urejevalniki & orodja -********************* - -.[perex] -Lahko ste spreten programer, vendar šele z dobrimi orodji postanete mojster. V tem poglavju boste našli nasvete za pomembna orodja, urejevalnike in vtičnike. - - -IDE urejevalnik -=============== - -Vsekakor priporočamo, da za razvoj uporabljate polnopravno IDE, kot so na primer PhpStorm, NetBeans, VS Code, in ne le urejevalnika besedil s podporo za PHP. Razlika je resnično bistvena. Ni razloga, da bi se zadovoljili zgolj z urejevalnikom, ki sicer zna obarvati sintakso, vendar ne dosega zmožnosti vrhunskega IDE-ja, ki natančno predlaga, preverja napake, zna refaktorirati kodo in še veliko več. Nekateri IDE-ji so plačljivi, drugi celo brezplačni. - -**NetBeans IDE** ima podporo za Nette, Latte in NEON že vgrajeno. - -**PhpStorm**: namestite te vtičnike v `Settings > Plugins > Marketplace` -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: v tržnici (marketplace) poiščite vtičnik "Nette Latte + Neon". - -Povežite tudi Tracy z urejevalnikom. Pri prikazu strani z napako bo potem mogoče klikniti na imena datotek, ki se bodo odprla v urejevalniku s kazalcem na ustrezni vrstici. Preberite, [kako konfigurirati sistem|tracy:open-files-in-ide]. - - -PHPStan -======= - -PHPStan je orodje, ki odkrije logične napake v kodi, preden jo zaženete. - -Namestimo ga s pomočjo Composerja: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -V projektu ustvarimo konfiguracijsko datoteko `phpstan.neon`: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -Nato pustimo, da analizira razrede v mapi `app/`: - -```shell -vendor/bin/phpstan analyse app -``` - -Izčrpno dokumentacijo najdete neposredno na [straneh PHPStan |https://phpstan.org]. - - -Code Checker -============ - -[Code Checker|tools:code-checker] preveri in po potrebi popravi nekatere formalne napake v vaši izvorni kodi: - -- odstranjuje [BOM |nette:glossary#BOM] -- preverja veljavnost predlog [Latte |latte:] -- preverja veljavnost datotek `.neon`, `.php` in `.json` -- preverja pojav [kontrolnih znakov |nette:glossary#Kontrolni znaki] -- preverja, ali je datoteka kodirana v UTF-8 -- preverja napačno zapisane `/* @anotacije */` (manjka zvezdica) -- odstranjuje zaključno oznako `?>` pri PHP datotekah -- odstranjuje presledke na desni strani in nepotrebne vrstice na koncu datoteke -- normalizira ločila vrstic na sistemska (če navedete možnost `-l`) - - -Composer -======== - -[Composer |best-practices:composer] je orodje za upravljanje odvisnosti v PHP. Omogoča nam deklariranje poljubno zapletenih odvisnosti posameznih knjižnic in jih nato za nas namesti v naš projekt. - - -Requirements Checker -==================== - -To je bilo orodje, ki je testiralo izvajalno okolje strežnika in obveščalo, ali (in v kolikšni meri) je mogoče ogrodje uporabljati. Trenutno je Nette mogoče uporabljati na vsakem strežniku, ki ima minimalno zahtevano različico PHP. diff --git a/tools/tr/ide.texy b/tools/tr/ide.texy deleted file mode 100644 index 9a0c49ad71..0000000000 --- a/tools/tr/ide.texy +++ /dev/null @@ -1,84 +0,0 @@ -Editörler & Araçlar -******************* - -.[perex] -Yetenekli bir programcı olabilirsiniz, ancak ancak iyi araçlarla bir usta olursunuz. Bu bölümde önemli araçlar, editörler ve eklentiler hakkında ipuçları bulacaksınız. - - -IDE Editörü -=========== - -Geliştirme için kesinlikle PhpStorm, NetBeans, VS Code gibi tam özellikli bir IDE kullanmanızı öneririz, sadece PHP desteği olan bir metin editörü değil. Fark gerçekten çok büyük. Sadece sözdizimini renklendirebilen, ancak tam olarak ipucu veren, hataları kontrol eden, kodu yeniden düzenleyebilen ve çok daha fazlasını yapabilen birinci sınıf bir IDE'nin yeteneklerine ulaşamayan bir editörle yetinmek için hiçbir neden yok. Bazı IDE'ler ücretlidir, diğerleri ise ücretsizdir. - -**NetBeans IDE** Nette, Latte ve NEON desteği zaten yerleşiktir. - -**PhpStorm**: `Settings > Plugins > Marketplace` bölümünden şu eklentileri yükleyin -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: marketplace'te "Nette Latte + Neon" eklentisini bulun. - -Ayrıca Tracy'yi editörünüzle bağlayın. Hata sayfası görüntülendiğinde, dosya adlarına tıklayabilir ve bunlar editörde ilgili satırda imleçle açılır. [Sistemi nasıl yapılandıracağınızı |tracy:open-files-in-ide] okuyun. - - -PHPStan -======= - -PHPStan, kodu çalıştırmadan önce mantıksal hataları ortaya çıkaran bir araçtır. - -Composer kullanarak kurarız: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Projede `phpstan.neon` yapılandırma dosyasını oluştururuz: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -Ve ardından `app/` klasöründeki sınıfları analiz etmesini sağlarız: - -```shell -vendor/bin/phpstan analyse app -``` - -Kapsamlı belgeleri doğrudan [PHPStan web sitesinde |https://phpstan.org] bulabilirsiniz. - - -Code Checker -============ - -[Code Checker|tools:code-checker] kaynak kodlarınızdaki bazı biçimsel hataları kontrol eder ve gerekirse düzeltir: - -- [BOM |nette:glossary#BOM] kaldırır -- [Latte |latte:] şablonlarının geçerliliğini kontrol eder -- `.neon`, `.php` ve `.json` dosyalarının geçerliliğini kontrol eder -- [kontrol karakterlerinin |nette:glossary#Kontrol Karakterleri] varlığını kontrol eder -- dosyanın UTF-8 olarak kodlanıp kodlanmadığını kontrol eder -- yanlış yazılmış `/* @anotace */` (yıldız eksik) kontrol eder -- PHP dosyalarındaki kapanış `?>` etiketini kaldırır -- dosya sonundaki sağdaki boşlukları ve gereksiz satırları kaldırır -- satır ayırıcılarını sistem varsayılanlarına normalleştirir (`-l` seçeneğini belirtirseniz) - - -Composer -======== - -[Composer |Composer] PHP'de bağımlılıkları yönetmek için bir araçtır. Bireysel kütüphanelerin keyfi olarak karmaşık bağımlılıklarını bildirmemize ve ardından bunları projemize kurmamıza olanak tanır. - - -Requirements Checker -==================== - -Sunucunun çalışma zamanı ortamını test eden ve framework'ün kullanılıp kullanılamayacağını (ve ne ölçüde) bildiren bir araçtı. Şu anda Nette, minimum gerekli PHP sürümüne sahip her sunucuda kullanılabilir. diff --git a/tools/uk/ide.texy b/tools/uk/ide.texy deleted file mode 100644 index ff87bafe2c..0000000000 --- a/tools/uk/ide.texy +++ /dev/null @@ -1,84 +0,0 @@ -Редактори та інструменти -************************ - -.[perex] -Ви можете бути вправним програмістом, але лише з хорошими інструментами ви станете майстром. У цьому розділі ви знайдете поради щодо важливих інструментів, редакторів та плагінів. - - -IDE редактор -============ - -Ми наполегливо рекомендуємо використовувати для розробки повноцінне IDE, таке як PhpStorm, NetBeans, VS Code, а не просто текстовий редактор з підтримкою PHP. Різниця справді суттєва. Немає причин задовольнятися простим редактором, який хоч і вміє підсвічувати синтаксис, але не досягає можливостей топового IDE, яке точно підказує, відстежує помилки, вміє рефакторити код та багато іншого. Деякі IDE платні, інші навіть безкоштовні. - -**NetBeans IDE** має вбудовану підтримку Nette, Latte та NEON. - -**PhpStorm**: встановіть ці плагіни в `Settings > Plugins > Marketplace` -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: знайдіть у marketplace плагін "Nette Latte + Neon". - -Також зв'яжіть Tracy з редактором. При відображенні сторінки помилки можна буде клікнути на імена файлів, і вони відкриються в редакторі з курсором на відповідному рядку. Прочитайте, [як налаштувати систему|tracy:open-files-in-ide]. - - -PHPStan -======= - -PHPStan — це інструмент, який виявляє логічні помилки в коді ще до його запуску. - -Встановимо його за допомогою Composer: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Створимо в проекті конфігураційний файл `phpstan.neon`: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -А потім запустимо аналіз класів у папці `app/`: - -```shell -vendor/bin/phpstan analyse app -``` - -Вичерпну документацію ви знайдете безпосередньо на [сайті PHPStan |https://phpstan.org]. - - -Code Checker -============ - -[Code Checker|tools:code-checker] перевіряє та, за потреби, виправляє деякі формальні помилки у ваших вихідних кодах: - -- видаляє [BOM |nette:glossary#BOM] -- перевіряє валідність шаблонів [Latte |latte:] -- перевіряє валідність файлів `.neon`, `.php` та `.json` -- перевіряє наявність [контрольних символів |nette:glossary#Керуючі символи] -- перевіряє, чи файл закодований у UTF-8 -- перевіряє помилково записані `/* @anotace */` (відсутня зірочка) -- видаляє завершальний `?>` у PHP файлах -- видаляє пробіли в кінці рядків та зайві рядки в кінці файлу -- нормалізує роздільники рядків до системних (якщо вказати опцію `-l`) - - -Composer -======== - -[Composer | Composer] — це інструмент для керування залежностями в PHP. Він дозволяє нам декларувати довільно складні залежності окремих бібліотек, а потім встановлює їх для нас у наш проект. - - -Requirements Checker -==================== - -Це був інструмент, який тестував середовище виконання сервера та інформував, чи (і якою мірою) можна використовувати фреймворк. На даний момент Nette можна використовувати на будь-якому сервері, який має мінімально необхідну версію PHP. From 06a89dd9ae0b66d634046959a5e4d7bfefa4e099 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Sat, 6 Jun 2026 17:00:50 +0200 Subject: [PATCH 42/50] added Coding Standard page --- contributing/cs/coding-standard.texy | 3 + contributing/en/coding-standard.texy | 3 + tools/bg/@home.texy | 1 + tools/cs/@home.texy | 1 + tools/cs/coding-standard.texy | 83 ++++++++++++++++++++++++++++ tools/de/@home.texy | 1 + tools/el/@home.texy | 1 + tools/en/@home.texy | 1 + tools/en/coding-standard.texy | 83 ++++++++++++++++++++++++++++ tools/es/@home.texy | 1 + tools/fr/@home.texy | 1 + tools/hu/@home.texy | 1 + tools/it/@home.texy | 1 + tools/ja/@home.texy | 1 + tools/pl/@home.texy | 1 + tools/pt/@home.texy | 1 + tools/ro/@home.texy | 1 + tools/ru/@home.texy | 1 + tools/sl/@home.texy | 1 + tools/tr/@home.texy | 1 + tools/uk/@home.texy | 1 + 21 files changed, 189 insertions(+) create mode 100644 tools/cs/coding-standard.texy create mode 100644 tools/en/coding-standard.texy diff --git a/contributing/cs/coding-standard.texy b/contributing/cs/coding-standard.texy index 5bac29274f..95e9155667 100644 --- a/contributing/cs/coding-standard.texy +++ b/contributing/cs/coding-standard.texy @@ -6,6 +6,9 @@ Tento dokument popisuje pravidla a doporučení pro vývoj Nette. Při přispív Nette Coding Standard odpovídá [PSR-12 Extended Coding Style |https://www.php-fig.org/psr/psr-12/] se dvěma hlavními výjimkami: pro odsazení používá [#tabulátory místo mezer] a pro [konstanty tříd používá PascalCase|https://blog.nette.org/cs/za-mene-kriku-v-kodu]. +.[tip] +Mnoho z těchto pravidel umí automaticky kontrolovat a opravovat nástroj [Nette Coding Standard |tools:coding-standard], takže je nemusíte hlídat ručně. + Obecná pravidla =============== diff --git a/contributing/en/coding-standard.texy b/contributing/en/coding-standard.texy index 2883d9634d..1f1f9cfb66 100644 --- a/contributing/en/coding-standard.texy +++ b/contributing/en/coding-standard.texy @@ -6,6 +6,9 @@ This document describes the rules and recommendations for developing Nette. When Nette Coding Standard corresponds to [PSR-12 Extended Coding Style |https://www.php-fig.org/psr/psr-12/] with two main exceptions: it uses [#tabs instead of spaces] for indentation, and uses [PascalCase for class constants|https://blog.nette.org/en/for-less-screaming-in-the-code]. +.[tip] +Many of these rules can be automatically checked and fixed by the [Nette Coding Standard |tools:coding-standard] tool, so you don't have to check them by hand. + General Rules ============= diff --git a/tools/bg/@home.texy b/tools/bg/@home.texy index 08c54d83e5..564c400bf3 100644 --- a/tools/bg/@home.texy +++ b/tools/bg/@home.texy @@ -14,6 +14,7 @@ Качество на кода ---------------- - [Code Checker |code-checker] проверява изходните ви файлове за формални недостатъци като невидим BOM, контролни знаци, повредено кодиране или невалиден синтаксис на PHP, Latte, NEON, JSON и YAML файлове и може да ги поправи автоматично. +- [Coding Standard |en:coding-standard] автоматично форматира вашия PHP код според Nette coding standard, от отстъпите и скобите до интервалите и подреждането на импортите. Изкуствен интелект diff --git a/tools/cs/@home.texy b/tools/cs/@home.texy index 1654095a08..e17bf14e38 100644 --- a/tools/cs/@home.texy +++ b/tools/cs/@home.texy @@ -14,6 +14,7 @@ Vývojové prostředí Kvalita kódu ------------ - [Code Checker |code-checker] zkontroluje vaše zdrojové soubory a najde v nich formální nedostatky, jako je neviditelný BOM, kontrolní znaky, chybné kódování nebo neplatná syntaxe souborů PHP, Latte, NEON, JSON a YAML, a umí je automaticky opravit. +- [Coding Standard |coding-standard] automaticky naformátuje váš PHP kód podle Nette coding standardu, od odsazení a závorek až po mezery a řazení importů. Umělá inteligence diff --git a/tools/cs/coding-standard.texy b/tools/cs/coding-standard.texy new file mode 100644 index 0000000000..6e99805e52 --- /dev/null +++ b/tools/cs/coding-standard.texy @@ -0,0 +1,83 @@ +Nette Coding Standard +********************* + +.[perex] +[Coding Standard |https://github.com/nette/coding-standard] automaticky naformátuje váš PHP kód podle [Nette coding standardu |contributing:coding-standard], od odsazení a závorek až po mezery a řazení importů. + +Pod kapotou kombinuje dva osvědčené nástroje, PHP CS Fixer a PHP CodeSniffer, které jsou už přednastavené, takže si nemusíte nic sami konfigurovat. + + +Instalace +========= + +Nástroj nainstalujte globálně pomocí Composeru: + +```shell +composer global require nette/coding-standard +``` + +a ujistěte se, že váš globální adresář `vendor/bin` je v [proměnné prostředí $PATH |https://getcomposer.org/doc/03-cli.md#global]. + + +Použití +======= + +Nástroj nabízí dva příkazy. Příkaz `check` jen vypíše prohřešky, zatímco `fix` je rovnou opraví: + +```shell +ecs check +ecs fix +``` + +Bez uvedení cest prohledá adresáře `src/` a `tests/`; můžete ale zadat i jednu nebo více vlastních cest, například `ecs check app bin`. + +Než nástroj poprvé spustíte v režimu oprav, určitě si soubory zazálohujte. + + +Verze PHP +========= + +Nástroj podporuje PHP 8.0 až 8.5 a pravidla uplatňuje přírůstkově podle verze. Verzi rozpozná automaticky z `composer.json` vašeho projektu, můžete ji ale nastavit i ručně volbou `--preset`: + +```shell +ecs check --preset php81 +``` + + +Vlastní pravidla +================ + +Pravidla si můžete pro svůj projekt upravit. Pro změnu pravidel PHP CS Fixeru vytvořte v kořeni projektu soubor `ncs.php`: + +```php +<?php +return [ + 'strict_comparison' => false, +]; +``` + +Pro změnu pravidel PHP CodeSnifferu vytvořte soubor `ncs.xml`. Nemusí odkazovat na verzový preset (ten se přidá automaticky) a pomocí `$presets/` můžete zapojit kterýkoliv z dodávaných presetů: + +```xml +<?xml version="1.0"?> +<ruleset name="MyProject"> + <!-- zapnutí importů use function/const --> + <rule ref="$presets/optimize-fn.xml"/> + + <!-- vypnutí pravidla --> + <exclude name="SlevomatCodingStandard.TypeHints.ReturnTypeHint"/> +</ruleset> +``` + +Oba soubory se načtou automaticky a vaše pravidla mají přednost před presetem. Pro jednorázovou úpravu, kterou nechcete commitovat, předáte další soubor volbou `--config-file` (`.php` pro fixer, `.xml` pro sniffer). + + +Continuous integration +====================== + +V CI nástroj nainstalujte jako projekt a spusťte ho odtud: + +```yaml +- run: composer create-project nette/coding-standard temp/coding-standard +- run: php temp/coding-standard/ecs check +``` diff --git a/tools/de/@home.texy b/tools/de/@home.texy index 027f5f3cc4..1d65866455 100644 --- a/tools/de/@home.texy +++ b/tools/de/@home.texy @@ -14,6 +14,7 @@ Entwicklungsumgebung Code-Qualität ------------- - [Code Checker |code-checker] überprüft Ihre Quelldateien auf formale Mängel wie ein unsichtbares BOM, Steuerzeichen, fehlerhafte Kodierung oder ungültige Syntax von PHP-, Latte-, NEON-, JSON- und YAML-Dateien und kann diese automatisch beheben. +- [Coding Standard |en:coding-standard] formatiert Ihren PHP-Code automatisch gemäß dem Nette Coding Standard, von der Einrückung und den Klammern bis hin zu Abständen und der Reihenfolge der Imports. Künstliche Intelligenz diff --git a/tools/el/@home.texy b/tools/el/@home.texy index 716a1dc628..8f05d771b0 100644 --- a/tools/el/@home.texy +++ b/tools/el/@home.texy @@ -14,6 +14,7 @@ Ποιότητα κώδικα --------------- - [Code Checker |code-checker] ελέγχει τα πηγαία αρχεία σας για τυπικά σφάλματα, όπως ένα αόρατο BOM, χαρακτήρες ελέγχου, κατεστραμμένη κωδικοποίηση ή μη έγκυρη σύνταξη αρχείων PHP, Latte, NEON, JSON και YAML, και μπορεί να τα διορθώσει αυτόματα. +- [Coding Standard |en:coding-standard] μορφοποιεί αυτόματα τον κώδικα PHP σας σύμφωνα με το πρότυπο κωδικοποίησης του Nette, από τη στοίχιση και τα άγκιστρα μέχρι τα κενά και τη σειρά των imports. Τεχνητή νοημοσύνη diff --git a/tools/en/@home.texy b/tools/en/@home.texy index 7c83f9d102..605a5ac6b5 100644 --- a/tools/en/@home.texy +++ b/tools/en/@home.texy @@ -14,6 +14,7 @@ Development Environment Code Quality ------------ - [Code Checker |code-checker] checks your source files for formal flaws such as an invisible BOM, control characters, broken encoding, or invalid syntax of PHP, Latte, NEON, JSON and YAML files, and can fix them automatically. +- [Coding Standard |coding-standard] automatically formats your PHP code according to the Nette coding standard, from indentation and braces to spacing and the ordering of imports. Artificial Intelligence diff --git a/tools/en/coding-standard.texy b/tools/en/coding-standard.texy new file mode 100644 index 0000000000..e88a41a350 --- /dev/null +++ b/tools/en/coding-standard.texy @@ -0,0 +1,83 @@ +Nette Coding Standard +********************* + +.[perex] +[Coding Standard |https://github.com/nette/coding-standard] automatically formats your PHP code according to the [Nette coding standard |contributing:coding-standard], from indentation and braces to spacing and the ordering of imports. + +Under the hood it combines two industry-standard tools, PHP CS Fixer and PHP CodeSniffer, which come preconfigured, so you do not have to set anything up yourself. + + +Installation +============ + +Install the tool globally using Composer: + +```shell +composer global require nette/coding-standard +``` + +and make sure your global vendor binaries directory is in [your `$PATH` environment variable|https://getcomposer.org/doc/03-cli.md#global]. + + +Usage +===== + +The tool provides two commands. The `check` command only reports violations, while `fix` repairs them automatically: + +```shell +ecs check +ecs fix +``` + +Without any arguments it scans the `src/` and `tests/` directories; you can also pass one or more of your own paths, for example `ecs check app bin`. + +Before you run the fixer for the first time, be sure to back up your files. + + +PHP Version +=========== + +The tool supports PHP 8.0 to 8.5 and applies the rules incrementally according to the version. It detects the version automatically from your project's `composer.json`, but you can also set it explicitly with the `--preset` option: + +```shell +ecs check --preset php81 +``` + + +Custom Rules +============ + +You can tweak the rules for your project. To change the PHP CS Fixer rules, create an `ncs.php` file in the project root: + +```php +<?php +return [ + 'strict_comparison' => false, +]; +``` + +To change the PHP CodeSniffer rules, create an `ncs.xml` file. It does not need to reference the version preset (it is combined with it automatically), and you can use `$presets/` to pull in any bundled preset: + +```xml +<?xml version="1.0"?> +<ruleset name="MyProject"> + <!-- enable use function/const imports --> + <rule ref="$presets/optimize-fn.xml"/> + + <!-- disable a rule --> + <exclude name="SlevomatCodingStandard.TypeHints.ReturnTypeHint"/> +</ruleset> +``` + +Both files are discovered automatically and your rules take precedence over the preset. For a one-off override that you do not want to commit, pass an extra file with `--config-file` (`.php` for the fixer, `.xml` for the sniffer). + + +Continuous Integration +====================== + +In a CI pipeline, install the tool as a project and run it from there: + +```yaml +- run: composer create-project nette/coding-standard temp/coding-standard +- run: php temp/coding-standard/ecs check +``` diff --git a/tools/es/@home.texy b/tools/es/@home.texy index 55010c1a22..444de4b348 100644 --- a/tools/es/@home.texy +++ b/tools/es/@home.texy @@ -14,6 +14,7 @@ Entorno de desarrollo Calidad del código ------------------ - [Code Checker |code-checker] comprueba sus archivos fuente en busca de defectos formales como un BOM invisible, caracteres de control, codificación dañada o sintaxis inválida de archivos PHP, Latte, NEON, JSON y YAML, y puede corregirlos automáticamente. +- [Coding Standard |en:coding-standard] formatea automáticamente su código PHP según el estándar de codificación de Nette, desde la sangría y las llaves hasta los espacios y la ordenación de las importaciones. Inteligencia artificial diff --git a/tools/fr/@home.texy b/tools/fr/@home.texy index 24e4cb619c..9eeaa8c832 100644 --- a/tools/fr/@home.texy +++ b/tools/fr/@home.texy @@ -14,6 +14,7 @@ Environnement de développement Qualité du code --------------- - [Code Checker |code-checker] vérifie vos fichiers sources et y détecte des défauts formels tels qu'un BOM invisible, des caractères de contrôle, un encodage incorrect ou une syntaxe invalide des fichiers PHP, Latte, NEON, JSON et YAML, et peut les corriger automatiquement. +- [Coding Standard |en:coding-standard] formate automatiquement votre code PHP selon le standard de codage Nette, de l'indentation et des accolades jusqu'aux espaces et à l'ordre des imports. Intelligence artificielle diff --git a/tools/hu/@home.texy b/tools/hu/@home.texy index 1d581dbe3b..4887c35af0 100644 --- a/tools/hu/@home.texy +++ b/tools/hu/@home.texy @@ -14,6 +14,7 @@ Fejlesztői környezet Kódminőség ---------- - [Code Checker |code-checker] ellenőrzi a forrásfájljaidat, és olyan formai hibákat keres bennük, mint a láthatatlan BOM, a vezérlő karakterek, a hibás kódolás vagy a PHP, Latte, NEON, JSON és YAML fájlok érvénytelen szintaxisa, és képes automatikusan kijavítani őket. +- [Coding Standard |en:coding-standard] automatikusan formázza a PHP kódodat a Nette coding standard szerint, a behúzástól és a zárójelektől kezdve a szóközökön át az importok rendezéséig. Mesterséges intelligencia diff --git a/tools/it/@home.texy b/tools/it/@home.texy index 56dc4927fe..5a05e0f4ab 100644 --- a/tools/it/@home.texy +++ b/tools/it/@home.texy @@ -14,6 +14,7 @@ Ambiente di sviluppo Qualità del codice ------------------ - [Code Checker |code-checker] controlla i tuoi file sorgente alla ricerca di difetti formali come un BOM invisibile, caratteri di controllo, codifica errata o sintassi non valida nei file PHP, Latte, NEON, JSON e YAML, e può correggerli automaticamente. +- [Coding Standard |en:coding-standard] formatta automaticamente il tuo codice PHP secondo lo standard di codifica di Nette, dall'indentazione e le parentesi agli spazi e all'ordinamento degli import. Intelligenza artificiale diff --git a/tools/ja/@home.texy b/tools/ja/@home.texy index 674cfee9df..fa7686a10d 100644 --- a/tools/ja/@home.texy +++ b/tools/ja/@home.texy @@ -14,6 +14,7 @@ Nette での開発を容易にする補助ツール。 コード品質 ----- - [Code Checker |code-checker] は、目に見えない BOM、制御文字、壊れたエンコーディング、PHP・Latte・NEON・JSON・YAML ファイルの不正な構文といった形式的な欠陥がないかソースファイルをチェックし、自動的に修正できます。 +- [Coding Standard |en:coding-standard] は、インデントや波括弧から、スペースの入れ方やインポートの並び順まで、Nette のコーディング標準に従って PHP コードを自動的に整形します。 人工知能 diff --git a/tools/pl/@home.texy b/tools/pl/@home.texy index 3dc205b0f6..3c0cb8905f 100644 --- a/tools/pl/@home.texy +++ b/tools/pl/@home.texy @@ -14,6 +14,7 @@ Narzędzia pomocnicze, które ułatwiają programowanie z Nette. Jakość kodu ----------- - [Code Checker |code-checker] sprawdza Twoje pliki źródłowe pod kątem formalnych usterek, takich jak niewidoczny BOM, znaki kontrolne, błędne kodowanie czy nieprawidłowa składnia plików PHP, Latte, NEON, JSON i YAML, oraz potrafi je automatycznie naprawić. +- [Coding Standard |en:coding-standard] automatycznie formatuje Twój kod PHP zgodnie ze standardem kodowania Nette, od wcięć i nawiasów po odstępy i kolejność importów. Sztuczna inteligencja diff --git a/tools/pt/@home.texy b/tools/pt/@home.texy index e8bfb50671..5cc8d7227a 100644 --- a/tools/pt/@home.texy +++ b/tools/pt/@home.texy @@ -14,6 +14,7 @@ Ambiente de Desenvolvimento Qualidade do Código ------------------- - [Code Checker |code-checker] verifica seus arquivos de origem em busca de falhas formais, como um BOM invisível, caracteres de controle, codificação corrompida ou sintaxe inválida de arquivos PHP, Latte, NEON, JSON e YAML, e pode corrigi-los automaticamente. +- [Coding Standard |en:coding-standard] formata automaticamente seu código PHP de acordo com o padrão de codificação do Nette, da indentação e chaves ao espaçamento e à ordenação das importações. Inteligência Artificial diff --git a/tools/ro/@home.texy b/tools/ro/@home.texy index 157319a7f8..5df6a4c5c2 100644 --- a/tools/ro/@home.texy +++ b/tools/ro/@home.texy @@ -14,6 +14,7 @@ Mediu de dezvoltare Calitatea codului ----------------- - [Code Checker |code-checker] verifică fișierele sursă pentru defecte formale precum un BOM invizibil, caractere de control, codificare deteriorată sau sintaxă invalidă a fișierelor PHP, Latte, NEON, JSON și YAML și le poate corecta automat. +- [Coding Standard |en:coding-standard] formatează automat codul PHP conform standardului de codare Nette, de la indentare și acolade până la spațiere și ordonarea importurilor. Inteligență artificială diff --git a/tools/ru/@home.texy b/tools/ru/@home.texy index 180ab37a00..9d1f8dd9a4 100644 --- a/tools/ru/@home.texy +++ b/tools/ru/@home.texy @@ -14,6 +14,7 @@ Качество кода ------------- - [Code Checker |code-checker] проверяет ваши исходные файлы и находит в них формальные недочёты, такие как невидимый BOM, управляющие символы, неправильную кодировку или некорректный синтаксис файлов PHP, Latte, NEON, JSON и YAML, и умеет их автоматически исправлять. +- [Coding Standard |en:coding-standard] автоматически форматирует ваш PHP-код согласно стандарту кодирования Nette, от отступов и скобок до пробелов и порядка импортов. Искусственный интеллект diff --git a/tools/sl/@home.texy b/tools/sl/@home.texy index ec982ded75..491ee05959 100644 --- a/tools/sl/@home.texy +++ b/tools/sl/@home.texy @@ -14,6 +14,7 @@ Razvojno okolje Kakovost kode ------------- - [Code Checker |code-checker] preveri vaše izvorne datoteke in v njih poišče formalne pomanjkljivosti, kot so neviden BOM, kontrolni znaki, pokvarjeno kodiranje ali neveljavna sintaksa datotek PHP, Latte, NEON, JSON in YAML, ter jih zna samodejno popraviti. +- [Coding Standard |en:coding-standard] samodejno oblikuje vašo PHP kodo v skladu z Nette coding standardom, od zamikov in oklepajev do presledkov in razvrščanja uvozov. Umetna inteligenca diff --git a/tools/tr/@home.texy b/tools/tr/@home.texy index 2b84564bad..234bd577ed 100644 --- a/tools/tr/@home.texy +++ b/tools/tr/@home.texy @@ -14,6 +14,7 @@ Geliştirme Ortamı Kod Kalitesi ------------ - [Code Checker |code-checker] kaynak dosyalarınızı görünmez bir BOM, kontrol karakterleri, bozuk kodlama veya PHP, Latte, NEON, JSON ve YAML dosyalarının geçersiz söz dizimi gibi biçimsel kusurlara karşı denetler ve bunları otomatik olarak düzeltebilir. +- [Coding Standard |en:coding-standard] PHP kodunuzu, girintiden parantezlere, boşluk bırakmaya ve içe aktarmaların sıralamasına kadar Nette kodlama standardına göre otomatik olarak biçimlendirir. Yapay Zekâ diff --git a/tools/uk/@home.texy b/tools/uk/@home.texy index 0ad9c700b4..0b364cf794 100644 --- a/tools/uk/@home.texy +++ b/tools/uk/@home.texy @@ -14,6 +14,7 @@ Якість коду ----------- - [Code Checker |code-checker] перевіряє ваші вихідні файли на формальні недоліки, такі як невидимий BOM, керуючі символи, пошкоджене кодування або неправильний синтаксис файлів PHP, Latte, NEON, JSON та YAML, і вміє виправляти їх автоматично. +- [Coding Standard |en:coding-standard] автоматично форматує ваш PHP код згідно з coding standard Nette, від відступів та дужок до пробілів і впорядкування імпортів. Штучний інтелект From 9b96a5693af8f02d1d95f068ef28d9cddae281c4 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Mon, 25 May 2026 20:06:02 +0200 Subject: [PATCH 43/50] added Nette PHPStan Rules page --- tools/bg/@home.texy | 1 + tools/cs/@home.texy | 1 + tools/cs/phpstan-rules.texy | 296 ++++++++++++++++++++++++++++++++++++ tools/de/@home.texy | 1 + tools/el/@home.texy | 1 + tools/en/@home.texy | 1 + tools/en/phpstan-rules.texy | 296 ++++++++++++++++++++++++++++++++++++ tools/es/@home.texy | 1 + tools/fr/@home.texy | 1 + tools/hu/@home.texy | 1 + tools/it/@home.texy | 1 + tools/ja/@home.texy | 1 + tools/pl/@home.texy | 1 + tools/pt/@home.texy | 1 + tools/ro/@home.texy | 1 + tools/ru/@home.texy | 1 + tools/sl/@home.texy | 1 + tools/tr/@home.texy | 1 + tools/uk/@home.texy | 1 + 19 files changed, 609 insertions(+) create mode 100644 tools/cs/phpstan-rules.texy create mode 100644 tools/en/phpstan-rules.texy diff --git a/tools/bg/@home.texy b/tools/bg/@home.texy index 564c400bf3..ab4917b6ff 100644 --- a/tools/bg/@home.texy +++ b/tools/bg/@home.texy @@ -15,6 +15,7 @@ ---------------- - [Code Checker |code-checker] проверява изходните ви файлове за формални недостатъци като невидим BOM, контролни знаци, повредено кодиране или невалиден синтаксис на PHP, Latte, NEON, JSON и YAML файлове и може да ги поправи автоматично. - [Coding Standard |en:coding-standard] автоматично форматира вашия PHP код според Nette coding standard, от отстъпите и скобите до интервалите и подреждането на импортите. +- [PHPStan Rules |en:phpstan-rules] учат PHPStan да разбира кода на Nette, така че статичният анализ извежда точни типове и докладва по-малко фалшиви сигнали. Изкуствен интелект diff --git a/tools/cs/@home.texy b/tools/cs/@home.texy index e17bf14e38..2250be0bb3 100644 --- a/tools/cs/@home.texy +++ b/tools/cs/@home.texy @@ -15,6 +15,7 @@ Kvalita kódu ------------ - [Code Checker |code-checker] zkontroluje vaše zdrojové soubory a najde v nich formální nedostatky, jako je neviditelný BOM, kontrolní znaky, chybné kódování nebo neplatná syntaxe souborů PHP, Latte, NEON, JSON a YAML, a umí je automaticky opravit. - [Coding Standard |coding-standard] automaticky naformátuje váš PHP kód podle Nette coding standardu, od odsazení a závorek až po mezery a řazení importů. +- [PHPStan Rules |phpstan-rules] naučí PHPStan rozumět Nette kódu, takže statická analýza odvozuje přesné typy a hlásí méně falešných chyb. Umělá inteligence diff --git a/tools/cs/phpstan-rules.texy b/tools/cs/phpstan-rules.texy new file mode 100644 index 0000000000..c0bb8b8d77 --- /dev/null +++ b/tools/cs/phpstan-rules.texy @@ -0,0 +1,296 @@ +Nette PHPStan Rules +******************* + +.[perex] +[PHPStan Rules |https://github.com/nette/phpstan-rules] naučí PHPStan rozumět Nette kódu, takže statická analýza odvozuje přesné typy a hlásí méně falešných chyb. + +Stačí rozšíření nainstalovat a [PHPStan |https://phpstan.org] například sám pozná typ komponenty tam, kde dříve viděl chybu: + +```php +class HomePresenter extends Presenter +{ + protected function createComponentMenu(): MenuControl + { + return new MenuControl; + } + + public function renderDefault(): void + { + $menu = $this['menu']; // PHPStan nyní odvodí MenuControl + $menu->setActive('home'); // bez varování o neznámé metodě + } +} +``` + + +Instalace +========= + +Rozšíření staví na statickém analyzátoru PHPStan, který odhalí logické chyby v kódu ještě dřív, než jej spustíte. Pokud ho zatím nepoužíváte, nainstalujte ho Composerem: + +```shell +composer require --dev phpstan/phpstan +``` + +Vytvořte konfigurační soubor `phpstan.neon`, kde uvedete adresáře k analýze a úroveň přísnosti: + +```neon +parameters: + paths: + - app + + level: 8 +``` + +PHPStan se pak spouští příkazem: + +```shell +vendor/bin/phpstan analyse +``` + +Podrobnou dokumentaci najdete na [stránkách PHPStan |https://phpstan.org]. + +Poté nainstalujte samotné rozšíření: + +```shell +composer require --dev nette/phpstan-rules +``` + +Potřebujete PHP 8.1 nebo vyšší a PHPStan 2.1+. + +Aby PHPStan rozšíření používal, je potřeba ho aktivovat. Buď si nainstalujte [phpstan/extension-installer |https://github.com/phpstan/extension-installer], který to zařídí za vás, nebo rozšíření přidejte ručně do `phpstan.neon`: + +```neon +includes: + - vendor/nette/phpstan-rules/extension.neon +``` + +Většina kontrol funguje bez další konfigurace. Pouze pro funkce popsané v sekci [#Assety] je potřeba malý konfigurační blok v `phpstan.neon` (viz níže). Veškerá konfigurace uvedená na této stránce patří do `phpstan.neon`, nikoli do `common.neon` nebo jiných konfiguračních souborů Nette DI. + + +Nativní PHP funkce +================== + +Mnoho nativních PHP funkcí má v deklarovaném návratovém typu `string|false` nebo `array|null`, ačkoli se chybová hodnota objevuje jen za podmínek, které v moderním kódu prakticky nemohou nastat: selhání `getcwd()` na funkčním filesystému, selhání `json_encode()` bez `JSON_THROW_ON_ERROR`, selhání `preg_split()` na konstantním patternu a podobně. Rozšíření tyto chybové hodnoty z návratových typů odstraní, takže PHPStan přestane vyžadovat ošetření chyb, které *nemohou* nastat. + +Kompletní seznam je v [extension-php.neon |https://github.com/nette/phpstan-rules/blob/master/extension-php.neon]. + + +Closures pro runtime kontrolu typů +---------------------------------- + +Běžný PHP idiom pro runtime ověření, že pole obsahuje hodnoty deklarovaného typu, používá typovanou variadickou closure volanou s operátorem spread: + +```php +/** @param string[] $items */ +public function setItems(array $items): void +{ + (function (string ...$items) {})(...$items); +} +``` + +PHP vynutí typ `string` na každém argumentu a vyhodí `TypeError`, pokud některý prvek není string. Tělo closure je prázdné a výraz existuje pouze kvůli vedlejšímu efektu. PHPStan by jinak hlásil `expr.resultUnused`, toto pravidlo ale daný vzor rozpozná a chybu nevypíše. + + +Aplikace +======== + +V presenterech metody jako `redirect()`, `forward()` nebo `sendJson()` ukončují běh vyhozením `Nette\Application\AbortException`. Když takové volání obalíte do `try` a zachytíte ho širokým `catch (\Throwable)` nebo `catch (\Exception)`, nechtěně tím přesměrování spolknete. Rozšíření na to upozorní: + +```php +try { + $this->redirect('Homepage:'); +} catch (\Throwable $e) { // chyba: spolkne AbortException + Debugger::log($e); +} +``` + +Řešením je výjimku znovu vyhodit, nebo ji vyčlenit do samostatné větve ještě před širokým catchem: + +```php +try { + $this->redirect('Homepage:'); +} catch (Nette\Application\AbortException $e) { + throw $e; +} catch (\Throwable $e) { + Debugger::log($e); +} +``` + + +Assety +====== + +V `phpstan.neon` (nikoli v konfiguraci Nette DI) nastavte mapování ID mapperů na třídy, aby PHPStan dokázal zúžit obecný typ `Asset` na konkrétní třídu: + +```neon +parameters: + nette: + assets: + mapping: + default: file # Nette\Assets\FilesystemMapper + images: file + vite: vite # Nette\Assets\ViteMapper + custom: App\MyMapper # libovolné FQCN +``` + +Hodnoty `file` a `vite` jsou zkratky pro vestavěné `FilesystemMapper` a `ViteMapper`. Jakákoli jiná hodnota se považuje za plně kvalifikovaný název vlastní třídy mapperu. + +Po nastavení: + +- `Registry::getMapper('vite')` vrací `ViteMapper` místo `Mapper`. +- `Registry::getAsset('default:logo.png')` vrací `ImageAsset`. `tryGetAsset()` vrací `ImageAsset|null`. +- `FilesystemMapper::getAsset('button.js')` a `ViteMapper::getAsset()` se zúžují stejným způsobem. + + +Component Model +=============== + +Rozšíření zúží návratový typ `Container::getComponent()` a `Container::offsetGet()` (tedy `$this['name']`) podle factory metod `createComponent<Name>()` deklarovaných na téže třídě. + +```php +class HomePresenter extends Presenter +{ + protected function createComponentMenu(): MenuControl + { + return new MenuControl; + } + + public function renderDefault(): void + { + $menu = $this->getComponent('menu'); // MenuControl + $menu = $this['menu']; // MenuControl + } +} +``` + +Pokud odpovídající factory neexistuje nebo název komponenty není konstantní string, zůstane návratový typ `getComponent()` i `$this['name']` nezměněný, tedy obecný `IComponent`. + + +Dependency Injection +==================== + +Vlastnosti označené atributem `#[Nette\DI\Attributes\Inject]` plní dependency injection až po vytvoření objektu. PHPStan by je proto hlásil jako neinicializované; rozšíření je naopak bere jako zapsané a inicializované: + +```php +class HomePresenter extends Presenter +{ + #[Inject] + public CartFacade $cart; // bez chyby o neinicializované vlastnosti +} +``` + + +Formuláře +========= + +Pokud je volání `$form->addText('name', …)`, `$form->addSelect(…)` apod. ve stejné funkci nebo metodě jako přístup k `$form['name']` (případně `$form->getComponent('name')`), rozšíření odvodí typ přístupu z odpovídajícího volání `addXxx()`: + +```php +public function createComponentSignInForm(): Form +{ + $form = new Form; + $form->addText('username', 'Username'); + $form->addPassword('password', 'Password'); + + $form['username']; // TextInput + $form['password']; // TextInput (Password je potomek) + return $form; +} +``` + +Přístup funguje i z jiné metody, než ve které formulář vznikl. Když ho vytvoříte ve factory `createComponentSignInForm()` a k jeho prvkům přistupujete jinde, rozšíření si přiřazení vystopuje zpět až k factory a dohledá odpovídající volání `addXxx()`: + +```php +public function renderDefault(): void +{ + $form = $this['signInForm']; // dohledá se createComponentSignInForm() + $form['username']; // TextInput + + // stejně tak funguje i přímý přístup + $this['signInForm']['username']; // TextInput + $this['signInForm-username']; // TextInput +} +``` + +Pokud žádné odpovídající volání `addXxx()` neexistuje, rozšíření se stejně jako Component Model pokusí najít factory `createComponent<Name>()`. + + +Vlastnosti event handlerů +------------------------- + +Formuláře data převedou na typ deklarovaný v parametru callbacku, ať jde o `stdClass`, `array` nebo vlastní DTO. Callback s užším datovým parametrem, než je deklarovaný union `array|object`, je proto v pořádku: + +```php +$form->onSuccess[] = function (Form $form, MyDto $data): void { + // … +}; +``` + +PHPStan by jinak hlásil `assign.propertyType`, protože `MyDto` je užší než `array|object`. Pravidlo tuto chybu potlačuje u vlastností `Form::$onSuccess`, `$onError`, `$onSubmit`, `$onRender`, `Container::$onValidate`, `SubmitButton::$onClick` a `$onInvalidClick`. + + +Schema +====== + +Rozšíření zúží návratový typ `Expect::array()` z deklarovaného unionu `Structure|Type` podle předaného argumentu: + +```php +Expect::array(); // Type +Expect::array(['name' => Expect::string()]); // Structure (všechny hodnoty jsou Schema) +Expect::array(['name' => Expect::string(), 'x']); // Structure|Type (Schema i ne-Schema hodnoty) +``` + +Pokud argument obsahuje Schema i ne-Schema hodnoty, deklarovaný union zůstane zachován. + + +Tester +====== + +PHPStan po voláních metod `Tester\Assert` zúží typ proměnné. Podporované metody: `null()`, `notNull()`, `true()`, `false()`, `truthy()`, `falsey()`, `same()`, `notSame()`, `type()`. + +```php +function process(?User $user): void +{ + Assert::notNull($user); + $user->getName(); // bez varování o volání na null +} +``` + + +Arrow funkce jako void callbacky +-------------------------------- + +Funkce Testeru `test()` a `Assert::exception()` přijímají callbacky typované jako `Closure(): void`, ale často se jim předávají arrow funkce ve stylu `fn () => throw new MyException`. Arrow funkce vždy vrací nějakou hodnotu, což by PHPStan jinak označil za typovou neshodu. Pravidlo tuto chybu potlačuje u následujících funkcí a metod: `test()`, `testException()`, `testNoError()`, `Tester\Assert::exception()`, `Tester\Assert::throws()`, `Tester\Assert::error()`, `Tester\Assert::noError()`. + + +Utils +===== + +**`Strings::match()` a `matchAll()`**: u konstantního patternu se návratový typ odvodí přímo z regulárního výrazu, tedy z jeho zachytávajících skupin (včetně pojmenovaných a volitelných). Flagy `captureOffset`, `unmatchedAsNull` a u `matchAll()` i `patternOrder` a `lazy` se promítnou do výsledného tvaru: + +```php +Strings::match($s, '#(\d+)-(\w+)#'); // array{non-falsy-string, decimal-int-string, non-empty-string}|null +Strings::match($s, '#(?<id>\d+)#'); // array{0: non-empty-string, id: decimal-int-string, 1: decimal-int-string}|null +Strings::matchAll($s, '#(\w+)#'); // list<array{string, non-empty-string}> +``` + +U nekonstantního patternu (a u metody `split()`) se tvar odvodí jen z flagů. + +**`Strings::replace()`**: je-li náhrada callback, typ jeho parametru `$matches` se odvodí ze stejného regulárního výrazu: + +```php +Strings::replace($s, '#(\d+)#', function (array $m) { + return $m[1]; // $m má typ array{non-empty-string, decimal-int-string} +}); +``` + +**Zúžení subjektu po `match()`**: uvnitř `if (Strings::match($s, …))` se podle patternu zúží i typ prohledávaného řetězce `$s`, například na `non-empty-string`. + +**Validace patternů**: nevalidní regulární výraz předaný do `match()`, `matchAll()`, `split()` nebo `replace()` rozšíření nahlásí už při analýze, ne až za běhu. + +**`Arrays::invoke()`** a **`Arrays::invokeMethod()`** vracejí místo deklarovaného `array` pole s typem návratové hodnoty volaného callable, resp. metody. + +**`Helpers::falseToNull()`** zúží návratový typ tak, že odstraní `false` a přidá `null`. Z `string|false` se tedy stane `string|null`. + +**`Html` magické metody**: `$el->setClass(…)`, `$el->addData(…)`, `$el->getHref()` a podobné se rozpoznají i bez `@method` anotací. `setXxx()` a `addXxx()` vrací `static` (fluent API), `getXxx()` vrací `mixed`. diff --git a/tools/de/@home.texy b/tools/de/@home.texy index 1d65866455..6fc80f5356 100644 --- a/tools/de/@home.texy +++ b/tools/de/@home.texy @@ -15,6 +15,7 @@ Code-Qualität ------------- - [Code Checker |code-checker] überprüft Ihre Quelldateien auf formale Mängel wie ein unsichtbares BOM, Steuerzeichen, fehlerhafte Kodierung oder ungültige Syntax von PHP-, Latte-, NEON-, JSON- und YAML-Dateien und kann diese automatisch beheben. - [Coding Standard |en:coding-standard] formatiert Ihren PHP-Code automatisch gemäß dem Nette Coding Standard, von der Einrückung und den Klammern bis hin zu Abständen und der Reihenfolge der Imports. +- [PHPStan Rules |en:phpstan-rules] bringen PHPStan bei, Nette-Code zu verstehen, sodass die statische Analyse präzise Typen ableitet und weniger Fehlalarme meldet. Künstliche Intelligenz diff --git a/tools/el/@home.texy b/tools/el/@home.texy index 8f05d771b0..8e94ca24a8 100644 --- a/tools/el/@home.texy +++ b/tools/el/@home.texy @@ -15,6 +15,7 @@ --------------- - [Code Checker |code-checker] ελέγχει τα πηγαία αρχεία σας για τυπικά σφάλματα, όπως ένα αόρατο BOM, χαρακτήρες ελέγχου, κατεστραμμένη κωδικοποίηση ή μη έγκυρη σύνταξη αρχείων PHP, Latte, NEON, JSON και YAML, και μπορεί να τα διορθώσει αυτόματα. - [Coding Standard |en:coding-standard] μορφοποιεί αυτόματα τον κώδικα PHP σας σύμφωνα με το πρότυπο κωδικοποίησης του Nette, από τη στοίχιση και τα άγκιστρα μέχρι τα κενά και τη σειρά των imports. +- [PHPStan Rules |en:phpstan-rules] μαθαίνουν στο PHPStan να κατανοεί τον κώδικα Nette, ώστε η στατική ανάλυση να συμπεραίνει ακριβείς τύπους και να αναφέρει λιγότερα ψευδώς θετικά. Τεχνητή νοημοσύνη diff --git a/tools/en/@home.texy b/tools/en/@home.texy index 605a5ac6b5..43b9ac8a6b 100644 --- a/tools/en/@home.texy +++ b/tools/en/@home.texy @@ -15,6 +15,7 @@ Code Quality ------------ - [Code Checker |code-checker] checks your source files for formal flaws such as an invisible BOM, control characters, broken encoding, or invalid syntax of PHP, Latte, NEON, JSON and YAML files, and can fix them automatically. - [Coding Standard |coding-standard] automatically formats your PHP code according to the Nette coding standard, from indentation and braces to spacing and the ordering of imports. +- [PHPStan Rules |phpstan-rules] teach PHPStan to understand Nette code, so static analysis infers precise types and reports fewer false positives. Artificial Intelligence diff --git a/tools/en/phpstan-rules.texy b/tools/en/phpstan-rules.texy new file mode 100644 index 0000000000..5cb9ad4899 --- /dev/null +++ b/tools/en/phpstan-rules.texy @@ -0,0 +1,296 @@ +Nette PHPStan Rules +******************* + +.[perex] +[PHPStan Rules |https://github.com/nette/phpstan-rules] teach PHPStan to understand Nette code, so static analysis infers precise types and reports fewer false positives. + +Just install the extension and [PHPStan |https://phpstan.org] will, for example, recognize a component's type where it previously saw only an error: + +```php +class HomePresenter extends Presenter +{ + protected function createComponentMenu(): MenuControl + { + return new MenuControl; + } + + public function renderDefault(): void + { + $menu = $this['menu']; // PHPStan now infers MenuControl + $menu->setActive('home'); // no unknown method warning + } +} +``` + + +Installation +============ + +This extension builds on the PHPStan static analyzer, which detects logical errors in your code before you even run it. If you don't use it yet, install it via Composer: + +```shell +composer require --dev phpstan/phpstan +``` + +Create a `phpstan.neon` configuration file specifying the directories to analyze and the rule level: + +```neon +parameters: + paths: + - app + + level: 8 +``` + +PHPStan is then run with the command: + +```shell +vendor/bin/phpstan analyse +``` + +You can find comprehensive documentation on the [PHPStan website |https://phpstan.org]. + +Then install the extension itself: + +```shell +composer require --dev nette/phpstan-rules +``` + +Requirements: PHP 8.1 or higher and PHPStan 2.1+. + +For PHPStan to use the extension, it needs to be activated. Either install [phpstan/extension-installer |https://github.com/phpstan/extension-installer], which does this for you, or add the extension manually to your `phpstan.neon`: + +```neon +includes: + - vendor/nette/phpstan-rules/extension.neon +``` + +Most checks work without any further setup. Only the [#Assets] section need a small configuration block in `phpstan.neon` (described below). Note that all configuration shown on this page belongs in `phpstan.neon`, not in your application's `common.neon` or other Nette DI configuration files. + + +Native PHP Functions +==================== + +Many native PHP functions declare a return type like `string|false` or `array|null`, even though the error value only occurs under conditions that practically cannot happen in modern code: `getcwd()` failing on a sane filesystem, `json_encode()` failing without `JSON_THROW_ON_ERROR`, `preg_split()` failing on a compile-time constant pattern, and so on. The extension removes the impossible parts of these return types, so PHPStan stops asking you to handle errors that cannot occur. + +The full list is in [extension-php.neon |https://github.com/nette/phpstan-rules/blob/master/extension-php.neon]. + + +Runtime type validation closures +-------------------------------- + +A common PHP idiom for runtime checking that an array contains items of a declared type uses a typed variadic closure called with the spread operator: + +```php +/** @param string[] $items */ +public function setItems(array $items): void +{ + (function (string ...$items) {})(...$items); +} +``` + +PHP enforces the `string` type on each spread argument and throws `TypeError` if any item is not a string. The closure body is empty, the expression exists only for its side effect. PHPStan would normally report `expr.resultUnused`; this rule recognises the pattern and stays silent. + + +Application +=========== + +In presenters, methods like `redirect()`, `forward()` or `sendJson()` end the run by throwing `Nette\Application\AbortException`. If you wrap such a call in a `try` and catch it with a broad `catch (\Throwable)` or `catch (\Exception)`, you accidentally swallow the redirect. The extension warns you about it: + +```php +try { + $this->redirect('Homepage:'); +} catch (\Throwable $e) { // error: swallows AbortException + Debugger::log($e); +} +``` + +The fix is to rethrow the exception, or to carve it out into a separate branch before the broad catch: + +```php +try { + $this->redirect('Homepage:'); +} catch (Nette\Application\AbortException $e) { + throw $e; +} catch (\Throwable $e) { + Debugger::log($e); +} +``` + + +Assets +====== + +In `phpstan.neon` (not in your Nette DI config), configure the mapping of mapper IDs to mapper classes so PHPStan can narrow the generic `Asset` type to a concrete asset class: + +```neon +parameters: + nette: + assets: + mapping: + default: file # Nette\Assets\FilesystemMapper + images: file + vite: vite # Nette\Assets\ViteMapper + custom: App\MyMapper # any FQCN +``` + +The values `file` and `vite` are shortcuts for the built-in `FilesystemMapper` and `ViteMapper`. Any other value is treated as a fully qualified class name of a custom mapper. + +After configuration: + +- `Registry::getMapper('vite')` returns `ViteMapper` instead of `Mapper`. +- `Registry::getAsset('default:logo.png')` returns `ImageAsset`. `tryGetAsset()` returns `ImageAsset|null`. +- `FilesystemMapper::getAsset('button.js')` and `ViteMapper::getAsset()` are narrowed the same way. + + +Component Model +=============== + +Narrows the return type of `Container::getComponent()` and `Container::offsetGet()` (i.e. `$this['name']`) based on `createComponent<Name>()` factory methods declared on the same class. + +```php +class HomePresenter extends Presenter +{ + protected function createComponentMenu(): MenuControl + { + return new MenuControl; + } + + public function renderDefault(): void + { + $menu = $this->getComponent('menu'); // MenuControl + $menu = $this['menu']; // MenuControl + } +} +``` + +When no matching factory exists or the component name is not a compile-time string, the return type of `getComponent()` and `$this['name']` stays unchanged, i.e. the generic `IComponent`. + + +Dependency Injection +==================== + +Properties marked with the `#[Nette\DI\Attributes\Inject]` attribute are filled by dependency injection after the object is created. PHPStan would therefore report them as uninitialized; the extension instead treats them as written and initialized: + +```php +class HomePresenter extends Presenter +{ + #[Inject] + public CartFacade $cart; // no uninitialized-property error +} +``` + + +Forms +===== + +When `$form->addText('name', …)`, `$form->addSelect(…)` and similar are called in the same function or method as the access to `$form['name']` (or `$form->getComponent('name')`), the extension infers the access type from the corresponding `addXxx()` call: + +```php +public function createComponentSignInForm(): Form +{ + $form = new Form; + $form->addText('username', 'Username'); + $form->addPassword('password', 'Password'); + + $form['username']; // TextInput + $form['password']; // TextInput (Password is a subclass) + return $form; +} +``` + +Access works from a method other than the one where the form was created. When you build it in the `createComponentSignInForm()` factory and access its controls elsewhere, the extension traces the assignment back to the factory and finds the matching `addXxx()` call: + +```php +public function renderDefault(): void +{ + $form = $this['signInForm']; // resolves createComponentSignInForm() + $form['username']; // TextInput + + // direct chained access works as well + $this['signInForm']['username']; // TextInput + $this['signInForm-username']; // TextInput +} +``` + +If no matching `addXxx()` call is found, the extension falls back to `createComponent<Name>()` factory lookup, just like the Component Model extension. + + +Event-handler properties +------------------------ + +Forms coerce the data to the type declared in the callback's parameter, be it `stdClass`, `array`, or a custom DTO. So a callback whose data parameter is narrower than the declared `array|object` union is valid at runtime: + +```php +$form->onSuccess[] = function (Form $form, MyDto $data): void { + // … +}; +``` + +PHPStan would normally report `assign.propertyType` because `MyDto` is narrower than `array|object`. The rule suppresses that error on `Form::$onSuccess`, `$onError`, `$onSubmit`, `$onRender`, `Container::$onValidate`, `SubmitButton::$onClick`, and `$onInvalidClick`. + + +Schema +====== + +Narrows the return type of `Expect::array()` from the declared `Structure|Type` union based on the argument: + +```php +Expect::array(); // Type +Expect::array(['name' => Expect::string()]); // Structure (all values are Schema) +Expect::array(['name' => Expect::string(), 'x']); // Structure|Type (mixed Schema and non-Schema) +``` + +When the argument mixes Schema and non-Schema values, the declared union is kept. + + +Tester +====== + +PHPStan understands type narrowing after `Tester\Assert` calls. Supported methods: `null()`, `notNull()`, `true()`, `false()`, `truthy()`, `falsey()`, `same()`, `notSame()`, `type()`. + +```php +function process(?User $user): void +{ + Assert::notNull($user); + $user->getName(); // no "called on null" warning +} +``` + + +Arrow functions as void callbacks +--------------------------------- + +Tester's `test()` and `Assert::exception()` accept callbacks typed as `Closure(): void`, but it is common to pass arrow functions like `fn () => throw new MyException`. An arrow function always has a return value, which PHPStan would normally flag as a type mismatch. The rule suppresses that error for the following functions and methods: `test()`, `testException()`, `testNoError()`, `Tester\Assert::exception()`, `Tester\Assert::throws()`, `Tester\Assert::error()`, `Tester\Assert::noError()`. + + +Utils +===== + +**`Strings::match()` and `matchAll()`**: for a constant pattern, the return type is inferred directly from the regular expression, i.e. from its capture groups (including named and optional ones). The flags `captureOffset`, `unmatchedAsNull`, and for `matchAll()` also `patternOrder` and `lazy` are reflected in the resulting shape: + +```php +Strings::match($s, '#(\d+)-(\w+)#'); // array{non-falsy-string, decimal-int-string, non-empty-string}|null +Strings::match($s, '#(?<id>\d+)#'); // array{0: non-empty-string, id: decimal-int-string, 1: decimal-int-string}|null +Strings::matchAll($s, '#(\w+)#'); // list<array{string, non-empty-string}> +``` + +For a non-constant pattern (and for the `split()` method), the shape is inferred from the flags only. + +**`Strings::replace()`**: when the replacement is a callback, the type of its `$matches` parameter is inferred from the same regular expression: + +```php +Strings::replace($s, '#(\d+)#', function (array $m) { + return $m[1]; // $m is of type array{non-empty-string, decimal-int-string} +}); +``` + +**Subject narrowing after `match()`**: inside `if (Strings::match($s, …))` the searched string `$s` is also narrowed based on the pattern, for example to `non-empty-string`. + +**Pattern validation**: an invalid regular expression passed to `match()`, `matchAll()`, `split()` or `replace()` is reported during analysis instead of at runtime. + +**`Arrays::invoke()`** and **`Arrays::invokeMethod()`** return an array of the callable / method return type instead of the declared `array`. + +**`Helpers::falseToNull()`** narrows the return type by removing `false` and adding `null`. Thus `string|false` becomes `string|null`. + +**`Html` magic methods**: `$el->setClass(…)`, `$el->addData(…)`, `$el->getHref()` and similar are resolved without `@method` annotations. `setXxx()` and `addXxx()` return `static` (fluent API), `getXxx()` returns `mixed`. diff --git a/tools/es/@home.texy b/tools/es/@home.texy index 444de4b348..935247ec55 100644 --- a/tools/es/@home.texy +++ b/tools/es/@home.texy @@ -15,6 +15,7 @@ Calidad del código ------------------ - [Code Checker |code-checker] comprueba sus archivos fuente en busca de defectos formales como un BOM invisible, caracteres de control, codificación dañada o sintaxis inválida de archivos PHP, Latte, NEON, JSON y YAML, y puede corregirlos automáticamente. - [Coding Standard |en:coding-standard] formatea automáticamente su código PHP según el estándar de codificación de Nette, desde la sangría y las llaves hasta los espacios y la ordenación de las importaciones. +- [PHPStan Rules |en:phpstan-rules] enseñan a PHPStan a entender el código de Nette, de modo que el análisis estático infiere tipos precisos y notifica menos falsos positivos. Inteligencia artificial diff --git a/tools/fr/@home.texy b/tools/fr/@home.texy index 9eeaa8c832..74eeab8370 100644 --- a/tools/fr/@home.texy +++ b/tools/fr/@home.texy @@ -15,6 +15,7 @@ Qualité du code --------------- - [Code Checker |code-checker] vérifie vos fichiers sources et y détecte des défauts formels tels qu'un BOM invisible, des caractères de contrôle, un encodage incorrect ou une syntaxe invalide des fichiers PHP, Latte, NEON, JSON et YAML, et peut les corriger automatiquement. - [Coding Standard |en:coding-standard] formate automatiquement votre code PHP selon le standard de codage Nette, de l'indentation et des accolades jusqu'aux espaces et à l'ordre des imports. +- [PHPStan Rules |en:phpstan-rules] apprennent à PHPStan à comprendre le code Nette, pour que l'analyse statique déduise des types précis et signale moins de faux positifs. Intelligence artificielle diff --git a/tools/hu/@home.texy b/tools/hu/@home.texy index 4887c35af0..097a1aec50 100644 --- a/tools/hu/@home.texy +++ b/tools/hu/@home.texy @@ -15,6 +15,7 @@ Kódminőség ---------- - [Code Checker |code-checker] ellenőrzi a forrásfájljaidat, és olyan formai hibákat keres bennük, mint a láthatatlan BOM, a vezérlő karakterek, a hibás kódolás vagy a PHP, Latte, NEON, JSON és YAML fájlok érvénytelen szintaxisa, és képes automatikusan kijavítani őket. - [Coding Standard |en:coding-standard] automatikusan formázza a PHP kódodat a Nette coding standard szerint, a behúzástól és a zárójelektől kezdve a szóközökön át az importok rendezéséig. +- [PHPStan Rules |en:phpstan-rules] megtanítják a PHPStan-t a Nette-kód megértésére, így a statikus elemzés pontos típusokat következtet ki és kevesebb téves riasztást jelez. Mesterséges intelligencia diff --git a/tools/it/@home.texy b/tools/it/@home.texy index 5a05e0f4ab..7d3324d4ae 100644 --- a/tools/it/@home.texy +++ b/tools/it/@home.texy @@ -15,6 +15,7 @@ Qualità del codice ------------------ - [Code Checker |code-checker] controlla i tuoi file sorgente alla ricerca di difetti formali come un BOM invisibile, caratteri di controllo, codifica errata o sintassi non valida nei file PHP, Latte, NEON, JSON e YAML, e può correggerli automaticamente. - [Coding Standard |en:coding-standard] formatta automaticamente il tuo codice PHP secondo lo standard di codifica di Nette, dall'indentazione e le parentesi agli spazi e all'ordinamento degli import. +- [PHPStan Rules |en:phpstan-rules] insegnano a PHPStan a comprendere il codice Nette, così l'analisi statica deduce tipi precisi e segnala meno falsi positivi. Intelligenza artificiale diff --git a/tools/ja/@home.texy b/tools/ja/@home.texy index fa7686a10d..a2ab2a8418 100644 --- a/tools/ja/@home.texy +++ b/tools/ja/@home.texy @@ -15,6 +15,7 @@ Nette での開発を容易にする補助ツール。 ----- - [Code Checker |code-checker] は、目に見えない BOM、制御文字、壊れたエンコーディング、PHP・Latte・NEON・JSON・YAML ファイルの不正な構文といった形式的な欠陥がないかソースファイルをチェックし、自動的に修正できます。 - [Coding Standard |en:coding-standard] は、インデントや波括弧から、スペースの入れ方やインポートの並び順まで、Nette のコーディング標準に従って PHP コードを自動的に整形します。 +- [PHPStan Rules |en:phpstan-rules] は、PHPStan に Nette のコードを理解させ、静的解析が正確な型を推論し、誤検知を減らします。 人工知能 diff --git a/tools/pl/@home.texy b/tools/pl/@home.texy index 3c0cb8905f..537260f506 100644 --- a/tools/pl/@home.texy +++ b/tools/pl/@home.texy @@ -15,6 +15,7 @@ Jakość kodu ----------- - [Code Checker |code-checker] sprawdza Twoje pliki źródłowe pod kątem formalnych usterek, takich jak niewidoczny BOM, znaki kontrolne, błędne kodowanie czy nieprawidłowa składnia plików PHP, Latte, NEON, JSON i YAML, oraz potrafi je automatycznie naprawić. - [Coding Standard |en:coding-standard] automatycznie formatuje Twój kod PHP zgodnie ze standardem kodowania Nette, od wcięć i nawiasów po odstępy i kolejność importów. +- [PHPStan Rules |en:phpstan-rules] uczą PHPStan rozumieć kod Nette, dzięki czemu analiza statyczna wnioskuje precyzyjne typy i zgłasza mniej fałszywych alarmów. Sztuczna inteligencja diff --git a/tools/pt/@home.texy b/tools/pt/@home.texy index 5cc8d7227a..613a694b4a 100644 --- a/tools/pt/@home.texy +++ b/tools/pt/@home.texy @@ -15,6 +15,7 @@ Qualidade do Código ------------------- - [Code Checker |code-checker] verifica seus arquivos de origem em busca de falhas formais, como um BOM invisível, caracteres de controle, codificação corrompida ou sintaxe inválida de arquivos PHP, Latte, NEON, JSON e YAML, e pode corrigi-los automaticamente. - [Coding Standard |en:coding-standard] formata automaticamente seu código PHP de acordo com o padrão de codificação do Nette, da indentação e chaves ao espaçamento e à ordenação das importações. +- [PHPStan Rules |en:phpstan-rules] ensinam o PHPStan a entender o código Nette, de modo que a análise estática infere tipos precisos e relata menos falsos positivos. Inteligência Artificial diff --git a/tools/ro/@home.texy b/tools/ro/@home.texy index 5df6a4c5c2..f5db71d900 100644 --- a/tools/ro/@home.texy +++ b/tools/ro/@home.texy @@ -15,6 +15,7 @@ Calitatea codului ----------------- - [Code Checker |code-checker] verifică fișierele sursă pentru defecte formale precum un BOM invizibil, caractere de control, codificare deteriorată sau sintaxă invalidă a fișierelor PHP, Latte, NEON, JSON și YAML și le poate corecta automat. - [Coding Standard |en:coding-standard] formatează automat codul PHP conform standardului de codare Nette, de la indentare și acolade până la spațiere și ordonarea importurilor. +- [PHPStan Rules |en:phpstan-rules] învață PHPStan să înțeleagă codul Nette, astfel încât analiza statică deduce tipuri precise și raportează mai puține alarme false. Inteligență artificială diff --git a/tools/ru/@home.texy b/tools/ru/@home.texy index 9d1f8dd9a4..7fcfd5247d 100644 --- a/tools/ru/@home.texy +++ b/tools/ru/@home.texy @@ -15,6 +15,7 @@ ------------- - [Code Checker |code-checker] проверяет ваши исходные файлы и находит в них формальные недочёты, такие как невидимый BOM, управляющие символы, неправильную кодировку или некорректный синтаксис файлов PHP, Latte, NEON, JSON и YAML, и умеет их автоматически исправлять. - [Coding Standard |en:coding-standard] автоматически форматирует ваш PHP-код согласно стандарту кодирования Nette, от отступов и скобок до пробелов и порядка импортов. +- [PHPStan Rules |en:phpstan-rules] учат PHPStan понимать код Nette, благодаря чему статический анализ выводит точные типы и сообщает меньше ложных срабатываний. Искусственный интеллект diff --git a/tools/sl/@home.texy b/tools/sl/@home.texy index 491ee05959..c23621d6a6 100644 --- a/tools/sl/@home.texy +++ b/tools/sl/@home.texy @@ -15,6 +15,7 @@ Kakovost kode ------------- - [Code Checker |code-checker] preveri vaše izvorne datoteke in v njih poišče formalne pomanjkljivosti, kot so neviden BOM, kontrolni znaki, pokvarjeno kodiranje ali neveljavna sintaksa datotek PHP, Latte, NEON, JSON in YAML, ter jih zna samodejno popraviti. - [Coding Standard |en:coding-standard] samodejno oblikuje vašo PHP kodo v skladu z Nette coding standardom, od zamikov in oklepajev do presledkov in razvrščanja uvozov. +- [PHPStan Rules |en:phpstan-rules] naučijo PHPStan razumeti kodo Nette, tako da statična analiza sklepa natančne tipe in javlja manj lažnih opozoril. Umetna inteligenca diff --git a/tools/tr/@home.texy b/tools/tr/@home.texy index 234bd577ed..1433737f2b 100644 --- a/tools/tr/@home.texy +++ b/tools/tr/@home.texy @@ -15,6 +15,7 @@ Kod Kalitesi ------------ - [Code Checker |code-checker] kaynak dosyalarınızı görünmez bir BOM, kontrol karakterleri, bozuk kodlama veya PHP, Latte, NEON, JSON ve YAML dosyalarının geçersiz söz dizimi gibi biçimsel kusurlara karşı denetler ve bunları otomatik olarak düzeltebilir. - [Coding Standard |en:coding-standard] PHP kodunuzu, girintiden parantezlere, boşluk bırakmaya ve içe aktarmaların sıralamasına kadar Nette kodlama standardına göre otomatik olarak biçimlendirir. +- [PHPStan Rules |en:phpstan-rules] PHPStan'a Nette kodunu anlamayı öğretir, böylece statik analiz kesin türler çıkarır ve daha az yanlış pozitif bildirir. Yapay Zekâ diff --git a/tools/uk/@home.texy b/tools/uk/@home.texy index 0b364cf794..f4af2006c8 100644 --- a/tools/uk/@home.texy +++ b/tools/uk/@home.texy @@ -15,6 +15,7 @@ ----------- - [Code Checker |code-checker] перевіряє ваші вихідні файли на формальні недоліки, такі як невидимий BOM, керуючі символи, пошкоджене кодування або неправильний синтаксис файлів PHP, Latte, NEON, JSON та YAML, і вміє виправляти їх автоматично. - [Coding Standard |en:coding-standard] автоматично форматує ваш PHP код згідно з coding standard Nette, від відступів та дужок до пробілів і впорядкування імпортів. +- [PHPStan Rules |en:phpstan-rules] вчать PHPStan розуміти код Nette, завдяки чому статичний аналіз виводить точні типи й повідомляє менше хибних спрацювань. Штучний інтелект From fd2f7023a0fedf995c3628729d68720d8ad7a41e Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Sat, 6 Jun 2026 19:02:33 +0200 Subject: [PATCH 44/50] added X-ray page --- tools/bg/@home.texy | 1 + tools/cs/@home.texy | 1 + tools/cs/xray.texy | 90 +++++++++++++++++++++++++++++++++++++++++++++ tools/de/@home.texy | 1 + tools/el/@home.texy | 1 + tools/en/@home.texy | 1 + tools/en/xray.texy | 90 +++++++++++++++++++++++++++++++++++++++++++++ tools/es/@home.texy | 1 + tools/fr/@home.texy | 1 + tools/hu/@home.texy | 1 + tools/it/@home.texy | 1 + tools/ja/@home.texy | 1 + tools/pl/@home.texy | 1 + tools/pt/@home.texy | 1 + tools/ro/@home.texy | 1 + tools/ru/@home.texy | 1 + tools/sl/@home.texy | 1 + tools/tr/@home.texy | 1 + tools/uk/@home.texy | 1 + 19 files changed, 197 insertions(+) create mode 100644 tools/cs/xray.texy create mode 100644 tools/en/xray.texy diff --git a/tools/bg/@home.texy b/tools/bg/@home.texy index ab4917b6ff..a6991f3dff 100644 --- a/tools/bg/@home.texy +++ b/tools/bg/@home.texy @@ -16,6 +16,7 @@ - [Code Checker |code-checker] проверява изходните ви файлове за формални недостатъци като невидим BOM, контролни знаци, повредено кодиране или невалиден синтаксис на PHP, Latte, NEON, JSON и YAML файлове и може да ги поправи автоматично. - [Coding Standard |en:coding-standard] автоматично форматира вашия PHP код според Nette coding standard, от отстъпите и скобите до интервалите и подреждането на импортите. - [PHPStan Rules |en:phpstan-rules] учат PHPStan да разбира кода на Nette, така че статичният анализ извежда точни типове и докладва по-малко фалшиви сигнали. +- [X-Ray |en:xray] показва ви точно как проектът ви използва екосистемата на Nette: кои методи, Latte филтри и конфигурационни ключове реално използвате. Изкуствен интелект diff --git a/tools/cs/@home.texy b/tools/cs/@home.texy index 2250be0bb3..3e4cf8ed20 100644 --- a/tools/cs/@home.texy +++ b/tools/cs/@home.texy @@ -16,6 +16,7 @@ Kvalita kódu - [Code Checker |code-checker] zkontroluje vaše zdrojové soubory a najde v nich formální nedostatky, jako je neviditelný BOM, kontrolní znaky, chybné kódování nebo neplatná syntaxe souborů PHP, Latte, NEON, JSON a YAML, a umí je automaticky opravit. - [Coding Standard |coding-standard] automaticky naformátuje váš PHP kód podle Nette coding standardu, od odsazení a závorek až po mezery a řazení importů. - [PHPStan Rules |phpstan-rules] naučí PHPStan rozumět Nette kódu, takže statická analýza odvozuje přesné typy a hlásí méně falešných chyb. +- [X-Ray |xray] vám ukáže, jak přesně váš projekt využívá ekosystém Nette: které metody, Latte filtry i konfigurační klíče doopravdy používáte. Umělá inteligence diff --git a/tools/cs/xray.texy b/tools/cs/xray.texy new file mode 100644 index 0000000000..a8c2ac5963 --- /dev/null +++ b/tools/cs/xray.texy @@ -0,0 +1,90 @@ +Nette X-Ray +*********** + +.[perex] +[X-Ray |https://github.com/nette/xray] vám ukáže, jak přesně váš projekt využívá ekosystém Nette: které metody, Latte filtry i konfigurační klíče doopravdy používáte. + +Přemýšleli jste někdy, které Nette metody voláte nejčastěji? Které Latte filtry vlastně používáte? Sahá ještě někdo na ten starý konfigurační klíč? X-Ray prohledá váš kód statickou analýzou a odpoví vám přehledným HTML reportem. + + +Co se analyzuje +=============== + +Místo regulárních výrazů a odhadů používá X-Ray statickou analýzu: rozliší typy skrz dědičnost, pozná deklarující třídy a sleduje vzory argumentů. Výsledkem je přesný obrázek o tom, jak váš projekt interaguje s Nette. + +| PHP a PHPT | Latte šablony | NEON konfigurace | +|------------|---------------|------------------| +| volání metod a funkcí | značky a n:atributy | vzory DI služeb | +| argumenty (poziční, pojmenované) | filtry a jejich argumenty | registrace rozšíření | +| použití návratových hodnot | funkce a konstanty | použité sekce | +| přístup k properties | varianty syntaxe | konfigurační klíče | +| dědičnost tříd a traity | | | +| přepisy metod | | | + + +Instalace +========= + +Nainstalujte ho přes Composer jako vývojovou závislost: + +```shell +composer require --dev nette/xray +``` + +Vyžaduje PHP 8.2 nebo vyšší a běží na PHPStanu 2.1. Funguje s libovolným projektem, který používá Nette, Latte, Tracy, Dibi nebo Texy. + + +Použití +======= + +Spusťte ho nad svými zdrojovými adresáři: + +```shell +vendor/bin/xray app/ src/ +``` + +Během chvíle získáte interaktivní HTML report (`xray-report.html`), který stačí otevřít v prohlížeči, a strojově čitelná data (`xray-report.json`): + +``` + + +Nette X-Ray +=========== + +Scanning PHP files ... 142/142 done +Scanning NEON files ... 4/4 done +Scanning Latte files ... 87/87 done + +Reports saved to: + xray-report.json + xray-report.html +``` + + +Konfigurace +=========== + +Chování upravíte souborem `nette-xray.neon` v kořeni projektu: + +```neon +# Výchozí cesty k analýze (použijí se, když neuvedete argumenty na příkazové řádce) +paths: + - app + - src + +# Další adresáře k vyloučení (vendor, temp, node_modules, .git jsou vyloučeny automaticky) +excludeDirs: + - generated + +# Automatické odeslání bez ptaní +upload: false +``` + +/--comment + + +Pomozte vývoji Nette +==================== + +Po analýze můžete report dobrovolně odeslat a pomoct tak směřovat vývoj frameworku – reálná data o používání jsou spolehlivější než ankety. Odesílají se jen agregovaná čísla: kolikrát se které API zavolá a jaké vzory používáte. Žádný kód, žádné cesty k souborům, žádné hodnoty proměnných. Data se odešlou jen tehdy, když to výslovně potvrdíte, a JSON report se vždy nejdřív uloží lokálně, takže si ho můžete v klidu prohlédnout. +\-- diff --git a/tools/de/@home.texy b/tools/de/@home.texy index 6fc80f5356..53435c3dd4 100644 --- a/tools/de/@home.texy +++ b/tools/de/@home.texy @@ -16,6 +16,7 @@ Code-Qualität - [Code Checker |code-checker] überprüft Ihre Quelldateien auf formale Mängel wie ein unsichtbares BOM, Steuerzeichen, fehlerhafte Kodierung oder ungültige Syntax von PHP-, Latte-, NEON-, JSON- und YAML-Dateien und kann diese automatisch beheben. - [Coding Standard |en:coding-standard] formatiert Ihren PHP-Code automatisch gemäß dem Nette Coding Standard, von der Einrückung und den Klammern bis hin zu Abständen und der Reihenfolge der Imports. - [PHPStan Rules |en:phpstan-rules] bringen PHPStan bei, Nette-Code zu verstehen, sodass die statische Analyse präzise Typen ableitet und weniger Fehlalarme meldet. +- [X-Ray |en:xray] zeigt Ihnen genau, wie Ihr Projekt das Nette-Ökosystem nutzt: welche Methoden, Latte-Filter und Konfigurationsschlüssel Sie tatsächlich verwenden. Künstliche Intelligenz diff --git a/tools/el/@home.texy b/tools/el/@home.texy index 8e94ca24a8..ca46179083 100644 --- a/tools/el/@home.texy +++ b/tools/el/@home.texy @@ -16,6 +16,7 @@ - [Code Checker |code-checker] ελέγχει τα πηγαία αρχεία σας για τυπικά σφάλματα, όπως ένα αόρατο BOM, χαρακτήρες ελέγχου, κατεστραμμένη κωδικοποίηση ή μη έγκυρη σύνταξη αρχείων PHP, Latte, NEON, JSON και YAML, και μπορεί να τα διορθώσει αυτόματα. - [Coding Standard |en:coding-standard] μορφοποιεί αυτόματα τον κώδικα PHP σας σύμφωνα με το πρότυπο κωδικοποίησης του Nette, από τη στοίχιση και τα άγκιστρα μέχρι τα κενά και τη σειρά των imports. - [PHPStan Rules |en:phpstan-rules] μαθαίνουν στο PHPStan να κατανοεί τον κώδικα Nette, ώστε η στατική ανάλυση να συμπεραίνει ακριβείς τύπους και να αναφέρει λιγότερα ψευδώς θετικά. +- [X-Ray |en:xray] σας δείχνει ακριβώς πώς το έργο σας χρησιμοποιεί το οικοσύστημα Nette: ποιες μεθόδους, φίλτρα Latte και κλειδιά ρυθμίσεων χρησιμοποιείτε πραγματικά. Τεχνητή νοημοσύνη diff --git a/tools/en/@home.texy b/tools/en/@home.texy index 43b9ac8a6b..d9dbbdbac9 100644 --- a/tools/en/@home.texy +++ b/tools/en/@home.texy @@ -16,6 +16,7 @@ Code Quality - [Code Checker |code-checker] checks your source files for formal flaws such as an invisible BOM, control characters, broken encoding, or invalid syntax of PHP, Latte, NEON, JSON and YAML files, and can fix them automatically. - [Coding Standard |coding-standard] automatically formats your PHP code according to the Nette coding standard, from indentation and braces to spacing and the ordering of imports. - [PHPStan Rules |phpstan-rules] teach PHPStan to understand Nette code, so static analysis infers precise types and reports fewer false positives. +- [X-Ray |xray] shows you exactly how your project uses the Nette ecosystem: which methods, Latte filters and configuration keys you actually use. Artificial Intelligence diff --git a/tools/en/xray.texy b/tools/en/xray.texy new file mode 100644 index 0000000000..fbe6262e77 --- /dev/null +++ b/tools/en/xray.texy @@ -0,0 +1,90 @@ +Nette X-Ray +*********** + +.[perex] +[X-Ray |https://github.com/nette/xray] shows you exactly how your project uses the Nette ecosystem: which methods, Latte filters and configuration keys you actually use. + +Ever wondered which Nette methods you call the most? Which Latte filters you actually use? Whether anyone still touches that old configuration key? X-Ray scans your code with static analysis and answers that with a clear HTML report. + + +What Gets Analyzed +================== + +Instead of regex or guessing, X-Ray uses static analysis: it resolves types through inheritance, detects declaring classes and tracks argument patterns. The result is an accurate picture of how your project interacts with Nette. + +| PHP and PHPT | Latte templates | NEON configuration | +|--------------|-----------------|--------------------| +| method & function calls | tags & n:attributes | DI service patterns | +| arguments (positional, named) | filters & their arguments | extension registration | +| return value usage | functions & constants | section usage | +| property access | syntax variants | configuration keys | +| class inheritance & traits | | | +| method overrides | | | + + +Installation +============ + +Install it via Composer as a dev dependency: + +```shell +composer require --dev nette/xray +``` + +It requires PHP 8.2 or higher and runs on PHPStan 2.1. It works with any project using Nette, Latte, Tracy, Dibi or Texy. + + +Usage +===== + +Point it at your source directories: + +```shell +vendor/bin/xray app/ src/ +``` + +Within moments you get an interactive HTML report (`xray-report.html`) you can open in your browser, plus machine-readable data (`xray-report.json`): + +``` + + +Nette X-Ray +=========== + +Scanning PHP files ... 142/142 done +Scanning NEON files ... 4/4 done +Scanning Latte files ... 87/87 done + +Reports saved to: + xray-report.json + xray-report.html +``` + + +Configuration +============= + +Create a `nette-xray.neon` file in your project root to customize the behavior: + +```neon +# Default analysis paths (used when no CLI arguments are given) +paths: + - app + - src + +# Additional directories to exclude (vendor, temp, node_modules, .git are excluded by default) +excludeDirs: + - generated + +# Auto-upload without asking +upload: false +``` + +/--comment + + +Help Improve Nette +================== + +After the analysis, you can optionally send the report to help guide the framework's development – real usage data is far more reliable than surveys. Only aggregated numbers are sent: how many times each API is called and which patterns you use. No code, no file paths, no variable values. Data is sent only if you explicitly confirm, and the JSON report is always saved locally first, so you can review it at your leisure. +\-- diff --git a/tools/es/@home.texy b/tools/es/@home.texy index 935247ec55..0cfec58c68 100644 --- a/tools/es/@home.texy +++ b/tools/es/@home.texy @@ -16,6 +16,7 @@ Calidad del código - [Code Checker |code-checker] comprueba sus archivos fuente en busca de defectos formales como un BOM invisible, caracteres de control, codificación dañada o sintaxis inválida de archivos PHP, Latte, NEON, JSON y YAML, y puede corregirlos automáticamente. - [Coding Standard |en:coding-standard] formatea automáticamente su código PHP según el estándar de codificación de Nette, desde la sangría y las llaves hasta los espacios y la ordenación de las importaciones. - [PHPStan Rules |en:phpstan-rules] enseñan a PHPStan a entender el código de Nette, de modo que el análisis estático infiere tipos precisos y notifica menos falsos positivos. +- [X-Ray |en:xray] le muestra exactamente cómo usa su proyecto el ecosistema de Nette: qué métodos, filtros de Latte y claves de configuración utiliza realmente. Inteligencia artificial diff --git a/tools/fr/@home.texy b/tools/fr/@home.texy index 74eeab8370..a1fa46d801 100644 --- a/tools/fr/@home.texy +++ b/tools/fr/@home.texy @@ -16,6 +16,7 @@ Qualité du code - [Code Checker |code-checker] vérifie vos fichiers sources et y détecte des défauts formels tels qu'un BOM invisible, des caractères de contrôle, un encodage incorrect ou une syntaxe invalide des fichiers PHP, Latte, NEON, JSON et YAML, et peut les corriger automatiquement. - [Coding Standard |en:coding-standard] formate automatiquement votre code PHP selon le standard de codage Nette, de l'indentation et des accolades jusqu'aux espaces et à l'ordre des imports. - [PHPStan Rules |en:phpstan-rules] apprennent à PHPStan à comprendre le code Nette, pour que l'analyse statique déduise des types précis et signale moins de faux positifs. +- [X-Ray |en:xray] vous montre exactement comment votre projet utilise l'écosystème Nette : quelles méthodes, filtres Latte et clés de configuration vous utilisez réellement. Intelligence artificielle diff --git a/tools/hu/@home.texy b/tools/hu/@home.texy index 097a1aec50..5ef44ab685 100644 --- a/tools/hu/@home.texy +++ b/tools/hu/@home.texy @@ -16,6 +16,7 @@ Kódminőség - [Code Checker |code-checker] ellenőrzi a forrásfájljaidat, és olyan formai hibákat keres bennük, mint a láthatatlan BOM, a vezérlő karakterek, a hibás kódolás vagy a PHP, Latte, NEON, JSON és YAML fájlok érvénytelen szintaxisa, és képes automatikusan kijavítani őket. - [Coding Standard |en:coding-standard] automatikusan formázza a PHP kódodat a Nette coding standard szerint, a behúzástól és a zárójelektől kezdve a szóközökön át az importok rendezéséig. - [PHPStan Rules |en:phpstan-rules] megtanítják a PHPStan-t a Nette-kód megértésére, így a statikus elemzés pontos típusokat következtet ki és kevesebb téves riasztást jelez. +- [X-Ray |en:xray] pontosan megmutatja, hogyan használja a projekted a Nette ökoszisztémát: mely metódusokat, Latte szűrőket és konfigurációs kulcsokat használsz ténylegesen. Mesterséges intelligencia diff --git a/tools/it/@home.texy b/tools/it/@home.texy index 7d3324d4ae..949dc3a3d9 100644 --- a/tools/it/@home.texy +++ b/tools/it/@home.texy @@ -16,6 +16,7 @@ Qualità del codice - [Code Checker |code-checker] controlla i tuoi file sorgente alla ricerca di difetti formali come un BOM invisibile, caratteri di controllo, codifica errata o sintassi non valida nei file PHP, Latte, NEON, JSON e YAML, e può correggerli automaticamente. - [Coding Standard |en:coding-standard] formatta automaticamente il tuo codice PHP secondo lo standard di codifica di Nette, dall'indentazione e le parentesi agli spazi e all'ordinamento degli import. - [PHPStan Rules |en:phpstan-rules] insegnano a PHPStan a comprendere il codice Nette, così l'analisi statica deduce tipi precisi e segnala meno falsi positivi. +- [X-Ray |en:xray] ti mostra esattamente come il tuo progetto utilizza l'ecosistema Nette: quali metodi, filtri Latte e chiavi di configurazione usi realmente. Intelligenza artificiale diff --git a/tools/ja/@home.texy b/tools/ja/@home.texy index a2ab2a8418..e9e7a9ddf5 100644 --- a/tools/ja/@home.texy +++ b/tools/ja/@home.texy @@ -16,6 +16,7 @@ Nette での開発を容易にする補助ツール。 - [Code Checker |code-checker] は、目に見えない BOM、制御文字、壊れたエンコーディング、PHP・Latte・NEON・JSON・YAML ファイルの不正な構文といった形式的な欠陥がないかソースファイルをチェックし、自動的に修正できます。 - [Coding Standard |en:coding-standard] は、インデントや波括弧から、スペースの入れ方やインポートの並び順まで、Nette のコーディング標準に従って PHP コードを自動的に整形します。 - [PHPStan Rules |en:phpstan-rules] は、PHPStan に Nette のコードを理解させ、静的解析が正確な型を推論し、誤検知を減らします。 +- [X-Ray |en:xray] は、プロジェクトが Nette エコシステムをどのように使っているかを正確に示します:実際に使用しているメソッド、Latte フィルター、設定キーがわかります。 人工知能 diff --git a/tools/pl/@home.texy b/tools/pl/@home.texy index 537260f506..13e507ae8e 100644 --- a/tools/pl/@home.texy +++ b/tools/pl/@home.texy @@ -16,6 +16,7 @@ Jakość kodu - [Code Checker |code-checker] sprawdza Twoje pliki źródłowe pod kątem formalnych usterek, takich jak niewidoczny BOM, znaki kontrolne, błędne kodowanie czy nieprawidłowa składnia plików PHP, Latte, NEON, JSON i YAML, oraz potrafi je automatycznie naprawić. - [Coding Standard |en:coding-standard] automatycznie formatuje Twój kod PHP zgodnie ze standardem kodowania Nette, od wcięć i nawiasów po odstępy i kolejność importów. - [PHPStan Rules |en:phpstan-rules] uczą PHPStan rozumieć kod Nette, dzięki czemu analiza statyczna wnioskuje precyzyjne typy i zgłasza mniej fałszywych alarmów. +- [X-Ray |en:xray] pokazuje dokładnie, jak Twój projekt korzysta z ekosystemu Nette: których metod, filtrów Latte i kluczy konfiguracyjnych faktycznie używasz. Sztuczna inteligencja diff --git a/tools/pt/@home.texy b/tools/pt/@home.texy index 613a694b4a..a7816009a7 100644 --- a/tools/pt/@home.texy +++ b/tools/pt/@home.texy @@ -16,6 +16,7 @@ Qualidade do Código - [Code Checker |code-checker] verifica seus arquivos de origem em busca de falhas formais, como um BOM invisível, caracteres de controle, codificação corrompida ou sintaxe inválida de arquivos PHP, Latte, NEON, JSON e YAML, e pode corrigi-los automaticamente. - [Coding Standard |en:coding-standard] formata automaticamente seu código PHP de acordo com o padrão de codificação do Nette, da indentação e chaves ao espaçamento e à ordenação das importações. - [PHPStan Rules |en:phpstan-rules] ensinam o PHPStan a entender o código Nette, de modo que a análise estática infere tipos precisos e relata menos falsos positivos. +- [X-Ray |en:xray] mostra exatamente como seu projeto usa o ecossistema Nette: quais métodos, filtros Latte e chaves de configuração você realmente usa. Inteligência Artificial diff --git a/tools/ro/@home.texy b/tools/ro/@home.texy index f5db71d900..abdeeb2ef3 100644 --- a/tools/ro/@home.texy +++ b/tools/ro/@home.texy @@ -16,6 +16,7 @@ Calitatea codului - [Code Checker |code-checker] verifică fișierele sursă pentru defecte formale precum un BOM invizibil, caractere de control, codificare deteriorată sau sintaxă invalidă a fișierelor PHP, Latte, NEON, JSON și YAML și le poate corecta automat. - [Coding Standard |en:coding-standard] formatează automat codul PHP conform standardului de codare Nette, de la indentare și acolade până la spațiere și ordonarea importurilor. - [PHPStan Rules |en:phpstan-rules] învață PHPStan să înțeleagă codul Nette, astfel încât analiza statică deduce tipuri precise și raportează mai puține alarme false. +- [X-Ray |en:xray] îți arată exact cum folosește proiectul tău ecosistemul Nette: ce metode, filtre Latte și chei de configurare folosești de fapt. Inteligență artificială diff --git a/tools/ru/@home.texy b/tools/ru/@home.texy index 7fcfd5247d..244b524eb9 100644 --- a/tools/ru/@home.texy +++ b/tools/ru/@home.texy @@ -16,6 +16,7 @@ - [Code Checker |code-checker] проверяет ваши исходные файлы и находит в них формальные недочёты, такие как невидимый BOM, управляющие символы, неправильную кодировку или некорректный синтаксис файлов PHP, Latte, NEON, JSON и YAML, и умеет их автоматически исправлять. - [Coding Standard |en:coding-standard] автоматически форматирует ваш PHP-код согласно стандарту кодирования Nette, от отступов и скобок до пробелов и порядка импортов. - [PHPStan Rules |en:phpstan-rules] учат PHPStan понимать код Nette, благодаря чему статический анализ выводит точные типы и сообщает меньше ложных срабатываний. +- [X-Ray |en:xray] показывает вам, как именно ваш проект использует экосистему Nette: какие методы, фильтры Latte и ключи конфигурации вы действительно используете. Искусственный интеллект diff --git a/tools/sl/@home.texy b/tools/sl/@home.texy index c23621d6a6..e46fda3f22 100644 --- a/tools/sl/@home.texy +++ b/tools/sl/@home.texy @@ -16,6 +16,7 @@ Kakovost kode - [Code Checker |code-checker] preveri vaše izvorne datoteke in v njih poišče formalne pomanjkljivosti, kot so neviden BOM, kontrolni znaki, pokvarjeno kodiranje ali neveljavna sintaksa datotek PHP, Latte, NEON, JSON in YAML, ter jih zna samodejno popraviti. - [Coding Standard |en:coding-standard] samodejno oblikuje vašo PHP kodo v skladu z Nette coding standardom, od zamikov in oklepajev do presledkov in razvrščanja uvozov. - [PHPStan Rules |en:phpstan-rules] naučijo PHPStan razumeti kodo Nette, tako da statična analiza sklepa natančne tipe in javlja manj lažnih opozoril. +- [X-Ray |en:xray] vam natančno pokaže, kako vaš projekt uporablja ekosistem Nette: katere metode, filtre Latte in konfiguracijske ključe dejansko uporabljate. Umetna inteligenca diff --git a/tools/tr/@home.texy b/tools/tr/@home.texy index 1433737f2b..936ad2890a 100644 --- a/tools/tr/@home.texy +++ b/tools/tr/@home.texy @@ -16,6 +16,7 @@ Kod Kalitesi - [Code Checker |code-checker] kaynak dosyalarınızı görünmez bir BOM, kontrol karakterleri, bozuk kodlama veya PHP, Latte, NEON, JSON ve YAML dosyalarının geçersiz söz dizimi gibi biçimsel kusurlara karşı denetler ve bunları otomatik olarak düzeltebilir. - [Coding Standard |en:coding-standard] PHP kodunuzu, girintiden parantezlere, boşluk bırakmaya ve içe aktarmaların sıralamasına kadar Nette kodlama standardına göre otomatik olarak biçimlendirir. - [PHPStan Rules |en:phpstan-rules] PHPStan'a Nette kodunu anlamayı öğretir, böylece statik analiz kesin türler çıkarır ve daha az yanlış pozitif bildirir. +- [X-Ray |en:xray] projenizin Nette ekosistemini tam olarak nasıl kullandığını gösterir: gerçekte hangi metotları, Latte filtrelerini ve yapılandırma anahtarlarını kullandığınızı. Yapay Zekâ diff --git a/tools/uk/@home.texy b/tools/uk/@home.texy index f4af2006c8..6c544559eb 100644 --- a/tools/uk/@home.texy +++ b/tools/uk/@home.texy @@ -16,6 +16,7 @@ - [Code Checker |code-checker] перевіряє ваші вихідні файли на формальні недоліки, такі як невидимий BOM, керуючі символи, пошкоджене кодування або неправильний синтаксис файлів PHP, Latte, NEON, JSON та YAML, і вміє виправляти їх автоматично. - [Coding Standard |en:coding-standard] автоматично форматує ваш PHP код згідно з coding standard Nette, від відступів та дужок до пробілів і впорядкування імпортів. - [PHPStan Rules |en:phpstan-rules] вчать PHPStan розуміти код Nette, завдяки чому статичний аналіз виводить точні типи й повідомляє менше хибних спрацювань. +- [X-Ray |en:xray] показує вам, як саме ваш проєкт використовує екосистему Nette: які методи, фільтри Latte та ключі конфігурації ви насправді використовуєте. Штучний інтелект From 8b46d74f04e547c7ae8b9b3393b71dce39139edc Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Mon, 25 May 2026 20:59:32 +0200 Subject: [PATCH 45/50] tracy 2.12.0 --- tracy/cs/extensions.texy | 23 +++++++++++++++++++++++ tracy/cs/guide.texy | 15 +++++++++++++++ tracy/en/extensions.texy | 23 +++++++++++++++++++++++ tracy/en/guide.texy | 15 +++++++++++++++ 4 files changed, 76 insertions(+) diff --git a/tracy/cs/extensions.texy b/tracy/cs/extensions.texy index 1e1fe25baf..f960a405d1 100644 --- a/tracy/cs/extensions.texy +++ b/tracy/cs/extensions.texy @@ -104,6 +104,29 @@ Pokud má být výchozí stav sbalený, doplňte oběma elementům třídu `trac Counter použijte statický, aby se nevytvářely duplicitní ID na jedné stránce. +Podpora AI agentů .{data-version:2.12} +-------------------------------------- + +Když prohlížeč ovládá AI agent, Tracy pošle markdown shrnutí Tracy Baru do JS konzole. Vlastní panely mohou nabídnout svůj markdown přidáním metody `getAgentInfo(): ?string` do třídy implementující `IBarPanel`: + +```php +class DatabasePanel implements Tracy\IBarPanel +{ + public function getTab(): string { /* ... */ } + public function getPanel(): string { /* ... */ } + + public function getAgentInfo(): ?string + { + return "## Database\n\n- Dotazy: {$this->count}\n- Celkový čas: {$this->time} ms\n"; + } +} +``` + +Vrácený markdown se zařadí do markdown shrnutí baru. Pokud metoda chybí nebo vrátí `null`, panel se ve shrnutí vynechá. + +Více v [integraci Tracy s AI agenty |guide#Podpora AI agentů]. + + Rozšíření pro Bluescreen ======================== diff --git a/tracy/cs/guide.texy b/tracy/cs/guide.texy index 8ce469764f..b1b37ef2d6 100644 --- a/tracy/cs/guide.texy +++ b/tracy/cs/guide.texy @@ -182,6 +182,21 @@ Pokud používáte celý Nette Framework, lze toto a další nastavit v [konfigu Aby vám však nezaplavila e-mailovou schránku, pošle vždy **pouze jednu zprávu** a vytvoří soubor `email-sent`. Vývojář po přijetí e-mailové notifikace zkontroluje log, opraví aplikaci a smaže monitorovací soubor, čímž se opět aktivuje odesílání e-mailů. +Podpora AI agentů .{data-version:2.12} +====================================== + +Když vaši aplikaci ovládá AI agent přes prohlížeč (Chrome DevTools MCP, Playwright, Puppeteer), Tracy jej detekuje podle JavaScriptové vlastnosti `navigator.webdriver` a posílá markdown verzi hlavních diagnostických výstupů do konzole prohlížeče vedle standardního UI: + +- **BlueScreen** – výjimka, stack trace a hodnoty proměnných se pošlou do `console.error()` vedle červené obrazovky, a to pro synchronní vykreslování i AJAXové chyby. +- **Tracy Bar** – markdown shrnutí hlavních panelů (SQL, Errors, Dumps) se pošle do `console.log()`. +- **`Debugger::dump()`** – plain text varianta vedle běžného HTML výpisu, aby dumpy nezůstaly pohřbené ve stránce. +- **Produkční 500 stránka** – `console.error()` agentovi sdělí, že došlo k chybě a že její detaily jsou zalogované na serveru. + +Detekce nastaví cookie `tracy-webdriver=1`; pokud chcete markdown výstup vidět z normálního prohlížeče, cookie si nastavte ručně v DevTools. Aktivace agenta neovlivňuje `.md` sourozence, kteří se zapisují vedle každého `log/exception-*.html` bez podmínek – ti jsou vstupem pro dávkové zpracování produkčních logů. + +Vlastní panely Tracy Baru mohou nabídnout svůj markdown výstup implementací [`getAgentInfo()` |extensions#Podpora AI agentů]. Pro uživatele Claude Code obsahuje [Nette plugin |https://ai.nette.org/en/claude-code] skill `tracy-debugging`, který agentovi vysvětluje, jak číst Tracy výstup z `list_console_messages()`. + + Otevírání v editoru =================== diff --git a/tracy/en/extensions.texy b/tracy/en/extensions.texy index 6a90c18526..9659bd79fc 100644 --- a/tracy/en/extensions.texy +++ b/tracy/en/extensions.texy @@ -104,6 +104,29 @@ If the default state is collapsed, add the class `tracy-collapsed` to both eleme Use a static counter to prevent duplicate IDs on one page. +AI Agent Support .{data-version:2.12} +------------------------------------- + +When an AI agent drives the browser, Tracy sends a markdown summary of the Tracy Bar to the JS console. Custom panels can supply their own markdown by adding a `getAgentInfo(): ?string` method to their `IBarPanel` implementation: + +```php +class DatabasePanel implements Tracy\IBarPanel +{ + public function getTab(): string { /* ... */ } + public function getPanel(): string { /* ... */ } + + public function getAgentInfo(): ?string + { + return "## Database\n\n- Queries: {$this->count}\n- Total time: {$this->time} ms\n"; + } +} +``` + +The returned markdown is included in the bar's markdown summary. When the method is missing or returns `null`, the panel is omitted from the summary. + +See [Tracy's AI agent integration |guide#AI Agent Support] for the full picture. + + Bluescreen Extensions ===================== diff --git a/tracy/en/guide.texy b/tracy/en/guide.texy index 9ab2120f19..d6415c5ee5 100644 --- a/tracy/en/guide.texy +++ b/tracy/en/guide.texy @@ -182,6 +182,21 @@ If you use the entire Nette Framework, you can set this and others in the [confi To protect your e-mail box from being flooded, Tracy sends **only one message** and creates a file `email-sent`. When a developer receives the e-mail notification, they check the log, correct the application, and delete the `email-sent` monitoring file. This reactivates the e-mail sending. +AI Agent Support .{data-version:2.12} +===================================== + +When an AI agent drives your application through a browser (Chrome DevTools MCP, Playwright, Puppeteer), Tracy detects it via the JavaScript `navigator.webdriver` property and sends a markdown version of the key diagnostics into the browser console alongside the standard UI: + +- **BlueScreen** – exception, stack trace and variable values sent to `console.error()` next to the red screen, for both synchronous rendering and AJAX errors. +- **Tracy Bar** – markdown summary of the main panels (SQL, Errors, Dumps) sent to `console.log()`. +- **`Debugger::dump()`** – a plain text variant alongside the regular HTML output, so dumps don't get buried in the page. +- **Production 500 page** – `console.error()` informs the agent that an error has occurred and that details have been logged on the server. + +Detection sets the cookie `tracy-webdriver=1`; you can set it manually in DevTools to enable the markdown output from a regular browser. Agent activation does not affect the `.md` siblings written next to every `log/exception-*.html` – those are produced unconditionally and form the basis for batch processing of production logs. + +Custom Tracy Bar panels can supply their own markdown by implementing [`getAgentInfo()` |extensions#AI Agent Support]. For Claude Code users, the [Nette plugin |https://ai.nette.org/en/claude-code] includes the `tracy-debugging` skill that teaches the agent how to read Tracy's output from `list_console_messages()`. + + Opening Files in the Editor =========================== From d4fd62d0e5bee7c21496d75295e153ca8a30310a Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Tue, 26 May 2026 19:27:17 +0200 Subject: [PATCH 46/50] nette/http 3.3.4 --- http/cs/configuration.texy | 12 ++++++++++++ http/cs/request.texy | 1 + http/en/configuration.texy | 12 ++++++++++++ http/en/request.texy | 1 + 4 files changed, 26 insertions(+) diff --git a/http/cs/configuration.texy b/http/cs/configuration.texy index 4d9bc137d9..cd73811488 100644 --- a/http/cs/configuration.texy +++ b/http/cs/configuration.texy @@ -108,6 +108,18 @@ http: ``` +Vynucení HTTPS .{data-version:3.3.4} +------------------------------------ + +Bezpodmínečně vynutí HTTPS schéma požadavku. Hodí se pro weby běžící výhradně na HTTPS za load balancerem nebo reverzní proxy, která terminuje TLS, ale neposílá hlavičku `X-Forwarded-Proto`, takže by standardní detekce HTTPS (ani s nastavenou [#HTTP proxy]) nezabrala. + +```neon +http: + # vynutí HTTPS schéma u všech požadavků + forceHttps: true # (bool) výchozí je false +``` + + Session ======= diff --git a/http/cs/request.texy b/http/cs/request.texy index 1827f489e0..7c0aed42f4 100644 --- a/http/cs/request.texy +++ b/http/cs/request.texy @@ -236,6 +236,7 @@ RequestFactory lze před zavoláním `fromGlobals()` konfigurovat: - metodou `$factory->setBinary()` vypnete automatické čištění vstupních parametrů od kontrolních znaků a neplatných UTF-8 sekvencí. - metodou `$factory->setProxy(...)` uvedete IP adresu [proxy serveru |configuration#HTTP proxy], což je nezbytné pro správnou detekci IP adresy uživatele. +- metodou `$factory->setForceHttps()` .{data-version:3.3.4} vynutíte HTTPS schéma požadavku bez ohledu na prostředí serveru. RequestFactory umožňuje definovat filtry, které automaticky transformují části URL požadavku. Tyto filtry odstraňují nežádoucí znaky z URL, které tam mohou být vloženy například nesprávnou implementací komentářových systémů na různých webech: diff --git a/http/en/configuration.texy b/http/en/configuration.texy index 64ce01eb2d..1537a3a2c4 100644 --- a/http/en/configuration.texy +++ b/http/en/configuration.texy @@ -108,6 +108,18 @@ http: ``` +Force HTTPS .{data-version:3.3.4} +--------------------------------- + +Unconditionally forces the request scheme to HTTPS. This is useful for HTTPS-only sites running behind a load balancer or reverse proxy that terminates TLS but does not pass the `X-Forwarded-Proto` header, so the standard HTTPS detection (even with [#HTTP Proxy] configured) would not catch it. + +```neon +http: + # force HTTPS scheme for all requests + forceHttps: true # (bool) defaults to false +``` + + Session ======= diff --git a/http/en/request.texy b/http/en/request.texy index 47e0232f54..2290ad59b9 100644 --- a/http/en/request.texy +++ b/http/en/request.texy @@ -236,6 +236,7 @@ RequestFactory can be configured before calling `fromGlobals()`: - using the `$factory->setBinary()` method disables automatic cleansing of input parameters from control characters and invalid UTF-8 sequences. - using the `$factory->setProxy(...)` method specifies the IP address of the [proxy server |configuration#HTTP Proxy], which is necessary for correct detection of the user's IP address. +- using the `$factory->setForceHttps()` .{data-version:3.3.4} method forces the request scheme to HTTPS regardless of the server environment. RequestFactory allows defining filters that automatically transform parts of the URL request. These filters remove unwanted characters from URLs that might have been inserted, for example, by incorrect implementations of comment systems on various websites: From d143c506dacd989a7f6fd1b7314ad6eab5788ac0 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Wed, 3 Jun 2026 01:30:35 +0200 Subject: [PATCH 47/50] nette/http 3.4.0 --- forms/cs/in-presenter.texy | 2 +- forms/cs/standalone.texy | 4 +- forms/en/in-presenter.texy | 2 +- forms/en/standalone.texy | 4 +- http/cs/@left-menu.texy | 1 + http/cs/request.texy | 38 +++++++- http/cs/response.texy | 24 +++-- http/cs/sessions.texy | 4 +- http/cs/ssrf.texy | 183 +++++++++++++++++++++++++++++++++++++ http/en/@left-menu.texy | 1 + http/en/request.texy | 38 +++++++- http/en/response.texy | 24 +++-- http/en/sessions.texy | 4 +- http/en/ssrf.texy | 183 +++++++++++++++++++++++++++++++++++++ 14 files changed, 480 insertions(+), 32 deletions(-) create mode 100644 http/cs/ssrf.texy create mode 100644 http/en/ssrf.texy diff --git a/forms/cs/in-presenter.texy b/forms/cs/in-presenter.texy index 2c827d31f7..d49fa4168e 100644 --- a/forms/cs/in-presenter.texy +++ b/forms/cs/in-presenter.texy @@ -359,7 +359,7 @@ Zmíněný CSRF útok spočívá v tom, že útočník naláká oběť na strán $form->allowCrossOrigin(); // POZOR! Vypne ochranu! ``` -Tato ochrana využívá SameSite cookie pojmenovanou `_nss`. Ochrana pomocí SameSite cookie nemusí být 100% spolehlivá, proto je vhodné zapnout ještě ochranu pomocí tokenu: +Tato ochrana se opírá o hlavičky `Sec-Fetch-*` (Fetch Metadata), které prohlížeč posílá automaticky. Starší prohlížeče, které je neposílají, nejsou pokryté, proto je vhodné zapnout ještě ochranu pomocí tokenu: ```php $form->addProtection(); diff --git a/forms/cs/standalone.texy b/forms/cs/standalone.texy index 1b980ceeda..51153c9d33 100644 --- a/forms/cs/standalone.texy +++ b/forms/cs/standalone.texy @@ -304,9 +304,9 @@ Zmíněný CSRF útok spočívá v tom, že útočník naláká oběť na strán $form->allowCrossOrigin(); // POZOR! Vypne ochranu! ``` -Tato ochrana využívá SameSite cookie pojmenovanou `_nss`. Vytvářejte proto objekt formuláře ještě před odesláním prvního výstupu, aby bylo možné cookie odeslat. +Tato ochrana se opírá o hlavičky `Sec-Fetch-*` (Fetch Metadata), které prohlížeč posílá automaticky s požadavkem. -Ochrana pomocí SameSite cookie nemusí být 100% spolehlivá, proto je vhodné zapnout ještě ochranu pomocí tokenu: +Starší prohlížeče, které tyto hlavičky neposílají, nejsou pokryté, proto je vhodné zapnout ještě ochranu pomocí tokenu: ```php $form->addProtection(); diff --git a/forms/en/in-presenter.texy b/forms/en/in-presenter.texy index b4cde43641..1dd522dc93 100644 --- a/forms/en/in-presenter.texy +++ b/forms/en/in-presenter.texy @@ -359,7 +359,7 @@ The mentioned CSRF attack involves an attacker luring a victim to a page that si $form->allowCrossOrigin(); // WARNING! Disables protection! ``` -This protection uses a SameSite cookie named `_nss`. SameSite cookie protection might not be 100% reliable, so it's advisable to also enable token protection: +This protection relies on the browser's `Sec-Fetch-*` headers (Fetch Metadata), which it sends automatically. Older browsers that don't send them are not covered, so it's advisable to also enable token protection: ```php $form->addProtection(); diff --git a/forms/en/standalone.texy b/forms/en/standalone.texy index 0260668a0e..8cb60618aa 100644 --- a/forms/en/standalone.texy +++ b/forms/en/standalone.texy @@ -304,9 +304,9 @@ The mentioned CSRF attack involves an attacker luring a victim to a page that si $form->allowCrossOrigin(); // WARNING! Disables protection! ``` -This protection uses a SameSite cookie named `_nss`. Therefore, create the form object before sending the first output so that the cookie can be sent. +This protection relies on the browser's `Sec-Fetch-*` headers (Fetch Metadata), which it sends automatically with the request. -SameSite cookie protection may not be 100% reliable, so it's advisable to also enable token protection: +Older browsers that don't send these headers are not covered, so it's advisable to also enable token protection: ```php $form->addProtection(); diff --git a/http/cs/@left-menu.texy b/http/cs/@left-menu.texy index 8753fc54a5..d49c625ad1 100644 --- a/http/cs/@left-menu.texy +++ b/http/cs/@left-menu.texy @@ -5,4 +5,5 @@ Nette HTTP - [HTTP response|response] - [Sessions] - [URL utilities |urls] +- [Ochrana proti SSRF |ssrf] - [Konfigurace |configuration] diff --git a/http/cs/request.texy b/http/cs/request.texy index 7c0aed42f4..f47f8e0a33 100644 --- a/http/cs/request.texy +++ b/http/cs/request.texy @@ -146,9 +146,41 @@ isSecured(): bool .[method] Je spojení šifrované (HTTPS)? Pro správnou funkčnost může být potřeba [nastavit proxy |configuration#HTTP proxy]. -isSameSite(): bool .[method] ----------------------------- -Přichází požadavek ze stejné (sub)domény a je iniciován kliknutím na odkaz? Nette k detekci používá cookie `_nss` (dříve `nette-samesite`). +isSameSite(): bool .[method deprecated] +--------------------------------------- +Přišel požadavek ze stejné stránky (same-site)? Od verze 3.4 ji nahrazuje schopnější metoda [isFrom() |#isFrom]. + + +isFrom(FetchSite|array $site, FetchDest|array|null $dest=null, ?bool $user=null): bool .[method]{data-version:3.4} +------------------------------------------------------------------------------------------------------------------ +Řekne vám, odkud požadavek přišel a jak ho prohlížeč vytvořil, na základě hlaviček `Sec-Fetch-*` (tzv. [Fetch Metadata |https://developer.mozilla.org/en-US/docs/Glossary/Fetch_metadata_request_header]), které prohlížeč nastavuje sám a stránka běžící v prohlížeči oběti je nedokáže zfalšovat ani odstranit. Nette ji interně používá k automatické ochraně formulářů a signálů před útoky [Cross-Site Request Forgery |nette:glossary#Cross-Site Request Forgery CSRF] (CSRF). Hodí se, když chcete ochránit vlastní citlivé akce, jako jsou API endpointy nebo destruktivní odkazy. + +Metoda vrátí `true` pouze tehdy, když požadavek splňuje **všechny** zadané podmínky. První parametr `$site` popisuje vztah mezi stránkou, která požadavek vyvolala, a vaším webem (hlavička `Sec-Fetch-Site`). Přijímá jednu hodnotu nebo pole těchto hodnot výčtu `FetchSite`: + +- `FetchSite::SameOrigin` – ze zcela stejného původu (schéma, host i port) +- `FetchSite::SameSite` – ze stejného webu, případně z jiné subdomény +- `FetchSite::CrossSite` – z cizího webu +- `FetchSite::None` – uživatel jej vyvolal přímo, např. zadáním URL nebo otevřením záložky + +```php +// přišel požadavek z našich vlastních stránek? +if (!$httpRequest->isFrom([FetchSite::SameOrigin, FetchSite::SameSite])) { + // akci zablokujeme +} +``` + +Volitelný parametr `$dest` (hlavička `Sec-Fetch-Dest`) udává, jaký druh zdroje prohlížeč načítá, např. `FetchDest::Document` pro navigaci na stránku nebo `FetchDest::Empty` pro požadavek z JavaScriptu. Volitelný parametr `$user` (hlavička `Sec-Fetch-User`) říká, zda navigaci vyvolala skutečná akce uživatele, jako kliknutí na odkaz či odeslání formuláře; hodnotou `true` ji vyžadujete. + +Kontrola, že je akce dostupná pouze z vlastních stránek a jen skutečnou akcí uživatele, pak vypadá takto: + +```php +if (!$httpRequest->isFrom(FetchSite::SameOrigin, FetchDest::Document, user: true)) { + $this->error(); +} +``` + +.[note] +Starší prohlížeče (Safari před 16.4) hlavičky `Sec-Fetch-*` neposílají. Pro ně Nette použije záložně cookie `SameSite=Strict`, která dokazuje pouze to, že požadavek není cross-site. Kontrolu, která navíc vyžaduje `$dest` nebo `$user`, tak nelze tímto způsobem ověřit a v těchto prohlížečích vrátí `false` – pokud je to příliš striktní, testujte jen `$site`. isAjax(): bool .[method] diff --git a/http/cs/response.texy b/http/cs/response.texy index 4732bc7a76..3ad5c46192 100644 --- a/http/cs/response.texy +++ b/http/cs/response.texy @@ -115,15 +115,16 @@ $httpResponse->sendAsFile('faktura.pdf'); ``` -setCookie(string $name, string $value, $time, ?string $path=null, ?string $domain=null, ?bool $secure=null, ?bool $httpOnly=null, ?string $sameSite='Lax') .[method] --------------------------------------------------------------------------------------------------------------------------------------------------------------------- +setCookie(string $name, string $value, $time, ?string $path=null, ?string $domain=null, ?bool $secure=null, ?bool $httpOnly=null, SameSite|string $sameSite='Lax', bool $partitioned=false) .[method] +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Odešle cookie. Výchozí hodnoty parametrů: -| `$path` | `'/'` | cookie má dosah na všechny cesty v (sub)doméně *(konfigurovatelné)* -| `$domain` | `null` | což znamená s dosahem na aktuální (sub)doménu, ale nikoliv její subdomény *(konfigurovatelné)* -| `$secure` | `true` | pokud web běží na HTTPS, jinak `false` *(konfigurovatelné)* -| `$httpOnly` | `true` | cookie je pro JavaScript nepřístupná -| `$sameSite` | `'Lax'` | cookie nemusí být odeslána při [přístupu z jiné domény |nette:glossary#SameSite cookie] +| `$path` | `'/'` | cookie má dosah na všechny cesty v (sub)doméně *(konfigurovatelné)* +| `$domain` | `null` | což znamená s dosahem na aktuální (sub)doménu, ale nikoliv její subdomény *(konfigurovatelné)* +| `$secure` | `true` | pokud web běží na HTTPS, jinak `false` *(konfigurovatelné)* +| `$httpOnly` | `true` | cookie je pro JavaScript nepřístupná +| `$sameSite` | `'Lax'` | cookie nemusí být odeslána při [přístupu z jiné domény |nette:glossary#SameSite cookie] +| `$partitioned` | `false` | zda je cookie partitioned, viz níže *(od verze 3.4)* Výchozí hodnoty parametrů `$path`, `$domain` a `$secure` můžete změnit v [konfiguraci |configuration#HTTP cookie]. @@ -135,7 +136,14 @@ $httpResponse->setCookie('lang', 'cs', '100 days'); Parametr `$domain` určuje, které domény mohou cookie přijímat. Není-li uveden, cookie přijímá stejná (sub)doména, jako ji nastavila, ale nikoliv její subdomény. Pokud je `$domain` zadaný, jsou zahrnuty i subdomény. Proto je uvedení `$domain` méně omezující než vynechání. Například při `$domain = 'nette.org'` jsou cookies dostupné i na všech subdoménách jako `doc.nette.org`. -Pro hodnotu `$sameSite` můžete použít konstanty `Response::SameSiteLax`, `SameSiteStrict` a `SameSiteNone`. +Hodnotu `$sameSite` můžete předat jako enum `Nette\Http\SameSite` – `SameSite::Lax`, `SameSite::Strict` nebo `SameSite::None` (fungují i řetězce `'Lax'`, `'Strict'`, `'None'`). Pokud ji nastavíte na `SameSite::None`, automaticky se zapne atribut `$secure`, protože prohlížeče cookie se `SameSite=None` bez něj odmítají. + +.{data-version:3.4} +Partitioned cookies (CHIPS) dávají cookie samostatné úložiště pro každý web nejvyšší úrovně. Když tedy služba třetí strany (například vložený widget) nastaví partitioned cookie, prohlížeč pro každý web, na kterém se widget objeví, uchovává oddělenou kopii a tyto kopie nelze vzájemně propojit pro sledování napříč weby. Zapnete je nastavením `$partitioned` na `true`; to zároveň vyžaduje atribut `$secure`, takže se zapne automaticky. + +```php +$httpResponse->setCookie('theme', 'dark', '1 year', sameSite: SameSite::None, partitioned: true); +``` deleteCookie(string $name, ?string $path=null, ?string $domain=null, ?bool $secure=null): void .[method] diff --git a/http/cs/sessions.texy b/http/cs/sessions.texy index de10e7715f..c004573654 100644 --- a/http/cs/sessions.texy +++ b/http/cs/sessions.texy @@ -183,8 +183,8 @@ setExpiration(?string $time): static .[method] Nastaví dobu neaktivity po které session vyexpiruje. -setCookieParameters(string $path, ?string $domain=null, ?bool $secure=null, ?string $samesite=null): static .[method] ---------------------------------------------------------------------------------------------------------------------- +setCookieParameters(string $path, ?string $domain=null, ?bool $secure=null, SameSite|string|null $samesite=null): static .[method] +---------------------------------------------------------------------------------------------------------------------------------- Nastavení parametrů pro cookie. Výchozí hodnoty parametrů můžete změnit v [konfiguraci |configuration#Session cookie]. diff --git a/http/cs/ssrf.texy b/http/cs/ssrf.texy new file mode 100644 index 0000000000..375a90f662 --- /dev/null +++ b/http/cs/ssrf.texy @@ -0,0 +1,183 @@ +Ochrana proti SSRF +****************** + +.[perex] +Když vaše aplikace stahuje URL zadanou uživatelem, může toho útočník zneužít a dostat se do vaší interní sítě. Třídy [#UrlValidator] a [#IPAddress] vám pomohou bránit se těmto útokům Server-Side Request Forgery (SSRF). + +→ [Instalace a požadavky |@home#Instalace] + + +Co je SSRF? +=========== + +Představte si funkci, kde uživatel zadá URL a váš server ji stáhne – avatar ze vzdálené adresy, cíl webhooku, náhled odkazu. Vypadá to neškodně, ale na adresu se připojuje server, ne prohlížeč uživatele. A server vidí místa, kam útočník nedosáhne: loopback rozhraní, privátní síť, cloudové služby. + +Útočník proto pošle URL, která místo na veřejný internet míří dovnitř. Typickými cíli jsou: + +- cloudová metadata na `http://169.254.169.254/`, která mohou prozradit přístupové klíče +- interní administrace a routery jako `http://192.168.1.1/` +- služby bez autentizace, například Redis na `http://localhost:6379/` + +Tato třída zranitelností je tak rozšířená, že patří mezi [OWASP Top 10 |https://owasp.org/Top10/]. Obranou je ověřit URL **dříve**, než ji stáhnete, a odmítnout vše, co se přeloží na neveřejnou adresu. + + +UrlValidator +============ + +[api:Nette\Http\UrlValidator] ověřuje URL proti konfigurovatelné politice: schéma, port, host, userinfo a IP adresy, na které se host přeloží. Základní použití je jediné volání: + +```php +use Nette\Http\UrlValidator; + +if (!(new UrlValidator)->allows($userUrl)) { + return; // nebezpečná URL, nestahujte ji +} +``` + +Výchozí politika je záměrně přísná – akceptuje pouze `https` na portu 443 mířící na veřejnou IP adresu. Vše ostatní (loopback, privátní rozsahy, link-local včetně cloudových metadat, rezervované rozsahy) je odmítnuto a multicast je odmítnut bezpodmínečně. To je správný výchozí bod pro stahování libovolných URL zadaných uživatelem. + + +Konfigurace politiky +-------------------- + +Politiku tvarujete přes konstruktor. Například chcete-li povolit prosté `http` na libovolném portu a dosáhnout na privátní adresy (užitečné uvnitř důvěryhodné sítě): + +```php +$validator = new UrlValidator( + schemes: ['http', 'https'], + ports: null, // libovolný port + allowPrivateIps: true, +); +``` + +Častým vzorem je omezit stahování na pevnou sadu partnerských domén pomocí allowlistu hostů. Prefix `*.` odpovídá libovolné hloubce subdomény, ale ne samotné doméně – pokud ji potřebujete, uveďte oba tvary: + +```php +$validator = new UrlValidator( + hostAllowlist: ['example.com', '*.example.com'], +); +``` + +Kompletní sada možností konstruktoru: + +| Parametr | Výchozí | Význam +|--------------------- +| `schemes` | `['https']` | povolená schémata; `[]` odmítne vše +| `ports` | `[443]` | povolené porty, `null` = libovolný; implicitní port ze schématu je respektován +| `allowPrivateIps` | `false` | povolit privátní rozsahy (10/8, 172.16/12, 192.168/16, fc00::/7) +| `allowLoopback` | `false` | povolit loopback (127.0.0.0/8, ::1) +| `allowLinkLocal` | `false` | povolit link-local vč. cloudových metadat 169.254.169.254 +| `allowReserved` | `false` | povolit rozsahy rezervované IANA +| `allowUserinfo` | `false` | povolit `user:pass@` v URL +| `hostAllowlist` | `null` | pokud je nastaven, host musí odpovídat jednomu vzoru; `[]` odmítne vše +| `hostBlocklist` | `null` | pokud je nastaven, host nesmí odpovídat žádnému vzoru + + +Metody validace +-------------- + +Validátor nabízí tři metody. `allows()` provede plnou kontrolu včetně překladu DNS – host se přeloží a **každá** A/AAAA adresa musí projít IP politikou: + +```php +(new UrlValidator)->allows($url); // bool +``` + +`allowsWithoutDns()` přeskakuje překlad DNS a kontroly IP rozsahů. Použijte ji jako rychlý předfiltr, nebo když je validace DNS delegována na stahovací vrstvu: + +```php +(new UrlValidator)->allowsWithoutDns($url); // bool +``` + +Obě metody přijímají řetězec, objekt [UrlImmutable |urls#UrlImmutable] nebo `null` (které vždy selže). + + +Obrana proti DNS rebindingu +-------------------------- + +Mezi validací a stažením je záludný souboj: útočník může při ověřování hostu vrátit bezpečnou IP a poté pro samotné stažení přepnout DNS na interní IP. K uzavření této díry vrací `getResolvedIPs()` ověřené IP adresy a vy na ně připnete spojení, aby stahování nešlo přesměrovat jinam: + +```php +$ips = (new UrlValidator)->getResolvedIPs($url); +if (!$ips) { + return; // nebezpečná URL +} + +$ch = curl_init($url); +$host = parse_url($url, PHP_URL_HOST); +curl_setopt($ch, CURLOPT_RESOLVE, ["$host:443:" . implode(',', $ips)]); +// ... proveďte požadavek +``` + +Metoda vrací pole IP řetězců (nejprve A záznamy, poté AAAA), které prošly celou politikou, nebo prázdné pole při jakémkoli selhání. Pro IP literál v URL ověří adresu přímo a žádný překlad DNS neprovádí. + + +IPAddress +========= + +[api:Nette\Http\IPAddress] je neměnný hodnotový objekt pro práci s IPv4 a IPv6 adresami. `UrlValidator` jej využívá interně, ale hodí se i samostatně, kdykoli adresy klasifikujete. Konstruktor vyhodí `Nette\InvalidArgumentException` u neplatné adresy: + +```php +use Nette\Http\IPAddress; + +$ip = new IPAddress('169.254.169.254'); +echo $ip; // '169.254.169.254' +``` + +Když nechcete výjimku, použijte tovární metodu `tryFrom()` nebo kontrolu `isValid()`: + +```php +$ip = IPAddress::tryFrom($input); // ?IPAddress +IPAddress::isValid($input); // bool +``` + + +Klasifikace adres +---------------- + +Predikáty říkají, do jaké třídy adresa patří. Klíčový je `isPublic()` – pravdivý jen pro veřejně směrovatelné adresy, což je přesně to, co obrana proti SSRF potřebuje: + +```php +$ip = new IPAddress('169.254.169.254'); +$ip->isPublic(); // false +$ip->isLinkLocal(); // true (rozsah cloudových metadat) +``` + +Kompletní sada predikátů: + +| Metoda | Testuje +|-------------------- +| `isPublic()` | veřejně směrovatelná (žádná z níže uvedených) +| `isPrivate()` | privátní rozsahy RFC 1918 / 4193 +| `isLoopback()` | 127.0.0.0/8, ::1 +| `isLinkLocal()` | 169.254.0.0/16 (vč. cloudových metadat), fe80::/10 +| `isMulticast()` | 224.0.0.0/4, ff00::/8 +| `isReserved()` | rezervováno IANA (dokumentace, CGNAT, budoucí použití, …) + + +Příslušnost k rozsahu +-------------------- + +`isInRange()` testuje, zda adresa spadá do CIDR bloku. Můžete předat síť s prefixem, nebo holou adresu pro přesnou shodu (implicitní /32 pro IPv4, /128 pro IPv6): + +```php +$ip = new IPAddress('192.168.1.50'); +$ip->isInRange('192.168.0.0/16'); // true +$ip->isInRange('10.0.0.1'); // false (přesná shoda) +``` + +Chybný vstup nebo jiná rodina IP vrací `false`. + + +IPv4-mapped IPv6 +---------------- + +Adresy zapsané jako IPv4-mapped IPv6 (například `::ffff:127.0.0.1`) jsou klasickým způsobem, jak proklouznout naivními filtry. `IPAddress` je normalizuje, takže predikáty rozsahů prohlédnou přestrojení: + +```php +$ip = new IPAddress('::ffff:127.0.0.1'); +$ip->isLoopback(); // true +$ip->isIPv4Mapped(); // true +$ip->toIPv4(); // IPAddress('127.0.0.1') +``` + +Metody `isIPv4()` a `isIPv6()` hlásí textový tvar: mapovaná adresa je IPv6, nikoli IPv4. diff --git a/http/en/@left-menu.texy b/http/en/@left-menu.texy index 652706062b..35f6b7d090 100644 --- a/http/en/@left-menu.texy +++ b/http/en/@left-menu.texy @@ -5,4 +5,5 @@ Nette HTTP - [HTTP Response |response] - [Sessions] - [URL Utility |urls] +- [SSRF Protection |ssrf] - [Configuration] diff --git a/http/en/request.texy b/http/en/request.texy index 2290ad59b9..d4651cf284 100644 --- a/http/en/request.texy +++ b/http/en/request.texy @@ -146,9 +146,41 @@ isSecured(): bool .[method] Is the connection encrypted (HTTPS)? Proper functionality might require [setting up a proxy |configuration#HTTP Proxy]. -isSameSite(): bool .[method] ----------------------------- -Is the request coming from the same (sub)domain and initiated by clicking a link? Nette uses the `_nss` cookie (formerly `nette-samesite`) for detection. +isSameSite(): bool .[method deprecated] +--------------------------------------- +Did the request come from the same site? Since version 3.4 it is replaced by the more capable [isFrom() |#isFrom]. + + +isFrom(FetchSite|array $site, FetchDest|array|null $dest=null, ?bool $user=null): bool .[method]{data-version:3.4} +------------------------------------------------------------------------------------------------------------------ +Tells you where the request came from and how the browser made it, based on the `Sec-Fetch-*` headers (so-called [Fetch Metadata |https://developer.mozilla.org/en-US/docs/Glossary/Fetch_metadata_request_header]) that the browser sets itself and a page running in the victim's browser can neither forge nor remove. Nette uses it internally to automatically protect forms and signals against [Cross-Site Request Forgery |nette:glossary#Cross-Site Request Forgery CSRF] (CSRF). It is useful when you want to guard your own sensitive actions, such as API endpoints or destructive links. + +The method returns `true` only when the request matches **all** the conditions you provide. The first parameter `$site` describes the relationship between the page that initiated the request and your site (the `Sec-Fetch-Site` header). It accepts a single value or a list of these `FetchSite` cases: + +- `FetchSite::SameOrigin` – from the exact same origin (scheme, host, and port) +- `FetchSite::SameSite` – from the same site, possibly a different subdomain +- `FetchSite::CrossSite` – from a foreign site +- `FetchSite::None` – the user initiated it directly, e.g. by typing the URL or opening a bookmark + +```php +// did the request originate from our own pages? +if (!$httpRequest->isFrom([FetchSite::SameOrigin, FetchSite::SameSite])) { + // block the action +} +``` + +The optional `$dest` parameter (the `Sec-Fetch-Dest` header) says what kind of resource the browser is fetching, e.g. `FetchDest::Document` for a top-level navigation or `FetchDest::Empty` for a request made from JavaScript. The optional `$user` parameter (the `Sec-Fetch-User` header) indicates whether the navigation was triggered by a genuine user action such as clicking a link or submitting a form; pass `true` to require it. + +A check that an action is reachable only from your own pages and only through a real user action then looks like this: + +```php +if (!$httpRequest->isFrom(FetchSite::SameOrigin, FetchDest::Document, user: true)) { + $this->error(); +} +``` + +.[note] +Older browsers (Safari before 16.4) do not send the `Sec-Fetch-*` headers. For them Nette falls back to a `SameSite=Strict` cookie that only proves the request is not cross-site. A check that additionally requires `$dest` or `$user` cannot be verified this way and returns `false` in those browsers – if that is too strict, test only `$site`. isAjax(): bool .[method] diff --git a/http/en/response.texy b/http/en/response.texy index 7dbd4dca00..eeffb70588 100644 --- a/http/en/response.texy +++ b/http/en/response.texy @@ -115,15 +115,16 @@ $httpResponse->sendAsFile('invoice.pdf'); ``` -setCookie(string $name, string $value, $time, ?string $path=null, ?string $domain=null, ?bool $secure=null, ?bool $httpOnly=null, ?string $sameSite='Lax') .[method] --------------------------------------------------------------------------------------------------------------------------------------------------------------------- +setCookie(string $name, string $value, $time, ?string $path=null, ?string $domain=null, ?bool $secure=null, ?bool $httpOnly=null, SameSite|string $sameSite='Lax', bool $partitioned=false) .[method] +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Sends a cookie. Default parameter values: -| `$path` | `'/'` | cookie is available for all paths within the (sub)domain *(configurable)* -| `$domain` | `null` | meaning available for the current (sub)domain, but not its subdomains *(configurable)* -| `$secure` | `true` | if the site is running on HTTPS, otherwise `false` *(configurable)* -| `$httpOnly` | `true` | cookie is inaccessible to JavaScript -| `$sameSite` | `'Lax'` | cookie might not be sent during [cross-origin access |nette:glossary#SameSite cookie] +| `$path` | `'/'` | cookie is available for all paths within the (sub)domain *(configurable)* +| `$domain` | `null` | meaning available for the current (sub)domain, but not its subdomains *(configurable)* +| `$secure` | `true` | if the site is running on HTTPS, otherwise `false` *(configurable)* +| `$httpOnly` | `true` | cookie is inaccessible to JavaScript +| `$sameSite` | `'Lax'` | cookie might not be sent during [cross-origin access |nette:glossary#SameSite cookie] +| `$partitioned` | `false` | whether the cookie is partitioned, see below *(since v3.4)* You can change the default values of the `$path`, `$domain`, and `$secure` parameters in the [configuration |configuration#HTTP Cookie]. @@ -135,7 +136,14 @@ $httpResponse->setCookie('lang', 'en', '100 days'); The `$domain` parameter determines which domains can accept the cookie. If not specified, the cookie is accepted by the same (sub)domain that set it, but not its subdomains. If `$domain` is specified, subdomains are also included. Therefore, specifying `$domain` is less restrictive than omitting it. For example, with `$domain = 'nette.org'`, cookies are also available on all subdomains like `doc.nette.org`. -You can use the constants `Response::SameSiteLax`, `Response::SameSiteStrict`, and `Response::SameSiteNone` for the `$sameSite` value. +You can pass the `$sameSite` value as a `Nette\Http\SameSite` enum – `SameSite::Lax`, `SameSite::Strict`, or `SameSite::None` (the string values `'Lax'`, `'Strict'`, `'None'` work too). If you set it to `SameSite::None`, the `$secure` attribute is enabled automatically, because browsers reject a `SameSite=None` cookie that is not secure. + +.{data-version:3.4} +Partitioned cookies (CHIPS) give a cookie its own separate storage for each top-level site. So when a third-party service (such as an embedded widget) sets a partitioned cookie, the browser keeps a distinct copy for every site the widget appears on, and these copies cannot be linked together for cross-site tracking. Turn it on by setting `$partitioned` to `true`; this also requires the `$secure` attribute, so it is enabled automatically. + +```php +$httpResponse->setCookie('theme', 'dark', '1 year', sameSite: SameSite::None, partitioned: true); +``` deleteCookie(string $name, ?string $path=null, ?string $domain=null, ?bool $secure=null): void .[method] diff --git a/http/en/sessions.texy b/http/en/sessions.texy index f0831458d5..41d00779ae 100644 --- a/http/en/sessions.texy +++ b/http/en/sessions.texy @@ -183,8 +183,8 @@ setExpiration(?string $time): static .[method] Sets the inactivity time after which the session expires. -setCookieParameters(string $path, ?string $domain=null, ?bool $secure=null, ?string $samesite=null): static .[method] ---------------------------------------------------------------------------------------------------------------------- +setCookieParameters(string $path, ?string $domain=null, ?bool $secure=null, SameSite|string|null $samesite=null): static .[method] +---------------------------------------------------------------------------------------------------------------------------------- Sets parameters for cookies. You can change the default parameter values in the [configuration |configuration#Session Cookie]. diff --git a/http/en/ssrf.texy b/http/en/ssrf.texy new file mode 100644 index 0000000000..72d7251719 --- /dev/null +++ b/http/en/ssrf.texy @@ -0,0 +1,183 @@ +SSRF Protection +*************** + +.[perex] +When your application downloads a URL supplied by a user, an attacker can abuse it to reach your internal network. The [#UrlValidator] and [#IPAddress] classes help you guard against these Server-Side Request Forgery (SSRF) attacks. + +→ [Installation and requirements |@home#Installation] + + +What is SSRF? +============= + +Imagine a feature where the user enters a URL and your server downloads it – an avatar from a remote address, a webhook target, a link preview. It looks harmless, but the server reaches the address, not the user's browser. And the server can see places the attacker can't: the loopback interface, the private network, cloud services. + +An attacker therefore submits a URL that points inward instead of to the public internet. Typical targets are: + +- cloud metadata at `http://169.254.169.254/`, which can leak access keys +- internal admin panels and routers like `http://192.168.1.1/` +- services with no authentication, such as Redis on `http://localhost:6379/` + +This class of vulnerability is so common it ranks among the [OWASP Top 10 |https://owasp.org/Top10/]. The defense is to validate the URL **before** you fetch it and to refuse anything that resolves to a non-public address. + + +UrlValidator +============ + +[api:Nette\Http\UrlValidator] checks a URL against a configurable policy: the scheme, port, host, userinfo, and the IP addresses the host resolves to. The basic usage is a single call: + +```php +use Nette\Http\UrlValidator; + +if (!(new UrlValidator)->allows($userUrl)) { + return; // unsafe URL, do not fetch it +} +``` + +The default policy is deliberately strict – it only accepts `https` on port 443 pointing to a public IP address. Everything else (loopback, private ranges, link-local including cloud metadata, reserved ranges) is rejected, and multicast is rejected unconditionally. This is the right starting point for fetching arbitrary user-supplied URLs. + + +Configuring the Policy +---------------------- + +You shape the policy through the constructor. For example, to allow plain `http` on any port and reach private addresses (useful inside a trusted network): + +```php +$validator = new UrlValidator( + schemes: ['http', 'https'], + ports: null, // any port + allowPrivateIps: true, +); +``` + +A common pattern is to restrict fetching to a fixed set of partner domains using a host allowlist. The `*.` prefix matches any subdomain depth but not the apex – list both forms if you need it: + +```php +$validator = new UrlValidator( + hostAllowlist: ['example.com', '*.example.com'], +); +``` + +The full set of constructor options: + +| Parameter | Default | Meaning +|--------------------- +| `schemes` | `['https']` | allowed schemes; `[]` rejects everything +| `ports` | `[443]` | allowed ports, `null` = any; the implicit port from the scheme is honored +| `allowPrivateIps` | `false` | allow private ranges (10/8, 172.16/12, 192.168/16, fc00::/7) +| `allowLoopback` | `false` | allow loopback (127.0.0.0/8, ::1) +| `allowLinkLocal` | `false` | allow link-local incl. cloud metadata 169.254.169.254 +| `allowReserved` | `false` | allow IANA-reserved ranges +| `allowUserinfo` | `false` | allow `user:pass@` in the URL +| `hostAllowlist` | `null` | if set, host must match one pattern; `[]` rejects all +| `hostBlocklist` | `null` | if set, host must not match any pattern + + +Validation Methods +------------------ + +The validator offers three methods. `allows()` runs the full check including DNS resolution – the host is resolved and **every** A/AAAA address must pass the IP policy: + +```php +(new UrlValidator)->allows($url); // bool +``` + +`allowsWithoutDns()` skips DNS resolution and the IP-range checks. Use it as a fast pre-filter, or when DNS validation is delegated to the fetch layer: + +```php +(new UrlValidator)->allowsWithoutDns($url); // bool +``` + +Both methods accept a string, a [UrlImmutable |urls#UrlImmutable] object, or `null` (which always fails). + + +Defeating DNS Rebinding +----------------------- + +There is a subtle race between validation and fetching: an attacker can return a safe IP when you validate the host, then switch DNS to an internal IP for the actual download. To close this hole, `getResolvedIPs()` returns the validated IP addresses, and you pin the connection to them so the fetch can't be redirected elsewhere: + +```php +$ips = (new UrlValidator)->getResolvedIPs($url); +if (!$ips) { + return; // unsafe URL +} + +$ch = curl_init($url); +$host = parse_url($url, PHP_URL_HOST); +curl_setopt($ch, CURLOPT_RESOLVE, ["$host:443:" . implode(',', $ips)]); +// ... execute the request +``` + +The method returns an array of IP strings (A records first, then AAAA) that passed the full policy, or an empty array on any failure. For an IP literal in the URL it validates the address directly and performs no DNS lookup. + + +IPAddress +========= + +[api:Nette\Http\IPAddress] is an immutable value object for working with IPv4 and IPv6 addresses. `UrlValidator` uses it internally, but it's handy on its own whenever you classify addresses. The constructor throws `Nette\InvalidArgumentException` for an invalid address: + +```php +use Nette\Http\IPAddress; + +$ip = new IPAddress('169.254.169.254'); +echo $ip; // '169.254.169.254' +``` + +When you don't want an exception, use the `tryFrom()` factory or the `isValid()` checker: + +```php +$ip = IPAddress::tryFrom($input); // ?IPAddress +IPAddress::isValid($input); // bool +``` + + +Address Classification +---------------------- + +The predicates tell you which class an address belongs to. The key one is `isPublic()` – true only for publicly routable addresses, which is exactly what an SSRF guard wants: + +```php +$ip = new IPAddress('169.254.169.254'); +$ip->isPublic(); // false +$ip->isLinkLocal(); // true (cloud metadata range) +``` + +The full set of predicates: + +| Method | Tests for +|-------------------- +| `isPublic()` | publicly routable (none of the below) +| `isPrivate()` | RFC 1918 / 4193 private ranges +| `isLoopback()` | 127.0.0.0/8, ::1 +| `isLinkLocal()` | 169.254.0.0/16 (incl. cloud metadata), fe80::/10 +| `isMulticast()` | 224.0.0.0/4, ff00::/8 +| `isReserved()` | IANA-reserved (documentation, CGNAT, future-use, …) + + +Range Membership +---------------- + +`isInRange()` tests whether the address falls within a CIDR block. You can pass a network with a prefix, or a bare address for an exact match (implicit /32 for IPv4, /128 for IPv6): + +```php +$ip = new IPAddress('192.168.1.50'); +$ip->isInRange('192.168.0.0/16'); // true +$ip->isInRange('10.0.0.1'); // false (exact match) +``` + +Malformed input or a different IP family returns `false`. + + +IPv4-mapped IPv6 +---------------- + +Addresses written as IPv4-mapped IPv6 (such as `::ffff:127.0.0.1`) are a classic way to slip past naive filters. `IPAddress` normalizes them, so the range predicates see through the disguise: + +```php +$ip = new IPAddress('::ffff:127.0.0.1'); +$ip->isLoopback(); // true +$ip->isIPv4Mapped(); // true +$ip->toIPv4(); // IPAddress('127.0.0.1') +``` + +The `isIPv4()` and `isIPv6()` methods report the textual form: a mapped address is IPv6, not IPv4. From 87507fc92fd28e20bf6db891ad60c5cb70121450 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Sun, 14 Jun 2026 18:43:47 +0200 Subject: [PATCH 48/50] improved homepages --- http/cs/@home.texy | 9 ++++++++- http/cs/@left-menu.texy | 2 +- http/en/@home.texy | 9 ++++++++- security/cs/@home.texy | 7 ++++++- security/en/@home.texy | 7 ++++++- 5 files changed, 29 insertions(+), 5 deletions(-) diff --git a/http/cs/@home.texy b/http/cs/@home.texy index 47814c400d..8442d4fdbb 100644 --- a/http/cs/@home.texy +++ b/http/cs/@home.texy @@ -2,7 +2,14 @@ Nette HTTP ********** .[perex] -Balíček `nette/http` zapouzdřuje [HTTP request|request] & [response], práci se [sessions] a [parsování a skládání URL |urls]. +Balíček `nette/http` je vaším pomocníkem pro veškerou komunikaci přes HTTP. Poskytuje srozumitelné objektové API nad příchozím požadavkem a odchozí odpovědí, usnadňuje práci se sessions i s URL adresami a navíc se postará o bezpečnost. Co v něm najdete: + +| [HTTP request |request] | příchozí požadavek a sanitizace vstupů +| [HTTP response |response] | odchozí odpověď, hlavičky a cookies +| [Sessions] | bezpečné uchování stavu mezi požadavky +| [Práce s URL |urls] | parsování a skládání URL adres +| [Ochrana proti SSRF |ssrf] | obrana proti útokům Server-Side Request Forgery +| [Konfigurace |configuration] | konfigurační volby balíčku Instalace diff --git a/http/cs/@left-menu.texy b/http/cs/@left-menu.texy index d49c625ad1..59dfcdcb47 100644 --- a/http/cs/@left-menu.texy +++ b/http/cs/@left-menu.texy @@ -4,6 +4,6 @@ Nette HTTP - [HTTP request|request] - [HTTP response|response] - [Sessions] -- [URL utilities |urls] +- [Práce s URL |urls] - [Ochrana proti SSRF |ssrf] - [Konfigurace |configuration] diff --git a/http/en/@home.texy b/http/en/@home.texy index 9ae502ba2d..474b16672b 100644 --- a/http/en/@home.texy +++ b/http/en/@home.texy @@ -2,7 +2,14 @@ Nette HTTP ********** .[perex] -The `nette/http` package encapsulates [HTTP request|request] & [response], working with [sessions] and [URL parsing and building |urls]. +The `nette/http` package is your companion for all HTTP communication. It provides a clear object-oriented API over the incoming request and outgoing response, simplifies working with sessions and URL addresses, and takes care of security on top of that. Here's what you'll find: + +| [HTTP Request |request] | incoming request and input sanitization +| [HTTP Response |response] | outgoing response, headers and cookies +| [Sessions] | secure state persistence between requests +| [URL Utility |urls] | parsing and building URL addresses +| [SSRF Protection |ssrf] | defense against Server-Side Request Forgery attacks +| [Configuration] | configuration options of the package Installation diff --git a/security/cs/@home.texy b/security/cs/@home.texy index 266334da18..2c28b8d488 100644 --- a/security/cs/@home.texy +++ b/security/cs/@home.texy @@ -2,7 +2,12 @@ Nette Security ************** .[perex] -Balíček `nette/security` má na starostí [přihlašování uživatelů |authentication], [ověřování oprávnění |authorization] a [hashování hesel |passwords]. +Balíček `nette/security` se postará o bezpečnost vaší aplikace tam, kde na ní záleží nejvíc: u uživatelských účtů. Vyřeší za vás přihlašování uživatelů, ověřování jejich oprávnění i bezpečné ukládání hesel. Co v něm najdete: + +| [Autentizace |authentication] | přihlašování uživatelů a správa identity +| [Autorizace |authorization] | ověřování oprávnění a řízení přístupu +| [Hashování hesel |passwords] | bezpečné ukládání hesel pomocí otisků +| [Konfigurace |configuration] | konfigurační volby balíčku Instalace diff --git a/security/en/@home.texy b/security/en/@home.texy index e1da9f34a4..f306d9dd2d 100644 --- a/security/en/@home.texy +++ b/security/en/@home.texy @@ -2,7 +2,12 @@ Nette Security ************** .[perex] -The `nette/security` package handles [authenticating users |authentication], [access control |authorization], and [password hashing |passwords]. +The `nette/security` package takes care of your application's security where it matters most: user accounts. It handles logging users in, verifying their permissions, and storing passwords safely. Here's what you'll find: + +| [Authentication |authentication] | logging users in and managing identity +| [Authorization |authorization] | verifying permissions and access control +| [Password Hashing |passwords] | storing passwords securely as hashes +| [Configuration] | configuration options of the package Installation From ac8e22cb101af95b17d005ae39cb8b4a0bfb9879 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Sat, 6 Jun 2026 19:21:40 +0200 Subject: [PATCH 49/50] WIP --- tools/bg/@home.texy | 4 ++-- tools/cs/@home.texy | 4 ++-- tools/de/@home.texy | 4 ++-- tools/el/@home.texy | 4 ++-- tools/en/@home.texy | 4 ++-- tools/es/@home.texy | 4 ++-- tools/fr/@home.texy | 4 ++-- tools/hu/@home.texy | 4 ++-- tools/it/@home.texy | 4 ++-- tools/ja/@home.texy | 4 ++-- tools/pl/@home.texy | 4 ++-- tools/pt/@home.texy | 4 ++-- tools/ro/@home.texy | 4 ++-- tools/ru/@home.texy | 4 ++-- tools/sl/@home.texy | 4 ++-- tools/tr/@home.texy | 4 ++-- tools/uk/@home.texy | 4 ++-- 17 files changed, 34 insertions(+), 34 deletions(-) diff --git a/tools/bg/@home.texy b/tools/bg/@home.texy index a6991f3dff..e714bd19fe 100644 --- a/tools/bg/@home.texy +++ b/tools/bg/@home.texy @@ -21,8 +21,8 @@ Изкуствен интелект ------------------ -- [Claude Code plugin |ai:en:claude-code] учи Claude Code на конвенциите на Nette: умения, автоматична валидация на Latte/NEON/JS и MCP интеграция. -- [MCP Inspector |ai:en:mcp-inspector] дава на AI реалното състояние на вашето приложение: DI услуги, схема на базата данни, маршрути и Tracy логове. +- [Claude Code plugin |https://ai.nette.org/en/claude-code] учи Claude Code на конвенциите на Nette: умения, автоматична валидация на Latte/NEON/JS и MCP интеграция. +- [MCP Inspector |https://ai.nette.org/en/mcp-inspector] дава на AI реалното състояние на вашето приложение: DI услуги, схема на базата данни, маршрути и Tracy логове. Frontend diff --git a/tools/cs/@home.texy b/tools/cs/@home.texy index 3e4cf8ed20..d3a70abf91 100644 --- a/tools/cs/@home.texy +++ b/tools/cs/@home.texy @@ -21,8 +21,8 @@ Kvalita kódu Umělá inteligence ----------------- -- [Claude Code plugin |ai:en:claude-code] naučí Claude Code konvence Nette: skills, automatická validace Latte/NEON/JS a integrace MCP. -- [MCP Inspector |ai:en:mcp-inspector] zpřístupní AI reálný stav aplikace: DI služby, schéma databáze, routy i Tracy logy. +- [Claude Code plugin |https://ai.nette.org/en/claude-code] naučí Claude Code konvence Nette: skills, automatická validace Latte/NEON/JS a integrace MCP. +- [MCP Inspector |https://ai.nette.org/en/mcp-inspector] zpřístupní AI reálný stav aplikace: DI služby, schéma databáze, routy i Tracy logy. Frontend diff --git a/tools/de/@home.texy b/tools/de/@home.texy index 53435c3dd4..4a12797deb 100644 --- a/tools/de/@home.texy +++ b/tools/de/@home.texy @@ -21,8 +21,8 @@ Code-Qualität Künstliche Intelligenz ---------------------- -- [Claude Code plugin |ai:en:claude-code] bringt Claude Code die Nette-Konventionen bei: Skills, automatische Validierung von Latte/NEON/JS und MCP-Integration. -- [MCP Inspector |ai:en:mcp-inspector] gibt der KI den realen Zustand Ihrer Anwendung: DI-Dienste, Datenbankschema, Routen und Tracy-Logs. +- [Claude Code plugin |https://ai.nette.org/en/claude-code] bringt Claude Code die Nette-Konventionen bei: Skills, automatische Validierung von Latte/NEON/JS und MCP-Integration. +- [MCP Inspector |https://ai.nette.org/en/mcp-inspector] gibt der KI den realen Zustand Ihrer Anwendung: DI-Dienste, Datenbankschema, Routen und Tracy-Logs. Frontend diff --git a/tools/el/@home.texy b/tools/el/@home.texy index ca46179083..7ec4e25113 100644 --- a/tools/el/@home.texy +++ b/tools/el/@home.texy @@ -21,8 +21,8 @@ Τεχνητή νοημοσύνη ----------------- -- [Claude Code plugin |ai:en:claude-code] διδάσκει στο Claude Code τις συμβάσεις του Nette: δεξιότητες, αυτόματη επικύρωση Latte/NEON/JS και ενσωμάτωση MCP. -- [MCP Inspector |ai:en:mcp-inspector] δίνει στην AI την πραγματική κατάσταση της εφαρμογής σας: υπηρεσίες DI, σχήμα βάσης δεδομένων, routes και logs του Tracy. +- [Claude Code plugin |https://ai.nette.org/en/claude-code] διδάσκει στο Claude Code τις συμβάσεις του Nette: δεξιότητες, αυτόματη επικύρωση Latte/NEON/JS και ενσωμάτωση MCP. +- [MCP Inspector |https://ai.nette.org/en/mcp-inspector] δίνει στην AI την πραγματική κατάσταση της εφαρμογής σας: υπηρεσίες DI, σχήμα βάσης δεδομένων, routes και logs του Tracy. Frontend diff --git a/tools/en/@home.texy b/tools/en/@home.texy index d9dbbdbac9..a329c9bd9d 100644 --- a/tools/en/@home.texy +++ b/tools/en/@home.texy @@ -21,8 +21,8 @@ Code Quality Artificial Intelligence ----------------------- -- [Claude Code plugin |ai:en:claude-code] teaches Claude Code the Nette conventions: skills, automatic validation of Latte/NEON/JS, and MCP integration. -- [MCP Inspector |ai:en:mcp-inspector] gives AI the real state of your application: DI services, database schema, routes and Tracy logs. +- [Claude Code plugin |https://ai.nette.org/en/claude-code] teaches Claude Code the Nette conventions: skills, automatic validation of Latte/NEON/JS, and MCP integration. +- [MCP Inspector |https://ai.nette.org/en/mcp-inspector] gives AI the real state of your application: DI services, database schema, routes and Tracy logs. Frontend diff --git a/tools/es/@home.texy b/tools/es/@home.texy index 0cfec58c68..0fc13e1417 100644 --- a/tools/es/@home.texy +++ b/tools/es/@home.texy @@ -21,8 +21,8 @@ Calidad del código Inteligencia artificial ----------------------- -- [Claude Code plugin |ai:en:claude-code] enseña a Claude Code las convenciones de Nette: skills, validación automática de Latte/NEON/JS e integración con MCP. -- [MCP Inspector |ai:en:mcp-inspector] da a la IA el estado real de su aplicación: servicios de DI, esquema de la base de datos, rutas y registros de Tracy. +- [Claude Code plugin |https://ai.nette.org/en/claude-code] enseña a Claude Code las convenciones de Nette: skills, validación automática de Latte/NEON/JS e integración con MCP. +- [MCP Inspector |https://ai.nette.org/en/mcp-inspector] da a la IA el estado real de su aplicación: servicios de DI, esquema de la base de datos, rutas y registros de Tracy. Frontend diff --git a/tools/fr/@home.texy b/tools/fr/@home.texy index a1fa46d801..5c20438987 100644 --- a/tools/fr/@home.texy +++ b/tools/fr/@home.texy @@ -21,8 +21,8 @@ Qualité du code Intelligence artificielle ------------------------- -- [Claude Code plugin |ai:en:claude-code] enseigne à Claude Code les conventions de Nette : skills, validation automatique de Latte/NEON/JS et intégration MCP. -- [MCP Inspector |ai:en:mcp-inspector] donne à l'IA l'état réel de votre application : services DI, schéma de base de données, routes et logs Tracy. +- [Claude Code plugin |https://ai.nette.org/en/claude-code] enseigne à Claude Code les conventions de Nette : skills, validation automatique de Latte/NEON/JS et intégration MCP. +- [MCP Inspector |https://ai.nette.org/en/mcp-inspector] donne à l'IA l'état réel de votre application : services DI, schéma de base de données, routes et logs Tracy. Frontend diff --git a/tools/hu/@home.texy b/tools/hu/@home.texy index 5ef44ab685..9764352c6e 100644 --- a/tools/hu/@home.texy +++ b/tools/hu/@home.texy @@ -21,8 +21,8 @@ Kódminőség Mesterséges intelligencia ------------------------- -- [Claude Code plugin |ai:en:claude-code] megtanítja a Claude Code-nak a Nette konvencióit: skillek, a Latte/NEON/JS automatikus validálása és MCP integráció. -- [MCP Inspector |ai:en:mcp-inspector] megadja az AI-nak az alkalmazásod valós állapotát: DI szolgáltatások, adatbázis-séma, route-ok és Tracy naplók. +- [Claude Code plugin |https://ai.nette.org/en/claude-code] megtanítja a Claude Code-nak a Nette konvencióit: skillek, a Latte/NEON/JS automatikus validálása és MCP integráció. +- [MCP Inspector |https://ai.nette.org/en/mcp-inspector] megadja az AI-nak az alkalmazásod valós állapotát: DI szolgáltatások, adatbázis-séma, route-ok és Tracy naplók. Frontend diff --git a/tools/it/@home.texy b/tools/it/@home.texy index 949dc3a3d9..0b752d91c7 100644 --- a/tools/it/@home.texy +++ b/tools/it/@home.texy @@ -21,8 +21,8 @@ Qualità del codice Intelligenza artificiale ------------------------ -- [Claude Code plugin |ai:en:claude-code] insegna a Claude Code le convenzioni di Nette: skill, validazione automatica di Latte/NEON/JS e integrazione MCP. -- [MCP Inspector |ai:en:mcp-inspector] fornisce all'AI lo stato reale della tua applicazione: servizi DI, schema del database, route e log di Tracy. +- [Claude Code plugin |https://ai.nette.org/en/claude-code] insegna a Claude Code le convenzioni di Nette: skill, validazione automatica di Latte/NEON/JS e integrazione MCP. +- [MCP Inspector |https://ai.nette.org/en/mcp-inspector] fornisce all'AI lo stato reale della tua applicazione: servizi DI, schema del database, route e log di Tracy. Frontend diff --git a/tools/ja/@home.texy b/tools/ja/@home.texy index e9e7a9ddf5..1ac1700bc5 100644 --- a/tools/ja/@home.texy +++ b/tools/ja/@home.texy @@ -21,8 +21,8 @@ Nette での開発を容易にする補助ツール。 人工知能 ---- -- [Claude Code plugin |ai:en:claude-code] は、Claude Code に Nette の規約を教えます:スキル、Latte/NEON/JS の自動検証、MCP 連携。 -- [MCP Inspector |ai:en:mcp-inspector] は、AI にアプリケーションの実際の状態を伝えます:DI サービス、データベーススキーマ、ルート、Tracy のログ。 +- [Claude Code plugin |https://ai.nette.org/en/claude-code] は、Claude Code に Nette の規約を教えます:スキル、Latte/NEON/JS の自動検証、MCP 連携。 +- [MCP Inspector |https://ai.nette.org/en/mcp-inspector] は、AI にアプリケーションの実際の状態を伝えます:DI サービス、データベーススキーマ、ルート、Tracy のログ。 フロントエンド diff --git a/tools/pl/@home.texy b/tools/pl/@home.texy index 13e507ae8e..77964d0a70 100644 --- a/tools/pl/@home.texy +++ b/tools/pl/@home.texy @@ -21,8 +21,8 @@ Jakość kodu Sztuczna inteligencja --------------------- -- [Claude Code plugin |ai:en:claude-code] uczy Claude Code konwencji Nette: skille, automatyczna walidacja Latte/NEON/JS oraz integracja MCP. -- [MCP Inspector |ai:en:mcp-inspector] daje AI rzeczywisty stan Twojej aplikacji: usługi DI, schemat bazy danych, trasy i logi Tracy. +- [Claude Code plugin |https://ai.nette.org/en/claude-code] uczy Claude Code konwencji Nette: skille, automatyczna walidacja Latte/NEON/JS oraz integracja MCP. +- [MCP Inspector |https://ai.nette.org/en/mcp-inspector] daje AI rzeczywisty stan Twojej aplikacji: usługi DI, schemat bazy danych, trasy i logi Tracy. Frontend diff --git a/tools/pt/@home.texy b/tools/pt/@home.texy index a7816009a7..5729a012e1 100644 --- a/tools/pt/@home.texy +++ b/tools/pt/@home.texy @@ -21,8 +21,8 @@ Qualidade do Código Inteligência Artificial ----------------------- -- [Claude Code plugin |ai:en:claude-code] ensina ao Claude Code as convenções do Nette: skills, validação automática de Latte/NEON/JS e integração com MCP. -- [MCP Inspector |ai:en:mcp-inspector] dá à IA o estado real da sua aplicação: serviços DI, esquema do banco de dados, rotas e logs do Tracy. +- [Claude Code plugin |https://ai.nette.org/en/claude-code] ensina ao Claude Code as convenções do Nette: skills, validação automática de Latte/NEON/JS e integração com MCP. +- [MCP Inspector |https://ai.nette.org/en/mcp-inspector] dá à IA o estado real da sua aplicação: serviços DI, esquema do banco de dados, rotas e logs do Tracy. Frontend diff --git a/tools/ro/@home.texy b/tools/ro/@home.texy index abdeeb2ef3..29d1e6d495 100644 --- a/tools/ro/@home.texy +++ b/tools/ro/@home.texy @@ -21,8 +21,8 @@ Calitatea codului Inteligență artificială ----------------------- -- [Claude Code plugin |ai:en:claude-code] învață Claude Code convențiile Nette: skill-uri, validare automată a Latte/NEON/JS și integrare MCP. -- [MCP Inspector |ai:en:mcp-inspector] oferă AI-ului starea reală a aplicației tale: servicii DI, schema bazei de date, rute și loguri Tracy. +- [Claude Code plugin |https://ai.nette.org/en/claude-code] învață Claude Code convențiile Nette: skill-uri, validare automată a Latte/NEON/JS și integrare MCP. +- [MCP Inspector |https://ai.nette.org/en/mcp-inspector] oferă AI-ului starea reală a aplicației tale: servicii DI, schema bazei de date, rute și loguri Tracy. Frontend diff --git a/tools/ru/@home.texy b/tools/ru/@home.texy index 244b524eb9..3253a99943 100644 --- a/tools/ru/@home.texy +++ b/tools/ru/@home.texy @@ -21,8 +21,8 @@ Искусственный интеллект ----------------------- -- [Claude Code plugin |ai:en:claude-code] обучает Claude Code соглашениям Nette: навыки, автоматическую проверку Latte/NEON/JS и интеграцию с MCP. -- [MCP Inspector |ai:en:mcp-inspector] даёт ИИ реальное состояние вашего приложения: сервисы DI, схему базы данных, маршруты и логи Tracy. +- [Claude Code plugin |https://ai.nette.org/en/claude-code] обучает Claude Code соглашениям Nette: навыки, автоматическую проверку Latte/NEON/JS и интеграцию с MCP. +- [MCP Inspector |https://ai.nette.org/en/mcp-inspector] даёт ИИ реальное состояние вашего приложения: сервисы DI, схему базы данных, маршруты и логи Tracy. Frontend diff --git a/tools/sl/@home.texy b/tools/sl/@home.texy index e46fda3f22..8db987bee5 100644 --- a/tools/sl/@home.texy +++ b/tools/sl/@home.texy @@ -21,8 +21,8 @@ Kakovost kode Umetna inteligenca ------------------ -- [Claude Code plugin |ai:en:claude-code] nauči Claude Code konvencij Nette: spretnosti, samodejno validacijo Latte/NEON/JS in integracijo MCP. -- [MCP Inspector |ai:en:mcp-inspector] daje AI dejansko stanje vaše aplikacije: storitve DI, shemo baze podatkov, poti in dnevnike Tracy. +- [Claude Code plugin |https://ai.nette.org/en/claude-code] nauči Claude Code konvencij Nette: spretnosti, samodejno validacijo Latte/NEON/JS in integracijo MCP. +- [MCP Inspector |https://ai.nette.org/en/mcp-inspector] daje AI dejansko stanje vaše aplikacije: storitve DI, shemo baze podatkov, poti in dnevnike Tracy. Frontend diff --git a/tools/tr/@home.texy b/tools/tr/@home.texy index 936ad2890a..177ca4122b 100644 --- a/tools/tr/@home.texy +++ b/tools/tr/@home.texy @@ -21,8 +21,8 @@ Kod Kalitesi Yapay Zekâ ---------- -- [Claude Code plugin |ai:en:claude-code] Claude Code'a Nette kurallarını öğretir: beceriler, Latte/NEON/JS'in otomatik doğrulanması ve MCP entegrasyonu. -- [MCP Inspector |ai:en:mcp-inspector] yapay zekâya uygulamanızın gerçek durumunu verir: DI servisleri, veritabanı şeması, rotalar ve Tracy günlükleri. +- [Claude Code plugin |https://ai.nette.org/en/claude-code] Claude Code'a Nette kurallarını öğretir: beceriler, Latte/NEON/JS'in otomatik doğrulanması ve MCP entegrasyonu. +- [MCP Inspector |https://ai.nette.org/en/mcp-inspector] yapay zekâya uygulamanızın gerçek durumunu verir: DI servisleri, veritabanı şeması, rotalar ve Tracy günlükleri. Frontend diff --git a/tools/uk/@home.texy b/tools/uk/@home.texy index 6c544559eb..9023fc386f 100644 --- a/tools/uk/@home.texy +++ b/tools/uk/@home.texy @@ -21,8 +21,8 @@ Штучний інтелект ---------------- -- [Claude Code plugin |ai:en:claude-code] навчає Claude Code конвенцій Nette: навички, автоматична валідація Latte/NEON/JS та інтеграція з MCP. -- [MCP Inspector |ai:en:mcp-inspector] надає AI реальний стан вашого застосунку: DI сервіси, схему бази даних, маршрути та логи Tracy. +- [Claude Code plugin |https://ai.nette.org/en/claude-code] навчає Claude Code конвенцій Nette: навички, автоматична валідація Latte/NEON/JS та інтеграція з MCP. +- [MCP Inspector |https://ai.nette.org/en/mcp-inspector] надає AI реальний стан вашого застосунку: DI сервіси, схему бази даних, маршрути та логи Tracy. Frontend From ef2f27a367dab692b927ce86059bc4731fb54808 Mon Sep 17 00:00:00 2001 From: CodeWithPetr <petr.ondracek90@gmail.com> Date: Tue, 23 Jun 2026 14:28:04 +0700 Subject: [PATCH 50/50] Update urls.texy Fix __toString for variable Immutable $url --- http/en/urls.texy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/http/en/urls.texy b/http/en/urls.texy index 608fa0064f..6c80b9485a 100644 --- a/http/en/urls.texy +++ b/http/en/urls.texy @@ -151,7 +151,7 @@ $newUrl = $url ->withPassword('') ->withPath('/en/'); -echo $newUrl; // 'http://john:xyz%2A12@nette.org:8080/en/?name=param#footer' +echo $newUrl; // 'http://nette.org:8080/en/?name=param#footer' ``` The `UrlImmutable` class implements the `JsonSerializable` interface and has a `__toString()` method, so the object can be printed or used in data passed to `json_encode()`.