Files
liquidjs/tutorials/parse-parameters.html
T

198 lines
21 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head prefix="og: http://ogp.me/ns#">
<meta charset="utf-8">
<title>Parse Parameters | LiquidJS</title>
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="dns-prefetch" href="https://cdn.jsdelivr.net/">
<link rel="manifest" href="/manifest.json">
<!-- Canonical links -->
<link rel="canonical" href="https://liquidjs.com/tutorials/parse-parameters.html">
<!-- Alternative links -->
<link rel="alternative" hreflang="en" href="https://liquidjs.com/tutorials/parse-parameters">
<link rel="alternative" hreflang="zh-cn" href="https://liquidjs.com/zh-cn/tutorials/parse-parameters">
<!-- Icon -->
<link rel="apple-touch-icon" sizes="57x57" href="../icon/apple-touch-icon-57x57.png">
<link rel="apple-touch-icon" sizes="114x114" href="../icon/apple-touch-icon-114x114.png">
<link rel="apple-touch-icon" sizes="72x72" href="../icon/apple-touch-icon-72x72.png">
<link rel="apple-touch-icon" sizes="144x144" href="../icon/apple-touch-icon-144x144.png">
<link rel="apple-touch-icon" sizes="60x60" href="../icon/apple-touch-icon-60x60.png">
<link rel="apple-touch-icon" sizes="120x120" href="../icon/apple-touch-icon-120x120.png">
<link rel="apple-touch-icon" sizes="76x76" href="../icon/apple-touch-icon-76x76.png">
<link rel="apple-touch-icon" sizes="152x152" href="../icon/apple-touch-icon-152x152.png">
<link rel="icon" type="image/png" href="../icon/favicon-196x196.png" sizes="196x196">
<link rel="icon" type="image/png" href="../icon/favicon-160x160.png" sizes="160x160">
<link rel="icon" type="image/png" href="../icon/favicon-96x96.png" sizes="96x96">
<link rel="icon" type="image/png" href="../icon/favicon-16x16.png" sizes="16x16">
<link rel="icon" type="image/png" href="../icon/favicon-32x32.png" sizes="32x32">
<meta name="msapplication-TileColor" content="#2f83cd">
<meta name="msapplication-TileImage" content="../icon/mstile-144x144.png">
<link rel="stylesheet" href="../css/navy.css">
<link rel="alternate" href="../atom.xml" title="LiquidJS" type="application/atom+xml">
<meta name="generator" content="Hexo 5.4.0"></head>
<body>
<div id="container">
<header id="header" class="wrapper">
<div id="header-inner" class="inner">
<h1 id="logo-wrap">
<a href="../index.html" id="logo">LiquidJS</a>
</h1>
<nav id="main-nav">
<a href="../tutorials/intro-to-liquid.html" class="main-nav-link">Tutorials</a><a href="../tags/overview.html" class="main-nav-link">Tags</a><a href="../filters/overview.html" class="main-nav-link">Filters</a><a href="../playground.html" class="main-nav-link">Playground</a><a href="../api/classes/liquid_.liquid.html" class="main-nav-link">API</a>
<div id="search-input-wrap">
<i id="search-input-icon" class="icon-search"></i>
<input type="search" id="search-input" placeholder="Search...">
</div>
</nav>
<div id="lang-select-wrap" class="main-nav-link">
<label><i class="icon-network"></i>English</label>
<select id="lang-select" data-canonical="tutorials/parse-parameters.html">
<option value="en" selected>English</option>
<option value="zh-cn">简体中文</option>
</select>
</div>
<a target="_blank" rel="noopener external nofollow noreferrer" href="https://github.com/harttle/liquidjs" id="github-link-wrap" class="main-nav-link"><i class="icon-github"></i>Github</a>
<a id="mobile-nav-toggle">
<span class="mobile-nav-toggle-bar"></span>
<span class="mobile-nav-toggle-bar"></span>
<span class="mobile-nav-toggle-bar"></span>
</a>
</div>
</header>
<div id="content-wrap">
<div id="content" class="wrapper">
<div id="content-inner">
<aside id="sidebar" role="navigation">
<div class="inner">
<strong class="sidebar-title">Getting Started</strong><a href="intro-to-liquid.html" class="sidebar-link">Intro to Liquid</a><a href="setup.html" class="sidebar-link">Setup</a><a href="options.html" class="sidebar-link">Options</a><a href="render-file.html" class="sidebar-link">Render Files</a><a href="partials-and-layouts.html" class="sidebar-link">Includes and Layouts</a><a href="use-in-expressjs.html" class="sidebar-link">Use in Express.js</a><strong class="sidebar-title">Advanced</strong><a href="caching.html" class="sidebar-link">Caching</a><a href="register-filters-tags.html" class="sidebar-link">Register Filters/Tags</a><a href="access-scope-in-filters.html" class="sidebar-link">Access Scope in Filters</a><a href="parse-parameters.html" class="sidebar-link current">Parse Parameters</a><a href="sync-and-async.html" class="sidebar-link">Sync and Async</a><a href="whitespace-control.html" class="sidebar-link">Whitespace Control</a><a href="plugins.html" class="sidebar-link">Plugins</a><a href="operators.html" class="sidebar-link">Operators</a><a href="truthy-and-falsy.html" class="sidebar-link">Truthy and Falsy</a><strong class="sidebar-title">Miscellaneous</strong><a href="migrate-to-9.html" class="sidebar-link">Migrate to LiquidJS 9</a><a href="changelog.html" class="sidebar-link">Changelog</a><a href="differences.html" class="sidebar-link">Differences with Shopify/liquid</a><a href="contribution-guidelines.html" class="sidebar-link">Contribution Guidelines</a>
</div>
</aside>
<article class="article-container" itemscope itemtype="http://schema.org/Article">
<div class="article-inner">
<div class="article">
<div class="inner">
<header class="article-header">
<h1 class="article-title" itemprop="name">Parse Parameters</h1>
<a target="_blank" rel="noopener external nofollow noreferrer" href="https://github.com/harttle/liquidjs/edit/master/docs/source/tutorials/parse-parameters.md" class="article-edit-link" title="Improve this doc"><i class="icon-pencil"></i></a>
</header>
<div class="article-content" itemprop="articleBody">
<h2 id="Access-Raw-Parameters" class="article-heading"><a href="#Access-Raw-Parameters" class="headerlink" title="Access Raw Parameters"></a>Access Raw Parameters<a class="article-anchor" href="#Access-Raw-Parameters" aria-hidden="true"></a></h2><p>As covered in <a href="/tutorials/register-filters-tags.html">Register Filters/Tags</a>, tag parameters is available on <code>tagToken.args</code> as a raw string. For example:</p>
<figure class="highlight javascript"><table><tr><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.registerTag(<span class="string">&#x27;random&#x27;</span>, &#123;</span><br><span class="line"> <span class="function"><span class="title">parse</span>(<span class="params">tagToken</span>)</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="built_in">this</span>.items = tagToken.args.split(<span class="string">&#x27; &#x27;</span>)</span><br><span class="line"> &#125;,</span><br><span class="line"> <span class="function"><span class="title">render</span>(<span class="params">context, emitter</span>)</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="built_in">Math</span>.floor(<span class="built_in">this</span>.items.length * <span class="built_in">Math</span>.random())</span><br><span class="line"> <span class="comment">// output that item</span></span><br><span class="line"> emitter.write(<span class="built_in">this</span>.items[index])</span><br><span class="line"> &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>
<p>Heres a JSFiddle version: <a target="_blank" rel="noopener external nofollow noreferrer" href="http://jsfiddle.net/ctj364up/2/">http://jsfiddle.net/ctj364up/2/</a></p>
<h2 id="Parse-Parameters-as-Values" class="article-heading"><a href="#Parse-Parameters-as-Values" class="headerlink" title="Parse Parameters as Values"></a>Parse Parameters as Values<a class="article-anchor" href="#Parse-Parameters-as-Values" aria-hidden="true"></a></h2><p>Sometimes we need more dynamic tags and want to pass values to the custom tag instead of static strings. Variables in LiquidJS can be literal (string, number, etc.) or a variable from current context scope.</p>
<p>The following modified template also contains 3 values to random from, but theyre values instead of static strings. The first one is string literal, second one is an identifier, third one is a property access sequence containing two identifiers.</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&#123;% random &quot;foo&quot; bar obj.coo %&#125;</span><br></pre></td></tr></table></figure>
<p>It can be tricky to parse all these cases manually, but theres a <a href="/api/classes/parser_tokenizer_.tokenizer.html">Tokenizer</a> class in LiquidJS you can make use of.</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> &#123; Liquid, Tokenizer, evalToken &#125; = <span class="built_in">require</span>(<span class="string">&#x27;liquidjs&#x27;</span>)</span><br><span class="line">engine.registerTag(<span class="string">&#x27;random&#x27;</span>, &#123;</span><br><span class="line"> <span class="function"><span class="title">parse</span>(<span class="params">tagToken</span>)</span> &#123;</span><br><span class="line"> <span class="keyword">const</span> tokenizer = <span class="keyword">new</span> Tokenizer(tagToken.args)</span><br><span class="line"> <span class="built_in">this</span>.items = []</span><br><span class="line"> <span class="keyword">while</span> (!tokenizer.end()) &#123;</span><br><span class="line"> <span class="comment">// here readValue() returns a LiteralToken or PropertyAccessToken</span></span><br><span class="line"> <span class="built_in">this</span>.items.push(tokenizer.readValue())</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;,</span><br><span class="line"> * <span class="function"><span class="title">render</span>(<span class="params">context, emitter</span>)</span> &#123;</span><br><span class="line"> <span class="keyword">const</span> index = <span class="built_in">Math</span>.floor(<span class="built_in">this</span>.items.length * <span class="built_in">Math</span>.random())</span><br><span class="line"> <span class="keyword">const</span> token = <span class="built_in">this</span>.items[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> evalToken(token, context)</span><br><span class="line"> emitter.write(value)</span><br><span class="line"> &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>
<p>Calling this tag in scope <code>&#123; bar: &quot;bar&quot;, obj: &#123; coo: &quot;coo&quot; &#125; &#125;</code> yields exactly the same result as the first example. See this 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">Async ans Promises</strong><p>Async calls in LiquidJS are implemented by generators directly, for we can call generators in synchronous manner so this tag implementation is also valid for <code>renderSync()</code>, <code>parseAndRenderSync()</code>, <code>renderFileSync()</code>. If you need to await a promise in tag implementation, simply replace <code>await somePromise</code> with <code>yield somePromise</code> and keep <code>* render()</code> instead of <code>async render()</code> will do the trick. See <a href="/tutorials/sync-and-async.html">Sync and Async</a> for more details.</p>
</blockquote>
<h2 id="Parse-Key-Value-Pairs-as-Named-Parameters" class="article-heading"><a href="#Parse-Key-Value-Pairs-as-Named-Parameters" class="headerlink" title="Parse Key-Value Pairs as Named Parameters"></a>Parse Key-Value Pairs as Named Parameters<a class="article-anchor" href="#Parse-Key-Value-Pairs-as-Named-Parameters" aria-hidden="true"></a></h2><p>Named parameters become very handy when therere optional parameters or lots of parameters, in which case the order of parameters is not important. This is exactly what <a href="/api/classes/template_tag_hash_.hash.html">Hash</a> class is invented for.</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&#123;% random from:2, to:max %&#125;</span><br></pre></td></tr></table></figure>
<p>In the above example, were trying to generate a random number in the range [2, max]. Well use <code>Hash</code> to parse <code>from</code> and <code>to</code> parameters.</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> &#123; Liquid, Hash &#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.registerTag(<span class="string">&#x27;random&#x27;</span>, &#123;</span><br><span class="line"> <span class="function"><span class="title">parse</span>(<span class="params">tagToken</span>)</span> &#123;</span><br><span class="line"> <span class="comment">// parse the parameters structure into `this.args`</span></span><br><span class="line"> <span class="built_in">this</span>.args = <span class="keyword">new</span> Hash(tagToken.args)</span><br><span class="line"> &#125;,</span><br><span class="line"> * <span class="function"><span class="title">render</span>(<span class="params">context, emitter</span>)</span> &#123;</span><br><span class="line"> <span class="comment">// evaluate the parameters in `context`</span></span><br><span class="line"> <span class="keyword">const</span> &#123;<span class="keyword">from</span>, to&#125; = <span class="keyword">yield</span> <span class="built_in">this</span>.args.render(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="built_in">Math</span>.floor(length * <span class="built_in">Math</span>.random())</span><br><span class="line"> emitter.write(value)</span><br><span class="line"> &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>
<p>Rendering <code>&#123;% random from:2, to:max %&#125;</code> in scope <code>&#123; max: 10 &#125;</code> will generate a random number in the range [2, 10]. See this JSFiddle: <a target="_blank" rel="noopener external nofollow noreferrer" href="http://jsfiddle.net/ctj364up/4/">http://jsfiddle.net/ctj364up/4/</a></p>
</div>
<footer class="article-footer">
<time class="article-footer-updated" datetime="2022-01-22T15:25:05.203Z" itemprop="dateModified">Last updated: 2022-01-22</time>
<a href="access-scope-in-filters.html" class="article-footer-prev" title="Access Scope in Filters"><i class="icon-chevron-left"></i><span>Prev</span></a><a href="sync-and-async.html" class="article-footer-next" title="Sync and Async"><span>Next</span><i class="icon-chevron-right"></i></a>
</footer>
</div>
</div>
<aside id="article-toc" role="navigation">
<div id="article-toc-inner">
<div id="article-toc-inner-list">
<strong class="sidebar-title">Contents</strong>
<ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#Access-Raw-Parameters"><span class="toc-text">Access Raw Parameters</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Parse-Parameters-as-Values"><span class="toc-text">Parse Parameters as Values</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Parse-Key-Value-Pairs-as-Named-Parameters"><span class="toc-text">Parse Key-Value Pairs as Named Parameters</span></a></li></ol>
</div>
<a href="#" id="article-toc-top">Back to Top</a>
</div>
</aside>
</div>
</article>
</div>
</div>
</div>
<footer id="footer" class="wrapper">
<div class="inner">
<div id="footer-copyright">
&copy; 2022 <a href="https://github.com/harttle/liquidjs/graphs/contributors" rel="external nofollow noreferrer" target="_blank">Harttle</a><br>
Documentation licensed under <a href="http://creativecommons.org/licenses/by/4.0/" rel="external nofollow noreferrer" target="_blank">CC BY 4.0</a>.
</div>
<div id="footer-links">
<a href="https://twitter.com/harttleharttle" rel="external nofollow noreferrer" class="footer-link" target="_blank"><i class="icon-twitter"></i></a>
<a href="https://www.patreon.com/harttle" rel="external nofollow noreferrer" class="footer-link" target="_blank"><i class="icon-patreon"></i></a>
<a href="https://opencollective.com/liquidjs" rel="external nofollow noreferrer" class="footer-link" target="_blank"><i class="icon-opencollective"></i></a>
<a href="https://github.com/harttle/liquidjs" rel="external nofollow noreferrer" class="footer-link" target="_blank"><i class="icon-github"></i></a>
</div>
</div>
</footer>
</div>
<div id="mobile-nav-dimmer"></div>
<nav id="mobile-nav">
<div id="mobile-nav-inner">
<ul id="mobile-nav-list">
<a href="../tutorials/intro-to-liquid.html" class="mobile-nav-link">Tutorials</a><a href="../tags/overview.html" class="mobile-nav-link">Tags</a><a href="../filters/overview.html" class="mobile-nav-link">Filters</a><a href="../playground.html" class="mobile-nav-link">Playground</a><a href="../api/classes/liquid_.liquid.html" class="mobile-nav-link">API</a>
<li class="mobile-nav-item">
<a href="https://github.com/harttle/liquidjs" class="mobile-nav-link" rel="external" target="_blank">GitHub</a>
</li>
</ul>
<div class="mobile-sidebar-list">
<strong class="mobile-nav-title">Getting Started</strong><a href="intro-to-liquid.html" class="mobile-nav-link">Intro to Liquid</a><a href="setup.html" class="mobile-nav-link">Setup</a><a href="options.html" class="mobile-nav-link">Options</a><a href="render-file.html" class="mobile-nav-link">Render Files</a><a href="partials-and-layouts.html" class="mobile-nav-link">Includes and Layouts</a><a href="use-in-expressjs.html" class="mobile-nav-link">Use in Express.js</a><strong class="mobile-nav-title">Advanced</strong><a href="caching.html" class="mobile-nav-link">Caching</a><a href="register-filters-tags.html" class="mobile-nav-link">Register Filters/Tags</a><a href="access-scope-in-filters.html" class="mobile-nav-link">Access Scope in Filters</a><a href="parse-parameters.html" class="mobile-nav-link current">Parse Parameters</a><a href="sync-and-async.html" class="mobile-nav-link">Sync and Async</a><a href="whitespace-control.html" class="mobile-nav-link">Whitespace Control</a><a href="plugins.html" class="mobile-nav-link">Plugins</a><a href="operators.html" class="mobile-nav-link">Operators</a><a href="truthy-and-falsy.html" class="mobile-nav-link">Truthy and Falsy</a><strong class="mobile-nav-title">Miscellaneous</strong><a href="migrate-to-9.html" class="mobile-nav-link">Migrate to LiquidJS 9</a><a href="changelog.html" class="mobile-nav-link">Changelog</a><a href="differences.html" class="mobile-nav-link">Differences with Shopify/liquid</a><a href="contribution-guidelines.html" class="mobile-nav-link">Contribution Guidelines</a>
</div>
</div>
<div id="mobile-lang-select-wrap">
<span id="mobile-lang-select-label"><i class="icon-network"></i><span>English</span></span>
<select id="mobile-lang-select" data-canonical="tutorials/parse-parameters.html">
<option value="en" selected>English</option>
<option value="zh-cn">简体中文</option>
</select>
</div>
</nav>
<script src="../js/main.js"></script>
<script src="https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.js"></script>
<script>
document.getElementById('search-input-wrap').classList.add('on');
docsearch({
apiKey: '01f36cc168657a26a385308b9e721bc6',
indexName: 'liquidjs',
inputSelector: '#search-input',
debug: false
});
</script>
</body>
</html>