Je možné vložit latte kód do šablony v proměnné?

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
LeonardoCA
Člen | 296
+
0
-

Konkrétně mi jde o to, že chci renderovat výsledek a zároveň originální latte kód a výsledný html kód

	<h2>Combination</h2>
	{capture $code}
	{bsalert success}{bsbadge success}1{/bsbadge} Combination of previous tags. {bslabel info} {bsiconw thumbs-up} It works!{/bslabel}{/bsalert}
	{/capture}
	<div class="row">
		<div class="span4">
			{!$code}
		</div>
		<div class="span4">
			{syntax double}<pre>{bsalert success}{bsbadge success}1{/bsbadge} Combination of previous tags. {bslabel info} {bsiconw thumbs-up} It works!{/bslabel}{/bsalert}</pre>{{/syntax double}}
		</div>
		<div class="span4">
			<pre>{$code}</pre>
		</div>
	</div>

Potřeboval bych do šablony předat řetězce v latte syntaxi a zatím jsem nepřišel na způsob jak je přímo v šabloně interpretovat.

Druhý dotaz, existuje nějaký filtr nebo jiný jednoduchý způsob, který by vygenerovaný kód trošku zarovnal? Zvýraznění syntaxe pak už je to nejmenší …

Editoval LeonardoCA (10. 6. 2012 19:19)

vvoody
Člen | 910
+
0
-

Vytvor komponentu, ktora bude mat sablonu Nette\Templating\Template.$template->setSource($latteKod)

LeonardoCA
Člen | 296
+
0
-

Nechtěl jsem to řešit na úrovni komponent nebo prezenteru. Raději bych to řešil vlastním makrem, ale nevím od čeho se odpíchnout.

bojovyletoun
Člen | 668
+
0
-

