@peter.naydenov/morph 0.0.4 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,43 @@
1
1
  # Migration Guides
2
2
 
3
- No migration guide available yet
3
+
4
+ ## 0.x.x -> 1.x.x
5
+ Main change is how you address templates. Before template name and storage were separated arguments. Now they are a single argument where the first element is the template name and the second element is the storage name. Storage name is optional and defaults to 'default'.
6
+
7
+ ```js
8
+ // Add template to default storage
9
+ // Before
10
+ morph.add ( 'myName', myTpl )
11
+ // After
12
+ morph.add ( ['myName'], myTpl )
13
+
14
+ // Add template to named storage
15
+ // Before
16
+ morph.add ( 'myName', myTpl, 'myStorage' )
17
+ // After
18
+ morph.add ( ['myName', 'myStorage'], myTpl )
19
+ ```
20
+
21
+ Calling the render function has changed. The first argument again is the data, but then we have optional injection object and then comes post processing function.
22
+
23
+ ```js
24
+ // My injection is new argument
25
+ // Before
26
+ morph.render ( myData, postProcess1, postProcess2, postProcess3 )
27
+ // After
28
+ morph.render ( myData, myInjection, postProcess1, postProcess2, postProcess3 )
29
+ ```
30
+
31
+ List method is extended. Now you can pass more then one storage to scan for template names.
32
+
33
+ ```js
34
+ // Before
35
+ let storage1Templates = morph.list ( 'storage1' )
36
+ let storage2Templates = morph.list ( 'storage2' )
37
+ let all = storage1Templates.concat ( storage2Templates )
38
+
39
+ // After
40
+ let all = morph.list ( ['storage1', 'storage2'] )
41
+ ```
42
+
43
+ Library is prety well typed now so expect a smooth migration process.
package/README.md CHANGED
@@ -1,5 +1,4 @@
1
1
  # Morph (@peter.naydenov/morph)
2
- **Experimental stage. Not tested well yet.**
3
2
 
