Giter Club home page Giter Club logo

tmpl's Introduction

Build Status Code Quality Coverage Status NPM version NPM downloads MIT License

Tmpl

The riot template engine

Installation

Npm

npm install riot-tmpl --save

Bower

From v2.4.2, bower is not supported.

Documentation

How it works?

Three ways:

  • Expressions: tmpl('{ value }', data). Returns the result of evaluated expression as a raw object.

  • Templates: tmpl('Hi { name } { surname }', data). Returns a string with evaluated expressions.

  • Filters: tmpl('{ show: !done, highlight: active }', data). Returns a space separated list of trueish keys (mainly used for setting html classes), e.g. "show highlight".

Template examples

tmpl('{ title || "Untitled" }', data)
tmpl('Results are { results ? "ready" : "loading" }', data)
tmpl('Today is { new Date() }', data)
tmpl('{ message.length > 140 && "Message is too long" }', data)
tmpl('This item got { Math.round(rating) } stars', data)
tmpl('<h1>{ title }</h1>{ body }', data)

Falsy expressions

In templates (as opposed to single expressions) all falsy values except zero (undefined/null/false) will default to empty string:

tmpl('{ undefined } - { false } - { null } - { 0 }', {})
// will return: " - - - 0"

tmpl('{}')                 // undefined
tmpl('{ false }', {})      // false
tmpl('{ null }', {})       // null
tmpl('{ 0 }', {})          // 0

