Latte filtr pro odstranění komentářů z vygenerováného HTML
- hiny
- Člen | 35
Zdravím, snažím se pomocí vlastního filtru odstranit komentáře z vygenerovaného HTML.
Napadlo mě, že to vyřeším tak, že celou šablonu @layout.latte zabalím do bloku navíc a použiji na něj filtr. Nicméně mi Laděnka vypisuje následující varování:
User Warning
Filter |stripcomments is called with incompatible content type HTML, try to prepend |stripHtml.
Což je pěkné, ale pokud bych to udělal, tak dostanu čistý text, což logicky nechci.
Nette verze 2.4.
BasePresenter
<?php
abstract class BasePresenter extends UI\Presenter
{
// ... "Nepodstatný" zbytek
protected function beforeRender()
{
parent::beforeRender();
// Filtr pro odstranění komentářů
$this->template->addFilter('stripcomments', function ($s) {
// Odebrání html komentářů <!-- -->
$result = preg_replace('/<!--(.|\n)*?-->/', '', $s);
return $result;
});
}
}
?>
@layout.latte
{block #allhtml|stripcomments}
{*
...
obsah šablony
...
*}
{/block}
Sice to dělá co má, ale není to jaksi ono. Moje otázka zní, jak to udělat, abych mohl používat filtry na vygenerovaný HTML kód, bez tohoto varování? Případně nějaký lepší způsob.
- hiny
- Člen | 35
GEpic napsal(a):
V případě že si těmito latte komentáři
označím
bloky/části kódu a následně stejně zakomentuji vetší část kódu,
která tyto komentáře obsahuje, tak se celek mine účinkem a celé se to
rozbije. Proto používám klasické HTML komentáře
a pokud
potřebuji zakomentovat větší část kódu použiji
latte komentáře
.
Viz:
<ul>
{* prvek x1 *}
<li>x1</li>
{* tohle zatím není potřeba
<li>x2</li>
<li>x2</li>
{* prvek x3 *}
<li>x3</li>
<li>x4</li>
*}
<li>x</li>
</ul>
Nicméně to jsme úplně mimo téma. Neřešíme otázku proč, ale jak ;-) Myslím, že otázka proč se tu řešila několikrát, ale zatím nikdo nenapsal, jak to udělat. Prosím tedy o zdržení se podobných komentářů.
- GEpic
- Člen | 566
hiny napsal(a):
GEpic napsal(a):
V případě že si těmito
latte komentáři
označím bloky/části kódu a následně stejně zakomentuji vetší část kódu, která tyto komentáře obsahuje, tak se celek mine účinkem a celé se to rozbije. Proto používám klasickéHTML komentáře
a pokud potřebuji zakomentovat větší část kódu použijilatte komentáře
.Viz:
<ul> {* prvek x1 *} <li>x1</li> {* tohle zatím není potřeba <li>x2</li> <li>x2</li> {* prvek x3 *} <li>x3</li> <li>x4</li> *} <li>x</li> </ul>
Nicméně to jsme úplně mimo téma. Neřešíme otázku proč, ale jak ;-) Myslím, že otázka proč se tu řešila několikrát, ale zatím nikdo nenapsal, jak to udělat. Prosím tedy o zdržení se podobných komentářů.
Já se neptám ‚proč‘ abych se ti vysmíval nebo něco, ale když odpovíš na mé proč, budu vědět záměr a budu moci nad problémem přemýšlet. A myslím, že to tak má většina lidí zde na fóru. :)
Mě by třeba zajímalo, odkud bereš ten generovaný kód, zda-li je
možnost ho v presenteru nějak vytáhnout? My totiž například parsujeme
makra z generovaného obsahu, a stačí to v beforeRender prohnat metodou, kde
už se o to preg_replace_all
postará. Do šablony pak putuje už
to, co se má skutečně vypsat a není potřeba to pak už nijak upravovat.
Editoval GEpic (22. 7. 2016 0:38)
- hiny
- Člen | 35
@GEpic Díky za nakopnutí směrem k makrům.
Nakonec jsem se inspiroval makrem spaceless
a pro mou potřebu
vytvořil následující třídu, kterou jsem zaregistroval v
config.neon
.
latte:
macros:
- App\Utils\CustomMacros
namespace App\Utils;
use Latte;
use Latte\CompileException;
use Latte\MacroNode;
use Latte\PhpWriter;
class CustomMacros extends Latte\Macros\MacroSet
{
public static function install(Latte\Compiler $compiler)
{
$me = new static($compiler);
$me->addMacro('stripcomments', [$me, 'macroStripComments'], [$me, 'macroStripComments']);
}
public function macroStripComments(MacroNode $node, PhpWriter $writer)
{
if ($node->modifiers || $node->args) {
throw new CompileException('Modifiers and arguments are not allowed in ' . $node->getNotation());
}
if (!$node->closing) {
return;
} else {
// Odebrání html komentářů <!-- -->
$node->content = preg_replace('/<!--(.|\n)*?-->/', '', $node->content);
}
}
}
Makro volám v šabloně @layout.latte
hned na začátku.
{stripcomments}
<!DOCTYPE html>
<!-- Zbytek šablony -->
{snippet content}
{include #content}
{/snippet}
<!-- Bude odstaněno -->
</html>{/stripcomments}
Nicméně v tento moment budu muset použít toto makro v každé
includované šabloně či načtené komponentě, stejně jako makro
spaceless
.
Je nějaké řešení jak toto obejít, abych ho nemusel všude vkládat a napsal ho jenom jednou do hlavní šablony?
- hiny
- Člen | 35
Zatím jediné funkční řešení, při kterém mi bude stačit upravit jednu šablonu a nemuset hlídat, zda jsem do nějaké šablony nezapomněl přidat makro, je vrátit se od makra zpět k filtru a původní myšlence.
Takže výsledek je stejný jako v 1. příspěvku s dodatečnou úpravou
Latte\Runtime\FilterExecutor
, čímž jsem obešel to
varování.
public function filterContent($name, FilterInfo $info, $arg)
{
/** ... */
if ($info->contentType !== Engine::CONTENT_TEXT && $lname !== "stripcomments") {
trigger_error("Filter |$name is called with incompatible content type " . strtoupper($info->contentType)
. ($info->contentType === Engine::CONTENT_HTML ? ', try to prepend |stripHtml.' : '.'), E_USER_WARNING);
}
/** ... */
}
- Roman Ožana
- Člen | 52
Vyřešil bych to takhle (Latte 2.4.2):
$this->template->addFilter('stripcomments', function (\Latte\Runtime\FilterInfo $fileInfo, $s) {
// Odebrání html komentářů <!-- -->
$result = preg_replace('/<!--(.|\n)*?-->/', '', $s);
return $result;
});
viz FilterExecutor.php podmínka zde https://github.com/…Executor.php#L152 a další zde https://github.com/…Executor.php#L185