From caf7139d07621a1714b3f434cfb9f4fe81436e0a Mon Sep 17 00:00:00 2001 From: Satyam Date: Wed, 18 Oct 2023 18:22:07 +0200 Subject: [PATCH] Added ability to loop through Map instances (and other iterables) --- README.md | 2 +- t.js | 42 ++++++++++++++++++------------------------ t.min.js | 3 +-- t_test.html | 17 +++++++++++++---- 4 files changed, 33 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 80c2895..18bb5b3 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ * Name-spaced variables: `{{=User.address.city}}` * If/else blocks: `{{value}} <> {{:value}} <> {{/value}}` * If not blocks: `{{!value}} <> {{/!value}}` - * Object/Array iteration: `{{@object_value}} {{=_key}}:{{=_val}} {{/@object_value}}` + * Object/Array/Map (any *Iterator*) iteration: `{{@object_value}} {{=_key}}:{{=_val}} {{/@object_value}}` * Multi-line templates (no removal of newlines required to render) * Render the same template multiple times with different data * Works in all modern browsers diff --git a/t.js b/t.js index add6913..98d07a6 100644 --- a/t.js +++ b/t.js @@ -30,14 +30,12 @@ } function get_value(vars, key) { - var parts = key.split('.'); - while (parts.length) { - if (!(parts[0] in vars)) { - return false; - } - vars = vars[parts.shift()]; - } - return vars; + return key + .split('.') + .reduce( + (out, part) => (out instanceof Map ? out.get(part) : out[part]) ?? false, + vars + ); } function render(fragment, vars) { @@ -67,22 +65,18 @@ // process array/obj iteration if (meta == '@') { - // store any previous vars - // reuse existing vars - _ = vars._key; - __ = vars._val; - for (i in val) { - if (val.hasOwnProperty(i)) { - vars._key = i; - vars._val = val[i]; - temp += render(inner, vars); - } - } - vars._key = _; - vars._val = __; - return temp; - } - + return Array.from( + !!val?.[Symbol.iterator] ? val.entries() : Object.entries(val), + ([_key, _val]) => render( + inner, + { + ...vars, + _key, + _val, + } + ) + ).join(''); + } }) .replace(valregex, function(_, meta, key) { var val = get_value(vars,key); diff --git a/t.min.js b/t.min.js index 4152667..8bd5fc0 100644 --- a/t.min.js +++ b/t.min.js @@ -1,2 +1 @@ -(function(){function c(a){this.t=a}function l(a,b){for(var e=b.split(".");e.length;){if(!(e[0]in a))return!1;a=a[e.shift()]}return a}function d(a,b){return a.replace(h,function(e,a,i,f,c,h,k,m){var f=l(b,f),j="",g;if(!f)return"!"==i?d(c,b):k?d(m,b):"";if(!i)return d(h,b);if("@"==i){e=b._key;a=b._val;for(g in f)f.hasOwnProperty(g)&&(b._key=g,b._val=f[g],j+=d(c,b));b._key=e;b._val=a;return j}}).replace(k,function(a,c,d){return(a=l(b,d))||0===a?"%"==c?(new Option(a)).innerHTML.replace(/"/g,"""): -a:""})}var h=/\{\{(([@!]?)(.+?))\}\}(([\s\S]+?)(\{\{:\1\}\}([\s\S]+?))?)\{\{\/\1\}\}/g,k=/\{\{([=%])(.+?)\}\}/g;c.prototype.render=function(a){return d(this.t,a)};window.t=c})(); \ No newline at end of file +!function(){var n=/\{\{(([@!]?)(.+?))\}\}(([\s\S]+?)(\{\{:\1\}\}([\s\S]+?))?)\{\{\/\1\}\}/g,t=/\{\{([=%])(.+?)\}\}/g;function r(n){this.t=n}function e(n,t){return t.split(".").reduce(((n,t)=>(n instanceof Map?n.get(t):n[t])??!1),n)}function i(r,o){return r.replace(n,(function(n,t,r,u,c,a,f,p){var s=e(o,u);return s?r?"@"==r?Array.from(s?.[Symbol.iterator]?s.entries():Object.entries(s),(([n,t])=>i(c,{...o,_key:n,_val:t}))).join(""):void 0:i(a,o):"!"==r?i(c,o):f?i(p,o):""})).replace(t,(function(n,t,r){var i=e(o,r);return i||0===i?"%"==t?function(n){return new Option(n).innerHTML.replace(/"/g,""")}(i):i:""}))}r.prototype.render=function(n){return i(this.t,n)},window.t=r}(); \ No newline at end of file diff --git a/t_test.html b/t_test.html index f410c54..5dfa9c7 100644 --- a/t_test.html +++ b/t_test.html @@ -15,7 +15,7 @@ - +