New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

wontache

Package Overview
Dependencies
Maintainers
1
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

wontache - npm Package Compare versions

Comparing version 0.1.0 to 0.2.0

wrap-module.js

69

module.js

@@ -8,3 +8,3 @@ import isFunction from 'underscore/modules/isFunction.js';

var BLOCK, CLOSE, COMMENT, DYNAMIC, INVERTED, PARENT, PARTIAL, SECTION, SET_DELIMITER, UNESCAPED, VARIABLE, addIndentation, areDefault, argumentList, concat, conditionalTag, correctStandalone, decompile, defaultDelimiters, detectClearance, escapeRegex, generateBlock, generateParent, _generateSection, initialIndent, interpolate, lineBreak, _mustache, newline, _parse, partial, payload, possiblyDynamic, pushNonEmptyLiteral, removeIndentation, renderInvertedSection, renderSection, renderSub, resolve, retokenize, section, sectionFunc, sectionList, sectionMismatch, spaces, specialChars, splitKey, strayEndingTag, stride, templateObject, tokenize, unclosedSection, variable;
var BLOCK, CLOSE, COMMENT, DYNAMIC, INVERTED, PARENT, PARTIAL, SECTION, SET_DELIMITER, UNESCAPED, VARIABLE, addIndentation, areDefault, argumentList, concat, conditionalTag, correctStandalone, decompile, defaultDelimiters, derefOp, detectClearance, escapeRegex, generateBlock, generateParent, _generateSection, initialIndent, interpolate, lineBreak, _mustache, newline, _parse, partial, payload, possiblyDynamic, pushNonEmptyLiteral, removeIndentation, renderInvertedSection, renderSection, renderSub, resolve, retokenize, section, sectionFunc, sectionList, sectionMismatch, spaces, specialChars, splitKey, strayEndingTag, stride, templateObject, tokenize, unclosedSection, variable;
defaultDelimiters = ['{{', '}}'];

@@ -277,3 +277,3 @@ newline = /\r?\n|\r/.source;

renderSection = function renderSection(state, key, func, delimiters) {
var context, filterText, frame, i, item, len, repeats, sectionText, value;
var context, frame, i, item, len, repeats, sectionText, value;
func = state.sections[func];

@@ -290,33 +290,34 @@

switch (false) {
case !!value:
return '';
if (!value) {
return '';
}
case !isFunction(value):
sectionText = func.sectionText != null ? func.sectionText : func.sectionText = decompile(state, func);
filterText = value.call(frame, sectionText);
if (isFunction(value)) {
sectionText = func.sectionText != null ? func.sectionText : func.sectionText = decompile(state, func);
value = value.call(frame, sectionText);
if (filterText === sectionText) {
return func(state);
} else {
return _mustache(filterText, delimiters)(null, state);
}
if (value === sectionText) {
return func(state);
}
default:
if (isString(value) || !isNumber(value.length)) {
value = [value];
}
if (isString(value)) {
return _mustache(value, delimiters)(null, state);
}
}
repeats = '';
context = state.context;
if (isString(value) || !isNumber(value.length)) {
value = [value];
}
for (i = 0, len = value.length; i < len; i++) {
item = value[i];
context.push(item);
repeats += func(state);
context.pop();
}
repeats = '';
context = state.context;
return repeats;
for (i = 0, len = value.length; i < len; i++) {
item = value[i];
context.push(item);
repeats += func(state);
context.pop();
}
return repeats;
}; // Render a `{{^section}}...{{/section}}` zero or one times.

@@ -528,5 +529,5 @@

clearLeft = leftTag.clearLeft;
isStandalone = +(clearLeft && clearRight);
start -= isStandalone;
end += isStandalone;
isStandalone = clearLeft && clearRight;
start -= +isStandalone;
end += +isStandalone;
return {

@@ -537,6 +538,8 @@ start: start,

};
}; // Mnemonic for the character that starts dynamic names.
}; // Mnemonic for the character that starts dynamic names, and a regular
// expression for taking it off, together with following whitespace.
DYNAMIC = '*'; // In partials and parents, the name may be prefixed with a star to indicate that
DYNAMIC = '*';
derefOp = /^\*\s*/; // In partials and parents, the name may be prefixed with a star to indicate that
// the name should be dynamically resolved from the context. In that case, the

