mirror of
https://github.com/harttle/liquidjs.git
synced 2026-09-15 12:20:40 -07:00
225 lines
25 KiB
HTML
225 lines
25 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head prefix="og: https://ogp.me/ns#">
|
|
<meta charset="utf-8">
|
|
<title>Security Model | LiquidJS</title>
|
|
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<meta name="description" content="LiquidJS is a simple, expressive, and safe template engine for JavaScript, compatible with Shopify and GitHub Pages.">
|
|
<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/security-model.html">
|
|
<!-- Alternative links -->
|
|
|
|
|
|
<link rel="alternative" hreflang="en" href="https://liquidjs.com/tutorials/security-model">
|
|
|
|
|
|
<!-- 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">
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/orestbida/[email protected]/dist/cookieconsent.css">
|
|
<script src="https://cdn.jsdelivr.net/gh/orestbida/[email protected]/dist/cookieconsent.umd.js"></script>
|
|
|
|
<script src="../js/cookieconsent-config.js"></script>
|
|
|
|
<meta name="generator" content="Hexo 7.3.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.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 class="main-nav-link icon-nav-link github-buttons-wrap">
|
|
<span class="gh-star">
|
|
<a class="gh-btn" href="https://github.com/harttle/liquidjs" target="_blank" rel="noopener external nofollow noreferrer" aria-label="Star harttle/liquidjs on GitHub">
|
|
<svg class="gh-btn-icon" viewBox="0 0 16 16" width="16" height="16" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"></path></svg>
|
|
<span>Star</span>
|
|
</a>
|
|
<a class="gh-count" id="gh-star-count" href="https://github.com/harttle/liquidjs" target="_blank" rel="noopener external nofollow noreferrer" aria-label="harttle/liquidjs stargazers"></a>
|
|
</span>
|
|
<a class="gh-btn gh-sponsor" href="https://github.com/sponsors/harttle" target="_blank" rel="noopener external nofollow noreferrer" aria-label="Sponsor @harttle on GitHub">
|
|
<svg class="gh-btn-icon" viewBox="0 0 16 16" width="16" height="16" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"></path></svg>
|
|
<span>Sponsor</span>
|
|
</a>
|
|
</div>
|
|
<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="escaping.html" class="sidebar-link">Escaping</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">Parse Parameters</a><a href="render-tag-content.html" class="sidebar-link">Render Tag Content</a><a href="drops.html" class="sidebar-link">Liquid Drops</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><a href="security-model.html" class="sidebar-link current">Security Model</a><a href="static-analysis.html" class="sidebar-link">Static Analysis</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="https://schema.org/Article">
|
|
<div class="article-inner">
|
|
<div class="article">
|
|
<div class="inner">
|
|
<header class="article-header">
|
|
<h1 class="article-title" itemprop="name">Security Model</h1>
|
|
|
|
<a target="_blank" rel="noopener external nofollow noreferrer" href="https://github.com/harttle/liquidjs/edit/master/docs/source/tutorials/security-model.md" class="article-edit-link" title="Improve this doc"><i class="icon-pencil"></i></a>
|
|
|
|
</header>
|
|
<div class="article-content" itemprop="articleBody">
|
|
<p>LiquidJS provides DoS-oriented limits (<code>parseLimit</code>, <code>renderLimit</code>, <code>memoryLimit</code>) to reduce risk. This page summarizes those limits, <a href="/api/interfaces/LiquidOptions.html#ownPropertyOnly"><code>ownPropertyOnly</code></a>, custom <a href="/api/classes/Drop.html"><code>Drop</code></a> usage, and the security boundary to assume in production.</p>
|
|
<h2 id="Security-boundary" class="article-heading"><a href="#Security-boundary" class="headerlink" title="Security boundary"></a>Security boundary<a class="article-anchor" href="#Security-boundary" aria-hidden="true"></a></h2><p>The built-in limits are cooperative safeguards, not strict runtime isolation.</p>
|
|
<ul>
|
|
<li>They do <strong>not</strong> equal process RSS/heap usage.</li>
|
|
<li>They do <strong>not</strong> sandbox JavaScript execution.</li>
|
|
<li>They should be combined with process/container limits and request timeouts for defense in depth.</li>
|
|
</ul>
|
|
<h2 id="Limits-at-a-glance" class="article-heading"><a href="#Limits-at-a-glance" class="headerlink" title="Limits at a glance"></a>Limits at a glance<a class="article-anchor" href="#Limits-at-a-glance" aria-hidden="true"></a></h2><ul>
|
|
<li><a href="/api/interfaces/LiquidOptions.html#parseLimit">parseLimit</a>: limit total template size per <code>parse()</code> call.</li>
|
|
<li><a href="/api/interfaces/LiquidOptions.html#renderLimit">renderLimit</a>: limit total render time per <code>render()</code> call.</li>
|
|
<li><a href="/api/interfaces/LiquidOptions.html#memoryLimit">memoryLimit</a>: cooperatively limit memory-sensitive allocations counted by LiquidJS.</li>
|
|
</ul>
|
|
<h2 id="Limit-details" class="article-heading"><a href="#Limit-details" class="headerlink" title="Limit details"></a>Limit details<a class="article-anchor" href="#Limit-details" aria-hidden="true"></a></h2><h3 id="parseLimit" class="article-heading"><a href="#parseLimit" class="headerlink" title="parseLimit"></a>parseLimit<a class="article-anchor" href="#parseLimit" aria-hidden="true"></a></h3><p><a href="/api/interfaces/LiquidOptions.html#parseLimit">parseLimit</a> restricts the size (character length) of templates parsed in each <code>.parse()</code> call, including referenced partials and layouts. Since LiquidJS parses template strings in near O(n) time, limiting total template length is usually sufficient.</p>
|
|
<p>A typical PC handles <code>1e8</code> (100M) characters without issues.</p>
|
|
<h3 id="renderLimit" class="article-heading"><a href="#renderLimit" class="headerlink" title="renderLimit"></a>renderLimit<a class="article-anchor" href="#renderLimit" aria-hidden="true"></a></h3><p>Restricting template size alone is insufficient because dynamic loops with large counts can occur during rendering. <a href="/api/interfaces/LiquidOptions.html#renderLimit">renderLimit</a> mitigates this by limiting the time consumed by each <code>render()</code> call.</p>
|
|
<pre class="line-numbers language-liquid" data-language="liquid"><code class="language-liquid"><span class="token liquid language-liquid"><span class="token delimiter punctuation">{%-</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">-%}</span></span>
|
|
order: <span class="token liquid language-liquid"><span class="token delimiter punctuation">{{</span>i<span class="token delimiter punctuation">}}</span></span>
|
|
<span class="token liquid language-liquid"><span class="token delimiter punctuation">{%-</span> <span class="token keyword">endfor</span> <span class="token delimiter punctuation">-%}</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre>
|
|
|
|
<p>Render time is checked on a per-template basis (before rendering each template). In the above example, there are 2 templates in the loop: <code>order:</code> and <code>{{i}}</code>, render time will be checked 10000000x2 times.</p>
|
|
<p><code>renderLimit</code> is not a hard CPU limiter. It is checked between template renders, so compute-intensive filters/tags/user-defined functions or deeply nested template execution between checks can still cause DoS.</p>
|
|
<h3 id="memoryLimit" class="article-heading"><a href="#memoryLimit" class="headerlink" title="memoryLimit"></a>memoryLimit<a class="article-anchor" href="#memoryLimit" aria-hidden="true"></a></h3><p><code>memoryLimit</code> only limits operations that LiquidJS explicitly counts.</p>
|
|
<ul>
|
|
<li>Counted: memory-sensitive LiquidJS operations that call internal memory accounting.</li>
|
|
<li>Not guaranteed counted: arbitrary user object behavior such as custom <code>toValue()</code>/<code>toString()</code> chains, or other host-side code that allocates outside LiquidJS accounting points.</li>
|
|
</ul>
|
|
<p>In other words, <code>memoryLimit</code> limits what LiquidJS counts, not every byte your process may allocate.</p>
|
|
<p>Even with a small number of templates and iterations, memory usage can grow exponentially. In the following example, memory doubles with each iteration:</p>
|
|
<pre class="line-numbers language-liquid" data-language="liquid"><code class="language-liquid"><span class="token liquid language-liquid"><span class="token delimiter punctuation">{%</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">%}</span></span>
|
|
<span class="token liquid language-liquid"><span class="token delimiter punctuation">{%</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">%}</span></span>
|
|
<span class="token liquid language-liquid"><span class="token delimiter punctuation">{%</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">%}</span></span>
|
|
<span class="token liquid language-liquid"><span class="token delimiter punctuation">{%</span> <span class="token keyword">endfor</span> <span class="token delimiter punctuation">%}</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre>
|
|
|
|
<p>As <a target="_blank" rel="noopener external nofollow noreferrer" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_management">JavaScript uses GC to manage memory</a>, <code>memoryLimit</code> may not reflect the actual memory footprint.</p>
|
|
<h2 id="ownPropertyOnly-and-scope-data" class="article-heading"><a href="#ownPropertyOnly-and-scope-data" class="headerlink" title="ownPropertyOnly and scope data"></a><code>ownPropertyOnly</code> and scope data<a class="article-anchor" href="#ownPropertyOnly-and-scope-data" aria-hidden="true"></a></h2><p>With <a href="/api/interfaces/LiquidOptions.html#ownPropertyOnly"><code>ownPropertyOnly</code></a> <code>true</code>, plain scope objects only expose <strong>own</strong> properties (no inherited / <code>Object.prototype</code> keys). Default <code>false</code> follows normal JS property access. Use <code>true</code> for untrusted or polluted objects; add <a href="/api/interfaces/LiquidOptions.html#strictVariables"><code>strictVariables</code></a> if missing paths should error. Override per render via <a href="/api/interfaces/RenderOptions.html#ownPropertyOnly"><code>RenderOptions</code></a>. This is a read policy for scope data—not a sandbox for filters, tags, or your code.</p>
|
|
<h2 id="Custom-Drop-classes" class="article-heading"><a href="#Custom-Drop-classes" class="headerlink" title="Custom Drop classes"></a>Custom <code>Drop</code> classes<a class="article-anchor" href="#Custom-Drop-classes" aria-hidden="true"></a></h2><p><a href="/api/classes/Drop.html"><code>Drop</code></a> values are not restricted the same way: LiquidJS still reads the prototype chain and may call <a href="/api/classes/Drop.html#liquidMethodMissing"><code>liquidMethodMissing</code></a>. <strong>You</strong> control what a drop exposes; narrow APIs and never feed unsafe data into drops unless the class is built for template access. <code>ownPropertyOnly</code> alone does not harden custom drops—audit them like any privileged code.</p>
|
|
<h2 id="Online-service-guidance" class="article-heading"><a href="#Online-service-guidance" class="headerlink" title="Online service guidance"></a>Online service guidance<a class="article-anchor" href="#Online-service-guidance" aria-hidden="true"></a></h2><p>If you run an online service, avoid rendering fully user-defined templates whenever possible.</p>
|
|
<ul>
|
|
<li>Prefer curated templates or a restricted template subset.</li>
|
|
<li>If user-defined templates are required, isolate rendering (worker/process/container), enforce OS/container memory and CPU limits, and apply request rate limits.</li>
|
|
<li>Treat <code>parseLimit</code>/<code>renderLimit</code>/<code>memoryLimit</code> as one layer in a broader DoS defense strategy.</li>
|
|
</ul>
|
|
<p>For heavy single-template operations, process-level isolation is still recommended (for example with <a target="_blank" rel="noopener external nofollow noreferrer" href="https://www.npmjs.com/package/paralleljs">paralleljs</a>).</p>
|
|
|
|
</div>
|
|
<footer class="article-footer">
|
|
<time class="article-footer-updated" datetime="2026-06-21T18:25:09.638Z" itemprop="dateModified">Last updated: 2026-06-21</time>
|
|
<a href="truthy-and-falsy.html" class="article-footer-prev" title="Truthy and Falsy"><i class="icon-chevron-left"></i><span>Prev</span></a><a href="static-analysis.html" class="article-footer-next" title="Static Analysis"><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="#Security-boundary"><span class="toc-text">Security boundary</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Limits-at-a-glance"><span class="toc-text">Limits at a glance</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Limit-details"><span class="toc-text">Limit details</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#parseLimit"><span class="toc-text">parseLimit</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#renderLimit"><span class="toc-text">renderLimit</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#memoryLimit"><span class="toc-text">memoryLimit</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#ownPropertyOnly-and-scope-data"><span class="toc-text">ownPropertyOnly and scope data</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Custom-Drop-classes"><span class="toc-text">Custom Drop classes</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Online-service-guidance"><span class="toc-text">Online service guidance</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">
|
|
© 2026 <a href="https://github.com/harttle/liquidjs/graphs/contributors" rel="external nofollow noreferrer" target="_blank">Harttle</a><br>
|
|
Documentation licensed under <a href="https://creativecommons.org/licenses/by/4.0/" rel="external nofollow noreferrer" target="_blank">CC BY 4.0</a>.
|
|
</div>
|
|
<div id="footer-links">
|
|
<button type="button" class="footer-link cookie-preferences" data-cc="show-consentModal" title="Manage cookie preferences"><i class="icon-shield"></i></button>
|
|
<a href="https://twitter.com/harttleharttle" rel="external nofollow noreferrer" class="footer-link" target="_blank"><i class="icon-twitter"></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.html" class="mobile-nav-link">API</a>
|
|
</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="escaping.html" class="mobile-nav-link">Escaping</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">Parse Parameters</a><a href="render-tag-content.html" class="mobile-nav-link">Render Tag Content</a><a href="drops.html" class="mobile-nav-link">Liquid Drops</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><a href="security-model.html" class="mobile-nav-link current">Security Model</a><a href="static-analysis.html" class="mobile-nav-link">Static Analysis</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-button-list">
|
|
<a href="https://github.com/harttle/liquidjs" class="mobile-nav-link" rel="external" target="_blank"><i class="icon-github"></i></a>
|
|
<a href="https://opencollective.com/liquidjs" class="mobile-nav-link" rel="external" target="_blank"><i class="icon-opencollective"></i></a>
|
|
</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({
|
|
appId: 'QJ35YOZTU4',
|
|
apiKey: '8c6cbb824b4c5023f0bb2ef29e228bef',
|
|
indexName: 'liquidjs',
|
|
inputSelector: '#search-input',
|
|
debug: false
|
|
});
|
|
</script>
|
|
|
|
<script async src="https://www.googletagmanager.com/gtag/js?id=G-GM713991QQ"></script>
|
|
<script type="text/plain" data-category="analytics">
|
|
window.dataLayer = window.dataLayer || [];
|
|
function gtag(){dataLayer.push(arguments);}
|
|
gtag('js', new Date());
|
|
gtag('config', 'G-GM713991QQ');
|
|
</script>
|
|
</body>
|
|
</html> |