nebude to triviiální.Napadá mě jedině využít 2 makra- jedno pro záznam a druhé pro vložení

  1. by bylo vlastně byla kombinace syntax off (Hledej Nette\Latte\Parser::filter() a capture Nette\Latte\CoreMacros::macroCapture() … ikdyž nevím, zda capture skutečně zafunguje
  2. makro pro vložení bude mít úkol kód zkompilovat a potom vložit. Takže tam budeš potřebovat části metod Nette\Latte\Parser::parse() a Nette\Latte\Compiler::compile(),.. Části proto, že např. u compile se rozhodně nebude generovat nové id šablony, ani prology a epilogy ani epitafy.

Editoval bojovyletoun (10. 6. 2012 21:33)

LeonardoCA
Člen | 296
+
0
-

bojovyletoun: Hmm. Capture zachycuje jen výstup, to už jsem testoval. A zbytek zní moc složitě. Myslím si, že by se měla dát najít nějaká jednodušší cesta.

S komponentou mám problém, protože standartní template získaná v komponentě přes $this->template se použít nedá – ta vyžaduje template v souboru a ignoruje setSource a při použití $template->setSource() se zase musí vytvořit nová instance template a musely by se zaregistrovat znovu všechny helpery, makra, atd. A tomu jsem se chtěl vyhnout.

Prostě bych chtěl řetězec latte kompilovat v rámci template (se stejnými parametry) do které je vložený.

Spíš jsem uvažoval, že by se mohla dát použit nějaká variace na macroBlock

Dodatek:

  • testuji na takřka čistém sandboxu Nette 2.0.3
  • cílem je addon modul závislý jen na Nette samotném, přidaný přes compilerExtension, bez jakýchkoli dalších zásahů sandboxu
  • myslím si, že by to mohla být velmi užitečná funkcionalita pro tvorbu dokumentace, tutoriálu, generátorů kódů, apod

Možná to latte neumožňuje, protože při nevhodném použití by snadno mohlo dojít k narušení bezpečnosti?

Editoval LeonardoCA (10. 6. 2012 22:44)

vvoody
Člen | 910
+
0
-

Co ty chces (ak to spravne chapem) ide uplne proti principu sablon, sablona sa kompiluje raz a potom sa spusta skopilovana verzia. Ty chces aby sa kompilovala pri kazdom requeste cela sablona? To totiz bude potrebne kedze chces mat samotny obsah sablony premenny. Skorej by som sa zamyslel ci nieco nerobim zle ak mi nestaci staticka sablona. Ak predsa nestaci tak nevidim problem preco nepouzit komponenty, okrem znovu registrovania helperov a makier ma nenapada ina prekazka.

LeonardoCA
Člen | 296
+
0
-

vvoody napsal(a):

Co ty chces (ak to spravne chapem) ide uplne proti principu sablon, sablona sa kompiluje raz a potom sa spusta skopilovana verzia. Ty chces aby sa kompilovala pri kazdom requeste cela sablona?

Z téhle strany jsem se nad tím nezamýšlel. Ohledně principu šablon máš pravdu. Dík za komentáře.

Díval jsem se prostě na šablonu a že se potřebuji nějak zbavit duplicitního kódu a vložit jej nejlépe dynamicky.

Z toho hlediska mi to smysl ještě úplně nedává. Nechci kompilovat celou šablonu, ale části šablony a stačí jen při změně – což se dá zajistit kešováním.

Možná bude přeci jen nejlepší řešení komponenta, ale stále si myslím, že to samé by v principu mělo být možné udělat na úrovni šablony a ve výsledku by nebyl zásadní rozdíl.

Jednu možnou variantu použití si představuji tak, že kodér napíše nějaký blok přímo v šabloně. A já jen pomocí makra podobného „capture“ zachytím nejen vyrenderovaný zkompilovaný kód, ale i původní latte kód mezi tagy „capture“. To je vše a myslím si, že to není vyloženě nic proti filozofii šablon.

A nebo bych měl přepsat kompilátor šablony?

Dám jiný hypotetický příklad, který mne napadá:

Mám komponentu, dva různí kodéři nakódují její šablonu úplně jiným stylem, ale se stejným výsledkem. Já bych chtěl zachytit jak výsledný kód, tak původní latte kód, který byl renderován. Nějak takto:

{captureOriginalLatteTemplateAndCompiledTemplate}
{control SomeComponent}
{/captureOriginalLatteTemplateAndCompiledTemplate}

Nebo se může jednat o libovolnou část kódu šablony, který mne zajímá.
Chci:

  • vidět zdrojový kód šablony
  • zkompilovaný výsledek
  • vyrenderovaný výsledek

Jak by se to dalo vyřešit?

Nechám si to projít hlavou…

nakonec má možná pravdu bojovyletoun a nejde to tak jednoduše, jak si představuju a nebo bych to měl řešit úplně mimo šablony

Edited: Už vím, kde jsem udělal chybu v úvaze. Zatímco zachytit výsledek je jednoduché, pomocí „obstart()“, atd…, zachytit co bylo pársováno a kompilováno podobně jednoduchým způsobem nelze… a v běžné praxi to není potřeba, takže pokud to budu chtít realizovat, tak budu muset pochopit celý proces kompilace a zaznamenat si kompilovaný kód sám. A v mém původním jednoduchém případu to asi raději obejdu s použitím komponenty.

Editoval LeonardoCA (11. 6. 2012 2:34)

@lex
Člen | 5
+
0
-

Chtel bych se zeptat jestli jste problem nejak vyresili? Resim dle meho nazoru podobnou vec:

Nacitam data z databaze a v textovem vystupu bych chtel pouzit macro {control}. Potreboval bych, aby mi jej sablona vyhodnotila jako volani komponenty. V soucasne dobe mi na toto makro pohlizi jako na prosty text.

Snazil jsem se podle vyse uvedenych navodu vytvorit helper, na zaklade funkci Nette\Latte\Parser::parse() a Nette\Latte\Compiler::compile(). Bohuzel jsem se dostal do situace kdy musim zaregistrovat zakladni makra.

Mohl by mi nekdo poradit nebo navest.

$template->registerHelper('reRenderLatte', function($value) {
	$parser = new \Nette\Latte\Parser;
	$compiler = new Nette\Latte\Compiler;
	//$arr = $parser->parse($value);
	//foreach ($arr as $item):
		//if($item->type = 'macroTag')
		$r = $compiler->compile ($parser->parse($value));
	//endforeach;
	return $r;
});

V sablone se to potom snazim vypsat nejak takto

{$item->obsah|reRenderLatte}

Dekuji za kazdou radu

Filip Procházka
Moderator | 4668
+
0
-

To vůbec není pěkné řešení, lépe takto

$this->template->obsah = $this->createTemplate('Nette\Templating\Template')
	->setSource($item->obsah);

A v šabloně

{include $obsah}
@lex
Člen | 5
+
0
-

Filip Procházka napsal(a):

To vůbec není pěkné řešení, lépe takto

$this->template->obsah = $this->createTemplate('Nette\Templating\Template')
	->setSource($item->obsah);

A v šabloně

{include $obsah}

Tvoje reseni semi libi vice, bohuzel mi ted nette hlasi chybu Template file name was not specified.

Presenter:

public function renderDefault($id = 1) {
	$item = $this->model->fetch($id);
	$this->template->obsah = $this->createTemplate('Nette\Templating\Template')
			->setSource($item->obsah);
	$this->template->item = $item;
}

Sablona:

{block title}{$item->nazev}{/block}

{block content}
{block|texy}

{include $obsah}

{/block}

Nejaky napad?

Edit1:
Promenna $obsah obsahuje nasledujici obsah:

== Nadpis

Lorem ipsum dolor sit amet consectetuer et ante porttitor accumsan Praesent.

{control galerie,2}

Lorem ipsum dolor sit amet consectetuer et ante porttitor accumsan Praesent.

Potrebuji aby {control galerie,2} bylo vyhodnoceno tak jako bych to napsal rucne do sablony, tedy vyvolanim componenty. Mohl by nekdo poradit?

Editoval @lex (5. 2. 2013 21:06)

@lex
Člen | 5
+
0
-

chybova hlaska (radek 23):

Nette\InvalidStateException

Template file name was not specified.

13:    if (!function_exists($_l->blocks['title'][] = '_lbb8f015b21f_title')) { function _lbb8f015b21f_title($_l, $_args) { extract($_args)
14:    ;echo Nette\Templating\Helpers::escapeHtml($item->nazev, ENT_NOQUOTES) ;
15:    }}
16:
17:    //
18:    // block content
19:    //
20:    if (!function_exists($_l->blocks['content'][] = '_lb1bf5e71f21_content')) { function _lb1bf5e71f21_content($_l, $_args) { extract($_args)
21:    ;ob_start() ?>
22:
23:    <?php Nette\Latte\Macros\CoreMacros::includeTemplate($obsah, $template->getParameters(), $_l->templates['e4lqlzynmr'])->render() ?>
24:
25:
26:
27:    <?php echo $template->texy(ob_get_clean()) ?>

Editoval @lex (5. 2. 2013 21:47)

@lex
Člen | 5
+
0
-

@lex napsal(a):

Filip Procházka napsal(a):

To vůbec není pěkné řešení, lépe takto

> $this->template->obsah = $this->createTemplate('Nette\Templating\Template')
> 	->setSource($item->obsah);

>

A v šabloně

> {include $obsah}

Tvoje reseni semi libi vice, bohuzel mi ted nette hlasi chybu Template file name was not specified.

Presenter:

public function renderDefault($id = 1) {
	$item = $this->model->fetch($id);
	$this->template->obsah = $this->createTemplate('Nette\Templating\Template')
			->setSource($item->obsah);
	$this->template->item = $item;
}

Sablona:

{block title}{$item->nazev}{/block}

{block content}
{block|texy}

{include $obsah}

{/block}

Nejaky napad?

Edit1:
Promenna $obsah obsahuje nasledujici obsah:

== Nadpis

Lorem ipsum dolor sit amet consectetuer et ante porttitor accumsan Praesent.

{control galerie,2}

Lorem ipsum dolor sit amet consectetuer et ante porttitor accumsan Praesent.

Potrebuji aby {control galerie,2} bylo vyhodnoceno tak jako bych to napsal rucne do sablony, tedy vyvolanim componenty. Mohl by nekdo poradit?

@lex napsal(a):

chybova hlaska (radek 23):

Nette\InvalidStateException

Template file name was not specified.

13:    if (!function_exists($_l->blocks['title'][] = '_lbb8f015b21f_title')) { function _lbb8f015b21f_title($_l, $_args) { extract($_args)
14:    ;echo Nette\Templating\Helpers::escapeHtml($item->nazev, ENT_NOQUOTES) ;
15:    }}
16:
17:    //
18:    // block content
19:    //
20:    if (!function_exists($_l->blocks['content'][] = '_lb1bf5e71f21_content')) { function _lb1bf5e71f21_content($_l, $_args) { extract($_args)
21:    ;ob_start() ?>
22:
23:    <?php Nette\Latte\Macros\CoreMacros::includeTemplate($obsah, $template->getParameters(), $_l->templates['e4lqlzynmr'])->render() ?>
24:
25:
26:
27:    <?php echo $template->texy(ob_get_clean()) ?>

Vyreseno:

Problem byl v tom ze misto Nette\Templating\Template se pouzilo Nette\Templating\FileTemplate. Pricina byla ta, ze v basePresenteru jsem pro praci s Texy pouzil:

	$template = parent::createTemplate();

Stacilo prepsan na

	$template = parent::createTemplate($class);

a vse funguje UAA! diky vsem