# Zkouška 19.1.2024 Handlebars formát (Škoda)

<{ForumPost(poster="throwaway", timestamp=2024-01-21 12:19:20)}>
Cílem je implementovat částečnou substituci pro Handlebars šablony.  
  
Program dostanete jeden argument a to je cesta k souboru šablony. Pokud se soubor nepodaří otevřít, program vypíše **Can not open file\n** (\n je znak konce řádku) a skončí. Pokud není šablona validní, program vypíše **Invalid template\n** a skončí. Pokud se povede šablonu načíst program čte a vyhodnocuje příkazy ze standardního vstupu.  
  
Handlebars formát  
  
Handlebars je textový šablonovací formát. Kontrolní výrazy začínají znaky **{{** a končí **}}**. Kontrolní sekvence může obsahovat jeden kontrolní výraz, nebo jejich dvojici. Ve druhém případě slouží první výraz jako otvírací a druhý jako zavírací. Mezi otevírací a zavírací výraz je možné vložit další obsah, čímž získáváme stromovou strukturu podobou třeba HTML.  
  
Validní šablona musí:  

    
* obsahovat pouze kontrolní výrazy níže uvedené

    
* být korektně "uzávorkovaná", otvírací a zavírací kontrolní výrazy se nesmí křížit

Názvy proměnných v kontrolních výrazech je třeba očistit o bílé znaky. Následující zápisy ekvivalentní:  

    <p>{{firstname}}</p>
    <p>{{      firstname}}</p>
    <p>{{      firstname   }}</p>
    <p>{{      firstname    }}</p>
    

  
Všechny výrazy reprezentují proměnnou s názvem **firstname**. Podobné pravidlo platí i pro výrazy obsahující klíčové slovo, například **if**.  
  
