From a40e5092373c9d61ea264c82da3e29dfe18ea995 Mon Sep 17 00:00:00 2001 From: George Lemon Date: Mon, 8 Apr 2024 09:54:04 +0300 Subject: [PATCH] update Signed-off-by: George Lemon --- README.md | 259 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 220 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 9899fe5..3ca1a0c 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@

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

- nimble install tim + nimble install tim / npm install timl

@@ -13,37 +13,56 @@ 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 +- Caching & Pre-compilation - 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 +- Output Minifier - Written in Nim language 👑 -## Quick Example +**Tim as a Package**: For developers looking to incorporate Tim's power into their projects, Tim Engine is +also available for Nim development as a Nimble package and for **JavaScript** developers as a native **Node.js** & **Bun** `.addon`. +This allows you to seamlessly integrate Tim compilation within your existing workflow, empowering you to leverage +Tim's capabilities directly within your codebase.
+#### Other features +- Available for Nim development via Nimble `npm install tim` +- Available for JavaScript backend via NPM `npm install timl` +- Built-in AST Interpreter & JIT Rendering + +**Standalone CLI App**
+This user-friendly command-line interface allows you to easily compile Tim code +directly to your desired target source code. Simply provide your Tim code as input, and the CLI will +output the equivalent code in `Nim`, `JavaScript`, `Ruby`, or `Python`. + +#### Other features +- Available for Linux, MacOS and Windows +- Built-in real-time Server-Side Rendering `SSR` via `ZeroMQ` + +### Quick Example ```timl 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 Syntax Highlighting plugins**
+[VSCode Extension](https://marketplace.visualstudio.com/items?itemName=CletusIgwe.timextension) | [Sublime Text 4](https://packagecontrol.io/packages/tim) + ## Tim in action -Check [/example](https://github.com/openpeeps/tim/tree/main/example) folder to better understand Tim's structure. [Also check the generated HTML file](https://htmlpreview.github.io/?https://raw.githubusercontent.com/openpeeps/tim/main/example/preview.html) +Check [/example](https://github.com/openpeeps/tim/tree/main/example) folder to better understand Tim's structure. +[Also check the generated HTML file](https://htmlpreview.github.io/?https://raw.githubusercontent.com/openpeeps/tim/main/example/preview.html) + -#### Template structure +### Template structure Tim has its own little filesystem that continuously monitors `.timl` for changes/creation or deletion. Here is a basic filesystem structure: +
+ See Tim's filesystem structure + ``` storage/ ast/ @@ -65,6 +84,7 @@ templates/ 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. @@ -89,16 +109,6 @@ body @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`. -```js - { - 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. @@ -120,7 +130,7 @@ footer > div.container > div.row > div.col-12 ``` 2. **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.
+The constant `$this` can be used to access data from the local storage.
Note: Using `$this` in a template will mark it as JIT. ```nim @@ -145,18 +155,15 @@ 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. ```timl -var a = 1 // a global variable +var a = 1 // a global scoped 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!" -``` +_Template variables are known at compile time. So the final output is generated as `.html`. +If the assigned value comes from local or global storage, then it will automatically trigger the JIT flag +and the final result will be saved as `.ast`_ #### Data types Supported datatypes: `string`, `int`, `float`, `bool`, `array`, `object` @@ -165,17 +172,63 @@ Supported datatypes: `string`, `int`, `float`, `bool`, `array`, `object` var a = "Hello" var b = 10 var c = 10.5 -var d = true // false +var d = true var e = [] // init an empty array var f = {} // init an empty object ``` +#### Math +Math is cool. +``` +var x = 2 * 2 - 1.5 +echo $x // 2.5 +``` + +#### Debug +Sometimes you want to know what the heck is going on! For debug reasons you can use `echo` to print data. +``` +echo "Hello, World!" +echo $this.weirdThing +``` + +Also, Tim provides an `assert` command so you can unit test your code. +``` +var x = "Tim is awesome, right?" +assert $x.type == string +assert $x == "Tim is awesome, right?" +``` +_Note, `assert` commands are cleared when in `release` mode_ + #### Function -_todo_ + +```timl +fn say(x: string): string // forward declaration + +fn say(x: string): string = + return "Hello, " & $x + +echo say("Pantzini!") +echo say "Pantzini" // this works too + +// function overloading works too +fn say(x: int): int = + return $x * 1 + +echo say(1) +h1 > span: say(2) +``` #### Conditionals -_todo_ +```timl +var x = 1 +if $x == 1 and $x > 0: + span: "one" +elif $x == 0 or $x < 1: + span: "zero" +else: + span: "nope" +``` #### For loop ```timl @@ -187,13 +240,13 @@ var boxes = [ fires and improve indoor air quality" } { - title: "Town Crier", + title: "Town Crier" description: "With booming voices and ringing bells, they delivered news and announcements in the days before mass media" } { - title: "Ratcatcher", + title: "Ratcatcher" description: "These pest controllers faced smelly challenges, but their work helped prevent the spread of diseases like the plague" @@ -208,6 +261,23 @@ div.container > div.row.mb-3 p.card-text: $box.description ``` +#### While loops +``` +var + i = 0 + x = ["fork", "work", "push"] +while $i < $x.high: + span: $x[$i] + inc $i +``` + +`break` command can be used in `for` and `while` loops to immediately leave the loop body +``` +for $c in "hello": + echo $x + break +``` + ### Escaping _todo_ @@ -225,19 +295,130 @@ Tim integrates a variety of embeddable code formats, including: **JavaScript**, ``` ### JSON block -_todo_ +Note that JSON and YAML blocks requires identification, a `#someIdent` is required after `@json` or `@yaml` +```timl +@json#sayHelloJson +{"hello": "hello"} +@end +``` ### YAML block -_todo_ +Tim can parse and validate YAML contents. +```timl +@yaml#sayHelloYaml +hello: "hello" +@end +``` #### CSS _todo_ +#### Placeholders +_todo_ + +#### Standard Library +Tim provides a built-in standard library of functions and small utilities:
+`std/system` (loaded by default), `std/[os, strings, arrays, objects, math]` + +```timl +// std/system +fn random*(max: int): int +fn len*(x: string): int +fn encode*(x: string): string +fn decode*(x: string): string +fn toString*(x: int): string +fn timl*(code: string): string + +// std/math +fn ceil*(x: float): float +fn floor*(x: float): float +fn max*(x: int, y: int): int +fn min*(x: int, y: int): int +fn round*(x: float): float +fn hypot*(x: float, y: float): float +fn log*(x: float, base: float): float +fn pow*(x: float, y: float): float +fn sqrt*(x: float): float +fn cos*(x: float): float +fn sin*(x: float): float +fn tan*(x: float): float +fn acos*(x: float): float +fn asin*(x: float): float +fn rad2deg*(d: float): float +fn deg2rad*(d: float): float +fn atan*(x: float): float +fn atan2*(x: float, y: float): float +fn trunc*(x: float): float + +// std/strings +fn endsWith*(s: string, suffix: string): bool +fn startsWith*(s: string, prefix: string): bool +fn capitalize*(s: string): string +fn replace*(s: string, sub: string, by: string): string +fn toLower*(s: string): string +fn contains*(s: string, sub: string): bool +fn parseBool*(s: string): bool +fn parseInt*(s: string): int +fn parseFloat*(s: string): float +fn format*(s: string, a: array): string + +// std/arrays +fn contains*(x: array, item: string): bool +fn add*(x: array, item: string): void +fn shift*(x: array): void +fn pop*(x: array): void +fn shuffle*(x: array): void +fn join*(x: array, sep: string): string +fn delete*(x: array, pos: int): void +fn find*(x: array, item: string): int + +// std/os +fn absolutePath*(path: string): string +fn dirExists*(path: string): bool +fn fileExists*(path: string): bool +fn normalize*(path: string): string +fn getFilename*(path: string): string +fn isAbsolute*(path: string): bool +fn readFile*(path: string): string +fn isRelative*(path: string, base: string): bool +fn getCurrentDir*(): string +fn join*(head: string, tail: string): string +fn parentDir*(path: string): string +fn walkFiles*(path: string): array +``` + +## 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`._ + +The internal websocket returns an empty string when detect file changes, so basically you can add an event listener on `message` in order to `reload` the page. +```js + { + function connectWatchoutServer() { + const watchout = new WebSocket('ws://127.0.0.1:6502/ws'); + watchout.addEventListener('message', () => location.reload()); + watchout.addEventListener('close', () => { + setTimeout(() => { + console.log('Watchout WebSocket is closed. Try again...') + connectWatchoutServer() + }, 300) + }) + } + connectWatchoutServer() + } +``` + +### Syntax Extensions +- VSCode Extension available in [VS Marketplace](https://marketplace.visualstudio.com/items?itemName=CletusIgwe.timextension) (Thanks to [Cletus Igwe](https://github.com/Uzo2005)) +- Sublime Syntax package available in [/editors](https://github.com/openpeeps/tim/blob/main/editors/tim.sublime-syntax) ### ❤ Contributions & Support - 🐛 Found a bug? [Create a new Issue](https://github.com/openpeeps/tim/issues) - 👋 Wanna help? [Fork it!](https://github.com/openpeeps/tim/fork) +- 🎉 Spread the word! **Tell your friends about Tim Engine** +- ⚽️ Play with Tim Engine in your next web-project - 😎 [Get €20 in cloud credits from Hetzner](https://hetzner.cloud/?ref=Hm0mYGM9NxZ4) - 🥰 [Donate via PayPal address](https://www.paypal.com/donate/?hosted_button_id=RJK3ZTDWPL55C)