@@ -548,3 +551,3 @@ // star is removed and the remainder of the name is split on the dots, like in

if (key[0] === DYNAMIC) {
return splitKey(key.slice(1));
return splitKey(key.replace(derefOp, ''));
} else {

@@ -837,3 +840,3 @@ return JSON.stringify(key);

if (sectionText) {
template.source = "mustache(".concat(templateObject(sectionText, delimiters), ")");
template.source = templateObject(sectionText, delimiters);
}

@@ -840,0 +843,0 @@

import { isString, isArray, isFunction, escape, isNumber, isObject } from 'underscore';
var BLOCK, CLOSE, COMMENT, DYNAMIC, INVERTED, PARENT, PARTIAL, SECTION, SET_DELIMITER, UNESCAPED, VARIABLE, addIndentation, areDefault, argumentList, concat, conditionalTag, correctStandalone, decompile, defaultDelimiters, detectClearance, escapeRegex, generateBlock, generateParent, _generateSection, initialIndent, interpolate, lineBreak, _mustache, newline, _parse, partial, payload, possiblyDynamic, pushNonEmptyLiteral, removeIndentation, renderInvertedSection, renderSection, renderSub, resolve, retokenize, section, sectionFunc, sectionList, sectionMismatch, spaces, specialChars, splitKey, strayEndingTag, stride, templateObject, tokenize, unclosedSection, variable;
var BLOCK, CLOSE, COMMENT, DYNAMIC, INVERTED, PARENT, PARTIAL, SECTION, SET_DELIMITER, UNESCAPED, VARIABLE, addIndentation, areDefault, argumentList, concat, conditionalTag, correctStandalone, decompile, defaultDelimiters, derefOp, detectClearance, escapeRegex, generateBlock, generateParent, _generateSection, initialIndent, interpolate, lineBreak, _mustache, newline, _parse, partial, payload, possiblyDynamic, pushNonEmptyLiteral, removeIndentation, renderInvertedSection, renderSection, renderSub, resolve, retokenize, section, sectionFunc, sectionList, sectionMismatch, spaces, specialChars, splitKey, strayEndingTag, stride, templateObject, tokenize, unclosedSection, variable;
defaultDelimiters = ['{{', '}}'];

@@ -271,3 +271,3 @@ newline = /\r?\n|\r/.source;

renderSection = function renderSection(state, key, func, delimiters) {
var context, filterText, frame, i, item, len, repeats, sectionText, value;
var context, frame, i, item, len, repeats, sectionText, value;
func = state.sections[func];

@@ -284,33 +284,34 @@

switch (false) {
case !!value:
return '';
if (!value) {
return '';
}
case !isFunction(value):
sectionText = func.sectionText != null ? func.sectionText : func.sectionText = decompile(state, func);
filterText = value.call(frame, sectionText);
if (isFunction(value)) {
sectionText = func.sectionText != null ? func.sectionText : func.sectionText = decompile(state, func);
value = value.call(frame, sectionText);
if (filterText === sectionText) {
return func(state);
} else {
return _mustache(filterText, delimiters)(null, state);
}
if (value === sectionText) {
return func(state);
}
default:
if (isString(value) || !isNumber(value.length)) {
value = [value];
}
if (isString(value)) {
return _mustache(value, delimiters)(null, state);
}
}
repeats = '';
context = state.context;
if (isString(value) || !isNumber(value.length)) {
value = [value];
}
for (i = 0, len = value.length; i < len; i++) {
item = value[i];
context.push(item);
repeats += func(state);
context.pop();
}
repeats = '';
context = state.context;
return repeats;
for (i = 0, len = value.length; i < len; i++) {
item = value[i];
context.push(item);
repeats += func(state);
context.pop();
}
return repeats;
}; // Render a `{{^section}}...{{/section}}` zero or one times.

@@ -522,5 +523,5 @@

clearLeft = leftTag.clearLeft;
isStandalone = +(clearLeft && clearRight);
start -= isStandalone;
end += isStandalone;
isStandalone = clearLeft && clearRight;
start -= +isStandalone;
end += +isStandalone;
return {

@@ -531,6 +532,8 @@ start: start,

};
}; // Mnemonic for the character that starts dynamic names.
}; // Mnemonic for the character that starts dynamic names, and a regular
// expression for taking it off, together with following whitespace.
DYNAMIC = '*'; // In partials and parents, the name may be prefixed with a star to indicate that
DYNAMIC = '*';
derefOp = /^\*\s*/; // In partials and parents, the name may be prefixed with a star to indicate that
// the name should be dynamically resolved from the context. In that case, the