Příklady:  

    {{#if firstname}}
    {{#if       firstname}}
    {{#if       firstname       }}
    

Všechny výrazy využívají proměnnou jménem **firstname**.  
  
Dále jsou popsány podporované kontrolní výrazy.  
  
Proměnná  
  
Příklad níže ukazuje použití kontrolního výrazy proměnné s názvem **firstname**.  

    <p>{{firstname}}</p>

Při dosazení proměnné, je celý kontrolní výraz nahrazen hodnotou proměnné. Například, pokud by proměnná **firstname** měla hodnotu **Ailish** získáme výraz:  

    <p>Ailish</p>

Klíčové slovo 'with'  
  
Výraz má s **with** má jeden argument oddělený mezerou. Hodnota argumentu následovaná znakem tečky je použita jako prefix pro všechny proměnné v podstromu výrazu.  
  
Příklad použití **with**:  

    {{#with person}}<p>{{firstname}}</p>{{/with}}

V tomto příklady je proměnná **firstname** přístupná pod jménem **person.firstname**. Předpona **person.** je utvořena z argumentu od **with** a znaku tečky**.**  
  
Klíčové slovo 'if'  
  
Klíčové slovo **if** značí oblast podmíněného výstupu. Výraz má jeden argument a to je jméno proměnné.  
  
Příklad níže dá na výstup **inner content** pouze tehdy, pokud existuje neprázdná proměnná **firstname**.  

    {{#if firstname}}inner content{{/if}}

Stejně jako pro proměnné i pro **if** je použitý prefix of **with**. Příklad níže tedy tedy využívá proměnné **person.firstname**.  

    {{#with person}}<p>{{#if firstname}}inner content{{/if}}</p>{{/with}}

Klíčové slovo 'each'  
  
Klíčové slovo **each** označuje kolekci hodnot. Výraz má jeden jeden argument a to je jméno proměnné.  

    <ul>
    {{#each people}}
      <li>{{firstname}}</li>
    {{/each}}
    </ul>
    

Hodnoty v podstromu výrazy jsou dostupné pomocí předpony ***.**. V příklady výše bych mohli adresovat vnitřní proměnnou **firstname** pomocí zápisu **people.*.firstname**.  
  
Příkazy  
  
Příkazy jsou zadávány na standardní vstup. Jednotlivé příkazy jsou odděleny znakem konce řádku (\n). Prázdné řádky by měl program ignorovat. Znak konce řádku není součástí příkazu. Pokud je příkaz nevalidní, nebo neznámý program musí vypsat **Invalid command\n** a pokračovat načtením dalšího příkazu. Program skončí ve chvíli, kdy není již co číst - tedy narazí na konec standardního vstupu.  
  
Níže jsou popsány podporované příkazy.  
  
print  
  
Příkaz nebere žádný argument. Vykonáním příkazy je vytisknutí aktuálního stavu šablony na standardní výstup. Bílé znaky mimo kontrolní výrazu musí být zachovány. Pokud kontrolní výraz má argumenty, jsou ty odděleny jednou mezerou. Vstupy ze sekce Handlebars formát by tak byly vypsány následovně:  

    {{firstname}}
    {{#if firstname}}
    

set  
  
Tento příkaz bere dva argumenty:  

* jméno proměnné

* hodnotu proměnné Pokud jsou oba argumenty přítomné, jsou oddělené bílým znakem (mezeru). To znamená, že jméno proměnné nemůže obsahovat bílý znak (mezeru). Zápis příkazy tedy odpovídá následující šabloně: 

    set {name-without-space} {rest of line is a value}

Příklady:  

* 

    set name Ailish

 - proměnné **name** s hodnotou **Ailish**

* 

    set person.message Secret message ...

 - proměnná **person.message** s hodnotou **Secret message ...**

* 

    set empty

 - proměnná **empty** s hodnotou `` (prázdný řetězec)

* 

    set empty 

 - proměnná **empty** s hodnotou `` (prázdný řetězec)(všimněte si mezery za **empty**)

* 

    set  name Ailish

 - v tomto případě jsou dvě mezery po **set**, jméno proměnné je tedy `` (prázdný řetězec) hodnota je **name Ailish**

Jakmile program dostane proměnou a její hodnotu, musí provést nahrazení v šabloně. Každá proměnná stejného jména musí být nahrazena dodanou hodnotou. Nezapomínejte na prefixy dodané pomocí **with** a **each**.  
  
Každá podmínka (**if**) obsahující danou proměnnou musí být vyhodnocena. Pokud je hodnota prázdná, je kontrolní sekvence **if** včetně obsahu z šablony odevzdána. Pokud je hodnota neprázdná, je kontrolní sekvence **if** nahrazena svým obsahem.  
  
Příklady  
  
Takto sekce obsahuje příklady šablon, příkazů a výstupů  
  
Jednoduché nahrazení  
  
Template:

    Message:
     {{message}}
    

Commands (starting with '>' (not part of the input) and output):  

    > set message You can do this
    > print
    Message:
     You can do this
    

Nahrazení na více místech  
  
Template:  

    {{value}} + {{value}} = {{result}}

Commands (starting with '>' (not part of the input) and output):  

    > set value 1
    > set result 2
    > print
    1 + 1 = 2
    

Klíčové slovo with  
  
Template:  

    {{value}} {{#with content}} {{value}} {{/with}}

Commands (starting with '>' (not part of the input) and output):  

    > set value one
    > print
    one {{#with content}} {{value}} {{/with}}
    > set content.value two
    > print
    one {{#with content}} two {{/with}}
    

Podmíněný výstup I  

    |{{#if should_render}} RENDER {{/if}}|

Commands (starting with '>' (not part of the input) and output):  

    > set should_render one
    > print
    | RENDER |
    

Podmíněný výstup II  

    |{{#if should_render}} RENDER {{/if}}|

Commands (starting with '>' (not part of the input) and output):  

    > set should_render
    > print
    ||
    

Nahrazování v kolekcích  

    Messages: {{#each items}} {{value}} {{unchanged}} {{/each}}

Commands (starting with '>' (not part of the input) and output):  

    > set items.*.value Single value ... 
    > print
    Messages: {{#each items}} Single value ...  {{unchanged}} {{/each}}
    


<{/ForumPost}>

<{ForumPost(poster="Anonymous", timestamp=2024-01-21 12:24:59)}>
Spravil si to?
<{/ForumPost}>

<{ForumPost(poster="throwaway", timestamp=2024-01-21 12:27:16)}>
ne
<{/ForumPost}>

<{ForumPost(poster="Anonymous", timestamp=2024-01-28 20:59:36)}>
Nevíš, jestli když to nějak máš, ale ne úplně dobře, tak máš šanci to udělat(s horší známkou)?  
Nebo je to tak, že když ti  to neprojde ReCodexem, tak máš za 4 ?
<{/ForumPost}>

<{ForumPost(poster="throwaway", timestamp=2024-01-30 00:05:03)}>
Bylo celkem 14 testů, teoreticky bylo možné projít i s žádným fungujícím, záleží na kvalitě kódu.  
Slyšel jsem, že někomu jich procházelo 11 a měl to za 1.
<{/ForumPost}>

