TEMPJS is a fast, low code and no dependencies templating langage where you can use javascript inside html !
- tempjs
See a simplified live editor on the github page
NOTE: Use a version upper or equal to 1.0.6 to prevent XSS injection
See the CHANGELOG file
There are several reasons why you should consider using tempjs:
-
Lightweight: tempjs is less than 5 kilobytes in size, making it a great choice for projects where size matters.
-
No dependencies: tempjs has no external dependencies, so you won't have to worry about installing and maintaining additional packages.
-
Written in TypeScript: tempjs is written in TypeScript, which makes it easy to use in modern projects and ensures that it follows best practices.
-
Fast: tempjs is optimized for rendering templates quickly, so your users won't experience any delays while waiting for content to load.
-
Cross-platform: tempjs works on any device and has the same properties and functionalities in both Node.js and the browser, making it a versatile tool for rendering templates in any environment.
-
Customizable: With tempjs, you can add as many custom delimiters and plugins as you want, allowing you to tailor it to your specific needs and make it work exactly the way you want it to.
By choosing tempjs, you can be confident that you're using a reliable and efficient template engine for your web application.
$ npm i tempjs-template
Or directly in the browser with
<script src="https://unpkg.com/tempjs-template@1.0.7/dist/index.js"></script>
import tempjs from "tempjs-template";
NOTE: You can use any javascript syntax into the template just ensure to use = operator if you want to return something (never use return)
In this example we render a list and apply a color on the index
const todos = ["Make a chatbot", "Eat an apple", "Do some sports"];
const data = { todos };
document.body.innerHTML = tempjs.compile(
`
{%_# I'm just a comment dont worry _%}
<ul>
{%_ let index = 0 _%}
{% for(const todo of todos){ _%}
<li style="color: {%= index%2 === 0 ? "red" : "green" %}">{%= todo %}</li>
{%_ ++index %}
{%_ } _%}
</ul>
`,
data
);
Working with async is pretty simple
await tempjs.compile(
`
{%_
const req = await fetch("https://jsonplaceholder.typicode.com/todos/")
const todos = await req.json()
_%}
<ul>
{%_ for(const todo of todos){ _%}
<li>{%= todo.title %}</li>
{%_ } _%}
</ul>
`,
{
/*some data here*/
},
{ async: true }
);
NOTE: The return type is calculed on the options so it will be automatically set to string or Promise<string>. Below is just a simplified version of the return type.
- tempjs.compile(template: string, data: Record<string, unknown>, options: Options): string | Promise<string>
- tempjs.compileFromFile(filePath: string, data: Record<string, unknown>, options: Options): string | Promise<string>
- tempjs.compileFromFileBrowser(filePath: string, data: Record<string, unknown>, options: Options): Promise<string>
- tempjs.createFunction(filePath: string, data: Record<string, unknown>, options: Options): () => string | Promise<string>
- tempjs.debug(filePath: string, data: Record<string, unknown>, options: Options): { template, options, data, generatedFunction, generatedCode, dataListName, dataListValue, pluginsName, pluginsFunctions }
include(filaname: string, data: Record<string, unknown>, options: Options): string | Promise<string>
{%@ include("header.html", { userName: "Yoann" }) %}
NOTE: Don't forget to set the option "async: true" if the file also have an includeBrowser
includeBrowser(filaname: string, data: Record<string, unknown>, options: Options): Promise<string>
{%@ await includeBrowser("header.html", { userName: "Yoann" }) %}
NOTE: It can be combined with custom delimiters (example: {%_# I'm a comment _%})
{%_
Remove white spaces before the first delimiter_%}
Remove white spaces after the last delimiter
{% if(5 > 0){ _%}
<h1>Five is greater than 0</h1>
{%_ } %}
Should compile as follow: <h1>Five is greater than 0</h1>
{% const greeting = "Hello World!" %}
<h1>{%= greeting %}</h1>
Should compile as follow: <h1>Hello World!</h1>
XSS injection warning: Only use this with include/includeBrowser or if you are sure about what you are doing
The html will be executed
{% const greeting = "<h1>Hello World!</h1>" %}
{%@ greeting %}
Should compile as follow: <h1>Hello World!</h1>
{%# You can write some comments here it will not be shown or evaluate
console.log("I ll not show") %}
<h1>I love Tempjs</h1>
Should compile as follow: <h1>I love Tempjs</h1>
{%% greeting %}
Should compile as follow: {% greeting %}
type Options = {
openDelimiter?: string;
closeDelimiter?: string;
context?: unknown;
async?: boolean;
minimified?: boolean;
root?: string;
removeWhitespace?: boolean;
delimiters?: {
name: string;
description: string;
delimiter: string;
fn: (content: string, options: Options) => string;
}[];
plugins?: { name: string; description: string; fn: Function }[];
};
- openDelimiter (default: {%) : Open delimiter
- closeDelimiter (default: %}) : Close delimiter
- context (default: null) : Context of the function
- async (default: false) : Make asynchronous requests in the template
- minimified (default: true) : Make the generated code more readable in debug mode
- root (default: null): Specifie a root directory for including files
- removeWhitespace (default: false): Remove all whitespace before and after js instruction
- delimiters : Create customs delimiters. By default you have:
= return a value
@ return a value without escaping HTML
# create a comment
% Ingnore js instruction and display is as text with delimiters
Examples of implementation:
- Comment
{
name: "comment",
description: "Shortcut to turn some code into a comment",
delimiter: "#",
fn: function (content, options) {
return "/*" + content + "*/";
},
}
- Return value
{
name: "return",
description: "Allow user to add variable to the output",
delimiter: "=",
fn: function (content, options) {
return `$__output += escapeHTML(${content})`;
},
},
- plugins : Create custom acessibles function into the template. By default you have "include" and "includeBrowser" that allow you to render other template into the current template:
include(filaname: string, data: Record<string, unknown>, options: Options): string | Promise<string>
includeBrowser(filaname: string, data: Record<string, unknown>, options: Options): Promise<string>
//Can be useful to create your own plugins
escapeHTML(obj: unknow): unknow //if the obj is a string HTML will be escaped
Example of implementation:
{
name: "truncat",
description: "Truncat some text",
fn: function(text: string, size: number){
return text.trim().substring(0, size);
},
},