@@ -542,3 +545,3 @@ // star is removed and the remainder of the name is split on the dots, like in

if (key[0] === DYNAMIC) {
return splitKey(key.slice(1));
return splitKey(key.replace(derefOp, ''));
} else {

@@ -831,3 +834,3 @@ return JSON.stringify(key);

if (sectionText) {
template.source = "mustache(".concat(templateObject(sectionText, delimiters), ")");
template.source = templateObject(sectionText, delimiters);
}

@@ -834,0 +837,0 @@

@@ -7,3 +7,3 @@ (function (global, factory) {

var BLOCK, CLOSE, COMMENT, DYNAMIC, INVERTED, PARENT, PARTIAL, SECTION, SET_DELIMITER, UNESCAPED, VARIABLE, addIndentation, areDefault, argumentList, concat, conditionalTag, correctStandalone, decompile, defaultDelimiters, detectClearance, escapeRegex, generateBlock, generateParent, _generateSection, initialIndent, interpolate, lineBreak, _mustache, newline, _parse, partial, payload, possiblyDynamic, pushNonEmptyLiteral, removeIndentation, renderInvertedSection, renderSection, renderSub, resolve, retokenize, section, sectionFunc, sectionList, sectionMismatch, spaces, specialChars, splitKey, strayEndingTag, stride, templateObject, tokenize, unclosedSection, variable;
var BLOCK, CLOSE, COMMENT, DYNAMIC, INVERTED, PARENT, PARTIAL, SECTION, SET_DELIMITER, UNESCAPED, VARIABLE, addIndentation, areDefault, argumentList, concat, conditionalTag, correctStandalone, decompile, defaultDelimiters, derefOp, detectClearance, escapeRegex, generateBlock, generateParent, _generateSection, initialIndent, interpolate, lineBreak, _mustache, newline, _parse, partial, payload, possiblyDynamic, pushNonEmptyLiteral, removeIndentation, renderInvertedSection, renderSection, renderSub, resolve, retokenize, section, sectionFunc, sectionList, sectionMismatch, spaces, specialChars, splitKey, strayEndingTag, stride, templateObject, tokenize, unclosedSection, variable;
defaultDelimiters = ['{{', '}}'];

@@ -276,3 +276,3 @@ newline = /\r?\n|\r/.source;

renderSection = function renderSection(state, key, func, delimiters) {
var context, filterText, frame, i, item, len, repeats, sectionText, value;
var context, frame, i, item, len, repeats, sectionText, value;
func = state.sections[func];

@@ -289,33 +289,34 @@

switch (false) {
case !!value:
return '';
if (!value) {
return '';
}
case !underscoreX_js.isFunction(value):
sectionText = func.sectionText != null ? func.sectionText : func.sectionText = decompile(state, func);
filterText = value.call(frame, sectionText);
if (underscoreX_js.isFunction(value)) {
sectionText = func.sectionText != null ? func.sectionText : func.sectionText = decompile(state, func);
value = value.call(frame, sectionText);
if (filterText === sectionText) {
return func(state);
} else {
return _mustache(filterText, delimiters)(null, state);
}
if (value === sectionText) {
return func(state);
}
default:
if (underscoreX_js.isString(value) || !underscoreX_js.isNumber(value.length)) {
value = [value];
}
if (underscoreX_js.isString(value)) {
return _mustache(value, delimiters)(null, state);
}
}
repeats = '';
context = state.context;
if (underscoreX_js.isString(value) || !underscoreX_js.isNumber(value.length)) {
value = [value];
}
for (i = 0, len = value.length; i < len; i++) {
item = value[i];
context.push(item);
repeats += func(state);
context.pop();
}
repeats = '';
context = state.context;
return repeats;
for (i = 0, len = value.length; i < len; i++) {
item = value[i];
context.push(item);
repeats += func(state);
context.pop();
}
return repeats;
}; // Render a `{{^section}}...{{/section}}` zero or one times.

@@ -527,5 +528,5 @@

clearLeft = leftTag.clearLeft;
isStandalone = +(clearLeft && clearRight);
start -= isStandalone;
end += isStandalone;
isStandalone = clearLeft && clearRight;
start -= +isStandalone;
end += +isStandalone;
return {

@@ -536,6 +537,8 @@ start: start,

};
}; // Mnemonic for the character that starts dynamic names.
}; // Mnemonic for the character that starts dynamic names, and a regular
// expression for taking it off, together with following whitespace.
DYNAMIC = '*'; // In partials and parents, the name may be prefixed with a star to indicate that
DYNAMIC = '*';
derefOp = /^\*\s*/; // In partials and parents, the name may be prefixed with a star to indicate that
// the name should be dynamically resolved from the context. In that case, the

@@ -547,3 +550,3 @@ // star is removed and the remainder of the name is split on the dots, like in

if (key[0] === DYNAMIC) {
return splitKey(key.slice(1));
return splitKey(key.replace(derefOp, ''));
} else {

@@ -836,3 +839,3 @@ return JSON.stringify(key);

if (sectionText) {
template.source = "mustache(".concat(templateObject(sectionText, delimiters), ")");
template.source = templateObject(sectionText, delimiters);
}

@@ -839,0 +842,0 @@

{
"name": "wontache",
"version": "0.1.0",
"version": "0.2.0",
"description": "Compact, spec-compliant Mustache implementation with extras",

@@ -27,3 +27,2 @@ "keywords": [

"module": "module.js",
"type": "commonjs",
"exports": {

@@ -40,3 +39,4 @@ ".": {

"./customUnderscore/*": "./customUnderscore/*",
"./package.json": "./package.json"
"./package.json": "./package.json",
"./wrap-module": "./wrap-module.js"
},

@@ -52,3 +52,5 @@ "files": [

"mustache-umd.js",
"mustache-umd.js.map"
"mustache-umd.js.map",
"wrap-module.js",
"wrap-module.js.map"
],

@@ -62,7 +64,7 @@ "scripts": {

"dependencies": {
"underscore": "^1.13.0-2"
"underscore": "^1.13.6"
},
"devDependencies": {
"@babel/core": "^7.13.8",
"@babel/preset-env": "^7.13.9",
"@babel/core": "^7.16.7",
"@babel/preset-env": "^7.13.12",
"@rollup/plugin-alias": "^3.1.2",

@@ -74,5 +76,6 @@ "@rollup/plugin-babel": "^5.3.0",

"coffeescript": "^2.6.1",
"mocha": "^9.1.3",
"rollup": "^2.39.1",
"mocha": "^9.2.2",
"rollup": "^2.42.1",
"rollup-plugin-coffee-script": "^2.0.0",
"wontache-devtools-rollup": "0",
"wontache-devtools-runcoffee": "0",

@@ -79,0 +82,0 @@ "yaml": "^1.10.0"

@@ -16,3 +16,3 @@ [![latest version on npm][shield-npm]][npm] [![author: Julian Gonggrijp][shield-jgonggrijp]][jgonggrijp] [![license text][shield-license]][license] [![code hosted on GitLab][shield-gitlab]][repo] [![changelog][shield-versions]][versions] [![issue tracker on GitLab][shield-issues]][tracker] [![pipeline status][shield-pipeline]][build]

Wontache is a fast, precompiling implementation of the [Mustache][mustache] templating language for JavaScript, written in just [a few hundred lines of literate CoffeeScript][source]. It fully implements version 1.2.2 of the [Mustache specification][spec], including the lambda and inheritance extensions, as well as some extra features which are listed further down below. An up-to-date reference of the Mustache templating language is available [over here][manpage].
Wontache is a fast, precompiling implementation of the [Mustache][mustache] templating language for JavaScript, written in just [a few hundred lines of literate CoffeeScript][source]. It fully implements version 1.3.0 of the [Mustache specification][spec], including the optional modules, as well as some extra features which are listed further down below. An up-to-date reference of the Mustache templating language is available [over here][manpage]. You can try out the Wontache engine in its full glory, right from your browser, in the [playground][playground].

@@ -32,2 +32,3 @@ Compared to:

[manpage]: https://jgonggrijp.gitlab.io/wontache/mustache.5.html
[playground]: https://jgonggrijp.gitlab.io/wontache/playground.html
[handlebars]: https://www.npmjs.com/package/handlebars

@@ -38,24 +39,19 @@ [mustache-js]: https://www.npmjs.com/package/mustache

- [Quickstart](#quickstart)
- [Development status](#development-status)
- [Extras](#extras)
- [Companion libraries and tools](#companion-libraries-and-tools)
- [Build variants](#build-variants)
- [Underscore dependency](#underscore-dependency)
- [Manual](#manual)
- [Compilation](#compilation)
- [Rendering](#rendering)
- [Partials](#partials)
- [Changing the delimiters](#changing-the-delimiters)
- [Precompilation](#precompilation)
- [`wrapModule`](#wrapmodule)
- [Decompilation](#decompilation)
- [Credits](#credits)
## Development status
The 0.x release series is intended for evaluation. Wontache already completely implements the latest Mustache specification and is fully tested. Templates that compile in Wontache 0.x are expected to also compile in the 1.x release series and should mostly produce the same output. However, the interface has not fully stabilized yet. Among other things, this means that you might need to recompile your templates when Wontache is updated.
Most of the current development work is focused on adding production-friendly conveniences, such as TypeScript and Flow type declarations, a command line tool and integrations for various code bundling tools. More extensive documentation is planned as well. You can track progress towards the official launch [over here][milestone].
[milestone]: https://gitlab.com/jgonggrijp/wontache/-/milestones/2
## Extras
- Intelligently handles block indentation in the context of inheritance, in accordance with a [proposed extension][block-reindent-spec] by the author.
- *new in version 0.1.0* Implements [dynamic names][dynamic-name-spec] in partials and parents, allowing you to write `{{>*name}}` to mean that `name` should be looked up in the context to find the actual name of the partial that should be interpolated. `name` may also be a dotted name or the implicit iterator `.`.
You can track planned extras [over here][extras].
[block-reindent-spec]: https://github.com/mustache/spec/pull/131
[dynamic-name-spec]: https://github.com/mustache/spec/pull/134
[extras]: https://gitlab.com/jgonggrijp/wontache/-/issues?label_name%5B%5D=enhancement
## Quickstart

@@ -76,6 +72,2 @@

const templateFunction = mustache(template);
console.log(templateFunction.source);
// mustache({sections: [function(state){...}, ...]})
// (useful for bundling templates with JavaScript)
const output = templateFunction(data);

@@ -90,2 +82,38 @@ // Hello Alice!

## Development status
The 0.x release series is intended for evaluation. Wontache already completely implements the latest Mustache [specification][spec] and is fully [tested][build]. Templates that compile in Wontache 0.x are expected to also compile in the 1.x release series and should mostly produce the same output. However, the interface has not fully stabilized yet. Among other things, this means that you might need to recompile your templates when Wontache is updated.
Most of the current development work is focused on adding production-friendly conveniences, such as TypeScript and Flow type declarations, a command line tool and integrations for various code bundling tools. More extensive documentation is planned as well. You can track progress towards the official launch [over here][milestone].
[milestone]: https://gitlab.com/jgonggrijp/wontache/-/milestones/2
## Extras
- Intelligently handles [block][block] indentation in the context of [inheritance][inheritance-spec], in accordance with a [proposed extension][block-reindent-spec] by the author.
- *new in version 0.1.0 (integrated in version 1.3.0 of the spec)* Implements [dynamic names][dynamic-name-spec] in [partials][partial] and [parents][parent], allowing you to write `{{>*name}}` to mean that `name` should be looked up in the context to find the actual name of the partial that should be interpolated. `name` may also be a dotted name or the implicit iterator `.`.
You can track planned extras [over here][extras].
[block]: https://jgonggrijp.gitlab.io/wontache/mustache.5.html#Blocks
[partial]: https://jgonggrijp.gitlab.io/wontache/mustache.5.html#Partials
[parent]: https://jgonggrijp.gitlab.io/wontache/mustache.5.html#Parents
[inheritance-spec]: https://github.com/mustache/spec/blob/v1.2.2/specs/%7Einheritance.yml
[block-reindent-spec]: https://github.com/mustache/spec/pull/131
[dynamic-name-spec]: https://github.com/mustache/spec/pull/134
[extras]: https://gitlab.com/jgonggrijp/wontache/-/issues?label_name%5B%5D=enhancement
## Companion libraries and tools
- [`rollup-plugin-wontache`][plugin-rollup] lets you bundle Mustache template files with your JavaScript code using Rollup.
- [`wontache-loader`][plugin-webpack] lets you bundle Mustache template files with your JavaScript code using webpack.
Integrations for more bundling and task automation tools are planned, as well as other companion libraries and tools.
[plugin-rollup]: https://jgonggrijp.gitlab.io/wontache/plugin-rollup.html
[plugin-webpack]: https://jgonggrijp.gitlab.io/wontache/plugin-webpack.html
## Build variants

@@ -124,6 +152,20 @@

var compiled = mustache('template with {{variable}}');
var template = 'template with {{variable}}';
var compiled = mustache(template);
```
The [Rollup plugin][plugin-rollup] and the [webpack loader][plugin-webpack] will generate the above code automatically and wrap it in a module, so you can import the compiled template directly from a standalone template file:
```mustache
{{! template.mustache }}
template with {{variable}}
```
```js
import compiled from './template.mustache';
```
### Rendering

@@ -140,20 +182,56 @@

### Precompilation
### Partials
The compiled template has a `source` property with a string representation of its source code. This can be used for ahead-of-time compilation, enabling you to compile each template once at build time and then (for example) send it to a browser where it will be executed many times.
The [Partial][partial] and [Parent][parent] tags let you render and interpolate a template inside another template. If your templates contain either of those tags, you have to do some administration so that compiled templates are able to find each other by name. This administration takes the form of an object, where each key is the name of a template that may be embedded. The corresponding value may be either a template string or a template function (if you set a template string, it will be compiled on first use).
```js
compiled.source;
// mustache(function(state) {
// return "template with " + state.v(["variable"]);
// })
// (The above source has been simplified for illustration.)
// The administration.
var namedTemplates = {
link: '<a href="{{&url}}">{{title}}</a>'
};
// A template that will need the above administration.
var template = '<ul>{{#.}}<li>{{>link}}{{/.}}</ul>';
var linkList = mustache(template);
// The data.
var links = [{
url: 'https://jgonggrijp.gitlab.io/wontache/',
title: 'Wontache home page'
}];
```
Keep in mind that the precompiled template code is larger than the original template text. You save startup time at the receiving end, at the expense of transferring more data.
There are two possible ways to make the partial administration available to a template function. The most *hygienic* way is to pass an object with a `partials` property as the second argument in the call to the template. This approach is **strongly recommended** for library authors, because it ensures that the partials provided to your template are completely isolated from the partials that other libraries or the application may be using.
The compiled template needs to have access to `mustache` at runtime. There are two main reasons for this: firstly, `mustache` provides runtime support functions, and secondly, some features of the Mustache template language require runtime recompilation of templates. If you are precompiling templates for later execution in a separate JavaScript session, make sure to import `mustache` in the module that contains your precompiled template.
```js
linkList(links, {partials: namedTemplates});
// '<ul><li><a href="https://jgonggrijp.gitlab.io/wontache/">Wontache home page</a></ul>'
```
If desired, you can write a wrapper function that always passes the same partial administration to a given template function.
```js
function render(templateFunc, data) {
return templateFunc(data, {partials: namedTemplates});
}
render(linkList, links);
// Same output as above ('<ul><li><a href="...</a></ul>').
```
The most *convenient* way is to assign your administration to `mustache.partials`. Template functions automatically fall back to this if you don't pass a set of partials explicitly, so it can be "set and forget". This approach is intended for application authors. When using it, do keep in mind that `mustache.partials` is easy to compromise, by overwriting either one of its keys or the property as a whole. In principle, a sloppy library author could do this as well. You may even want to dedicate a test to ensuring that `mustache.partials` is complete.
```js
Object.assign(mustache.partials, namedTemplates);
// Could also use Underscore's _.extend for compatibility.
linkList(links);
// Same output again ('<ul><li><a href="...</a></ul>').
```
### Changing the delimiters

@@ -199,56 +277,45 @@

### Partials
### Precompilation
The [Partial][partial] and [Parent][parent] tags let you render and interpolate a template inside another template. If your templates contain either of those tags, you have to do some administration so that compiled templates are able to find each other by name. This administration takes the form of an object, where each key is the name of a template that may be embedded. The corresponding value may be either a template string or a template function (if you set a template string, it will be compiled on first use).
Template [compilation](#compilation) is a costly operation. Precompilation is an **optimization** that lets you do the compilation ahead of time.
```js
A common situation where you might want to use precompilation, is in a client side web application. The application will respond faster if it does not need to compile its templates before [rendering](#rendering) them. Precompilation lets you do the compilation already before the application code is sent to the client, for example in a serverside process that bundles the code.
// The administration.
var namedTemplates = {
link: '<a href="{{&url}}">{{title}}</a>'
};
Keep in mind that the precompiled template code is larger than the original template text. You save startup time at the receiving end, at the expense of transferring more data.
// A template that will need the above administration.
var template = '<ul>{{#.}}<li>{{>link}}{{/.}}</ul>';
var linkList = mustache(template);
The easiest way to use precompilation, is to set `precompile: true` when using the [Rollup plugin][plugin-rollup] or the [webpack loader][plugin-webpack]. However, you can also tap directly in the underlying mechanisms if you need a custom solution.
// The data.
var links = [{
url: 'https://jgonggrijp.gitlab.io/wontache/',
title: 'Wontache home page'
}];
As described [above](#compilation), when you compile a template the "regular" way, you obtain a function that will render the template. This function has a `source` property, which is a string that encodes a JavaScript object. That object contains the end result of compilation. It can be passed to `mustache` instead of the original template text, in order to recreate the compiled template function. In other words, if you build a string `precompiled` as follows,
```js
var precompiled = "import mustache from 'wontache';\n" +
"export default mustache(" + compiled.source + ");";
```
[partial]: https://jgonggrijp.gitlab.io/wontache/mustache.5.html#Partials
[parent]: https://jgonggrijp.gitlab.io/wontache/mustache.5.html#Parents
and you write `precompiled` to a file, you have created a new JavaScript module that exports `compiled`. No compilation needs to be done in that module; all that work was already done when you created `compiled` the first time, before writing the module code to disk.
There are two possible ways to make the partial administration available to a template function. The most *hygienic* way is to pass an object with a `partials` property as the second argument in the call to the template. This approach is **strongly recommended** for library authors, because it ensures that the partials provided to your template are completely isolated from the partials that other libraries or the application may be using.
`compiled.source` does not include the outer `mustache()` function call in order to give you freedom. For example, you could name the `mustache` import differently, or you could write JavaScript code that has the precompiled objects in an array rather than passing them directly to `mustache`.
```js
If writing JavaScript modules is exactly what you want to do, however, you do not need to build the strings yourself. Instead, you can use [`wrapModule`](#wrapmodule), as described in the following section.
linkList(links, {partials: namedTemplates});
// '<ul><li><a href="https://jgonggrijp.gitlab.io/wontache/">Wontache home page</a></ul>'
```
If desired, you can write a wrapper function that always passes the same partial administration to a given template function.
### wrapModule
```js
The [Rollup plugin][plugin-rollup] and integrations for other build tools all do roughly the same thing: take a Mustache template and wrap it as a JavaScript module. The common logic is contained in the `wrapModule` function, which is the default and only export of the auxiliary module `wontache/wrap-module`.
function render(templateFunc, data) {
return templateFunc(data, {partials: namedTemplates});
}
`wrapModule` takes the raw template string as the first argument and an object with options as an optional second argument. It returns a string with the JavaScript module code. The following options are available.
render(linkList, links);
// Same output as above ('<ul><li><a href="...</a></ul>').
```
- `precompile`: boolean to indicate whether you want to use [precompilation](#precompilation), default `false`.
- `type`: string naming the module type, either `'ESM'` (default), `'AMD'` or `'CommonJS'`.
- `delimiters`: the [delimiters](#changing-the-delimiters) that the compiler should start parsing with, default `['{{', '}}']`.
- `wontache`: the name used for the default import from Wontache, default `'mustache'`.
The most *convenient* way is to assign your administration to `mustache.partials`. Template functions automatically fall back to this if you don't pass a set of partials explicitly, so it can be "set and forget". This approach is intended for application authors. When using it, do keep in mind that `mustache.partials` is easy to compromise, by overwriting either one of its keys or the property as a whole. In principle, a sloppy library author could do this as well. You may even want to dedicate a test to ensuring that `mustache.partials` is complete.
```js
Object.assign(mustache.partials, namedTemplates);
// Could also use Underscore's _.extend for compatibility.
import wrapModule from 'wontache/wrap-module';
linkList(links);
// Same output again ('<ul><li><a href="...</a></ul>').
const wrappedModule = wrapModule(template, {precompile: true});
// import mustache from 'wontache';
// export default mustache(...);
```

@@ -259,3 +326,3 @@

Since templates sometimes need to be recompiled, there is a "backdoor" of sorts to reconstruct the original template text from the compiled function. While this is mostly an implementation detail, it might occasionally be useful for debugging purposes.
Since templates sometimes need to be recompiled, there is a "backdoor" of sorts to reconstruct the original template text from the [compiled](#compilation) function. While this is mostly an implementation detail, it might occasionally be useful for debugging purposes.

@@ -262,0 +329,0 @@ ```js

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc