Node template engine that can include other templates? - node.js

Starting to get into node but struggling to pick a template engine..
Is there an engine out there that can include other templates in the same twig can?
EG:
{% include 'template.html' with {'foo': 'bar'} %}

I recommend a new template engine: Saker, it enables fluid coding workflow, unlike most template syntaxes, you do not need to interrupt your coding to explicitly denote server blocks within your HTML.
Saker is my personal open source project.
Github: https://github.com/eshengsky/saker

I went with this in the end:
http://paularmstrong.github.io/swig/
I is a port of twig to js.. absolutely awesome and does exactly what you would expect from a twig.
UPDATE: It swig ha since been deprecated in favor of:
https://mozilla.github.io/nunjucks/

Related

Inject meta tag dynamically to HTML with Express

Summary:
I'm currently migrating a website on Apache + PHP stack over to Node + Express, and would like to know what is the best way/best practice (if there is one) for dynamically injecting meta tags under the new stack.
Details:
Under the existing stack, meta tags are injected dynamically by adding PHP codes into the HTML file directly. As rendering is done on server side, the tags are properly interpreted by Facebook/Google+/whatever web crawlers.
Under the new stack, after doing some research, I've come across two options:
Use template engine like Pug (Jade) to render the HTML with locals. (It seems to be an overkill to rewrite the existing HTML with Pug's syntax though? Can Pug deal with HTML, or I've to consider other template engine like EJS? What template engine do you advise me to explore?)
Use DOM manipulation plugin like Cheerio to inject the meta tags first, before rendering begins.
Between these two options, which one will have a better performance or there is no material difference? Are there any other ways that you'd otherwise recommend? Thanks!
EJS would probably be the simplest one for that and very similar to PHP.
You can also take a look at Mustache and Handlebars for other options with minimal changes to your existing HTML.
with EJS: <html><head><%= yourMetaTags %> ...
with Mustache: <html><head>{{ yourMetaTags }} ...
with Handlebars: <html><head>{{ yourMetaTags }} ...
Also doT.js is very fast.
See:
http://www.embeddedjs.com/
https://mustache.github.io/
http://handlebarsjs.com/
http://olado.github.io/doT/
Parsing the HTML and manipulating it with a DOM API just to insert meta tags would be an overkill in my opinion.
On the other hand if all you need is to insert meta tags then you could make a simple regex substitution, using something like yourHTML.replace('<head>', '<head>'+yourMetaTags); but it could potentially get more complex over time when you need more functionality. After all, everyone has made a templating engine at some point in life.

Wrap contextual html around a specific twig variable {{ product.name }}

I want to automatically wrap some html, lets say <span data-id=".."> when I call {{ product.name }} in my twig template.
So when in a twig template, I use {{ product.name }}, I want the output to be: <span data-type="product" data-id="8" data-prop="name">My product name</span>. I cannot use twig filters or macros, since I really need the template syntax to be {{ product.name }}, so the end-user (template designer), does not have to care about it.
The reason I need this is because I am building an on-page editting tool for twig templates, so I need to know the contexts of those variables from within HTML.
I have tried to override the Compiler that the Twig_Environment uses, but I cannot seem to alter the output of the twig variable node.
How can I do this?
EDIT
I wanted to mention that I need this to use the {{ product.name }} syntax, since other designers will work with those templates outside of Symfony 2. I want to make almost all twig variables editable in the front-end, so a solution with filters or macros can indeed work, but it kills the usability and readability of the platform I am writing. There is no public API currently in twig that can achieve what I want, that is why I am fiddling with the twig compiler. I do not have the required knowledge of the Twig internals to achieve this. If someone could point me into a direction that would be great!
UPDATE 2
I have found a place where I can achieve what I want. Every GetAttr node is compiled to $this->getAttribute($someContext, "property"). So if I can change the subclass of compiled twig template, I can achieve what I want. By default all twig templates extend from Twig_Template. I want to extend this method.
How can I change the subclass of all compiled twig templates?
UPDATE 3
I've found a way to use my own base class for all compiled twig templates. I can simply set it as an option on the twig environment, see this link. I hope to get it working tomorrow and I will post a proper answer on how I solved it all together. Not sure how I will handle escaping, since that will happen after the $this->getAttribute() is called.
I think macros are the best candidates for those kind of wrappings.
For example:
main.twig
{% import "macros.twig" as macros %}
{{ macros.display_product(product) }}
macros.twig
{% macro display_product(product) %}
<span data-id="{{ product.id }}" data-prop="name">{{ product.name }}</span>
{% endmacro %}
Context
product:
id: 8
name: My Georgeous Product
Result
<span data-id="8" data-prop="name">My Georgeous Product</span>
See fiddle
I've solved it by wrapping the PrintNode that is created when parsing a VAR_START token (inside the twig parser) with my own EditablePrintNode. In that node I traverse the expression that is compiled by the print node and get the necessary property path and pass that as an argument to a wrapper function around the default twig escape function that is compiled by the PrintNode.
I suggest to write a custom filter. You can find the doc here about how to write and configure in your environment
// an anonymous function
$filter = new Twig_SimpleFilter('my_custom_product_filter', function ($product) {
return '<span data-id="'.$product->getId().'" data-prop="name">'.$product->getName().'</span>';
});
You need to register as described in the doc
then you can use as follow:
{{ myProduct|my_custom_product_filter}}
Hope this help

