tim icon indicating copy to clipboard operation
tim copied to clipboard

This is Tim ⚡️ A high-performance template engine & markup language written in Nim

Tim - Template Engine
⚡️ A high-performance template engine & markup language
FastCompiled • Written in Nim language 👑

nimble install tim

API reference

Github Actions Github Actions

😍 Key Features

or more like a todo list

  • Fast & easy to code!
  • Cross-platform and multi-threaded
  • Caching and Pre-compilation
  • JIT Rendering
  • Output Minifier
  • Transpiles to JavaScript for Client-Side Rendering
  • Supports embeddable code json, js, yaml, css
  • Available as a Nimble library for Nim development
  • Built-in Browser Sync & Reload
  • Built-in real-time Server-Side Rendering SSR via ZeroMQ
  • Source-to-Source translator (transpiles to JavaScript, Ruby, Python and more)
  • Template localization
  • Written in Nim language 👑

Quick Example

div.container > div.row > div.col-lg-7.mx-auto
  h1.display-3.fw-bold: "Tim is Awesome"
  a href="https://github.com/openpeeps/tim" title="This is hot!": "Check Tim on GitHub"

Tim in action

Check /example folder to better understand Tim's structure. Also check the generated HTML file

Template structure

Tim has its own little filesystem that continuously monitors .timl for changes/creation or deletion. Here is a basic filesystem structure:

storage/
  ast/
    # auto-generated
    # for storing pre-compiled binary .ast nodes
  html/
    # auto-generated
    # for storing html files from static templates
templates/
  layouts/ # main place for layouts. (create the directory manually)
    base.timl
    customer.timl
  partials/ # main place for storing partials (create the directory manually)
    product/
      price.timl
      cta.timl
  views/ # main place for storing views (create the directory manually)
    customer.timl
    products.timl
    product.timl

Client-Side Rendering

Tim Engine seamlessly shifts rendering to the client side for dynamic interactions, using the intuitive @client block statement.

body
  section#contact > div.container
    div.row > div.col-12 > h3.fw-bold: "Leave a message"
    div#commentForm

  @client target="#commentForm"
    form method="POST" action="/submitComment"
      div.form-floating
        input.form-control type="text" name="username"
          placeholder="Your name" autocomplete="off" required=""
        label: "Your name"
  
      div.form-floating.my-3
        textarea.form-control name="message" style="height: 140px" required="": "Your message"
        label: "Your message"
      div.text-center > button.btn.btn-dark.px-4.rounded-pill type="submit": "Submit your message"
  @end

Browser Sync & Reload

Compile your project with -d:timHotCode flag, then connect to Tim's WebSocket server to auto reload the page when there are changes on disk.
Note that this feature is not available when compiling with -d:release.

  {
    const watchout = new WebSocket('ws://127.0.0.1:6502/ws');
    watchout.addEventListener('message', () => location.reload());
  }

Data

Tim provides 3 types of data storages. Global and Local as JsonNode objects for handling immutable data from the app to your timl templates, and Template based data at template level using Tim's built-in AST-based interpreter.

  1. Global data can be passed at precompile-time and is made available globally for all layouts, views and partials.
    Note: Using $app in a template will mark it as JIT.
timl.precompile(
  global = %*{
    "year": parseInt(now().format("yyyy"))
  }
)

Accessing global data can be done using the $app constant:

footer > div.container > div.row > div.col-12
  small: "© " & $app.year & " — Made by Humans from OpenPeeps"
  1. Local data can be passed to a template from route's callback (controller). $this constant can be used to access data from the local storage.
    Note: Using $this in a template will mark it as JIT.
timl.render("index", local = %*{
  loggedin: true,
  username: "Johnny Boy"
})
if $this.loggedin:
  h1.fw-bold: "Hello, " & $this.username
  a href="/logout": "Log out"
else:
  h1: "Hello!"
  a href="/login": "Please login to view this page"
  1. Template variables can be declared inside templates using var or const. The only difference between these two is that constants are immutable and requires initialization.

The scope of a declared variable is limited to the branch in which it was declared.

var a = 1       // a global variable
if $a == 1:
  var b = 2     // a block-scoped variable
  echo $a + b   // prints 3
echo $b         // error, undeclared variable

Debug

For debug reasons you can use echo to print data

echo "Hello, World!"

Data types

Supported datatypes: string, int, float, bool, array, object

var a = "Hello"
var b = 10
var c = 10.5 
var d = true    // false

var e = []      // init an empty array
var f = {}      // init an empty object

Function

todo

Conditionals

todo

For loop

var boxes = [
  {
    title: "Chimney Sweep"
    description: "Once feared for the soot they carried,
      these skilled climbers cleaned fireplaces to prevent
      fires and improve indoor air quality" 
  }
  {
    title: "Town Crier",
    description: "With booming voices and ringing bells,
      they delivered news and announcements in the days
      before mass media"
  }
  {
    title: "Ratcatcher",
    description: "These pest controllers faced smelly
      challenges, but their work helped prevent the
      spread of diseases like the plague"
  }
]

div.container > div.row.mb-3
  div.col-12 > h3.fw-bold: "Forgotten Professions"
  for $box in $boxes:
    div.col-lg-4 > div.card > div.card-body
      div.card-title.fw-bold.h4: $box.title
      p.card-text: $box.description

Escaping

todo

Embed Code

Tim integrates a variety of embeddable code formats, including: JavaScript, YAML/JSON and CSS

JavaScript block

@js
  document.addEventListener('DOMContentLoaded', function() {
    console.log("Hello, hello, hello!")
  });
@end

JSON block

todo

YAML block

todo

CSS

todo

❤ Contributions & Support

🎩 License

Tim Engine | LGPLv3 license. Made by Humans from OpenPeeps.
Copyright © 2024 OpenPeeps & Contributors — All rights reserved.