4
3
  ![version](https://img.shields.io/github/package-json/v/peterNaydenov/morph)
5
4
  ![license](https://img.shields.io/github/license/peterNaydenov/morph)
@@ -52,8 +51,8 @@ import morph from "@peter.naydenov/morph"
52
51
  const myTemplateDescription = {
53
52
  template: `Hello, {{name}}!` // simple template - a string with a placeholder
54
53
  }
55
- const myTemplate = morph.build ( myTemplateDescription ); // myTemplate is a render function
56
- const htmlBlock = myTemplate ( { name: 'Peter' } ) // Provide data to the render function and get the result
54
+ const myTemplate = morph.build ( myTemplateDescription ); // myTemplate is a render function
55
+ const htmlBlock = myTemplate ( { name: 'Peter' } ) // Provide data to the render function and get the result
57
56
  // htmlBlock === 'Hello, Peter!'
58
57
  ```
59
58
 
@@ -61,9 +60,10 @@ Morph contains also a builtin template storage. Instead of creating variable for
61
60
 
62
61
  ```js
63
62
  // add template to the storage. Automatically builds the render function
64
- morph.add ( 'myTemplate', myTemplateDescription )
63
+ // Array of two elements. 0 - template name, 1 - optional. Storage name. Defaults to 'default'
64
+ morph.add ( ['myTemplate'], myTemplateDescription )
65
65
  // get template from the storage and render it
66
- const htmlBlock = morph.get ( 'myTemplate' )({ name: 'Peter' })
66
+ const htmlBlock = morph.get ( ['myTemplate'] )({ name: 'Peter' })
67
67
  ```
68
68
 
69
69
  Let's see a more complex example before we go into details:
package/dist/morph.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var e=require("@peter.naydenov/walk"),t=require("@peter.naydenov/stack");function r(e){return function t(r){const{TG_PRX:a,TG_SFX:o,TG_SIZE_P:s,TG_SIZE_S:c}=e;let i,l,u,f=[];if("string"!=typeof r)return n("notAString");if(0==r.length)return[];if(i=r.indexOf(a),0<i&&f.push(r.slice(0,i)),-1==i)return f.push(r),f;{if(u=r.indexOf(a,i+s),l=r.indexOf(o),-1==l)return n("missingClosing");if(l<i)return n("closedBeforeOpened");if(l+=c,-1!=u&&u<l)return n("newBeforeClosed");f.push(r.slice(i,l));let e=t(r.slice(l));return f.concat(e)}}}function n(e){switch(e){case"notAString":return"Error: Template is not a string.";case"missingClosing":return"Error: Placeholder with missing closing tag.";case"closedBeforeOpened":return"Error: Placeholder closing tag without starting one.";case"newBeforeClosed":return"Error: Nested placeholders. Close placeholder before open new one.";default:return"Error: Unknown template error."}}function a(t){const r={};let n=0;if(t instanceof Function)return{dataDeepLevel:0,nestedData:[t()]};if(null==t)return{dataDeepLevel:0,nestedData:[null]};if("string"==typeof t)return{dataDeepLevel:0,nestedData:[t]};return e({data:t,objectCallback:function({key:e,value:t,breadcrumbs:a}){let o=!1;return n=a.split("/").length-1,isNaN(e)||(o=!0),r[n]||(r[n]=o?[]:{}),"root"===e?r[n]=t:o?r[n].push(t):r[n][a]=t,t}}),{dataDeepLevel:n,nestedData:r}}var o={TG_PRX:"{{",TG_SFX:"}}",TG_SIZE_P:2,TG_SIZE_S:2};function s(e){return null==e?"null":"string"==typeof e||"number"==typeof e||"boolean"==typeof e?"primitive":"function"==typeof e?"function":e instanceof Array?"array":e instanceof Object?"object":void 0}function c(e,t,n){e instanceof Object&&Object.entries(e).forEach((([t,r])=>{r instanceof Object&&(e[t]=r.text)}));const a="function"==typeof n[t];return e=function(e={}){return"string"==typeof e?{text:e}:e}(e),a?n[t](e):function(e,t){if(null==t)return null;const n=r(o)(e),a=o;return n.forEach(((e,r)=>{if(e.includes(a.TG_PRX)){const o=e.replace(a.TG_PRX,"").replace(a.TG_SFX,"").trim();t[o]&&(n[r]=t[o])}})),n.join("")}(n[t],e)}function i(n,i=!1){const{hasError:l,placeholders:u,chop:f,helpers:d,handshake:p}=function(e){const{template:t,helpers:n={},handshake:a}=e,{TG_PRX:s,TG_SFX:c,TG_SIZE_P:i,TG_SIZE_S:l}=o,u=[];let f=null;const d=r(o)(t);return"string"==typeof d?f=d:d.forEach(((e,t)=>{const r=RegExp(s+"\\s*(.*?)\\s*(?::\\s*(.*?)\\s*)?"+c,"g");if(e.includes(s)){const a=r.exec(e);u.push({index:t,data:(n=a[1],n||null),action:a[2]?a[2].split(",").map((e=>e.trim())):null})}var n})),u.forEach((e=>{e.action&&e.action.every((e=>"#"===e||(e.startsWith("?")&&(e=e.replace("?","")),e.startsWith("+")&&(e=e.replace("+","")),e.startsWith("[]")&&(e=e.replace("[]","")),e.startsWith(">")&&(e=e.replace(">","")),""===e||!!n[e]||(f=`Error: Missing helper: ${e}`,!1))))})),{hasError:f,placeholders:u,chop:d,helpers:n,handshake:a}}(n);if(l){function h(){return l}return i?[!1,h]:h}{let b=structuredClone(f);function m(r={},...n){const o=s(r),i=[];if("null"===o)return b.join("");if("string"==typeof r)switch(r){case"raw":return b.join("");case"demo":if(!p)return"Error: No handshake data.";r=p;break;case"handshake":return p?structuredClone(p):"Error: No handshake data.";case"placeholders":return u.map((e=>b[e.index])).join(", ");default:return`Error: Wrong command "${r}". Available commands: raw, demo, handshake, placeholders.`}return"array"!==o&&(r=[r]),r.forEach((r=>{u.forEach((n=>{const{index:o,data:i,action:l}=n;if(!l&&i){const u=r[i];switch(s(u)){case"function":return void(b[o]=u());case"primitive":return void(b[o]=u);case"array":return void("primitive"===s(u[0])&&(b[o]=u[0]));case"object":return void(u.text&&(b[o]=u.text))}}else{const{dataDeepLevel:f,nestedData:p}=a("@all"===i||null===i||"@root"===i?r:r[i]),h=function*(e,r){let n=t({type:"LIFO"});for(let t=0;t<=r;t++)n.push(e[t]);for(;n&&!n.isEmpty();){let e=yield n.pull();e&&n.push(e)}}(function(e,t=10){let r={},n=0,a=[...e],o=0;do{r[o]=[],o++}while(o<=t);return a.every((e=>"#"===e?(n++,!(n>t)):e.startsWith("?")?(r[n].push({type:"route",name:e.replace("?",""),level:n}),!0):e.startsWith("+")?(r[n].push({type:"extendedRender",name:e.replace("+",""),level:n}),!0):e.startsWith("[]")?(r[n].push({type:"mix",name:e.replace("[]",""),level:n}),!0):e.startsWith(">")?(r[n].push({type:"data",name:e.replace(">",""),level:n}),!0):(""===e||r[n].push({type:"render",name:e,level:n}),!0))),r}(l,f),f);for(let E of h){let{type:v,name:k,level:j}=E,x=p[j],g=s(x);switch(v){case"route":switch(g){case"array":x.forEach(((e,t)=>{if(null==e)return;const r=s(e),n=d[k](e);null!=n&&("object"===r?x[t].text=c(e,n,d):x[t]=c(e,n,d))}));break;case"object":x.text=c(x,routeName,d);break;case"primitive":p[j]=c(x,routeName,d)}break;case"data":switch(g){case"array":x.forEach(((e,t)=>x[t]=e instanceof Function?d[k](e()):d[k](e)));break;case"object":case"primitive":p[j]=d[k](x);break;case"function":p[j]=d[k](x())}break;case"render":const _="function"==typeof d[k];switch(g){case"array":_?x.forEach(((e,t)=>{if(null==e)return;const r=s(e),n=d[k](e);null==n&&(x[t]=null),"object"===r?e.text=n:x[t]=n})):x.forEach(((e,t)=>{if(null==e)return;const r=s(e),n=c(e,k,d);null==n&&(x[t]=null),"object"===r?e.text=n:x[t]=n}));break;case"primitive":p[j]=c(x,k,d);break;case"object":Object.keys(x).find((e=>e.includes("/")))?Object.entries(x).forEach((([e,t])=>t.text=c(t,k,d))):x.text=c(x,k,d)}break;case"extendedRender":"function"==typeof d[k]&&(p[j]=d[k](p[0]));break;case"mix":if(""===k)switch(g){case"object":Object.keys(x).find((e=>e.includes("/")))?Object.entries(x).forEach((([e,t])=>p[j][e]=t.text)):p[j]=x.text;for(let T=j-1;T>=0;T--)p[T]=e({data:p[T],objectCallback:w});function w({value:e,breadcrumbs:t}){return p[j][t]?p[j][t]:e}break;case"array":p[j]=x.map((e=>"object"===s(e)?e.text:e)).filter((e=>null!=e)).join("")}else p[j]=d[k](x)}}let m=s(p[0]),y=p[0];switch(m){case"primitive":if(null==y)return;b[o]=y;break;case"object":if(null==y.text)return;b[o]=y.text;break;case"array":b[o]=y.join("")}}})),i.push(b.join(""))})),"array"===o?i:n?n.reduce(((e,t)=>t(e)),i.join("")):i.join("")}return i?[!0,m]:m}}const l={default:{}};const u={build:i,get:function(e,t="default"){return l[t]?l[t][e]?l[t][e]:function(){return`Error: Template "${e}" does not exist in storage "${t}".`}:function(){return`Error: Storage "${t}" does not exist.`}},add:function(e,t,r="default"){let n=t,a=!0;l[r]||(l[r]={}),"function"!=typeof t&&([a,n]=i(t,!0)),a?l[r][e]=n:console.error(`Error: Template "${e}" looks broken and is not added to storage.`)},list:function(e="default"){return l[e]?Object.keys(l[e]):[]},clear:function(){Object.keys(l).forEach((e=>{"default"!=e?delete l[e]:l.default={}}))},remove:function(e,t="default"){return l[t]?l[t][e]?void delete l[t][e]:`Error: Template "${e}" does not exist in storage "${t}".`:`Error: Storage "${t}" does not exist.`}};module.exports=u;
1
+ "use strict";var e=require("@peter.naydenov/walk"),t=require("@peter.naydenov/stack");function r(e){return function t(r){const{TG_PRX:a,TG_SFX:o,TG_SIZE_P:s,TG_SIZE_S:c}=e;let i,l,u,f=[];if("string"!=typeof r)return n("notAString");if(0==r.length)return[];if(i=r.indexOf(a),0<i&&f.push(r.slice(0,i)),-1==i)return f.push(r),f;{if(u=r.indexOf(a,i+s),l=r.indexOf(o),-1==l)return n("missingClosing");if(l<i)return n("closedBeforeOpened");if(l+=c,-1!=u&&u<l)return n("newBeforeClosed");f.push(r.slice(i,l));let e=t(r.slice(l));return f.concat(e)}}}function n(e){switch(e){case"notAString":return"Error: Template is not a string.";case"missingClosing":return"Error: Placeholder with missing closing tag.";case"closedBeforeOpened":return"Error: Placeholder closing tag without starting one.";case"newBeforeClosed":return"Error: Nested placeholders. Close placeholder before open new one.";default:return"Error: Unknown template error."}}function a(t){const r={};let n=0;if(t instanceof Function)return{dataDeepLevel:0,nestedData:[t()]};if(null==t)return{dataDeepLevel:0,nestedData:[null]};if("string"==typeof t)return{dataDeepLevel:0,nestedData:[t]};return e({data:t,objectCallback:function({key:e,value:t,breadcrumbs:a}){let o=!1;return n=a.split("/").length-1,isNaN(e)||(o=!0),r[n]||(r[n]=o?[]:{}),"root"===e?r[n]=t:o?r[n].push(t):r[n][a]=t,t}}),{dataDeepLevel:n,nestedData:r}}var o={TG_PRX:"{{",TG_SFX:"}}",TG_SIZE_P:2,TG_SIZE_S:2};function s(e){return null==e?"null":"string"==typeof e||"number"==typeof e||"boolean"==typeof e?"primitive":"function"==typeof e?"function":e instanceof Array?"array":e instanceof Object?"object":void 0}function c(e,t,n,...a){e instanceof Object&&Object.entries(e).forEach((([t,r])=>{r instanceof Object&&(e[t]=r.text)}));const s="function"==typeof n[t];return e=function(e={}){return"string"==typeof e?{text:e}:e}(e),s?n[t](e,...a):function(e,t){if(null==t)return null;const n=r(o)(e),a=o;return n.forEach(((e,r)=>{if(e.includes(a.TG_PRX)){const o=e.replace(a.TG_PRX,"").replace(a.TG_SFX,"").trim();t[o]&&(n[r]=t[o])}})),n.join("")}(n[t],e)}function i(n,i=!1,...l){const{hasError:u,placeholders:f,chop:d,helpers:p,handshake:h}=function(e){const{template:t,helpers:n={},handshake:a}=e,{TG_PRX:s,TG_SFX:c,TG_SIZE_P:i,TG_SIZE_S:l}=o,u=[];let f=null;const d=r(o)(t);return"string"==typeof d?f=d:d.forEach(((e,t)=>{const r=RegExp(s+"\\s*(.*?)\\s*(?::\\s*(.*?)\\s*)?"+c,"g");if(e.includes(s)){const a=r.exec(e);u.push({index:t,data:(n=a[1],n||null),action:a[2]?a[2].split(",").map((e=>e.trim())):null})}var n})),u.forEach((e=>{e.action&&e.action.every((e=>"#"===e||(e.startsWith("?")&&(e=e.replace("?","")),e.startsWith("+")&&(e=e.replace("+","")),e.startsWith("[]")&&(e=e.replace("[]","")),e.startsWith(">")&&(e=e.replace(">","")),""===e||!!n[e]||(f=`Error: Missing helper: ${e}`,!1))))})),{hasError:f,placeholders:u,chop:d,helpers:n,handshake:a}}(n);if(u){function b(){return u}return i?[!1,b]:b}{let m=structuredClone(d);function y(r={},...n){const o=s(r),i=[];if("null"===o)return m.join("");if("string"==typeof r)switch(r){case"raw":return m.join("");case"demo":if(!h)return"Error: No handshake data.";r=h;break;case"handshake":return h?structuredClone(h):"Error: No handshake data.";case"placeholders":return f.map((e=>m[e.index])).join(", ");default:return`Error: Wrong command "${r}". Available commands: raw, demo, handshake, placeholders.`}return"array"!==o&&(r=[r]),r.forEach((r=>{f.forEach((o=>{const{index:i,data:u,action:f}=o;if(!f&&u){const d=r[u];switch(s(d)){case"function":return void(m[i]=d());case"primitive":return void(m[i]=d);case"array":return void("primitive"===s(d[0])&&(m[i]=d[0]));case"object":return void(d.text&&(m[i]=d.text))}}else{const{dataDeepLevel:h,nestedData:b}=a("@all"===u||null===u||"@root"===u?r:r[u]),y=function*(e,r){let n=t({type:"LIFO"});for(let t=0;t<=r;t++)n.push(e[t]);for(;n&&!n.isEmpty();){let e=yield n.pull();e&&n.push(e)}}(function(e,t=10){let r={},n=0,a=[...e],o=0;do{r[o]=[],o++}while(o<=t);return a.every((e=>"#"===e?(n++,!(n>t)):e.startsWith("?")?(r[n].push({type:"route",name:e.replace("?",""),level:n}),!0):e.startsWith("+")?(r[n].push({type:"extendedRender",name:e.replace("+",""),level:n}),!0):e.startsWith("[]")?(r[n].push({type:"mix",name:e.replace("[]",""),level:n}),!0):e.startsWith(">")?(r[n].push({type:"data",name:e.replace(">",""),level:n}),!0):(""===e||r[n].push({type:"render",name:e,level:n}),!0))),r}(f,h),h);for(let k of y){let{type:x,name:g,level:j}=k,_=b[j],w=s(_);switch(x){case"route":switch(w){case"array":_.forEach(((e,t)=>{if(null==e)return;const r=s(e),a=p[g](e);null!=a&&("object"===r?_[t].text=c(e,a,p,...l,...n):_[t]=c(e,a,p,...l,...n))}));break;case"object":_.text=c(_,routeName,p,...l,...n);break;case"primitive":b[j]=c(_,routeName,p,...l,...n)}break;case"data":switch(w){case"array":_.forEach(((e,t)=>_[t]=e instanceof Function?p[g](e()):p[g](e)));break;case"object":case"primitive":b[j]=p[g](_);break;case"function":b[j]=p[g](_())}break;case"render":const T="function"==typeof p[g];switch(w){case"array":T?_.forEach(((e,t)=>{if(null==e)return;const r=s(e),n=p[g](e);null==n&&(_[t]=null),"object"===r?e.text=n:_[t]=n})):_.forEach(((e,t)=>{if(null==e)return;const r=s(e),a=c(e,g,p,...l,...n);null==a&&(_[t]=null),"object"===r?e.text=a:_[t]=a}));break;case"primitive":b[j]=c(_,g,p,...l,...n);break;case"object":Object.keys(_).find((e=>e.includes("/")))?Object.entries(_).forEach((([e,t])=>t.text=c(t,g,p,...l,...n))):_.text=c(_,g,p,...l,...n)}break;case"extendedRender":"function"==typeof p[g]&&(b[j]=p[g](b[0]));break;case"mix":if(""===g)switch(w){case"object":Object.keys(_).find((e=>e.includes("/")))?Object.entries(_).forEach((([e,t])=>b[j][e]=t.text)):b[j]=_.text;for(let O=j-1;O>=0;O--)b[O]=e({data:b[O],objectCallback:S});function S({value:e,breadcrumbs:t}){return b[j][t]?b[j][t]:e}break;case"array":b[j]=_.map((e=>"object"===s(e)?e.text:e)).filter((e=>null!=e)).join("")}else b[j]=p[g](_)}}let E=s(b[0]),v=b[0];switch(E){case"primitive":if(null==v)return;m[i]=v;break;case"object":if(null==v.text)return;m[i]=v.text;break;case"array":m[i]=v.join("")}}})),i.push(m.join(""))})),"array"===o?i:i.join("")}return i?[!0,y]:y}}const l={default:{}};const u={build:i,get:function(e,t="default"){return l[t]?l[t][e]?l[t][e]:function(){return`Error: Template "${e}" does not exist in storage "${t}".`}:function(){return`Error: Storage "${t}" does not exist.`}},add:function([e,t="default"],r,...n){let a=r,o=!0;l[strName]||(l[strName]={}),"function"!=typeof r&&([o,a]=i(r,!0,...n)),o?l[strName][e]=a:console.error(`Error: Template "${e}" looks broken and is not added to storage.`)},list:function(e="default"){return l[e]?Object.keys(l[e]):[]},clear:function(){Object.keys(l).forEach((e=>{"default"!=e?delete l[e]:l.default={}}))},remove:function(e,t="default"){return l[t]?l[t][e]?void delete l[t][e]:`Error: Template "${e}" does not exist in storage "${t}".`:`Error: Storage "${t}" does not exist.`}};module.exports=u;
@@ -1 +1 @@
1
- import e from"@peter.naydenov/walk";import t from"@peter.naydenov/stack";function r(e){return function t(r){const{TG_PRX:a,TG_SFX:o,TG_SIZE_P:s,TG_SIZE_S:c}=e;let i,l,u,f=[];if("string"!=typeof r)return n("notAString");if(0==r.length)return[];if(i=r.indexOf(a),0<i&&f.push(r.slice(0,i)),-1==i)return f.push(r),f;{if(u=r.indexOf(a,i+s),l=r.indexOf(o),-1==l)return n("missingClosing");if(l<i)return n("closedBeforeOpened");if(l+=c,-1!=u&&u<l)return n("newBeforeClosed");f.push(r.slice(i,l));let e=t(r.slice(l));return f.concat(e)}}}function n(e){switch(e){case"notAString":return"Error: Template is not a string.";case"missingClosing":return"Error: Placeholder with missing closing tag.";case"closedBeforeOpened":return"Error: Placeholder closing tag without starting one.";case"newBeforeClosed":return"Error: Nested placeholders. Close placeholder before open new one.";default:return"Error: Unknown template error."}}function a(t){const r={};let n=0;if(t instanceof Function)return{dataDeepLevel:0,nestedData:[t()]};if(null==t)return{dataDeepLevel:0,nestedData:[null]};if("string"==typeof t)return{dataDeepLevel:0,nestedData:[t]};return e({data:t,objectCallback:function({key:e,value:t,breadcrumbs:a}){let o=!1;return n=a.split("/").length-1,isNaN(e)||(o=!0),r[n]||(r[n]=o?[]:{}),"root"===e?r[n]=t:o?r[n].push(t):r[n][a]=t,t}}),{dataDeepLevel:n,nestedData:r}}var o={TG_PRX:"{{",TG_SFX:"}}",TG_SIZE_P:2,TG_SIZE_S:2};function s(e){return null==e?"null":"string"==typeof e||"number"==typeof e||"boolean"==typeof e?"primitive":"function"==typeof e?"function":e instanceof Array?"array":e instanceof Object?"object":void 0}function c(e,t,n){e instanceof Object&&Object.entries(e).forEach((([t,r])=>{r instanceof Object&&(e[t]=r.text)}));const a="function"==typeof n[t];return e=function(e={}){return"string"==typeof e?{text:e}:e}(e),a?n[t](e):function(e,t){if(null==t)return null;const n=r(o)(e),a=o;return n.forEach(((e,r)=>{if(e.includes(a.TG_PRX)){const o=e.replace(a.TG_PRX,"").replace(a.TG_SFX,"").trim();t[o]&&(n[r]=t[o])}})),n.join("")}(n[t],e)}function i(n,i=!1){const{hasError:l,placeholders:u,chop:f,helpers:d,handshake:p}=function(e){const{template:t,helpers:n={},handshake:a}=e,{TG_PRX:s,TG_SFX:c,TG_SIZE_P:i,TG_SIZE_S:l}=o,u=[];let f=null;const d=r(o)(t);return"string"==typeof d?f=d:d.forEach(((e,t)=>{const r=RegExp(s+"\\s*(.*?)\\s*(?::\\s*(.*?)\\s*)?"+c,"g");if(e.includes(s)){const a=r.exec(e);u.push({index:t,data:(n=a[1],n||null),action:a[2]?a[2].split(",").map((e=>e.trim())):null})}var n})),u.forEach((e=>{e.action&&e.action.every((e=>"#"===e||(e.startsWith("?")&&(e=e.replace("?","")),e.startsWith("+")&&(e=e.replace("+","")),e.startsWith("[]")&&(e=e.replace("[]","")),e.startsWith(">")&&(e=e.replace(">","")),""===e||!!n[e]||(f=`Error: Missing helper: ${e}`,!1))))})),{hasError:f,placeholders:u,chop:d,helpers:n,handshake:a}}(n);if(l){function h(){return l}return i?[!1,h]:h}{let b=structuredClone(f);function m(r={},...n){const o=s(r),i=[];if("null"===o)return b.join("");if("string"==typeof r)switch(r){case"raw":return b.join("");case"demo":if(!p)return"Error: No handshake data.";r=p;break;case"handshake":return p?structuredClone(p):"Error: No handshake data.";case"placeholders":return u.map((e=>b[e.index])).join(", ");default:return`Error: Wrong command "${r}". Available commands: raw, demo, handshake, placeholders.`}return"array"!==o&&(r=[r]),r.forEach((r=>{u.forEach((n=>{const{index:o,data:i,action:l}=n;if(!l&&i){const u=r[i];switch(s(u)){case"function":return void(b[o]=u());case"primitive":return void(b[o]=u);case"array":return void("primitive"===s(u[0])&&(b[o]=u[0]));case"object":return void(u.text&&(b[o]=u.text))}}else{const{dataDeepLevel:f,nestedData:p}=a("@all"===i||null===i||"@root"===i?r:r[i]),h=function*(e,r){let n=t({type:"LIFO"});for(let t=0;t<=r;t++)n.push(e[t]);for(;n&&!n.isEmpty();){let e=yield n.pull();e&&n.push(e)}}(function(e,t=10){let r={},n=0,a=[...e],o=0;do{r[o]=[],o++}while(o<=t);return a.every((e=>"#"===e?(n++,!(n>t)):e.startsWith("?")?(r[n].push({type:"route",name:e.replace("?",""),level:n}),!0):e.startsWith("+")?(r[n].push({type:"extendedRender",name:e.replace("+",""),level:n}),!0):e.startsWith("[]")?(r[n].push({type:"mix",name:e.replace("[]",""),level:n}),!0):e.startsWith(">")?(r[n].push({type:"data",name:e.replace(">",""),level:n}),!0):(""===e||r[n].push({type:"render",name:e,level:n}),!0))),r}(l,f),f);for(let E of h){let{type:v,name:k,level:j}=E,x=p[j],g=s(x);switch(v){case"route":switch(g){case"array":x.forEach(((e,t)=>{if(null==e)return;const r=s(e),n=d[k](e);null!=n&&("object"===r?x[t].text=c(e,n,d):x[t]=c(e,n,d))}));break;case"object":x.text=c(x,routeName,d);break;case"primitive":p[j]=c(x,routeName,d)}break;case"data":switch(g){case"array":x.forEach(((e,t)=>x[t]=e instanceof Function?d[k](e()):d[k](e)));break;case"object":case"primitive":p[j]=d[k](x);break;case"function":p[j]=d[k](x())}break;case"render":const _="function"==typeof d[k];switch(g){case"array":_?x.forEach(((e,t)=>{if(null==e)return;const r=s(e),n=d[k](e);null==n&&(x[t]=null),"object"===r?e.text=n:x[t]=n})):x.forEach(((e,t)=>{if(null==e)return;const r=s(e),n=c(e,k,d);null==n&&(x[t]=null),"object"===r?e.text=n:x[t]=n}));break;case"primitive":p[j]=c(x,k,d);break;case"object":Object.keys(x).find((e=>e.includes("/")))?Object.entries(x).forEach((([e,t])=>t.text=c(t,k,d))):x.text=c(x,k,d)}break;case"extendedRender":"function"==typeof d[k]&&(p[j]=d[k](p[0]));break;case"mix":if(""===k)switch(g){case"object":Object.keys(x).find((e=>e.includes("/")))?Object.entries(x).forEach((([e,t])=>p[j][e]=t.text)):p[j]=x.text;for(let T=j-1;T>=0;T--)p[T]=e({data:p[T],objectCallback:w});function w({value:e,breadcrumbs:t}){return p[j][t]?p[j][t]:e}break;case"array":p[j]=x.map((e=>"object"===s(e)?e.text:e)).filter((e=>null!=e)).join("")}else p[j]=d[k](x)}}let m=s(p[0]),y=p[0];switch(m){case"primitive":if(null==y)return;b[o]=y;break;case"object":if(null==y.text)return;b[o]=y.text;break;case"array":b[o]=y.join("")}}})),i.push(b.join(""))})),"array"===o?i:n?n.reduce(((e,t)=>t(e)),i.join("")):i.join("")}return i?[!0,m]:m}}const l={default:{}};const u={build:i,get:function(e,t="default"){return l[t]?l[t][e]?l[t][e]:function(){return`Error: Template "${e}" does not exist in storage "${t}".`}:function(){return`Error: Storage "${t}" does not exist.`}},add:function(e,t,r="default"){let n=t,a=!0;l[r]||(l[r]={}),"function"!=typeof t&&([a,n]=i(t,!0)),a?l[r][e]=n:console.error(`Error: Template "${e}" looks broken and is not added to storage.`)},list:function(e="default"){return l[e]?Object.keys(l[e]):[]},clear:function(){Object.keys(l).forEach((e=>{"default"!=e?delete l[e]:l.default={}}))},remove:function(e,t="default"){return l[t]?l[t][e]?void delete l[t][e]:`Error: Template "${e}" does not exist in storage "${t}".`:`Error: Storage "${t}" does not exist.`}};export{u as default};
1
+ import e from"@peter.naydenov/walk";import t from"@peter.naydenov/stack";function r(e){return function t(r){const{TG_PRX:a,TG_SFX:o,TG_SIZE_P:s,TG_SIZE_S:c}=e;let i,l,u,f=[];if("string"!=typeof r)return n("notAString");if(0==r.length)return[];if(i=r.indexOf(a),0<i&&f.push(r.slice(0,i)),-1==i)return f.push(r),f;{if(u=r.indexOf(a,i+s),l=r.indexOf(o),-1==l)return n("missingClosing");if(l<i)return n("closedBeforeOpened");if(l+=c,-1!=u&&u<l)return n("newBeforeClosed");f.push(r.slice(i,l));let e=t(r.slice(l));return f.concat(e)}}}function n(e){switch(e){case"notAString":return"Error: Template is not a string.";case"missingClosing":return"Error: Placeholder with missing closing tag.";case"closedBeforeOpened":return"Error: Placeholder closing tag without starting one.";case"newBeforeClosed":return"Error: Nested placeholders. Close placeholder before open new one.";default:return"Error: Unknown template error."}}function a(t){const r={};let n=0;if(t instanceof Function)return{dataDeepLevel:0,nestedData:[t()]};if(null==t)return{dataDeepLevel:0,nestedData:[null]};if("string"==typeof t)return{dataDeepLevel:0,nestedData:[t]};return e({data:t,objectCallback:function({key:e,value:t,breadcrumbs:a}){let o=!1;return n=a.split("/").length-1,isNaN(e)||(o=!0),r[n]||(r[n]=o?[]:{}),"root"===e?r[n]=t:o?r[n].push(t):r[n][a]=t,t}}),{dataDeepLevel:n,nestedData:r}}var o={TG_PRX:"{{",TG_SFX:"}}",TG_SIZE_P:2,TG_SIZE_S:2};function s(e){return null==e?"null":"string"==typeof e||"number"==typeof e||"boolean"==typeof e?"primitive":"function"==typeof e?"function":e instanceof Array?"array":e instanceof Object?"object":void 0}function c(e,t,n,...a){e instanceof Object&&Object.entries(e).forEach((([t,r])=>{r instanceof Object&&(e[t]=r.text)}));const s="function"==typeof n[t];return e=function(e={}){return"string"==typeof e?{text:e}:e}(e),s?n[t](e,...a):function(e,t){if(null==t)return null;const n=r(o)(e),a=o;return n.forEach(((e,r)=>{if(e.includes(a.TG_PRX)){const o=e.replace(a.TG_PRX,"").replace(a.TG_SFX,"").trim();t[o]&&(n[r]=t[o])}})),n.join("")}(n[t],e)}function i(n,i=!1,...l){const{hasError:u,placeholders:f,chop:d,helpers:p,handshake:h}=function(e){const{template:t,helpers:n={},handshake:a}=e,{TG_PRX:s,TG_SFX:c,TG_SIZE_P:i,TG_SIZE_S:l}=o,u=[];let f=null;const d=r(o)(t);return"string"==typeof d?f=d:d.forEach(((e,t)=>{const r=RegExp(s+"\\s*(.*?)\\s*(?::\\s*(.*?)\\s*)?"+c,"g");if(e.includes(s)){const a=r.exec(e);u.push({index:t,data:(n=a[1],n||null),action:a[2]?a[2].split(",").map((e=>e.trim())):null})}var n})),u.forEach((e=>{e.action&&e.action.every((e=>"#"===e||(e.startsWith("?")&&(e=e.replace("?","")),e.startsWith("+")&&(e=e.replace("+","")),e.startsWith("[]")&&(e=e.replace("[]","")),e.startsWith(">")&&(e=e.replace(">","")),""===e||!!n[e]||(f=`Error: Missing helper: ${e}`,!1))))})),{hasError:f,placeholders:u,chop:d,helpers:n,handshake:a}}(n);if(u){function b(){return u}return i?[!1,b]:b}{let m=structuredClone(d);function y(r={},...n){const o=s(r),i=[];if("null"===o)return m.join("");if("string"==typeof r)switch(r){case"raw":return m.join("");case"demo":if(!h)return"Error: No handshake data.";r=h;break;case"handshake":return h?structuredClone(h):"Error: No handshake data.";case"placeholders":return f.map((e=>m[e.index])).join(", ");default:return`Error: Wrong command "${r}". Available commands: raw, demo, handshake, placeholders.`}return"array"!==o&&(r=[r]),r.forEach((r=>{f.forEach((o=>{const{index:i,data:u,action:f}=o;if(!f&&u){const d=r[u];switch(s(d)){case"function":return void(m[i]=d());case"primitive":return void(m[i]=d);case"array":return void("primitive"===s(d[0])&&(m[i]=d[0]));case"object":return void(d.text&&(m[i]=d.text))}}else{const{dataDeepLevel:h,nestedData:b}=a("@all"===u||null===u||"@root"===u?r:r[u]),y=function*(e,r){let n=t({type:"LIFO"});for(let t=0;t<=r;t++)n.push(e[t]);for(;n&&!n.isEmpty();){let e=yield n.pull();e&&n.push(e)}}(function(e,t=10){let r={},n=0,a=[...e],o=0;do{r[o]=[],o++}while(o<=t);return a.every((e=>"#"===e?(n++,!(n>t)):e.startsWith("?")?(r[n].push({type:"route",name:e.replace("?",""),level:n}),!0):e.startsWith("+")?(r[n].push({type:"extendedRender",name:e.replace("+",""),level:n}),!0):e.startsWith("[]")?(r[n].push({type:"mix",name:e.replace("[]",""),level:n}),!0):e.startsWith(">")?(r[n].push({type:"data",name:e.replace(">",""),level:n}),!0):(""===e||r[n].push({type:"render",name:e,level:n}),!0))),r}(f,h),h);for(let k of y){let{type:x,name:g,level:j}=k,_=b[j],w=s(_);switch(x){case"route":switch(w){case"array":_.forEach(((e,t)=>{if(null==e)return;const r=s(e),a=p[g](e);null!=a&&("object"===r?_[t].text=c(e,a,p,...l,...n):_[t]=c(e,a,p,...l,...n))}));break;case"object":_.text=c(_,routeName,p,...l,...n);break;case"primitive":b[j]=c(_,routeName,p,...l,...n)}break;case"data":switch(w){case"array":_.forEach(((e,t)=>_[t]=e instanceof Function?p[g](e()):p[g](e)));break;case"object":case"primitive":b[j]=p[g](_);break;case"function":b[j]=p[g](_())}break;case"render":const T="function"==typeof p[g];switch(w){case"array":T?_.forEach(((e,t)=>{if(null==e)return;const r=s(e),n=p[g](e);null==n&&(_[t]=null),"object"===r?e.text=n:_[t]=n})):_.forEach(((e,t)=>{if(null==e)return;const r=s(e),a=c(e,g,p,...l,...n);null==a&&(_[t]=null),"object"===r?e.text=a:_[t]=a}));break;case"primitive":b[j]=c(_,g,p,...l,...n);break;case"object":Object.keys(_).find((e=>e.includes("/")))?Object.entries(_).forEach((([e,t])=>t.text=c(t,g,p,...l,...n))):_.text=c(_,g,p,...l,...n)}break;case"extendedRender":"function"==typeof p[g]&&(b[j]=p[g](b[0]));break;case"mix":if(""===g)switch(w){case"object":Object.keys(_).find((e=>e.includes("/")))?Object.entries(_).forEach((([e,t])=>b[j][e]=t.text)):b[j]=_.text;for(let O=j-1;O>=0;O--)b[O]=e({data:b[O],objectCallback:S});function S({value:e,breadcrumbs:t}){return b[j][t]?b[j][t]:e}break;case"array":b[j]=_.map((e=>"object"===s(e)?e.text:e)).filter((e=>null!=e)).join("")}else b[j]=p[g](_)}}let E=s(b[0]),v=b[0];switch(E){case"primitive":if(null==v)return;m[i]=v;break;case"object":if(null==v.text)return;m[i]=v.text;break;case"array":m[i]=v.join("")}}})),i.push(m.join(""))})),"array"===o?i:i.join("")}return i?[!0,y]:y}}const l={default:{}};const u={build:i,get:function(e,t="default"){return l[t]?l[t][e]?l[t][e]:function(){return`Error: Template "${e}" does not exist in storage "${t}".`}:function(){return`Error: Storage "${t}" does not exist.`}},add:function([e,t="default"],r,...n){let a=r,o=!0;l[strName]||(l[strName]={}),"function"!=typeof r&&([o,a]=i(r,!0,...n)),o?l[strName][e]=a:console.error(`Error: Template "${e}" looks broken and is not added to storage.`)},list:function(e="default"){return l[e]?Object.keys(l[e]):[]},clear:function(){Object.keys(l).forEach((e=>{"default"!=e?delete l[e]:l.default={}}))},remove:function(e,t="default"){return l[t]?l[t][e]?void delete l[t][e]:`Error: Template "${e}" does not exist in storage "${t}".`:`Error: Storage "${t}" does not exist.`}};export{u as default};
package/dist/morph.umd.js CHANGED
@@ -1 +1 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("@peter.naydenov/walk")):"function"==typeof define&&define.amd?define(["@peter.naydenov/walk"],t):(e="undefined"!=typeof globalThis?globalThis:e||self).morph=t(e.walk)}(this,(function(e){"use strict";function t(e){return function t(n){const{TG_PRX:o,TG_SFX:a,TG_SIZE_P:i,TG_SIZE_S:l}=e;let s,c,u,f=[];if("string"!=typeof n)return r("notAString");if(0==n.length)return[];if(s=n.indexOf(o),0<s&&f.push(n.slice(0,s)),-1==s)return f.push(n),f;{if(u=n.indexOf(o,s+i),c=n.indexOf(a),-1==c)return r("missingClosing");if(c<s)return r("closedBeforeOpened");if(c+=l,-1!=u&&u<c)return r("newBeforeClosed");f.push(n.slice(s,c));let e=t(n.slice(c));return f.concat(e)}}}function r(e){switch(e){case"notAString":return"Error: Template is not a string.";case"missingClosing":return"Error: Placeholder with missing closing tag.";case"closedBeforeOpened":return"Error: Placeholder closing tag without starting one.";case"newBeforeClosed":return"Error: Nested placeholders. Close placeholder before open new one.";default:return"Error: Unknown template error."}}function n(t){const r={};let n=0;if(t instanceof Function)return{dataDeepLevel:0,nestedData:[t()]};if(null==t)return{dataDeepLevel:0,nestedData:[null]};if("string"==typeof t)return{dataDeepLevel:0,nestedData:[t]};return e({data:t,objectCallback:function({key:e,value:t,breadcrumbs:o}){let a=!1;return n=o.split("/").length-1,isNaN(e)||(a=!0),r[n]||(r[n]=a?[]:{}),"root"===e?r[n]=t:a?r[n].push(t):r[n][o]=t,t}}),{dataDeepLevel:n,nestedData:r}}function*o(e,t){let r=function(e={}){let t=[],{type:r,limit:n,onLimit:o}=Object.assign({},{type:"FIFO",limit:!1,onLimit:"update"},e),a="LIFO"===r.toUpperCase(),i=!1;function l(e=1,r=0){let n=[];return r>0&&Array.from({length:r}).map((()=>t.pop())),1==e?t.pop():(Array.from({length:e}).map((()=>{let e=t.pop();null!=e&&n.push(e)})),n)}function s(e=1,r=0){let n=[],o=t.length-r;return e>1&&Array.from({length:e}).map((()=>{null!=t[o-1]&&n.push(t[o-1]),o--})),1==e?t[t.length-1]:n}function c(){}return c.prototype={pull:l,pullReverse:function(e=1,t=0){let r=l(e,t);return r instanceof Array?r.reverse():r},peek:s,peekReverse:function(e=1,t=0){const r=s(e,t);return r instanceof Array?r.reverse():r},getSize:()=>t.length,isEmpty:()=>0==t.length,reset:()=>(t=[],!0),debug:()=>[...t]},c.prototype.push=a?function(e){const r=e instanceof Array,a=r?e.length:1;let s=!1;if("full"!==o||!i){if(n&&r&&a>n&&(e=e.slice(0,-a+n)),n){const a=(r?e.length:1)+t.length;a>=n&&"full"===o&&(e=e.slice(0,-(a-n))),a>=n&&"update"===o&&(s=l(a-n))}return t=e instanceof Array?t.concat(e):t.concat([e]),i=!!n&&t.length===n,s||void 0}}:function(e){const r=e instanceof Array,a=r?e.length:1;let s=!1;if("full"!==o||!i){if(n&&r&&a>n&&(e=e.slice(a-n)),n){const a=(r?e.length:1)+t.length;a>=n&&"full"===o&&(e=e.slice(0,-(a-n))),a>=n&&"update"===o&&(s=l(a-n))}return t=r?e.reduce(((e,t)=>[t,...e]),t):[e].reduce(((e,t)=>[t,...e]),t),i=!!n&&t.length===n,s||void 0}},new c}({type:"LIFO"});for(let n=0;n<=t;n++)r.push(e[n]);for(;r&&!r.isEmpty();){let e=yield r.pull();e&&r.push(e)}}var a={TG_PRX:"{{",TG_SFX:"}}",TG_SIZE_P:2,TG_SIZE_S:2};function i(e){return null==e?"null":"string"==typeof e||"number"==typeof e||"boolean"==typeof e?"primitive":"function"==typeof e?"function":e instanceof Array?"array":e instanceof Object?"object":void 0}function l(e,r,n){e instanceof Object&&Object.entries(e).forEach((([t,r])=>{r instanceof Object&&(e[t]=r.text)}));const o="function"==typeof n[r];return e=function(e={}){return"string"==typeof e?{text:e}:e}(e),o?n[r](e):function(e,r){if(null==r)return null;const n=t(a)(e),o=a;return n.forEach(((e,t)=>{if(e.includes(o.TG_PRX)){const a=e.replace(o.TG_PRX,"").replace(o.TG_SFX,"").trim();r[a]&&(n[t]=r[a])}})),n.join("")}(n[r],e)}function s(r,s=!1){const{hasError:c,placeholders:u,chop:f,helpers:p,handshake:d}=function(e){const{template:r,helpers:n={},handshake:o}=e,{TG_PRX:i,TG_SFX:l,TG_SIZE_P:s,TG_SIZE_S:c}=a,u=[];let f=null;const p=t(a)(r);return"string"==typeof p?f=p:p.forEach(((e,t)=>{const r=RegExp(i+"\\s*(.*?)\\s*(?::\\s*(.*?)\\s*)?"+l,"g");if(e.includes(i)){const o=r.exec(e);u.push({index:t,data:(n=o[1],n||null),action:o[2]?o[2].split(",").map((e=>e.trim())):null})}var n})),u.forEach((e=>{e.action&&e.action.every((e=>"#"===e||(e.startsWith("?")&&(e=e.replace("?","")),e.startsWith("+")&&(e=e.replace("+","")),e.startsWith("[]")&&(e=e.replace("[]","")),e.startsWith(">")&&(e=e.replace(">","")),""===e||!!n[e]||(f=`Error: Missing helper: ${e}`,!1))))})),{hasError:f,placeholders:u,chop:p,helpers:n,handshake:o}}(r);if(c){function h(){return c}return s?[!1,h]:h}{let y=structuredClone(f);function m(t={},...r){const a=i(t),s=[];if("null"===a)return y.join("");if("string"==typeof t)switch(t){case"raw":return y.join("");case"demo":if(!d)return"Error: No handshake data.";t=d;break;case"handshake":return d?structuredClone(d):"Error: No handshake data.";case"placeholders":return u.map((e=>y[e.index])).join(", ");default:return`Error: Wrong command "${t}". Available commands: raw, demo, handshake, placeholders.`}return"array"!==a&&(t=[t]),t.forEach((t=>{u.forEach((r=>{const{index:a,data:s,action:c}=r;if(!c&&s){const u=t[s];switch(i(u)){case"function":return void(y[a]=u());case"primitive":return void(y[a]=u);case"array":return void("primitive"===i(u[0])&&(y[a]=u[0]));case"object":return void(u.text&&(y[a]=u.text))}}else{const{dataDeepLevel:f,nestedData:d}=n("@all"===s||null===s||"@root"===s?t:t[s]),h=o(function(e,t=10){let r={},n=0,o=[...e],a=0;do{r[a]=[],a++}while(a<=t);return o.every((e=>"#"===e?(n++,!(n>t)):e.startsWith("?")?(r[n].push({type:"route",name:e.replace("?",""),level:n}),!0):e.startsWith("+")?(r[n].push({type:"extendedRender",name:e.replace("+",""),level:n}),!0):e.startsWith("[]")?(r[n].push({type:"mix",name:e.replace("[]",""),level:n}),!0):e.startsWith(">")?(r[n].push({type:"data",name:e.replace(">",""),level:n}),!0):(""===e||r[n].push({type:"render",name:e,level:n}),!0))),r}(c,f),f);for(let g of h){let{type:v,name:E,level:k}=g,j=d[k],x=i(j);switch(v){case"route":switch(x){case"array":j.forEach(((e,t)=>{if(null==e)return;const r=i(e),n=p[E](e);null!=n&&("object"===r?j[t].text=l(e,n,p):j[t]=l(e,n,p))}));break;case"object":j.text=l(j,routeName,p);break;case"primitive":d[k]=l(j,routeName,p)}break;case"data":switch(x){case"array":j.forEach(((e,t)=>j[t]=e instanceof Function?p[E](e()):p[E](e)));break;case"object":case"primitive":d[k]=p[E](j);break;case"function":d[k]=p[E](j())}break;case"render":const w="function"==typeof p[E];switch(x){case"array":w?j.forEach(((e,t)=>{if(null==e)return;const r=i(e),n=p[E](e);null==n&&(j[t]=null),"object"===r?e.text=n:j[t]=n})):j.forEach(((e,t)=>{if(null==e)return;const r=i(e),n=l(e,E,p);null==n&&(j[t]=null),"object"===r?e.text=n:j[t]=n}));break;case"primitive":d[k]=l(j,E,p);break;case"object":Object.keys(j).find((e=>e.includes("/")))?Object.entries(j).forEach((([e,t])=>t.text=l(t,E,p))):j.text=l(j,E,p)}break;case"extendedRender":"function"==typeof p[E]&&(d[k]=p[E](d[0]));break;case"mix":if(""===E)switch(x){case"object":Object.keys(j).find((e=>e.includes("/")))?Object.entries(j).forEach((([e,t])=>d[k][e]=t.text)):d[k]=j.text;for(let _=k-1;_>=0;_--)d[_]=e({data:d[_],objectCallback:T});function T({value:e,breadcrumbs:t}){return d[k][t]?d[k][t]:e}break;case"array":d[k]=j.map((e=>"object"===i(e)?e.text:e)).filter((e=>null!=e)).join("")}else d[k]=p[E](j)}}let m=i(d[0]),b=d[0];switch(m){case"primitive":if(null==b)return;y[a]=b;break;case"object":if(null==b.text)return;y[a]=b.text;break;case"array":y[a]=b.join("")}}})),s.push(y.join(""))})),"array"===a?s:r?r.reduce(((e,t)=>t(e)),s.join("")):s.join("")}return s?[!0,m]:m}}const c={default:{}};return{build:s,get:function(e,t="default"){return c[t]?c[t][e]?c[t][e]:function(){return`Error: Template "${e}" does not exist in storage "${t}".`}:function(){return`Error: Storage "${t}" does not exist.`}},add:function(e,t,r="default"){let n=t,o=!0;c[r]||(c[r]={}),"function"!=typeof t&&([o,n]=s(t,!0)),o?c[r][e]=n:console.error(`Error: Template "${e}" looks broken and is not added to storage.`)},list:function(e="default"){return c[e]?Object.keys(c[e]):[]},clear:function(){Object.keys(c).forEach((e=>{"default"!=e?delete c[e]:c.default={}}))},remove:function(e,t="default"){return c[t]?c[t][e]?void delete c[t][e]:`Error: Template "${e}" does not exist in storage "${t}".`:`Error: Storage "${t}" does not exist.`}}}));
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("@peter.naydenov/walk")):"function"==typeof define&&define.amd?define(["@peter.naydenov/walk"],t):(e="undefined"!=typeof globalThis?globalThis:e||self).morph=t(e.walk)}(this,(function(e){"use strict";function t(e){return function t(n){const{TG_PRX:o,TG_SFX:a,TG_SIZE_P:i,TG_SIZE_S:s}=e;let l,c,u,f=[];if("string"!=typeof n)return r("notAString");if(0==n.length)return[];if(l=n.indexOf(o),0<l&&f.push(n.slice(0,l)),-1==l)return f.push(n),f;{if(u=n.indexOf(o,l+i),c=n.indexOf(a),-1==c)return r("missingClosing");if(c<l)return r("closedBeforeOpened");if(c+=s,-1!=u&&u<c)return r("newBeforeClosed");f.push(n.slice(l,c));let e=t(n.slice(c));return f.concat(e)}}}function r(e){switch(e){case"notAString":return"Error: Template is not a string.";case"missingClosing":return"Error: Placeholder with missing closing tag.";case"closedBeforeOpened":return"Error: Placeholder closing tag without starting one.";case"newBeforeClosed":return"Error: Nested placeholders. Close placeholder before open new one.";default:return"Error: Unknown template error."}}function n(t){const r={};let n=0;if(t instanceof Function)return{dataDeepLevel:0,nestedData:[t()]};if(null==t)return{dataDeepLevel:0,nestedData:[null]};if("string"==typeof t)return{dataDeepLevel:0,nestedData:[t]};return e({data:t,objectCallback:function({key:e,value:t,breadcrumbs:o}){let a=!1;return n=o.split("/").length-1,isNaN(e)||(a=!0),r[n]||(r[n]=a?[]:{}),"root"===e?r[n]=t:a?r[n].push(t):r[n][o]=t,t}}),{dataDeepLevel:n,nestedData:r}}function*o(e,t){let r=function(e={}){let t=[],{type:r,limit:n,onLimit:o}=Object.assign({},{type:"FIFO",limit:!1,onLimit:"update"},e),a="LIFO"===r.toUpperCase(),i=!1;function s(e=1,r=0){let n=[];return r>0&&Array.from({length:r}).map((()=>t.pop())),1==e?t.pop():(Array.from({length:e}).map((()=>{let e=t.pop();null!=e&&n.push(e)})),n)}function l(e=1,r=0){let n=[],o=t.length-r;return e>1&&Array.from({length:e}).map((()=>{null!=t[o-1]&&n.push(t[o-1]),o--})),1==e?t[t.length-1]:n}function c(){}return c.prototype={pull:s,pullReverse:function(e=1,t=0){let r=s(e,t);return r instanceof Array?r.reverse():r},peek:l,peekReverse:function(e=1,t=0){const r=l(e,t);return r instanceof Array?r.reverse():r},getSize:()=>t.length,isEmpty:()=>0==t.length,reset:()=>(t=[],!0),debug:()=>[...t]},c.prototype.push=a?function(e){const r=e instanceof Array,a=r?e.length:1;let l=!1;if("full"!==o||!i){if(n&&r&&a>n&&(e=e.slice(0,-a+n)),n){const a=(r?e.length:1)+t.length;a>=n&&"full"===o&&(e=e.slice(0,-(a-n))),a>=n&&"update"===o&&(l=s(a-n))}return t=e instanceof Array?t.concat(e):t.concat([e]),i=!!n&&t.length===n,l||void 0}}:function(e){const r=e instanceof Array,a=r?e.length:1;let l=!1;if("full"!==o||!i){if(n&&r&&a>n&&(e=e.slice(a-n)),n){const a=(r?e.length:1)+t.length;a>=n&&"full"===o&&(e=e.slice(0,-(a-n))),a>=n&&"update"===o&&(l=s(a-n))}return t=r?e.reduce(((e,t)=>[t,...e]),t):[e].reduce(((e,t)=>[t,...e]),t),i=!!n&&t.length===n,l||void 0}},new c}({type:"LIFO"});for(let n=0;n<=t;n++)r.push(e[n]);for(;r&&!r.isEmpty();){let e=yield r.pull();e&&r.push(e)}}var a={TG_PRX:"{{",TG_SFX:"}}",TG_SIZE_P:2,TG_SIZE_S:2};function i(e){return null==e?"null":"string"==typeof e||"number"==typeof e||"boolean"==typeof e?"primitive":"function"==typeof e?"function":e instanceof Array?"array":e instanceof Object?"object":void 0}function s(e,r,n,...o){e instanceof Object&&Object.entries(e).forEach((([t,r])=>{r instanceof Object&&(e[t]=r.text)}));const i="function"==typeof n[r];return e=function(e={}){return"string"==typeof e?{text:e}:e}(e),i?n[r](e,...o):function(e,r){if(null==r)return null;const n=t(a)(e),o=a;return n.forEach(((e,t)=>{if(e.includes(o.TG_PRX)){const a=e.replace(o.TG_PRX,"").replace(o.TG_SFX,"").trim();r[a]&&(n[t]=r[a])}})),n.join("")}(n[r],e)}function l(r,l=!1,...c){const{hasError:u,placeholders:f,chop:p,helpers:d,handshake:h}=function(e){const{template:r,helpers:n={},handshake:o}=e,{TG_PRX:i,TG_SFX:s,TG_SIZE_P:l,TG_SIZE_S:c}=a,u=[];let f=null;const p=t(a)(r);return"string"==typeof p?f=p:p.forEach(((e,t)=>{const r=RegExp(i+"\\s*(.*?)\\s*(?::\\s*(.*?)\\s*)?"+s,"g");if(e.includes(i)){const o=r.exec(e);u.push({index:t,data:(n=o[1],n||null),action:o[2]?o[2].split(",").map((e=>e.trim())):null})}var n})),u.forEach((e=>{e.action&&e.action.every((e=>"#"===e||(e.startsWith("?")&&(e=e.replace("?","")),e.startsWith("+")&&(e=e.replace("+","")),e.startsWith("[]")&&(e=e.replace("[]","")),e.startsWith(">")&&(e=e.replace(">","")),""===e||!!n[e]||(f=`Error: Missing helper: ${e}`,!1))))})),{hasError:f,placeholders:u,chop:p,helpers:n,handshake:o}}(r);if(u){function m(){return u}return l?[!1,m]:m}{let y=structuredClone(p);function b(t={},...r){const a=i(t),l=[];if("null"===a)return y.join("");if("string"==typeof t)switch(t){case"raw":return y.join("");case"demo":if(!h)return"Error: No handshake data.";t=h;break;case"handshake":return h?structuredClone(h):"Error: No handshake data.";case"placeholders":return f.map((e=>y[e.index])).join(", ");default:return`Error: Wrong command "${t}". Available commands: raw, demo, handshake, placeholders.`}return"array"!==a&&(t=[t]),t.forEach((t=>{f.forEach((a=>{const{index:l,data:u,action:f}=a;if(!f&&u){const p=t[u];switch(i(p)){case"function":return void(y[l]=p());case"primitive":return void(y[l]=p);case"array":return void("primitive"===i(p[0])&&(y[l]=p[0]));case"object":return void(p.text&&(y[l]=p.text))}}else{const{dataDeepLevel:h,nestedData:m}=n("@all"===u||null===u||"@root"===u?t:t[u]),b=o(function(e,t=10){let r={},n=0,o=[...e],a=0;do{r[a]=[],a++}while(a<=t);return o.every((e=>"#"===e?(n++,!(n>t)):e.startsWith("?")?(r[n].push({type:"route",name:e.replace("?",""),level:n}),!0):e.startsWith("+")?(r[n].push({type:"extendedRender",name:e.replace("+",""),level:n}),!0):e.startsWith("[]")?(r[n].push({type:"mix",name:e.replace("[]",""),level:n}),!0):e.startsWith(">")?(r[n].push({type:"data",name:e.replace(">",""),level:n}),!0):(""===e||r[n].push({type:"render",name:e,level:n}),!0))),r}(f,h),h);for(let E of b){let{type:k,name:j,level:x}=E,w=m[x],T=i(w);switch(k){case"route":switch(T){case"array":w.forEach(((e,t)=>{if(null==e)return;const n=i(e),o=d[j](e);null!=o&&("object"===n?w[t].text=s(e,o,d,...c,...r):w[t]=s(e,o,d,...c,...r))}));break;case"object":w.text=s(w,routeName,d,...c,...r);break;case"primitive":m[x]=s(w,routeName,d,...c,...r)}break;case"data":switch(T){case"array":w.forEach(((e,t)=>w[t]=e instanceof Function?d[j](e()):d[j](e)));break;case"object":case"primitive":m[x]=d[j](w);break;case"function":m[x]=d[j](w())}break;case"render":const _="function"==typeof d[j];switch(T){case"array":_?w.forEach(((e,t)=>{if(null==e)return;const r=i(e),n=d[j](e);null==n&&(w[t]=null),"object"===r?e.text=n:w[t]=n})):w.forEach(((e,t)=>{if(null==e)return;const n=i(e),o=s(e,j,d,...c,...r);null==o&&(w[t]=null),"object"===n?e.text=o:w[t]=o}));break;case"primitive":m[x]=s(w,j,d,...c,...r);break;case"object":Object.keys(w).find((e=>e.includes("/")))?Object.entries(w).forEach((([e,t])=>t.text=s(t,j,d,...c,...r))):w.text=s(w,j,d,...c,...r)}break;case"extendedRender":"function"==typeof d[j]&&(m[x]=d[j](m[0]));break;case"mix":if(""===j)switch(T){case"object":Object.keys(w).find((e=>e.includes("/")))?Object.entries(w).forEach((([e,t])=>m[x][e]=t.text)):m[x]=w.text;for(let S=x-1;S>=0;S--)m[S]=e({data:m[S],objectCallback:O});function O({value:e,breadcrumbs:t}){return m[x][t]?m[x][t]:e}break;case"array":m[x]=w.map((e=>"object"===i(e)?e.text:e)).filter((e=>null!=e)).join("")}else m[x]=d[j](w)}}let g=i(m[0]),v=m[0];switch(g){case"primitive":if(null==v)return;y[l]=v;break;case"object":if(null==v.text)return;y[l]=v.text;break;case"array":y[l]=v.join("")}}})),l.push(y.join(""))})),"array"===a?l:l.join("")}return l?[!0,b]:b}}const c={default:{}};return{build:l,get:function(e,t="default"){return c[t]?c[t][e]?c[t][e]:function(){return`Error: Template "${e}" does not exist in storage "${t}".`}:function(){return`Error: Storage "${t}" does not exist.`}},add:function([e,t="default"],r,...n){let o=r,a=!0;c[strName]||(c[strName]={}),"function"!=typeof r&&([a,o]=l(r,!0,...n)),a?c[strName][e]=o:console.error(`Error: Template "${e}" looks broken and is not added to storage.`)},list:function(e="default"){return c[e]?Object.keys(c[e]):[]},clear:function(){Object.keys(c).forEach((e=>{"default"!=e?delete c[e]:c.default={}}))},remove:function(e,t="default"){return c[t]?c[t][e]?void delete c[t][e]:`Error: Template "${e}" does not exist in storage "${t}".`:`Error: Storage "${t}" does not exist.`}}}));
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@peter.naydenov/morph",
3
3
  "description": "Template engine",
4
- "version": "0.0.4",
4
+ "version": "1.0.0",
5
5
  "license": "MIT",
6
6
  "author": "Peter Naydenov",
7
- "main": "./dist/morph.umd.js",
7
+ "main": ".src/main.js",
8
8
  "type": "module",
9
9
  "exports": {
10
10
  ".": {
11
- "import": "./dist/morph.esm.mjs",
11
+ "import": "./src/main.js",
12
12
  "require": "./dist/morph.cjs",
13
- "default": "./dist/morph.umd.js"
13
+ "default": "./src/main.js"
14
14
  },
15
15
  "./package.json": "./package.json",
16
16
  "./dist/*": "./dist/*",
package/src/main.js CHANGED
@@ -7,6 +7,7 @@
7
7
  * History notes:
8
8
  * - Idea was born on October 28th, 2024.
9
9
  * - Published on GitHub for first time: November 30th, 2024
10
+ * - Version 1.0.0: December 28st, 2024
10
11
  *
11
12
  */
12
13
 
@@ -15,11 +16,26 @@ import build from "./methods/build.js"
15
16
 
16
17
 
17
18
 
18
- const storage = { default: {}};
19
+ const storage = ( () => ({default: {}}) ) ();
19
20
 
20
21
 
21
22
 
22
- function get ( prop, strName='default' ) {
23
+
24
+
25
+
26
+ /**
27
+ * Get a template from a storage.
28
+ *
29
+ * @param {string[]} location - The location of the template. Array of two elements.
30
+ * The first element is the name of the template. The second element
31
+ * is optional and is the name of the storage. Defaults to 'default'.
32
+ *
33
+ * @returns {function } The template (a render function) if it exists in the storage.
34
+ * An function that returns an error message if
35
+ * either the storage or template does not exist.
36
+ */
37
+ function get ( location ) {
38
+ const [prop, strName='default'] = location;
23
39
  if ( !storage[strName] ) {
24
40
  return function () {
25
41
  return `Error: Storage "${strName}" does not exist.`
@@ -35,25 +51,63 @@ function get ( prop, strName='default' ) {
35
51
 
36
52
 
37
53
 
38
- function add ( name, tplfn, strName='default' ) {
54
+
55
+
56
+
57
+
58
+ /**
59
+ * Add a template to a storage.
60
+ *
61
+ * If the template is already a function, it is added to the storage.
62
+ * If the template is a template description (an object), it is built and
63
+ * added to the storage.
64
+ * If the template is broken, an error message is printed in the console
65
+ * and the template is not added to the storage.
66
+ *
67
+ * @param {string[]} location - The location to add the template to. Array of two elements.
68
+ * The first element is the name of the template. The second element
69
+ * is optional and is the name of the storage. Defaults to 'default'.
70
+ * @param {object|function} tplfn - The template description or the already built template function.
71
+ * @param {...any} args - Additional arguments to be passed to the build function.
72
+ * Only used if the first argument is a template description.
73
+ */
74
+ function add ( location, tplfn, ...args ) {
75
+ const [ name, strName='default'] = location
39
76
  let fn = tplfn;
40
77
  let successBuild = true;
41
78
  if( !storage[strName] ) storage[strName] = {}
42
- if ( typeof tplfn !== 'function' ) [ successBuild, fn ] = build ( tplfn, true )
43
-
79
+ if ( typeof tplfn !== 'function' ) {
80
+ let r = build ( tplfn, true, ...args )
81
+ successBuild = r[0]
82
+ fn = r[1]
83
+ }
44
84
  if ( successBuild ) storage[strName][name] = fn
45
85
  else console.error ( `Error: Template "${name}" looks broken and is not added to storage.` )
46
86
  } // add func.
47
87
 
48
88
 
49
89
 
50
- function list ( strName='default' ) {
51
- if ( !storage[strName] ) return []
52
- return Object.keys ( storage[strName] )
90
+ /**
91
+ * Returns an array of all the names of the templates in the given storages.
92
+ * No arguments - will return the list of templates in the 'default' storage.
93
+ *
94
+ * @param {string[]} [storageNames=['default']] - The names of the storages to retrieve template names from;
95
+ * @returns {string[]} An array of all the template names in the given storages;
96
+ */
97
+ function list ( storageNames=['default'] ) {
98
+ let r = storageNames.map ( strName => {
99
+ if ( !storage[strName] ) return []
100
+ else return Object.keys ( storage[strName])
101
+ })
102
+ return r.flat ()
53
103
  } // list func.
54
104
 
55
105
 
56
106
 
107
+ /**
108
+ * Clears all templates from the storages.
109
+ * This function deletes all storages. Storage 'default' will be reset to an empty object.
110
+ */
57
111
  function clear ( ) {
58
112
  const keys = Object.keys ( storage )
59
113
  keys.forEach ( key => {
@@ -64,28 +118,26 @@ function clear ( ) {
64
118
 
65
119
 
66
120
 
67
- function remove ( name, strName='default' ) {
121
+
122
+ /**
123
+ * Removes a template from the storage.
124
+ *
125
+ * @param {string[]} location - The location to remove the template from. Array of two elements.
126
+ * The first element is the name of the template. The second element
127
+ * is optional and is the name of the storage. Defaults to 'default'.
128
+ *
129
+ * @returns {void|string} An error message if the storage or template does not exist.
130
+ */
131
+ function remove ( location ) {
132
+ const [name, strName='default'] = location;
68
133
  if ( !storage[strName] ) return `Error: Storage "${strName}" does not exist.`
69
134
  if ( !storage[strName][name] ) return `Error: Template "${name}" does not exist in storage "${strName}".`
70
135
  delete storage[strName][name]
71
136
  } // remove func.
72
137
 
73
138
 
74
-
139
+ // Engine API
75
140
  const morphAPI = {
76
- // Engine API
77
- /**
78
- *
79
- * build -
80
- * add - register a component to component storage
81
- * get - get a component from component storage
82
- * list - list all components in component storage
83
- * clear - clear all templates in component storage
84
- * remove - remove a template from component storage
85
- *
86
- * shine - extra step to remove all non used placeholders and <rs> tags
87
- *
88
- */
89
141
  build // build a component from template description
90
142
  , get // get a component from component storage
91
143
  , add // add a component to component storage
@@ -94,8 +146,7 @@ const morphAPI = {
94
146
  , remove // remove a template from component storage
95
147
  } // morphAPI
96
148
 
97
- // TODO: How to change render templates on condition?
98
- // - Use compiled versions of simile templates
149
+
99
150
 
100
151
  export default morphAPI
101
152
 
@@ -10,9 +10,22 @@ import render from './render.js'
10
10
 
11
11
  import walk from '@peter.naydenov/walk'
12
12
 
13
+ /**
14
+ * @typedef {Object} Template
15
+ * @property {string} template - Data to be rendered;
16
+ * @property {object} [helpers] - Optional. Object with helper functions or simple templates for this template;
17
+ * @property {object} [handshake] - Optional. Example for data to be rendered with;
18
+ */
13
19
 
14
20
 
15
- function build ( tpl, extra=false ) {
21
+ /**
22
+ *
23
+ * @param {Template} tpl - template definition;
24
+ * @param {boolean} [extra] - Optional. How to receive the answer - faslse:as a string(answer) or tuple[success, answer];
25
+ * @param {object} [buildDependencies] - Optional. External dependencies injected;
26
+ * @returns {function} - rendering function
27
+ */
28
+ function build ( tpl, extra=false, buildDependencies={} ) {
16
29
  const { hasError, placeholders, chop, helpers, handshake } = _readTemplate ( tpl );
17
30
  if ( hasError ) {
18
31
  function fail () { return hasError }
@@ -22,7 +35,23 @@ import walk from '@peter.naydenov/walk'
22
35
  let cuts = structuredClone ( chop );
23
36
  // *** Template recognition complete. Start building the rendering function -->
24
37
 
25
- function success ( d={}, ...args ) {
38
+ /**
39
+ * Function to render a template with data.
40
+ * @param {Object} [d={}] - The data to render with. If string, it's a command.
41
+ * @param {Object} [dependencies={}] - The dependencies to use for the rendering.
42
+ * @param {...any} args - The postprocessing functions to apply to the result.
43
+ * @returns {string|string[]} The rendered template.
44
+ * @description
45
+ * If 'd' is a string, it's a command. The available commands are:
46
+ * - 'raw' - returns the original template with placeholders
47
+ * - 'demo' - renders the template with the handshake data
48
+ * - 'handshake' - returns a copy of the handshake data
49
+ * - 'placeholders' - returns the placeholders as a comma separated string
50
+ * If 'd' is an object, it's the data to render with. If it's an array, it's an array of objects to render with.
51
+ * The function returns the rendered template.
52
+ * If 'args' are provided, they are applied to the result in order.
53
+ */
54
+ function success ( d={}, dependencies={}, ...args ) {
26
55
  const
27
56
  topLevelType = _defineDataType ( d )
28
57
  , endData = []
@@ -98,15 +127,15 @@ import walk from '@peter.naydenov/walk'
98
127
  const dType = _defineDataType ( d )
99
128
  const routeName = helpers[name]( d );
100
129
  if ( routeName == null ) return
101
- if ( dType === 'object' ) theData[i]['text'] = render ( d, routeName, helpers )
102
- else theData[i] = render ( d, routeName, helpers )
130
+ if ( dType === 'object' ) theData[i]['text'] = render ( d, routeName, helpers, {...buildDependencies, ...dependencies} )
131
+ else theData[i] = render ( d, routeName, helpers, {...buildDependencies, ...dependencies} )
103
132
  })
104
133
  break
105
134
  case 'object':
106
- theData['text'] = render ( theData, routeName, helpers )
135
+ theData['text'] = render ( theData, name, helpers, {...buildDependencies, ...dependencies} )
107
136
  break
108
137
  case 'primitive':
109
- nestedData[level] = render ( theData, routeName, helpers )
138
+ nestedData[level] = render ( theData, name, helpers, {...buildDependencies, ...dependencies} )
110
139
  break
111
140
  }
112
141
  break
@@ -143,7 +172,7 @@ import walk from '@peter.naydenov/walk'
143
172
  if ( d == null ) return
144
173
  const
145
174
  dType = _defineDataType ( d )
146
- , text = render ( d, name, helpers )
175
+ , text = render ( d, name, helpers, {...buildDependencies, ...dependencies} )
147
176
  ;
148
177
  if ( text == null ) theData[i] = null
149
178
  if ( dType === 'object' ) d['text'] = text
@@ -151,12 +180,12 @@ import walk from '@peter.naydenov/walk'
151
180
  })
152
181
  break
153
182
  case 'primitive':
154
- nestedData[level] = render ( theData, name, helpers )
183
+ nestedData[level] = render ( theData, name, helpers, {...buildDependencies, ...dependencies} )
155
184
  break
156
185
  case 'object':
157
186
  let kTest = Object.keys ( theData ).find ( k => k.includes ( '/' ) ); // Check if keys are breadcrumbs
158
- if ( kTest ) Object.entries( theData ).forEach( ([k,v]) => v['text'] = render ( v, name, helpers ) )
159
- else theData['text'] = render ( theData, name, helpers )
187
+ if ( kTest ) Object.entries( theData ).forEach( ([k,v]) => v['text'] = render ( v, name, helpers, {...buildDependencies, ...dependencies} ) )
188
+ else theData['text'] = render ( theData, name, helpers, {...buildDependencies, ...dependencies} )
160
189
  break
161
190
  } // switch renderDataType
162
191
  break;
@@ -224,7 +253,11 @@ import walk from '@peter.naydenov/walk'
224
253
  }) // forEach d
225
254
 
226
255
  if ( topLevelType === 'array' ) return endData
227
- if (args) return args.reduce ( (acc, fn) => fn ( acc ), endData.join ( '' ) )
256
+ // Execute postprocess functions
257
+ if (args) return args.reduce ( (acc, fn) => {
258
+ if ( typeof fn !== 'function' ) return acc
259
+ return fn ( acc, {...buildDependencies,...dependencies} )
260
+ }, endData.join ( '' ) )
228
261
  else return endData.join ( '' )
229
262
 
230
263
  } // success func.
@@ -2,7 +2,18 @@ import _renderHolder from "./_renderHolder.js"
2
2
 
3
3
 
4
4
 
5
- function render ( theData, name, helpers ) {
5
+ /**
6
+ *
7
+ * Execute rendering and return the results
8
+ *
9
+ * @param {object|string} theData - Data to be rendered. If it's a string, it's the value of 'text' property.
10
+ * @param {string} name - Name of the render to be executed.
11
+ * @param {object} helpers - Object with helper functions or templates.
12
+ * @param {...any} args - Extra arguments to be passed to the render function.
13
+ *
14
+ * @returns {string} - Rendered string.
15
+ */
16
+ function render ( theData, name, helpers, ...args ) {
6
17
  // *** Executes rendering and return the results
7
18
  if ( theData instanceof Object ) { // Make sure all properties are not objects
8
19
  Object.entries ( theData ).forEach ( ([key, value]) => {
@@ -15,7 +26,7 @@ function render ( theData, name, helpers ) {
15
26
  } // setRenderData func.
16
27
  const isRenderFunction = typeof helpers[name] === 'function'; // Render could be a function or template.
17
28
  theData = setRenderData ( theData )
18
- if ( isRenderFunction ) return helpers[name]( theData )
29
+ if ( isRenderFunction ) return helpers[name]( theData, ...args )
19
30
  else return _renderHolder ( helpers[name], theData )
20
31
  } // render func.
21
32