Yii 2 registerJs in twig templates

In the Yii 2.0 guide it says you can register Javascript code in a twig template like this:
{registerJs key='show' position='POS_LOAD'}
$("span.show").replaceWith('<div class="show">');
{/registerJs}
Tried this but it will simply output the whole snippet {registerJs ... as text on the page without adding it to the page's Javascript Code.
Similar commands like registerJsFile or registerCss aren't working either.
Am I missing something? Thanks!
EDIT:
As Mihai P. noted below, {registerJs} is syntax for Smarty templates. So, the question is: is there a similar way to register inline JS in Twig templates? The documentation only mentions registering assets.
You can use this in your Twig template, which is the current view, to call registerJs.
{% set script %}
var app = new Vue({
el: '#vue-widget',
data: {
message: 'Hello Vue!'
}
})
{% endset %}
{{ this.registerJs(script,4,'vue-widget') }}
The question is 3 years old, I put it here for someone runs into a similar problem.
You can use this in the Twig template with View constant like below:
{{ this.registerJs('$("span.show").replaceWith(\'<div class="show">\');', constant('\\yii\\web\\View::POS_HEAD')) }}
And, you can also call registerJs inside the Yii2 controller, which I think it makes the code cleaner
$this->getView()->registerJs('$("span.show").replaceWith(\'<div class="show">\');', \yii\web\View::POS_HEAD);
Your example is copied from the smarty section not the twig. There are some examples in the twig section that you might want to try.

How can I use Express to render dynamic files?

I'm looking to use Express to render raw strings as HTML, with the ability to reference static files in a specified directory (CSS, images, and other resources).
I've done a lot of research, but I haven't seen anything that approaches what I'm trying to do. For example, I thought perhaps writing a custom templating engine that only pretended to load a file would cut it, but that doesn't seem to do the trick.
What's the best way to approach this?
There are many ways to do it.
It can done in any other templating engine as well but here i am guiding you to implement same using EJS(Embedded Javascript).
Use Express Generator to create an ExpressJS app with EJS templating Engine.
command :
express --ejs AppName
For more information about express Generator refer to doc here
Now EJS has tags such as :
1. <% code %> - Code that is evaulated without "echo" it is not printed out.
2. <%= code %> - Code that is evaluated and printed out and escaped!
3. <%- Code %> - Code that is evaluated printed out and not escaped!
So in your case you can use 3rd the third tag that i have mentioned above.
Render EJS views in the usual way from your route config:
res.render('index.ejs', {
// data you want to pass ..
});
Code sample
Some time ago i was playing around with EJS, i developed a very small blogApp for practice.
You can look into this view, line number 33, for more practical way of implementing same.

Natural Templating .html (like Thymeleaf) for Node.js

Is there Natural Templating for Node.js
Natural Templating (like Thymeleaf template engine) is when template page or it's part can be perfectly displayed by a browser as a prototype, without being executed at all.
That is, I have template with .html extension, and I can just open in browser to preview it, and use standard HTML dev tools to edit.
UPDATE: I have added answered, that were added in comments. (Do new StackOverflower users fear to add answers?) Hope to hear from developers, that actually use those things (just add new answer)
github.com/flatiron/plates (answered by generalhenry)
Plates (short for templates) binds data to markup. Plates has NO
special syntax. It works in the browser and in Node.js.
Active
I have a jinja like template engine in the backend.
My frontend sometimes needs to retrieve data from the server and interpolate with the content of a HTML5 template tag.
I could do that with query selectors. But I want something more closer to thymeleaf or mustache without special syntax (especially not to conflict with my backend template engine and not have any issues when presented in the HTML5 template tag).
So I created this:
https://github.com/marcodpt/tint
While this works in the browser (and that's fine for my personal use), it's not difficult to use a DOM API to port it to node or deno.
<html>
<head>
<script type="module">
import compile from "https://cdn.jsdelivr.net/gh/marcodpt/tint#2.0.0/template.js"
const render = compile(document.getElementById("app"))
render({
message: "Hello World!"
})
</script>
</head>
<body>
<div id="app">
<h1 :text="message">Loading...</h1>
</div>
</body>
</html>
{{ mustache }} (answered by etienne)
Logic-less templates.
Available in Ruby, JavaScript, Python, Erlang, PHP, Perl, Objective-C,
Java, .NET, Android, C++, Go, Lua, ooc, ActionScript, ColdFusion,
Scala, Clojure, Fantom, CoffeeScript, D, and for node.js.
Works great with TextMate, Vim, Emacs, and Coda.
I was using Handlebars.
There are actually quite a few template engines in JavaScript and here you can decide what you need.

Resources