From acd02af00b19798ad751a7ae0ecdae744636ccbe Mon Sep 17 00:00:00 2001
From: tbreuss
Date: Sun, 4 Dec 2022 16:08:19 +0100
Subject: [PATCH 01/15] wip
Signed-off-by: tbreuss
---
plugins/twig_plus/TwigPlusExtension.php | 90 +++++-------------
templates/pages/filtered.twig | 31 ------
templates/pages/recent.twig | 15 ---
tests/acceptance/HerbieInfoCest.php | 2 -
.../SysPlugins/TwigPlus/TwigPlusSmokeTest.php | 14 ---
website/site/pages-de.zip | Bin 31387 -> 0 bytes
website/site/pages/3-recipes/1-index.md | 19 +++-
website/site/themes/default/css/styles.css | 2 +-
website/site/themes/default/recipe.twig | 22 ++++-
9 files changed, 58 insertions(+), 137 deletions(-)
delete mode 100644 templates/pages/filtered.twig
delete mode 100644 templates/pages/recent.twig
delete mode 100644 website/site/pages-de.zip
diff --git a/plugins/twig_plus/TwigPlusExtension.php b/plugins/twig_plus/TwigPlusExtension.php
index c09dafec..7ba6e61d 100644
--- a/plugins/twig_plus/TwigPlusExtension.php
+++ b/plugins/twig_plus/TwigPlusExtension.php
@@ -48,23 +48,21 @@ public function getFunctions(): array
{
$options = ['is_safe' => ['html']];
return [
- new TwigFunction('menu_ascii_tree', [$this, 'functionAsciiTree'], $options),
- new TwigFunction('menu_breadcrumb', [$this, 'functionBreadcrumb'], $options),
- new TwigFunction('menu_list', [$this, 'functionListing'], $options),
- new TwigFunction('menu_pager', [$this, 'functionPager'], $options),
- new TwigFunction('menu_sitemap', [$this, 'functionSitemap'], $options),
- new TwigFunction('menu_tree', [$this, 'functionMenu'], $options),
- new TwigFunction('page_taxonomies', [$this, 'functionPageTaxonomies'], $options),
- new TwigFunction('pages_filtered', [$this, 'functionPagesFiltered'], $options),
- new TwigFunction('pages_recent', [$this, 'functionPagesRecent'], $options),
- new TwigFunction('taxonomy_archive', [$this, 'functionTaxonomyArchive'], $options),
- new TwigFunction('taxonomy_authors', [$this, 'functionTaxonomyAuthors'], $options),
- new TwigFunction('taxonomy_categories', [$this, 'functionTaxonomyCategories'], $options),
- new TwigFunction('taxonomy_tags', [$this, 'functionTaxonomyTags'], $options)
+ new TwigFunction('menu_ascii_tree', [$this, 'menuAsciiTree'], $options),
+ new TwigFunction('menu_breadcrumb', [$this, 'menuBreadcrumb'], $options),
+ new TwigFunction('menu_list', [$this, 'menuList'], $options),
+ new TwigFunction('menu_pager', [$this, 'menuPager'], $options),
+ new TwigFunction('menu_sitemap', [$this, 'menuSitemap'], $options),
+ new TwigFunction('menu_tree', [$this, 'menuTree'], $options),
+ new TwigFunction('page_taxonomies', [$this, 'pageTaxonomies'], $options),
+ new TwigFunction('taxonomy_archive', [$this, 'taxonomyArchive'], $options),
+ new TwigFunction('taxonomy_authors', [$this, 'taxonomyAuthors'], $options),
+ new TwigFunction('taxonomy_categories', [$this, 'taxonomyCategories'], $options),
+ new TwigFunction('taxonomy_tags', [$this, 'taxonomyTags'], $options)
];
}
- public function functionAsciiTree(
+ public function menuAsciiTree(
string $route = '',
int $maxDepth = -1,
bool $showHidden = false
@@ -86,7 +84,7 @@ public function functionAsciiTree(
/**
* @param array{0: string, 1?: string}|string $homeLink
*/
- public function functionBreadcrumb(
+ public function menuBreadcrumb(
string $delim = '',
$homeLink = '',
bool $reverse = false
@@ -133,7 +131,7 @@ public function functionBreadcrumb(
* @throws RuntimeError
* @throws SyntaxError
*/
- public function functionListing(
+ public function menuList(
?PageList $pageList = null,
string $filter = '',
string $sort = '',
@@ -170,7 +168,7 @@ public function functionListing(
return $this->environment->render($template, ['pagination' => $pagination]);
}
- public function functionMenu(
+ public function menuTree(
string $route = '',
int $maxDepth = -1,
bool $showHidden = false,
@@ -203,7 +201,7 @@ public function functionMenu(
* @throws RuntimeError
* @throws SyntaxError
*/
- public function functionPageTaxonomies(
+ public function pageTaxonomies(
?Page $page = null,
string $pageRoute = '',
bool $renderAuthors = true,
@@ -223,7 +221,7 @@ public function functionPageTaxonomies(
/**
* @throws \Exception
*/
- public function functionPager(
+ public function menuPager(
string $limit = '',
string $prevPageLabel = '',
string $nextPageLabel = '',
@@ -287,55 +285,13 @@ public function functionPager(
return strtr($template, $replacements);
}
- /**
- * @param array $routeParams
- * @throws LoaderError
- * @throws RuntimeError
- * @throws SyntaxError
- */
- public function functionPagesFiltered(
- array $routeParams,
- string $template = '@template/pages/filtered.twig'
- ): string {
- return $this->environment->render($template, [
- 'routeParams' => $routeParams
- ]);
- }
-
- /**
- * @throws LoaderError
- * @throws RuntimeError
- * @throws SyntaxError
- */
- public function functionPagesRecent(
- ?PageList $pageList = null,
- string $dateFormat = '%e. %B %Y',
- int $limit = 5,
- ?string $pageType = null,
- bool $showDate = false,
- string $title = 'Recent posts',
- string $template = '@template/pages/recent.twig'
- ): string {
- if ($pageList === null) {
- $pageList = $this->pageRepository->findAll();
- }
- $recentPages = $pageList->getRecent($limit, $pageType);
- return $this->environment->render($template, [
- 'recentPages' => $recentPages,
- 'dateFormat' => $dateFormat,
- 'pageType' => $pageType,
- 'showDate' => $showDate,
- 'title' => $title
- ]);
- }
-
- public function functionSitemap(
+ public function menuSitemap(
string $route = '',
int $maxDepth = -1,
bool $showHidden = false,
string $class = 'sitemap'
): string {
- return $this->functionMenu($route, $maxDepth, $showHidden, $class);
+ return $this->menuTree($route, $maxDepth, $showHidden, $class);
}
/**
@@ -343,7 +299,7 @@ public function functionSitemap(
* @throws RuntimeError
* @throws SyntaxError
*/
- public function functionTaxonomyArchive(
+ public function taxonomyArchive(
?PageList $pageList = null,
string $pageRoute = '',
string $pageType = '',
@@ -369,7 +325,7 @@ public function functionTaxonomyArchive(
* @throws RuntimeError
* @throws SyntaxError
*/
- public function functionTaxonomyAuthors(
+ public function taxonomyAuthors(
?PageList $pageList = null,
string $pageRoute = '',
string $pageType = '',
@@ -395,7 +351,7 @@ public function functionTaxonomyAuthors(
* @throws RuntimeError
* @throws SyntaxError
*/
- public function functionTaxonomyCategories(
+ public function taxonomyCategories(
?PageList $pageList = null,
string $pageRoute = '',
string $pageType = '',
@@ -421,7 +377,7 @@ public function functionTaxonomyCategories(
* @throws RuntimeError
* @throws SyntaxError
*/
- public function functionTaxonomyTags(
+ public function taxonomyTags(
?PageList $pageList = null,
string $pageRoute = '',
string $pageType = '',
diff --git a/templates/pages/filtered.twig b/templates/pages/filtered.twig
deleted file mode 100644
index 8ca8bd60..00000000
--- a/templates/pages/filtered.twig
+++ /dev/null
@@ -1,31 +0,0 @@
-{% apply spaceless %}
- {% if routeParams %}
-
- {% if routeParams.author %}
-
- Filtered by Author "{{ routeParams.author }}"
-
- {% elseif routeParams.category %}
-
- Filtered by Category "{{ routeParams.category }}"
-
- {% elseif routeParams.tag %}
-
- Filtered by Tag "{{ routeParams.tag }}"
-
- {% elseif routeParams.year and routeParams.month and routeParams.day %}
-
- Filtered by Year/Month/Day "{{ routeParams.year }}-{{ routeParams.month }}-{{ routeParams.day }}"
-
- {% elseif routeParams.year and routeParams.month %}
-
- Filtered by Year/Month "{{ routeParams.year }}-{{ routeParams.month }}"
-
- {% elseif routeParams.year %}
-
- Filtered by Year "{{ routeParams.year }}"
-
- {% endif %}
-
- {% endif %}
-{% endapply %}
\ No newline at end of file
diff --git a/templates/pages/recent.twig b/templates/pages/recent.twig
deleted file mode 100644
index 0fa87f0c..00000000
--- a/templates/pages/recent.twig
+++ /dev/null
@@ -1,15 +0,0 @@
-{% apply spaceless %}
- {% if recentPages|length > 0 %}
-
-
{{ title }}
-
- {% for pageItem in recentPages %}
- -
- {{ page_link(pageItem.route, pageItem.title) }}
- {% if showDate %}
{{ pageItem.date|strftime(dateFormat) }}{% endif %}
-
- {% endfor %}
-
-
- {% endif %}
-{% endapply %}
\ No newline at end of file
diff --git a/tests/acceptance/HerbieInfoCest.php b/tests/acceptance/HerbieInfoCest.php
index e5d46136..0d11f11a 100644
--- a/tests/acceptance/HerbieInfoCest.php
+++ b/tests/acceptance/HerbieInfoCest.php
@@ -442,8 +442,6 @@ public function testNumberAndSortingOfTwigFunctions(AcceptanceTester $I)
'menu_sitemap',
'menu_tree',
'page_taxonomies',
- 'pages_filtered',
- 'pages_recent',
'taxonomy_archive',
'taxonomy_authors',
'taxonomy_categories',
diff --git a/tests/integration/SysPlugins/TwigPlus/TwigPlusSmokeTest.php b/tests/integration/SysPlugins/TwigPlus/TwigPlusSmokeTest.php
index 261953b0..36f75099 100644
--- a/tests/integration/SysPlugins/TwigPlus/TwigPlusSmokeTest.php
+++ b/tests/integration/SysPlugins/TwigPlus/TwigPlusSmokeTest.php
@@ -69,20 +69,6 @@ public function testMenuPagerFunction(): void
$this->assertEquals($expected, $actual);
}
- public function testPagesFilteredFunction(): void
- {
- $expected = '';
- $actual = $this->twig()->renderString('{{ pages_filtered([]) }}');
- $this->assertEquals($expected, $actual);
- }
-
- public function testPagesRecentFunction(): void
- {
- $expected = '';
- $actual = $this->twig()->renderString('{{ pages_recent(limit=1) }}');
- $this->assertEquals($expected, $actual);
- }
-
public function testMenuSitemapFunction(): void
{
$expected = '';
diff --git a/website/site/pages-de.zip b/website/site/pages-de.zip
deleted file mode 100644
index 8955a7a6e43040562f916ce5a9ff2a44af67957b..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 31387
zcmbSz1yo#HvNrA>+}+*X-Q9u)cXtRb!JXjl1a}K=0fH0Uo!~CvZ|U^l=(K!3bf@edwQKu|#DyqbUUa0c)}{ELT^iJ_yBIlYbXAIwlm)s4^q>y`e(
zYW|T^PXJklLN@}c5nUacHZf6RddRIAw
zYP+mbopOAXZb*s_0=BPs2V=+5oO)*Noith@ddhAhs)#YLq6{Qdbh#Uy20*G;$$rXw
zVX63+%wU**mziEvMPJ3)&e7x#nVSz}j9LKemHs00_Y^sWKt@czHD>bI{-8i|9`
z^1#kOin-MV-P)>fG?M0Au*Q=Eeq@s$!81PDNmaXSJ83|^iS7o~OZ|+LZ}m|5j!A3UAdS$M=FvQh`y#mx3h(e2z8FI$T6@iTRFZnFbZVn3tdQGiKQ
zzZi+0&LVqE5*lbB=B7Oz%J%q$l4w4)E|?i086V_3I`|6`ep9mtSHnsF9s+nMd~xlc
zN9U~l(V#OZS;obgRqXA4J!7{cine&UIiB1kIyYTp1bX)u$Zn1|?YT&R|IB5F&>}tI
zSO#BtzkGgp{=t9*<%&t{mRSkEh7o{v(UEMr;h+Uv1_>;iP-ESR#vyZnYLh$Nvq?yZ
zWF5}%y1$nj9J_(9MhV!(-|w$GVCS&`HmR>KCnTbvqRH^5fz#{%eygK3-u}APMh0j`
zW(MyJ&g5j(&k)ta6#YPAF+nMiaDZ!YkOJ?}1V@2XHVC`?KsiH#z=TrK7-(fWX1gSg
z)Okr&1QjkGOsVer9*Bf-oiaJ8OFl@F4^pG+ZEDZ3_9>C
z<>fk+rHP<)VsNRE%TaIeE^c2uZ$E8qd#mmc#oSvX&{$F5G0>HM;qH81YenG;)N&6R
zo+S>KH+-k$9>g(LS{}B^A>{;Pv1K?**^v90`*O-W*C47i0Ur+&R@G=j&~gHzy#gs{
z+)%E-FFvaX$-aSku6J#%^9Pz(n;#(_lznX(8bU5Jmo{GzS{xdZv{oW2t5pU^(vwO-
zP`z@`AdQs5n|wY?L=9mT2Q&eCc2Otr2Ce*l+$ngZei6+|6DCp~uY`0qaLr8&2ClsR
z;3m0UoZ8(lNVAL*itI@fOmT6c)mfi+s%=Fx_yVbFW;9D9dL3`x&Cf08k;5p{REWBv
zhzaz%WDito9bJ2>x-^NAIBgffhuHgkTpcIl&=MhQj$?@$iyfki9qdycl+iC0D%ozO
zao*coiqM4CJ!?kr)45lHJ}t#wmjl-NLTmPA=6lPu#Wwrw$iCcBr|2Ob;%Ezf!2pn%
zk_riy+=nQOcGzJ>A|+d=Z#2PcusSA
zUO8n2jV0=V%#UU42;b4uSz}$?yv`6Q&!R&X2~Vqc7o8iS^_*rEC%r&1#l9%-<3O(Z
z6|^4Bbu}1yxGCae+d{~tazR#>S|!5;!#g>t&r6#I^ka7jK6;8;AaHV%qk`XOTyTJvM~4DzjeYe
z^jvW+j&*JTT}2S;E{9aNKG}ip^Vi`(xpR*;*B(km~HaCP~I*x$BlOqR`<6
z*1}t5lQByensA-Kud44251a5qK^&|n?fL?<8C1&B>Ypsc-b4Fr4ih8H1@05PdMC7X
zIzd4&AfQ(t^wT^2Jta^F_$~Oqypx5ksog(a(`!Zm_xsG?Z^8U*ROZXxzlQQD@DWEf
z4H{IlG(&JxeWoRjf
zq-MWJ(b7}V$;(Me(MqWyKtWI~Ur+I1iDKwxlEUTvaRrLsiokUMGQP_B=M?}R07X+N
z{}l;dpTqv8>vz_6W`E{jnOO2h|6IQWfuD>_{+5INDqsMUma0~NFQ>N#CR*!f5!Whe5bJVfNS3TmD}ep%o5
zPM{R0W?+-~cY?&4aAm6_C{G6ZGdR!I>e!5prI+W`li37zvk@USpwmj%Er>yIwP+Uk
zF{2(f-*+6DRAiY;1vD*Vm}4^q+nB3bsgQ3O#5di9ZRq4;oH>CTSPrPnE++WIOrZcuP`g7YP
znpKUI0PB_hqUWE8n)}|4XkdbjBvGCf0WL
zHYT>t|8$A3AbkbKEB%FMp<<0ZKqo8DXbOkIh2#r7ASmDcg7!6;z8&<}q%97((I2jD
z6$FE*kdZ&Gu5@^vs;L$B4GYTfPQ`^FA#RJQfveZ)$1YYk~N
zGo%l2AJmmD*_+c!35>DtnISx_yr2B8_jb^cEKFY!FTO*yPhekjB(
z^@$|@RB^10uadgRC!W5p<559aNp2w!lzvp#7P1Usd6QI@Zbb|fq03bdFWYvrcMje2
zmIYKu{PihuhI`FpqdU0%-c>#_MuJdymG~I@%ZiwMjnf~}9W9HLvPkYGMX^LA*R2uc
zb84bIFvI<&7HzucRg7;JHj@Ub@0R5Do+|CrtT9wp&`V!pb;=c9cd_FGF9j(eSfc%91b?{bKl62S=YM#!e>&>l*g%p>xBM0(QpX;RxVTcFC`#j$
zqo4(XByQ}DU$cYos{52Sr@V1nnA-4X7FT6PLkv1DR*T&+FFU;fk1Ps#?%)*r&?wvq
z^6-~~+Y^-cpFeL&C3?}`Z
zziEB*D-7+qeTtt$Q(20tGNECp=MLO@233)kO^Q{RptSuS0^i}1JPSP`24iCv03yjp
zqZC-BhK@twg?BqkBPGaCv7p5#
zl1az-uvO87`-4jaJbg~WQbFqGUW_BzBjZpknHs+eZ^h6qoEP}3
zUBZg#p;ZCw@^#;TT7)dO!e2p~7Vzp%i})kf{$dfi!qP^st6<{aItX+V-O(UKa6l70
z`jfGkgT|OfH;w*W-yP~8w^kzMC5DNSN*p-0p4t-Kt*C4WC=0=~9Pgk7?uLYuboP%b
z_hjv42>aRts7R}WII8g-p<6k1&X!C)<>!!##HV~kw`3Bmg?3|yN*o9iaWv_K2ldRP
zyY(MDAWrzWk9=|P7YgkutdH(0mD#IlJs&%(6h3%aqP>iNB%XCVUI>0~tgY33A&hg*
zN?KCoZZ|R*WOg;f=~ZXUzv$^{aFW(>gnq%s+X*u#8~7zy8BP4eO8*&SxCrA_ZF&(A
zA7%g`dR5L(wf#Ls;Q$8$!04Z?ra#oi%*e#W$i&1-XK85bV(92W{}-lS^A)7u=PkM_
zGBMMPNS(JDqc#jS--zie)Flb~L^jFLp^5qowG~k6qVX2wMSk$DeY05Dnd9F2x@P6t
zwnDyiydA`Nu_~~JIeu3n;5Prb@?(LVfdqlKh$FSlSw!G^w=wc*
z@oEn9oFj3IG#zh(qv`oaKg~fPOQJZAO_54_cz|XeeU?{>@wE-J46{lxLzWz
zGI)D>dDnRG?TQ&06U4YGB5r7Q)#N5=WH1fvhYD~J-2{7-Bl~?zGt)vPu-z3~5;qzi
zu#$l(#~toc&=q2o&?oXnXRJ`5a1ec>9e&k=667Szo1Ag}Qjm&Dwp`A6yi~F^Ek4Zr
zQ`eu*LRO&{L@l^Kmj0;qtyMm*xP@s7I*`5wg5Mh{j{FXc7^z3m@&9W4*#()o2u(
zC+TqVlWa{eI=MlS}yO&)xM9qIaY!vNqe*Vn(qq^ij8PsZ~s@c>T>T7CG7;
zeQOe>b*CohEs;N2I;89z4v>5``hs|mO>Ai|nmRn6YMV4A%!V}$jh#DeHfk|EBHa6O
z6m{G&a(Aw_G8?L3;>I`xCRyF=uS$s!xhDy9en+5GM;4gCTArrDR8nG6?Ir8d?@qqg
zP~c0fuak{d@=a2%n=tX$8y^p28{cBJXKV`xHxz*)ZeGIplsJYW`FwAo0KJhewce)A
z?^LHAI@kMdyC1QYuS)biXq41a5BpA?DgLGgi8n#{OxfC%szN3?p&5NvxbKD(Nw$Kf
z1ki9yDj2*_EXoeZ;1RKF`IW(Ik(~a`=C5_c1
zKQF@hEp$@S04!r|FF8idn+XB)x=rkDY~Na4p&7h;rKZx5lS6x^Vl^qy*s=bpLw9Q8
z@uXQs+>(b%=@-~nY@~;ttX2ZT+$#cpV#DZf>AMBs6{3H`1}76UGZP@|Ffy@uXX5x1
z9Iyajzya1P{Uzz}QI)Y;27u#HW0WpMw>Vt|nkXfNG?+h!DpA=pR>SD6XmTWJ)%oXB
zj`)maPc3T?*2@mlm_efi*;;RzHTS3)NP)Or76m-W)_ePhZ{|s7YWOk5>04u^QcIDb
zp%>((M5|K-EuKSUzUhK
zX)gEC(AYj-N3?O19PZod)h(c9@el{Nwjey&uowPN)U9)o&pI#z;-pqnFZe@o1&^)V_syEQ|$73sn`ctRtJOuWD_2=>fT{ROTuX0HdidH>$AoWT^
z2ICq(f$VoH3}Bt!u+hDsouQ3gyi4@WNXs88CD*nN;CX&`uqh`GLRaS&d@1mXnZ@fv
z$$kK4UXk$=GrIo^%rG&r)7jd&{(>1009HT&>y`e385`9vwo9)iC(TWA#HTqvR52tl
z$yjo_iTcnh^((~14{oJos$*4MT-)>FM`ycvWFntQu9>hESv`;xKE_|TabSH~&{v6uJw-78+?E>M
zHQOkK8$Ed0U>r=h$+?z{Hu|oJCU|
z`H)=`%lJjHU;!guQ)JQfpz*_W?CA@YXr$(fo3zca*a?cpc|{4e=xl~L82sQutmjF#
zLu;Is+ldrnf!s{mLZm&_A86C~LiY=`@Rlv-swa$b{VnBUc;DWT%cZ|Zy9_Ciq|o;p
zj9D2AZLwXaDoga6);A$!m@uUwoB|tyH|2*Ul!EpStsc7jFpJ|A93Hmv(3YPf-BSH2pS!iZ-2U5KBNqnDlhnq&mOo?3NLn~6iTPc0CptWKGCR_d
zGi$X>PMO677CjKOGe^LI983B}c2(3A+?O!0>pRY_l6ZE);+h`NWmDISR0q?vCU;ubJ2qD1@?W~f0TYq$|}ow4jP
zuv;=hR6m$e3mfX<)=AvA&{r%Ph{i^Mhbt)8sJ;=cN2f44;IoUKpB+hGO5>UzI9IYQ
z`|Q`Qvn_7_*oHTcgpm;1A74u~v2~N3l$rz)6pQ1dKVCP<`H+YvU-O>5$p!&AL=5k4
zPe6dd9$OGq!1*dHf|aWVuk4a6QgzaLXJZ$VzJGxXARqg;b`!#1VFu9L`Pp&$A3Hq1i6vtlUJW0j=FM5Lyrq)4jd<(ZfZnHzs?yp%^8dgc`ZEgj#4lF4ZK;9
zM_3ZxOOyZ!&$H%NJgJ&M80}am{k<%w5ECtQC5hf*=Z$0w101!PaddGT-SFa>W)mgi
zQg{EL*}9<3z(R2+gBK@1@f-L(%qY(ViIw26TLwOoQ1)X;Jd$+ITvjBjFV0_FCgO(K
z%*iQ|$D@v*J~$6|iWfI!+wRjNdtEVy*nkT%?5l%MZ4?(of0Fh^@2?{n7Sym*HP$W9
zS&%?Lp|)$>=a5B$+4dA{5sdznq#Gw~xD!I8-VgrZUERU#M+p^Uj~HRQ9Q(z2XskeS
zpuuwC%i@#WXyEyBjZ&1s=dNa}Q|_t||FrFtjs?CVb`Xg%PsHT6Hi(ihhQ5P2Q-`r!
z9&=8@`L*!hmaS?a1C$g=D)?Z7LYz;<3VlkX8bL3`gmb1{NY8`{M~|CLDc?YEf%ojB
zC}`}c-2kH`LTk=`L~@I1oLot;)@*(t*l18RQ104-C^C-Dr+K>
z+wY)}^3&DVOKJL624b0QEh;_HNcBTqneE;9Q-?-+|5HqV&~8epQ^Y-u$5RAgqKAID
zw!K4MMrMa`IUmu{uuWJd#DH?$u7-19V7w$KpFEmn!H
zekyY8q#+!MxpcrSk8Mysayd~Ojpw3)`uvzO!>yoA39%ro+Mtf7-)+2RKzV%mWmwyT
z_6$pWhvUv5^GTY4!0~!?zb=*d?z4}Rqi^<-s@}!^#>V!sd;DiV&Q!VC1?%v%EpvN{
z=}8-QG|`ton%I@iswEJhKtQi}`V(odU_Iqh|EnH;ef}%bSm=!GY@Gp(vOm%51x9EN4@%Pr-?|8D)*;~7qS=j!gwf*X3URy4&^gr@6`PF>lotid^zY$+yR$wY+?J4j{g5jS~Bi`
z)hgC6Tsi5C%uNiPoy<*4{-M~pe<=2q{zqXEe_{LUX0iP-fwp%x|8uh{|H1Q>{zsnw
zSpk2Af`4`3|6@#e9U%Z&{p%5ppKAS!>%R{0Cje(Oa1LdRUgvd$|Lci}zpL~0I06a4o_;wI@l&tA9F6#=X8%ufv;Xta
zh*wPhYDzz?{x9KvaVP(yE&VUq{>G#H*D2TU*y8<#(Z8hqjZ^vmk{IXTS^w6r{GVmU
z{ddOy?ppr8ME=d*{o-BzN4Bqi;P1KN6+93S!CwOZk{kY#(Y(pwP(u8iAV2h2f-?Sk?%%uWoMmFAL*&(TEF(?boloFO`@==mQ_
z#l2Q&al|%aWH}Q{a>NoQ8A{hd=yw=Xal+VV5M*t0kzeZ7X6<-M(0EA@6~9c
z2wZsKikM-hR95CZE?l-{hsL>QDxO~4_lABY_>tp_8aQeCWsFBTsH&!da#-?FT!}SK
zn$B4a9cJR)5K_N}(v`4BXfz5OKQpi>i<>Pxdw!q#7-|VLJu6fKxvoNWVw#f_Zcdmo
z9BgOBiGaM>D0W*%+Vz*Q69Huao>;sanLY)p^3bpFYp^mOBX__kI>>!5`ZgaO7%VDX
zu)SG_Eo$^3%FCVZ|4?(49OM;8n(WHAmn1
z9Z6Ept#roE^Rvbr#iOHAsePUz-C)_o!xHXS&SWl^L|~V6k@sFfg2IerM0$hn$)Pz1
zqJK6%AH0lr3Yz~sM+9#CsrjN+c~665c#FwG2`pS4NSV{A3T{+(Xx>zW3igx%3GqHjJMV#_XE!x4pg-{AeD6`Cl{sDET`~o7TP;=;kZw3
zgB$wn10P%*V~|K{Rjay5O>tO^luRzR$BTXQG8QGnVsc}bNMFYWm--O
z+JM;=8$!nR^jBzD?#cHlyb6_pbd3=As_-V|#5>3Rmuser-|6mX$h_B9e83M{kp(>4
z8czjya@6qmzKS-rR(QX;oqB8cRLP-RF0uf(9*;)D?>1O%_`Ycv6cLO5r1BA)a`=-v
zr48{QT9U0)>CStRTsxHZG^8JD3}o!fo&GHe@^V=5X#PQmNPvF$5(nKJ3)#F{H+d@r
zBpXzUw@Nv1;R~>=$j7B4c#JPwM|eJ1H;)2Z4UpA}=&D`Q%G+1Skj8HTABWjb4)VywlaDE_JN1^7I|wn9TNF@8w7Nx_u9VzR&x3l91^VBZif9
zR-w@HIy-wNO}sF8_h8SJ+>vDmKTy9%u}^88MUeiF10_E_B8SQaQ&5Na{ElY
zHG+HxBJPo8fW2M&VNae&ccI`%u1XHga~p|8Z~W8MJhV*JpWp6I0M#i>W<9#Zrd3~q>$71;gjk~g2V?t
z3W_kO&`4A2J7F2dn{Y1Vao_9f%YAUN{HIqh-aQT55_NrQA-#F}v75a%TsulCl{N2d
z6ZoyC4%_aujp$S9p>%?ffjqjH({L_Q(L4c%DtxZ>)16Vt8#LU6dYgBxyJua>?9@!m
zYPkEb7)pv*^~5+Z18#XVKeDLPH8o3M(~Ip;Ll8wZGaZgo9G8i&S~90>Mt
zG`e6UVi}_SN_W;#=tfr@frJRvvs}1u?Q9kbdL6KD!7=ZO%6S~@XKwI?J@XMv$%Xk&
zbPYx12ih;PUbY1}wiMLb#hCJ@Lb>X!ZO`>^j#RvH#~&mYgXbPZvX7Ai;&4NALw2J<
zDO*}lF~dQiHU*)a$5Fftbz+&8riYac<5)6J;5HU)sd5;mPi{S>xo_213|4#}&x|ke
zhn=x88t|u{?7zR9kRO?nrPZl_`LX*ZuYxD0ybK|$n3RE2tGf@em&lmU)Gl$ybc1kW0pD;5<*kW5nN-j(&WRAdYR0|C9-$4|@odtNyLNZo!8AOB1u
zep=2iS;T9K@*gTozUUgjK^HhtH{W1;==#7dKF(Fx`;Y*s#DVq2ex;Dj-L-N|Ww}lH
zTW4u1p)3$r`dMMwGaN(5tb$Sh|Sk;F=L2aU{
z&eJ_aQuSzZCVIt6gC%0K;g&l#`U$so5(<9b{py>z6sVnss$Lkv!U`>xEn7sG82ofE
z#T5>{5u3yEj@@nlUD$wm<3({|)oFBIExIVM1ospcoG6uQsdh#mBXGy
z4FzUOT9WXY6v`T|QBz)bIyjQ(w$bDmoe;Tqe~_iFV;1U4tL9UJJTM(St%b3k_hX-#Of}4Z)Z8WiG-_>|
z$w&+N*fe5DPQA0)LZh0_$W83}csG^wmWMKkoC_|PnII9RGANE%X}iXVj0tj$NhDBJ
ztdPnUV+28U4_CtIgDcOXbS4NI6>2s;?*P$`~*Z3WEbHVcT;*7(BjPDy~BR
z0gXp`jc?(DFL3As8+@WyH>S+}0Dg&%RxEKM%=BHymVol(qMUrj+cGiJrqx{iZm`@NK2F
z5E#YTd2cUwFUvAzi+dR|FrL48l#XAgmshm$EFXlf1=&nUPkm;sEL5%!gZaG3Oxg2n
zX5vqK&U1Q5gWH`Exst|tx-*rxNj3oHPMN{t!?w>hoRUQCrs^hN&T3V&vg$hR?$%@j
zQzzND4|$}?sv5#%<-Xb)(CGZqMbM7p%h%F=?+Rm>Cpl|mf
z@Yw*7=uvl6NV(|NzcMCJE>S>vCg%&zpu?Llz&7}Z`DXKx;9pMz`0-jzyl3a6!$o{#BVX!ApyvPmc5
zA15T5B^dI_4IW^mEiB-BZ(0Pif2^#kz&Cw!RbMpdW*ZKZ)AuTn9;kr7M6G4%VU)+;
z^{)ZuU-9l3=}uxkTD#v#iGxvub=&8ll>G=o3o6D-FUKmwC>E7FO%Y&|W|D%6CeelN
z{>WRM0{xQnp+n-%zmteQDRlEBwdr&IS&&_jW0ON8M(~vo6?i#00-?y&vo<8-%pBUl
zVUFda4#og%W{f&86h9Vt6qad95gP4UFt?hTGEG#PpOq-etYsi>M-5aqo`&k}s;DEb
zw8^LFVXP&6nB-thS5k-w#=v2HpW*$w<2=4*;C&HMD@d@CMGCgJ*1Ry!FUaok>!{|?
zu!fAaYHboJV3tM|dfzvR>i0xI^fGW$BXk*{G2`QK)60ye6YB22Z*E$?Z{gI9K7_l9
zUguNZhx!hO4)Y8PotijqwXvfq;zOS!ctXSVto{xqBxM|W`IOkB8crLF(RKjL)NB~H
zL%yFt=QdU!hl@VDY8DJ0uQ+K^aE~POOyAF){P0o_J*EweS(ZS%4Oit;>j~IZ5;T!C
z#t;Q0`={e8+wbG>Rm+x{`2HCc2=&DGaFxT=Jm&Yt>IkUimouRp+UWOQTnE*IO#T%i
z<|f~9=m@;R2Nc%FCt(n|Kc_-EY!*47fWL_EMcp5?ii3U8>nHl|z3e4$Txd`{tNgCA
zDp0pl>TA$WZtS*<4;Lqu4O>X=WeJb&$>-ksIDPJv>FuapUxsitv@O$%_0c20!aLRR
zIVE=XFs+!=nG0d|x?nd2DWDcLF2r6f>;#Sa0cpR4lPl_jyE{(abn2<%;)I^;6X|WI
z8jAh3;K7vx_cHsrK$E*OGlFk_9I7Y8)=WbJK=2i4zlY#wKyULuLy+}n@ck=w{Vxzq
zQj@crkp#qDjYJe8e^f-{XygbmWB;(Idg8d)n>qZH@9M`lC2g5R(HC|XIGhgY0t4kI
zSyiN<*7RGcsvVx!hiY73FGsD`E}%Q`%7o$j7OM+k=d$Y5SFQpDa%;0qxQOd|i}Pw(
zM96SjPi%VC=iQ$wcJCCd%$dH$fB3G}*533ZOnOI0GP(tNFaGnrvd3IO+a03Qn5!|L
zRit?PxvlMazXIjs+jtIWd8aKhc*&$RHiVWdp$0nmqFqamHBCpp((X)StPO>S*sn7#
zeljf|X1Hm2Gb~*TGGi*-NJ^*AZ=;1PCh{C41<;P$Pq>Mk7wn74wQfGx>&ISk
z%rLDK6m^6_Y?56!vK|Lk06Q~g+2k*R2#~G7N6gsHl}Jk`mbh;uQ60+N7L&jM?SEx=3#3{&Q-j@d)V_2PO4Y8cPkXRzFc>7+0FU!~v
zOv3;#KSH3ZM1-t`Dhh@0lQHdru8K*dfr5FC|dU1~lN
z-MY8r3%3HZeWi59^i#L_tYIn^pi0%CTN8#bi(_m}I4V=Do+qk7AgsS0S
zQ=6cT{*+VW^1#dpY!bHy)EKl4ad4i7r(w^+LZhAOO`fRy>qm3WlBxO?!vmLy#%wVf
zX-)OYIzKxGzNe=hFw%0E7QP1WcnmrAbpX3Oq7Y%Z&JsoyU
zBi0_sLsYCA-M}bH*MleGo@GMUH!Q6kuyw}1!M7Z@F~K$}s}2Sd^lGs6>K!(2uJ_+|
z-1Y1cKsfEV5K!sTSFZ!}tp^T$XXzg9j8KAd3GOkpYE?BVfz}$i`pq%Kc|8`(GSFrsl9RjucYIt%mByFOkCVb$5O6
z5SVY+Z@?n(HX?N6l@IY_0r){rwc4_1
z>4+Md!Ag%}Y*{qyc(M83;sa4Ed}x?aU!DCG>|=8U>VqpKI$da_JQ3yxobuG0ek_(B
zEtcI*4DHU=Q|GvV1Ur89)s9_|LkZ3f?6~aR>YazgsCwD1I@}*S7+$?U-#FMP&9F;B
z7DaoHExWZLdhI)h=+o8C6-fnUmdfymfhBc4t)u9(AgqQSF)
z_Bqj)F_$r-L*$70A+9A&h8Pv$7$!^6eSSSlQZ;DaBx3wEdT}^a~gwL;8OajxPhJS8(!~~TI&aB6jg~pS9h?5+3#T$!(9C0N0bmG
z95}ZDguE}3^*mVyal_qYQsUh7Q{ow37@RZcS
zraPcQgxbJvo>KOxV8t+b5|Dd+m@(Pk+hCGU;cdc+X#w9XRAY@QL(H>bU|n*!F~)fO
z2p|XzMQ&F&gf%ZkPouy#yJ?^wwjM_bZD?)ielb0Eld>?t8#w){o-MH)8tH|;Fme~d
zQm<0AhkQep7+{d#`q+HTBr@O#As<36rK8o;HLW2ZF7yp<8(DA;;d5o~(7f-IsspnA
z_3mPFIP`b2IPE*n+LEA#NLV?uF5JMmRBwR2>P0qP-omu
z_sM}WUM$=ws8b@qog}^~frx|=T$)qG()6fbSQ}inLsZ|N(vG@D8mF-f4YH=EyBf9*
z%6rBHTQYxj7eOtpQC7)o-P6Xi^XIgd>5i
zogyjM5%}jE{Jh={q5YmsI6b;B?>2srGzEUk)FeiH(O`uSJ@qm+jLEWhkpMfL`I^8S
zKqL)L?YB2BE0)E*%R~)q$MiHS}pA7!j+;OF0v7sZ6y5F<0U0H
z-_jM(crQ{4Pr8{6+1d<-pwzT6MmF+mPT^d$CCZG?sj~yyc`ppX!0VUbhLc)H$&;co
z06JiwY6LXU8r^?ukMV=ehIyI)f$kHu4QYSQzQ7N@%uu39-yv+74s-l#cNKbfiL#b>
zlvS{__iRXBfw|cA>JTWqgk=PM9P{)On7-y!Zb0!h($g99d3QaF+Tr73*PkSA;ew9Y
zP1&`e-}=PXxpQ>Rgxm&n15Ib}?41~N#SX?98ao)H#qVNC<@w0+*|ppzkBrYTro}l-
z;NMbCC@NrA!v%Aekb_-a$XGlu=MQL=Ml@iFtV9GX!`Th6*i@dI1*SFk8R8|vpoAk7
zQh>d?T&vC*+MT1?)u_(-Dn?=`l2qsu^~~s??r>>7HE<@Ok!(z%eAoUXvf*jXpG}6Z
zMPWjbeF0RveCb>#9y7U-0zQo=Mj&XnqSe-IVk5$*?VH|GJ?K4lGy7Ql_2we0DLxKS
zx?3tEKK=)@=ebb57YW{#@)5kf-d4TH%?PQ-82o%bY>RG>X?KP#>$4YS(})qnQbSJ$
z4}x>1w@bsmuVr(auwV`&pk#gx#lH{IDZu~UGyFL*{!P#DKg?mpVuY*!J;UJBA86W*
zR*PP_jB^dB0|t!WOpezF%1AbcO6lCJKYwcaQBw*iYZBI`y|NEm*@aQ;f$ehLH?0Gn
zKZv2PzcaE-8he&wPQRq;MxTyGQm;CV1%GQiB!`0)`;k{~?CdRyx4~kzLT7chzt$TC
z;u3mxupZKhw-8JEjkk>!Y;hZs=;}2D?*>>|Ag=fXS$qV0L~?`Hl@^gr_#;aj^1Ugg
z@2#~Gx?F_^-v-y+f5yw$Z5LflU>JrG8y|;3L3L&PmSJ)+cLYlvl0!lH?c-w*Oy~4)
ztzN?<$c5X0Hws5C=Zud<%B&H2w}&Y
zi=x$`wbxr3Up4$w_kTaDvkYis{@UsP*RlF9`hPvG^BJ&yb81I7nh7?L5h?igDZH1s
zUSyP>>1~tk3ak*rHQ{W0hDgni+brOeRcGGS$GiHu@DC)7_HwDnC(j?lu+*-yJvPuo
zS~Rq^53kk~T|dbCFKdf@e1o(FYaT$WaCxK9uC!~HGxTv>4F#8+jQwpA^XbP?cU!zQFOwzdVtS4*@3{yLWdxZc-m
z{;7?>H*hckc1rt8y7;f!V0}GrWolvO;%Mk>VQ2fl$QcV&|M_JS5R4!^ep0}Et#Y6X
zwO0AILU$DWVB)o?q1)=^h1EP(WXzj`hf*9Jnx@I|bkL3gdEAORC&$OPEG!mjs?xBs6pn*ma;OrwBpzA4sA9C4d?b6ET8i7S5mn3YPOBwt*|%NphWsem+a+zP
z-w<-2*#3}{p&q=!VZyt;*Mf9jK&ukeg{qk)4UZFK<+wP9Z`$1r={);RuZ~(m3gqc%
z@4mR**9jkE9)qKpp}cK+YpnnKtVu2E=}x6{())0E`(e5iYE_mQFgE$bOJRnErKJmF
zCWhEs#vCKJ$ANauS}acOC#!zU8&O)fr|qv#hAHY+S{Bd;3ul;&2&;AceIEQ?a?Q1-
z74>Lu`2(rBRk|)+;GQF4L7?Xj8Pr#qGplt*;i1W!x86?TSJop9x;n)h73OFkFj{8}
z2zQB>Mk_sj5bteb*zNfye6r|k-&dkdQh5nI2M+fj%msEcAh9H~vte3xjp=P+z{x|7OTuukh8sa9uq
zjbxX3{&;rcMu>4%{W!kD9A}$vTO1M1)Ay}vn>y6iis2+h_=s!ea@A*w@6;EKS6Ig=GFo5!-j@JwA-!o%4PRkYc1_KHb192(>56)y
zPCYjLZu~OzQ%T?0#})bnr`{P&9$mG_?f&d2J$;j_Wes}Op*(?3e@J>sd8QDKHRAh0
z2_(?E@vg{Fr8T!Pk7@zyX2iIgwVtMINCi|j{`7a}TW4F1Y>-y+rihD5in|3aAJe-E
zQ*x7#$#&cg8McB1rg;N(Q$BJres;kgCYSc=haFYtA9rFaeN53|0MvD_aQr<`GhhKtp#KU~HacSqM-wB!mkoLR
zFF^WTT@G+)1$FfZwF3T>mP>4sK5`gHidQI-oywA8Y^tb$1H~vDRnii5iETo}eIeg@
zK7E_?S<=F^pr+`cHUb+o(9_rZ)XO(=i_@`3ireIKd<#ijlC#o@IBp}3
znPN<$`Mpv#=0vD99LCB*$FoZ^H*v}|xJ-t4Z^Czszk#EXYQg#!CI=g}YoRAPYQ_+U
zd|upFNNlnHad9`8GPrhbv^s)dAx1r4M8SX4mpmni72#+#yZ|jeP!~_WkG2z_Fp)5I
zPD{d5-_WUDlEF{mq9vhprNr>^FkP(^OXfO&2d!M8bPvV$Zca(+&>boU65L7|$o%6i6U$x1GyCyKFul?vIdFW|gE_
zUpbIRGZx-ofmk)1c802-y%?|GANM7Bsl7j=W*9atB#L7%!<5-7|2#g;5k0C?cDZ!o
z?F;yND}1-*{7seYyO_T0N=L&=WdzA@lf44{v0u$n$1UFb63~)`YxLpcn^O3Pf4MBi
zwpzeFfn3O)m~-L`L-io=!st3&9_%(Vh(_V$h07WQUC!IjWJgOe)<%&O;Gh!fs|lyM
z@&`9XK{N6xn`A+2yFsrEC08Vwb5q-o$B|(FFzy|a@7h^+nD=JSbUxMGG2{&R_U@F)eI7yj^
z`k>K6JYLM4ZXc#GJ+8$}KM^fQeejv}gc+Wx_j$SK>yjBOv_b1J%Ffgquu=3a689#b`!`b%Bfi{fQ~@gccCT~S^RCVhDKE#G`n0K}n
zy<pQve8*k=pJIJ^HxH|+Lm
znBNgqZ=q~)UQQ;emjE{jKXd~@un?XI`?BG=d=ZG=3;b(RK+Itlegp6|uO8+1zGeh)
zgEGy3^))PjbG=T^hSt{q+ngXOLFV;NsE}LUexL>LTzFJ)Z76g9UEpTHK8YJ-ts|znKn8jZ3_;o^e8r({4F9?@$QACYE>Ij6gsNr@f6R+o;(k
z2*2+GqX$C*?3ye8J4u>T@)#b_M=>9XNTQ3Iq-?PQWfnM@IA;eR&_H;!kLaSRHY4Hz
zDApBR%iwKW@0jeBt+Kq3NaPHVSPkAb_fKduBT%qw|CvXfnQl}4mRv}bFPv6hk~Yl}qoHKnwO7BPiy6p{aX`M>7Qi}}&%8S>2YoXy@ft>QjR&2zGj^8fq+bud@z|mq-&y}*9eYTA%vv*-i%&%alL)mYF2*5-
z%Chm@JC$)^BbJ5(+aB%w6L`l(xnA-80q1{(Kb?r~uTbGu)weScUGiI~%|33p4gZ-?
zV7_@^y@=$>Pq$+9qu-f}WJ&wtyEYvj9gqL&UY3IqNHG(L^6BGW4jCQm>Bhe--pkk7
z)&&^?-jjqKbWTw%h*eQd>YxsArPnD%Q!YV~>;+7C?K9OKn{!_ep7x5~*d!Kz;N=zX
zs%Rs*ZVM(=5kIwz8ySU?Ra-KZ-`0=v*J|OVx=ew#Z$_Gkdkw@}qX;kCb(EMtUzwy;>{J*c7F4YWVf-=ley?kMB!h
ze83=)qo_#;SgEG3YU8vVx9KC-h_w6ppccU+Hye0zHcQELI0puQbsuAC`BnGWIVSDq
zv!SxQ$J^c%Jw7soS8H2i%H=QSaO&EVK9gadtdt{5D+;czf4FLAYE96nbfZePu-g$e
zv6g?V1Pb+Wahq}^4F~#y*jJRj$aPG_`)}T4$IG%6Kgc2{I(smcDkz!A{d#bz;;`}ojbA%d
zZ^w}K@K;3C|05di=wrG`woKIR^7ll$^&^suBA&8~mJ7!g9qDvS=HxgY&HIYgN@aCy
zbz8eabpqQqN#A=;+O=9G_rzmFzU{o+t9nuGfQ+2emldjsJwYU1<2=iPOUXuk;}4UBPa;18IAxTN)pe^bviXWDynyUuGG0%EsaO$
zE-MT^A^eu_iCSknIlR2v8Ib0%vayVmS4blb0F9tF53UetL52p%=!ff0XwtYb?E^I;
z1ITBZT9IU9J&z=H&f>b;S=ku{n(E&h_T3X`jouz?mY%bdcDR(Nc8Iy2{X4G6+QK%qODt`
zqWV|5O0aJ1eSRr+aKjhQ;53~@-onGQ+j_)Uyv4+s@C`7Bdk)@$C!_PYfrf?#SPE
zhPcL{e(Br0ZRv^0q-|B9jM?HpTJX{b3=(La_*Mm2baAQWMr-c*`RfoVbFWA|HZ#
zAB4Nr9uTH)8WW`~QoyFak3l>sf_V+m4VqKPx-lxB;c_&JK_?qQOTCCX15bby&b^qL!qnDp#ERE1nqJ(+`h39d+`L9lGQ!=k_Pn|8{U=EWuw(GVuNltrPp7zEzdE
z=Qr$Fq;cmD2rp3SY9=_!aR!{?3kgM^_IUYuEi$LV`3Ts?ZN6M=Z1Y4hO@AB~0~)9@^+6@8z^y
z5%r{Ym!Yd@svt`!yMsy8=@9=5%Wu8#J{r3=nW>-aX4zNfJ3re;brim-!m!;Q98ueX7>L#=Of-0RC3RjtW+X|~GU3K;^=?_V^wkK{SY{GjFoQ-yD|
z#XIlyVLk(WJ`(eI7)G`T^e$mL5N0aQYS7#NCo!_N#@QlK>#AJez#a&Nk-x5`zMs?%;uBdn??L$F7eoZ`_G+y02H5
zS*P{AqcyyPo1vQN*YVnp$IJ8P)tz4)^}cUF&sX`mTNQ(7-uYu5oewsNjY?GIetxp7
z|9pDd$+IeE0s76AS6{yq$bVZ>aKZyj^DhUODw+^q0*_IB2_OE+A>UwASE;_l%<*)#
zH}+8k{ZbiD&7Vr)qAkVh{%H&jJa?^wNb-F-Jo@}krII{@h=L23Nsa|Kj)mY@9PJ{7
z6ZV(d#M{2JyT9~0lcEph%IeCR_&Na&G4&L~0IT&!6gKL5mJ}>0@yTac@0#P@wx(y_
z*)LVnk?;41B@->VeWW!r9_xMm(l)OyS%%p|WQ7!$aK{_dX7{(hSByNdRNcUr5F}vx
z&m$$imU^{8?*P$Ufz9u_tPa?kZytN~PlWBje21MXCHIo!J6VkV8|w_t5(Ret9N!#T
z`l+atBTfUZncit>$kq|NHd37?i$|E;+~M&{$8QIX9`8er?-35Kt=D?a=dFq)=N%v!L0`jWf#4H8ojc^k;=$fy|drO&!H+yL6;Z2%Qw)x4Wd9q{|swc8=1qjO>;j
z`uyfT-hpc-p@PeA)gFGwH=iT1
zX}KZoBJ`C%YI~XA1?f-!nX9&?ez0EW@pAEAF89H;3Z_E2{!h!BzcQ)}H}xfaeZjTz
z_P?)uWM%u+oGQJp^bH>x5w>5Grkz}R>|?;m){mB!=2z=9jGT)*J&OO$%N%)Pv#Eb<
zQN@`MrIfsc(~-J@N*qmH^}d7S9cfc9>t}{^BIvH^JMucx&Daw)YDdcB-JI?0T
zy^%zT$=R4rZ$dk<-Wpw<3LU(GgI*fm}=HLs7
zF8`x@e|IzMhHA)u6&nPEB#D5?Xo^bd!^sn(`*{#L&l4hB64^_rMG83E%u7p
zt@qugtVV>V>9!GLKhDTsEp@P_Ct%N4;$GI`=q1-f6oYaYf^AO8IWKNyjMC~?_x#a^
z+;E6qCQp=xbi#UFL5QrKmdIT8vo
z$?va;$9k39*>6bJTeav+Tzd8+hu(&f0jZ?Sb|;_J3IlH_l#DCh7hUHMaF?@JpOP3Q
zRS-Mdn?4;}F~IlphiJ#P1~nqFAuRjj7CSDr`VSpNE1UiVSZa$I-`HRqywJvXsQS*g
z+Rx@K!_V@cd@MOPV9H;f`!LaIa8$s)uUcWq>!h*YlaFWpOh?DpLmj?vB_T)@gKnjE
z_z!436hywAd0Vyd|JOrouOC2G!Gp*L{Kl+?dQsz(5>maw(QeGDSN#%6;+4U5Tc=V~
zn|Hf2-EwpFwO|YU8Q8_4@~1J?%Bo3zyV+*nUaxlHqAcD@&A@~Y=E_-p*WxOFbd2^2
ze9>FA?s=*;@4QU=cAUD|yPIavG+129(pNkV(st)VT@m({VXZ`)Uem*8yMpRF6&~zx%
zRKBAI0B!Id4g9?TLZJ{s*ii$h96NM~LSe-)Y2sAH&n6YmlI58?jIb?cr)lw0gb{qg
z<#w}SeWtn_@IJ#N#enx26*9?eQZ35hItvzP*c~vb4^Ru3j!~fyo+9Vt6Rn;o>KdN{
z=<*&@8xEL{VKQOb0AI|BYMwn0GTiRz2#KlfZkg0RD|%vTqd_Oa+_`|v0~Io96;eAn
z;f}e|6{AfD(-**inQ>_ylduTIKzsCmbMj)f!z`@~$5OXANg(1Kwg^3-(BN{4Xk_(bmG|>-#Pjm{S0kTM#5)Y6?qCzG`aAVQ_f;tk0
z13Y^$ofs`#A#N(%oLTo!IA8^KVgejxs89&s_)s`xVxrEbbdFo;>4ukL3PG74(hbcZ
zvs4cARDcGbq#
z*t!Pw5w>o2+zz_jP7`(jo!CC6#fZURQ1k4@G3Y$d!FIqIWB?Q18Bqv57!2ABs&O2U
zJvJlv)6BNO8w|u>g0%jEuMFm54Sd!QtO49As89%T7!;b5|8W?)+)z|w;G<8Vp0;E9
zFfi1|)Nu^DTv1dEZ0FNDOj8JT7&5@88!EFHjbPaVbVo1|5{yD7#ZN_{-F~BtN8mT+
zaSIJH6b0UXgJULC$fU2rQ+Ah=Mq&5iDBv77nzV6nT4ajzsDj}EdqQ>s89&8Q=z6EsefS;;8#M0Lg=3g
zG6RpF6L$5P8{Y?v2m%8pOrYJneUX|85n~^4<_tU$Fd86XfQz&N2?Hu*Qa5tR
z3qQb62k+ldGQhaNO1Lr=)Sse4CVfO+c`-fi91Fs+kZ|=IEu<52mpwh?91CEvkZ>+P
zxVb}xO!8Nm33ARwc34n2iJdlp_%&!jsT1Wi0rWqn7cfA;wgyfTryU?M$XONaRoeLy
zgGeV$9%~<*?Fy35Q6ZC3H0dGEJrx~`4ClUqvwu{`B&154j;(Xct;M3k8Assm5*0G3
zP>&w!oU`n(z;Gf8I3z{|0XC!uJje7VEG(R00jt4^6&WyFiltered by Author "{{ routeParams.author }}"
+ {% elseif routeParams.category %}
+ Filtered by Category "{{ routeParams.category }}"
+ {% elseif routeParams.tag %}
+ Filtered by Tag "{{ routeParams.tag }}"
+ {% elseif routeParams.year and routeParams.month and routeParams.day %}
+ Filtered by Year/Month/Day "{{ routeParams.year }}-{{ routeParams.month }}-{{ routeParams.day }}"
+ {% elseif routeParams.year and routeParams.month %}
+ Filtered by Year/Month "{{ routeParams.year }}-{{ routeParams.month }}"
+ {% elseif routeParams.year %}
+ Filtered by Year "{{ routeParams.year }}"
+ {% endif %}
+{% endapply %}
-{% set items = site.pageList.filterItems('recipe', 'recipes', routeParams) %}
-{% for item in items %}
+{% for item in site.pageList.filterItems('recipe', 'recipes', routeParams) %}
{{ page_link(item.route, item.title) }}
{{ item.date|strftime("%e. %B %Y") }}
diff --git a/website/site/themes/default/css/styles.css b/website/site/themes/default/css/styles.css
index a2cd44ec..ac8bc05a 100644
--- a/website/site/themes/default/css/styles.css
+++ b/website/site/themes/default/css/styles.css
@@ -256,7 +256,7 @@ table {
font-size:0.8945em;
line-height:1.7;
}
-.sidebar .widget-blog {
+.sidebar .widget {
padding-bottom:2em;
}
.sidebar a {
diff --git a/website/site/themes/default/recipe.twig b/website/site/themes/default/recipe.twig
index c36519bf..416de85a 100644
--- a/website/site/themes/default/recipe.twig
+++ b/website/site/themes/default/recipe.twig
@@ -13,11 +13,25 @@
From d6cf67bd38d6a1449589d08498984b3e57dbb363 Mon Sep 17 00:00:00 2001
From: tbreuss
Date: Tue, 6 Dec 2022 22:45:18 +0100
Subject: [PATCH 02/15] wip
Signed-off-by: tbreuss
---
plugins/twig/README.md | 19 +
.../TwigExtension.php} | 244 +++++++++-
.../TwigPlugin.php} | 11 +-
plugins/twig/config.php | 10 +
plugins/twig_core/README.md | 19 -
plugins/twig_core/config.php | 10 -
plugins/twig_plus/README.md | 19 -
plugins/twig_plus/TwigPlusExtension.php | 422 ------------------
plugins/twig_plus/TwigPlusPlugin.php | 40 --
plugins/twig_plus/config.php | 10 -
templates/page/taxonomies.twig | 58 ---
templates/taxonomy/archive.twig | 14 -
templates/taxonomy/authors.twig | 13 -
templates/taxonomy/categories.twig | 13 -
templates/taxonomy/tags.twig | 13 -
tests/_data/site/config/main.php | 2 +-
tests/_data/site/pages/index.html | 2 +-
tests/_data/site/pages/plugins/twig-plus.html | 4 -
tests/acceptance/HerbieInfoCest.php | 42 +-
.../Fixtures/markdown/config/main.php | 2 +-
.../integration/Fixtures/site/config/main.php | 2 +-
.../Fixtures/textile/config/main.php | 2 +-
.../SysPlugins/TwigPlus/TwigPlusSmokeTest.php | 35 --
website/site/config/main.php | 2 +-
website/site/data/plugins.yml | 19 +-
website/site/themes/default/blog.twig | 26 --
website/site/themes/default/recipe.twig | 7 -
27 files changed, 298 insertions(+), 762 deletions(-)
create mode 100644 plugins/twig/README.md
rename plugins/{twig_core/TwigCoreExtension.php => twig/TwigExtension.php} (63%)
rename plugins/{twig_core/TwigCorePlugin.php => twig/TwigPlugin.php} (77%)
create mode 100755 plugins/twig/config.php
delete mode 100644 plugins/twig_core/README.md
delete mode 100755 plugins/twig_core/config.php
delete mode 100644 plugins/twig_plus/README.md
delete mode 100644 plugins/twig_plus/TwigPlusExtension.php
delete mode 100644 plugins/twig_plus/TwigPlusPlugin.php
delete mode 100755 plugins/twig_plus/config.php
delete mode 100644 templates/page/taxonomies.twig
delete mode 100644 templates/taxonomy/archive.twig
delete mode 100644 templates/taxonomy/authors.twig
delete mode 100644 templates/taxonomy/categories.twig
delete mode 100644 templates/taxonomy/tags.twig
delete mode 100644 tests/_data/site/pages/plugins/twig-plus.html
delete mode 100644 website/site/themes/default/blog.twig
diff --git a/plugins/twig/README.md b/plugins/twig/README.md
new file mode 100644
index 00000000..11e1b89f
--- /dev/null
+++ b/plugins/twig/README.md
@@ -0,0 +1,19 @@
+# Twig System Plugin
+
+`Twig` is a [Herbie](http://github.com/getherbie) system plugin that brings support for several Twig filters, functions and tests.
+
+## Installation
+
+The plugin is installed already.
+
+To activate it, add `twig` to the `enabledSysPlugins` configuration option.
+
+~~~php
+return [
+ 'enabledSysPlugins' => 'twig'
+];
+~~~
+
+## More Information
+
+For more information, see .
diff --git a/plugins/twig_core/TwigCoreExtension.php b/plugins/twig/TwigExtension.php
similarity index 63%
rename from plugins/twig_core/TwigCoreExtension.php
rename to plugins/twig/TwigExtension.php
index 76510806..2b84e1bf 100644
--- a/plugins/twig_core/TwigCoreExtension.php
+++ b/plugins/twig/TwigExtension.php
@@ -2,15 +2,21 @@
declare(strict_types=1);
-namespace herbie\sysplugin\twig_core;
+namespace herbie\sysplugin\twig;
use Ausi\SlugGenerator\SlugGenerator;
use herbie\Alias;
use herbie\Assets;
use herbie\Config;
+use herbie\Page;
+use herbie\PageList;
+use herbie\PageRepositoryInterface;
use herbie\PageTree;
use herbie\PageTreeFilterIterator;
+use herbie\PageTreeHtmlRenderer;
use herbie\PageTreeIterator;
+use herbie\PageTreeTextRenderer;
+use herbie\Pagination;
use herbie\Selector;
use herbie\Site;
use herbie\Translator;
@@ -30,18 +36,14 @@
use function herbie\str_trailing_slash;
use function herbie\time_format;
-final class TwigCoreExtension extends AbstractExtension
+final class TwigExtension extends AbstractExtension
{
private Alias $alias;
-
private Assets $assets;
-
private Environment $environment;
-
+ private PageRepositoryInterface $pageRepository;
private SlugGenerator $slugGenerator;
-
private Translator $translator;
-
private UrlManager $urlManager;
/**
@@ -51,6 +53,7 @@ public function __construct(
Alias $alias,
Assets $assets,
Environment $environment,
+ PageRepositoryInterface $pageRepository,
SlugGenerator $slugGenerator,
Translator $translator,
UrlManager $urlManager
@@ -58,6 +61,7 @@ public function __construct(
$this->alias = $alias;
$this->assets = $assets;
$this->environment = $environment;
+ $this->pageRepository = $pageRepository;
$this->slugGenerator = $slugGenerator;
$this->translator = $translator;
$this->urlManager = $urlManager;
@@ -92,6 +96,12 @@ public function getFunctions(): array
]),
new TwigFunction('file', [$this, 'functionFile'], ['is_safe' => ['html']]),
new TwigFunction('image', [$this, 'functionImage'], ['is_safe' => ['html']]),
+ new TwigFunction('menu_ascii_tree', [$this, 'menuAsciiTree'], ['is_safe' => ['html']]),
+ new TwigFunction('menu_breadcrumb', [$this, 'menuBreadcrumb'], ['is_safe' => ['html']]),
+ new TwigFunction('menu_list', [$this, 'menuList'], ['is_safe' => ['html']]),
+ new TwigFunction('menu_pager', [$this, 'menuPager'], ['is_safe' => ['html']]),
+ new TwigFunction('menu_sitemap', [$this, 'menuSitemap'], ['is_safe' => ['html']]),
+ new TwigFunction('menu_tree', [$this, 'menuTree'], ['is_safe' => ['html']]),
new TwigFunction('page_link', [$this, 'functionPageLink'], ['is_safe' => ['html']]),
new TwigFunction('page_title', [$this, 'functionPageTitle'], ['needs_context' => true]),
new TwigFunction('output_css', [$this, 'functionOutputCss'], ['is_safe' => ['html']]),
@@ -301,6 +311,216 @@ public function functionMailLink(
}
}
+ public function menuAsciiTree(
+ string $route = '',
+ int $maxDepth = -1,
+ bool $showHidden = false
+ ): string {
+ // TODO use $class parameter
+ $branch = $this->pageRepository->findAll()->getPageTree()->findByRoute($route);
+ if ($branch === null) {
+ return '';
+ }
+
+ $treeIterator = new PageTreeIterator($branch);
+ $filterIterator = new PageTreeFilterIterator($treeIterator, !$showHidden);
+
+ $asciiTree = new PageTreeTextRenderer($filterIterator);
+ $asciiTree->setMaxDepth($maxDepth);
+ return $asciiTree->render();
+ }
+
+ /**
+ * @param array{0: string, 1?: string}|string $homeLink
+ */
+ public function menuBreadcrumb(
+ string $delim = '',
+ $homeLink = '',
+ bool $reverse = false
+ ): string {
+ // TODO use string type for param $homeLink (like "route|label")
+
+ $links = [];
+
+ if (!empty($homeLink)) {
+ if (is_array($homeLink)) {
+ $route = reset($homeLink);
+ $label = isset($homeLink[1]) ? $homeLink[1] : 'Home';
+ } else {
+ $route = $homeLink;
+ $label = 'Home';
+ }
+ $links[] = $this->createLink($route, $label);
+ }
+
+ [$route] = $this->urlManager->parseRequest();
+ $pageTrail = $this->pageRepository->findAll()->getPageTrail($route);
+ foreach ($pageTrail as $item) {
+ $links[] = $this->createLink($item->getRoute(), $item->getMenuTitle());
+ }
+
+ if (!empty($reverse)) {
+ $links = array_reverse($links);
+ }
+
+ $html = '';
+ foreach ($links as $i => $link) {
+ if ($i > 0 && !empty($delim)) {
+ $html .= '- ' . $delim . '
';
+ }
+ $html .= '- ' . $link . '
';
+ }
+ $html .= '
';
+
+ return $html;
+ }
+
+ /**
+ * @throws LoaderError
+ * @throws RuntimeError
+ * @throws SyntaxError
+ */
+ public function menuList(
+ ?PageList $pageList = null,
+ string $filter = '',
+ string $sort = '',
+ bool $shuffle = false,
+ int $limit = 10,
+ string $template = '@snippet/listing.twig'
+ ): string {
+ if ($pageList === null) {
+ $pageList = $this->pageRepository->findAll();
+ }
+
+ if (!empty($filter)) {
+ [$field, $value] = explode('|', $filter);
+ $pageList = $pageList->filter($field, $value);
+ }
+
+ if (!empty($sort)) {
+ [$field, $direction] = explode('|', $sort);
+ $pageList = $pageList->sort($field, $direction);
+ }
+
+ if ($shuffle) {
+ $pageList = $pageList->shuffle();
+ }
+
+ // filter pages with empty title
+ $pageList = $pageList->filter(function (Page $page) {
+ return !empty($page->getTitle());
+ });
+
+ $pagination = new Pagination($pageList);
+ $pagination->setLimit($limit);
+
+ return $this->environment->render($template, ['pagination' => $pagination]);
+ }
+
+ public function menuTree(
+ string $route = '',
+ int $maxDepth = -1,
+ bool $showHidden = false,
+ string $class = 'menu'
+ ): string {
+ // NOTE duplicated code, see function sitemap
+ $branch = $this->pageRepository->findAll()->getPageTree()->findByRoute($route);
+ if ($branch === null) {
+ return '';
+ }
+
+ $treeIterator = new PageTreeIterator($branch);
+ $filterIterator = new PageTreeFilterIterator($treeIterator, !$showHidden);
+
+ $htmlTree = new PageTreeHtmlRenderer($filterIterator);
+ $htmlTree->setMaxDepth($maxDepth);
+ $htmlTree->setClass($class);
+ $htmlTree->setItemCallback(function (PageTree $node) {
+ $menuItem = $node->getMenuItem();
+ $href = $this->urlManager->createUrl($menuItem->getRoute());
+ return sprintf('%s', $href, $menuItem->getMenuTitle());
+ });
+
+ [$currenRoute] = $this->urlManager->parseRequest();
+ return $htmlTree->render($currenRoute);
+ }
+
+ /**
+ * @throws \Exception
+ */
+ public function menuPager(
+ string $limit = '',
+ string $prevPageLabel = '',
+ string $nextPageLabel = '',
+ string $prevPageIcon = '',
+ string $nextPageIcon = '',
+ string $cssClass = 'pager',
+ string $template = '{prev}{next}
'
+ ): string {
+ [$route] = $this->urlManager->parseRequest();
+ $pageList = $this->pageRepository->findAll();
+
+ if ($limit !== '') {
+ $pageList = $pageList->filter(function ($page) use ($limit) {
+ return strpos($page->getRoute(), $limit) === 0;
+ });
+ }
+
+ $prevPage = null;
+ $currentPage = null;
+ $nextPage = null;
+ $lastPage = null;
+ foreach ($pageList as $key => $page) {
+ if ($currentPage) {
+ $nextPage = $page;
+ break;
+ }
+ if ($key === $route) {
+ $prevPage = $lastPage;
+ $currentPage = $page;
+ continue;
+ }
+ $lastPage = $page;
+ }
+
+ $replacements = [
+ '{class}' => $cssClass,
+ '{prev}' => '',
+ '{next}' => ''
+ ];
+
+ if (isset($prevPage)) {
+ $label = empty($prevPageLabel) ? $prevPage->getMenuTitle() : $prevPageLabel;
+ $label = sprintf('%s', $cssClass, $label);
+ if ($prevPageIcon) {
+ $label = sprintf('%s%s', $cssClass, $prevPageIcon, $label);
+ }
+ $attribs = ['class' => $cssClass . '-link-prev'];
+ $replacements['{prev}'] = $this->createLink($prevPage->getRoute(), $label, $attribs);
+ }
+
+ if (isset($nextPage)) {
+ $label = empty($nextPageLabel) ? $nextPage->getMenuTitle() : $nextPageLabel;
+ $label = sprintf('%s', $cssClass, $label);
+ if ($nextPageIcon) {
+ $label = sprintf('%s%s', $label, $cssClass, $nextPageIcon);
+ }
+ $attribs = ['class' => $cssClass . '-link-next'];
+ $replacements['{next}'] = $this->createLink($nextPage->getRoute(), $label, $attribs);
+ }
+
+ return strtr($template, $replacements);
+ }
+
+ public function menuSitemap(
+ string $route = '',
+ int $maxDepth = -1,
+ bool $showHidden = false,
+ string $class = 'sitemap'
+ ): string {
+ return $this->menuTree($route, $maxDepth, $showHidden, $class);
+ }
+
public function functionOutputCss(?string $group = null, bool $addTimestamp = false): string
{
return $this->assets->outputCss($group, $addTimestamp);
@@ -463,4 +683,14 @@ public function testIsWritable(string $alias): bool
$filename = $this->alias->get($alias);
return is_writable($filename);
}
+
+ /**
+ * @param array $htmlAttributes
+ */
+ protected function createLink(string $route, string $label, array $htmlAttributes = []): string
+ {
+ $url = $this->urlManager->createUrl($route);
+ $attributesAsString = $this->buildHtmlAttributes($htmlAttributes);
+ return sprintf('%s', $url, $attributesAsString, $label);
+ }
}
diff --git a/plugins/twig_core/TwigCorePlugin.php b/plugins/twig/TwigPlugin.php
similarity index 77%
rename from plugins/twig_core/TwigCorePlugin.php
rename to plugins/twig/TwigPlugin.php
index 981c2374..30921a62 100644
--- a/plugins/twig_core/TwigCorePlugin.php
+++ b/plugins/twig/TwigPlugin.php
@@ -2,20 +2,22 @@
declare(strict_types=1);
-namespace herbie\sysplugin\twig_core;
+namespace herbie\sysplugin\twig;
use Ausi\SlugGenerator\SlugGenerator;
use herbie\Alias;
use herbie\Assets;
use herbie\event\TwigInitializedEvent;
+use herbie\PageRepositoryInterface;
use herbie\Plugin;
use herbie\Translator;
use herbie\UrlManager;
-final class TwigCorePlugin extends Plugin
+final class TwigPlugin extends Plugin
{
private Alias $alias;
private Assets $assets;
+ private PageRepositoryInterface $pageRepository;
private SlugGenerator $slugGenerator;
private Translator $translator;
private UrlManager $urlManager;
@@ -23,12 +25,14 @@ final class TwigCorePlugin extends Plugin
public function __construct(
Alias $alias,
Assets $assets,
+ PageRepositoryInterface $pageRepository,
SlugGenerator $slugGenerator,
Translator $translator,
UrlManager $urlManager
) {
$this->alias = $alias;
$this->assets = $assets;
+ $this->pageRepository = $pageRepository;
$this->slugGenerator = $slugGenerator;
$this->translator = $translator;
$this->urlManager = $urlManager;
@@ -43,10 +47,11 @@ public function eventListeners(): array
public function onTwigInitialized(TwigInitializedEvent $event): void
{
- $event->getEnvironment()->addExtension(new TwigCoreExtension(
+ $event->getEnvironment()->addExtension(new TwigExtension(
$this->alias,
$this->assets,
$event->getEnvironment(),
+ $this->pageRepository,
$this->slugGenerator,
$this->translator,
$this->urlManager
diff --git a/plugins/twig/config.php b/plugins/twig/config.php
new file mode 100755
index 00000000..2744e481
--- /dev/null
+++ b/plugins/twig/config.php
@@ -0,0 +1,10 @@
+ 2,
+ 'pluginName' => 'twig',
+ 'pluginClass' => TwigPlugin::class,
+ 'pluginPath' => __DIR__,
+];
diff --git a/plugins/twig_core/README.md b/plugins/twig_core/README.md
deleted file mode 100644
index 01dc5e70..00000000
--- a/plugins/twig_core/README.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# Twig Core System Plugin
-
-`Twig Core` is a [Herbie](http://github.com/getherbie) system plugin that brings support for several Twig filters, functions and tests.
-
-## Installation
-
-The plugin is installed already.
-
-To activate it, add `twig_core` to the `enabledSysPlugins` configuration option.
-
-~~~php
-return [
- 'enabledSysPlugins' => 'twig_core'
-];
-~~~
-
-## More Information
-
-For more information, see .
diff --git a/plugins/twig_core/config.php b/plugins/twig_core/config.php
deleted file mode 100755
index 6aefc3d5..00000000
--- a/plugins/twig_core/config.php
+++ /dev/null
@@ -1,10 +0,0 @@
- 2,
- 'pluginName' => 'twig_core',
- 'pluginClass' => TwigCorePlugin::class,
- 'pluginPath' => __DIR__,
-];
diff --git a/plugins/twig_plus/README.md b/plugins/twig_plus/README.md
deleted file mode 100644
index 80dedc14..00000000
--- a/plugins/twig_plus/README.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# Twig Plus System Plugin
-
-`Twig Plus` is a [Herbie](http://github.com/getherbie) system plugin that brings support for several Twig functions.
-
-## Installation
-
-The plugin is installed already.
-
-To activate it, add `twig_plus` to the `enabledSysPlugins` configuration option.
-
-~~~php
-return [
- 'enabledSysPlugins' => 'twig_plus'
-];
-~~~
-
-## More Information
-
-For more information, see .
diff --git a/plugins/twig_plus/TwigPlusExtension.php b/plugins/twig_plus/TwigPlusExtension.php
deleted file mode 100644
index 7ba6e61d..00000000
--- a/plugins/twig_plus/TwigPlusExtension.php
+++ /dev/null
@@ -1,422 +0,0 @@
-environment = $environment;
- $this->pageRepository = $pageRepository;
- $this->urlManager = $urlManager;
- }
-
- /**
- * @return TwigFunction[]
- */
- public function getFunctions(): array
- {
- $options = ['is_safe' => ['html']];
- return [
- new TwigFunction('menu_ascii_tree', [$this, 'menuAsciiTree'], $options),
- new TwigFunction('menu_breadcrumb', [$this, 'menuBreadcrumb'], $options),
- new TwigFunction('menu_list', [$this, 'menuList'], $options),
- new TwigFunction('menu_pager', [$this, 'menuPager'], $options),
- new TwigFunction('menu_sitemap', [$this, 'menuSitemap'], $options),
- new TwigFunction('menu_tree', [$this, 'menuTree'], $options),
- new TwigFunction('page_taxonomies', [$this, 'pageTaxonomies'], $options),
- new TwigFunction('taxonomy_archive', [$this, 'taxonomyArchive'], $options),
- new TwigFunction('taxonomy_authors', [$this, 'taxonomyAuthors'], $options),
- new TwigFunction('taxonomy_categories', [$this, 'taxonomyCategories'], $options),
- new TwigFunction('taxonomy_tags', [$this, 'taxonomyTags'], $options)
- ];
- }
-
- public function menuAsciiTree(
- string $route = '',
- int $maxDepth = -1,
- bool $showHidden = false
- ): string {
- // TODO use $class parameter
- $branch = $this->pageRepository->findAll()->getPageTree()->findByRoute($route);
- if ($branch === null) {
- return '';
- }
-
- $treeIterator = new PageTreeIterator($branch);
- $filterIterator = new PageTreeFilterIterator($treeIterator, !$showHidden);
-
- $asciiTree = new PageTreeTextRenderer($filterIterator);
- $asciiTree->setMaxDepth($maxDepth);
- return $asciiTree->render();
- }
-
- /**
- * @param array{0: string, 1?: string}|string $homeLink
- */
- public function menuBreadcrumb(
- string $delim = '',
- $homeLink = '',
- bool $reverse = false
- ): string {
- // TODO use string type for param $homeLink (like "route|label")
-
- $links = [];
-
- if (!empty($homeLink)) {
- if (is_array($homeLink)) {
- $route = reset($homeLink);
- $label = isset($homeLink[1]) ? $homeLink[1] : 'Home';
- } else {
- $route = $homeLink;
- $label = 'Home';
- }
- $links[] = $this->createLink($route, $label);
- }
-
- [$route] = $this->urlManager->parseRequest();
- $pageTrail = $this->pageRepository->findAll()->getPageTrail($route);
- foreach ($pageTrail as $item) {
- $links[] = $this->createLink($item->getRoute(), $item->getMenuTitle());
- }
-
- if (!empty($reverse)) {
- $links = array_reverse($links);
- }
-
- $html = '';
- foreach ($links as $i => $link) {
- if ($i > 0 && !empty($delim)) {
- $html .= '- ' . $delim . '
';
- }
- $html .= '- ' . $link . '
';
- }
- $html .= '
';
-
- return $html;
- }
-
- /**
- * @throws LoaderError
- * @throws RuntimeError
- * @throws SyntaxError
- */
- public function menuList(
- ?PageList $pageList = null,
- string $filter = '',
- string $sort = '',
- bool $shuffle = false,
- int $limit = 10,
- string $template = '@snippet/listing.twig'
- ): string {
- if ($pageList === null) {
- $pageList = $this->pageRepository->findAll();
- }
-
- if (!empty($filter)) {
- [$field, $value] = explode('|', $filter);
- $pageList = $pageList->filter($field, $value);
- }
-
- if (!empty($sort)) {
- [$field, $direction] = explode('|', $sort);
- $pageList = $pageList->sort($field, $direction);
- }
-
- if ($shuffle) {
- $pageList = $pageList->shuffle();
- }
-
- // filter pages with empty title
- $pageList = $pageList->filter(function (Page $page) {
- return !empty($page->getTitle());
- });
-
- $pagination = new Pagination($pageList);
- $pagination->setLimit($limit);
-
- return $this->environment->render($template, ['pagination' => $pagination]);
- }
-
- public function menuTree(
- string $route = '',
- int $maxDepth = -1,
- bool $showHidden = false,
- string $class = 'menu'
- ): string {
- // NOTE duplicated code, see function sitemap
- $branch = $this->pageRepository->findAll()->getPageTree()->findByRoute($route);
- if ($branch === null) {
- return '';
- }
-
- $treeIterator = new PageTreeIterator($branch);
- $filterIterator = new PageTreeFilterIterator($treeIterator, !$showHidden);
-
- $htmlTree = new PageTreeHtmlRenderer($filterIterator);
- $htmlTree->setMaxDepth($maxDepth);
- $htmlTree->setClass($class);
- $htmlTree->setItemCallback(function (PageTree $node) {
- $menuItem = $node->getMenuItem();
- $href = $this->urlManager->createUrl($menuItem->getRoute());
- return sprintf('%s', $href, $menuItem->getMenuTitle());
- });
-
- [$currenRoute] = $this->urlManager->parseRequest();
- return $htmlTree->render($currenRoute);
- }
-
- /**
- * @throws LoaderError
- * @throws RuntimeError
- * @throws SyntaxError
- */
- public function pageTaxonomies(
- ?Page $page = null,
- string $pageRoute = '',
- bool $renderAuthors = true,
- bool $renderCategories = true,
- bool $renderTags = true,
- string $template = '@template/page/taxonomies.twig'
- ): string {
- return $this->environment->render($template, [
- 'page' => $page,
- 'pageRoute' => $pageRoute,
- 'renderAuthors' => $renderAuthors,
- 'renderCategories' => $renderCategories,
- 'renderTags' => $renderTags
- ]);
- }
-
- /**
- * @throws \Exception
- */
- public function menuPager(
- string $limit = '',
- string $prevPageLabel = '',
- string $nextPageLabel = '',
- string $prevPageIcon = '',
- string $nextPageIcon = '',
- string $cssClass = 'pager',
- string $template = '{prev}{next}
'
- ): string {
- [$route] = $this->urlManager->parseRequest();
- $pageList = $this->pageRepository->findAll();
-
- if ($limit !== '') {
- $pageList = $pageList->filter(function ($page) use ($limit) {
- return strpos($page->getRoute(), $limit) === 0;
- });
- }
-
- $prevPage = null;
- $currentPage = null;
- $nextPage = null;
- $lastPage = null;
- foreach ($pageList as $key => $page) {
- if ($currentPage) {
- $nextPage = $page;
- break;
- }
- if ($key === $route) {
- $prevPage = $lastPage;
- $currentPage = $page;
- continue;
- }
- $lastPage = $page;
- }
-
- $replacements = [
- '{class}' => $cssClass,
- '{prev}' => '',
- '{next}' => ''
- ];
-
- if (isset($prevPage)) {
- $label = empty($prevPageLabel) ? $prevPage->getMenuTitle() : $prevPageLabel;
- $label = sprintf('%s', $cssClass, $label);
- if ($prevPageIcon) {
- $label = sprintf('%s%s', $cssClass, $prevPageIcon, $label);
- }
- $attribs = ['class' => $cssClass . '-link-prev'];
- $replacements['{prev}'] = $this->createLink($prevPage->getRoute(), $label, $attribs);
- }
-
- if (isset($nextPage)) {
- $label = empty($nextPageLabel) ? $nextPage->getMenuTitle() : $nextPageLabel;
- $label = sprintf('%s', $cssClass, $label);
- if ($nextPageIcon) {
- $label = sprintf('%s%s', $label, $cssClass, $nextPageIcon);
- }
- $attribs = ['class' => $cssClass . '-link-next'];
- $replacements['{next}'] = $this->createLink($nextPage->getRoute(), $label, $attribs);
- }
-
- return strtr($template, $replacements);
- }
-
- public function menuSitemap(
- string $route = '',
- int $maxDepth = -1,
- bool $showHidden = false,
- string $class = 'sitemap'
- ): string {
- return $this->menuTree($route, $maxDepth, $showHidden, $class);
- }
-
- /**
- * @throws LoaderError
- * @throws RuntimeError
- * @throws SyntaxError
- */
- public function taxonomyArchive(
- ?PageList $pageList = null,
- string $pageRoute = '',
- string $pageType = '',
- bool $showCount = false,
- string $title = 'Archive',
- string $template = '@template/taxonomy/archive.twig'
- ): string {
- if ($pageList === null) {
- $pageList = $this->pageRepository->findAll();
- }
- $months = $pageList->getMonths($pageType);
- return $this->environment->render($template, [
- 'months' => $months,
- 'pageRoute' => $pageRoute,
- 'pageType' => $pageType,
- 'showCount' => $showCount,
- 'title' => $title
- ]);
- }
-
- /**
- * @throws LoaderError
- * @throws RuntimeError
- * @throws SyntaxError
- */
- public function taxonomyAuthors(
- ?PageList $pageList = null,
- string $pageRoute = '',
- string $pageType = '',
- bool $showCount = false,
- string $title = 'Authors',
- string $template = '@template/taxonomy/authors.twig'
- ): string {
- if ($pageList === null) {
- $pageList = $this->pageRepository->findAll();
- }
- $authors = $pageList->getAuthors($pageType);
- return $this->environment->render($template, [
- 'authors' => $authors,
- 'pageRoute' => $pageRoute,
- 'pageType' => $pageType,
- 'showCount' => $showCount,
- 'title' => $title
- ]);
- }
-
- /**
- * @throws LoaderError
- * @throws RuntimeError
- * @throws SyntaxError
- */
- public function taxonomyCategories(
- ?PageList $pageList = null,
- string $pageRoute = '',
- string $pageType = '',
- bool $showCount = false,
- string $title = 'Categories',
- string $template = '@template/taxonomy/categories.twig'
- ): string {
- if ($pageList === null) {
- $pageList = $this->pageRepository->findAll();
- }
- $categories = $pageList->getCategories($pageType);
- return $this->environment->render($template, [
- 'categories' => $categories,
- 'pageRoute' => $pageRoute,
- 'pageType' => $pageType,
- 'showCount' => $showCount,
- 'title' => $title
- ]);
- }
-
- /**
- * @throws LoaderError
- * @throws RuntimeError
- * @throws SyntaxError
- */
- public function taxonomyTags(
- ?PageList $pageList = null,
- string $pageRoute = '',
- string $pageType = '',
- bool $showCount = false,
- string $title = 'Tags',
- string $template = '@template/taxonomy/tags.twig'
- ): string {
- if ($pageList === null) {
- $pageList = $this->pageRepository->findAll();
- }
- $tags = $pageList->getTags($pageType);
- return $this->environment->render($template, [
- 'pageRoute' => $pageRoute,
- 'pageType' => $pageType,
- 'showCount' => $showCount,
- 'tags' => $tags,
- 'title' => $title
- ]);
- }
-
- /**
- * @param array $htmlOptions
- */
- protected function buildHtmlAttributes(array $htmlOptions = []): string
- {
- $attributes = '';
- foreach ($htmlOptions as $key => $value) {
- $attributes .= $key . '="' . $value . '" ';
- }
- return trim($attributes);
- }
-
- /**
- * @param array $htmlAttributes
- */
- protected function createLink(string $route, string $label, array $htmlAttributes = []): string
- {
- $url = $this->urlManager->createUrl($route);
- $attributesAsString = $this->buildHtmlAttributes($htmlAttributes);
- return sprintf('%s', $url, $attributesAsString, $label);
- }
-}
diff --git a/plugins/twig_plus/TwigPlusPlugin.php b/plugins/twig_plus/TwigPlusPlugin.php
deleted file mode 100644
index 762b465c..00000000
--- a/plugins/twig_plus/TwigPlusPlugin.php
+++ /dev/null
@@ -1,40 +0,0 @@
-pageRepository = $pageRepository;
- $this->urlManager = $urlManager;
- }
-
- public function eventListeners(): array
- {
- return [
- [TwigInitializedEvent::class, [$this, 'onTwigInitialized']],
- ];
- }
-
- public function onTwigInitialized(TwigInitializedEvent $event): void
- {
- $event->getEnvironment()->addExtension(new TwigPlusExtension(
- $event->getEnvironment(),
- $this->pageRepository,
- $this->urlManager
- ));
- }
-}
diff --git a/plugins/twig_plus/config.php b/plugins/twig_plus/config.php
deleted file mode 100755
index 0c2ea3d8..00000000
--- a/plugins/twig_plus/config.php
+++ /dev/null
@@ -1,10 +0,0 @@
- 2,
- 'pluginName' => 'twig_plus',
- 'pluginClass' => TwigPlusPlugin::class,
- 'pluginPath' => __DIR__,
-];
diff --git a/templates/page/taxonomies.twig b/templates/page/taxonomies.twig
deleted file mode 100644
index 4b6efc1a..00000000
--- a/templates/page/taxonomies.twig
+++ /dev/null
@@ -1,58 +0,0 @@
-{% apply spaceless %}
- {% if renderCategories and renderTags and renderAuthors %}
-
-
- {# render markup for categories #}
- {% if renderCategories %}
- {% set categories = page.getCategories() %}
- {% if categories %}
-
- Categories:
-
- {% set delim = '' %}
- {% for category in categories %}
- {%- set route = pageRoute ~ '/category/' ~ category|slugify -%}
- {{ delim|raw }}{{ page_link(route, category) }}
- {%- set delim = ', ' -%}
- {% endfor %}
-
- {% endif %}
- {% endif %}
-
- {# render markup for tags #}
- {% if renderTags %}
- {% set tags = page.getTags() %}
- {% if tags %}
-
- Tags:
-
- {% set delim = '' %}
- {% for tag in tags %}
- {%- set route = pageRoute ~ '/tag/' ~ tag|slugify -%}
- {{ delim|raw }}{{ page_link(route, tag) }}
- {%- set delim = ', ' -%}
- {% endfor %}
-
- {% endif %}
- {% endif %}
-
- {# render markup for authors #}
- {% if renderAuthors %}
- {% set authors = page.getAuthors() %}
- {% if authors %}
-
- Authors:
-
- {% set delim = '' %}
- {% for author in authors %}
- {%- set route = pageRoute ~ '/author/' ~ author|slugify -%}
- {{ delim|raw }}{{ page_link(route, author) }}
- {%- set delim = ', ' -%}
- {% endfor %}
-
- {% endif %}
- {% endif %}
-
-
- {% endif %}
-{% endapply %}
\ No newline at end of file
diff --git a/templates/taxonomy/archive.twig b/templates/taxonomy/archive.twig
deleted file mode 100644
index 78a6abfe..00000000
--- a/templates/taxonomy/archive.twig
+++ /dev/null
@@ -1,14 +0,0 @@
-{% apply spaceless %}
- {% if months|length > 0 %}
-
-
{{ title }}
-
- {% for item in months %}
- {% set route = pageRoute ~ '/' ~ item.year ~ '/' ~ item.month %}
- {% set label = item.date|strftime('%B %Y') %}
- - {{ page_link(route, label) }}{% if showCount %} ({{ item.count }}){% endif %}
- {% endfor %}
-
-
- {% endif %}
-{% endapply %}
\ No newline at end of file
diff --git a/templates/taxonomy/authors.twig b/templates/taxonomy/authors.twig
deleted file mode 100644
index 58183ad7..00000000
--- a/templates/taxonomy/authors.twig
+++ /dev/null
@@ -1,13 +0,0 @@
-{% apply spaceless %}
- {% if authors|length > 0 %}
-
-
{{ title }}
-
- {% for author, count in authors %}
- {% set route = pageRoute ~ '/author/' ~ author|slugify %}
- - {{ page_link(route, author) }}{% if showCount %} ({{ count }}){% endif %}
- {% endfor %}
-
-
- {% endif %}
-{% endapply %}
\ No newline at end of file
diff --git a/templates/taxonomy/categories.twig b/templates/taxonomy/categories.twig
deleted file mode 100644
index 703b567e..00000000
--- a/templates/taxonomy/categories.twig
+++ /dev/null
@@ -1,13 +0,0 @@
-{% apply spaceless %}
- {% if categories|length > 0 %}
-
-
{{ title }}
-
- {% for category, count in categories %}
- {% set route = pageRoute ~ '/category/' ~ category|slugify %}
- - {{ page_link(route, category) }}{% if showCount %} ({{ count }}){% endif %}
- {% endfor %}
-
-
- {% endif %}
-{% endapply %}
\ No newline at end of file
diff --git a/templates/taxonomy/tags.twig b/templates/taxonomy/tags.twig
deleted file mode 100644
index 08a4a5c5..00000000
--- a/templates/taxonomy/tags.twig
+++ /dev/null
@@ -1,13 +0,0 @@
-{% apply spaceless %}
- {% if tags|length > 0 %}
-
-
{{ title }}
-
- {% for tag, count in tags %}
- {% set route = pageRoute ~ '/tag/' ~ tag|slugify %}
- - {{ page_link(route, tag) }}{% if showCount %} ({{ count }}){% endif %}
- {% endfor %}
-
-
- {% endif %}
-{% endapply %}
\ No newline at end of file
diff --git a/tests/_data/site/config/main.php b/tests/_data/site/config/main.php
index 5ec2dca7..bcad7fc3 100644
--- a/tests/_data/site/config/main.php
+++ b/tests/_data/site/config/main.php
@@ -18,7 +18,7 @@
]
],
'enabledPlugins' => '',
- 'enabledSysPlugins' => 'twig_core,twig_plus,markdown,rest,textile,imagine,dummy',
+ 'enabledSysPlugins' => 'twig,markdown,rest,textile,imagine,dummy',
'plugins' => [
'imagine' => [
'test' => true,
diff --git a/tests/_data/site/pages/index.html b/tests/_data/site/pages/index.html
index 832c938e..d14a4eb5 100644
--- a/tests/_data/site/pages/index.html
+++ b/tests/_data/site/pages/index.html
@@ -6,7 +6,7 @@ Herbie Tests
{{ 100000|filesize }}
-{{ sitemap() }}
+{{ menu_sitemap() }}
Downloads
diff --git a/tests/_data/site/pages/plugins/twig-plus.html b/tests/_data/site/pages/plugins/twig-plus.html
deleted file mode 100644
index 53e1d20a..00000000
--- a/tests/_data/site/pages/plugins/twig-plus.html
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Twig Plus Plugin
-hidden: false
----
diff --git a/tests/acceptance/HerbieInfoCest.php b/tests/acceptance/HerbieInfoCest.php
index 0d11f11a..0c95c626 100644
--- a/tests/acceptance/HerbieInfoCest.php
+++ b/tests/acceptance/HerbieInfoCest.php
@@ -107,10 +107,8 @@ public function testNumberAndSortingOfPhpClasses(AcceptanceTester $I)
'herbie\sysplugin\markdown\MarkdownSysPlugin',
'herbie\sysplugin\rest\RestSysPlugin',
'herbie\sysplugin\textile\TextileSysPlugin',
- 'herbie\sysplugin\twig_core\TwigCoreExtension',
- 'herbie\sysplugin\twig_core\TwigCorePlugin',
- 'herbie\sysplugin\twig_plus\TwigPlusExtension',
- 'herbie\sysplugin\twig_plus\TwigPlusPlugin',
+ 'herbie\sysplugin\twig\TwigExtension',
+ 'herbie\sysplugin\twig\TwigPlugin',
];
$I->amOnPage('/herbie-info');
$I->see('PHP Classes (' . count($classes) . ')', 'h2');
@@ -309,16 +307,11 @@ public function testNumberAndSortingOfConfig(AcceptanceTester $I)
'plugins.textile.pluginClass',
'plugins.textile.pluginName',
'plugins.textile.pluginPath',
- 'plugins.twig_core.apiVersion',
- 'plugins.twig_core.location',
- 'plugins.twig_core.pluginClass',
- 'plugins.twig_core.pluginName',
- 'plugins.twig_core.pluginPath',
- 'plugins.twig_plus.apiVersion',
- 'plugins.twig_plus.location',
- 'plugins.twig_plus.pluginClass',
- 'plugins.twig_plus.pluginName',
- 'plugins.twig_plus.pluginPath',
+ 'plugins.twig.apiVersion',
+ 'plugins.twig.location',
+ 'plugins.twig.pluginClass',
+ 'plugins.twig.pluginName',
+ 'plugins.twig.pluginPath',
'theme',
'urls.media',
'urls.web',
@@ -426,6 +419,12 @@ public function testNumberAndSortingOfTwigFunctions(AcceptanceTester $I)
'file_link',
'file',
'image',
+ 'menu_ascii_tree',
+ 'menu_breadcrumb',
+ 'menu_list',
+ 'menu_pager',
+ 'menu_sitemap',
+ 'menu_tree',
'page_link',
'page_title',
'output_css',
@@ -435,17 +434,6 @@ public function testNumberAndSortingOfTwigFunctions(AcceptanceTester $I)
'url',
'abs_url',
'mail_link',
- 'menu_ascii_tree',
- 'menu_breadcrumb',
- 'menu_list',
- 'menu_pager',
- 'menu_sitemap',
- 'menu_tree',
- 'page_taxonomies',
- 'taxonomy_archive',
- 'taxonomy_authors',
- 'taxonomy_categories',
- 'taxonomy_tags',
'herbie_debug',
'markdown',
'rest',
@@ -514,7 +502,6 @@ public function testNumberAndSortingOfEvents(AcceptanceTester $I)
'herbie\event\TwigInitializedEvent',
'herbie\event\TwigInitializedEvent',
'herbie\event\TwigInitializedEvent',
- 'herbie\event\TwigInitializedEvent',
'herbie\event\RenderLayoutEvent',
'herbie\event\RenderLayoutEvent',
'herbie\event\RenderLayoutEvent',
@@ -542,8 +529,7 @@ public function testNumberAndSortingOfPlugins(AcceptanceTester $I)
{
$plugins = [
'CORE',
- 'twig_core',
- 'twig_plus',
+ 'twig',
'markdown',
'rest',
'textile',
diff --git a/tests/integration/Fixtures/markdown/config/main.php b/tests/integration/Fixtures/markdown/config/main.php
index 3b9c9a25..66b6fc95 100644
--- a/tests/integration/Fixtures/markdown/config/main.php
+++ b/tests/integration/Fixtures/markdown/config/main.php
@@ -8,7 +8,7 @@
'debug' => true,
],
],
- 'enabledSysPlugins' => 'twig_core,twig_plus,markdown',
+ 'enabledSysPlugins' => 'twig,markdown',
'plugins' => [
'markdown' => [
'enableTwigFilter' => false,
diff --git a/tests/integration/Fixtures/site/config/main.php b/tests/integration/Fixtures/site/config/main.php
index 79711259..3bc25558 100644
--- a/tests/integration/Fixtures/site/config/main.php
+++ b/tests/integration/Fixtures/site/config/main.php
@@ -9,5 +9,5 @@
'cache' => false,
],
],
- 'enabledSysPlugins' => 'twig_core,twig_plus,dummy,imagine,markdown,textile',
+ 'enabledSysPlugins' => 'twig,dummy,imagine,markdown,textile',
];
diff --git a/tests/integration/Fixtures/textile/config/main.php b/tests/integration/Fixtures/textile/config/main.php
index 233499d0..d88fe5ab 100644
--- a/tests/integration/Fixtures/textile/config/main.php
+++ b/tests/integration/Fixtures/textile/config/main.php
@@ -1,7 +1,7 @@
'twig_core,twig_plus,textile',
+ 'enabledSysPlugins' => 'twig,textile',
'components' => [
'fileLogger' => null,
],
diff --git a/tests/integration/SysPlugins/TwigPlus/TwigPlusSmokeTest.php b/tests/integration/SysPlugins/TwigPlus/TwigPlusSmokeTest.php
index 36f75099..839b1144 100644
--- a/tests/integration/SysPlugins/TwigPlus/TwigPlusSmokeTest.php
+++ b/tests/integration/SysPlugins/TwigPlus/TwigPlusSmokeTest.php
@@ -53,13 +53,6 @@ public function testMenuTreeFunction(): void
$this->assertEquals($expected, $actual);
}
- public function testPageTaxonomiesFunction(): void
- {
- $expected = '';
- $actual = $this->twig()->renderString('{{ page_taxonomies() }}');
- $this->assertEquals($expected, $actual);
- }
-
public function testMenuPagerFunction(): void
{
$expected = '
From dd6f51a6ddcfe03873d5fb1d8432d570c9f8f540 Mon Sep 17 00:00:00 2001
From: tbreuss
Date: Wed, 7 Dec 2022 21:04:02 +0100
Subject: [PATCH 03/15] wip
Signed-off-by: tbreuss
---
plugins/twig/TwigExtension.php | 73 ++++++++--------
templates/macros/page.twig | 6 +-
templates/macros/pages.twig | 4 +-
templates/macros/taxonomy.twig | 10 +--
.../{mail_link.twig => link_mail.twig} | 0
templates/snippets/listing.twig | 8 +-
tests/_data/site/pages/index.html | 22 ++---
tests/_data/site/pages/plugins/dummy.html | 2 +-
tests/_data/site/themes/default/main.twig | 2 +-
tests/acceptance/HerbieInfoCest.php | 26 +++---
.../TwigCore/Filters/FilesizeFilterTest.php | 32 +++----
.../TwigCore/Filters/StrftimeFilterTest.php | 22 ++---
.../TwigCore/Functions/AbsUrlFunctionTest.php | 10 +--
.../TwigCore/Functions/AddCssFunctionTest.php | 2 +-
.../TwigCore/Functions/AddJsFunctionTest.php | 2 +-
.../Functions/FileLinkFunctionTest.php | 2 +-
.../Functions/MailLinkFunctionTest.php | 12 +--
.../Functions/OutputCssFunctionTest.php | 4 +-
.../Functions/OutputJsFunctionTest.php | 4 +-
.../Functions/PageLinkFunctionTest.php | 2 +-
.../TwigCore/Functions/UrlFunctionTest.php | 8 +-
.../TwigCore/Tests/ReadableTest.php | 8 +-
.../TwigCore/Tests/WritableTest.php | 8 +-
website/site/data/twig_filters.yml | 4 +-
website/site/data/twig_functions.yml | 83 +++++++++++++++----
website/site/data/twig_tests.yml | 8 +-
website/site/pages/3-recipes/1-index.md | 4 +-
.../adding-a-sitemap-for-search-engines.md | 4 +-
website/site/pages/atom.xml | 10 +--
website/site/pages/imprint.md | 2 +-
website/site/pages/robots.txt | 2 +-
website/site/pages/sitemap.xml | 2 +-
website/site/snippets/twig_features.twig | 2 +-
.../themes/default/includes/simplesearch.twig | 2 +-
website/site/themes/default/main.twig | 34 ++++----
website/site/themes/default/recipe.twig | 2 +-
36 files changed, 237 insertions(+), 191 deletions(-)
rename templates/snippets/{mail_link.twig => link_mail.twig} (100%)
diff --git a/plugins/twig/TwigExtension.php b/plugins/twig/TwigExtension.php
index 2b84e1bf..b6cb84f9 100644
--- a/plugins/twig/TwigExtension.php
+++ b/plugins/twig/TwigExtension.php
@@ -73,10 +73,10 @@ public function __construct(
public function getFilters(): array
{
return [
- new TwigFilter('filesize', [$this, 'filterFilesize']),
new TwigFilter('find', [$this, 'filterFind'], ['is_variadic' => true]),
+ new TwigFilter('format_date', [$this, 'filterStrftime']),
+ new TwigFilter('format_size', [$this, 'filterFilesize']),
new TwigFilter('slugify', [$this, 'filterSlugify']),
- new TwigFilter('strftime', [$this, 'filterStrftime']),
new TwigFilter('visible', [$this, 'filterVisible'], ['deprecated' => true]) // doesn't work properly
];
}
@@ -87,30 +87,27 @@ public function getFilters(): array
public function getFunctions(): array
{
return [
- new TwigFunction('add_css', [$this, 'functionAddCss']),
- new TwigFunction('add_js', [$this, 'functionAddJs']),
- new TwigFunction('css_classes', [$this, 'functionCssClasses'], ['needs_context' => true]),
- new TwigFunction('file_link', [$this, 'functionFileLink'], [
- 'is_safe' => ['html'],
- 'needs_context' => true
- ]),
- new TwigFunction('file', [$this, 'functionFile'], ['is_safe' => ['html']]),
- new TwigFunction('image', [$this, 'functionImage'], ['is_safe' => ['html']]),
+ new TwigFunction('css_add', [$this, 'cssAdd']),
+ new TwigFunction('css_classes', [$this, 'cssClasses'], ['needs_context' => true]),
+ new TwigFunction('css_out', [$this, 'cssOut'], ['is_safe' => ['html']]),
+ new TwigFunction('file', [$this, 'file'], ['is_safe' => ['html']]),
+ new TwigFunction('image', [$this, 'image'], ['is_safe' => ['html']]),
+ new TwigFunction('js_add', [$this, 'jsAdd']),
+ new TwigFunction('js_out', [$this, 'jsOut'], ['is_safe' => ['html']]),
+ new TwigFunction('link_file', [$this, 'linkFile'], ['is_safe' => ['html'], 'needs_context' => true]),
+ new TwigFunction('link_mail', [$this, 'linkMail'], ['is_safe' => ['html']]),
+ new TwigFunction('link_page', [$this, 'linkPage'], ['is_safe' => ['html']]),
new TwigFunction('menu_ascii_tree', [$this, 'menuAsciiTree'], ['is_safe' => ['html']]),
new TwigFunction('menu_breadcrumb', [$this, 'menuBreadcrumb'], ['is_safe' => ['html']]),
new TwigFunction('menu_list', [$this, 'menuList'], ['is_safe' => ['html']]),
new TwigFunction('menu_pager', [$this, 'menuPager'], ['is_safe' => ['html']]),
new TwigFunction('menu_sitemap', [$this, 'menuSitemap'], ['is_safe' => ['html']]),
new TwigFunction('menu_tree', [$this, 'menuTree'], ['is_safe' => ['html']]),
- new TwigFunction('page_link', [$this, 'functionPageLink'], ['is_safe' => ['html']]),
- new TwigFunction('page_title', [$this, 'functionPageTitle'], ['needs_context' => true]),
- new TwigFunction('output_css', [$this, 'functionOutputCss'], ['is_safe' => ['html']]),
- new TwigFunction('output_js', [$this, 'functionOutputJs'], ['is_safe' => ['html']]),
- new TwigFunction('snippet', [$this, 'functionSnippet'], ['is_safe' => ['all']]),
- new TwigFunction('translate', [$this, 'functionTranslate']),
- new TwigFunction('url', [$this, 'functionUrl']),
- new TwigFunction('abs_url', [$this, 'functionAbsUrl']),
- new TwigFunction('mail_link', [$this, 'functionMailLink'], ['is_safe' => ['html']])
+ new TwigFunction('page_title', [$this, 'pageTitle'], ['needs_context' => true]),
+ new TwigFunction('snippet', [$this, 'snippet'], ['is_safe' => ['all']]),
+ new TwigFunction('translate', [$this, 'translate']),
+ new TwigFunction('url_rel', [$this, 'urlRelative']),
+ new TwigFunction('url_abs', [$this, 'urlAbsolute']),
];
}
@@ -120,8 +117,8 @@ public function getFunctions(): array
public function getTests(): array
{
return [
- new TwigTest('readable', [$this, 'testIsReadable']),
- new TwigTest('writable', [$this, 'testIsWritable'])
+ new TwigTest('file_readable', [$this, 'testIsReadable']),
+ new TwigTest('file_writable', [$this, 'testIsWritable'])
];
}
@@ -202,7 +199,7 @@ public function filterVisible(PageTree $tree): PageTreeFilterIterator
/**
* @param array|string $paths
*/
- public function functionAddCss(
+ public function cssAdd(
$paths,
array $attr = [],
?string $group = null,
@@ -215,7 +212,7 @@ public function functionAddCss(
/**
* @param array|string $paths
*/
- public function functionAddJs(
+ public function jsAdd(
$paths,
array $attr = [],
?string $group = null,
@@ -229,7 +226,7 @@ public function functionAddJs(
* @param array $context
* @return string
*/
- public function functionCssClasses(array $context): string
+ public function cssClasses(array $context): string
{
$page = 'error';
if (isset($context['page'])) {
@@ -256,7 +253,7 @@ public function functionCssClasses(array $context): string
return str_replace(['/', '.'], '-', $class);
}
- public function functionFileLink(
+ public function linkFile(
array $context,
string $path,
string $label = '',
@@ -288,11 +285,11 @@ public function functionFileLink(
return strtr('{label}{info}', $replace);
}
- public function functionMailLink(
+ public function linkMail(
string $email,
?string $label = null,
array $attribs = [],
- string $template = '@snippet/mail_link.twig'
+ string $template = '@snippet/link_mail.twig'
): string {
$attribs['href'] = 'mailto:' . $email;
$attribs['class'] = $attribs['class'] ?? 'link__label';
@@ -521,12 +518,12 @@ public function menuSitemap(
return $this->menuTree($route, $maxDepth, $showHidden, $class);
}
- public function functionOutputCss(?string $group = null, bool $addTimestamp = false): string
+ public function cssOut(?string $group = null, bool $addTimestamp = false): string
{
return $this->assets->outputCss($group, $addTimestamp);
}
- public function functionOutputJs(?string $group = null, bool $addTimestamp = false): string
+ public function jsOut(?string $group = null, bool $addTimestamp = false): string
{
return $this->assets->outputJs($group, $addTimestamp);
}
@@ -537,12 +534,12 @@ public function functionOutputJs(?string $group = null, bool $addTimestamp = fal
* @throws RuntimeError
* @throws SyntaxError
*/
- public function functionSnippet(string $path, array $context = []): string
+ public function snippet(string $path, array $context = []): string
{
return $this->environment->render($path, $context);
}
- public function functionImage(
+ public function image(
string $src,
int $width = 0,
int $height = 0,
@@ -564,7 +561,7 @@ public function functionImage(
return sprintf('', $this->buildHtmlAttributes($attribs));
}
- public function functionPageLink(string $route, string $label, array $attribs = []): string
+ public function linkPage(string $route, string $label, array $attribs = []): string
{
$scheme = parse_url($route, PHP_URL_SCHEME);
if ($scheme === null) {
@@ -592,7 +589,7 @@ public function functionPageLink(string $route, string $label, array $attribs =
/**
* @param array{site: Site} $context
*/
- public function functionPageTitle(
+ public function pageTitle(
array $context,
string $delim = ' / ',
string $siteTitle = '',
@@ -622,22 +619,22 @@ public function functionPageTitle(
return implode($delim, $titles);
}
- public function functionTranslate(string $category = '', string $message = '', array $params = []): string
+ public function translate(string $category = '', string $message = '', array $params = []): string
{
return $this->translator->translate($category, $message, $params);
}
- public function functionUrl(string $route = ''): string
+ public function urlRelative(string $route = ''): string
{
return $this->urlManager->createUrl($route);
}
- public function functionAbsUrl(string $route = ''): string
+ public function urlAbsolute(string $route = ''): string
{
return $this->urlManager->createAbsoluteUrl($route);
}
- public function functionFile(string $path, string $label = '', bool $info = false, array $attribs = []): string
+ public function file(string $path, string $label = '', bool $info = false, array $attribs = []): string
{
$attribs['class'] = $attribs['class'] ?? 'link__label';
diff --git a/templates/macros/page.twig b/templates/macros/page.twig
index bbca12fa..113df59e 100644
--- a/templates/macros/page.twig
+++ b/templates/macros/page.twig
@@ -58,7 +58,7 @@
{% set delim = '' %}
{% for category in categories %}
{%- set route = options.pageRoute ~ '/category/' ~ category|slugify -%}
- {{ delim|raw }}{{ page_link(route, category) }}
+ {{ delim|raw }}{{ link_page(route, category) }}
{%- set delim = ', ' -%}
{% endfor %}
@@ -75,7 +75,7 @@
{% set delim = '' %}
{% for tag in tags %}
{%- set route = options.pageRoute ~ '/tag/' ~ tag|slugify -%}
- {{ delim|raw }}{{ page_link(route, tag) }}
+ {{ delim|raw }}{{ link_page(route, tag) }}
{%- set delim = ', ' -%}
{% endfor %}
@@ -92,7 +92,7 @@
{% set delim = '' %}
{% for author in authors %}
{%- set route = options.pageRoute ~ '/author/' ~ author|slugify -%}
- {{ delim|raw }}{{ page_link(route, author) }}
+ {{ delim|raw }}{{ link_page(route, author) }}
{%- set delim = ', ' -%}
{% endfor %}
diff --git a/templates/macros/pages.twig b/templates/macros/pages.twig
index 0d93a02b..ecf7298d 100644
--- a/templates/macros/pages.twig
+++ b/templates/macros/pages.twig
@@ -22,8 +22,8 @@
{% for pageItem in recentPages %}
-
- {{ page_link(pageItem.route, pageItem.title) }}
- {% if options.showDate %}
{{ pageItem.date|strftime(options.dateFormat) }}{% endif %}
+ {{ link_page(pageItem.route, pageItem.title) }}
+ {% if options.showDate %}
{{ pageItem.date|format_date(options.dateFormat) }}{% endif %}
{% endfor %}
diff --git a/templates/macros/taxonomy.twig b/templates/macros/taxonomy.twig
index f4e903f0..0f99e04b 100644
--- a/templates/macros/taxonomy.twig
+++ b/templates/macros/taxonomy.twig
@@ -17,8 +17,8 @@
{% for item in months %}
{% set route = pageRoute ~ '/' ~ item.year ~ '/' ~ item.month %}
- {% set label = item.date|strftime('%B %Y') %}
- - {{ page_link(route, label) }}{% if showCount %} ({{ item.count }}){% endif %}
+ {% set label = item.date|format_date('%B %Y') %}
+ - {{ link_page(route, label) }}{% if showCount %} ({{ item.count }}){% endif %}
{% endfor %}
@@ -47,7 +47,7 @@
{% for author, count in authors %}
{% set route = pageRoute ~ '/author/' ~ author|slugify %}
- - {{ page_link(route, author) }}{% if showCount %} ({{ count }}){% endif %}
+ - {{ link_page(route, author) }}{% if showCount %} ({{ count }}){% endif %}
{% endfor %}
@@ -76,7 +76,7 @@
{% for category, count in categories %}
{% set route = pageRoute ~ '/category/' ~ category|slugify %}
- - {{ page_link(route, category) }}{% if showCount %} ({{ count }}){% endif %}
+ - {{ link_page(route, category) }}{% if showCount %} ({{ count }}){% endif %}
{% endfor %}
@@ -105,7 +105,7 @@
{% for tag, count in tags %}
{% set route = pageRoute ~ '/tag/' ~ tag|slugify %}
- - {{ page_link(route, tag) }}{% if showCount %} ({{ count }}){% endif %}
+ - {{ link_page(route, tag) }}{% if showCount %} ({{ count }}){% endif %}
{% endfor %}
diff --git a/templates/snippets/mail_link.twig b/templates/snippets/link_mail.twig
similarity index 100%
rename from templates/snippets/mail_link.twig
rename to templates/snippets/link_mail.twig
diff --git a/templates/snippets/listing.twig b/templates/snippets/listing.twig
index 30df443e..5c36b4f2 100644
--- a/templates/snippets/listing.twig
+++ b/templates/snippets/listing.twig
@@ -3,10 +3,10 @@
{% for menuitem in pagination %}
- {{ page_link(menuitem.route, menuitem.getMenuTitle()) }}
+ {{ link_page(menuitem.route, menuitem.getMenuTitle()) }}
{% if menuitem.image %}
-
+
{% endif %}
{{ menuitem.excerpt }}
@@ -17,10 +17,10 @@
diff --git a/tests/_data/site/pages/index.html b/tests/_data/site/pages/index.html
index d14a4eb5..94e41200 100644
--- a/tests/_data/site/pages/index.html
+++ b/tests/_data/site/pages/index.html
@@ -4,21 +4,21 @@
Herbie Tests
-{{ 100000|filesize }}
+{{ 100000|format_size }}
{{ menu_sitemap() }}
Downloads
-{{ file_link('favicon.ico', 'File', true) }}
+{{ link_file('favicon.ico', 'File', true) }}
-Download
+Download
- - {{ file_link('dummy.pdf') }}
- - {{ file_link('dummy.pdf', 'Dummy', false) }}
- - {{ file_link('dummy.pdf', 'Dummy', true) }}
- - {{ file_link('dummy.pdf', 'Dummy', true, { target:"_blank"}) }}
+ - {{ link_file('dummy.pdf') }}
+ - {{ link_file('dummy.pdf', 'Dummy', false) }}
+ - {{ link_file('dummy.pdf', 'Dummy', true) }}
+ - {{ link_file('dummy.pdf', 'Dummy', true, { target:"_blank"}) }}
Imagine
@@ -36,13 +36,13 @@ Imagine
Links
- - {{ page_link('adfsafsdf', 'About') }}
- - {{ page_link('about', 'About') }}
- - {{ page_link('https://example.com/', 'About') }}
+ - {{ link_page('adfsafsdf', 'About') }}
+ - {{ link_page('about', 'About') }}
+ - {{ link_page('https://example.com/', 'About') }}
Mailto-Links
- - {{ mail_link('me@example.com', 'John Doe') }}
+ - {{ link_mail('me@example.com', 'John Doe') }}
diff --git a/tests/_data/site/pages/plugins/dummy.html b/tests/_data/site/pages/plugins/dummy.html
index 22dd0130..1cc9e53f 100644
--- a/tests/_data/site/pages/plugins/dummy.html
+++ b/tests/_data/site/pages/plugins/dummy.html
@@ -9,4 +9,4 @@ Dummy Plugin
{{ dummy("This is from") }}.
{% if "dummy" is dummy %}This is from Dummy Test.{% endif %}
{% apply dummy_dynamic %}This is from {% endapply %}.
-{{ file_link('dummy.pdf', 'Dummy', true) }}
+{{ link_file('dummy.pdf', 'Dummy', true) }}
diff --git a/tests/_data/site/themes/default/main.twig b/tests/_data/site/themes/default/main.twig
index 166581fa..5d88bcd9 100644
--- a/tests/_data/site/themes/default/main.twig
+++ b/tests/_data/site/themes/default/main.twig
@@ -19,7 +19,7 @@
Herbie Tests
{%- for menu in site.pageTrail -%}
{{- ' / ' -}}
- {{ menu.title }}
+ {{ menu.title }}
{%- endfor -%}
diff --git a/tests/acceptance/HerbieInfoCest.php b/tests/acceptance/HerbieInfoCest.php
index 0c95c626..d26b994b 100644
--- a/tests/acceptance/HerbieInfoCest.php
+++ b/tests/acceptance/HerbieInfoCest.php
@@ -379,10 +379,10 @@ public function testNumberAndSortingOfTwigFilters(AcceptanceTester $I)
'escape',
'e',
'raw',
- 'filesize',
'find',
+ 'format_date',
+ 'format_size',
'slugify',
- 'strftime',
'visible',
'markdown',
'rest',
@@ -413,27 +413,27 @@ public function testNumberAndSortingOfTwigFunctions(AcceptanceTester $I)
'include',
'source',
'dump',
- 'add_css',
- 'add_js',
+ 'css_add',
'css_classes',
- 'file_link',
+ 'css_out',
'file',
'image',
+ 'js_add',
+ 'js_out',
+ 'link_file',
+ 'link_mail',
+ 'link_page',
'menu_ascii_tree',
'menu_breadcrumb',
'menu_list',
'menu_pager',
'menu_sitemap',
'menu_tree',
- 'page_link',
'page_title',
- 'output_css',
- 'output_js',
'snippet',
'translate',
- 'url',
- 'abs_url',
- 'mail_link',
+ 'url_rel',
+ 'url_abs',
'herbie_debug',
'markdown',
'rest',
@@ -462,8 +462,8 @@ public function testNumberAndSortingOfTwigTests(AcceptanceTester $I)
'constant',
'empty',
'iterable',
- 'readable',
- 'writable',
+ 'file_readable',
+ 'file_writable',
'dummy',
'local_odd',
'mytest',
diff --git a/tests/integration/SysPlugins/TwigCore/Filters/FilesizeFilterTest.php b/tests/integration/SysPlugins/TwigCore/Filters/FilesizeFilterTest.php
index dca18ef3..55b408db 100644
--- a/tests/integration/SysPlugins/TwigCore/Filters/FilesizeFilterTest.php
+++ b/tests/integration/SysPlugins/TwigCore/Filters/FilesizeFilterTest.php
@@ -29,33 +29,33 @@ protected function _setUp(): void
public function testFilesizeWithWrongType(): void
{
$this->expectException(TypeError::class);
- $twig = '{{ "string"|filesize }}'; // string
+ $twig = '{{ "string"|format_size }}'; // string
$this->twigRenderer->renderString($twig);
- $twig = '{{ {a:1}|filesize }}'; // object
+ $twig = '{{ {a:1}|format_size }}'; // object
$this->twigRenderer->renderString($twig);
}
public function testFilesizeWithNegativeValue(): void
{
- $twig = '{{ "-1"|filesize }}';
+ $twig = '{{ "-1"|format_size }}';
$actual = $this->twigRenderer->renderString($twig);
$this->assertSame('0', $actual);
}
public function testFilesizeWithValidValues(): void
{
- $this->assertSame('0', $this->twigRenderer->renderString('{{ "0"|filesize }}'));
- $this->assertSame('1 Byte', $this->twigRenderer->renderString('{{ "1"|filesize }}'));
- $this->assertSame('2 B', $this->twigRenderer->renderString('{{ "2"|filesize }}'));
- $this->assertSame('1024 B', $this->twigRenderer->renderString('{{ "1024"|filesize }}'));
- $this->assertSame('1 KB', $this->twigRenderer->renderString('{{ "1025"|filesize }}')); // KB (* 1024)
- $this->assertSame('1024 KB', $this->twigRenderer->renderString('{{ "1048576"|filesize }}'));
- $this->assertSame('1 MB', $this->twigRenderer->renderString('{{ "1048577"|filesize }}')); // MB (* 1024)
- $this->assertSame('1024 MB', $this->twigRenderer->renderString('{{ "1073741824"|filesize }}'));
- $this->assertSame('1 GB', $this->twigRenderer->renderString('{{ "1073741825"|filesize }}')); // GB (* 1024)
- $this->assertSame('1024 GB', $this->twigRenderer->renderString('{{ "1099511627776"|filesize }}'));
- $this->assertSame('1 TB', $this->twigRenderer->renderString('{{ "1099511627777"|filesize }}')); // TB (* 1024)
- $this->assertSame('1024 TB', $this->twigRenderer->renderString('{{ "1125899906842624"|filesize }}'));
- $this->assertSame('1 PB', $this->twigRenderer->renderString('{{ "1125899906842625"|filesize }}')); // TB (* 1024)
+ $this->assertSame('0', $this->twigRenderer->renderString('{{ "0"|format_size }}'));
+ $this->assertSame('1 Byte', $this->twigRenderer->renderString('{{ "1"|format_size }}'));
+ $this->assertSame('2 B', $this->twigRenderer->renderString('{{ "2"|format_size }}'));
+ $this->assertSame('1024 B', $this->twigRenderer->renderString('{{ "1024"|format_size }}'));
+ $this->assertSame('1 KB', $this->twigRenderer->renderString('{{ "1025"|format_size }}')); // KB (* 1024)
+ $this->assertSame('1024 KB', $this->twigRenderer->renderString('{{ "1048576"|format_size }}'));
+ $this->assertSame('1 MB', $this->twigRenderer->renderString('{{ "1048577"|format_size }}')); // MB (* 1024)
+ $this->assertSame('1024 MB', $this->twigRenderer->renderString('{{ "1073741824"|format_size }}'));
+ $this->assertSame('1 GB', $this->twigRenderer->renderString('{{ "1073741825"|format_size }}')); // GB (* 1024)
+ $this->assertSame('1024 GB', $this->twigRenderer->renderString('{{ "1099511627776"|format_size }}'));
+ $this->assertSame('1 TB', $this->twigRenderer->renderString('{{ "1099511627777"|format_size }}')); // TB (* 1024)
+ $this->assertSame('1024 TB', $this->twigRenderer->renderString('{{ "1125899906842624"|format_size }}'));
+ $this->assertSame('1 PB', $this->twigRenderer->renderString('{{ "1125899906842625"|format_size }}')); // TB (* 1024)
}
}
diff --git a/tests/integration/SysPlugins/TwigCore/Filters/StrftimeFilterTest.php b/tests/integration/SysPlugins/TwigCore/Filters/StrftimeFilterTest.php
index 2f6d6770..23388c10 100644
--- a/tests/integration/SysPlugins/TwigCore/Filters/StrftimeFilterTest.php
+++ b/tests/integration/SysPlugins/TwigCore/Filters/StrftimeFilterTest.php
@@ -33,31 +33,31 @@ public function testStrftimeWithValidDates(): void
// timestamp as integer
$this->assertSame(
'12. September 2022',
- $this->twigRenderer->renderString('{{ 1662952416|strftime("%e. %B %Y") }}')
+ $this->twigRenderer->renderString('{{ 1662952416|format_date("%e. %B %Y") }}')
);
// timestamp as string
$this->assertSame(
'12. September 2022',
- $this->twigRenderer->renderString('{{ "1662952416"|strftime("%e. %B %Y") }}')
+ $this->twigRenderer->renderString('{{ "1662952416"|format_date("%e. %B %Y") }}')
);
// iso-date
$this->assertSame(
'12. September 2022',
- $this->twigRenderer->renderString('{{ "2022-09-12"|strftime("%e. %B %Y") }}')
+ $this->twigRenderer->renderString('{{ "2022-09-12"|format_date("%e. %B %Y") }}')
);
// empty string
$this->assertSame(
time_format("%e. %B %Y"),
- $this->twigRenderer->renderString('{{ ""|strftime("%e. %B %Y") }}')
+ $this->twigRenderer->renderString('{{ ""|format_date("%e. %B %Y") }}')
);
// year with month (without day)
$this->assertSame(
time_format(" 1. September 2022"),
- $this->twigRenderer->renderString('{{ "2022-09"|strftime("%e. %B %Y") }}')
+ $this->twigRenderer->renderString('{{ "2022-09"|format_date("%e. %B %Y") }}')
);
}
@@ -65,32 +65,32 @@ public function testStrftimeWithWrongDates(): void
{
$this->assertSame(
'invalid-date',
- $this->twigRenderer->renderString('{{ "invalid-date"|strftime("%e. %B %Y") }}')
+ $this->twigRenderer->renderString('{{ "invalid-date"|format_date("%e. %B %Y") }}')
);
$this->assertSame(
time_format('%e. %B %Y', time_from_string('1970-01-01')),
- $this->twigRenderer->renderString('{{ 2000|strftime("%e. %B %Y") }}')
+ $this->twigRenderer->renderString('{{ 2000|format_date("%e. %B %Y") }}')
);
$this->assertSame(
'2000-13-32',
- $this->twigRenderer->renderString('{{ "2000-13-32"|strftime("%e. %B %Y") }}')
+ $this->twigRenderer->renderString('{{ "2000-13-32"|format_date("%e. %B %Y") }}')
);
$this->assertSame(
time_format('%e. %B %Y', time_from_string('2000-12-31')), // quite random
- $this->twigRenderer->renderString('{{ "20000-12-31"|strftime("%e. %B %Y") }}')
+ $this->twigRenderer->renderString('{{ "20000-12-31"|format_date("%e. %B %Y") }}')
);
$this->assertSame(
time_format("%e. %B %Y"),
- $this->twigRenderer->renderString('{{ false|strftime("%e. %B %Y") }}')
+ $this->twigRenderer->renderString('{{ false|format_date("%e. %B %Y") }}')
);
$this->assertSame(
time_format('%e. %B %Y', time_from_string('1970-01-01')),
- $this->twigRenderer->renderString('{{ true|strftime("%e. %B %Y") }}')
+ $this->twigRenderer->renderString('{{ true|format_date("%e. %B %Y") }}')
);
}
}
diff --git a/tests/integration/SysPlugins/TwigCore/Functions/AbsUrlFunctionTest.php b/tests/integration/SysPlugins/TwigCore/Functions/AbsUrlFunctionTest.php
index fe55aa1b..99da485b 100644
--- a/tests/integration/SysPlugins/TwigCore/Functions/AbsUrlFunctionTest.php
+++ b/tests/integration/SysPlugins/TwigCore/Functions/AbsUrlFunctionTest.php
@@ -25,8 +25,8 @@ private function twig(): TwigRenderer
public function testUrlWithoutRoute(): void
{
$tests = [
- ['http:/', '{{ abs_url() }}'],
- ['http:/', '{{ abs_url("") }}'],
+ ['http:/', '{{ url_abs() }}'],
+ ['http:/', '{{ url_abs("") }}'],
];
foreach ($tests as $test) {
$this->assertSame($test[0], $this->twig()->renderString($test[1]));
@@ -36,9 +36,9 @@ public function testUrlWithoutRoute(): void
public function testUrlWithValidRoutes(): void
{
$tests = [
- ['http:/one', '{{ abs_url("one") }}'],
- ['http:/one/two', '{{ abs_url("one/two") }}'],
- ['http:/one/two/three', '{{ abs_url("one/two/three") }}']
+ ['http:/one', '{{ url_abs("one") }}'],
+ ['http:/one/two', '{{ url_abs("one/two") }}'],
+ ['http:/one/two/three', '{{ url_abs("one/two/three") }}']
];
foreach ($tests as $test) {
$this->assertSame($test[0], $this->twig()->renderString($test[1]));
diff --git a/tests/integration/SysPlugins/TwigCore/Functions/AddCssFunctionTest.php b/tests/integration/SysPlugins/TwigCore/Functions/AddCssFunctionTest.php
index ef8e83ca..12368b92 100644
--- a/tests/integration/SysPlugins/TwigCore/Functions/AddCssFunctionTest.php
+++ b/tests/integration/SysPlugins/TwigCore/Functions/AddCssFunctionTest.php
@@ -21,7 +21,7 @@ private function twig(): TwigRenderer
public function testPowerOn(): void
{
- $this->twig()->renderString('{{ add_css("@site/assets/styles.css") }}');
+ $this->twig()->renderString('{{ css_add("@site/assets/styles.css") }}');
}
// TODO write more tests
diff --git a/tests/integration/SysPlugins/TwigCore/Functions/AddJsFunctionTest.php b/tests/integration/SysPlugins/TwigCore/Functions/AddJsFunctionTest.php
index 2ca9c3f9..950fb53a 100644
--- a/tests/integration/SysPlugins/TwigCore/Functions/AddJsFunctionTest.php
+++ b/tests/integration/SysPlugins/TwigCore/Functions/AddJsFunctionTest.php
@@ -21,7 +21,7 @@ private function twig(): TwigRenderer
public function testPowerOn(): void
{
- $this->twig()->renderString('{{ add_js("@site/assets/script.js") }}');
+ $this->twig()->renderString('{{ js_add("@site/assets/script.js") }}');
}
// TODO write more tests
diff --git a/tests/integration/SysPlugins/TwigCore/Functions/FileLinkFunctionTest.php b/tests/integration/SysPlugins/TwigCore/Functions/FileLinkFunctionTest.php
index cd1ffea1..ba193a7a 100644
--- a/tests/integration/SysPlugins/TwigCore/Functions/FileLinkFunctionTest.php
+++ b/tests/integration/SysPlugins/TwigCore/Functions/FileLinkFunctionTest.php
@@ -23,7 +23,7 @@ public function testPowerOn(): void
{
$this->assertEquals(
'dummy.pdf',
- $this->twig()->renderString('{{ file_link("dummy.pdf") }}')
+ $this->twig()->renderString('{{ link_file("dummy.pdf") }}')
);
}
diff --git a/tests/integration/SysPlugins/TwigCore/Functions/MailLinkFunctionTest.php b/tests/integration/SysPlugins/TwigCore/Functions/MailLinkFunctionTest.php
index c31eddf3..47c32b92 100644
--- a/tests/integration/SysPlugins/TwigCore/Functions/MailLinkFunctionTest.php
+++ b/tests/integration/SysPlugins/TwigCore/Functions/MailLinkFunctionTest.php
@@ -23,7 +23,7 @@ private function twig(): TwigRenderer
public function testLinkWithoutParams(): void
{
$this->expectException(ArgumentCountError::class);
- $twig = '{{ mail_link() }}';
+ $twig = '{{ link_mail() }}';
$this->twig()->renderString($twig);
}
@@ -32,7 +32,7 @@ public function testLinkWithEmail(): void
$expected = $this->getHtml(
'me@example.com'
);
- $twig = '{{ mail_link("me@example.com") }}';
+ $twig = '{{ link_mail("me@example.com") }}';
$actual = $this->twig()->renderString($twig);
$this->assertSame($expected, $actual);
}
@@ -42,7 +42,7 @@ public function testLinkWithEmailAndLabel(): void
$expected = $this->getHtml(
'Example'
);
- $twig = '{{ mail_link("me@example.com", "Example") }}';
+ $twig = '{{ link_mail("me@example.com", "Example") }}';
$actual = $this->twig()->renderString($twig);
$this->assertSame($expected, $actual);
}
@@ -52,7 +52,7 @@ public function testLinkWithEmailLabelAndAttribs(): void
$expected = $this->getHtml(
'Example'
);
- $twig = '{{ mail_link("me@example.com", "Example", {class:"link-class", id:"link-id"}) }}';
+ $twig = '{{ link_mail("me@example.com", "Example", {class:"link-class", id:"link-id"}) }}';
$actual = $this->twig()->renderString($twig);
$this->assertSame($expected, $actual);
}
@@ -60,14 +60,14 @@ public function testLinkWithEmailLabelAndAttribs(): void
public function testLinkWithCustomTemplate(): void
{
$expected = 'me@example.com';
- $twig = '{{ mail_link("me@example.com", template="{{label}}") }}';
+ $twig = '{{ link_mail("me@example.com", template="{{label}}") }}';
$actual = $this->twig()->renderString($twig);
$this->assertSame($expected, $actual);
}
public function testLinkWithNotExistingCustomTemplate(): void
{
- $twig = '{{ mail_link("me@example.com", template="@not/existing/template.twig") }}';
+ $twig = '{{ link_mail("me@example.com", template="@not/existing/template.twig") }}';
$this->assertEquals('me@example.com', $this->twig()->renderString($twig));
}
diff --git a/tests/integration/SysPlugins/TwigCore/Functions/OutputCssFunctionTest.php b/tests/integration/SysPlugins/TwigCore/Functions/OutputCssFunctionTest.php
index 55e69820..4a5f3f94 100644
--- a/tests/integration/SysPlugins/TwigCore/Functions/OutputCssFunctionTest.php
+++ b/tests/integration/SysPlugins/TwigCore/Functions/OutputCssFunctionTest.php
@@ -21,8 +21,8 @@ private function twig(): TwigRenderer
public function testPowerOn(): void
{
- $twig = '{{ add_css("@site/assets/styles.css") }}'
- . '{{ output_css() }}';
+ $twig = '{{ css_add("@site/assets/styles.css") }}'
+ . '{{ css_out() }}';
$this->assertEquals(
'',
$this->twig()->renderString($twig)
diff --git a/tests/integration/SysPlugins/TwigCore/Functions/OutputJsFunctionTest.php b/tests/integration/SysPlugins/TwigCore/Functions/OutputJsFunctionTest.php
index da2becde..e8861c03 100644
--- a/tests/integration/SysPlugins/TwigCore/Functions/OutputJsFunctionTest.php
+++ b/tests/integration/SysPlugins/TwigCore/Functions/OutputJsFunctionTest.php
@@ -21,8 +21,8 @@ private function twig(): TwigRenderer
public function testPowerOn(): void
{
- $twig = '{{ add_js("@site/assets/script.js") }}'
- . '{{ output_js() }}';
+ $twig = '{{ js_add("@site/assets/script.js") }}'
+ . '{{ js_out() }}';
$this->assertEquals(
'',
$this->twig()->renderString($twig)
diff --git a/tests/integration/SysPlugins/TwigCore/Functions/PageLinkFunctionTest.php b/tests/integration/SysPlugins/TwigCore/Functions/PageLinkFunctionTest.php
index 0e87d8a8..8774b80b 100644
--- a/tests/integration/SysPlugins/TwigCore/Functions/PageLinkFunctionTest.php
+++ b/tests/integration/SysPlugins/TwigCore/Functions/PageLinkFunctionTest.php
@@ -23,7 +23,7 @@ public function testPowerOn(): void
{
$this->assertEquals(
'label',
- $this->twig()->renderString('{{ page_link("route", "label") }}')
+ $this->twig()->renderString('{{ link_page("route", "label") }}')
);
}
diff --git a/tests/integration/SysPlugins/TwigCore/Functions/UrlFunctionTest.php b/tests/integration/SysPlugins/TwigCore/Functions/UrlFunctionTest.php
index 7d1f55d3..803825bd 100644
--- a/tests/integration/SysPlugins/TwigCore/Functions/UrlFunctionTest.php
+++ b/tests/integration/SysPlugins/TwigCore/Functions/UrlFunctionTest.php
@@ -22,14 +22,14 @@ private function twig(): TwigRenderer
public function testUrlWithoutRoute(): void
{
- $twig = '{{ url() }}';
+ $twig = '{{ url_rel() }}';
$this->assertSame('/', $this->twig()->renderString($twig));
}
public function testUrlWithValidRoutes(): void
{
- $this->assertSame('/one', $this->twig()->renderString('{{ url("one") }}'));
- $this->assertSame('/one/two', $this->twig()->renderString('{{ url("one/two") }}'));
- $this->assertSame('/one/two/three', $this->twig()->renderString('{{ url("one/two/three") }}'));
+ $this->assertSame('/one', $this->twig()->renderString('{{ url_rel("one") }}'));
+ $this->assertSame('/one/two', $this->twig()->renderString('{{ url_rel("one/two") }}'));
+ $this->assertSame('/one/two/three', $this->twig()->renderString('{{ url_rel("one/two/three") }}'));
}
}
diff --git a/tests/integration/SysPlugins/TwigCore/Tests/ReadableTest.php b/tests/integration/SysPlugins/TwigCore/Tests/ReadableTest.php
index 5821c7c4..f6148d9b 100644
--- a/tests/integration/SysPlugins/TwigCore/Tests/ReadableTest.php
+++ b/tests/integration/SysPlugins/TwigCore/Tests/ReadableTest.php
@@ -42,7 +42,7 @@ public function testReadableWithoutCondition(): void
public function testReadableWithEmptyParam(): void
{
$twig = <<assertSame('not readable', $this->twig()->renderString($twig));
}
@@ -50,7 +50,7 @@ public function testReadableWithEmptyParam(): void
public function testReadableWithExistingAlias(): void
{
$twig = <<assertSame('is readable', $this->twig()->renderString($twig));
}
@@ -58,7 +58,7 @@ public function testReadableWithExistingAlias(): void
public function testReadableWithExistingAliasWithoutPermissions(): void
{
$twig = <<assertSame('not readable', $this->twig()->renderString($twig));
}
@@ -66,7 +66,7 @@ public function testReadableWithExistingAliasWithoutPermissions(): void
public function testReadableWithNotExistingAlias(): void
{
$twig = <<assertSame('not readable', $this->twig()->renderString($twig));
}
diff --git a/tests/integration/SysPlugins/TwigCore/Tests/WritableTest.php b/tests/integration/SysPlugins/TwigCore/Tests/WritableTest.php
index cd450f9c..ffbd7694 100644
--- a/tests/integration/SysPlugins/TwigCore/Tests/WritableTest.php
+++ b/tests/integration/SysPlugins/TwigCore/Tests/WritableTest.php
@@ -40,7 +40,7 @@ public function testWritableWithoutCondition(): void
public function testWritableWithEmptyParam(): void
{
$twig = <<assertSame('no', $this->twig()->renderString($twig));
}
@@ -48,7 +48,7 @@ public function testWritableWithEmptyParam(): void
public function testWritableWithExistingAlias(): void
{
$twig = <<assertSame('yes', $this->twig()->renderString($twig));
}
@@ -56,7 +56,7 @@ public function testWritableWithExistingAlias(): void
public function testWritableWithExistingAliasWithoutPermissions(): void
{
$twig = <<assertSame('no', $this->twig()->renderString($twig));
}
@@ -64,7 +64,7 @@ public function testWritableWithExistingAliasWithoutPermissions(): void
public function testReadableWithNotExistingAlias(): void
{
$twig = <<assertSame('no', $this->twig()->renderString($twig));
}
diff --git a/website/site/data/twig_filters.yml b/website/site/data/twig_filters.yml
index e5ecaac2..1acef209 100644
--- a/website/site/data/twig_filters.yml
+++ b/website/site/data/twig_filters.yml
@@ -1,7 +1,7 @@
---
- name: filesize
code: >-
- {{ 12345678|filesize }}
+ {{ 12345678|format_size }}
desc: Returns file size in a human readable format (B, KB, MB, GB, TB, PB).
return:
- string
@@ -45,7 +45,7 @@
- The slugified string
- name: strftime
code: >-
- {{ "2022-09-13"|strftime("%Y-%m-%d") }}
+ {{ "2022-09-13"|format_date("%Y-%m-%d") }}
desc: Formats a local time/date according to locale settings.
This is a wrapper for the same-named PHP function.
params:
diff --git a/website/site/data/twig_functions.yml b/website/site/data/twig_functions.yml
index 989c36fb..f829f242 100644
--- a/website/site/data/twig_functions.yml
+++ b/website/site/data/twig_functions.yml
@@ -1,7 +1,7 @@
---
-- name: abs_url
+- name: url_abs
code: >-
- {{ abs_url("doc/contents/variables") }}
+ {{ url_abs("doc/contents/variables") }}
desc: Returns the absolute URL for a given route.
params:
- name: route
@@ -11,9 +11,9 @@
return:
- string
- The absolute URL.
-- name: add_css
+- name: css_add
code: >-
- {{ add_css("@site/themes/styles.css", {class: "styles"}, "default", false, 1) }}
+ {{ css_add("@site/themes/styles.css", {class: "styles"}, "default", false, 1) }}
desc: Adds a CSS asset to the HTML page.
params:
- name: paths
@@ -38,9 +38,9 @@
default: "-1"
return:
- void
-- name: add_js
+- name: js_add
code: >-
- {{ add_js("@site/themes/script.js", {class: "scripts"}, "default", false, 1) }}
+ {{ js_add("@site/themes/script.js", {class: "scripts"}, "default", false, 1) }}
desc: Adds a JavaScript asset to the HTML page.
params:
- name: paths
@@ -294,9 +294,9 @@
return:
- string
- The menu as unordered list
-- name: output_css
+- name: css_out
code: >-
- {{ output_css("default") }}
+ {{ css_out("default") }}
desc: Outputs the CSS assets for a given group.
params:
- name: group
@@ -310,9 +310,9 @@
return:
- void
- The CSS assets
-- name: output_js
+- name: js_out
code: >-
- {{ output_js("default") }}
+ {{ js_out("default") }}
desc: Outputs the JavaScript assets for a given group.
params:
- name: group
@@ -326,9 +326,57 @@
return:
- string
- The JavaScript assets
-- name: page_link
+- name: link_file
code: >-
- {{ page_link("doc/contents/variables", "Content variables", {class: "page-link"}) }}
+ {{ link_file("dummy.pdf", "My dummy file", true, {class: "link-file"}) }}
+ desc: Returns a HTML link with a file from site/media folder.
+ params:
+ - name: path
+ type: string
+ desc: The path to the file in site/media folder.
+ default: ''
+ - name: label
+ type: string
+ desc: The label.
+ default: ''
+ - name: info
+ type: bool
+ desc: Adds info with file size und file extension.
+ default: false
+ - name: attribs
+ type: array
+ desc: The HTML attributes passed as an associative array.
+ default: ''
+ return:
+ - string
+ - The link to a file
+- name: link_mail
+ code: >-
+ {{ link_mail("me@example.com", "John Doe", {class: "link-page"}, "@snippet/link.twig") }}
+ desc: Returns a HTML mailto link.
+ params:
+ - name: email
+ type: string
+ desc: The email.
+ default: ''
+ - name: label
+ type: string
+ desc: The label.
+ default: ''
+ - name: attribs
+ type: array
+ desc: The HTML attributes passed as an associative array.
+ default: ''
+ - name: template
+ type: string
+ desc: The aliased path to the template file.
+ default: ''
+ return:
+ - string
+ - The mailto link
+- name: link_page
+ code: >-
+ {{ link_page("doc/contents/variables", "Content variables", {class: "link-page"}) }}
desc: Returns a HTML link with label and attributes for a given route or an URL.
params:
- name: route
@@ -392,9 +440,10 @@
- string
- The included snippet
- name: translate
- code: >-
- {{ translate("app", "Plugin \"{plugin}\" enabled but not found!", {plugin: "dummy"}) }}
- desc: Translates a string according to the configuration and locale settings.
+ code: >
+ {{ translate("app", "Plugin {plugin} enabled but not found!", {plugin: "dummy"}) }}
+ desc: >
+ Translates a string according to the configuration and locale settings.
params:
- name: category
type: string
@@ -411,9 +460,9 @@
return:
- string
- The translated message
-- name: url
+- name: url_rel
code: >-
- {{ url("doc/contents") }}
+ {{ url_rel("doc/contents") }}
desc: Returns the relative URL to a given route.
params:
- name: route
diff --git a/website/site/data/twig_tests.yml b/website/site/data/twig_tests.yml
index 5ad8ab9f..ffe9fd3f 100644
--- a/website/site/data/twig_tests.yml
+++ b/website/site/data/twig_tests.yml
@@ -1,15 +1,15 @@
---
-- name: readable
+- name: file_readable
code: >-
- {% if "@site/data" is readable %}
+ {% if "@site/data" is file_readable %}
Path or file is readable
{% endif %}
desc: Tests if the given alias or path exists and is readable.
return:
- bool
-- name: writable
+- name: file_writable
code: >-
- {% if "@site/data" is writable %}
+ {% if "@site/data" is file_writable %}
Path or file is writable
{% endif %}
desc: Tests if the given alias or path exists and is writable.
diff --git a/website/site/pages/3-recipes/1-index.md b/website/site/pages/3-recipes/1-index.md
index 0342ec67..40665d5e 100644
--- a/website/site/pages/3-recipes/1-index.md
+++ b/website/site/pages/3-recipes/1-index.md
@@ -22,8 +22,8 @@ layout: recipe
{% endapply %}
{% for item in site.pageList.filterItems('recipe', 'recipes', routeParams) %}
-{{ page_link(item.route, item.title) }}
- {{ item.date|strftime("%e. %B %Y") }}
+
{{ link_page(item.route, item.title) }}
+ {{ item.date|format_date("%e. %B %Y") }}
{% else %}
There are no entries available.
diff --git a/website/site/pages/3-recipes/adding-a-sitemap-for-search-engines.md b/website/site/pages/3-recipes/adding-a-sitemap-for-search-engines.md
index aab38ebf..aeb563ac 100644
--- a/website/site/pages/3-recipes/adding-a-sitemap-for-search-engines.md
+++ b/website/site/pages/3-recipes/adding-a-sitemap-for-search-engines.md
@@ -56,7 +56,7 @@ Instead we retrieve a page list and iterate over all pages and output their URL
{% for page in site.pageList %}
- {{ abs_url(page.route) }}
+ {{ url_abs(page.route) }}
{% if(item.date) %}
{{ page.date|date("c") }}
{% endif %}
@@ -103,7 +103,7 @@ So, create a new page `robots.txt` in the `site/pages` folder with the following
---
User-agent: *
Allow: /
- Sitemap: {{ abs_url('sitemap.xml') }}
+ Sitemap: {{ url_abs('sitemap.xml') }}
{% endverbatim %}
In this case, we allow all robots on all paths.
diff --git a/website/site/pages/atom.xml b/website/site/pages/atom.xml
index fec64efb..56865a57 100644
--- a/website/site/pages/atom.xml
+++ b/website/site/pages/atom.xml
@@ -8,16 +8,16 @@ hidden: true
Herbie CMS Feed
Create small but fully functional websites or blogs in no time and with little effort 👌
-
-
- {{ abs_url('/') }}
+
+
+ {{ url_abs('/') }}
{{ "now"|date('r') }}
{% for item in site.pageList %}
{% if item.title != '' %}
{{ item.title }} / Herbie CMS
-
- {{ abs_url(item.route) }}
+
+ {{ url_abs(item.route) }}
{% if item.date %}{{ item.date|date("c") }}{% endif %}
{% if item.date %}{{ item.date|date("c") }}{% endif %}
{% if item.abstract %}{{ item.abstract }}{% endif %}
diff --git a/website/site/pages/imprint.md b/website/site/pages/imprint.md
index d8be5e75..bc2a1a61 100644
--- a/website/site/pages/imprint.md
+++ b/website/site/pages/imprint.md
@@ -11,7 +11,7 @@ Birsweg 5
CH-4203 Grellingen
Phone: +41 79 332 67 81
-Email: {{ page_link("contact", "Use the contact form") }}
+Email: {{ link_page("contact", "Use the contact form") }}
## Disclaimer
diff --git a/website/site/pages/robots.txt b/website/site/pages/robots.txt
index 4623ce56..fffff1bc 100644
--- a/website/site/pages/robots.txt
+++ b/website/site/pages/robots.txt
@@ -4,4 +4,4 @@ layout: ""
content_type: text/plain
keep_extension: true
---
-Sitemap: {{ abs_url('sitemap.xml') }}
+Sitemap: {{ url_abs('sitemap.xml') }}
diff --git a/website/site/pages/sitemap.xml b/website/site/pages/sitemap.xml
index 818e8d17..b6c8956f 100644
--- a/website/site/pages/sitemap.xml
+++ b/website/site/pages/sitemap.xml
@@ -8,7 +8,7 @@ keep_extension: true
{% for item in site.pageList %}
- {{ abs_url(item.route) }}
+ {{ url_abs(item.route) }}
{% if(item.date) %}
{{ item.date|date("c") }}
{% endif %}
diff --git a/website/site/snippets/twig_features.twig b/website/site/snippets/twig_features.twig
index 492aac85..7b589a26 100644
--- a/website/site/snippets/twig_features.twig
+++ b/website/site/snippets/twig_features.twig
@@ -1,4 +1,4 @@
-{% for item in attribute(site.data, type) %}
+{% for item in attribute(site.data, type)|sort((a, b) => a.name <=> b.name) %}
{{ attribute(item, 'name') }}
diff --git a/website/site/themes/default/includes/simplesearch.twig b/website/site/themes/default/includes/simplesearch.twig
index dc84e080..7ff9edf5 100644
--- a/website/site/themes/default/includes/simplesearch.twig
+++ b/website/site/themes/default/includes/simplesearch.twig
@@ -1,5 +1,5 @@