Deploying to gh-pages from @ harttle/liquidjs@292a93b738 🚀

This commit is contained in:
harttle
2024-08-20 01:26:51 +00:00
parent 3fd671b610
commit 5c42b7fb7c
238 changed files with 3824 additions and 1819 deletions
+12 -3
View File
@@ -93,10 +93,19 @@
</header>
<div class="article-content" itemprop="articleBody">
<p><a href="/tutorials/register-filters-tags.html">注册过滤器和标签</a> 里介绍过,可以在函数参数里直接获得过滤器的参数:</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></pre></td><td class="code"><pre><span class="line"><span class="comment">// Usage: &#123;&#123; 1 | add: 2, 3 &#125;&#125;</span></span><br><span class="line"><span class="comment">// Output: 6</span></span><br><span class="line">engine.<span class="title function_">registerFilter</span>(<span class="string">&#x27;add&#x27;</span>, <span class="function">(<span class="params">initial, arg1, arg2</span>) =&gt;</span> initial + arg1 + arg2)</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token comment">// Usage: &#123;&#123; 1 | add: 2, 3 &#125;&#125;</span>
<span class="token comment">// Output: 6</span>
engine<span class="token punctuation">.</span><span class="token function">registerFilter</span><span class="token punctuation">(</span><span class="token string">'add'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">initial<span class="token punctuation">,</span> arg1<span class="token punctuation">,</span> arg2</span><span class="token punctuation">)</span> <span class="token operator">=></span> initial <span class="token operator">+</span> arg1 <span class="token operator">+</span> arg2<span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre>
<p>但有些过滤器还需要访问当前上下文的变量,比如把 URL 路径转换为完整的 URL 时,需要访问上下文的 <code>origin</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></pre></td><td class="code"><pre><span class="line"><span class="comment">// Usage: &#123;&#123; &#x27;/index.html&#x27; | fullURL &#125;&#125;</span></span><br><span class="line"><span class="comment">// Scope: &#123; origin: &quot;https://liquidjs.com&quot; &#125;</span></span><br><span class="line"><span class="comment">// Output: https://liquidjs.com/index.html</span></span><br><span class="line"></span><br><span class="line">engine.<span class="title function_">registerFilter</span>(<span class="string">&#x27;fullURL&#x27;</span>, <span class="keyword">function</span> (<span class="params">path</span>) &#123;</span><br><span class="line"> <span class="keyword">const</span> origin = <span class="variable language_">this</span>.<span class="property">context</span>.<span class="title function_">get</span>([<span class="string">&#x27;origin&#x27;</span>])</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="title function_">URL</span>(path, origin).<span class="title function_">toString</span>() </span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token comment">// Usage: &#123;&#123; '/index.html' | fullURL &#125;&#125;</span>
<span class="token comment">// Scope: &#123; origin: "https://liquidjs.com" &#125;</span>
<span class="token comment">// Output: https://liquidjs.com/index.html</span>
engine<span class="token punctuation">.</span><span class="token function">registerFilter</span><span class="token punctuation">(</span><span class="token string">'fullURL'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">path</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">const</span> origin <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>context<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string">'origin'</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">URL</span><span class="token punctuation">(</span>path<span class="token punctuation">,</span> origin<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p>见这个 JSFiddle<a target="_blank" rel="noopener external nofollow noreferrer" href="http://jsfiddle.net/ctj364up/1/">http://jsfiddle.net/ctj364up/1/</a></p>
<blockquote class="note warn"><strong class="note-title">箭头函数</strong><p>在箭头函数里 <code>this</code> 会绑定到当前 JavaScript 上下文,你需要用 <code>function(){}</code> 来替代 <code>()=&gt;{}</code> 语法,才能正确地访问 <code>this.context</code></p>
@@ -105,7 +114,7 @@
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.430Z" itemprop="dateModified">上次更新:2024-08-19</time>
<time class="article-footer-updated" datetime="2024-08-20T01:26:05.768Z" itemprop="dateModified">上次更新:2024-08-20</time>
<a href="register-filters-tags.html" class="article-footer-prev" title="注册标签/过滤器"><i class="icon-chevron-left"></i><span>上一页</span></a><a href="parse-parameters.html" class="article-footer-next" title="参数解析"><span>下一页</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+19 -4
View File
@@ -96,19 +96,34 @@
<p>LiquidJS 在这一方面比较灵活,提供了多种不同的方式来达到提升性能的目的。</p>
<h2 id="手动缓存" class="article-heading"><a href="#手动缓存" class="headerlink" title="手动缓存"></a>手动缓存<a class="article-anchor" href="#手动缓存" aria-hidden="true"></a></h2><p><a href="/api/classes/Liquid.html#parse">.parse()</a>, <a href="/api/classes/Liquid.html#parseFile">.parseFile()</a>, <a href="/api/classes/Liquid.html#parseFileSync">.parseFileSync()</a> API 可以用来把字符串或文件解析成模板。得到的模板可以用不同的数据去重复地渲染得到不同的 HTML。</p>
<p>从字符串解析:</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> tpl = engine.<span class="title function_">parse</span>(<span class="string">&#x27;&#123;&#123;name | capitalize&#125;&#125;&#x27;</span>);</span><br><span class="line"></span><br><span class="line">engine.<span class="title function_">renderSync</span>(tpl, &#123;<span class="attr">name</span>: <span class="string">&#x27;alice&#x27;</span>&#125;) <span class="comment">// &#x27;Alice&#x27;</span></span><br><span class="line">engine.<span class="title function_">renderSync</span>(tpl, &#123;<span class="attr">name</span>: <span class="string">&#x27;bob&#x27;</span>&#125;) <span class="comment">// &#x27;Bob&#x27;</span></span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">var</span> tpl <span class="token operator">=</span> engine<span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span><span class="token string">'&#123;&#123;name | capitalize&#125;&#125;'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
engine<span class="token punctuation">.</span><span class="token function">renderSync</span><span class="token punctuation">(</span>tpl<span class="token punctuation">,</span> <span class="token punctuation">&#123;</span><span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'alice'</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span> <span class="token comment">// 'Alice'</span>
engine<span class="token punctuation">.</span><span class="token function">renderSync</span><span class="token punctuation">(</span>tpl<span class="token punctuation">,</span> <span class="token punctuation">&#123;</span><span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'bob'</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span> <span class="token comment">// 'Bob'</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre>
<p>从文件解析:</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> tpl = engine.<span class="title function_">parseFileSync</span>(<span class="string">&#x27;hello&#x27;</span>); <span class="comment">// contents of `hello.liquid`: &#123;&#123;name&#125;&#125;</span></span><br><span class="line"></span><br><span class="line">engine.<span class="title function_">renderSync</span>(tpl, &#123;<span class="attr">name</span>: <span class="string">&#x27;alice&#x27;</span>&#125;) <span class="comment">// &#x27;Alice&#x27;</span></span><br><span class="line">engine.<span class="title function_">renderSync</span>(tpl, &#123;<span class="attr">name</span>: <span class="string">&#x27;bob&#x27;</span>&#125;) <span class="comment">// &#x27;Bob&#x27;</span></span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">var</span> tpl <span class="token operator">=</span> engine<span class="token punctuation">.</span><span class="token function">parseFileSync</span><span class="token punctuation">(</span><span class="token string">'hello'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// contents of `hello.liquid`: &#123;&#123;name&#125;&#125;</span>
engine<span class="token punctuation">.</span><span class="token function">renderSync</span><span class="token punctuation">(</span>tpl<span class="token punctuation">,</span> <span class="token punctuation">&#123;</span><span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'alice'</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span> <span class="token comment">// 'Alice'</span>
engine<span class="token punctuation">.</span><span class="token function">renderSync</span><span class="token punctuation">(</span>tpl<span class="token punctuation">,</span> <span class="token punctuation">&#123;</span><span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'bob'</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span> <span class="token comment">// 'Bob'</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre>
<p>上述代码中字符串或文件只被解析了一次,可以反复利用去渲染不同的数据。有很多模板文件时可以把 <code>tpl</code> 变量存在 <code>Map</code> 中,后续再 <code>.render()</code> 时直接从 Map 中拿出解析好的模板去渲染。</p>
<h2 id="cache-选项" class="article-heading"><a href="#cache-选项" class="headerlink" title="cache 选项"></a><code>cache</code> 选项<a class="article-anchor" href="#cache-选项" aria-hidden="true"></a></h2><p>如果你只用 <code>.renderFile()</code><code>.renderFileSync()</code> 也可以直接设置 <a href="/api/interfaces/LiquidOptions.html#cache">cache</a> 选项,LiquidJS 会帮你缓存。</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> &#123; <span class="title class_">Liquid</span> &#125; = <span class="built_in">require</span>(<span class="string">&#x27;liquidjs&#x27;</span>);</span><br><span class="line"><span class="keyword">var</span> engine = <span class="keyword">new</span> <span class="title class_">Liquid</span>(&#123;</span><br><span class="line"> <span class="attr">cache</span>: <span class="literal">true</span></span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// LiquidJS 将会解析 hello.liquid 然后用 &#123;name: &#x27;alice&#x27;&#125; 渲染它</span></span><br><span class="line">engine.<span class="title function_">renderFileSync</span>(<span class="string">&#x27;hello&#x27;</span>, &#123;<span class="attr">name</span>: <span class="string">&#x27;alice&#x27;</span>&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">// LiquidJS 会找到上次 hello.liquid 解析的结果模板,再用 &#123;name: &#x27;bob&#x27;&#125; 渲染它</span></span><br><span class="line">engine.<span class="title function_">renderFileSync</span>(<span class="string">&#x27;hello&#x27;</span>, &#123;<span class="attr">name</span>: <span class="string">&#x27;bob&#x27;</span>&#125;)</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">var</span> <span class="token punctuation">&#123;</span> Liquid <span class="token punctuation">&#125;</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'liquidjs'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> engine <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Liquid</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
<span class="token literal-property property">cache</span><span class="token operator">:</span> <span class="token boolean">true</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// LiquidJS 将会解析 hello.liquid 然后用 &#123;name: 'alice'&#125; 渲染它</span>
engine<span class="token punctuation">.</span><span class="token function">renderFileSync</span><span class="token punctuation">(</span><span class="token string">'hello'</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span><span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'alice'</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token comment">// LiquidJS 会找到上次 hello.liquid 解析的结果模板,再用 &#123;name: 'bob'&#125; 渲染它</span>
engine<span class="token punctuation">.</span><span class="token function">renderFileSync</span><span class="token punctuation">(</span><span class="token string">'hello'</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span><span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'bob'</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.430Z" itemprop="dateModified">上次更新:2024-08-19</time>
<time class="article-footer-updated" datetime="2024-08-20T01:26:05.768Z" itemprop="dateModified">上次更新:2024-08-20</time>
<a href="use-in-expressjs.html" class="article-footer-prev" title="Express.js 中使用"><i class="icon-chevron-left"></i><span>上一页</span></a><a href="escaping.html" class="article-footer-next" title="转义"><span>下一页</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-19T19:37:03.734Z" itemprop="dateModified">上次更新:2024-08-19</time>
<time class="article-footer-updated" datetime="2024-08-20T01:26:42.372Z" itemprop="dateModified">上次更新:2024-08-20</time>
<a href="migrate-to-9.html" class="article-footer-prev" title="迁移到 LiquidJS 9"><i class="icon-chevron-left"></i><span>上一页</span></a><a href="differences.html" class="article-footer-next" title="与 Shopify/liquid 的不同"><span>下一页</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-19T19:36:26.430Z" itemprop="dateModified">上次更新:2024-08-19</time>
<time class="article-footer-updated" datetime="2024-08-20T01:26:05.768Z" itemprop="dateModified">上次更新:2024-08-20</time>
<a href="differences.html" class="article-footer-prev" title="与 Shopify/liquid 的不同"><i class="icon-chevron-left"></i><span>上一页</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-19T19:36:26.430Z" itemprop="dateModified">上次更新:2024-08-19</time>
<time class="article-footer-updated" datetime="2024-08-20T01:26:05.768Z" itemprop="dateModified">上次更新:2024-08-20</time>
<a href="changelog.html" class="article-footer-prev" title="更新日志"><i class="icon-chevron-left"></i><span>上一页</span></a><a href="contribution-guidelines.html" class="article-footer-next" title="贡献指南"><span>下一页</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+13 -4
View File
@@ -94,23 +94,32 @@
<div class="article-content" itemprop="articleBody">
<p>当模板或数据上下文不可信时,启用DoS预防选项至关重要。LiquidJS 提供了三个选项用于此目的:<code>parseLimit</code><code>renderLimit</code><code>memoryLimit</code></p>
<h2 id="TL-DR" class="article-heading"><a href="#TL-DR" class="headerlink" title="TL;DR"></a>TL;DR<a class="article-anchor" href="#TL-DR" aria-hidden="true"></a></h2><p>设置这些选项可以在很大程度上确保你的 LiquidJS 实例不会长时间挂起或消耗过多内存。这些限制基于可用的 JavaScript API,因此它们不是精确的硬性限制,而是确保你的进程不会失败或挂起的阈值。</p>
<figure class="highlight typescript"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> liquid = <span class="keyword">new</span> <span class="title class_">Liquid</span>(&#123;</span><br><span class="line"> <span class="attr">parseLimit</span>: <span class="number">1e8</span>, <span class="comment">// 每次渲染的模板的典型大小</span></span><br><span class="line"> <span class="attr">renderLimit</span>: <span class="number">1000</span>, <span class="comment">// 每次渲染最多 1s</span></span><br><span class="line"> <span class="attr">memoryLimit</span>: <span class="number">1e9</span>, <span class="comment">// LiquidJS 可用的内存(1e9 对应 1GB)</span></span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">const</span> liquid <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Liquid</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
parseLimit<span class="token operator">:</span> <span class="token number">1e8</span><span class="token punctuation">,</span> <span class="token comment">// 每次渲染的模板的典型大小</span>
renderLimit<span class="token operator">:</span> <span class="token number">1000</span><span class="token punctuation">,</span> <span class="token comment">// 每次渲染最多 1s</span>
memoryLimit<span class="token operator">:</span> <span class="token number">1e9</span><span class="token punctuation">,</span> <span class="token comment">// LiquidJS 可用的内存(1e9 对应 1GB)</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<h2 id="parseLimit" class="article-heading"><a href="#parseLimit" class="headerlink" title="parseLimit"></a>parseLimit<a class="article-anchor" href="#parseLimit" aria-hidden="true"></a></h2><p><a href="/api/interfaces/LiquidOptions.html#parseLimit">parseLimit</a> 限制每次 <code>.parse()</code> 调用中解析的模板大小(字符长度),包括引用的 partials 和 layouts。由于 LiquidJS 解析模板字符串的时间复杂度接近 O(n),限制模板总长度通常就足够了。</p>
<p>普通电脑可以很容易处理 <code>1e8</code>100M)个字符的模板。</p>
<h2 id="renderLimit" class="article-heading"><a href="#renderLimit" class="headerlink" title="renderLimit"></a>renderLimit<a class="article-anchor" href="#renderLimit" aria-hidden="true"></a></h2><p>仅限制模板大小是不够的,因为在渲染时可能会出现动态的数组和循环。<a href="/api/interfaces/LiquidOptions.html#renderLimit">renderLimit</a> 通过限制每次 <code>render()</code> 调用的时间来缓解这些问题。</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;%- for i in (1..10000000) -%&#125;</span><br><span class="line"> order: &#123;&#123;i&#125;&#125;</span><br><span class="line">&#123;%- endfor -%&#125;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-liquid" data-language="liquid"><code class="language-liquid"><span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%-</span> <span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token punctuation">(</span><span class="token number">1</span><span class="token range operator">..</span><span class="token number">10000000</span><span class="token punctuation">)</span> <span class="token delimiter punctuation">-%&#125;</span></span>
order: <span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;&#123;</span>i<span class="token delimiter punctuation">&#125;&#125;</span></span>
<span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%-</span> <span class="token keyword">endfor</span> <span class="token delimiter punctuation">-%&#125;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre>
<p>渲染时间是在渲染每个模板之前检查的。在上面的例子中,循环中有两个模板:<code>order:</code><code>&#123;&#123;i&#125;&#125;</code>,因此会检查 2x10000000 次。</p>
<p>单个模板内的标签和过滤器仍然可能把进程挂起。要完全控制渲染过程,建议使用类似 <a target="_blank" rel="noopener external nofollow noreferrer" href="https://www.npmjs.com/package/paralleljs">paralleljs</a> 的进程管理器。</p>
<h2 id="memoryLimit" class="article-heading"><a href="#memoryLimit" class="headerlink" title="memoryLimit"></a>memoryLimit<a class="article-anchor" href="#memoryLimit" aria-hidden="true"></a></h2><p>即使模板和迭代次数较少,内存使用量也可能呈指数增长。在下面的示例中,内存会在每次迭代中翻倍:</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><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#123;% assign array = &quot;1,2,3&quot; | split: &quot;,&quot; %&#125;</span><br><span class="line">&#123;% for i in (1..32) %&#125;</span><br><span class="line"> &#123;% assign array = array | concat: array %&#125;</span><br><span class="line">&#123;% endfor %&#125;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-liquid" data-language="liquid"><code class="language-liquid"><span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> <span class="token keyword">assign</span> array <span class="token operator">=</span> <span class="token string">"1,2,3"</span> <span class="token operator">|</span> <span class="token function filter">split</span><span class="token operator">:</span> <span class="token string">","</span> <span class="token delimiter punctuation">%&#125;</span></span>
<span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> <span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token punctuation">(</span><span class="token number">1</span><span class="token range operator">..</span><span class="token number">32</span><span class="token punctuation">)</span> <span class="token delimiter punctuation">%&#125;</span></span>
<span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> <span class="token keyword">assign</span> array <span class="token operator">=</span> array <span class="token operator">|</span> <span class="token function filter">concat</span><span class="token operator">:</span> array <span class="token delimiter punctuation">%&#125;</span></span>
<span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> <span class="token keyword">endfor</span> <span class="token delimiter punctuation">%&#125;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre>
<p><a href="/api/interfaces/LiquidOptions.html#memoryLimit">memoryLimit</a> 限制内存敏感的过滤器,以防止过度的内存分配。由于 <a target="_blank" rel="noopener external nofollow noreferrer" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_management">JavaScript 使用 GC 来管理内存</a><code>memoryLimit</code> 仅限制 LiquidJS 中内存敏感过滤器分配的对象总数,因此可能无法反映实际的内存占用。</p>
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.430Z" itemprop="dateModified">上次更新:2024-08-19</time>
<time class="article-footer-updated" datetime="2024-08-20T01:26:05.768Z" itemprop="dateModified">上次更新:2024-08-20</time>
<a href="truthy-and-falsy.html" class="article-footer-prev" title="真和假"><i class="icon-chevron-left"></i><span>上一页</span></a><a href="migrate-to-9.html" class="article-footer-next" title="迁移到 LiquidJS 9"><span>下一页</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+106 -10
View File
@@ -96,7 +96,23 @@
<blockquote class="note info"><strong class="note-title">JavaScript 中的 Drop</strong><p><em>Drop</em> 接口在 LiquidJS 中实现方式与内置过滤器和其他模板功能不同。由于 LiquidJS 在 JavaScript 中运行,自定义 Drop 在 JavaScript 中一定需要重新实现。JavaScript 类与 Ruby 类之间没有兼容性可言。</p>
</blockquote>
<h2 id="基本用法" class="article-heading"><a href="#基本用法" class="headerlink" title="基本用法"></a>基本用法<a class="article-anchor" href="#基本用法" aria-hidden="true"></a></h2><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Liquid</span>, <span class="title class_">Drop</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;liquidjs&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">SettingsDrop</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Drop</span> &#123;</span><br><span class="line"> <span class="title function_">constructor</span>(<span class="params"></span>) &#123;</span><br><span class="line"> <span class="variable language_">super</span>()</span><br><span class="line"> <span class="variable language_">this</span>.<span class="property">foo</span> = <span class="string">&#x27;FOO&#x27;</span></span><br><span class="line"> &#125;</span><br><span class="line"> <span class="title function_">bar</span>(<span class="params"></span>) &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="string">&#x27;BAR&#x27;</span></span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> engine = <span class="keyword">new</span> <span class="title class_">Liquid</span>()</span><br><span class="line"><span class="keyword">const</span> template = <span class="string">`foo: &#123;&#123;settings.foo&#125;&#125;, bar: &#123;&#123;settings.bar&#125;&#125;`</span></span><br><span class="line"><span class="keyword">const</span> context = &#123; <span class="attr">settings</span>: <span class="keyword">new</span> <span class="title class_">SettingsDrop</span>() &#125;</span><br><span class="line"><span class="comment">// 输出: &quot;foo: FOO, bar: BAR&quot;</span></span><br><span class="line">engine.<span class="title function_">parseAndRender</span>(template, context).<span class="title function_">then</span>(<span class="function"><span class="params">html</span> =&gt;</span> <span class="variable language_">console</span>.<span class="title function_">log</span>(html))</span><br></pre></td></tr></table></figure>
<h2 id="基本用法" class="article-heading"><a href="#基本用法" class="headerlink" title="基本用法"></a>基本用法<a class="article-anchor" href="#基本用法" aria-hidden="true"></a></h2><pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">import</span> <span class="token punctuation">&#123;</span> Liquid<span class="token punctuation">,</span> Drop <span class="token punctuation">&#125;</span> <span class="token keyword">from</span> <span class="token string">'liquidjs'</span>
<span class="token keyword">class</span> <span class="token class-name">SettingsDrop</span> <span class="token keyword">extends</span> <span class="token class-name">Drop</span> <span class="token punctuation">&#123;</span>
<span class="token function">constructor</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">super</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>foo <span class="token operator">=</span> <span class="token string">'FOO'</span>
<span class="token punctuation">&#125;</span>
<span class="token function">bar</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">return</span> <span class="token string">'BAR'</span>
<span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">const</span> engine <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Liquid</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> template <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">foo: &#123;&#123;settings.foo&#125;&#125;, bar: &#123;&#123;settings.bar&#125;&#125;</span><span class="token template-punctuation string">`</span></span>
<span class="token keyword">const</span> context <span class="token operator">=</span> <span class="token punctuation">&#123;</span> <span class="token literal-property property">settings</span><span class="token operator">:</span> <span class="token keyword">new</span> <span class="token class-name">SettingsDrop</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#125;</span>
<span class="token comment">// 输出: "foo: FOO, bar: BAR"</span>
engine<span class="token punctuation">.</span><span class="token function">parseAndRender</span><span class="token punctuation">(</span>template<span class="token punctuation">,</span> context<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">html</span> <span class="token operator">=></span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>html<span class="token punctuation">)</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p><a target="_blank" rel="noopener external nofollow noreferrer" href="https://runkit.com/embed/2is7di4mc7kk">Runkit 链接</a></p>
<p>如上所示,除了从上下文作用域中读取属性外,还可以调用方法。您只需创建一个继承自 <code>Drop</code> 的自定义类。</p>
@@ -104,19 +120,93 @@
</blockquote>
<h2 id="liquidMethodMissing" class="article-heading"><a href="#liquidMethodMissing" class="headerlink" title="liquidMethodMissing"></a>liquidMethodMissing<a class="article-anchor" href="#liquidMethodMissing" aria-hidden="true"></a></h2><p>如果属性名不能静态地确定的情况下,可以利用 <code>liquidMethodMissing</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Liquid</span>, <span class="title class_">Drop</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;liquidjs&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">SettingsDrop</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Drop</span> &#123;</span><br><span class="line"> <span class="title function_">liquidMethodMissing</span>(<span class="params">key</span>) &#123;</span><br><span class="line"> <span class="keyword">return</span> key.<span class="title function_">toUpperCase</span>()</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> engine = <span class="keyword">new</span> <span class="title class_">Liquid</span>()</span><br><span class="line"><span class="comment">// 输出: &quot;COO&quot;</span></span><br><span class="line">engine.<span class="title function_">parseAndRender</span>(<span class="string">&quot;&#123;&#123;settings.coo&#125;&#125;&quot;</span>, &#123; <span class="attr">settings</span>: <span class="keyword">new</span> <span class="title class_">SettingsDrop</span>() &#125;)</span><br><span class="line"> .<span class="title function_">then</span>(<span class="function"><span class="params">html</span> =&gt;</span> <span class="variable language_">console</span>.<span class="title function_">log</span>(html))</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">import</span> <span class="token punctuation">&#123;</span> Liquid<span class="token punctuation">,</span> Drop <span class="token punctuation">&#125;</span> <span class="token keyword">from</span> <span class="token string">'liquidjs'</span>
<span class="token keyword">class</span> <span class="token class-name">SettingsDrop</span> <span class="token keyword">extends</span> <span class="token class-name">Drop</span> <span class="token punctuation">&#123;</span>
<span class="token function">liquidMethodMissing</span><span class="token punctuation">(</span><span class="token parameter">key</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">return</span> key<span class="token punctuation">.</span><span class="token function">toUpperCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">const</span> engine <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Liquid</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment">// 输出: "COO"</span>
engine<span class="token punctuation">.</span><span class="token function">parseAndRender</span><span class="token punctuation">(</span><span class="token string">"&#123;&#123;settings.coo&#125;&#125;"</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span> <span class="token literal-property property">settings</span><span class="token operator">:</span> <span class="token keyword">new</span> <span class="token class-name">SettingsDrop</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">html</span> <span class="token operator">=></span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>html<span class="token punctuation">)</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p><code>liquidMethodMissing</code> 支持 Promise,这意味着您可以在其中进行异步调用。一个更有用的例子是通过使用 Drop 动态地从数据库获取值。通过使用 Drop,您可以避免将每个属性都硬编码到上下文中。例如:</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Liquid</span>, <span class="title class_">Drop</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;liquidjs&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">DBDrop</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Drop</span> &#123;</span><br><span class="line"> <span class="keyword">async</span> <span class="title function_">liquidMethodMissing</span>(<span class="params">key</span>) &#123;</span><br><span class="line"> <span class="keyword">const</span> record = <span class="keyword">await</span> db.<span class="title function_">getRecordByKey</span>(key)</span><br><span class="line"> <span class="keyword">return</span> record.<span class="property">value</span></span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> engine = <span class="keyword">new</span> <span class="title class_">Liquid</span>()</span><br><span class="line"><span class="keyword">const</span> context = &#123; <span class="attr">db</span>: <span class="keyword">new</span> <span class="title class_">DBDrop</span>() &#125;</span><br><span class="line">engine.<span class="title function_">parseAndRender</span>(<span class="string">&quot;&#123;&#123;db.coo&#125;&#125;&quot;</span>, context).<span class="title function_">then</span>(<span class="function"><span class="params">html</span> =&gt;</span> <span class="variable language_">console</span>.<span class="title function_">log</span>(html))</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">import</span> <span class="token punctuation">&#123;</span> Liquid<span class="token punctuation">,</span> Drop <span class="token punctuation">&#125;</span> <span class="token keyword">from</span> <span class="token string">'liquidjs'</span>
<span class="token keyword">class</span> <span class="token class-name">DBDrop</span> <span class="token keyword">extends</span> <span class="token class-name">Drop</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">async</span> <span class="token function">liquidMethodMissing</span><span class="token punctuation">(</span><span class="token parameter">key</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">const</span> record <span class="token operator">=</span> <span class="token keyword">await</span> db<span class="token punctuation">.</span><span class="token function">getRecordByKey</span><span class="token punctuation">(</span>key<span class="token punctuation">)</span>
<span class="token keyword">return</span> record<span class="token punctuation">.</span>value
<span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">const</span> engine <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Liquid</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> context <span class="token operator">=</span> <span class="token punctuation">&#123;</span> <span class="token literal-property property">db</span><span class="token operator">:</span> <span class="token keyword">new</span> <span class="token class-name">DBDrop</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#125;</span>
engine<span class="token punctuation">.</span><span class="token function">parseAndRender</span><span class="token punctuation">(</span><span class="token string">"&#123;&#123;db.coo&#125;&#125;"</span><span class="token punctuation">,</span> context<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">html</span> <span class="token operator">=></span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>html<span class="token punctuation">)</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<h2 id="valueOf-NaN" class="article-heading"><a href="#valueOf-NaN" class="headerlink" title="valueOf"></a>valueOf<a class="article-anchor" href="#valueOf-NaN" aria-hidden="true"></a></h2><p>Drop 可以实现一个 <code>valueOf()</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Liquid</span>, <span class="title class_">Drop</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;liquidjs&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">ColorDrop</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Drop</span> &#123;</span><br><span class="line"> <span class="title function_">valueOf</span>(<span class="params"></span>) &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="string">&#x27;red&#x27;</span></span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> engine = <span class="keyword">new</span> <span class="title class_">Liquid</span>()</span><br><span class="line"><span class="keyword">const</span> context = &#123; <span class="attr">color</span>: <span class="keyword">new</span> <span class="title class_">ColorDrop</span>() &#125;</span><br><span class="line"><span class="comment">// 输出: &quot;red&quot;</span></span><br><span class="line">engine.<span class="title function_">parseAndRender</span>(<span class="string">&quot;&#123;&#123;color&#125;&#125;&quot;</span>, context).<span class="title function_">then</span>(<span class="function"><span class="params">html</span> =&gt;</span> <span class="variable language_">console</span>.<span class="title function_">log</span>(html))</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">import</span> <span class="token punctuation">&#123;</span> Liquid<span class="token punctuation">,</span> Drop <span class="token punctuation">&#125;</span> <span class="token keyword">from</span> <span class="token string">'liquidjs'</span>
<span class="token keyword">class</span> <span class="token class-name">ColorDrop</span> <span class="token keyword">extends</span> <span class="token class-name">Drop</span> <span class="token punctuation">&#123;</span>
<span class="token function">valueOf</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">return</span> <span class="token string">'red'</span>
<span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">const</span> engine <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Liquid</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> context <span class="token operator">=</span> <span class="token punctuation">&#123;</span> <span class="token literal-property property">color</span><span class="token operator">:</span> <span class="token keyword">new</span> <span class="token class-name">ColorDrop</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#125;</span>
<span class="token comment">// 输出: "red"</span>
engine<span class="token punctuation">.</span><span class="token function">parseAndRender</span><span class="token punctuation">(</span><span class="token string">"&#123;&#123;color&#125;&#125;"</span><span class="token punctuation">,</span> context<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">html</span> <span class="token operator">=></span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>html<span class="token punctuation">)</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<h2 id="toLiquid" class="article-heading"><a href="#toLiquid" class="headerlink" title="toLiquid"></a>toLiquid<a class="article-anchor" href="#toLiquid" aria-hidden="true"></a></h2><p><code>toLiquid()</code> 不是 <code>Drop</code> 的方法,但它可以用于返回一个 <code>Drop</code>。在您有一个上下文中固定结构且不能更改其值的情况下,您可以实现 <code>toLiquid()</code>,以便让 LiquidJS 使用返回的值而不是自身来渲染模板。</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Liquid</span>, <span class="title class_">Drop</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;liquidjs&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> context = &#123;</span><br><span class="line"> <span class="attr">person</span>: &#123;</span><br><span class="line"> <span class="attr">firstName</span>: <span class="string">&quot;Jun&quot;</span>,</span><br><span class="line"> <span class="attr">lastName</span>: <span class="string">&quot;Yang&quot;</span>,</span><br><span class="line"> <span class="attr">name</span>: <span class="string">&quot;Jun Yang&quot;</span>,</span><br><span class="line"> <span class="attr">toLiquid</span>: <span class="function">() =&gt;</span> (&#123;</span><br><span class="line"> <span class="attr">firstName</span>: <span class="variable language_">this</span>.<span class="property">firstName</span>,</span><br><span class="line"> <span class="attr">lastName</span>: <span class="variable language_">this</span>.<span class="property">lastName</span>,</span><br><span class="line"> <span class="comment">// 使用不同的 `name`</span></span><br><span class="line"> <span class="attr">name</span>: <span class="string">&quot;Yang, Jun&quot;</span></span><br><span class="line"> &#125;)</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> engine = <span class="keyword">new</span> <span class="title class_">Liquid</span>()</span><br><span class="line"><span class="comment">// 输出: &quot;Yang, Jun&quot;</span></span><br><span class="line">engine.<span class="title function_">parseAndRender</span>(<span class="string">&quot;&#123;&#123;person.name&#125;&#125;&quot;</span>, context).<span class="title function_">then</span>(<span class="function"><span class="params">html</span> =&gt;</span> <span class="variable language_">console</span>.<span class="title function_">log</span>(html))</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">import</span> <span class="token punctuation">&#123;</span> Liquid<span class="token punctuation">,</span> Drop <span class="token punctuation">&#125;</span> <span class="token keyword">from</span> <span class="token string">'liquidjs'</span>
<span class="token keyword">const</span> context <span class="token operator">=</span> <span class="token punctuation">&#123;</span>
<span class="token literal-property property">person</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
<span class="token literal-property property">firstName</span><span class="token operator">:</span> <span class="token string">"Jun"</span><span class="token punctuation">,</span>
<span class="token literal-property property">lastName</span><span class="token operator">:</span> <span class="token string">"Yang"</span><span class="token punctuation">,</span>
<span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">"Jun Yang"</span><span class="token punctuation">,</span>
<span class="token function-variable function">toLiquid</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
<span class="token literal-property property">firstName</span><span class="token operator">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span>firstName<span class="token punctuation">,</span>
<span class="token literal-property property">lastName</span><span class="token operator">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span>lastName<span class="token punctuation">,</span>
<span class="token comment">// 使用不同的 `name`</span>
<span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">"Yang, Jun"</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">const</span> engine <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Liquid</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment">// 输出: "Yang, Jun"</span>
engine<span class="token punctuation">.</span><span class="token function">parseAndRender</span><span class="token punctuation">(</span><span class="token string">"&#123;&#123;person.name&#125;&#125;"</span><span class="token punctuation">,</span> context<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">html</span> <span class="token operator">=></span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>html<span class="token punctuation">)</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p>当然,您还可以在 <code>toLiquid()</code> 方法中返回一个 <code>PersonDrop</code> 实例,并在 <code>PersonDrop</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Liquid</span>, <span class="title class_">Drop</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;liquidjs&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">PersonDrop</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Drop</span> &#123;</span><br><span class="line"> <span class="title function_">constructor</span>(<span class="params">person</span>) &#123;</span><br><span class="line"> <span class="variable language_">super</span>()</span><br><span class="line"> <span class="variable language_">this</span>.<span class="property">person</span> = person</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="title function_">name</span>(<span class="params"></span>) &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">person</span>.<span class="property">lastName</span> + <span class="string">&quot;, &quot;</span> + <span class="variable language_">this</span>.<span class="property">person</span>.<span class="property">firstName</span></span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> context = &#123;</span><br><span class="line"> <span class="attr">person</span>: &#123;</span><br><span class="line"> <span class="attr">firstName</span>: <span class="string">&quot;Jun&quot;</span>,</span><br><span class="line"> <span class="attr">lastName</span>: <span class="string">&quot;Yang&quot;</span>,</span><br><span class="line"> <span class="attr">name</span>: <span class="string">&quot;Jun Yang&quot;</span>,</span><br><span class="line"> <span class="attr">toLiquid</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123; <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">PersonDrop</span>(<span class="variable language_">this</span>) &#125;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> engine = <span class="keyword">new</span> <span class="title class_">Liquid</span>()</span><br><span class="line"><span class="comment">// 输出: &quot;Yang, Jun&quot;</span></span><br><span class="line">engine.<span class="title function_">parseAndRender</span>(<span class="string">&quot;&#123;&#123;person.name&#125;&#125;&quot;</span>, context).<span class="title function_">then</span>(<span class="function"><span class="params">html</span> =&gt;</span> <span class="variable language_">console</span>.<span class="title function_">log</span>(html))</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">import</span> <span class="token punctuation">&#123;</span> Liquid<span class="token punctuation">,</span> Drop <span class="token punctuation">&#125;</span> <span class="token keyword">from</span> <span class="token string">'liquidjs'</span>
<span class="token keyword">class</span> <span class="token class-name">PersonDrop</span> <span class="token keyword">extends</span> <span class="token class-name">Drop</span> <span class="token punctuation">&#123;</span>
<span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">person</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">super</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>person <span class="token operator">=</span> person
<span class="token punctuation">&#125;</span>
<span class="token function">name</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>person<span class="token punctuation">.</span>lastName <span class="token operator">+</span> <span class="token string">", "</span> <span class="token operator">+</span> <span class="token keyword">this</span><span class="token punctuation">.</span>person<span class="token punctuation">.</span>firstName
<span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">const</span> context <span class="token operator">=</span> <span class="token punctuation">&#123;</span>
<span class="token literal-property property">person</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
<span class="token literal-property property">firstName</span><span class="token operator">:</span> <span class="token string">"Jun"</span><span class="token punctuation">,</span>
<span class="token literal-property property">lastName</span><span class="token operator">:</span> <span class="token string">"Yang"</span><span class="token punctuation">,</span>
<span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">"Jun Yang"</span><span class="token punctuation">,</span>
<span class="token function-variable function">toLiquid</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">PersonDrop</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span> <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">const</span> engine <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Liquid</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment">// 输出: "Yang, Jun"</span>
engine<span class="token punctuation">.</span><span class="token function">parseAndRender</span><span class="token punctuation">(</span><span class="token string">"&#123;&#123;person.name&#125;&#125;"</span><span class="token punctuation">,</span> context<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">html</span> <span class="token operator">=></span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>html<span class="token punctuation">)</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<blockquote class="note info"><strong class="note-title"><code>toLiquid()</code><code>valueOf()</code> 的区别</strong><ul>
<li><code>valueOf()</code> 通常用来定义当前变量如何渲染,<code>toLiquid()</code> 通常用来把一个对象转换为 Drop 或另一个提供给模板的 scope。</li>
@@ -126,22 +216,28 @@
<h2 id="特殊-Drop" class="article-heading"><a href="#特殊-Drop" class="headerlink" title="特殊 Drop"></a>特殊 Drop<a class="article-anchor" href="#特殊-Drop" aria-hidden="true"></a></h2><p>LiquidJS 本身实现了几个内置 Drop,以促进模板编写。此部分与 Shopify Liquid 兼容,因为我们需要模板具有可移植性。</p>
<h3 id="blank" class="article-heading"><a href="#blank" class="headerlink" title="blank"></a>blank<a class="article-anchor" href="#blank" aria-hidden="true"></a></h3><p>用于检查字符串变量是否为 <code>false</code><code>null</code><code>undefined</code>、空字符串或字符串仅包含空白字符。</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;% unless author == blank %&#125;</span><br><span class="line"> &#123;&#123;author&#125;&#125;</span><br><span class="line">&#123;% endif %&#125;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-liquid" data-language="liquid"><code class="language-liquid"><span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> <span class="token keyword">unless</span> author <span class="token operator">==</span> blank <span class="token delimiter punctuation">%&#125;</span></span>
<span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;&#123;</span>author<span class="token delimiter punctuation">&#125;&#125;</span></span>
<span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> <span class="token keyword">endif</span> <span class="token delimiter punctuation">%&#125;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre>
<h3 id="empty" class="article-heading"><a href="#empty" class="headerlink" title="empty"></a>empty<a class="article-anchor" href="#empty" aria-hidden="true"></a></h3><p>用于检查数组、字符串或对象是否为空。</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;% if authors == empty %&#125;</span><br><span class="line"> 作者列表为空</span><br><span class="line">&#123;% endif %&#125;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-liquid" data-language="liquid"><code class="language-liquid"><span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> <span class="token keyword">if</span> authors <span class="token operator">==</span> <span class="token empty keyword">empty</span> <span class="token delimiter punctuation">%&#125;</span></span>
作者列表为空
<span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> <span class="token keyword">endif</span> <span class="token delimiter punctuation">%&#125;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre>
<blockquote class="note info"><strong class="note-title"><code>empty</code> 的实现</strong><p>对于数组和字符串,LiquidJS 检查它们的 <code>.length</code> 属性。对于对象,LiquidJS 调用 <code>Object.keys()</code> 来检查它是否有键。</p>
</blockquote>
<h3 id="nil" class="article-heading"><a href="#nil" class="headerlink" title="nil"></a>nil<a class="article-anchor" href="#nil" aria-hidden="true"></a></h3><p><code>nil</code> Drop 用于检查变量是否未定义或定义为 <code>null</code><code>undefined</code>,本质上等同于 JavaScript 的 <code>== null</code> 检查。</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;% if notexist == nil %&#125;</span><br><span class="line"> 空变量</span><br><span class="line">&#123;% endif %&#125;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-liquid" data-language="liquid"><code class="language-liquid"><span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> <span class="token keyword">if</span> notexist <span class="token operator">==</span> <span class="token boolean">nil</span> <span class="token delimiter punctuation">%&#125;</span></span>
空变量
<span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> <span class="token keyword">endif</span> <span class="token delimiter punctuation">%&#125;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre>
<h3 id="其他-Drop" class="article-heading"><a href="#其他-Drop" class="headerlink" title="其他 Drop"></a>其他 Drop<a class="article-anchor" href="#其他-Drop" aria-hidden="true"></a></h3><p>仍然有一些特定标签的 Drop,例如 <code>forloop</code><code>tablerowloop</code><code>block</code>,这些在各自的标签文档中有详细介绍。</p>
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.430Z" itemprop="dateModified">上次更新:2024-08-19</time>
<time class="article-footer-updated" datetime="2024-08-20T01:26:05.768Z" itemprop="dateModified">上次更新:2024-08-20</time>
<a href="render-tag-content.html" class="article-footer-prev" title="渲染标签内容"><i class="icon-chevron-left"></i><span>上一页</span></a><a href="sync-and-async.html" class="article-footer-next" title="同步和异步"><span>下一页</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+15 -9
View File
@@ -99,37 +99,43 @@
</ol>
<h2 id="HTML-转义" class="article-heading"><a href="#HTML-转义" class="headerlink" title="HTML 转义"></a>HTML 转义<a class="article-anchor" href="#HTML-转义" aria-hidden="true"></a></h2><p>默认情况下输出是不转义的,但你可以用 <a href="../filters/escape.html">escape</a> 过滤器来做 HTML 转义:</p>
<p>输入</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;&#123; &quot;1 &lt; 2&quot; | escape &#125;&#125;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-liquid" data-language="liquid"><code class="language-liquid"><span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;&#123;</span> <span class="token string">"1 &lt; 2"</span> <span class="token operator">|</span> <span class="token function filter">escape</span> <span class="token delimiter punctuation">&#125;&#125;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p>输出</p>
<figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">1 &amp;lt; 2</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-text" data-language="text"><code class="language-text">1 &amp;lt; 2<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p>LiquidJS 也提供了其他过滤器来支持不同的转义需求:<a href="../filters/escape.html">escape_once</a>, <a href="../filters/newline_to_br.html">newline_to_br</a>, <a href="../filters/strip_html.html">strip_html</a></p>
<p>当输出的变量不被信任时,可以把 <a href="./options.html#outputEscape">outputEscape</a> 参数设置为 <code>&quot;escape&quot;</code> 来启用默认 HTML 转义。这种情况下,如果你需要某个输出不被转义,则需要使用 <a href="../filters/raw.html">raw</a> 过滤器:</p>
<p>输入</p>
<figure class="highlight plaintext"><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">&#123;&#123; &quot;1 &lt; 2&quot; &#125;&#125;</span><br><span class="line">&#123;&#123; &quot;&lt;button&gt;OK&lt;/button&gt;&quot; | raw &#125;&#125;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-liquid" data-language="liquid"><code class="language-liquid"><span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;&#123;</span> <span class="token string">"1 &lt; 2"</span> <span class="token delimiter punctuation">&#125;&#125;</span></span>
<span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;&#123;</span> <span class="token string">"&lt;button>OK&lt;/button>"</span> <span class="token operator">|</span> <span class="token keyword">raw</span> <span class="token delimiter punctuation">&#125;&#125;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre>
<p>输出</p>
<figure class="highlight text"><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 &amp;lt; 2</span><br><span class="line">&lt;button&gt;OK&lt;/button&gt;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-text" data-language="text"><code class="language-text">1 &amp;lt; 2
&lt;button>OK&lt;/button><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre>
<h2 id="Liquid-转义" class="article-heading"><a href="#Liquid-转义" class="headerlink" title="Liquid 转义"></a>Liquid 转义<a class="article-anchor" href="#Liquid-转义" aria-hidden="true"></a></h2><p>为了输出 Liquid 的特殊字符比如 <code>&#123;&#123;</code><code>&#123;%</code>,你需要 <a href="../filters/raw.html">raw</a> 标签。</p>
<p>输入</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><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#123;% raw %&#125;</span><br><span class="line"> In LiquidJS, &#123;&#123; this | escape &#125;&#125; will be HTML-escaped, but</span><br><span class="line"> &#123;&#123;&#123; that &#125;&#125;&#125; will not.</span><br><span class="line">&#123;% endraw %&#125;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-liquid" data-language="liquid"><code class="language-liquid"><span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> <span class="token keyword">raw</span> <span class="token delimiter punctuation">%&#125;</span></span>
In LiquidJS, &#123;&#123; this | escape &#125;&#125; will be HTML-escaped, but
&#123;&#123;&#123; that &#125;&#125;&#125; will not.
<span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> <span class="token keyword">endraw</span> <span class="token delimiter punctuation">%&#125;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre>
<p>输出</p>
<figure class="highlight text"><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">In LiquidJS, &#123;&#123; this | escape &#125;&#125; will be HTML-escaped, but</span><br><span class="line">&#123;&#123;&#123; that &#125;&#125;&#125; will not.</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-text" data-language="text"><code class="language-text">In LiquidJS, &#123;&#123; this | escape &#125;&#125; will be HTML-escaped, but
&#123;&#123;&#123; that &#125;&#125;&#125; will not.<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre>
<p>Within strings literals in LiquidJS template, <code>\</code> can be used to escape special characters in string syntax. For example:</p>
<p>输入</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;&#123; &quot;\&quot;&quot; &#125;&#125;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-liquid" data-language="liquid"><code class="language-liquid"><span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;&#123;</span> <span class="token string">"\"</span>" <span class="token delimiter punctuation">&#125;&#125;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p>输出</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&quot;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-liquid" data-language="liquid"><code class="language-liquid">"<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.430Z" itemprop="dateModified">上次更新:2024-08-19</time>
<time class="article-footer-updated" datetime="2024-08-20T01:26:05.768Z" itemprop="dateModified">上次更新:2024-08-20</time>
<a href="caching.html" class="article-footer-prev" title="缓存"><i class="icon-chevron-left"></i><span>上一页</span></a><a href="register-filters-tags.html" class="article-footer-next" title="注册标签/过滤器"><span>下一页</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+10 -6
View File
@@ -102,26 +102,30 @@
</blockquote>
<h2 id="输出" class="article-heading"><a href="#输出" class="headerlink" title="输出"></a>输出<a class="article-anchor" href="#输出" aria-hidden="true"></a></h2><p><strong>输出</strong> 用于转换和输出变量到 HTML。下面的模板将会把 <code>username</code> 的值插入到 input 的 <code>value</code></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;input type=&quot;text&quot; name=&quot;user&quot; value=&quot;&#123;&#123;username&#125;&#125;&quot;&gt;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-liquid" data-language="liquid"><code class="language-liquid"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>user<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;&#123;</span>username<span class="token delimiter punctuation">&#125;&#125;</span></span><span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p><em>输出</em> 里的值可以在输出之前经过若干个 <strong>过滤器</strong> 的转换。比如在变量后面追加一个字符串:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;&#123; username | append: &quot;, welcome to LiquidJS!&quot; &#125;&#125;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-liquid" data-language="liquid"><code class="language-liquid"><span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;&#123;</span> username <span class="token operator">|</span> <span class="token function filter">append</span><span class="token operator">:</span> <span class="token string">", welcome to LiquidJS!"</span> <span class="token delimiter punctuation">&#125;&#125;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p>过滤器可以级联,用起来像管道一样:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;&#123; username | append: &quot;, welcome to LiquidJS!&quot; | capitalize &#125;&#125;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-liquid" data-language="liquid"><code class="language-liquid"><span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;&#123;</span> username <span class="token operator">|</span> <span class="token function filter">append</span><span class="token operator">:</span> <span class="token string">", welcome to LiquidJS!"</span> <span class="token operator">|</span> <span class="token function filter">capitalize</span> <span class="token delimiter punctuation">&#125;&#125;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p><a href="../filters/overview.html">这里</a> 是 LiquidJS 支持的完整的过滤器列表。</p>
<h2 id="标签" class="article-heading"><a href="#标签" class="headerlink" title="标签"></a>标签<a class="article-anchor" href="#标签" aria-hidden="true"></a></h2><p><strong>标签</strong> 用于控制模板渲染过程,操作模板变量,和其他模板交互等。例如 <code>assign</code> 可以用来定义一个模板中可以使用的变量:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% assign foo = &quot;FOO&quot; %&#125;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-liquid" data-language="liquid"><code class="language-liquid"><span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> <span class="token keyword">assign</span> foo <span class="token operator">=</span> <span class="token string">"FOO"</span> <span class="token delimiter punctuation">%&#125;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p>一般标签成对地出现,一个开始标签和一个对应的结束标签,比如:</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><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#123;% if foo == &quot;FOO&quot; %&#125;</span><br><span class="line"> Variable `foo` equals &quot;FOO&quot;</span><br><span class="line">&#123;% else %&#125;</span><br><span class="line"> Variable `foo` not equals &quot;FOO&quot;</span><br><span class="line">&#123;% endif %&#125;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-liquid" data-language="liquid"><code class="language-liquid"><span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> <span class="token keyword">if</span> foo <span class="token operator">==</span> <span class="token string">"FOO"</span> <span class="token delimiter punctuation">%&#125;</span></span>
Variable `foo` equals "FOO"
<span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> <span class="token keyword">else</span> <span class="token delimiter punctuation">%&#125;</span></span>
Variable `foo` not equals "FOO"
<span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> <span class="token keyword">endif</span> <span class="token delimiter punctuation">%&#125;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p><a href="../tags/overview.html">这里</a> 是 LiquidJS 支持的完整的标签列表。</p>
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.430Z" itemprop="dateModified">上次更新:2024-08-19</time>
<time class="article-footer-updated" datetime="2024-08-20T01:26:05.768Z" itemprop="dateModified">上次更新:2024-08-20</time>
<a href="setup.html" class="article-footer-next" title="安装"><span>下一页</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-19T19:36:26.430Z" itemprop="dateModified">上次更新:2024-08-19</time>
<time class="article-footer-updated" datetime="2024-08-20T01:26:05.768Z" itemprop="dateModified">上次更新:2024-08-20</time>
<a href="dos.html" class="article-footer-prev" title="DoS"><i class="icon-chevron-left"></i><span>上一页</span></a><a href="changelog.html" class="article-footer-next" title="更新日志"><span>下一页</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-19T19:36:26.430Z" itemprop="dateModified">上次更新:2024-08-19</time>
<time class="article-footer-updated" datetime="2024-08-20T01:26:05.768Z" itemprop="dateModified">上次更新:2024-08-20</time>
<a href="plugins.html" class="article-footer-prev" title="插件"><i class="icon-chevron-left"></i><span>上一页</span></a><a href="truthy-and-falsy.html" class="article-footer-next" title="真和假"><span>下一页</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+18 -7
View File
@@ -93,7 +93,10 @@
</header>
<div class="article-content" itemprop="articleBody">
<p><a href="/api/classes/Liquid.html">Liquid</a> 构造函数接受一个参数对象,用来定义各种模板引擎行为。这些参数都是可选的,比如我可以指定其中一个参数 <code>cache</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> &#123; <span class="title class_">Liquid</span> &#125; = <span class="built_in">require</span>(<span class="string">&#x27;liquidjs&#x27;</span>)</span><br><span class="line"><span class="keyword">const</span> engine = <span class="keyword">new</span> <span class="title class_">Liquid</span>(&#123;</span><br><span class="line"> <span class="attr">cache</span>: <span class="literal">true</span></span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">const</span> <span class="token punctuation">&#123;</span> Liquid <span class="token punctuation">&#125;</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'liquidjs'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> engine <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Liquid</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
<span class="token literal-property property">cache</span><span class="token operator">:</span> <span class="token boolean">true</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre>
<blockquote class="note info"><strong class="note-title">API 文档</strong><p>下面的所有选项的概述,希望了解具体的类型和签名,请前往 <a href="https://liquidjs.com/api/interfaces/LiquidOptions.html" target="_self">LiquidOptions | API</a>.</p>
</blockquote>
@@ -108,10 +111,10 @@
<p>注意由于历史原因这个选项叫做 dynamicPartials,但它对 layout 也起作用。</p>
</blockquote>
<p><strong>dynamicPartials</strong> 表示是否把传给 <a href="../tags/include.html">include</a>, <a href="../tags/render.html">render</a>, <a href="../tags/layout.html">layout</a> 标签的文件名当做变量处理。默认为 <code>true</code>。例如用上下文 <code>&#123; file: &#39;foo.html&#39; &#125;</code> 渲染下面的模板将会引入文件 <code>foo.html</code></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% include file %&#125;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-liquid" data-language="liquid"><code class="language-liquid"><span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> <span class="token keyword">include</span> file <span class="token delimiter punctuation">%&#125;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p>设置 <code>dynamicPartials: false</code> 后 LiquidJS 将会尝试去读取 <code>file</code>。当你的模板之间都是静态引入关系时会很有用:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% liquid foo.html %&#125;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-liquid" data-language="liquid"><code class="language-liquid"><span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> <span class="token keyword">liquid</span> foo<span class="token punctuation">.</span>html <span class="token delimiter punctuation">%&#125;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<blockquote class="note warn"><strong class="note-title">常见陷阱</strong><p>LiquidJS 把这个选项默认值设为 <code>true</code> 以兼容于 shopify/liquid,但如果你在使用 <a href="https://github.com/11ty/eleventy" rel="external nofollow noreferrer" target="_blank">eleventy</a> 它会设置默认值 <code>false</code> (参考 <a href="https://www.11ty.dev/docs/languages/liquid/#quoted-include-paths" rel="external nofollow noreferrer" target="_blank">Quoted Include Paths</a>)以兼容于 Jekyll。</p>
</blockquote>
@@ -125,10 +128,18 @@
<li>参数放到了 <code>include</code> 变量下,而非当前作用域。</li>
</ul>
<p>例如下面的模板中,<code>name.html</code> 没有带引号,<code>header</code><code>&quot;HEADER&quot;</code><code>=</code> 分隔,<code>header</code> 参数通过 <code>include.header</code> 来引用。更多详情请参考 <a href="../tags/include.html">include</a></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><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></pre></td><td class="code"><pre><span class="line">// entry template</span><br><span class="line">&#123;% include article.html header=&quot;HEADER&quot; content=&quot;CONTENT&quot; %&#125;</span><br><span class="line"></span><br><span class="line">// article.html</span><br><span class="line">&lt;article&gt;</span><br><span class="line"> &lt;header&gt;&#123;&#123;include.header&#125;&#125;&lt;/header&gt;</span><br><span class="line"> &#123;&#123;include.content&#125;&#125;</span><br><span class="line">&lt;/article&gt;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-liquid" data-language="liquid"><code class="language-liquid">// entry template
<span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> <span class="token keyword">include</span> <span class="token object">article</span><span class="token punctuation">.</span>html header<span class="token operator">=</span><span class="token string">"HEADER"</span> content<span class="token operator">=</span><span class="token string">"CONTENT"</span> <span class="token delimiter punctuation">%&#125;</span></span>
// article.html
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>article</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>header</span><span class="token punctuation">></span></span><span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;&#123;</span><span class="token keyword">include</span><span class="token punctuation">.</span>header<span class="token delimiter punctuation">&#125;&#125;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>header</span><span class="token punctuation">></span></span>
<span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;&#123;</span><span class="token keyword">include</span><span class="token punctuation">.</span>content<span class="token delimiter punctuation">&#125;&#125;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>article</span><span class="token punctuation">></span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<h2 id="extname" class="article-heading"><a href="#extname" class="headerlink" title="extname"></a>extname<a class="article-anchor" href="#extname" aria-hidden="true"></a></h2><p><strong>extname</strong> 定义了默认的文件后缀,当传入文件名不包含后缀时自动追加。默认值是 <code>&#39;&#39;</code> 也就是说默认是禁用的。如果设置为 <code>.liquid</code></p>
<figure class="highlight plaintext"><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">&#123;% render &quot;foo&quot; %&#125; 没有后缀,添加 &quot;.liquid&quot; 并加载 foo.liquid</span><br><span class="line">&#123;% render &quot;foo.html&quot; %&#125; 已经有后缀了,直接加载 foo.html</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-liquid" data-language="liquid"><code class="language-liquid"><span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> <span class="token keyword">render</span> <span class="token string">"foo"</span> <span class="token delimiter punctuation">%&#125;</span></span> 没有后缀,添加 ".liquid" 并加载 foo.liquid
<span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> <span class="token keyword">render</span> <span class="token string">"foo.html"</span> <span class="token delimiter punctuation">%&#125;</span></span> 已经有后缀了,直接加载 foo.html<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre>
<blockquote class="note info"><strong class="note-title">旧版行为</strong><p>在 2.0.1 之前,<code>extname</code> 默认值为 <code>.liquid</code>。要禁用它需要明确设置为 <code>extname: ''</code>。详情参考 <a href="https://github.com/harttle/liquidjs/issues/41" rel="external nofollow noreferrer" target="_blank">#41</a></p>
</blockquote>
@@ -148,7 +159,7 @@
<p><strong>dateFormat</strong> 用于指定输出日期的默认格式. <code>%A, %B %-e, %Y at %-l:%M %P %z</code> 如果未指定,将使用. 例如,设置 <code>dateFormat: %Y-%m-%dT%H:%M:%S:%LZ</code> 以输出 [JavaSrcipt Date.toJson()][<a target="_blank" rel="noopener external nofollow noreferrer" href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Date/toJSON]">https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Date/toJSON]</a> 格式.</p>
<h2 id="换行和缩进" class="article-heading"><a href="#换行和缩进" class="headerlink" title="换行和缩进"></a>换行和缩进<a class="article-anchor" href="#换行和缩进" aria-hidden="true"></a></h2><p><strong>greedy</strong>, <strong>trimOutputLeft</strong>, <strong>trimOutputRight</strong>, <strong>trimTagLeft</strong>, <strong>trimTagRight</strong> 选项用来移除 Liquid 语法周围的换行和缩进,详情请参考 <a href="./whitespace-control.html">Whitespace Control</a></p>
<h2 id="自定义分隔符" class="article-heading"><a href="#自定义分隔符" class="headerlink" title="自定义分隔符"></a>自定义分隔符<a class="article-anchor" href="#自定义分隔符" aria-hidden="true"></a></h2><p><strong>outputDelimiterLeft</strong>, <strong>outputDelimiterRight</strong>, <strong>tagDelimiterLeft</strong>, <strong>tagDelimiterRight</strong> 用来自定义 LiquidJS 中 <a href="./intro-to-liquid.html">标签和过滤器</a> 的分隔符。例如设置了 <code>outputDelimiterLeft: &lt;%=, outputDelimiterRight: %&gt;</code> 后我们可以避免跟其他模板引擎冲突:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;%= username | append: &quot;, welcome to LiquidJS!&quot; %&gt;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-ejs" data-language="ejs"><code class="language-ejs"><span class="token ejs language-ejs"><span class="token delimiter punctuation">&lt;%=</span><span class="token language-javascript"> username <span class="token operator">|</span> append<span class="token operator">:</span> <span class="token string">", welcome to LiquidJS!"</span> </span><span class="token delimiter punctuation">%></span></span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<h2 id="严格模式" class="article-heading"><a href="#严格模式" class="headerlink" title="严格模式"></a>严格模式<a class="article-anchor" href="#严格模式" aria-hidden="true"></a></h2><p><strong>strictFilters</strong> 用来启用过滤器的严格模式,如果设置为 <code>true</code> 过滤器不存在时解析会抛出异常。默认为 <code>false</code>,这时会跳过不存在的过滤器。</p>
<p><strong>strictVariables</strong> 用来启用变量严格模式。如果设置为 <code>true</code> 变量不存在时渲染会抛出异常,默认为 <code>false</code> 这时不存在的变量会被渲染为空字符串。</p>
@@ -160,7 +171,7 @@
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.430Z" itemprop="dateModified">上次更新:2024-08-19</time>
<time class="article-footer-updated" datetime="2024-08-20T01:26:05.768Z" itemprop="dateModified">上次更新:2024-08-20</time>
<a href="setup.html" class="article-footer-prev" title="安装"><i class="icon-chevron-left"></i><span>上一页</span></a><a href="render-file.html" class="article-footer-next" title="文件渲染"><span>下一页</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+51 -6
View File
@@ -93,31 +93,76 @@
</header>
<div class="article-content" itemprop="articleBody">
<h2 id="访问原始参数" class="article-heading"><a href="#访问原始参数" class="headerlink" title="访问原始参数"></a>访问原始参数<a class="article-anchor" href="#访问原始参数" aria-hidden="true"></a></h2><p><a href="/tutorials/register-filters-tags.html">注册过滤器和标签</a> 中提到,可以通过 <code>tagToken.args</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></pre></td><td class="code"><pre><span class="line"><span class="comment">// Usage: &#123;% random foo bar coo %&#125;</span></span><br><span class="line"><span class="comment">// Output: &quot;foo&quot;, &quot;bar&quot; or &quot;coo&quot;</span></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">// tagToken.args === &quot;foo bar coo&quot;</span></span><br><span class="line"> <span class="variable language_">this</span>.<span class="property">items</span> = tagToken.<span class="property">args</span>.<span class="title function_">split</span>(<span class="string">&#x27; &#x27;</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">// get a random index</span></span><br><span class="line"> <span class="keyword">const</span> index = <span class="title class_">Math</span>.<span class="title function_">floor</span>(<span class="variable language_">this</span>.<span class="property">items</span>.<span class="property">length</span> * <span class="title class_">Math</span>.<span class="title function_">random</span>())</span><br><span class="line"> <span class="comment">// output that item</span></span><br><span class="line"> emitter.<span class="title function_">write</span>(<span class="variable language_">this</span>.<span class="property">items</span>[index])</span><br><span class="line"> &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token comment">// Usage: &#123;% random foo bar coo %&#125;</span>
<span class="token comment">// Output: "foo", "bar" or "coo"</span>
engine<span class="token punctuation">.</span><span class="token function">registerTag</span><span class="token punctuation">(</span><span class="token string">'random'</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span>
<span class="token function">parse</span><span class="token punctuation">(</span><span class="token parameter">tagToken</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token comment">// tagToken.args === "foo bar coo"</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>items <span class="token operator">=</span> tagToken<span class="token punctuation">.</span>args<span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">' '</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
<span class="token function">render</span><span class="token punctuation">(</span><span class="token parameter">context<span class="token punctuation">,</span> emitter</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token comment">// get a random index</span>
<span class="token keyword">const</span> index <span class="token operator">=</span> Math<span class="token punctuation">.</span><span class="token function">floor</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>items<span class="token punctuation">.</span>length <span class="token operator">*</span> Math<span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token comment">// output that item</span>
emitter<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>items<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p>见这个 JSFiddle<a target="_blank" rel="noopener external nofollow noreferrer" href="http://jsfiddle.net/ctj364up/2/">http://jsfiddle.net/ctj364up/2/</a></p>
<h2 id="解析参数的值" class="article-heading"><a href="#解析参数的值" class="headerlink" title="解析参数的值"></a>解析参数的值<a class="article-anchor" href="#解析参数的值" aria-hidden="true"></a></h2><p>除了静态的参数字符串之外,我们更希望把动态的值传递给标签。LiquidJS 中的值可以是字面量(字符串、数字等,也可以是当前上下文的变量。</p>
<p>下面是修改过的模板,也包含三个值用来随机。但它们表示的是值而不是静态的字符串。第一个是字符串字面量,第二个是标识符(表示变量),第三个是属性访问表达式,包含两个标识符。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% random &quot;foo&quot; bar obj.coo %&#125;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-liquid" data-language="liquid"><code class="language-liquid"><span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> random <span class="token string">"foo"</span> bar obj<span class="token punctuation">.</span>coo <span class="token delimiter punctuation">%&#125;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p>解析这么多种情况会很麻烦,但 LiquidJS 提供了 <a href="/api/classes/Tokenizer.html">Tokenizer</a> 类来处理这种情况。</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></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_">Tokenizer</span>, evalToken &#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="keyword">const</span> tokenizer = <span class="keyword">new</span> <span class="title class_">Tokenizer</span>(tagToken.<span class="property">args</span>)</span><br><span class="line"> <span class="variable language_">this</span>.<span class="property">items</span> = []</span><br><span class="line"> <span class="keyword">while</span> (!tokenizer.<span class="title function_">end</span>()) &#123;</span><br><span class="line"> <span class="comment">// here readValue() returns a LiteralToken or PropertyAccessToken</span></span><br><span class="line"> <span class="variable language_">this</span>.<span class="property">items</span>.<span class="title function_">push</span>(tokenizer.<span class="title function_">readValue</span>())</span><br><span class="line"> &#125;</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> index = <span class="title class_">Math</span>.<span class="title function_">floor</span>(<span class="variable language_">this</span>.<span class="property">items</span>.<span class="property">length</span> * <span class="title class_">Math</span>.<span class="title function_">random</span>())</span><br><span class="line"> <span class="keyword">const</span> token = <span class="variable language_">this</span>.<span class="property">items</span>[index]</span><br><span class="line"> <span class="comment">// in LiquidJS, we use yield to wait for async call</span></span><br><span class="line"> <span class="keyword">const</span> value = <span class="keyword">yield</span> <span class="title function_">evalToken</span>(token, context)</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>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">const</span> <span class="token punctuation">&#123;</span> Liquid<span class="token punctuation">,</span> Tokenizer<span class="token punctuation">,</span> evalToken <span class="token punctuation">&#125;</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'liquidjs'</span><span class="token punctuation">)</span>
engine<span class="token punctuation">.</span><span class="token function">registerTag</span><span class="token punctuation">(</span><span class="token string">'random'</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span>
<span class="token function">parse</span><span class="token punctuation">(</span><span class="token parameter">tagToken</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">const</span> tokenizer <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Tokenizer</span><span class="token punctuation">(</span>tagToken<span class="token punctuation">.</span>args<span class="token punctuation">)</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>items <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token operator">!</span>tokenizer<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token comment">// here readValue() returns a LiteralToken or PropertyAccessToken</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>items<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>tokenizer<span class="token punctuation">.</span><span class="token function">readValue</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
<span class="token operator">*</span> <span class="token function">render</span><span class="token punctuation">(</span><span class="token parameter">context<span class="token punctuation">,</span> emitter</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">const</span> index <span class="token operator">=</span> Math<span class="token punctuation">.</span><span class="token function">floor</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>items<span class="token punctuation">.</span>length <span class="token operator">*</span> Math<span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> token <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>items<span class="token punctuation">[</span>index<span class="token punctuation">]</span>
<span class="token comment">// in LiquidJS, we use yield to wait for async call</span>
<span class="token keyword">const</span> value <span class="token operator">=</span> <span class="token keyword">yield</span> <span class="token function">evalToken</span><span class="token punctuation">(</span>token<span class="token punctuation">,</span> context<span class="token punctuation">)</span>
emitter<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p>用上下文 <code>&#123; bar: &quot;bar&quot;, obj: &#123; coo: &quot;coo&quot; &#125; &#125;</code> 来调用这个标签可以得到上第一个例子一样的效果。见这个 JSFiddle:<a target="_blank" rel="noopener external nofollow noreferrer" href="http://jsfiddle.net/ctj364up/3/">http://jsfiddle.net/ctj364up/3/</a>.</p>
<blockquote class="note info"><strong class="note-title">异步和 Promise</strong><p>在 LiquidJS 里异步用生成器实现,这样同样一份标签的实现也可以用于同步的 API 比如 <code>renderSync()</code><code>parseAndRenderSync()</code><code>renderFileSync()</code>。如果要在标签实现里等待 Promise,只需要把 <code>await somePromise</code> 换成 <code>yield somePromise</code>,并保留 <code>* render()</code> 不要改成 <code>async render()</code>。更多细节请参考 <a href="/tutorials/sync-and-async.html">Sync and Async</a></p>
</blockquote>
<h2 id="把键值对解析为命名参数" class="article-heading"><a href="#把键值对解析为命名参数" class="headerlink" title="把键值对解析为命名参数"></a>把键值对解析为命名参数<a class="article-anchor" href="#把键值对解析为命名参数" aria-hidden="true"></a></h2><p>当参数很多时或者有可选参数时,使用命名参数语法会很方便。这时参数由无序的键值对构成,LiquidJS 中的 <a href="/api/classes/Hash.html">Hash</a> 类就是来处理这种情况的。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% random from:2, to:max %&#125;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-liquid" data-language="liquid"><code class="language-liquid"><span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> random from<span class="token operator">:</span><span class="token number">2</span><span class="token punctuation">,</span> to<span class="token operator">:</span>max <span class="token delimiter punctuation">%&#125;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p>上面的例子用来产生 [2, max] 范围内的随机数。我们要用 <code>Hash</code> 来解析 <code>from</code><code>to</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></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">// 解析参数结果,存到 `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">// 在当前 `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>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">const</span> <span class="token punctuation">&#123;</span> Liquid<span class="token punctuation">,</span> Hash <span class="token punctuation">&#125;</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'liquidjs'</span><span class="token punctuation">)</span>
engine<span class="token punctuation">.</span><span class="token function">registerTag</span><span class="token punctuation">(</span><span class="token string">'random'</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span>
<span class="token function">parse</span><span class="token punctuation">(</span><span class="token parameter">tagToken</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token comment">// 解析参数结果,存到 `this.args` 里</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>args <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Hash</span><span class="token punctuation">(</span>tagToken<span class="token punctuation">.</span>args<span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
<span class="token operator">*</span> <span class="token function">render</span><span class="token punctuation">(</span><span class="token parameter">context<span class="token punctuation">,</span> emitter</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token comment">// 在当前 `context` 下计算参数的值</span>
<span class="token keyword">const</span> <span class="token punctuation">&#123;</span>from<span class="token punctuation">,</span> to<span class="token punctuation">&#125;</span> <span class="token operator">=</span> <span class="token keyword">yield</span> <span class="token keyword">this</span><span class="token punctuation">.</span>args<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span>context<span class="token punctuation">)</span>
<span class="token keyword">const</span> length <span class="token operator">=</span> to <span class="token operator">-</span> from <span class="token operator">+</span> <span class="token number">1</span>
<span class="token keyword">const</span> value <span class="token operator">=</span> from <span class="token operator">+</span> Math<span class="token punctuation">.</span><span class="token function">floor</span><span class="token punctuation">(</span>length <span class="token operator">*</span> Math<span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
emitter<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p><code>&#123; max: 10 &#125;</code> 上下文上渲染 <code>{% random from:2, to:max %}</code> 将会得到 [2, 10] 范围内的随机数。见这个 JSFiddle:<a target="_blank" rel="noopener external nofollow noreferrer" href="http://jsfiddle.net/ctj364up/4/">http://jsfiddle.net/ctj364up/4/</a></p>
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.430Z" itemprop="dateModified">上次更新:2024-08-19</time>
<time class="article-footer-updated" datetime="2024-08-20T01:26:05.768Z" itemprop="dateModified">上次更新:2024-08-20</time>
<a href="access-scope-in-filters.html" class="article-footer-prev" title="过滤器里访问上下文"><i class="icon-chevron-left"></i><span>上一页</span></a><a href="render-tag-content.html" class="article-footer-next" title="渲染标签内容"><span>下一页</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+23 -5
View File
@@ -93,19 +93,37 @@
</header>
<div class="article-content" itemprop="articleBody">
<h2 id="引用模板片段" class="article-heading"><a href="#引用模板片段" class="headerlink" title="引用模板片段"></a>引用模板片段<a class="article-anchor" href="#引用模板片段" aria-hidden="true"></a></h2><p>对于如下两个模板文件:</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><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></pre></td><td class="code"><pre><span class="line">// 文件:color.liquid</span><br><span class="line">color: &#x27;&#123;&#123; color &#125;&#125;&#x27; shape: &#x27;&#123;&#123; shape &#125;&#125;&#x27;</span><br><span class="line"></span><br><span class="line">// 文件:theme.liquid</span><br><span class="line">&#123;% assign shape = &#x27;circle&#x27; %&#125;</span><br><span class="line">&#123;% include &#x27;color&#x27; %&#125;</span><br><span class="line">&#123;% include &#x27;color&#x27; with &#x27;red&#x27; %&#125;</span><br><span class="line">&#123;% include &#x27;color&#x27;, color: &#x27;yellow&#x27;, shape: &#x27;square&#x27; %&#125;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-none"><code class="language-none">&#x2F;&#x2F; 文件:color.liquid
color: &#39;&#123;&#123; color &#125;&#125;&#39; shape: &#39;&#123;&#123; shape &#125;&#125;&#39;
&#x2F;&#x2F; 文件:theme.liquid
&#123;% assign shape &#x3D; &#39;circle&#39; %&#125;
&#123;% include &#39;color&#39; %&#125;
&#123;% include &#39;color&#39; with &#39;red&#39; %&#125;
&#123;% include &#39;color&#39;, color: &#39;yellow&#39;, shape: &#39;square&#39; %&#125;<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p>输出为:</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">color: &#x27;&#x27; shape: &#x27;circle&#x27;</span><br><span class="line">color: &#x27;red&#x27; shape: &#x27;circle&#x27;</span><br><span class="line">color: &#x27;yellow&#x27; shape: &#x27;square&#x27;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-none"><code class="language-none">color: &#39;&#39; shape: &#39;circle&#39;
color: &#39;red&#39; shape: &#39;circle&#39;
color: &#39;yellow&#39; shape: &#39;square&#39;<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre>
<blockquote class="note tip"><strong class="note-title">&quot;.liquid&quot; 文件扩展名</strong><p>如果设置了 <code>extname: &quot;.liquid&quot;</code> 选项,就可以省略 <code>layout</code>, <code>render</code><code>include</code> 里面文件名的 “.liquid” 后缀。详情请参考 <a href="./options.html#extname">extname 选项</a></p>
</blockquote>
<h2 id="布局模板(模板继承)" class="article-heading"><a href="#布局模板(模板继承)" class="headerlink" title="布局模板(模板继承)"></a>布局模板(模板继承)<a class="article-anchor" href="#布局模板(模板继承)" aria-hidden="true"></a></h2><p>对于如下两个模板文件:</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><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></pre></td><td class="code"><pre><span class="line">// 文件:default-layout.liquid</span><br><span class="line">Header</span><br><span class="line">&#123;% block content %&#125;My default content&#123;% endblock %&#125;</span><br><span class="line">Footer</span><br><span class="line"></span><br><span class="line">// 文件:page.liquid</span><br><span class="line">&#123;% layout &quot;default-layout&quot; %&#125;</span><br><span class="line">&#123;% block content %&#125;My page content&#123;% endblock %&#125;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-none"><code class="language-none">&#x2F;&#x2F; 文件:default-layout.liquid
Header
&#123;% block content %&#125;My default content&#123;% endblock %&#125;
Footer
&#x2F;&#x2F; 文件:page.liquid
&#123;% layout &quot;default-layout&quot; %&#125;
&#123;% block content %&#125;My page content&#123;% endblock %&#125;<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p>渲染 <code>page.liquid</code> 将会输出:</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">Header</span><br><span class="line">My page content</span><br><span class="line">Footer</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-none"><code class="language-none">Header
My page content
Footer<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre>
<blockquote class="note tip"><strong class="note-title">Block</strong><ul>
<li>布局文件(父模板)中可以定义多个 block;</li>
@@ -114,7 +132,7 @@
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.430Z" itemprop="dateModified">上次更新:2024-08-19</time>
<time class="article-footer-updated" datetime="2024-08-20T01:26:05.768Z" itemprop="dateModified">上次更新:2024-08-20</time>
<a href="render-file.html" class="article-footer-prev" title="文件渲染"><i class="icon-chevron-left"></i><span>上一页</span></a><a href="use-in-expressjs.html" class="article-footer-next" title="Express.js 中使用"><span>下一页</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+13 -3
View File
@@ -95,11 +95,21 @@
<p>一组标签和过滤器可以封装为一个 <strong>插件</strong>,通常发包到 NPM 来方便使用。本文介绍如何创建和使用插件。</p>
<h2 id="编写插件" class="article-heading"><a href="#编写插件" class="headerlink" title="编写插件"></a>编写插件<a class="article-anchor" href="#编写插件" aria-hidden="true"></a></h2><p>LiquidJS 插件就是一个简单的函数,它的第一个参数是 <a href="/api/classes/Liquid.html">Liquid 类</a>,其中的 <code>this</code> 是它被注册到的 Liquid 实例。可以通过 <code>this</code> 来调用 Liquid API,比如 <a href="./register-filters-tags.html">注册标签和过滤器</a></p>
<p>现在我们来写一个插件并在其中注册一个过滤器,来把输入字符串转换为大写:</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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Inside the plugin function, `this` refers to the Liquid instance.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> Liquid: provides facilities to implement tags and filters.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = <span class="keyword">function</span> (<span class="params">Liquid</span>) &#123;</span><br><span class="line"> <span class="variable language_">this</span>.<span class="title function_">registerFilter</span>(<span class="string">&#x27;upup&#x27;</span>, <span class="function"><span class="params">x</span> =&gt;</span> x.<span class="title function_">toUpperCase</span>());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token comment">/**
* Inside the plugin function, `this` refers to the Liquid instance.
*
* @param Liquid: provides facilities to implement tags and filters.
*/</span>
module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">Liquid</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">registerFilter</span><span class="token punctuation">(</span><span class="token string">'upup'</span><span class="token punctuation">,</span> <span class="token parameter">x</span> <span class="token operator">=></span> x<span class="token punctuation">.</span><span class="token function">toUpperCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p>把上述代码保存为 <code>upup.js</code></p>
<h2 id="使用插件" class="article-heading"><a href="#使用插件" class="headerlink" title="使用插件"></a>使用插件<a class="article-anchor" href="#使用插件" aria-hidden="true"></a></h2><p>把插件传递给 <code>.plugin()</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> engine = <span class="keyword">new</span> <span class="title class_">Liquid</span>()</span><br><span class="line"></span><br><span class="line">engine.<span class="title function_">plugin</span>(<span class="built_in">require</span>(<span class="string">&#x27;./upup.js&#x27;</span>));</span><br><span class="line">engine.<span class="title function_">parseAndRender</span>(<span class="string">&#x27;&#123;&#123; &quot;foo&quot; | upup &#125;&#125;&#x27;</span>).<span class="title function_">then</span>(<span class="variable language_">console</span>.<span class="property">log</span>)</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">const</span> engine <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Liquid</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
engine<span class="token punctuation">.</span><span class="token function">plugin</span><span class="token punctuation">(</span><span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./upup.js'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
engine<span class="token punctuation">.</span><span class="token function">parseAndRender</span><span class="token punctuation">(</span><span class="token string">'&#123;&#123; "foo" | upup &#125;&#125;'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre>
<p>上述代码将会输出 <code>&quot;FOO&quot;</code></p>
<h2 id="插件列表" class="article-heading"><a href="#插件列表" class="headerlink" title="插件列表"></a>插件列表<a class="article-anchor" href="#插件列表" aria-hidden="true"></a></h2><p>由于本仓库只包含 <a target="_blank" rel="noopener external nofollow noreferrer" href="https://github.com/Shopify/liquid/">Shopify/liquid</a> 核心仓库的标签和插件(参考 <a target="_blank" rel="noopener external nofollow noreferrer" href="https://github.com/harttle/liquidjs#differences-and-limitations">https://github.com/harttle/liquidjs#differences-and-limitations</a>),Shopify 平台上特有的插件只能通过插件来使用。</p>
@@ -111,7 +121,7 @@
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.430Z" itemprop="dateModified">上次更新:2024-08-19</time>
<time class="article-footer-updated" datetime="2024-08-20T01:26:05.768Z" itemprop="dateModified">上次更新:2024-08-20</time>
<a href="whitespace-control.html" class="article-footer-prev" title="换行和缩进"><i class="icon-chevron-left"></i><span>上一页</span></a><a href="operators.html" class="article-footer-next" title="运算符"><span>下一页</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+58 -7
View File
@@ -92,30 +92,81 @@
</header>
<div class="article-content" itemprop="articleBody">
<h2 id="注册标签" class="article-heading"><a href="#注册标签" class="headerlink" title="注册标签"></a>注册标签<a class="article-anchor" href="#注册标签" aria-hidden="true"></a></h2><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></pre></td><td class="code"><pre><span class="line"><span class="comment">// 使用方式: &#123;% upper name %&#125;</span></span><br><span class="line">engine.<span class="title function_">registerTag</span>(<span class="string">&#x27;upper&#x27;</span>, &#123;</span><br><span class="line"> <span class="attr">parse</span>: <span class="keyword">function</span>(<span class="params">tagToken, remainTokens</span>) &#123;</span><br><span class="line"> <span class="variable language_">this</span>.<span class="property">value</span> = <span class="keyword">new</span> <span class="title class_">Value</span>(token.<span class="property">args</span>, liquid)</span><br><span class="line"> &#125;,</span><br><span class="line"> <span class="attr">render</span>: <span class="keyword">function</span>*(scope, hash) &#123;</span><br><span class="line"> <span class="keyword">const</span> str = <span class="keyword">yield</span> <span class="variable language_">this</span>.<span class="property">value</span>.<span class="title function_">value</span>(ctx); <span class="comment">// &#x27;alice&#x27;</span></span><br><span class="line"> <span class="keyword">return</span> str.<span class="title function_">toUpperCase</span>() <span class="comment">// &#x27;Alice&#x27;</span></span><br><span class="line"> &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>
<h2 id="注册标签" class="article-heading"><a href="#注册标签" class="headerlink" title="注册标签"></a>注册标签<a class="article-anchor" href="#注册标签" aria-hidden="true"></a></h2><pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token comment">// 使用方式: &#123;% upper name %&#125;</span>
engine<span class="token punctuation">.</span><span class="token function">registerTag</span><span class="token punctuation">(</span><span class="token string">'upper'</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span>
<span class="token function-variable function">parse</span><span class="token operator">:</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">tagToken<span class="token punctuation">,</span> remainTokens</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>value <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Value</span><span class="token punctuation">(</span>token<span class="token punctuation">.</span>args<span class="token punctuation">,</span> liquid<span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
<span class="token function-variable function">render</span><span class="token operator">:</span> <span class="token keyword">function</span><span class="token operator">*</span><span class="token punctuation">(</span>scope<span class="token punctuation">,</span> hash<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">const</span> str <span class="token operator">=</span> <span class="token keyword">yield</span> <span class="token keyword">this</span><span class="token punctuation">.</span>value<span class="token punctuation">.</span><span class="token function">value</span><span class="token punctuation">(</span>ctx<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 'alice'</span>
<span class="token keyword">return</span> str<span class="token punctuation">.</span><span class="token function">toUpperCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 'Alice'</span>
<span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<ul>
<li><code>parse</code>: 从 <code>remainTokens</code> 中读取后续的标签/输出/HTML,直到找到你期望的结束标签。</li>
<li><code>render</code>: 把 scope 数据和此前解析得到的 Token 结合,输出 HTML 字符串。</li>
</ul>
<p>对于更复杂的标签实现,可以提供一个继承自 <code>Tag</code> 的类:</p>
<figure class="highlight typescript"><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></pre></td><td class="code"><pre><span class="line"><span class="comment">// Usage: &#123;% upper name:&quot;alice&quot; %&#125;</span></span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Hash</span>, <span class="title class_">Tag</span>, <span class="title class_">TagToken</span>, <span class="title class_">Context</span>, <span class="title class_">Emitter</span>, <span class="title class_">TopLevelToken</span>, <span class="title class_">Liquid</span> &#125; <span class="keyword">from</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;upper&#x27;</span>, <span class="keyword">class</span> <span class="title class_">UpperTag</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Tag</span> &#123;</span><br><span class="line"> <span class="keyword">private</span> <span class="attr">hash</span>: <span class="title class_">Hash</span></span><br><span class="line"> <span class="title function_">constructor</span>(<span class="params"><span class="attr">tagToken</span>: <span class="title class_">TagToken</span>, <span class="attr">remainTokens</span>: <span class="title class_">TopLevelToken</span>[], <span class="attr">liquid</span>: <span class="title class_">Liquid</span></span>) &#123;</span><br><span class="line"> <span class="variable language_">super</span>(tagToken, remainTokens, liquid)</span><br><span class="line"> <span class="variable language_">this</span>.<span class="property">hash</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"><span class="attr">ctx</span>: <span class="title class_">Context</span></span>) &#123;</span><br><span class="line"> <span class="keyword">const</span> hash = <span class="keyword">yield</span> <span class="variable language_">this</span>.<span class="property">hash</span>.<span class="title function_">render</span>();</span><br><span class="line"> <span class="keyword">return</span> hash.<span class="property">name</span>.<span class="title function_">toUpperCase</span>() <span class="comment">// &#x27;ALICE&#x27;</span></span><br><span class="line"> &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-typescript" data-language="typescript"><code class="language-typescript"><span class="token comment">// Usage: &#123;% upper name:"alice" %&#125;</span>
<span class="token keyword">import</span> <span class="token punctuation">&#123;</span> Hash<span class="token punctuation">,</span> Tag<span class="token punctuation">,</span> TagToken<span class="token punctuation">,</span> Context<span class="token punctuation">,</span> Emitter<span class="token punctuation">,</span> TopLevelToken<span class="token punctuation">,</span> Liquid <span class="token punctuation">&#125;</span> <span class="token keyword">from</span> <span class="token string">'liquidjs'</span>
engine<span class="token punctuation">.</span><span class="token function">registerTag</span><span class="token punctuation">(</span><span class="token string">'upper'</span><span class="token punctuation">,</span> <span class="token keyword">class</span> <span class="token class-name">UpperTag</span> <span class="token keyword">extends</span> <span class="token class-name">Tag</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">private</span> hash<span class="token operator">:</span> Hash
<span class="token function">constructor</span><span class="token punctuation">(</span>tagToken<span class="token operator">:</span> TagToken<span class="token punctuation">,</span> remainTokens<span class="token operator">:</span> TopLevelToken<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> liquid<span class="token operator">:</span> Liquid<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">super</span><span class="token punctuation">(</span>tagToken<span class="token punctuation">,</span> remainTokens<span class="token punctuation">,</span> liquid<span class="token punctuation">)</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>hash <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Hash</span><span class="token punctuation">(</span>tagToken<span class="token punctuation">.</span>args<span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span>
<span class="token operator">*</span> <span class="token function">render</span><span class="token punctuation">(</span>ctx<span class="token operator">:</span> Context<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">const</span> hash <span class="token operator">=</span> <span class="token keyword">yield</span> <span class="token keyword">this</span><span class="token punctuation">.</span>hash<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> hash<span class="token punctuation">.</span>name<span class="token punctuation">.</span><span class="token function">toUpperCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 'ALICE'</span>
<span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p>可以参考已有的标签实现:<a target="_blank" rel="noopener external nofollow noreferrer" href="https://github.com/harttle/liquidjs/tree/master/src/tags">https://github.com/harttle/liquidjs/tree/master/src/tags</a></p>
<h2 id="注册过滤器" class="article-heading"><a href="#注册过滤器" class="headerlink" title="注册过滤器"></a>注册过滤器<a class="article-anchor" href="#注册过滤器" aria-hidden="true"></a></h2><figure class="highlight javascript"><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"><span class="comment">// 使用方式: &#123;&#123; name | upper &#125;&#125;</span></span><br><span class="line">engine.<span class="title function_">registerFilter</span>(<span class="string">&#x27;upper&#x27;</span>, <span class="function"><span class="params">v</span> =&gt;</span> v.<span class="title function_">toUpperCase</span>())</span><br></pre></td></tr></table></figure>
<h2 id="注册过滤器" class="article-heading"><a href="#注册过滤器" class="headerlink" title="注册过滤器"></a>注册过滤器<a class="article-anchor" href="#注册过滤器" aria-hidden="true"></a></h2><pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token comment">// 使用方式: &#123;&#123; name | upper &#125;&#125;</span>
engine<span class="token punctuation">.</span><span class="token function">registerFilter</span><span class="token punctuation">(</span><span class="token string">'upper'</span><span class="token punctuation">,</span> <span class="token parameter">v</span> <span class="token operator">=></span> v<span class="token punctuation">.</span><span class="token function">toUpperCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre>
<p>过滤器的参数将会传递给上面注册的过滤器函数,从第二个参数开始(第一个参数是过滤器左侧的输入),例如:</p>
<figure class="highlight javascript"><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"><span class="comment">// Usage: &#123;&#123; 1 | add: 2, 3 &#125;&#125;</span></span><br><span class="line">engine.<span class="title function_">registerFilter</span>(<span class="string">&#x27;add&#x27;</span>, <span class="function">(<span class="params">initial, arg1, arg2</span>) =&gt;</span> initial + arg1 + arg2)</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token comment">// Usage: &#123;&#123; 1 | add: 2, 3 &#125;&#125;</span>
engine<span class="token punctuation">.</span><span class="token function">registerFilter</span><span class="token punctuation">(</span><span class="token string">'add'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">initial<span class="token punctuation">,</span> arg1<span class="token punctuation">,</span> arg2</span><span class="token punctuation">)</span> <span class="token operator">=></span> initial <span class="token operator">+</span> arg1 <span class="token operator">+</span> arg2<span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre>
<p>查看已有的过滤器实现:<a target="_blank" rel="noopener external nofollow noreferrer" href="https://github.com/harttle/liquidjs/tree/master/src/filters">https://github.com/harttle/liquidjs/tree/master/src/filters</a>。对于复杂的标签,也可以用一个类来实现:</p>
<figure class="highlight typescript"><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></pre></td><td class="code"><pre><span class="line"><span class="comment">// Usage: &#123;% upper name:&quot;alice&quot; %&#125;</span></span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Hash</span>, <span class="title class_">Tag</span>, <span class="title class_">TagToken</span>, <span class="title class_">Context</span>, <span class="title class_">Emitter</span>, <span class="title class_">TopLevelToken</span>, <span class="title class_">Liquid</span> &#125; <span class="keyword">from</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;upper&#x27;</span>, <span class="keyword">class</span> <span class="title class_">UpperTag</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Tag</span> &#123;</span><br><span class="line"> <span class="keyword">private</span> <span class="attr">hash</span>: <span class="title class_">Hash</span></span><br><span class="line"> <span class="title function_">constructor</span>(<span class="params"><span class="attr">tagToken</span>: <span class="title class_">TagToken</span>, <span class="attr">remainTokens</span>: <span class="title class_">TopLevelToken</span>[], <span class="attr">liquid</span>: <span class="title class_">Liquid</span></span>) &#123;</span><br><span class="line"> <span class="variable language_">super</span>(tagToken, remainTokens, liquid)</span><br><span class="line"> <span class="variable language_">this</span>.<span class="property">hash</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"><span class="attr">ctx</span>: <span class="title class_">Context</span></span>) &#123;</span><br><span class="line"> <span class="keyword">const</span> hash = <span class="keyword">yield</span> <span class="variable language_">this</span>.<span class="property">hash</span>.<span class="title function_">render</span>();</span><br><span class="line"> <span class="keyword">return</span> hash.<span class="property">name</span>.<span class="title function_">toUpperCase</span>() <span class="comment">// &#x27;ALICE&#x27;</span></span><br><span class="line"> &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-typescript" data-language="typescript"><code class="language-typescript"><span class="token comment">// Usage: &#123;% upper name:"alice" %&#125;</span>
<span class="token keyword">import</span> <span class="token punctuation">&#123;</span> Hash<span class="token punctuation">,</span> Tag<span class="token punctuation">,</span> TagToken<span class="token punctuation">,</span> Context<span class="token punctuation">,</span> Emitter<span class="token punctuation">,</span> TopLevelToken<span class="token punctuation">,</span> Liquid <span class="token punctuation">&#125;</span> <span class="token keyword">from</span> <span class="token string">'liquidjs'</span>
engine<span class="token punctuation">.</span><span class="token function">registerTag</span><span class="token punctuation">(</span><span class="token string">'upper'</span><span class="token punctuation">,</span> <span class="token keyword">class</span> <span class="token class-name">UpperTag</span> <span class="token keyword">extends</span> <span class="token class-name">Tag</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">private</span> hash<span class="token operator">:</span> Hash
<span class="token function">constructor</span><span class="token punctuation">(</span>tagToken<span class="token operator">:</span> TagToken<span class="token punctuation">,</span> remainTokens<span class="token operator">:</span> TopLevelToken<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> liquid<span class="token operator">:</span> Liquid<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">super</span><span class="token punctuation">(</span>tagToken<span class="token punctuation">,</span> remainTokens<span class="token punctuation">,</span> liquid<span class="token punctuation">)</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>hash <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Hash</span><span class="token punctuation">(</span>tagToken<span class="token punctuation">.</span>args<span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span>
<span class="token operator">*</span> <span class="token function">render</span><span class="token punctuation">(</span>ctx<span class="token operator">:</span> Context<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">const</span> hash <span class="token operator">=</span> <span class="token keyword">yield</span> <span class="token keyword">this</span><span class="token punctuation">.</span>hash<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> hash<span class="token punctuation">.</span>name<span class="token punctuation">.</span><span class="token function">toUpperCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 'ALICE'</span>
<span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<h2 id="反注册标签-过滤器" class="article-heading"><a href="#反注册标签-过滤器" class="headerlink" title="反注册标签/过滤器"></a>反注册标签/过滤器<a class="article-anchor" href="#反注册标签-过滤器" aria-hidden="true"></a></h2><p>有时可能需要禁用一些标签/过滤器(比如 <a target="_blank" rel="noopener external nofollow noreferrer" href="https://github.com/harttle/liquidjs/issues/324">#324</a>),注册一个假的标签/过滤器并在里面抛出相应的错误即可。</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="comment">// 禁用标签</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">// 禁用过滤器</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>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token comment">// 禁用标签</span>
<span class="token keyword">const</span> disabledTag <span class="token operator">=</span> <span class="token punctuation">&#123;</span>
<span class="token function-variable function">parse</span><span class="token operator">:</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">tag "</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>token<span class="token punctuation">.</span>name<span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token string">" disabled</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>
engine<span class="token punctuation">.</span><span class="token function">registerTag</span><span class="token punctuation">(</span><span class="token string">'include'</span><span class="token punctuation">,</span> disabledTag<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 禁用过滤器</span>
<span class="token keyword">function</span> <span class="token function">disabledFilter</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">return</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">filter "</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>name<span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token string">" disabled</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>
engine<span class="token punctuation">.</span><span class="token function">registerFilter</span><span class="token punctuation">(</span><span class="token string">'plus'</span><span class="token punctuation">,</span> <span class="token function">disabledFilter</span><span class="token punctuation">(</span><span class="token string">'plus'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.430Z" itemprop="dateModified">上次更新:2024-08-19</time>
<time class="article-footer-updated" datetime="2024-08-20T01:26:05.768Z" itemprop="dateModified">上次更新:2024-08-20</time>
<a href="escaping.html" class="article-footer-prev" title="转义"><i class="icon-chevron-left"></i><span>上一页</span></a><a href="access-scope-in-filters.html" class="article-footer-next" title="过滤器里访问上下文"><span>下一页</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+38 -7
View File
@@ -94,20 +94,32 @@
<div class="article-content" itemprop="articleBody">
<p>一个典型的项目会有一个目录下都是模板,最方便的方式就是设置 LiquidJS 的 <a href="/api/interfaces/LiquidOptions.html#root">root</a> 然后调用 <a href="/api/classes/Liquid.html#renderFile">.renderFile()</a><a href="/api/classes/Liquid.html#renderFileSync">.renderFileSync()</a> 来渲染其中的一个模板文件。</p>
<h2 id="渲染一个文件" class="article-heading"><a href="#渲染一个文件" class="headerlink" title="渲染一个文件"></a>渲染一个文件<a class="article-anchor" href="#渲染一个文件" aria-hidden="true"></a></h2><p>例如你有如下的目录结构:</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><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">.</span><br><span class="line">├── index.js</span><br><span class="line">└── views/</span><br><span class="line"> ├── hello.liquid</span><br><span class="line"> └── world.liquid</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-none"><code class="language-none">.
├── index.js
└── views&#x2F;
├── hello.liquid
└── world.liquid<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p>其中 <code>hello.liquid</code> 内容为:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">name: &#123;&#123;name&#125;&#125;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-liquid" data-language="liquid"><code class="language-liquid">name: <span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;&#123;</span>name<span class="token delimiter punctuation">&#125;&#125;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p><code>index.js</code> 中可以这样渲染 <code>hello.liquid</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> engine = <span class="keyword">new</span> <span class="title class_">Liquid</span>(&#123;</span><br><span class="line"> <span class="attr">root</span>: path.<span class="title function_">resolve</span>(__dirname, <span class="string">&#x27;views/&#x27;</span>), <span class="comment">// 设置模板查找目录</span></span><br><span class="line"> <span class="attr">extname</span>: <span class="string">&#x27;.liquid&#x27;</span> <span class="comment">// 添加后缀,默认为 &quot;&quot; 表示不添加后缀</span></span><br><span class="line">&#125;);</span><br><span class="line"><span class="comment">// 将会读取并渲染 `views/hello.liquid`</span></span><br><span class="line">engine.<span class="title function_">renderFile</span>(<span class="string">&quot;hello&quot;</span>, &#123;<span class="attr">name</span>: <span class="string">&#x27;alice&#x27;</span>&#125;).<span class="title function_">then</span>(<span class="variable language_">console</span>.<span class="property">log</span>)</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">var</span> engine <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Liquid</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
<span class="token literal-property property">root</span><span class="token operator">:</span> path<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'views/'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token comment">// 设置模板查找目录</span>
<span class="token literal-property property">extname</span><span class="token operator">:</span> <span class="token string">'.liquid'</span> <span class="token comment">// 添加后缀,默认为 "" 表示不添加后缀</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 将会读取并渲染 `views/hello.liquid`</span>
engine<span class="token punctuation">.</span><span class="token function">renderFile</span><span class="token punctuation">(</span><span class="token string">"hello"</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span><span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'alice'</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p>执行 <code>node index.js</code> 你将会得到类似这样的输出:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">name: alice</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-none"><code class="language-none">name: alice<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<h2 id="模板查找" class="article-heading"><a href="#模板查找" class="headerlink" title="模板查找"></a>模板查找<a class="article-anchor" href="#模板查找" aria-hidden="true"></a></h2><p>传递给 <a href="/api/classes/Liquid.html#renderFile">.renderFile()</a>, <a href="/api/classes/Liquid.html#parseFile">.parseFile()</a> <a href="/api/classes/Liquid.html#renderFileSync">.renderFileSync()</a>, <a href="/api/classes/Liquid.html#parseFileSync">.parseFileSync()</a> 这些 API 的模板名,<br>以及传递给 <a target="_blank" rel="noopener external nofollow noreferrer" href="https://help.shopify.com/themes/liquid/tags/theme-tags#include">include</a>, <a target="_blank" rel="noopener external nofollow noreferrer" href="https://help.shopify.com/en/themes/liquid/tags/theme-tags#layout">layout</a> 这些标签的模板名,将会根据 <a href="/api/interfaces/LiquidOptions.html#root">root</a> 选项来查找。</p>
<p><code>root</code> 可以设置为 <code>string</code> 类型的路径(见上面的例子), 也可以设置为一个字符串数组表示路径列表,这时 LiquidJS 将会按顺序去查找。例如:</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> engine = <span class="keyword">new</span> <span class="title class_">Liquid</span>(&#123;</span><br><span class="line"> <span class="attr">root</span>: [<span class="string">&#x27;views/&#x27;</span>, <span class="string">&#x27;views/partials/&#x27;</span>],</span><br><span class="line"> <span class="attr">extname</span>: <span class="string">&#x27;.liquid&#x27;</span></span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">var</span> engine <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Liquid</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
<span class="token literal-property property">root</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'views/'</span><span class="token punctuation">,</span> <span class="token string">'views/partials/'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token literal-property property">extname</span><span class="token operator">:</span> <span class="token string">'.liquid'</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre>
<blockquote class="note tip"><strong class="note-title">相对路径</strong><p><code>root</code> 中使用相对路径将会被解释为相对于 <code>cwd()</code>(当前工作目录)。</p>
</blockquote>
@@ -130,12 +142,31 @@
</blockquote>
<h2 id="文件系统接口" class="article-heading"><a href="#文件系统接口" class="headerlink" title="文件系统接口"></a>文件系统接口<a class="article-anchor" href="#文件系统接口" aria-hidden="true"></a></h2><p>LiquidJS 定义了一个<a href="/api/interfaces/FS.html">文件系统接口</a>,在 Node.js 下的默认实现是 <a target="_blank" rel="noopener external nofollow noreferrer" href="https://github.com/harttle/liquidjs/blob/master/src/fs/fs-impl.ts">src/fs/node.ts</a>,在浏览器打包文件中的默认实现是 <a target="_blank" rel="noopener external nofollow noreferrer" href="https://github.com/harttle/liquidjs/blob/master/src/fs/fs-impl-browser.ts">src/fs/browser.ts</a><br>你可以通过创建 <code>Liquid</code> 时的 <a href="/api/interfaces/LiquidOptions.html#fs">fs</a> 参数来指定一个自定义实现来指定如何读取模板文件。比如从数据库里读取:</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> engine = <span class="keyword">new</span> <span class="title class_">Liquid</span>(&#123;</span><br><span class="line"> <span class="attr">fs</span>: &#123;</span><br><span class="line"> <span class="title function_">readFileSync</span> (file) &#123;</span><br><span class="line"> <span class="keyword">return</span> db.<span class="title function_">model</span>(<span class="string">&#x27;Template&#x27;</span>).<span class="title function_">findByIdSync</span>(file).<span class="property">text</span></span><br><span class="line"> &#125;,</span><br><span class="line"> <span class="keyword">await</span> <span class="title function_">readFile</span> (file) &#123;</span><br><span class="line"> <span class="keyword">const</span> template = <span class="keyword">await</span> db.<span class="title function_">model</span>(<span class="string">&#x27;Template&#x27;</span>).<span class="title function_">findById</span>(file)</span><br><span class="line"> <span class="keyword">return</span> template.<span class="property">text</span></span><br><span class="line"> &#125;,</span><br><span class="line"> <span class="title function_">existsSync</span> () &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span></span><br><span class="line"> &#125;,</span><br><span class="line"> <span class="keyword">await</span> <span class="title function_">exists</span> () &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span></span><br><span class="line"> &#125;,</span><br><span class="line"> <span class="title function_">resolve</span>(<span class="params">root, file, ext</span>) &#123;</span><br><span class="line"> <span class="keyword">return</span> file</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">const</span> engine <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Liquid</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
<span class="token literal-property property">fs</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
<span class="token function">readFileSync</span> <span class="token punctuation">(</span><span class="token parameter">file</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">return</span> db<span class="token punctuation">.</span><span class="token function">model</span><span class="token punctuation">(</span><span class="token string">'Template'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">findByIdSync</span><span class="token punctuation">(</span>file<span class="token punctuation">)</span><span class="token punctuation">.</span>text
<span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
<span class="token keyword">await</span> <span class="token function">readFile</span> <span class="token punctuation">(</span><span class="token parameter">file</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">const</span> template <span class="token operator">=</span> <span class="token keyword">await</span> db<span class="token punctuation">.</span><span class="token function">model</span><span class="token punctuation">(</span><span class="token string">'Template'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">findById</span><span class="token punctuation">(</span>file<span class="token punctuation">)</span>
<span class="token keyword">return</span> template<span class="token punctuation">.</span>text
<span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
<span class="token function">existsSync</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">return</span> <span class="token boolean">true</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
<span class="token keyword">await</span> <span class="token function">exists</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">return</span> <span class="token boolean">true</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
<span class="token function">resolve</span><span class="token punctuation">(</span><span class="token parameter">root<span class="token punctuation">,</span> file<span class="token punctuation">,</span> ext</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">return</span> file
<span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.430Z" itemprop="dateModified">上次更新:2024-08-19</time>
<time class="article-footer-updated" datetime="2024-08-20T01:26:05.768Z" itemprop="dateModified">上次更新:2024-08-20</time>
<a href="options.html" class="article-footer-prev" title="选项"><i class="icon-chevron-left"></i><span>上一页</span></a><a href="partials-and-layouts.html" class="article-footer-next" title="引用/继承"><span>下一页</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+64 -8
View File
@@ -94,10 +94,14 @@
<div class="article-content" itemprop="articleBody">
<p>自定义标签可以有内容,也可以嵌套使用。本文描述了如何实现一个由<em>开始标签</em><em>结束标签</em>和之间的<em>标签内容</em>的自定义标签。</p>
<h2 id="渲染标签内容" class="article-heading"><a href="#渲染标签内容" class="headerlink" title="渲染标签内容"></a>渲染标签内容<a class="article-anchor" href="#渲染标签内容" aria-hidden="true"></a></h2><p>我们先实现一个简单的 <code>wrap</code> 标签,它会把内容包装在 <code>&lt;div class=&quot;wrapper&quot;&gt;&lt;/div&gt;</code> 元素里:</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;% wrap %&#125;</span><br><span class="line"> &#123;&#123; &quot;hello world!&quot; | capitalize &#125;&#125;</span><br><span class="line">&#123;% endwrap %&#125;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-liquid" data-language="liquid"><code class="language-liquid"><span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> wrap <span class="token delimiter punctuation">%&#125;</span></span>
<span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;&#123;</span> <span class="token string">"hello world!"</span> <span class="token operator">|</span> <span class="token function filter">capitalize</span> <span class="token delimiter punctuation">&#125;&#125;</span></span>
<span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> endwrap <span class="token delimiter punctuation">%&#125;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre>
<p>期望输出:</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>
<pre class="line-numbers language-markup" data-language="markup"><code class="language-markup"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">'</span>wrapper<span class="token punctuation">'</span></span><span class="token punctuation">></span></span>
Hello world!
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre>
<p>首先 <a href="./register-filters-tags.html">注册</a> 一个名为 <code>wrap</code> 的标签,把内容解析到 <code>this.tpls</code> 数组里。<code>parse(tagToken, remainTokens)</code> 中,</p>
<ul>
@@ -105,25 +109,77 @@
<li><code>remainTokens</code> 是当前模板中后续所有 <em>Token</em> 的数组。</li>
</ul>
<p>我们要做的是从 <code>remainTokens</code> 里拿出来/<code>.shift()</code> 足够的标签直到遇到 <code>endwrap</code>(其实可以是任意名字,但按照惯例应该叫 <code>endwrap</code>)。如果到模板结尾都没遇到 <code>endwrap</code>,需要抛出一个标签未关闭的 <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">// 得到了结束标签,停止解析</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">// 把 Token 解析成 Template</span></span><br><span class="line"> <span class="comment">// parseToken() 可能会消耗多个 Token</span></span><br><span class="line"> <span class="comment">// 例如 &#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>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript">engine<span class="token punctuation">.</span><span class="token function">registerTag</span><span class="token punctuation">(</span><span class="token string">'wrap'</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span>
<span class="token function">parse</span><span class="token punctuation">(</span><span class="token parameter">tagToken<span class="token punctuation">,</span> remainTokens</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>tpls <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
<span class="token keyword">let</span> closed <span class="token operator">=</span> <span class="token boolean">false</span>
<span class="token keyword">while</span><span class="token punctuation">(</span>remainTokens<span class="token punctuation">.</span>length<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">let</span> token <span class="token operator">=</span> remainTokens<span class="token punctuation">.</span><span class="token function">shift</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment">// 得到了结束标签,停止解析</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>token<span class="token punctuation">.</span>name <span class="token operator">===</span> <span class="token string">'endwrap'</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
closed <span class="token operator">=</span> <span class="token boolean">true</span>
<span class="token keyword">break</span>
<span class="token punctuation">&#125;</span>
<span class="token comment">// 把 Token 解析成 Template</span>
<span class="token comment">// parseToken() 可能会消耗多个 Token</span>
<span class="token comment">// 例如 &#123;% if %&#125;...&#123;% endif %&#125;</span>
<span class="token keyword">let</span> tpl <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>liquid<span class="token punctuation">.</span>parser<span class="token punctuation">.</span><span class="token function">parseToken</span><span class="token punctuation">(</span>token<span class="token punctuation">,</span> remainTokens<span class="token punctuation">)</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>tpls<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>tpl<span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>closed<span class="token punctuation">)</span> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">tag </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>tagToken<span class="token punctuation">.</span><span class="token function">getText</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token string"> not closed</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
<span class="token operator">*</span> <span class="token function">render</span><span class="token punctuation">(</span><span class="token parameter">context<span class="token punctuation">,</span> emitter</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
emitter<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span><span class="token string">"&lt;div class='wrapper'>"</span><span class="token punctuation">)</span>
<span class="token keyword">yield</span> <span class="token keyword">this</span><span class="token punctuation">.</span>liquid<span class="token punctuation">.</span>renderer<span class="token punctuation">.</span><span class="token function">renderTemplates</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>tpls<span class="token punctuation">,</span> context<span class="token punctuation">,</span> emitter<span class="token punctuation">)</span>
emitter<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span><span class="token string">"&lt;/div>"</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p><code>.renderTemplates()</code> 可能是异步的,因此需要 <code>yield</code> 来等它完成。更多关于 LiquidJS 异步的信息可以参考 <a href="./sync-and-async.html">同步和异步</a><code>render()</code> 的其他部分比较直观,这是 JSFiddle 版本:<a target="_blank" rel="noopener external nofollow noreferrer" href="http://jsfiddle.net/por0zcn1/3/">http://jsfiddle.net/por0zcn1/3/</a></p>
<h2 id="使用-ParseStream" class="article-heading"><a href="#使用-ParseStream" class="headerlink" title="使用 ParseStream"></a>使用 ParseStream<a class="article-anchor" href="#使用-ParseStream" aria-hidden="true"></a></h2><p>对于像 <a href="../tags/for.html">for</a><a href="../tags/if.html">if</a> 这样的复杂标签,<code>parse()</code> 会变得很复杂。使用 <a href="/api/classes/ParseStream.html">ParseStream</a> 工具可以按事件风格来组织 <code>parse()</code> 的逻辑。下面是用 <code>ParseStream</code> 重写过的 <code>parse()</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></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">// 注意这里不能用箭头函数,因为我们需要 `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>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token function">parse</span><span class="token punctuation">(</span><span class="token parameter">tagToken<span class="token punctuation">,</span> remainTokens</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>tpls <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>liquid<span class="token punctuation">.</span>parser<span class="token punctuation">.</span><span class="token function">parseStream</span><span class="token punctuation">(</span>remainTokens<span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'template'</span><span class="token punctuation">,</span> <span class="token parameter">tpl</span> <span class="token operator">=></span> <span class="token keyword">this</span><span class="token punctuation">.</span>tpls<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>tpl<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token comment">// 注意这里不能用箭头函数,因为我们需要 `this`</span>
<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'tag:endwrap'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'end'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">tag </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>tagToken<span class="token punctuation">.</span><span class="token function">getText</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token string"> not closed</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span> <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p>这是 JSFiddle 链接:<a target="_blank" rel="noopener external nofollow noreferrer" href="http://jsfiddle.net/por0zcn1/4/">http://jsfiddle.net/por0zcn1/4/</a>。简单起见,下面的例子都借助 <code>ParseStream</code> 来实现。</p>
<h2 id="操作上下文" class="article-heading"><a href="#操作上下文" class="headerlink" title="操作上下文"></a>操作上下文<a class="article-anchor" href="#操作上下文" aria-hidden="true"></a></h2><p>上面的 <code>wrap</code> 标签看起来没什么用,反正没它也可以很容易地渲染那部分内容。我们现在来实现一个 <code>repeat</code> 标签,把内容渲染两次(还可以<a href="./parse-parameters.html">加个参数</a>让它渲染任意次):</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>
<pre class="line-numbers language-liquid" data-language="liquid"><code class="language-liquid"><span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> repeat <span class="token delimiter punctuation">%&#125;</span></span>
<span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;&#123;</span> repeat<span class="token punctuation">.</span>i <span class="token delimiter punctuation">&#125;&#125;</span></span>. <span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;&#123;</span> <span class="token string">"hello world!"</span> <span class="token operator">|</span> <span class="token function filter">capitalize</span> <span class="token delimiter punctuation">&#125;&#125;</span></span>
<span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> endrepeat <span class="token delimiter punctuation">%&#125;</span></span>`<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre>
<p>期望输出:</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>
<pre class="line-numbers language-markup" data-language="markup"><code class="language-markup">1. Hello world!
2. Hello world!<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre>
<p>你可能注意到了在 <code>repeat</code> 上下文里有个额外的变量 <code>repeat.i</code>,这就需要我们操作 <em>上下文</em></p>
<blockquote class="note info"><strong class="note-title">上下文</strong><p><em>上下文</em> 定义了 Liquid 模板中每个变量的值。在 LiquidJS 中,<code>Context</code> 由一个 <code>Scope</code> 的栈组成。<em>Scope</em> 就是一个普通对象,就像传给 <code>engine.render(tpl, scope)</code><code>scope</code> 一样。</p>
</blockquote>
<p>每次进入新的 <em>上下文</em> 时,我们需要 <code>push</code> 一个新的 <code>Scope</code>。当结束渲染并退出 <em>上下文</em> 时,再把 <code>Scope</code><em>上下文</em> <code>pop</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></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>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript">engine<span class="token punctuation">.</span><span class="token function">registerTag</span><span class="token punctuation">(</span><span class="token string">'repeat'</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span>
<span class="token function">parse</span><span class="token punctuation">(</span><span class="token parameter">tagToken<span class="token punctuation">,</span> remainTokens</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>tpls <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>liquid<span class="token punctuation">.</span>parser<span class="token punctuation">.</span><span class="token function">parseStream</span><span class="token punctuation">(</span>remainTokens<span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'template'</span><span class="token punctuation">,</span> <span class="token parameter">tpl</span> <span class="token operator">=></span> <span class="token keyword">this</span><span class="token punctuation">.</span>tpls<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>tpl<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'tag:endrepeat'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'end'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">tag </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>tagToken<span class="token punctuation">.</span><span class="token function">getText</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token string"> not closed</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span> <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
<span class="token operator">*</span> <span class="token function">render</span><span class="token punctuation">(</span><span class="token parameter">context<span class="token punctuation">,</span> emitter</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">const</span> repeat <span class="token operator">=</span> <span class="token punctuation">&#123;</span> <span class="token literal-property property">i</span><span class="token operator">:</span> <span class="token number">1</span> <span class="token punctuation">&#125;</span>
context<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span> repeat <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token keyword">yield</span> <span class="token keyword">this</span><span class="token punctuation">.</span>liquid<span class="token punctuation">.</span>renderer<span class="token punctuation">.</span><span class="token function">renderTemplates</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>tpls<span class="token punctuation">,</span> context<span class="token punctuation">,</span> emitter<span class="token punctuation">)</span>
repeat<span class="token punctuation">.</span>i<span class="token operator">++</span>
<span class="token keyword">yield</span> <span class="token keyword">this</span><span class="token punctuation">.</span>liquid<span class="token punctuation">.</span>renderer<span class="token punctuation">.</span><span class="token function">renderTemplates</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>tpls<span class="token punctuation">,</span> context<span class="token punctuation">,</span> emitter<span class="token punctuation">)</span>
context<span class="token punctuation">.</span><span class="token function">pop</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p><code>parse()</code> 部分和 <code>wrap</code> 标签完全相同,在 <code>render()</code> 部分我们通过调用两次 <code>.renderTemplates(this.tpls)</code> 来重复渲染内容。这是 JSFiddle 链接:<a target="_blank" rel="noopener external nofollow noreferrer" href="http://jsfiddle.net/por0zcn1/2/">http://jsfiddle.net/por0zcn1/2/</a></p>
<blockquote class="note warn"><strong class="note-title">成对使用 Push 和 Pop</strong><p>必须成对地使用 <code>context.push()</code><code>context.pop()</code>。如果忘记 <code>pop()</code> 会导致 <code>Scope</code> 泄露给后面的模板内容,也可能损坏 <em>上下文</em> 栈。.</p>
@@ -132,7 +188,7 @@
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.430Z" itemprop="dateModified">上次更新:2024-08-19</time>
<time class="article-footer-updated" datetime="2024-08-20T01:26:05.768Z" itemprop="dateModified">上次更新:2024-08-20</time>
<a href="parse-parameters.html" class="article-footer-prev" title="参数解析"><i class="icon-chevron-left"></i><span>上一页</span></a><a href="drops.html" class="article-footer-next" title="Liquid Drop"><span>下一页</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+18 -7
View File
@@ -94,21 +94,32 @@
<div class="article-content" itemprop="articleBody">
<p>如果你还不了解 Liquid 模板语言,请参考 <a href="./intro-to-liquid.html">Liquid 模板语言简介</a></p>
<h2 id="在-Node-js-里使用" class="article-heading"><a href="#在-Node-js-里使用" class="headerlink" title="在 Node.js 里使用"></a>在 Node.js 里使用<a class="article-anchor" href="#在-Node-js-里使用" aria-hidden="true"></a></h2><p>通过 NPM 安装:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install --save liquidjs</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-bash" data-language="bash"><code class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> <span class="token parameter variable">--save</span> liquidjs<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<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></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> &#123; <span class="title class_">Liquid</span> &#125; = <span class="built_in">require</span>(<span class="string">&#x27;liquidjs&#x27;</span>);</span><br><span class="line"><span class="keyword">var</span> engine = <span class="keyword">new</span> <span class="title class_">Liquid</span>();</span><br><span class="line"></span><br><span class="line">engine</span><br><span class="line"> .<span class="title function_">parseAndRender</span>(<span class="string">&#x27;&#123;&#123;name | capitalize&#125;&#125;&#x27;</span>, &#123;<span class="attr">name</span>: <span class="string">&#x27;alice&#x27;</span>&#125;)</span><br><span class="line"> .<span class="title function_">then</span>(<span class="variable language_">console</span>.<span class="property">log</span>); <span class="comment">// 输出 &#x27;Alice&#x27;</span></span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">var</span> <span class="token punctuation">&#123;</span> Liquid <span class="token punctuation">&#125;</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'liquidjs'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> engine <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Liquid</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
engine
<span class="token punctuation">.</span><span class="token function">parseAndRender</span><span class="token punctuation">(</span><span class="token string">'&#123;&#123;name | capitalize&#125;&#125;'</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span><span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'alice'</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 输出 'Alice'</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<blockquote class="note info"><strong class="note-title">示例</strong><p>这里有一个 LiquidJS 在 Node.js 里使用的例子:<a href="https://github.com/harttle/liquidjs/blob/master/demo/nodejs/" rel="external nofollow noreferrer" target="_blank">liquidjs/demo/nodejs/</a>.</p>
</blockquote>
<p>LiquidJS 的类型定义也导出并发布到了 NPM 包里,写 TypeScript 的项目可以直接这样使用:</p>
<figure class="highlight typescript"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Liquid</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;liquidjs&#x27;</span>;</span><br><span class="line"><span class="keyword">const</span> engine = <span class="keyword">new</span> <span class="title class_">Liquid</span>();</span><br><span class="line"></span><br><span class="line">engine</span><br><span class="line"> .<span class="title function_">parseAndRender</span>(<span class="string">&#x27;&#123;&#123;name | capitalize&#125;&#125;&#x27;</span>, &#123;<span class="attr">name</span>: <span class="string">&#x27;alice&#x27;</span>&#125;)</span><br><span class="line"> .<span class="title function_">then</span>(<span class="variable language_">console</span>.<span class="property">log</span>); <span class="comment">// 输出 &#x27;Alice&#x27;</span></span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">import</span> <span class="token punctuation">&#123;</span> Liquid <span class="token punctuation">&#125;</span> <span class="token keyword">from</span> <span class="token string">'liquidjs'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> engine <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Liquid</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
engine
<span class="token punctuation">.</span><span class="token function">parseAndRender</span><span class="token punctuation">(</span><span class="token string">'&#123;&#123;name | capitalize&#125;&#125;'</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span>name<span class="token operator">:</span> <span class="token string">'alice'</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token builtin">console</span><span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 输出 'Alice'</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<blockquote class="note info"><strong class="note-title">示例</strong><p>这里有一个 LiquidJS 在 TypeScript 下的例子:<a href="https://github.com/harttle/liquidjs/blob/master/demo/typescript/" rel="external nofollow noreferrer" target="_blank">liquidjs/demo/typescript/</a>.</p>
</blockquote>
<h2 id="在浏览器里使用" class="article-heading"><a href="#在浏览器里使用" class="headerlink" title="在浏览器里使用"></a>在浏览器里使用<a class="article-anchor" href="#在浏览器里使用" aria-hidden="true"></a></h2><p>LiquidJS 预先构建了 UMD Bundle,可以通过 jsDelivr CDN 来引用:</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"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://cdn.jsdelivr.net/npm/liquidjs/dist/liquid.browser.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span> <span class="comment">&lt;!--生产环境--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://cdn.jsdelivr.net/npm/liquidjs/dist/liquid.browser.umd.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span> <span class="comment">&lt;!--开发环境--&gt;</span></span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-markup" data-language="markup"><code class="language-markup"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>https://cdn.jsdelivr.net/npm/liquidjs/dist/liquid.browser.min.js<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span> <span class="token comment">&lt;!--生产环境--></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>https://cdn.jsdelivr.net/npm/liquidjs/dist/liquid.browser.umd.js<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span> <span class="token comment">&lt;!--开发环境--></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre>
<blockquote class="note info"><strong class="note-title">示例</strong><p>这里有一个 jsFiddle 上的在线例子:<a href="https://jsfiddle.net/x43eb0z6/" rel="external nofollow noreferrer" target="_blank">jsfiddle.net/x43eb0z6</a>,其源码也可以在 <a href="https://github.com/harttle/liquidjs/blob/master/demo/browser/" rel="external nofollow noreferrer" target="_blank">liquidjs/demo/browser/</a> 找到。</p>
</blockquote>
@@ -117,16 +128,16 @@
</blockquote>
<h2 id="在命令行里使用" class="article-heading"><a href="#在命令行里使用" class="headerlink" title="在命令行里使用"></a>在命令行里使用<a class="article-anchor" href="#在命令行里使用" aria-hidden="true"></a></h2><p>你还可以在命令行里使用 LiquidJS:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">&#x27;&#123;&#123;&quot;hello&quot; | capitalize&#125;&#125;&#x27;</span> | npx liquidjs</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-bash" data-language="bash"><code class="language-bash"><span class="token builtin class-name">echo</span> <span class="token string">'&#123;&#123;"hello" | capitalize&#125;&#125;'</span> <span class="token operator">|</span> npx liquidjs<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p>模板来自标准输入,数据则来自参数,这个参数可以是一个 JSON 文件的路径,也可以是一个 JSON 字符串:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">&#x27;Hello, &#123;&#123; name &#125;&#125;.&#x27;</span> | npx liquidjs <span class="string">&#x27;&#123;&quot;name&quot;: &quot;Snake&quot;&#125;&#x27;</span></span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-bash" data-language="bash"><code class="language-bash"><span class="token builtin class-name">echo</span> <span class="token string">'Hello, &#123;&#123; name &#125;&#125;.'</span> <span class="token operator">|</span> npx liquidjs <span class="token string">'&#123;"name": "Snake"&#125;'</span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<h2 id="其他" class="article-heading"><a href="#其他" class="headerlink" title="其他"></a>其他<a class="article-anchor" href="#其他" aria-hidden="true"></a></h2><p><a target="_blank" rel="noopener external nofollow noreferrer" href="https://github.com/stevenanthonyrevo">@stevenanthonyrevo</a> 还提供了一个 ReactJS demo,请参考 <a target="_blank" rel="noopener external nofollow noreferrer" href="https://github.com/harttle/liquidjs/blob/master/demo/reactjs/">liquidjs/demo/reactjs/</a></p>
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.430Z" itemprop="dateModified">上次更新:2024-08-19</time>
<time class="article-footer-updated" datetime="2024-08-20T01:26:05.768Z" itemprop="dateModified">上次更新:2024-08-20</time>
<a href="intro-to-liquid.html" class="article-footer-prev" title="Liquid 简介"><i class="icon-chevron-left"></i><span>上一页</span></a><a href="options.html" class="article-footer-next" title="选项"><span>下一页</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+51 -5
View File
@@ -110,7 +110,21 @@
<li><code>evalValueSync()</code></li>
</ul>
<h2 id="如何实现兼容同步的标签" class="article-heading"><a href="#如何实现兼容同步的标签" class="headerlink" title="如何实现兼容同步的标签"></a>如何实现兼容同步的标签<a class="article-anchor" href="#如何实现兼容同步的标签" aria-hidden="true"></a></h2><p>LiquidJS 使用基于生成器的异步实现,来让同一份代码支持同步和异步调用。例如下面的 <code>UpperTag</code> 既可以用于 <code>engine.renderSync()</code> 也可以用于 <code>engine.render()</code></p>
<figure class="highlight typescript"><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">import</span> &#123; <span class="title class_">TagToken</span>, <span class="title class_">Context</span>, <span class="title class_">Emitter</span>, <span class="title class_">TopLevelToken</span>, <span class="title class_">Value</span>, <span class="title class_">Tag</span>, <span class="title class_">Liquid</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;liquidjs&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// Usage: &#123;% upper &quot;alice&quot; %&#125;</span></span><br><span class="line"><span class="comment">// Output: ALICE</span></span><br><span class="line">engine.<span class="title function_">registerTag</span>(<span class="string">&#x27;upper&#x27;</span>, <span class="keyword">class</span> <span class="title class_">UpperTag</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Tag</span> &#123;</span><br><span class="line"> <span class="keyword">private</span> <span class="attr">value</span>: <span class="title class_">Value</span></span><br><span class="line"> <span class="title function_">constructor</span> (<span class="params"><span class="attr">token</span>: <span class="title class_">TagToken</span>, <span class="attr">remainTokens</span>: <span class="title class_">TopLevelToken</span>[], <span class="attr">liquid</span>: <span class="title class_">Liquid</span></span>) &#123;</span><br><span class="line"> <span class="variable language_">super</span>(token, remainTokens, liquid)</span><br><span class="line"> <span class="variable language_">this</span>.<span class="property">value</span> = <span class="keyword">new</span> <span class="title class_">Value</span>(token.<span class="property">args</span>, liquid)</span><br><span class="line"> &#125;</span><br><span class="line"> * <span class="title function_">render</span> (<span class="attr">ctx</span>: <span class="title class_">Context</span>, <span class="attr">emitter</span>: <span class="title class_">Emitter</span>) &#123;</span><br><span class="line"> <span class="keyword">const</span> title = <span class="keyword">yield</span> <span class="variable language_">this</span>.<span class="property">value</span>.<span class="title function_">value</span>(ctx)</span><br><span class="line"> emitter.<span class="title function_">write</span>(title.<span class="title function_">toUpperCase</span>())</span><br><span class="line"> &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">import</span> <span class="token punctuation">&#123;</span> TagToken<span class="token punctuation">,</span> Context<span class="token punctuation">,</span> Emitter<span class="token punctuation">,</span> TopLevelToken<span class="token punctuation">,</span> Value<span class="token punctuation">,</span> Tag<span class="token punctuation">,</span> Liquid <span class="token punctuation">&#125;</span> <span class="token keyword">from</span> <span class="token string">'liquidjs'</span>
<span class="token comment">// Usage: &#123;% upper "alice" %&#125;</span>
<span class="token comment">// Output: ALICE</span>
engine<span class="token punctuation">.</span><span class="token function">registerTag</span><span class="token punctuation">(</span><span class="token string">'upper'</span><span class="token punctuation">,</span> <span class="token keyword">class</span> <span class="token class-name">UpperTag</span> <span class="token keyword">extends</span> <span class="token class-name">Tag</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">private</span> value<span class="token operator">:</span> Value
<span class="token function">constructor</span> <span class="token punctuation">(</span>token<span class="token operator">:</span> TagToken<span class="token punctuation">,</span> remainTokens<span class="token operator">:</span> TopLevelToken<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> liquid<span class="token operator">:</span> Liquid<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">super</span><span class="token punctuation">(</span>token<span class="token punctuation">,</span> remainTokens<span class="token punctuation">,</span> liquid<span class="token punctuation">)</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>value <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Value</span><span class="token punctuation">(</span>token<span class="token punctuation">.</span>args<span class="token punctuation">,</span> liquid<span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span>
<span class="token operator">*</span> <span class="token function">render</span> <span class="token punctuation">(</span>ctx<span class="token operator">:</span> Context<span class="token punctuation">,</span> emitter<span class="token operator">:</span> Emitter<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">const</span> title <span class="token operator">=</span> <span class="token keyword">yield</span> <span class="token keyword">this</span><span class="token punctuation">.</span>value<span class="token punctuation">.</span><span class="token function">value</span><span class="token punctuation">(</span>ctx<span class="token punctuation">)</span>
emitter<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>title<span class="token punctuation">.</span><span class="token function">toUpperCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p>所有内置标签都兼容同步,可以安全地用于同步或异步 API。实现同时支持同异步的标签,需要:</p>
<ul>
@@ -119,19 +133,51 @@
<li>不能调用会返回 Promise 的函数。</li>
</ul>
<h2 id="调用返回-Promise-的函数" class="article-heading"><a href="#调用返回-Promise-的函数" class="headerlink" title="调用返回 Promise 的函数"></a>调用返回 Promise 的函数<a class="article-anchor" href="#调用返回-Promise-的函数" aria-hidden="true"></a></h2><p>但 LiquidJS 是支持 <code>Promise</code> 的,你仍然可以调用返回 <code>Promise</code> 的方法并等它 resolve。只需要把 <code>await</code> 换成 <code>yield</code>。例如:</p>
<figure class="highlight typescript"><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></pre></td><td class="code"><pre><span class="line">* <span class="title function_">render</span> (<span class="attr">ctx</span>: <span class="title class_">Context</span>, <span class="attr">emitter</span>: <span class="title class_">Emitter</span>) &#123;</span><br><span class="line"> <span class="keyword">const</span> file = <span class="keyword">yield</span> <span class="variable language_">this</span>.<span class="property">value</span>.<span class="title function_">value</span>(ctx)</span><br><span class="line"> <span class="keyword">const</span> title = <span class="keyword">yield</span> fs.<span class="title function_">readFile</span>(file, <span class="string">&#x27;utf8&#x27;</span>)</span><br><span class="line"> emitter.<span class="title function_">write</span>(title.<span class="title function_">toUpperCase</span>())</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-typescript" data-language="typescript"><code class="language-typescript"><span class="token operator">*</span> <span class="token function">render</span> <span class="token punctuation">(</span>ctx<span class="token operator">:</span> Context<span class="token punctuation">,</span> emitter<span class="token operator">:</span> Emitter<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">const</span> file <span class="token operator">=</span> <span class="token keyword">yield</span> <span class="token keyword">this</span><span class="token punctuation">.</span>value<span class="token punctuation">.</span><span class="token function">value</span><span class="token punctuation">(</span>ctx<span class="token punctuation">)</span>
<span class="token keyword">const</span> title <span class="token operator">=</span> <span class="token keyword">yield</span> fs<span class="token punctuation">.</span><span class="token function">readFile</span><span class="token punctuation">(</span>file<span class="token punctuation">,</span> <span class="token string">'utf8'</span><span class="token punctuation">)</span>
emitter<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>title<span class="token punctuation">.</span><span class="token function">toUpperCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p>现在 <code>* render()</code> 调用了一个返回 Promise 的 API,它就不再兼容同步了。不兼容同步的标签也仍然是合法标签,在异步 API 下也会正常运行。被同步调用时,返回 <code>Promise</code> 的标签会被渲染成 <code>[object Promise]</code></p>
<h2 id="把-LiquidJS-生成器转换成-Promise" class="article-heading"><a href="#把-LiquidJS-生成器转换成-Promise" class="headerlink" title="把 LiquidJS 生成器转换成 Promise"></a>把 LiquidJS 生成器转换成 Promise<a class="article-anchor" href="#把-LiquidJS-生成器转换成-Promise" aria-hidden="true"></a></h2><p>有些 LiquidJS API 会返回 <code>Promise</code>,有些会返回生成器。你可以用 <a href="/api/functions/toPromise.html">toPromise</a> 来把生成器转换为 <code>Promise</code>,比如:</p>
<figure class="highlight typescript"><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">import</span> &#123; <span class="title class_">TagToken</span>, <span class="title class_">Context</span>, <span class="title class_">Emitter</span>, <span class="title class_">TopLevelToken</span>, <span class="title class_">Value</span>, <span class="title class_">Tag</span>, <span class="title class_">Liquid</span>, toPromise &#125; <span class="keyword">from</span> <span class="string">&#x27;liquidjs&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// Usage: &#123;% upper &quot;alice&quot; %&#125;</span></span><br><span class="line"><span class="comment">// Output: ALICE</span></span><br><span class="line">engine.<span class="title function_">registerTag</span>(<span class="string">&#x27;upper&#x27;</span>, <span class="keyword">class</span> <span class="title class_">UpperTag</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Tag</span> &#123;</span><br><span class="line"> <span class="keyword">private</span> <span class="attr">value</span>: <span class="title class_">Value</span></span><br><span class="line"> <span class="title function_">constructor</span> (<span class="params"><span class="attr">token</span>: <span class="title class_">TagToken</span>, <span class="attr">remainTokens</span>: <span class="title class_">TopLevelToken</span>[], <span class="attr">liquid</span>: <span class="title class_">Liquid</span></span>) &#123;</span><br><span class="line"> <span class="variable language_">super</span>(token, remainTokens, liquid)</span><br><span class="line"> <span class="variable language_">this</span>.<span class="property">value</span> = <span class="keyword">new</span> <span class="title class_">Value</span>(token.<span class="property">args</span>, liquid)</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">async</span> <span class="title function_">render</span> (<span class="attr">ctx</span>: <span class="title class_">Context</span>, <span class="attr">emitter</span>: <span class="title class_">Emitter</span>) &#123;</span><br><span class="line"> <span class="keyword">const</span> title = <span class="keyword">await</span> <span class="title function_">toPromise</span>(<span class="variable language_">this</span>.<span class="property">value</span>.<span class="title function_">value</span>(ctx))</span><br><span class="line"> emitter.<span class="title function_">write</span>(title.<span class="title function_">toUpperCase</span>())</span><br><span class="line"> &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">import</span> <span class="token punctuation">&#123;</span> TagToken<span class="token punctuation">,</span> Context<span class="token punctuation">,</span> Emitter<span class="token punctuation">,</span> TopLevelToken<span class="token punctuation">,</span> Value<span class="token punctuation">,</span> Tag<span class="token punctuation">,</span> Liquid<span class="token punctuation">,</span> toPromise <span class="token punctuation">&#125;</span> <span class="token keyword">from</span> <span class="token string">'liquidjs'</span>
<span class="token comment">// Usage: &#123;% upper "alice" %&#125;</span>
<span class="token comment">// Output: ALICE</span>
engine<span class="token punctuation">.</span><span class="token function">registerTag</span><span class="token punctuation">(</span><span class="token string">'upper'</span><span class="token punctuation">,</span> <span class="token keyword">class</span> <span class="token class-name">UpperTag</span> <span class="token keyword">extends</span> <span class="token class-name">Tag</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">private</span> value<span class="token operator">:</span> Value
<span class="token function">constructor</span> <span class="token punctuation">(</span>token<span class="token operator">:</span> TagToken<span class="token punctuation">,</span> remainTokens<span class="token operator">:</span> TopLevelToken<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> liquid<span class="token operator">:</span> Liquid<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">super</span><span class="token punctuation">(</span>token<span class="token punctuation">,</span> remainTokens<span class="token punctuation">,</span> liquid<span class="token punctuation">)</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>value <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Value</span><span class="token punctuation">(</span>token<span class="token punctuation">.</span>args<span class="token punctuation">,</span> liquid<span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">async</span> <span class="token function">render</span> <span class="token punctuation">(</span>ctx<span class="token operator">:</span> Context<span class="token punctuation">,</span> emitter<span class="token operator">:</span> Emitter<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">const</span> title <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">toPromise</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>value<span class="token punctuation">.</span><span class="token function">value</span><span class="token punctuation">(</span>ctx<span class="token punctuation">)</span><span class="token punctuation">)</span>
emitter<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>title<span class="token punctuation">.</span><span class="token function">toUpperCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<h2 id="纯异步标签" class="article-heading"><a href="#纯异步标签" class="headerlink" title="纯异步标签"></a>纯异步标签<a class="article-anchor" href="#纯异步标签" aria-hidden="true"></a></h2><p>如果你的标签就不打算支持同步,可以干脆实现成 <code>async render()</code>,这样就可以使用更熟悉的 <code>await</code> 了:</p>
<figure class="highlight typescript"><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">import</span> &#123; toPromise, <span class="title class_">TagToken</span>, <span class="title class_">Context</span>, <span class="title class_">Emitter</span>, <span class="title class_">TopLevelToken</span>, <span class="title class_">Value</span>, <span class="title class_">Tag</span>, <span class="title class_">Liquid</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;liquidjs&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// Usage: &#123;% upper &quot;alice&quot; %&#125;</span></span><br><span class="line"><span class="comment">// Output: ALICE</span></span><br><span class="line">engine.<span class="title function_">registerTag</span>(<span class="string">&#x27;upper&#x27;</span>, <span class="keyword">class</span> <span class="title class_">UpperTag</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Tag</span> &#123;</span><br><span class="line"> <span class="keyword">private</span> <span class="attr">value</span>: <span class="title class_">Value</span></span><br><span class="line"> <span class="title function_">constructor</span> (<span class="params"><span class="attr">token</span>: <span class="title class_">TagToken</span>, <span class="attr">remainTokens</span>: <span class="title class_">TopLevelToken</span>[], <span class="attr">liquid</span>: <span class="title class_">Liquid</span></span>) &#123;</span><br><span class="line"> <span class="variable language_">super</span>(token, remainTokens, liquid)</span><br><span class="line"> <span class="variable language_">this</span>.<span class="property">value</span> = <span class="keyword">new</span> <span class="title class_">Value</span>(token.<span class="property">args</span>, liquid)</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">async</span> <span class="title function_">render</span> (<span class="attr">ctx</span>: <span class="title class_">Context</span>, <span class="attr">emitter</span>: <span class="title class_">Emitter</span>) &#123;</span><br><span class="line"> <span class="keyword">const</span> title = <span class="keyword">await</span> <span class="title function_">toPromise</span>(<span class="variable language_">this</span>.<span class="property">value</span>.<span class="title function_">value</span>(ctx))</span><br><span class="line"> emitter.<span class="title function_">write</span>(<span class="string">`&lt;h1&gt;<span class="subst">$&#123;title&#125;</span>&lt;/h1&gt;`</span>)</span><br><span class="line"> &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">import</span> <span class="token punctuation">&#123;</span> toPromise<span class="token punctuation">,</span> TagToken<span class="token punctuation">,</span> Context<span class="token punctuation">,</span> Emitter<span class="token punctuation">,</span> TopLevelToken<span class="token punctuation">,</span> Value<span class="token punctuation">,</span> Tag<span class="token punctuation">,</span> Liquid <span class="token punctuation">&#125;</span> <span class="token keyword">from</span> <span class="token string">'liquidjs'</span>
<span class="token comment">// Usage: &#123;% upper "alice" %&#125;</span>
<span class="token comment">// Output: ALICE</span>
engine<span class="token punctuation">.</span><span class="token function">registerTag</span><span class="token punctuation">(</span><span class="token string">'upper'</span><span class="token punctuation">,</span> <span class="token keyword">class</span> <span class="token class-name">UpperTag</span> <span class="token keyword">extends</span> <span class="token class-name">Tag</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">private</span> value<span class="token operator">:</span> Value
<span class="token function">constructor</span> <span class="token punctuation">(</span>token<span class="token operator">:</span> TagToken<span class="token punctuation">,</span> remainTokens<span class="token operator">:</span> TopLevelToken<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> liquid<span class="token operator">:</span> Liquid<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">super</span><span class="token punctuation">(</span>token<span class="token punctuation">,</span> remainTokens<span class="token punctuation">,</span> liquid<span class="token punctuation">)</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>value <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Value</span><span class="token punctuation">(</span>token<span class="token punctuation">.</span>args<span class="token punctuation">,</span> liquid<span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">async</span> <span class="token function">render</span> <span class="token punctuation">(</span>ctx<span class="token operator">:</span> Context<span class="token punctuation">,</span> emitter<span class="token operator">:</span> Emitter<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">const</span> title <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">toPromise</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>value<span class="token punctuation">.</span><span class="token function">value</span><span class="token punctuation">(</span>ctx<span class="token punctuation">)</span><span class="token punctuation">)</span>
emitter<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">&lt;h1></span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>title<span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token string">&lt;/h1></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.430Z" itemprop="dateModified">上次更新:2024-08-19</time>
<time class="article-footer-updated" datetime="2024-08-20T01:26:05.768Z" itemprop="dateModified">上次更新:2024-08-20</time>
<a href="drops.html" class="article-footer-prev" title="Liquid Drop"><i class="icon-chevron-left"></i><span>上一页</span></a><a href="whitespace-control.html" class="article-footer-next" title="换行和缩进"><span>下一页</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-19T19:36:26.430Z" itemprop="dateModified">上次更新:2024-08-19</time>
<time class="article-footer-updated" datetime="2024-08-20T01:26:05.768Z" itemprop="dateModified">上次更新:2024-08-20</time>
<a href="operators.html" class="article-footer-prev" title="运算符"><i class="icon-chevron-left"></i><span>上一页</span></a><a href="dos.html" class="article-footer-next" title="DoS"><span>下一页</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+27 -6
View File
@@ -93,28 +93,49 @@
</header>
<div class="article-content" itemprop="articleBody">
<p>LiquidJS 可以用来作为 <a target="_blank" rel="noopener external nofollow noreferrer" href="https://expressjs.com/en/resources/template-engines.html">Express 的模板引擎</a>。可以把 Liquid 设置到 <a target="_blank" rel="noopener external nofollow noreferrer" href="http://expressjs.com/en/guide/using-template-engines.html">view engine</a> 选项上即可:</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> &#123; <span class="title class_">Liquid</span> &#125; = <span class="built_in">require</span>(<span class="string">&#x27;liquidjs&#x27;</span>);</span><br><span class="line"><span class="keyword">var</span> engine = <span class="keyword">new</span> <span class="title class_">Liquid</span>();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 注册为 liquid 文件的模板引擎</span></span><br><span class="line">app.<span class="title function_">engine</span>(<span class="string">&#x27;liquid&#x27;</span>, engine.<span class="title function_">express</span>()); </span><br><span class="line">app.<span class="title function_">set</span>(<span class="string">&#x27;views&#x27;</span>, <span class="string">&#x27;./views&#x27;</span>); <span class="comment">// 指定模板目录</span></span><br><span class="line">app.<span class="title function_">set</span>(<span class="string">&#x27;view engine&#x27;</span>, <span class="string">&#x27;liquid&#x27;</span>); <span class="comment">// 把 liquid 文件设为默认模板</span></span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">var</span> <span class="token punctuation">&#123;</span> Liquid <span class="token punctuation">&#125;</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'liquidjs'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> engine <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Liquid</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 注册为 liquid 文件的模板引擎</span>
app<span class="token punctuation">.</span><span class="token function">engine</span><span class="token punctuation">(</span><span class="token string">'liquid'</span><span class="token punctuation">,</span> engine<span class="token punctuation">.</span><span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
app<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">'views'</span><span class="token punctuation">,</span> <span class="token string">'./views'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 指定模板目录</span>
app<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">'view engine'</span><span class="token punctuation">,</span> <span class="token string">'liquid'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 把 liquid 文件设为默认模板</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<blockquote class="note info"><strong class="note-title">示例</strong><p>这是一个在 Express.js 中使用 LiquidJS 的例子:<a href="https://github.com/harttle/liquidjs/blob/master/demo/express/" rel="external nofollow noreferrer" target="_blank">liquidjs/demo/express/</a>.</p>
</blockquote>
<h2 id="模板查找" class="article-heading"><a href="#模板查找" class="headerlink" title="模板查找"></a>模板查找<a class="article-anchor" href="#模板查找" aria-hidden="true"></a></h2><p>LiquidJS 仍然会去 <a href="/api/interfaces/LiquidOptions.html#root">root</a> 指定的目录查找(参考 <a href="./render-a-file.html">Render A Template File</a>),也会去 Express.js 的 <a target="_blank" rel="noopener external nofollow noreferrer" href="http://expressjs.com/en/guide/using-template-engines.html"><code>views</code></a> 选项指定的目录里(上述例子中是 <code>./views</code>)去查找。例如你有这样的目录结构:</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><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">.</span><br><span class="line">├── views1/</span><br><span class="line">│ └── hello.liquid</span><br><span class="line">└── views2/</span><br><span class="line"> └── world.liquid</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-none"><code class="language-none">.
├── views1&#x2F;
│ └── hello.liquid
└── views2&#x2F;
└── world.liquid<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p>LiquidJS 的模板 root 设置到了 <code>views1</code>Express.js 的 views 设置到了 <code>views2</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> &#123; <span class="title class_">Liquid</span> &#125; = <span class="built_in">require</span>(<span class="string">&#x27;liquidjs&#x27;</span>);</span><br><span class="line"><span class="keyword">var</span> engine = <span class="keyword">new</span> <span class="title class_">Liquid</span>(&#123;</span><br><span class="line"> <span class="attr">root</span>: <span class="string">&#x27;./views1/&#x27;</span></span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">app.<span class="title function_">engine</span>(<span class="string">&#x27;liquid&#x27;</span>, engine.<span class="title function_">express</span>()); </span><br><span class="line">app.<span class="title function_">set</span>(<span class="string">&#x27;views&#x27;</span>, <span class="string">&#x27;./views2&#x27;</span>);</span><br><span class="line">app.<span class="title function_">set</span>(<span class="string">&#x27;view engine&#x27;</span>, <span class="string">&#x27;liquid&#x27;</span>);</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">var</span> <span class="token punctuation">&#123;</span> Liquid <span class="token punctuation">&#125;</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'liquidjs'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> engine <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Liquid</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
<span class="token literal-property property">root</span><span class="token operator">:</span> <span class="token string">'./views1/'</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
app<span class="token punctuation">.</span><span class="token function">engine</span><span class="token punctuation">(</span><span class="token string">'liquid'</span><span class="token punctuation">,</span> engine<span class="token punctuation">.</span><span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
app<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">'views'</span><span class="token punctuation">,</span> <span class="token string">'./views2'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
app<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">'view engine'</span><span class="token punctuation">,</span> <span class="token string">'liquid'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p><code>hello.liquid</code><code>world.liquid</code> 两个文件都可以找到并且成功渲染:</p>
<figure class="highlight javascript"><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">res.<span class="title function_">render</span>(<span class="string">&#x27;hello&#x27;</span>)</span><br><span class="line">res.<span class="title function_">render</span>(<span class="string">&#x27;world&#x27;</span>)</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript">res<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span><span class="token string">'hello'</span><span class="token punctuation">)</span>
res<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span><span class="token string">'world'</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre>
<h2 id="缓存" class="article-heading"><a href="#缓存" class="headerlink" title="缓存"></a>缓存<a class="article-anchor" href="#缓存" aria-hidden="true"></a></h2><p>直接把 <a href="/api/interfaces/LiquidOptions.html#cache">cache 选项</a> 设为 <code>true</code> 即可开启模板缓存,参考 <a href="./caching.html">缓存</a> 一文。推荐在生产环境中开启缓存,可以用如下代码:</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> &#123; <span class="title class_">Liquid</span> &#125; = <span class="built_in">require</span>(<span class="string">&#x27;liquidjs&#x27;</span>);</span><br><span class="line"><span class="keyword">var</span> engine = <span class="keyword">new</span> <span class="title class_">Liquid</span>(&#123;</span><br><span class="line"> <span class="attr">cache</span>: process.<span class="property">env</span>.<span class="property">NODE_ENV</span> === <span class="string">&#x27;production&#x27;</span></span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">var</span> <span class="token punctuation">&#123;</span> Liquid <span class="token punctuation">&#125;</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'liquidjs'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> engine <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Liquid</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
<span class="token literal-property property">cache</span><span class="token operator">:</span> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">NODE_ENV</span> <span class="token operator">===</span> <span class="token string">'production'</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre>
<p><code>cache</code> 还可以是一个数字表示最大缓存的模板数量,也可以是一个自定义的缓存实现,详情请参考 <a href="/api/interfaces/LiquidOptions.html#cache">cache 选项</a></p>
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.430Z" itemprop="dateModified">上次更新:2024-08-19</time>
<time class="article-footer-updated" datetime="2024-08-20T01:26:05.768Z" itemprop="dateModified">上次更新:2024-08-20</time>
<a href="partials-and-layouts.html" class="article-footer-prev" title="引用/继承"><i class="icon-chevron-left"></i><span>上一页</span></a><a href="caching.html" class="article-footer-next" title="缓存"><span>下一页</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
+8 -5
View File
@@ -94,16 +94,19 @@
<div class="article-content" itemprop="articleBody">
<p>为了让源代码缩进好看,我们会加很多空白字符比如把不会产生输出的标签也单独一行。LiquidJS 提供了空白字符控制机制,可以避免这些多余的空白字符输出到 HTML 中。</p>
<h2 id="通过标记的方式" class="article-heading"><a href="#通过标记的方式" class="headerlink" title="通过标记的方式"></a>通过标记的方式<a class="article-anchor" href="#通过标记的方式" aria-hidden="true"></a></h2><p>默认所有标签和输出的行,都会在行尾产生一个换行(<code>\n</code>),如果有缩进的话还会产生很多前导空格。例如:</p>
<figure class="highlight plaintext"><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">&#123;% author = &quot;harttle&quot; %&#125;</span><br><span class="line">&#123;&#123; author &#125;&#125;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-liquid" data-language="liquid"><code class="language-liquid"><span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> author <span class="token operator">=</span> <span class="token string">"harttle"</span> <span class="token delimiter punctuation">%&#125;</span></span>
<span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;&#123;</span> author <span class="token delimiter punctuation">&#125;&#125;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre>
<p>将会输出(注意前面的空行):</p>
<figure class="highlight plaintext"><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"></span><br><span class="line">harttle</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-none"><code class="language-none">
harttle<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre>
<p>可以在标签和输出的标记里面加横线(<code>{{-</code>, <code>-&#125;&#125;</code>, <code>{%-</code>, <code>-%&#125;</code>)来移除左侧/右侧的空白。例如:</p>
<figure class="highlight plaintext"><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">&#123;% assign author = &quot;harttle&quot; -%&#125;</span><br><span class="line">&#123;&#123; author &#125;&#125;</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-liquid" data-language="liquid"><code class="language-liquid"><span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;%</span> <span class="token keyword">assign</span> author <span class="token operator">=</span> <span class="token string">"harttle"</span> <span class="token delimiter punctuation">-%&#125;</span></span>
<span class="token liquid language-liquid"><span class="token delimiter punctuation">&#123;&#123;</span> author <span class="token delimiter punctuation">&#125;&#125;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre>
<p>将会输出:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">harttle</span><br></pre></td></tr></table></figure>
<pre class="line-numbers language-none"><code class="language-none">harttle<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p>这个例子中 <code>-%&#125;</code> 移除了 <code>assign</code> 标签右侧的空白。</p>
<h2 id="通过选项" class="article-heading"><a href="#通过选项" class="headerlink" title="通过选项"></a>通过选项<a class="article-anchor" href="#通过选项" aria-hidden="true"></a></h2><p>此外 LiquidJS 还提供了一系列选项来帮助扫代码式地移除空白:</p>
@@ -118,7 +121,7 @@
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2024-08-19T19:36:26.430Z" itemprop="dateModified">上次更新:2024-08-19</time>
<time class="article-footer-updated" datetime="2024-08-20T01:26:05.768Z" itemprop="dateModified">上次更新:2024-08-20</time>
<a href="sync-and-async.html" class="article-footer-prev" title="同步和异步"><i class="icon-chevron-left"></i><span>上一页</span></a><a href="plugins.html" class="article-footer-next" title="插件"><span>下一页</span><i class="icon-chevron-right"></i></a>
</footer>
</div>