Skip to content
Switch branches/tags

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time


StencilJS is a Stencil extension that allows to extend Stencil template engine with custom filters and tags written in JavaScript.

This framework is intended to be used by developers of tools/apps who wants to provide their users an option to write their own tags and filters. It does not provide (at least at this point) any tools to discover such scripts and load them.


Link StencilJS module to your target, either using SPM, Carthage or CocoaPods.

Then add JSExtension to your Stencil Environment:

let ext = JSExtension()
let env = Environment(extensions: [ext])

JSExtension provides additional methods to register filters and tags using JavaScript code which are similar to the methods to add filters and tags written in Swift:

func registerFilter(_ name: String, script code: String) func registerSimpleTag(_ name: String, script code: String) func registerTag(_ name: String, script code: String)

By default each of these methods uses JSContext instance from jsContext property of JSExtension. This way all of your JavaScript code will be executed in the same context. Alternatively you can pass these methods arbitrary JSContext instance to make them run the code in isolation.

Writing filters and tags in JavaScript

Each filter or tag should be defined as a function with the same name that you use to register it for.

Filters should accept two parameters - value and params and can return transformed value.

// template:
{{ name|uppercase }}

// code:
function uppercase(value, params) { 
	return value.toUpperCase() 
// template:
{{ tags|join:', '}}

// code:
function join(value, params) { 
	return value.join(params[0]) 

Simple tags are tags that can be processed without additional parsing. They accept context as a parameter and should return string.

// template:
{% hello %}

// code:
function hello(context) { 
	return \"Hello, \" + context.valueForKey('name') 

Tags should accept two parameters - parser and token and should define render function that accepts context.

function tag(parser, token) {
	// use parser to parse token
	this.render = function(contet) {
		// use parsed token to render data from context

You can check tests or Stencil source code for more detailed examples of tags.

In JavaScript you can use all the same methods of TokenParser and Token, you can subscript context by key and you can push new level onto the context.

TokenParser methods:

  • func parse() -> [NodeType] - parse the given tokens into nodes

  • func parse_until(_ tags: [String]?) -> [NodeType] - parse the given tokens into nodes until it finds one of specified tags

  • func nextToken() -> Token? - returns next token without actually parsing it

  • func compileFilter(_ token: String) -> Resolvable! - parses all filters in the token

Token methods:

  • func components() -> [String] - returns the underlying value as an array seperated by spaces

  • var contents: String { get } - returns the underlying value

Context methods:

  • func value(forKey key: String) -> Any? - returns the value in the context identified by a given key. Usage: context.valueForKey('name')

  • func setValue(_ value: Any?, forKey key: String) - sets the value in the context identified by a given key. Usage: context.setValueForKey('value', 'key')

  • func push(_ closure: JSValue) -> Any - pushed new level onto the context. Usage: push(function() { ... })

  • func push(_ dictionary: [String : Any], _ closure: JSValue) -> Any - pushed new level onto the context with provided values. Usage: push({'key': 'value'}, function() { ... })

Variable methods:

  • init(_ variable: String) - creates variable with a name. Usage: new Variable('var')

  • func resolve(_ context: Context) -> Any? - resolves the value of variable or filter expression

VariableNode methods:

  • init?(_ variable: JSValue) - creates variable node with a string or Resolvable object. Usage: new VariableNode('var') or `new VariableNode(Variable('var'))

  • func render(_ context: Context) throws -> String - renders the node by resolving corresponding variable

Free functions:

  • func renderNodes([NodeType], Context) -> String - free function to render array of nodes in a context


Stencil is licensed under the BSD license. See LICENSE for more info.


JavaScriptCore extension for Stencil







No packages published