Začalo to problémem, pokračovalo různými inspiracemi a skončilo řešením.
Potíž s odkazovaným problémem v běžných šablonovacích systémech (Smarty-like) je ten, že jazyk, jakým jsou šablony v Smarty-like systémech psány, je imperativní. U šablon se všeobecně podle mě hodí více deklarativní způsob vyjadřování – šablonovači řeknu pouze to, co má udělat a jak to konkrétně udělá, mě nezajímá. Příklad: říct šablonovači „chci vypsat seznam položek oddělených čárkami“ je jednodušší než psát „pro každou položku v seznamu: pokud je to první položka, vytiskni pouze tuhle položku; jinak vytiskni čárku a potom teprve položku“.
Další věcí, která by se dala označit jako „jQuery idiom“ (terminus technicus jako noha), je, že nezáleží, jestli je operace aplikována na jednu, nebo více položek. Je jedno, jestli mám jen jednu položku, nebo jich je milion – já chci, aby každá položka byla obklopena tagem <b>.
A třetí podstatnou věcí je kontext. Kontext obsahuje vstupní data a zprostředkovává je šabloně.
Syntaxe šablon staví na tom, že šablony jsou bloky textu s dírami, které chtějí něčím vyplnit. Aby bylo poznat, kde díra začíná, je použit znak dolaru. Po něm následuje buď určení podkontextu, nebo filtr. Volitelně se na výsledek dají aplikovat další filtry oddělené dvojtečkou. Znak, který by oznamoval ukončení díry je podle mě nadbytečný a nenapomáhá čitelnosti.
Nejdříve případ, kdy následuje určení podkontextu. Podkontext se dá určit selektorem. Řekněme, že kontext je name = "world" a šablona:
Hello, $name!
Výsledkem bude Hello, world!. Selektor odpovídá regulárnímu výrazu [a-zA-Z0-9_]+. Vícenásobný selektor je více takových selektorů oddělených tečkami:
Hello, $person.name.first!
V kontextu person = (name = (first = "Fred")) vytiskne Hello, Fred!.
Krom selektoru může podkontext také určit pole, nebo řetězec:
$"Hello", $(1, 2, 3, 4, 5)!
Řetězec je sekvence znaků ohraničených uvozovkami. Pole je kolekce položek oddělených čárkami. Výstupem předchozího kódu v jakémkoli kontextu bude: Hello, 12345! Kontext řetězce vrací na výstup samotný řetězec. Pole vrací na výstup postupně výstup každého prvku.
To pravě ořechové začíná, když se začnou používat filtry. Nejjednodušším filtrem je aplikace anonymní šablony:
$(1, 2, 3, 4, 5):{$$, }
Jelikož anonymní šablona je filtr, je od selektoru oddělena dvojtečkou. Text šablony je ohraničen složenými závorkami. Protože kontextem pro anonymní šablonu je pole, je šablona aplikována na každou položku a výsledkem je pole nových položek. $$ je aktuální kontext. Výsledkem šablony bude: 1, 2, 3, 4, 5, . Krom $$ je dalším speciálním kontextem $# který obsahuje klíč pole:
$(foo = "bar", "bar" = "baz"):{$# = $$, }
Výsledek: foo = bar, bar = baz, .
Filtrem může být také pojmenovaná šablona:
$"foo":#justprint{$$}
Výhoda pojmenované šablony je v tom, že ji nadále můžeme používat pouze pomocí jejího jména. Pokud tedy předchozí šablonu upravíme na:
$"foo":#justprint{$$}
$"bar:justprint
Výstupem bude:
foo bar
Je také možno definovat pojmenovanou šablonu mimo výraz začínající dolarem:
#justprint{$$}
$"foo":justprint
$"bar":justprint
Výstup bude stejný jako předtím. Pojmenovaná šablona definovaná mimo výraz s dolarem nic nevytiskne, pouze se pak bude dát použít v následujících výrazech.
Posledním, vlastně už známým druhem filtru, je aplikace pojmenované funkce. V případech výše to vždycky byly šablony, které tyto filtry vytvářely, ale taková pojmenovaná funkce může být externě definovaná, někde v PHP kódu (takové funkce jsou samozřejmě mnohem mocnější). Krom toho mohou přijímat další parametr, např.:
$"foo":transform(upper):prepend{->}
Parametrem je buď pole, nebo šablona (rozdíl mezi zavoláním funkce s šablonou a aplikací pojmenované šablony je v tom, že u pojmenované šablony je na začátku mřížka). V případě šablony se jedná vlastně o jednoprvkové pole – prepend({->}).
A co když není vytvořen žádný nový kontext a za dolarem následuje už rovnou filtr? Pak se bere aktuální kontext (pozor, kdyby za justprint na druhém řádku nebyly kulaté závorky, bylo by to bráno jako selektor, nikoli jako aplikace filtru):
#justprint{$$}
$"foo":{$justprint()}
Je to samé jako:
#justprint{$$}
$"foo":{$$:justprint}
A jak by vypadal problém ze začátku v tomto šablonovacím systému?
<ul>
$seznam:{<li><a href="/zobrazit?id=$id">$(
"vymazat" = $vymazat,
"upravit" = $upravit
):allTrue:{<a href="/$#?id=$id">$#</a>}:pss(" (", ", ", ")")</li>}
</ul>
Filtr alltrue vybere všechny pravdivé hodnoty. pss přijímá tři parametry – prefix, separator, suffix – položky pole spojí pomocí separatoru, před ně přidá prefix a za ně suffix, jednalo by se o funkci definovanou někde mimo šablony.
Jak by mohlo vypadat vypsání tabulky:
<table>
<tr>
<th>Jméno</th>
<th>Heslo</th>
</tr>
$uzivatele:{
<tr class="$#:class("odd", "even")">
<td>$jmeno</td>
<td>$heslo</td>
</tr>
}
</table>
Anebo hieararchické menu:
$($menu):#menu{
<ul>
<li>
<a href="$url">$nazev</a>
$($podmenu):menu
</li>
</ul>
}
Doposud žádný komentář
Přidat komentář