Skip to content

Instantly share code, notes, and snippets.

@reedspool
Created February 5, 2022 06:30
Show Gist options
  • Save reedspool/a0c9efaad855440d29e1ced4c841bbe7 to your computer and use it in GitHub Desktop.
Save reedspool/a0c9efaad855440d29e1ced4c841bbe7 to your computer and use it in GitHub Desktop.
/**
* Nunjucks template rendering hyperscript extension
*
* Adds command `render <expr> [with <namedArgumentList>] [into <expr>]`
*
* Expression may be an element or a pre-compiled nunjucks template (via `compile template`)
*
* ex:
* `<template id="tmpl-my-template">Hello, {{ hello }}</template>`
* `render #tmpl-my-template with (hello: 'world') into <body />`
*
* ex:
*
* `<template _="init precompile me into $myTemplate">Hello, {{ hello }}</template>`
* `render $myTemplate with (hello: 'world')`
* `put the result at the start of <body />`
*
* Adds command `precompile <expr> #tmpl-my-template [into $myTemplate]`
*
* @param {HyperscriptObject} _hyperscript
*/
const hyperscriptNunjucksExtension = _hyperscript => {
_hyperscript.addCommand("render", function(parser, runtime, tokens) {
if (!tokens.matchToken("render")) return;
var template_ = parser.requireElement("expression", tokens);
var templateArgs = {};
if (tokens.matchToken("with")) {
templateArgs = parser.parseElement("namedArgumentList", tokens);
}
if (tokens.matchToken("into")) {
var target_ = parser.requireElement("expression", tokens);
}
return {
args: [template_, templateArgs, target_],
op: function(ctx, template, templateArgs, target) {
if (template.__nunjucks_precompiled) {
ctx.result = template.render(templateArgs);
} else {
if (!(template instanceof Element)) throw new Error(template_.sourceFor() + " is not an element");
ctx.result = nunjucks.renderString(template.innerHTML, templateArgs);
}
if (target) {
if (Array.isArray(target)) target = target[0]
if (!(target instanceof Element)) throw new Error(target_.sourceFor() + " is not an element");
target.innerHTML = ctx.result;
}
return runtime.findNext(this, ctx);
},
};
});
_hyperscript.addCommand("precompile", function(parser, runtime, tokens) {
if (!tokens.matchToken("precompile")) return;
var template_ = parser.requireElement("expression", tokens);
if (tokens.matchToken("into")) {
var target = parser.requireElement("symbol", tokens);
}
return {
args: [template_],
op: function(ctx, template) {
if (!(template instanceof Element)) throw new Error(template_.sourceFor() + " is not an element");
ctx.result = nunjucks.compile(template.innerHTML);
ctx.result.__nunjucks_precompiled = true;
if (target) {
runtime.setSymbol(target.name, ctx, target.scope, ctx.result);
}
return runtime.findNext(this, ctx);
},
};
});
}
@tomberek
Copy link

tomberek commented Feb 5, 2022

Will one need to run processNode?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment