Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@rhinostone/swig

Package Overview
Dependencies
Maintainers
1
Versions
23
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@rhinostone/swig

A simple, powerful, and extendable templating engine for node.js and browsers, similar to Django, Jinja2, and Twig.

latest
Source
npmnpm
Version
2.4.3
Version published
Weekly downloads
789
-29.49%
Maintainers
1
Weekly downloads
 
Created
Source

Swig

CI NPM version NPM Downloads Socket Badge

Multi-flavor template engine for Node.js and browsers — native Swig syntax (Jinja2/Django-inspired) and Twig syntax via dedicated frontends sharing one IR backend. gina-io/swig started as a maintained continuation of the abandoned paularmstrong/swig (last released 2014) and is now a standalone project. Security and bug fixes ship here.

Part of the Gina ecosystem. This is the built-in template engine for Gina (npm), a Node.js MVC framework with HTTP/2, multi-bundle architecture, and scope-based data isolation.

Swig is a Jinja2/Django-inspired template engine for node.js and browsers. The syntax will feel familiar to Jinja2 and Django users, but Swig is not drop-in compatible with either — porting templates from an existing project requires a handful of changes. See the Migration Guide for the full parity list and workaround patterns.

Coming from Twig? Install @rhinostone/swig-twig instead — a dedicated Twig-syntax frontend with closer parity than working around incompatibilities here.

Workspace packages

PackageDescriptionWhen to use
@rhinostone/swigNative Swig syntax (Jinja2/Django-inspired). Drop-in for @rhinostone/swig@1.x consumers.Upgrading from @rhinostone/swig@1.x, or starting fresh with Swig syntax.
@rhinostone/swig-twigTwig-syntax frontend with closer Twig parity.Migrating from PHP Twig, or writing new templates in Twig syntax.
@rhinostone/swig-coreShared IR, backend, and runtime primitives.Building a custom flavor frontend. Otherwise pulled in transitively.

Each frontend pins the matching @rhinostone/swig-core version exactly during the alpha cycle — the IR is not stable across alpha minors. From 2.0.0 stable onward, frontends and the core release in lockstep.

Features

  • Available for node.js and major web browsers.
  • Express compatible.
  • Object-Oriented template inheritance.
  • Apply filters and transformations to output in your templates.
  • Hardened against prototype-pollution__proto__ / constructor / prototype blocked at parser, tag-side, and IR-emission layers. CVE-2023-25345 fully patched. 9 regression cases under tests/regressions.test.js.
  • Automatically escapes all variable output (HTML by default; configurable per-call).
  • Lots of iteration and conditionals supported.
  • Robust without the bloat.
  • Extendable and customizable — register custom filters, tags, and loaders per-instance.

Benchmarks

benchmarks/render.js measures sync-render throughput across five workload shapes against Nunjucks.

cd benchmarks && npm install && node render.js

In production-typical settings (autoescape on), @rhinostone/swig outperforms Nunjucks on iteration-heavy templates by 2–3.5× and ties on simple control flow. See benchmarks/README.md for the methodology, the full result table, and how to reproduce on your own hardware.

Need Help? Have Questions? Comments?

  • File an issue at gina-io/swig/issues.
  • Swig v0.x → v1.x migration notes — the original upstream wiki has been deleted; see HISTORY.md entries around v1.0.0 for the individual breaking changes. For porting from Jinja2 or Django into Swig, see the Migration Guide.

Installation

npm install @rhinostone/swig

For Twig syntax:

npm install @rhinostone/swig-twig

Documentation

User-facing documentation lives in the Gina Docusaurus site under the Swig Template Engine section, maintained in gina-io/docs at docs/swig/. The JSDoc blocks in lib/swig.js, lib/filters.js, lib/tags/, and lib/loaders/ remain the canonical source-of-truth for the public API and are mirrored into the Docusaurus pages.

Basic Example

Template code

<h1>{{ pagename|title }}</h1>
<ul>
{% for author in authors %}
    <li{% if loop.first %} class="first"{% endif %}>{{ author }}</li>
{% endfor %}
</ul>

node.js code

var swig  = require('@rhinostone/swig');
var template = swig.compileFile('/absolute/path/to/template.html');
var output = template({
    pagename: 'awesome people',
    authors: ['Paul', 'Jim', 'Jane']
});

Output

<h1>Awesome People</h1>
<ul>
    <li class="first">Paul</li>
    <li>Jim</li>
    <li>Jane</li>
</ul>

For working example see examples/basic.

Migrating from @rhinostone/swig@1.x

@rhinostone/swig@2.x is drop-in for 1.x consumersswig.compileFile, swig.renderFile, swig.setFilter, swig.setTag, and the rest of the public API are unchanged. The internal carve into @rhinostone/swig-core is transparent (test gate during the alpha cycle: byte-identical compiled output against the 1.x test suite).

2.0.0 also ships @rhinostone/swig-twig, a sibling Twig-syntax frontend. Switching is opt-in — your existing @rhinostone/swig install keeps working.

Migrating from Jinja2 or Django

Swig is inspired by Jinja2 and Django, not a drop-in replacement. Common pitfalls when porting existing templates:

  • No is / is not / not in operators — rewrite {% if x is defined %} as {% if x !== undefined %}, {% if x not in xs %} as {% if not (x in xs) %}.
  • Django forloop.counter → Swig loop.index (Swig follows Jinja2 loop-variable naming).
  • {{ super() }} / {{ block.super }}{% parent %} — Swig uses a dedicated tag inside the overriding block.
  • Django filter args use a colon (|date:"Y-m-d") — Swig uses parens (|date("Y-m-d")).
  • {% with x=1 %}{% set x = 1 %}, and no block-form {% set %}…{% endset %}.
  • No {% from "f" import x %} — use {% import "f" as ns %} + ns.x instead.
  • Method calls require parens — Django auto-invokes x.get_absolute_url; Swig needs x.get_absolute_url().
  • ~25 Jinja2 filters are absentdefault, truncate, tojson, round, int, float, map, select, batch, trim, etc. Register them via swig.setFilter(name, fn).

Full parity tables and workaround patterns: Migration Guide.

How it works

Swig reads template files and translates them into cached JavaScript functions. The pipeline is: parse → emit IR → lower IR to JS source → new Function(...). At render time, the compiled function runs against a context object to produce the output string.

In 2.x, frontend parsers (native Swig syntax in @rhinostone/swig, Twig syntax in @rhinostone/swig-twig) emit a shared intermediate representation. The backend in @rhinostone/swig-core lowers IR to JS. New flavors plug in at the frontend without touching the runtime.

License

MIT. Copyright (c) 2010-2016 Paul Armstrong and contributors, (c) 2026 Rhinostone. See LICENSE for the full text and AUTHORS for the contributor roster.

Keywords

template

FAQs

Package last updated on 22 May 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts