Deploying to gh-pages from @ harttle/liquidjs@5b1658c823 🚀

This commit is contained in:
harttle
2024-08-19 19:37:14 +00:00
parent 4757bef033
commit 3fd671b610
239 changed files with 1693 additions and 1641 deletions
+1 -1
View File
@@ -105,7 +105,7 @@
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-18T05:44:37.719Z" itemprop="dateModified">Last updated: 2024-08-18</time>
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.426Z" itemprop="dateModified">Last updated: 2024-08-19</time>
<a href="register-filters-tags.html" class="article-footer-prev" title="Register Filters/Tags"><i class="icon-chevron-left"></i><span>Prev</span></a><a href="parse-parameters.html" class="article-footer-next" title="Parse Parameters"><span>Next</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+1 -1
View File
@@ -108,7 +108,7 @@
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-18T05:44:37.719Z" itemprop="dateModified">Last updated: 2024-08-18</time>
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.426Z" itemprop="dateModified">Last updated: 2024-08-19</time>
<a href="use-in-expressjs.html" class="article-footer-prev" title="Use in Express.js"><i class="icon-chevron-left"></i><span>Prev</span></a><a href="escaping.html" class="article-footer-next" title="Escaping"><span>Next</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+1 -1
View File
@@ -746,7 +746,7 @@
</script></li></ul>
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-18T05:45:11.071Z" itemprop="dateModified">Last updated: 2024-08-18</time>
<time class="article-footer-updated" datetime="2024-08-19T19:37:03.734Z" itemprop="dateModified">Last updated: 2024-08-19</time>
<a href="migrate-to-9.html" class="article-footer-prev" title="Migrate to LiquidJS 9"><i class="icon-chevron-left"></i><span>Prev</span></a><a href="differences.html" class="article-footer-next" title="Differences with Shopify/liquid"><span>Next</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+1 -1
View File
@@ -102,7 +102,7 @@
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-18T05:44:37.719Z" itemprop="dateModified">Last updated: 2024-08-18</time>
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.426Z" itemprop="dateModified">Last updated: 2024-08-19</time>
<a href="differences.html" class="article-footer-prev" title="Differences with Shopify/liquid"><i class="icon-chevron-left"></i><span>Prev</span></a>
</footer>
</div>
+1 -1
View File
@@ -126,7 +126,7 @@
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-18T05:44:37.719Z" itemprop="dateModified">Last updated: 2024-08-18</time>
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.426Z" itemprop="dateModified">Last updated: 2024-08-19</time>
<a href="changelog.html" class="article-footer-prev" title="Changelog"><i class="icon-chevron-left"></i><span>Prev</span></a><a href="contribution-guidelines.html" class="article-footer-next" title="Contribution Guidelines"><span>Next</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+1 -1
View File
@@ -111,7 +111,7 @@
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-18T05:44:37.719Z" itemprop="dateModified">Last updated: 2024-08-18</time>
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.426Z" itemprop="dateModified">Last updated: 2024-08-19</time>
<a href="truthy-and-falsy.html" class="article-footer-prev" title="Truthy and Falsy"><i class="icon-chevron-left"></i><span>Prev</span></a><a href="migrate-to-9.html" class="article-footer-next" title="Migrate to LiquidJS 9"><span>Next</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+1 -1
View File
@@ -141,7 +141,7 @@
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-18T05:44:37.719Z" itemprop="dateModified">Last updated: 2024-08-18</time>
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.426Z" itemprop="dateModified">Last updated: 2024-08-19</time>
<a href="render-tag-content.html" class="article-footer-prev" title="Render Tag Content"><i class="icon-chevron-left"></i><span>Prev</span></a><a href="sync-and-async.html" class="article-footer-next" title="Sync and Async"><span>Next</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+1 -1
View File
@@ -129,7 +129,7 @@
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-18T05:44:37.719Z" itemprop="dateModified">Last updated: 2024-08-18</time>
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.426Z" itemprop="dateModified">Last updated: 2024-08-19</time>
<a href="caching.html" class="article-footer-prev" title="Caching"><i class="icon-chevron-left"></i><span>Prev</span></a><a href="register-filters-tags.html" class="article-footer-next" title="Register Filters/Tags"><span>Next</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+1 -1
View File
@@ -121,7 +121,7 @@
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-18T05:44:37.719Z" itemprop="dateModified">Last updated: 2024-08-18</time>
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.426Z" itemprop="dateModified">Last updated: 2024-08-19</time>
<a href="setup.html" class="article-footer-next" title="Setup"><span>Next</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+1 -1
View File
@@ -116,7 +116,7 @@
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-18T05:44:37.719Z" itemprop="dateModified">Last updated: 2024-08-18</time>
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.426Z" itemprop="dateModified">Last updated: 2024-08-19</time>
<a href="dos.html" class="article-footer-prev" title="DoS"><i class="icon-chevron-left"></i><span>Prev</span></a><a href="changelog.html" class="article-footer-next" title="Changelog"><span>Next</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+1 -1
View File
@@ -106,7 +106,7 @@
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-18T05:44:37.719Z" itemprop="dateModified">Last updated: 2024-08-18</time>
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.426Z" itemprop="dateModified">Last updated: 2024-08-19</time>
<a href="plugins.html" class="article-footer-prev" title="Plugins"><i class="icon-chevron-left"></i><span>Prev</span></a><a href="truthy-and-falsy.html" class="article-footer-next" title="Truthy and Falsy"><span>Next</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+1 -1
View File
@@ -162,7 +162,7 @@
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-18T05:44:37.719Z" itemprop="dateModified">Last updated: 2024-08-18</time>
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.426Z" itemprop="dateModified">Last updated: 2024-08-19</time>
<a href="setup.html" class="article-footer-prev" title="Setup"><i class="icon-chevron-left"></i><span>Prev</span></a><a href="render-file.html" class="article-footer-next" title="Render Files"><span>Next</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+2 -2
View File
@@ -113,11 +113,11 @@
<p>In the above example, were trying to generate a random number in the range [2, max]. Well use <code>Hash</code> to parse <code>from</code> and <code>to</code> parameters.</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> &#123; <span class="title class_">Liquid</span>, <span class="title class_">Hash</span> &#125; = <span class="built_in">require</span>(<span class="string">&#x27;liquidjs&#x27;</span>)</span><br><span class="line"></span><br><span class="line">engine.<span class="title function_">registerTag</span>(<span class="string">&#x27;random&#x27;</span>, &#123;</span><br><span class="line"> <span class="title function_">parse</span>(<span class="params">tagToken</span>) &#123;</span><br><span class="line"> <span class="comment">// parse the parameters structure into `this.args`</span></span><br><span class="line"> <span class="variable language_">this</span>.<span class="property">args</span> = <span class="keyword">new</span> <span class="title class_">Hash</span>(tagToken.<span class="property">args</span>)</span><br><span class="line"> &#125;,</span><br><span class="line"> * <span class="title function_">render</span>(<span class="params">context, emitter</span>) &#123;</span><br><span class="line"> <span class="comment">// evaluate the parameters in `context`</span></span><br><span class="line"> <span class="keyword">const</span> &#123;<span class="keyword">from</span>, to&#125; = <span class="keyword">yield</span> <span class="variable language_">this</span>.<span class="property">args</span>.<span class="title function_">render</span>(context)</span><br><span class="line"> <span class="keyword">const</span> length = to - <span class="keyword">from</span> + <span class="number">1</span></span><br><span class="line"> <span class="keyword">const</span> value = <span class="keyword">from</span> + <span class="title class_">Math</span>.<span class="title function_">floor</span>(length * <span class="title class_">Math</span>.<span class="title function_">random</span>())</span><br><span class="line"> emitter.<span class="title function_">write</span>(value)</span><br><span class="line"> &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>
<p>Rendering <code>&#123;% random from:2, to:max %&#125;</code> in scope <code>&#123; max: 10 &#125;</code> will generate a random number in the range [2, 10]. See this JSFiddle: <a target="_blank" rel="noopener external nofollow noreferrer" href="https://jsfiddle.net/ctj364up/4/">https://jsfiddle.net/ctj364up/4/</a></p>
<p>Rendering <code>{% random from:2, to:max %}</code> in scope <code>&#123; max: 10 &#125;</code> will generate a random number in the range [2, 10]. See this JSFiddle: <a target="_blank" rel="noopener external nofollow noreferrer" href="https://jsfiddle.net/ctj364up/4/">https://jsfiddle.net/ctj364up/4/</a></p>
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-18T05:44:37.719Z" itemprop="dateModified">Last updated: 2024-08-18</time>
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.426Z" itemprop="dateModified">Last updated: 2024-08-19</time>
<a href="access-scope-in-filters.html" class="article-footer-prev" title="Access Scope in Filters"><i class="icon-chevron-left"></i><span>Prev</span></a><a href="render-tag-content.html" class="article-footer-next" title="Render Tag Content"><span>Next</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+1 -1
View File
@@ -112,7 +112,7 @@
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-18T05:44:37.719Z" itemprop="dateModified">Last updated: 2024-08-18</time>
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.426Z" itemprop="dateModified">Last updated: 2024-08-19</time>
<a href="render-file.html" class="article-footer-prev" title="Render Files"><i class="icon-chevron-left"></i><span>Prev</span></a><a href="use-in-expressjs.html" class="article-footer-next" title="Use in Express.js"><span>Next</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+1 -1
View File
@@ -109,7 +109,7 @@
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-18T05:44:37.719Z" itemprop="dateModified">Last updated: 2024-08-18</time>
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.426Z" itemprop="dateModified">Last updated: 2024-08-19</time>
<a href="whitespace-control.html" class="article-footer-prev" title="Whitespace Control"><i class="icon-chevron-left"></i><span>Prev</span></a><a href="operators.html" class="article-footer-next" title="Operators"><span>Next</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+1 -1
View File
@@ -112,7 +112,7 @@
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// disable a tag</span></span><br><span class="line"><span class="keyword">const</span> disabledTag = &#123;</span><br><span class="line"> <span class="attr">parse</span>: <span class="keyword">function</span>(<span class="params">token</span>) &#123;</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">`tag &quot;<span class="subst">$&#123;token.name&#125;</span>&quot; disabled`</span>);</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line">engine.<span class="title function_">registerTag</span>(<span class="string">&#x27;include&#x27;</span>, disabledTag);</span><br><span class="line"></span><br><span class="line"><span class="comment">// disable a filter</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">disabledFilter</span>(<span class="params">name</span>) &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">`filter &quot;<span class="subst">$&#123;name&#125;</span>&quot; disabled`</span>);</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line">engine.<span class="title function_">registerFilter</span>(<span class="string">&#x27;plus&#x27;</span>, <span class="title function_">disabledFilter</span>(<span class="string">&#x27;plus&#x27;</span>));</span><br></pre></td></tr></table></figure>
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-18T05:44:37.719Z" itemprop="dateModified">Last updated: 2024-08-18</time>
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.426Z" itemprop="dateModified">Last updated: 2024-08-19</time>
<a href="escaping.html" class="article-footer-prev" title="Escaping"><i class="icon-chevron-left"></i><span>Prev</span></a><a href="access-scope-in-filters.html" class="article-footer-next" title="Access Scope in Filters"><span>Next</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+1 -1
View File
@@ -134,7 +134,7 @@
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-18T05:44:37.719Z" itemprop="dateModified">Last updated: 2024-08-18</time>
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.426Z" itemprop="dateModified">Last updated: 2024-08-19</time>
<a href="options.html" class="article-footer-prev" title="Options"><i class="icon-chevron-left"></i><span>Prev</span></a><a href="partials-and-layouts.html" class="article-footer-next" title="Includes and Layouts"><span>Next</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+30 -4
View File
@@ -99,14 +99,40 @@
<p>Expected output:</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&#x27;wrapper&#x27;</span>&gt;</span></span><br><span class="line"> Hello world!</span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>Firstly, [register][register-tags] a tag with name <code>wrap</code> and parse the content into <code>this.tpls</code>. Here in <code>parse(tagToken, remainTokens)</code>,</p>
<p>Firstly, <a href="./register-filters-tags.html">register</a> a tag with name <code>wrap</code> and parse the content into <code>this.tpls</code>. Here in <code>parse(tagToken, remainTokens)</code>,</p>
<ul>
<li><code>tagToken</code> is current token `</li>
<li><code>tagToken</code> is current token <code>{% wrap %}</code>, and</li>
<li><code>remainTokens</code> is an array of all tokens following <code>{% wrap %}</code> until the end of this template file.</li>
</ul>
<p>Basically, what we need to do is take/<code>.shift()</code> enough tags from <code>remainTokens</code> until we got a <code>endwrap</code> token (the name can be arbitrary, but in convention, we need it to be <code>endwrap</code>). And if theres no <code>endwrap</code> until the end of template file, we need to throw an tag-not-closed <code>Error</code>.</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">engine.<span class="title function_">registerTag</span>(<span class="string">&#x27;wrap&#x27;</span>, &#123;</span><br><span class="line"> <span class="title function_">parse</span>(<span class="params">tagToken, remainTokens</span>) &#123;</span><br><span class="line"> <span class="variable language_">this</span>.<span class="property">tpls</span> = []</span><br><span class="line"> <span class="keyword">let</span> closed = <span class="literal">false</span></span><br><span class="line"> <span class="keyword">while</span>(remainTokens.<span class="property">length</span>) &#123;</span><br><span class="line"> <span class="keyword">let</span> token = remainTokens.<span class="title function_">shift</span>()</span><br><span class="line"> <span class="comment">// we got the end tag! stop taking tokens</span></span><br><span class="line"> <span class="keyword">if</span> (token.<span class="property">name</span> === <span class="string">&#x27;endwrap&#x27;</span>) &#123;</span><br><span class="line"> closed = <span class="literal">true</span></span><br><span class="line"> <span class="keyword">break</span></span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">// parse token into template</span></span><br><span class="line"> <span class="comment">// parseToken() may consume more than 1 tokens</span></span><br><span class="line"> <span class="comment">// e.g. &#123;% if %&#125;...&#123;% endif %&#125;</span></span><br><span class="line"> <span class="keyword">let</span> tpl = <span class="variable language_">this</span>.<span class="property">liquid</span>.<span class="property">parser</span>.<span class="title function_">parseToken</span>(token, remainTokens)</span><br><span class="line"> <span class="variable language_">this</span>.<span class="property">tpls</span>.<span class="title function_">push</span>(tpl)</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">if</span> (!closed) <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">`tag <span class="subst">$&#123;tagToken.getText()&#125;</span> not closed`</span>)</span><br><span class="line"> &#125;,</span><br><span class="line"> * <span class="title function_">render</span>(<span class="params">context, emitter</span>) &#123;</span><br><span class="line"> emitter.<span class="title function_">write</span>(<span class="string">&quot;&lt;div class=&#x27;wrapper&#x27;&gt;&quot;</span>)</span><br><span class="line"> <span class="keyword">yield</span> <span class="variable language_">this</span>.<span class="property">liquid</span>.<span class="property">renderer</span>.<span class="title function_">renderTemplates</span>(<span class="variable language_">this</span>.<span class="property">tpls</span>, context, emitter)</span><br><span class="line"> emitter.<span class="title function_">write</span>(<span class="string">&quot;&lt;/div&gt;&quot;</span>)</span><br><span class="line"> &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>
<p><code>.renderTemplates()</code> can be async, we need <code>yield</code> to wait it complete. More details on async in LiquidJS, please refer to <a href="./sync-and-async.html">Sync and Async</a>. Other parts of <code>render()</code> method is quite straightforward. Heres a JSFiddle version: <a target="_blank" rel="noopener external nofollow noreferrer" href="https://jsfiddle.net/por0zcn1/3/">https://jsfiddle.net/por0zcn1/3/</a></p>
<h2 id="Using-ParseStream" class="article-heading"><a href="#Using-ParseStream" class="headerlink" title="Using ParseStream"></a>Using ParseStream<a class="article-anchor" href="#Using-ParseStream" aria-hidden="true"></a></h2><p>When it comes to complex tags like <a href="../tags/for.html">for</a> and <a href="../tags/if.html">if</a>, the <code>parse()</code> can be very complicated. Theres a <a href="/api/classes/ParseStream.html">ParseStream</a> utility to organize the <code>parse()</code> in event-based style. Following is a re-written <code>parse()</code> using <code>ParseStream</code> and does exactly the same as above example.</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_">parse</span>(<span class="params">tagToken, remainTokens</span>) &#123;</span><br><span class="line"> <span class="variable language_">this</span>.<span class="property">tpls</span> = []</span><br><span class="line"> <span class="variable language_">this</span>.<span class="property">liquid</span>.<span class="property">parser</span>.<span class="title function_">parseStream</span>(remainTokens)</span><br><span class="line"> .<span class="title function_">on</span>(<span class="string">&#x27;template&#x27;</span>, <span class="function"><span class="params">tpl</span> =&gt;</span> <span class="variable language_">this</span>.<span class="property">tpls</span>.<span class="title function_">push</span>(tpl))</span><br><span class="line"> <span class="comment">// note that we cannot use arrow function because we need `this`</span></span><br><span class="line"> .<span class="title function_">on</span>(<span class="string">&#x27;tag:endwrap&#x27;</span>, <span class="keyword">function</span> (<span class="params"></span>) &#123; <span class="variable language_">this</span>.<span class="title function_">stop</span>() &#125;)</span><br><span class="line"> .<span class="title function_">on</span>(<span class="string">&#x27;end&#x27;</span>, <span class="function">() =&gt;</span> &#123; <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">`tag <span class="subst">$&#123;tagToken.getText()&#125;</span> not closed`</span>) &#125;)</span><br><span class="line"> .<span class="title function_">start</span>()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>Heres a JSFiddle version: <a target="_blank" rel="noopener external nofollow noreferrer" href="https://jsfiddle.net/por0zcn1/4/">https://jsfiddle.net/por0zcn1/4/</a>. For simplicity, the following examples are implemented using <code>ParseStream</code>.</p>
<h2 id="Manipulate-the-Context" class="article-heading"><a href="#Manipulate-the-Context" class="headerlink" title="Manipulate the Context"></a>Manipulate the Context<a class="article-anchor" href="#Manipulate-the-Context" aria-hidden="true"></a></h2><p>The <code>wrap</code> tag above doesnt seem to be very useful, without using that tag we can render the content anyway. Now were going to implement a <code>repeat</code> tag to render the content 2 times (we can also add a <a href="./parse-parameters.html">parameter</a> to render arbitrary times).</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#123;% repeat %&#125;</span><br><span class="line"> &#123;&#123; repeat.i &#125;&#125;. &#123;&#123; &quot;hello world!&quot; | capitalize &#125;&#125;</span><br><span class="line">&#123;% endrepeat %&#125;`</span><br></pre></td></tr></table></figure>
<p>Expected outputs:</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">1. Hello world!</span><br><span class="line">2. Hello world!</span><br></pre></td></tr></table></figure>
<p>As youve noticed, theres an additional <code>repeat.i</code> in the context of <code>repeat</code>. That is implemented by manipulating the <em>Context</em>.</p>
<blockquote class="note info"><strong class="note-title">Context</strong><p><em>Context</em> defines the value of each variable in Liquid template. In LiquidJS, a <code>Context</code> consists of a stack of <code>Scope</code>s. A <em>Scope</em> is a plain object like the one specified in <code>engine.render(tpl, scope)</code>.</p>
</blockquote>
<p>Each time we enter a new <em>Context</em>, we need to push a new <em>Scope</em>. And when we finish rendering and exit the <em>Context</em>, we pop the <em>Scope</em> from the <em>Context</em>. As you can see in the following implementation:</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">engine.<span class="title function_">registerTag</span>(<span class="string">&#x27;repeat&#x27;</span>, &#123;</span><br><span class="line"> <span class="title function_">parse</span>(<span class="params">tagToken, remainTokens</span>) &#123;</span><br><span class="line"> <span class="variable language_">this</span>.<span class="property">tpls</span> = []</span><br><span class="line"> <span class="variable language_">this</span>.<span class="property">liquid</span>.<span class="property">parser</span>.<span class="title function_">parseStream</span>(remainTokens)</span><br><span class="line"> .<span class="title function_">on</span>(<span class="string">&#x27;template&#x27;</span>, <span class="function"><span class="params">tpl</span> =&gt;</span> <span class="variable language_">this</span>.<span class="property">tpls</span>.<span class="title function_">push</span>(tpl))</span><br><span class="line"> .<span class="title function_">on</span>(<span class="string">&#x27;tag:endrepeat&#x27;</span>, <span class="keyword">function</span> (<span class="params"></span>) &#123; <span class="variable language_">this</span>.<span class="title function_">stop</span>() &#125;)</span><br><span class="line"> .<span class="title function_">on</span>(<span class="string">&#x27;end&#x27;</span>, <span class="function">() =&gt;</span> &#123; <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">`tag <span class="subst">$&#123;tagToken.getText()&#125;</span> not closed`</span>) &#125;)</span><br><span class="line"> .<span class="title function_">start</span>()</span><br><span class="line"> &#125;,</span><br><span class="line"> * <span class="title function_">render</span>(<span class="params">context, emitter</span>) &#123;</span><br><span class="line"> <span class="keyword">const</span> repeat = &#123; <span class="attr">i</span>: <span class="number">1</span> &#125;</span><br><span class="line"> context.<span class="title function_">push</span>(&#123; repeat &#125;)</span><br><span class="line"> <span class="keyword">yield</span> <span class="variable language_">this</span>.<span class="property">liquid</span>.<span class="property">renderer</span>.<span class="title function_">renderTemplates</span>(<span class="variable language_">this</span>.<span class="property">tpls</span>, context, emitter)</span><br><span class="line"> repeat.<span class="property">i</span>++</span><br><span class="line"> <span class="keyword">yield</span> <span class="variable language_">this</span>.<span class="property">liquid</span>.<span class="property">renderer</span>.<span class="title function_">renderTemplates</span>(<span class="variable language_">this</span>.<span class="property">tpls</span>, context, emitter)</span><br><span class="line"> context.<span class="title function_">pop</span>()</span><br><span class="line"> &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>
<p>The <code>parse()</code> is exactly the same as <code>wrap</code> tag, we repeat the content simply by calling <code>.renderTemplates(this.tpls)</code> twice during <code>render()</code>. Heres the JSFiddle: <a target="_blank" rel="noopener external nofollow noreferrer" href="https://jsfiddle.net/por0zcn1/2/">https://jsfiddle.net/por0zcn1/2/</a></p>
<blockquote class="note warn"><strong class="note-title">Use Push & Pop in Pairs</strong><p><code>context.push()</code> and <code>context.pop()</code> have to be used in pairs. Failing to <code>pop()</code> the <em>Scope</em> you pushed will leak the <em>Scope</em> to latter templates and may corrupt the <em>Context</em> stack.</p>
</blockquote>
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-18T05:44:37.719Z" itemprop="dateModified">Last updated: 2024-08-18</time>
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.426Z" itemprop="dateModified">Last updated: 2024-08-19</time>
<a href="parse-parameters.html" class="article-footer-prev" title="Parse Parameters"><i class="icon-chevron-left"></i><span>Prev</span></a><a href="drops.html" class="article-footer-next" title="Liquid Drops"><span>Next</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
@@ -115,7 +141,7 @@
<div id="article-toc-inner">
<div id="article-toc-inner-list">
<strong class="sidebar-title">Contents</strong>
<ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#Render-Tag-Content"><span class="toc-text">Render Tag Content</span></a></li></ol>
<ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#Render-Tag-Content"><span class="toc-text">Render Tag Content</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Using-ParseStream"><span class="toc-text">Using ParseStream</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Manipulate-the-Context"><span class="toc-text">Manipulate the Context</span></a></li></ol>
</div>
<a href="#" id="article-toc-top">Back to Top</a>
</div>
+1 -1
View File
@@ -140,7 +140,7 @@
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-18T05:44:37.719Z" itemprop="dateModified">Last updated: 2024-08-18</time>
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.426Z" itemprop="dateModified">Last updated: 2024-08-19</time>
<a href="intro-to-liquid.html" class="article-footer-prev" title="Intro to Liquid"><i class="icon-chevron-left"></i><span>Prev</span></a><a href="options.html" class="article-footer-next" title="Options"><span>Next</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+1 -1
View File
@@ -134,7 +134,7 @@
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-18T05:44:37.719Z" itemprop="dateModified">Last updated: 2024-08-18</time>
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.426Z" itemprop="dateModified">Last updated: 2024-08-19</time>
<a href="drops.html" class="article-footer-prev" title="Liquid Drops"><i class="icon-chevron-left"></i><span>Prev</span></a><a href="whitespace-control.html" class="article-footer-next" title="Whitespace Control"><span>Next</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+1 -1
View File
@@ -226,7 +226,7 @@
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-18T05:44:37.719Z" itemprop="dateModified">Last updated: 2024-08-18</time>
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.426Z" itemprop="dateModified">Last updated: 2024-08-19</time>
<a href="operators.html" class="article-footer-prev" title="Operators"><i class="icon-chevron-left"></i><span>Prev</span></a><a href="dos.html" class="article-footer-next" title="DoS"><span>Next</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+1 -1
View File
@@ -113,7 +113,7 @@
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-18T05:44:37.719Z" itemprop="dateModified">Last updated: 2024-08-18</time>
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.426Z" itemprop="dateModified">Last updated: 2024-08-19</time>
<a href="partials-and-layouts.html" class="article-footer-prev" title="Includes and Layouts"><i class="icon-chevron-left"></i><span>Prev</span></a><a href="caching.html" class="article-footer-next" title="Caching"><span>Next</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+1 -1
View File
@@ -118,7 +118,7 @@
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-18T05:44:37.719Z" itemprop="dateModified">Last updated: 2024-08-18</time>
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.426Z" itemprop="dateModified">Last updated: 2024-08-19</time>
<a href="sync-and-async.html" class="article-footer-prev" title="Sync and Async"><i class="icon-chevron-left"></i><span>Prev</span></a><a href="plugins.html" class="article-footer-next" title="Plugins"><span>Next</span><i class="icon-chevron-right"></i></a>
</footer>
</div>