1
0

Fixes #542: render each and render all

This commit is contained in:
Zef Hemel 2023-10-30 14:15:12 +01:00
parent 1d8e7d5c35
commit 8f4d6e5d23
13 changed files with 74 additions and 17 deletions

View File

@ -26,7 +26,7 @@ LimitClause { kw<"limit"> Expression }
OrderClause { Order commaSep<OrderBy> }
OrderBy { Expression OrderDirection? }
SelectClause { kw<"select"> commaSep<Select> }
RenderClause { kw<"render"> PageRef }
RenderClause { kw<"render"> ( kw<"each"> | kw<"all"> )? PageRef }
Select { Identifier | Expression kw<"as"> Identifier }

View File

@ -1,18 +1,18 @@
// This file was generated by lezer-generator. You probably shouldn't edit it.
import {LRParser} from "@lezer/lr"
const spec_Identifier = {__proto__:null,where:12, null:28, and:40, or:42, limit:52, select:66, as:70, render:74}
const spec_Identifier = {__proto__:null,where:12, null:28, and:40, or:42, limit:52, select:66, as:70, render:74, each:76, all:78}
export const parser = LRParser.deserialize({
version: 14,
states: ")lOVQPOOOmQQO'#C^QOQPOOOtQQO'#CwOOQO'#DT'#DTO!`QQO,58xOtQQO'#C`OtQQO'#CuO!gQQO'#C|O#RQPO'#DQOOQO'#Cg'#CgOtQQO'#CkOOQO'#Cd'#CdO#WQSO'#CcO&_QSO'#ClOOQO'#Cl'#ClOtQQO'#CnO(VQSO'#CyOOQO'#Cc'#CcO(sQQO'#DpOOQO,59c,59cOOQO-E7R-E7RO)[QSO,58zO)rQSO,59aO*YQSO'#ClO*sQSO'#DOO*zQQO'#DqOOQO,59h,59hOOQO,59l,59lO+cQSO'#D]O+pQPO,59VO+uQQO,59XO+zQQO,59`O,RQSO,59YOtQQO,59^OtQQO,59^OtQQO,59^OOQO'#Cz'#CzOOQO,59e,59eOtQQO,59ZOtQQO,59ZOtQQO'#DVO,YQQO,5:[O,qQQO,59jO!gQQO'#DWO,vQQO,5:]OtQQO'#DUO-_QPO,59wOOQO1G.q1G.qOOQO1G.s1G.sO-jQPO1G.zOOQO1G.z1G.zOOQO1G.t1G.tO/`QSO1G.xOOQO1G.x1G.xO/jQSO1G.xO1hQSO1G.uO1oQSO1G.uOOQO,59q,59qOOQO-E7T-E7TOOQO1G/U1G/UOOQO,59r,59rOOQO-E7U-E7UO1vQSO,59pOOQO-E7S-E7SOOQO7+$f7+$f",
stateData: "2]~O}OS~ORPO~OUUOjVOlROqWOuXO~O{QX~P[OT^OX[OY[O[YO][O^[O!OZO!T`O~O{Qa~P[OThOX[OY[O[YO][O^[O!OZO!T`O~OvlO~O!SoOUVXdVXeVXgVXjVXlVXoVXqVXuVX{VX!QVX!VVX!WVX!XVX!YVX!ZVX![VX!]VX!^VX!_VX!`VX!aVX!bVX!cVXsVX!RVX!UVX~O!TpOd`Xe`Xg`X!S`X!V`X!W`X!X`X!Y`X!Z`X![`X!]`X!^`X!_`X!``X!a`X!b`X!c`Xs`X~OU`Xj`Xl`Xo`Xq`Xu`X{`X!Q`X!R`X!U`X~P%QOdwOexOgrO!VrO!WrO!XrO!YrO!ZrO![rO!]rO!^rO!_sO!`sO!asO!btO!ctO~OouOUmXjmXlmXqmXumX{mX!QmX~P'RO!QyOU!dXj!dXl!dXq!dXu!dX{!dX~OUSajSalSaqSauSa{Sa~P'ROUiajialiaqiauia{ia~P'ROUrXjrXlrXqrXurX{rX!QrX~P%QOs{O~P'RO!Q|OU!eXj!eXl!eXq!eXu!eX{!eX~O!Q!OO!R!PX!U!PX~P'RO!R!QO~OT!RO~O!U!TO~PtO!U!UO~P'RO!QyOU!daj!dal!daq!dau!da{!da~OT!^O~O!Q|OU!eaj!eal!eaq!eau!ea{!ea~O!Q!OO!R!Pa!U!Pa~O!U!cO~O!_sO!`sO!asOUfidfiefigfijfilfiofiqfiufi{fi!Qfi!Vfi!Wfi!Xfi!Yfi!Zfi![fi!]fi!^fisfi!Rfi!Ufi~O!btO!ctO~P-oO!bfi!cfi~P-oOgrO!VrO!WrO!XrO!YrO!ZrO![rO!]rO!^rO!_sO!`sO!asO!btO!ctOUciecijcilciociqciuci{ci!Qcisci!Rci!Uci~Odci~P/tOdwO~P/tO!Qxa!Rxa!Uxa~P'ROl[goTXo~",
goto: "&S!fPP!gP!jPP!n#gPP#xPPP#x$Z$l#g#gPP#gP#g!jP!jP$}%TP!jP%WP!jPP%^%d%j%pPPPP%vPPPPPPPPPPPPPPPPPP%|&PRQOTSPTSaRyQfUQgVSiW|SmZpQq`Q!VrQ!WsQ!XtQ!YwQ!ZxR!a!OobRUVWZ`prstwxy|!Oo[RUVWZ`prstwxy|!Oo]RUVWZ`prstwxy|!Oo_RUVWZ`prstwxy|!OQcRR![yRvaQjWR!_|QTPReTQ!PmR!b!PQzcR!]zQ}jR!`}QnZR!SpRdRRkW",
nodeNames: "⚠ Program Query TagIdentifier WhereClause Identifier where Expression Value Number String Bool BooleanKW Regex null List LVal Attribute ParenthesizedExpression LogicalExpression and or BinExpression InKW Call LimitClause limit OrderClause Order OrderBy OrderDirection OrderKW SelectClause select Select as RenderClause render PageRef",
maxTerm: 67,
states: ")xOVQPOOOmQQO'#C^QOQPOOOtQQO'#CwOOQO'#DV'#DVO!`QQO,58xOtQQO'#C`OtQQO'#CuO!gQQO'#C|O#RQSO'#DQOOQO'#Cg'#CgOtQQO'#CkOOQO'#Cd'#CdO#^QSO'#CcO&eQSO'#ClOOQO'#Cl'#ClOtQQO'#CnO(]QSO'#CyOOQO'#Cc'#CcO(yQQO'#DrOOQO,59c,59cOOQO-E7T-E7TO)bQSO,58zO)xQSO,59aO*`QSO'#ClO*yQSO'#DOO+QQQO'#DsOOQO,59h,59hOOQO,59l,59lO+iQPO,59lO+nQSO'#D_O+{QPO,59VO,QQQO,59XO,VQQO,59`O,^QSO,59YOtQQO,59^OtQQO,59^OtQQO,59^OOQO'#Cz'#CzOOQO,59e,59eOtQQO,59ZOtQQO,59ZOtQQO'#DXO,eQQO,5:^O,|QQO,59jO!gQQO'#DYO-RQQO,5:_OOQO1G/W1G/WOtQQO'#DWO-jQPO,59yOOQO1G.q1G.qOOQO1G.s1G.sO-uQPO1G.zOOQO1G.z1G.zOOQO1G.t1G.tO/kQSO1G.xOOQO1G.x1G.xO/uQSO1G.xO1sQSO1G.uO1zQSO1G.uOOQO,59s,59sOOQO-E7V-E7VOOQO1G/U1G/UOOQO,59t,59tOOQO-E7W-E7WO2RQSO,59rOOQO-E7U-E7UOOQO7+$f7+$f",
stateData: "2h~O!POS~ORPO~OUUOjVOlROqWOuXO~O}QX~P[OT^OX[OY[O[YO][O^[O!QZO!V`O~O}Qa~P[OThOX[OY[O[YO][O^[O!QZO!V`O~OvmOwmOxlO~O!UpOUVXdVXeVXgVXjVXlVXoVXqVXuVX}VX!SVX!XVX!YVX!ZVX![VX!]VX!^VX!_VX!`VX!aVX!bVX!cVX!dVX!eVXsVX!TVX!WVX~O!VqOd`Xe`Xg`X!U`X!X`X!Y`X!Z`X![`X!]`X!^`X!_`X!``X!a`X!b`X!c`X!d`X!e`Xs`X~OU`Xj`Xl`Xo`Xq`Xu`X}`X!S`X!T`X!W`X~P%WOdxOeyOgsO!XsO!YsO!ZsO![sO!]sO!^sO!_sO!`sO!atO!btO!ctO!duO!euO~OovOUmXjmXlmXqmXumX}mX!SmX~P'XO!SzOU!fXj!fXl!fXq!fXu!fX}!fX~OUSajSalSaqSauSa}Sa~P'XOUiajialiaqiauia}ia~P'XOUrXjrXlrXqrXurX}rX!SrX~P%WOs|O~P'XO!S}OU!gXj!gXl!gXq!gXu!gX}!gX~Ox!PO~O!S!QO!T!RX!W!RX~P'XO!T!SO~OT!TO~O!W!VO~PtO!W!WO~P'XO!SzOU!faj!fal!faq!fau!fa}!fa~OT!`O~O!S}OU!gaj!gal!gaq!gau!ga}!ga~O!S!QO!T!Ra!W!Ra~O!W!eO~O!atO!btO!ctOUfidfiefigfijfilfiofiqfiufi}fi!Sfi!Xfi!Yfi!Zfi![fi!]fi!^fi!_fi!`fisfi!Tfi!Wfi~O!duO!euO~P-zO!dfi!efi~P-zOgsO!XsO!YsO!ZsO![sO!]sO!^sO!_sO!`sO!atO!btO!ctO!duO!euOUciecijcilciociqciuci}ci!Scisci!Tci!Wci~Odci~P0POdxO~P0PO!Sza!Tza!Wza~P'XOl[goTXo~",
goto: "&U!hPP!iP!lPP!p#iPP#zPPP#z$]$n#i#iPP#iP#i!lP!lP%P%VP!lP%YP!lPPPP%`%f%l%rPPPP%xPPPPPPPPPPPPPPPPPP&O&RRQOTSPTSaRzQfUQgVSiW}SnZqQr`Q!XsQ!YtQ!ZuQ![xQ!]yR!c!QobRUVWZ`qstuxyz}!Qo[RUVWZ`qstuxyz}!Qo]RUVWZ`qstuxyz}!Qo_RUVWZ`qstuxyz}!QQcRR!^zRwaQjWR!a}QTPReTQ!RnR!d!RQ{cR!_{Q!OjR!b!OQoZR!UqRdRRkW",
nodeNames: "⚠ Program Query TagIdentifier WhereClause Identifier where Expression Value Number String Bool BooleanKW Regex null List LVal Attribute ParenthesizedExpression LogicalExpression and or BinExpression InKW Call LimitClause limit OrderClause Order OrderBy OrderDirection OrderKW SelectClause select Select as RenderClause render each all PageRef",
maxTerm: 69,
skippedNodes: [0],
repeatNodeCount: 4,
tokenData: "8k~RzX^#upq#uqr$jrs$}uv%uxy%zyz&Pz{&U{|&Z|}&`}!O&e!O!P&j!P!Q&o!Q![)a!^!_)i!_!`)v!`!a*T!c!}*b!}#O+d#P#Q,a#T#U,f#U#W*b#W#X.c#X#Y*b#Y#Z/S#Z#]*b#]#^2^#^#c*b#c#d3j#d#h*b#h#i7Z#i#o*b#y#z#u$f$g#u#BY#BZ#u$IS$I_#u$Ip$Iq$}$Iq$Ir$}$I|$JO#u$JT$JU#u$KV$KW#u&FU&FV#u~#zY}~X^#upq#u#y#z#u$f$g#u#BY#BZ#u$IS$I_#u$I|$JO#u$JT$JU#u$KV$KW#u&FU&FV#u~$mP!_!`$p~$uP!Y~#r#s$x~$}O!^~~%QWOr$}rs%js$Ip$}$Ip$Iq%j$Iq$Ir%j$Ir;'S$};'S;=`%o<%lO$}~%oOY~~%rP;=`<%l$}~%zO!a~~&PO!T~~&UO!U~~&ZO!_~~&`O!b~~&eO!Q~~&jO!c~~&oO!S~U&vX!`S]QOY'cZ]'c^!P'c!P!Q(T!Q#O'c#O#P(Y#P;'S'c;'S;=`)Z<%lO'cQ'hX]QOY'cZ]'c^!P'c!P!Q(T!Q#O'c#O#P(Y#P;'S'c;'S;=`)Z<%lO'cQ(YO]QQ(]RO;'S'c;'S;=`(f;=`O'cQ(kY]QOY'cZ]'c^!P'c!P!Q(T!Q#O'c#O#P(Y#P;'S'c;'S;=`)Z;=`<%l'c<%lO'cQ)^P;=`<%l'c~)fPX~!Q![)a~)nP!V~!_!`)q~)vO!W~~){P!X~#r#s*O~*TO!]~~*YP![~!_!`*]~*bO!Z~V*iURPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#o*bP+QURP}!O*{!P!Q*{!Q![*{!c!}*{#R#S*{#T#o*{R+iP!OQ!}#O+lP+oTO#P+l#P#Q,O#Q;'S+l;'S;=`,Z<%lO+lP,RP#P#Q,UP,ZOvPP,^P;=`<%l+l~,fO!R~V,mWRPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#g*b#g#h-V#h#o*bV-^WRPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#V*b#V#W-v#W#o*bV.PURPoSTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#o*bV.jWRPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#X*b#X#Y,f#Y#o*bV/ZVRPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#U/p#U#o*bV/wWRPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#`*b#`#a0a#a#o*bV0hWRPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#g*b#g#h1Q#h#o*bV1XWRPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#X*b#X#Y1q#Y#o*bV1zURP[QTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#o*bV2eWRPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#b*b#b#c2}#c#o*bV3WURPgSTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#o*bV3qWRPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#f*b#f#g4Z#g#o*bV4bWRPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#W*b#W#X4z#X#o*bV5RWRPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#X*b#X#Y5k#Y#o*bV5rWRPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#f*b#f#g6[#g#o*bV6cVRPTUpq6x}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#o*bU6{P#U#V7OU7RP#m#n7UU7ZOlUV7bWRPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#f*b#f#g7z#g#o*bV8RWRPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#i*b#i#j1Q#j#o*b",
tokenData: "8k~RzX^#upq#uqr$jrs$}uv%uxy%zyz&Pz{&U{|&Z|}&`}!O&e!O!P&j!P!Q&o!Q![)a!^!_)i!_!`)v!`!a*T!c!}*b!}#O+d#P#Q,a#T#U,f#U#W*b#W#X.c#X#Y*b#Y#Z/S#Z#]*b#]#^2^#^#c*b#c#d3j#d#h*b#h#i7Z#i#o*b#y#z#u$f$g#u#BY#BZ#u$IS$I_#u$Ip$Iq$}$Iq$Ir$}$I|$JO#u$JT$JU#u$KV$KW#u&FU&FV#u~#zY!P~X^#upq#u#y#z#u$f$g#u#BY#BZ#u$IS$I_#u$I|$JO#u$JT$JU#u$KV$KW#u&FU&FV#u~$mP!_!`$p~$uP![~#r#s$x~$}O!`~~%QWOr$}rs%js$Ip$}$Ip$Iq%j$Iq$Ir%j$Ir;'S$};'S;=`%o<%lO$}~%oOY~~%rP;=`<%l$}~%zO!c~~&PO!V~~&UO!W~~&ZO!a~~&`O!d~~&eO!S~~&jO!e~~&oO!U~U&vX!bS]QOY'cZ]'c^!P'c!P!Q(T!Q#O'c#O#P(Y#P;'S'c;'S;=`)Z<%lO'cQ'hX]QOY'cZ]'c^!P'c!P!Q(T!Q#O'c#O#P(Y#P;'S'c;'S;=`)Z<%lO'cQ(YO]QQ(]RO;'S'c;'S;=`(f;=`O'cQ(kY]QOY'cZ]'c^!P'c!P!Q(T!Q#O'c#O#P(Y#P;'S'c;'S;=`)Z;=`<%l'c<%lO'cQ)^P;=`<%l'c~)fPX~!Q![)a~)nP!X~!_!`)q~)vO!Y~~){P!Z~#r#s*O~*TO!_~~*YP!^~!_!`*]~*bO!]~V*iURPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#o*bP+QURP}!O*{!P!Q*{!Q![*{!c!}*{#R#S*{#T#o*{V+iP!QQ!}#O+lT+oTO#P+l#P#Q,O#Q;'S+l;'S;=`,Z<%lO+lT,RP#P#Q,UT,ZOxTT,^P;=`<%l+l~,fO!T~V,mWRPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#g*b#g#h-V#h#o*bV-^WRPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#V*b#V#W-v#W#o*bV.PURPoSTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#o*bV.jWRPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#X*b#X#Y,f#Y#o*bV/ZVRPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#U/p#U#o*bV/wWRPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#`*b#`#a0a#a#o*bV0hWRPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#g*b#g#h1Q#h#o*bV1XWRPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#X*b#X#Y1q#Y#o*bV1zURP[QTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#o*bV2eWRPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#b*b#b#c2}#c#o*bV3WURPgSTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#o*bV3qWRPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#f*b#f#g4Z#g#o*bV4bWRPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#W*b#W#X4z#X#o*bV5RWRPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#X*b#X#Y5k#Y#o*bV5rWRPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#f*b#f#g6[#g#o*bV6cVRPTUpq6x}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#o*bU6{P#U#V7OU7RP#m#n7UU7ZOlUV7bWRPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#f*b#f#g7z#g#o*bV8RWRPTU}!O*b!P!Q*{!Q![*b!c!}*b#R#S*b#T#i*b#i#j1Q#j#o*b",
tokenizers: [0, 1, 2],
topRules: {"Program":[0,1]},
specialized: [{term: 5, get: value => spec_Identifier[value] || -1}],
tokenPrec: 787
tokenPrec: 798
})

