Nimja Template Engine
repository·master·Indexed 42 days ago
https://github.com/enthus1ast/nimjaA high-performance, statically typed template engine for the Nim programming language, inspired by Jinja2 and Twig. Nimja compiles templates directly into Nim code at compile-time, providing features such as template inheritance via 'extends', partials via 'importnimja', and full access to Nim's syntax and control structures. It supports custom output types, hot code reloading, and targeted block rendering via the 'blockToRender' parameter.
What's inside Nimja
- Nimja is a typed and compiled template engine for Nim, inspired by Jinja2 and Twig. It transforms templates into Nim code at compile-time, allowing you to use the full power of the Nim language directly within your templates. This results in extremely high performance, as templates are executed as native code.
Use template inheritance with extends
masterA child template can extend a master template using the
{% extends "path/to/master.nimja" %}syntax. The master template defines placeholder{% block name %}tags, which the child template fills by defining blocks with the same name.Rules for
extends:extendsmust be the first token in the template (comments and strings are allowed before it).- If a template extends another, all content in the child template must be wrapped in a
{% block %}. - The master template can declare variables that become visible in the child template.
{# child.nimja #} {% extends "partials/_master.nimja" %} {% block content %} I AM CONTENT {% endblock %} {% block footer %} ...The footer.. {% endblock %}Use baseDir with template compilation functions
masterTo ensure template imports (like
{% importnimja ... %}) work correctly, especially when your templates are used in different modules, always provide thebaseDirparameter to compilation functions.It is discouraged to use absolute paths with
tmplf. Instead, use a relative path and specify thebaseDirusinggetScriptDir()or a similar mechanism.Recommended Pattern:
compileTemplateFile("some/template.nimja", baseDir = getScriptDir())compileTemplateFile("templates/index.nimja", baseDir = getScriptDir())How templates and Nim code interact
masterBecause Nimja transforms templates into Nim code, templates have access to all variables passed into the rendering procedure. Furthermore, you can write arbitrary Nim code inside template tags.
Syntax Mapping:
{{ myObj.myVar }}becomes$(myObj.myVar){% myExpression.inc() %}becomesmyExpression.inc(){# comment #}is a template comment.
Custom Output Types: The return variable of a template procedure can be a
string, aRope, or any object that implements the&=(obj: YourObj, str: string) procedure.proc foo(ss: string, ii: int): string = compileTemplateStr( """example{% if ii == 1%}{{ss}}{%endif%}{% var myvar = 1 %}{% myvar.inc %}""" )Configure VSCode Syntax Highlighting for .nimja files
masterSince
.nimjafiles are not natively recognized by VSCode, you can associate them with thehtmllanguage mode to enable syntax coloring and formatting. Add the following to your VSCodesettings.json:"files.associations": { "*.nwt": "html", "*.nimja": "html" }Compile Nimja templates
masterBecause Nimja is a compiled engine, you must recompile your application whenever you change a
.nimjatemplate file.To ensure Nim detects changes in template files, use the
-f(force) flag:nim c -f -r yourfile.nimEnable Hot Code Reloading for Templates
masterNimja supports hot code reloading (HCR) to allow you to modify templates and your template-rendering logic without restarting your host application.
To implement this:
- Import
nimja/hcrutilsin your host application. - Use a
ChangeWatcherto monitor your templates directory. - Call
asyncCheck cw.recompile()when a change is detected to recompile your template module (e.g.,tmpls.nim).
Note: When moving to production, comment out the
asyncCheck cw.recompile()line.import nimja/hcrutils import jester, os var cw = newChangeWatcher(@[getAppDir() / "templates/"]) asyncCheck cw.recompile()- Import
Run the Nimja playground in a browser
masterThe Nimja playground demonstrates that Nimja can run on the JavaScript target. The current implementation is a simple demonstration that replaces the
innerHTMLof the document.To run the playground locally:
- Compile the
jsplayground.nimfile to JavaScript using the Nim compiler:nim js jsplayground.nim - Open the resulting
index.htmlfile in your web browser.
nim js jsplayground.nim- Compile the
Debug Nimja Template Compilation
masterYou can use specific Nim compiler flags to inspect the internal state of Nimja's template engine during development:
-d:dumpNwtAst: Dumps theNwtAst.-d:dumpNwtAstPretty: Dumps theNwtAstas pretty-printed JSON.-d:dumpNwtMacro: Dumps the generated Nim macros.-d:nwtCacheOff: Disables theNwtNodecache.-d:noPreallocatedString: Prevents preallocating the output string.-d:noCondenseStrings: Disables string condensing.
nim c -d:dumpNwtAst -r yourfile.nim nim c -d:dumpNwtAstPretty -r yourfile.nim nim c -d:dumpNwtMacro -r yourfile.nimUse nimjautils for enhanced loop control
masterThe
nimja/nimjautilsmodule provides a.loop()method for iterators, yielding aLoopobject that provides metadata about the current iteration.Loop object fields:
index0: Current index (starts at 0).index: Current index (starts at 1).revindex0: Reverse index (starts at 0 from the end).revindex: Reverse index (starts at 1 from the end).length: Total length of the sequence.first: Boolean, true if first iteration.last: Boolean, true if last iteration.previtem: Option containing the previous item.nextitem: Option containing the next item.cycle(@[...]): Returns a value that cycles through the provided array.
{% for (loop, row) in rows.loop() %} <li class="{{ loop.cycle(@["odd", "even"]) }}">{{row}}</li> {% endfor %}Render specific template blocks
masterAs of version 0.10.0, all template rendering procedures (tmpls,tmplf,compileTemplateString, andcompileTemplateFile) support ablockToRenderparameter. When this parameter is set, Nimja will only render the specified block from the template, which is useful for implementing features like HTMX partial updates.Core Template Compilation Procedures
masterNimja provides three primary procedures to transform templates into Nim code. These procedures generate the body of a procedure or iterator, typically appending to a
resultvariable.compileTemplateStr(str: string): Compiles a template string into Nim AST.compileTemplateFile(path: string): Compiles the content of a file into Nim AST.tmpls(str: string)andtmplf(path: string): Shorthand versions for inlining a render call directly.
Important: When using
importnimjaorextends, you must provide thebaseDirparameter (often usinggetScriptDir()) so the compiler can locate the referenced files.import nimja/parser import os # Using compileTemplateFile in a procedure proc myRenderProc(someParam: string): string = compileTemplateFile("myFile.html", baseDir = getScriptDir()) # Using tmpls for inlining let leet = 1337 echo tmpls("foo {{leet}}") # Using tmplf for inlining a file echo tmplf("templates" / "myfile.nimja", baseDir = getScriptDir())