Changes in v2.3

  • Brackets can not contain characters in the set [\x00-\x1F<>a-zA-Z0-9'",;\\]
  • No comments in expressions, the compiler is the only that strip comments
  • Attributes with expressions containing > must be quoted

See API and CHANGES for details.

tmpl's People

Contributors

amarcruz avatar cognitom avatar gianlucaguarini avatar manhg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

tmpl's Issues

Supporting ordered keys for objects

Use case: I have an object, where I want to control the sort/display order.
Using the code below, I can accomplish this with:

<div each="{ ckey,crow inkey [recordkeys,records] }">
</div>

Whereas:

  • records is an object containing an indexed list of objects like:
{ "a":{"foo":"bar", "bar":"foo"},
  "b":{"foo":1,     "bar":2}
}
  • recordkeys is a sorted array of the keys involved e.g. ["b", "a"]
  • ckey will iterate through recordkeys.
  • crow will iterate through the objects contained in records.

It's essentially the same as:

<div each="{ ckey,crow in records }">
</div>

But with a well-defined sort order instead; determined by the order in recordkeys. The current each={ ... in ... } statement basically has an implementation-defined sort order which cannot be influenced deterministically.

Patch for riot itself:

commit 12d0441da420700cd56237cff6cca4512c52b8bf
Author: Stephen R. van den Berg <[email protected]>
Date:   Mon Aug 29 15:57:42 2016 +0200

    Support inkey keyword for each and sorted keylists.

diff --git a/lib/browser/tag/each.js b/lib/browser/tag/each.js
index d5394ad..2fd3ad6 100644
--- a/lib/browser/tag/each.js
+++ b/lib/browser/tag/each.js
@@ -31,8 +31,9 @@ import {
  * @returns { Object } - new object containing the values of the original item
  *
  * The variables 'key' and 'val' are arbitrary.
- * They depend on the collection type looped (Array, Object)
+ * They depend on the collection type looped (Array, Object, [Array, Object])
  * and on the expression used on the each tag
+ * The [Array, Object] variant is valid when the member inkey is true.
  *
  */
 export function mkitem(expr, key, val, base) {
@@ -119,15 +120,21 @@ export default function _each(dom, parent, expr) {
   expr.update = function updateEach() {
     // get the new items collection
     var items = tmpl(expr.val, parent),
+      keys,
       // create a fragment to hold the new DOM nodes to inject in the parent tag
       frag = document.createDocumentFragment()
     root = ref.parentNode

+    if (expr.inkey) {
+      keys = items[0]
+      items = items[1]
+    }
+
     // object loop. any changes cause full redraw
     if (!isArray(items)) {
       hasKeys = items || false
       items = hasKeys ?
-        Object.keys(items).map(function (key) {
+        (keys || Object.keys(items)).map(function (key) {
           return mkitem(expr, key, items[key])
         }) : []
     }
@@ -144,7 +151,8 @@ export default function _each(dom, parent, expr) {
       // reorder only if the items are objects

       var
-        _mustReorder = mustReorder && typeof item == T_OBJECT && !hasKeys,
+        _mustReorder = mustReorder && typeof item == T_OBJECT &&
+         (!hasKeys || expr.inkey),
         oldPos = oldItems.indexOf(item),
         pos = ~oldPos && _mustReorder ? oldPos : i,
         // does a tag exist in this position?

And for riot-tmpl:

commit 6a6ae43b68f72c262c4ed242b009357e4452aed6
Author: Stephen R. van den Berg <[email protected]>
Date:   Mon Aug 29 03:18:38 2016 +0200

    Support inkey keyword for each and sorted keylists.

diff --git a/src/brackets.js b/src/brackets.js
index 45842a8..9c0460d 100644
--- a/src/brackets.js
+++ b/src/brackets.js
@@ -118,7 +118,7 @@ var brackets = (function (UNDEF) {
     /\\({)|{/g,                 // $_RIX_OPEN
     RegExp('\\\\(})|([[({])|(})|' + S_QBLOCKS, REGLOB),       // $_RIX_CLOSE
     DEFAULT,                    // $_RIX_PAIR
-    /^\s*{\^?\s*([$\w]+)(?:\s*,\s*(\S+))?\s+in\s+(\S.*)\s*}/, // $_RIX_LOOP
+    /^\s*{\^?\s*([$\w]+)(?:\s*,\s*([$\w]+))?\s+in(key)?\s+(\S.*)\s*}/, // $_RIX_LOOP
     /(^|[^\\]){=[\S\s]*?}/      // $_RIX_RAW
   ]
It's essentially the same as:
But with a well-defined sort order instead; determined by the order in recordkeys.

@@ -319,7 +319,8 @@ var brackets = (function (UNDEF) {
     var m = expr.match(_cache[$_RIX_LOOP])

     return m
-      ? { key: m[1], pos: m[2], val: _cache[0] + m[3].trim() + _cache[1] }
+      ? { key: m[1], pos: m[2], val: _cache[0] + m[4].trim() + _cache[1],
+          inkey: m[3] === 'key' }
       : { val: expr.trim() }
   }

I submitted this to riot/riot#1964 as well. It's a bit unclear what the best entrypoint for this is.

The new tmpl does not pass all the riot tests

@aMarCruz
Including the newest version of tmpl.js some riot tests fail. Could you please fix the issue?
Steps to reproduce the issue:

  • switch to the riot 2.3.0 branch
  • install npm install riot-tmpl
  • include it in riot
import 'browser/wrap/prefix'
import 'browser/global-variables'
import '../node_modules/riot-observable/lib/index'
riot.observable = observable
import 'browser/mixin'
import 'browser/router'
import '../node_modules/riot-tmpl/lib/index'
import 'browser/tag/mkdom'
import 'browser/tag/each'
import 'browser/tag/parse'
import 'browser/tag/tag'
import 'browser/tag/update'
import 'browser/tag/util'
import 'browser/tag/vdom'
import 'browser/wrap/suffix'
  • trigger build riot triggering the tests

Making Handlebars work: Should riot-tmpl ignore {{expr}} but not {expr}?

I am looking at riot-tmpl and was wondering if we could recode it to ignore the double braces. Would it be hard to implement this? Or what can you guys say about this work around to make handlebars work?

In my setup, I would have to do two rendering stages:

Handelbars.compile(riot.render())(context)

Can someone please validate this suggestion, thanks!

Problem with backslash

First, thanks for the great library! Made my life much easier and is working great.

I did however run recently into one issue. It is illustrated here:

const tmpl = require('riot-tmpl');
tmpl.brackets.set('{{ }}');
tmpl.tmpl('C:\\User\\{{name}}.txt', {name: 'frank'});

The output here is: 'C:\\User{{name}}.txt'
but I would have expected: 'C:\\User\\frank.txt'

Can that be fixed with some configuration? Is it expected behavior or simply a bug?

Yo can use brackets <% %> anymore

This popular brackets from ASP looks great, but is causing many issues in riot.

ASP parses their files and then send the result to the html parser.
riot, by contrast, receives the tags from the html parser, probably altered. This is causing confusion to users that believe riot is a sort of ASP.

Also, the character > complicates the detection of tag elements, especially attributes. The compiler and tmpl are using the same function to separate expressions from markup: the new brackets.split function. brackets.split needs to be light because it must be included in riot, even without the compiler.

This new brackets function is the bridge between custom brackets, tmpl and the compiler, 'cause tmpl can receive the full body of a tag element and, practically, compile it from scratch (think about <yield> as example).

Changing brackets and expression cache

When brackets are changed after one expression is compiled, the compiled expression remains in the cache:

riot.util.brackets.set('{{ }}')
riot.util.tmpl('{{ x }} and { x }', { x: 2 })      // returns "2 and { x }"
riot.util.brackets.set(null)                       // reset brackets to '{ }'
riot.util.tmpl('{{ x }} and { x }', { x: 2 })      // fail, expression is in cache with '{{ }}'

There's no workaround.

Safe eval

I think we can enable a special riot-tmpl version where all the expressions can be safely evaluated avoiding this
Please check how vue.js has solved the issue riot/riot#1076 (comment)

Render unescaped HTML

In the docs it says we can define a raw tag to render unescaped HTML.
Well that works, but it's not very clean.

<raw content="{ json(aListData.data).toString() }"></raw>

I would like Riot to support an alternative way of displaying unescaped HTML, why not like this:

{{ html }}

{{ json(aListData.data).toString() }}

If it's not that hard to solve and if it doesn't increase the code size too much...

Each loops, __checked doesn't work

I had that classic case when you want to append new elements in a list, considering that back-end already sets a initial amount of items on the page load, and the server is not node, could be anything, php, .net or whatever.

Virtual DOM really don't help me in this case, so I thought that would be a good idea to separate in riot templates files, rendering new items on first user interaction.

The ideal scenario would be to use that format described in the docs, like tmpl('', {}). However, each loops and __checked properties are not evaluated at all, as result I had to loop over items in js and then replace string looking for __checked and removing the underlines...

I though that template system and riot was decoupled, but I can't get the same templating features I have using riot component approach.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.