View File

@ -29,4 +29,4 @@ export const
SelectClause = 32,
Select = 34,
RenderClause = 36,
PageRef = 38
PageRef = 40

View File

@ -262,7 +262,8 @@ export const highlightingDirectiveParser = directiveParser.configure({
"String": t.string,
"Number": t.number,
"PageRef": ct.WikiLinkTag,
"where limit select render Order OrderKW and or as InKW": t.keyword,
"where limit select render Order OrderKW and or as InKW each all":
t.keyword,
}),
],
});

View File

@ -26,7 +26,7 @@ LimitClause { kw<"limit"> Expression }
OrderClause { Order commaSep<OrderBy> }
OrderBy { Expression OrderDirection? }
SelectClause { kw<"select"> commaSep<Select> }
RenderClause { kw<"render"> PageRef }
RenderClause { kw<"render"> ( kw<"each"> | kw<"all"> )? PageRef }
Select { Identifier | Expression kw<"as"> Identifier }

View File

@ -74,7 +74,10 @@ export function astToKvQuery(
break;
}
case "RenderClause": {
query.render = (clause[2][1] as string).slice(2, -2);
// console.log("Render clause", clause);
const pageRef = (clause as any[]).find((c) => c[0] === "PageRef");
query.render = pageRef[1].slice(2, -2);
query.renderAll = !!(clause as any[]).find((c) => c[0] === "all");
break;
}
default:

View File

@ -149,6 +149,29 @@ Deno.test("Test directive parser", () => {
{
querySource: "task",
render: "my/page",
renderAll: false,
},
);
assertEquals(
astToKvQuery(
wrapQueryParse(`task render each [[my/page]]`)!,
),
{
querySource: "task",
render: "my/page",
renderAll: false,
},
);
assertEquals(
astToKvQuery(
wrapQueryParse(`task render all [[my/page]]`)!,
),
{
querySource: "task",
render: "my/page",
renderAll: true,
},
);

View File

@ -66,6 +66,7 @@ export type Query = {
select?: Select[];
limit?: QueryExpression;
render?: string;
renderAll?: boolean;
distinct?: boolean;
};

View File

@ -1,6 +1,7 @@
import { handlebars, space } from "$sb/syscalls.ts";
import { handlebarHelpers } from "../../common/syscalls/handlebar_helpers.ts";
import { PageMeta } from "$sb/types.ts";
import { render } from "preact";
export function defaultJsonTransformer(_k: string, v: any) {
if (v === undefined) {
@ -57,9 +58,12 @@ export async function renderTemplate(
pageMeta: PageMeta,
renderTemplate: string,
data: any[],
renderAll: boolean,
): Promise<string> {
let templateText = await space.readPage(renderTemplate);
templateText = `{{#each .}}\n${templateText}\n{{/each}}`;
if (!renderAll) {
templateText = `{{#each .}}\n${templateText}\n{{/each}}`;
}
return handlebars.renderTemplate(templateText, data, { page: pageMeta });
}

View File

@ -4,6 +4,7 @@ import { parseTreeToAST } from "$sb/lib/tree.ts";
import { astToKvQuery } from "$sb/lib/parse-query.ts";
import { jsonToMDTable, renderTemplate } from "../directive/util.ts";
import { replaceTemplateVars } from "../template/template.ts";
import { parse } from "../../common/markdown_parser/parse_tree.ts";
export async function widget(bodyText: string): Promise<WidgetContent> {
const pageMeta = await space.getPageMeta(await editor.getCurrentPage());
@ -45,6 +46,7 @@ export async function widget(bodyText: string): Promise<WidgetContent> {
pageMeta,
parsedQuery.render,
allResults,
parsedQuery.renderAll!,
);
resultMarkdown = rendered.trim();
} else {

View File

@ -1,6 +1,13 @@
An attempt at documenting the changes/new features introduced in each
release.
---
## 0.5.4
* Many styling fixes and improvements to [[Live Queries]] and [[Live Templates]]
* Added a “source” button to [[Live Queries]] and [[Live Templates]] for better debugging (showing you the markdown code rendered by the template so you can more easily detect issues)
* [[Live Queries]]:
* Support for `render all` where the entire result set is passed to a single template allowing you to e.g. dynamically build up tables, see [[Live Queries@render]] for an example.
---
## 0.5.3
* Changes to [[Objects]]:

View File

@ -55,14 +55,25 @@ person
where page = "{{@page.name}}"
select name, age, age + 1 as nextYear
```
### `render [[template]]`
By default results are rendered as a table, to instead render each result item using [[Templates|a template]], use the `render` clause:
### `render each [[template]]` and `render all [[template]]`
$render
By default results are rendered as a table, to instead render results using [[Templates|a template]], use the `render` clause, which comes in two shapes `render each` where the template is instantiated for _each_ result (the `each` keyword is optional):
```query
person
where page = "{{@page.name}}"
render [[template/person]]
render each [[template/person]]
```
And `render all` where the entire result set is passed to the template as a list so the template can do its own iteration using `#each`, which you could then use to e.g. build a table (using this [[template/people]] template for instance):
```query
person
where page = "{{@page.name}}"
render all [[template/people]]
```
## Expressions
$expression

View File

@ -0,0 +1,5 @@
| Name | Age |
|----------|----------|
{{#each .}}
| **{{name}}** | {{age}} |
{{/each}}