@peter.naydenov/morph 1.1.3 → 1.2.1
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.
- package/Changelog.md +12 -0
- package/dist/morph.cjs +1 -1
- package/dist/morph.esm.mjs +1 -1
- package/dist/morph.umd.js +1 -1
- package/package.json +8 -7
- package/src/methods/_defineData.js +11 -13
- package/src/methods/_renderHolder.js +2 -1
- package/src/methods/_setupActions.js +10 -2
- package/src/methods/build.js +76 -38
- package/src/methods/render.js +2 -0
- package/types/index.d.ts +60 -0
package/Changelog.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
+
### 1.2.1 (2025-03-16)
|
|
6
|
+
- [x]Enhanced Error Handling in setupActions.js: Improved the error message to provide more context about the missing level markers, making it easier to debug;
|
|
7
|
+
- [x] Added TypeScript Type Definitions: Created a types directory with an index.d.ts file containing TypeScript definitions for the library, and added the "types" field to package.json for better TypeScript support;
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### 1.2.0 (2025-03-14)
|
|
12
|
+
- [x] Bug fix: Deeply nested data;
|
|
13
|
+
- [x] Improve: Error message if actions do not have deepness of the data (very difficult to debug);
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
5
17
|
### 1.1.3 (2025-01-23)
|
|
6
18
|
- [x] Improve: Error messages when using method "add" with template -> null;
|
|
7
19
|
|
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:
|
|
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,r){const n=[];let a=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]]};if(!r.includes("#"))return n.push([t]),{dataDeepLevel:0,nestedData:n};return e({data:t,objectCallback:function({key:e,value:t,breadcrumbs:r}){return a=r.split("/").length-1,n[a]||(n[a]=[]),t instanceof Array?n[a].push(t):n[a].push([t]),t}}),{dataDeepLevel:a,nestedData:n}}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),r instanceof Array&&(e[t]=r[0])}));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}=o,i=[],l="string"==typeof t?t.replace(/<!--[\s\S]*?-->/g,"").replace(/\s{2,}/g," "):t;let u=null;const f=r(o)(l);return"string"==typeof f?u=f:f.forEach(((e,t)=>{const r=RegExp(s+"\\s*(.*?)\\s*(?::\\s*(.*?)\\s*)?"+c,"g");if(e.includes(s)){const a=r.exec(e);i.push({index:t,data:(n=a[1],n||null),action:a[2]?a[2].split(",").map((e=>e.trim())):null})}var n})),i.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]||(u=`Error: Missing helper: ${e}`,!1))))})),{hasError:u,placeholders:i,chop:f,helpers:n,handshake:a}}(n);if(u){function b(){return u}return i?[!1,b]:b}{let y=structuredClone(d);function m(r={},n={},...o){const i=[];let u=s(r);if(r=e({data:r}),"null"===u)return y.join("");if("string"==typeof r)switch(r){case"raw":return y.join("");case"demo":if(!h)return"Error: No handshake data.";u=s(r=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 "${r}". Available commands: raw, demo, handshake, placeholders.`}return"array"!==u&&(r=[r]),r.forEach((r=>{f.forEach((o=>{const{index:i,data:u,action:f}=o;if(!f&&u){const e=r[u];switch(s(e)){case"function":return void(y[i]=e());case"primitive":return void(y[i]=e);case"array":return void("primitive"===s(e[0])&&(y[i]=e[0]));case"object":return void(e.text&&(y[i]=e.text))}}else{let{dataDeepLevel:o,nestedData:d}=a("@all"===u||null===u||"@root"===u?r:r[u],f),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=[...e],a=0,o=0,s=0;n.forEach((e=>{"#"===e&&s++})),s<t&&console.error(`Error: Actions doesn't describe all levels of data. Actions: ${e}`);do{r[o]=[],o++}while(o<=t);return n.every((e=>"#"===e?(a++,!(a>t)):e.startsWith("?")?(r[a].push({type:"route",name:e.replace("?",""),level:a}),!0):e.startsWith("+")?(r[a].push({type:"extendedRender",name:e.replace("+",""),level:a}),!0):e.startsWith("[]")?(r[a].push({type:"mix",name:e.replace("[]",""),level:a}),!0):e.startsWith(">")?(r[a].push({type:"data",name:e.replace(">",""),level:a}),!0):(""===e||r[a].push({type:"render",name:e,level:a}),!0))),r}(f,o),o);for(let t of h){let{type:r,name:a,level:o}=t;d[o].forEach((t=>{let i=s(t);switch(r){case"route":switch(i){case"array":t.forEach(((e,r)=>{if(null==e)return;const o=s(e),i=p[a](e);null!=i&&("object"===o?t[r].text=c(e,i,p,{...l,...n}):t[r]=c(e,i,p,{...l,...n}))}));break;case"object":t.text=c(t,a,p,{...l,...n});break;case"primitive":d[o]=c(t,a,p,{...l,...n})}break;case"data":switch(i){case"array":t.forEach(((e,r)=>t[r]=e instanceof Function?p[a](e()):p[a](e)));break;case"object":d[o]=[p[a](t)];break;case"function":d[o]=[p[a](t())];break;case"primitive":d[o]=p[a](t)}break;case"render":const u="function"==typeof p[a];switch(i){case"array":u?t.forEach(((e,r)=>{if(null==e)return;const o=s(e),c=p[a](e,{...l,...n});null==c&&(t[r]=null),"object"===o?e.text=c:t[r]=c})):t.forEach(((e,r)=>{if(null==e)return;const o=s(e),i=c(e,a,p,{...l,...n});null==i?t[r]=null:"object"===o?e.text=i:t[r]=i}));break;case"function":d[o]=p[a](t(),{...l,...n});break;case"primitive":d[o]=c(t,a,p,{...l,...n});break;case"object":if(u)d[o][0].text=p[a](t,{...l,...n});else{Object.keys(t).find((e=>e.includes("/")))?Object.entries(t).forEach((([e,t])=>t.text=c(t,a,p,{...l,...n}))):t.text=c(t,a,p,{...l,...n})}}break;case"extendedRender":"function"==typeof p[a]&&(d[o]=p[a](d[0][0]));break;case"mix":if(""===a)switch(i){case"object":Object.keys(t).find((e=>e.includes("/")))?Object.entries(t).forEach((([e,t])=>d[o][e]=t.text)):d[o]=t.text;for(let h=o-1;h>=0;h--)d[h]=e({data:d[h],objectCallback:f});function f({value:e,breadcrumbs:t}){return d[o][t]?d[o][t]:e}break;case"array":t.forEach(((e,r)=>{if(r>0){let n=s(e);if(null==e)return;t[0]+="object"===n?`${e.text}`:`${e}`,t.toSpliced(r,1)}else{let r=s(e);if(t[0]="",null===r)return;t[0]="object"===r?`${e.text}`:`${e}`}})),t.length=1}else{let b=p[a](t),y=s(b);switch(t.forEach(((e,r)=>t.splice(r,1))),t.length=0,y){case"primitive":t[0]=b;break;case"array":t.push(...b)}}}}))}if(d instanceof Array&&1===d.length&&d[0]instanceof Array&&(d=d[0]),null==d[0])return;let b=s(d[0]),m=d[0];switch(b){case"primitive":if(null==m)return;y[i]=m;break;case"object":if(null==m.text)return;y[i]=m.text;break;case"array":const e=s(m[0]);y[i]="object"===e?m.map((e=>e.text)).join(""):m.join("")}}})),i.push(y.join(""))})),"array"===u?i:o?o.reduce(((e,t)=>"function"!=typeof t?e:t(e,{...l,...n})),i.join("")):i.join("")}return i?[!0,m]:m}}const l={default:{}};const u={build:i,get:function(e){if(!(e instanceof Array))return function(){return'Error: Argument "location" is a string. Should be an array. E.g. ["templateName", "storageName"].'};const[t,r="default"]=e;return l[r]?l[r][t]?l[r][t]:function(){return`Error: Template "${t}" does not exist in storage "${r}".`}:function(){return`Error: Storage "${r}" does not exist.`}},add:function(e,t,...r){const[n,a="default"]=e;if(null==t)return void console.warn(`Warning: Template ${a}/${n} is not added to storage. The template is null.`);let o=t,s=!0;if(l[a]||(l[a]={}),"function"!=typeof t){let e=i(t,!0,...r);s=e[0],o=e[1]}s?l[a][n]=o:console.error(`Error: Template "${n}" looks broken and is not added to storage.`)},list:function(e=["default"]){return e.map((e=>l[e]?Object.keys(l[e]):[])).flat()},clear:function(){Object.keys(l).forEach((e=>{"default"!=e?delete l[e]:l.default={}}))},remove:function(e){const[t,r="default"]=e;return l[r]?l[r][t]?void delete l[r][t]:`Error: Template "${t}" does not exist in storage "${r}".`:`Error: Storage "${r}" does not exist.`}};module.exports=u;
|
package/dist/morph.esm.mjs
CHANGED
|
@@ -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:
|
|
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,r){const n=[];let a=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]]};if(!r.includes("#"))return n.push([t]),{dataDeepLevel:0,nestedData:n};return e({data:t,objectCallback:function({key:e,value:t,breadcrumbs:r}){return a=r.split("/").length-1,n[a]||(n[a]=[]),t instanceof Array?n[a].push(t):n[a].push([t]),t}}),{dataDeepLevel:a,nestedData:n}}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),r instanceof Array&&(e[t]=r[0])}));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}=o,i=[],l="string"==typeof t?t.replace(/<!--[\s\S]*?-->/g,"").replace(/\s{2,}/g," "):t;let u=null;const f=r(o)(l);return"string"==typeof f?u=f:f.forEach(((e,t)=>{const r=RegExp(s+"\\s*(.*?)\\s*(?::\\s*(.*?)\\s*)?"+c,"g");if(e.includes(s)){const a=r.exec(e);i.push({index:t,data:(n=a[1],n||null),action:a[2]?a[2].split(",").map((e=>e.trim())):null})}var n})),i.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]||(u=`Error: Missing helper: ${e}`,!1))))})),{hasError:u,placeholders:i,chop:f,helpers:n,handshake:a}}(n);if(u){function b(){return u}return i?[!1,b]:b}{let m=structuredClone(d);function y(r={},n={},...o){const i=[];let u=s(r);if(r=e({data:r}),"null"===u)return m.join("");if("string"==typeof r)switch(r){case"raw":return m.join("");case"demo":if(!h)return"Error: No handshake data.";u=s(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"!==u&&(r=[r]),r.forEach((r=>{f.forEach((o=>{const{index:i,data:u,action:f}=o;if(!f&&u){const e=r[u];switch(s(e)){case"function":return void(m[i]=e());case"primitive":return void(m[i]=e);case"array":return void("primitive"===s(e[0])&&(m[i]=e[0]));case"object":return void(e.text&&(m[i]=e.text))}}else{let{dataDeepLevel:o,nestedData:d}=a("@all"===u||null===u||"@root"===u?r:r[u],f),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=[...e],a=0,o=0,s=0;n.forEach((e=>{"#"===e&&s++})),s<t&&console.error(`Error: Actions doesn't describe all levels of data. Actions: ${e}`);do{r[o]=[],o++}while(o<=t);return n.every((e=>"#"===e?(a++,!(a>t)):e.startsWith("?")?(r[a].push({type:"route",name:e.replace("?",""),level:a}),!0):e.startsWith("+")?(r[a].push({type:"extendedRender",name:e.replace("+",""),level:a}),!0):e.startsWith("[]")?(r[a].push({type:"mix",name:e.replace("[]",""),level:a}),!0):e.startsWith(">")?(r[a].push({type:"data",name:e.replace(">",""),level:a}),!0):(""===e||r[a].push({type:"render",name:e,level:a}),!0))),r}(f,o),o);for(let t of h){let{type:r,name:a,level:o}=t;d[o].forEach((t=>{let i=s(t);switch(r){case"route":switch(i){case"array":t.forEach(((e,r)=>{if(null==e)return;const o=s(e),i=p[a](e);null!=i&&("object"===o?t[r].text=c(e,i,p,{...l,...n}):t[r]=c(e,i,p,{...l,...n}))}));break;case"object":t.text=c(t,a,p,{...l,...n});break;case"primitive":d[o]=c(t,a,p,{...l,...n})}break;case"data":switch(i){case"array":t.forEach(((e,r)=>t[r]=e instanceof Function?p[a](e()):p[a](e)));break;case"object":d[o]=[p[a](t)];break;case"function":d[o]=[p[a](t())];break;case"primitive":d[o]=p[a](t)}break;case"render":const u="function"==typeof p[a];switch(i){case"array":u?t.forEach(((e,r)=>{if(null==e)return;const o=s(e),c=p[a](e,{...l,...n});null==c&&(t[r]=null),"object"===o?e.text=c:t[r]=c})):t.forEach(((e,r)=>{if(null==e)return;const o=s(e),i=c(e,a,p,{...l,...n});null==i?t[r]=null:"object"===o?e.text=i:t[r]=i}));break;case"function":d[o]=p[a](t(),{...l,...n});break;case"primitive":d[o]=c(t,a,p,{...l,...n});break;case"object":if(u)d[o][0].text=p[a](t,{...l,...n});else{Object.keys(t).find((e=>e.includes("/")))?Object.entries(t).forEach((([e,t])=>t.text=c(t,a,p,{...l,...n}))):t.text=c(t,a,p,{...l,...n})}}break;case"extendedRender":"function"==typeof p[a]&&(d[o]=p[a](d[0][0]));break;case"mix":if(""===a)switch(i){case"object":Object.keys(t).find((e=>e.includes("/")))?Object.entries(t).forEach((([e,t])=>d[o][e]=t.text)):d[o]=t.text;for(let h=o-1;h>=0;h--)d[h]=e({data:d[h],objectCallback:f});function f({value:e,breadcrumbs:t}){return d[o][t]?d[o][t]:e}break;case"array":t.forEach(((e,r)=>{if(r>0){let n=s(e);if(null==e)return;t[0]+="object"===n?`${e.text}`:`${e}`,t.toSpliced(r,1)}else{let r=s(e);if(t[0]="",null===r)return;t[0]="object"===r?`${e.text}`:`${e}`}})),t.length=1}else{let b=p[a](t),m=s(b);switch(t.forEach(((e,r)=>t.splice(r,1))),t.length=0,m){case"primitive":t[0]=b;break;case"array":t.push(...b)}}}}))}if(d instanceof Array&&1===d.length&&d[0]instanceof Array&&(d=d[0]),null==d[0])return;let b=s(d[0]),y=d[0];switch(b){case"primitive":if(null==y)return;m[i]=y;break;case"object":if(null==y.text)return;m[i]=y.text;break;case"array":const e=s(y[0]);m[i]="object"===e?y.map((e=>e.text)).join(""):y.join("")}}})),i.push(m.join(""))})),"array"===u?i:o?o.reduce(((e,t)=>"function"!=typeof t?e:t(e,{...l,...n})),i.join("")):i.join("")}return i?[!0,y]:y}}const l={default:{}};const u={build:i,get:function(e){if(!(e instanceof Array))return function(){return'Error: Argument "location" is a string. Should be an array. E.g. ["templateName", "storageName"].'};const[t,r="default"]=e;return l[r]?l[r][t]?l[r][t]:function(){return`Error: Template "${t}" does not exist in storage "${r}".`}:function(){return`Error: Storage "${r}" does not exist.`}},add:function(e,t,...r){const[n,a="default"]=e;if(null==t)return void console.warn(`Warning: Template ${a}/${n} is not added to storage. The template is null.`);let o=t,s=!0;if(l[a]||(l[a]={}),"function"!=typeof t){let e=i(t,!0,...r);s=e[0],o=e[1]}s?l[a][n]=o:console.error(`Error: Template "${n}" looks broken and is not added to storage.`)},list:function(e=["default"]){return e.map((e=>l[e]?Object.keys(l[e]):[])).flat()},clear:function(){Object.keys(l).forEach((e=>{"default"!=e?delete l[e]:l.default={}}))},remove:function(e){const[t,r="default"]=e;return l[r]?l[r][t]?void delete l[r][t]:`Error: Template "${t}" does not exist in storage "${r}".`:`Error: Storage "${r}" 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(
|
|
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:a,TG_SFX:o,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(a),0<s&&f.push(n.slice(0,s)),-1==s)return f.push(n),f;{if(u=n.indexOf(a,s+i),c=n.indexOf(o),-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,r){const n=[];let a=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]]};if(!r.includes("#"))return n.push([t]),{dataDeepLevel:0,nestedData:n};return e({data:t,objectCallback:function({key:e,value:t,breadcrumbs:r}){return a=r.split("/").length-1,n[a]||(n[a]=[]),t instanceof Array?n[a].push(t):n[a].push([t]),t}}),{dataDeepLevel:a,nestedData:n}}function*a(e,t){let r=function(e={}){let t=[],{type:r,limit:n,onLimit:a}=Object.assign({},{type:"FIFO",limit:!1,onLimit:"update"},e),o="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=[],a=t.length-r;return e>1&&Array.from({length:e}).map((()=>{null!=t[a-1]&&n.push(t[a-1]),a--})),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=o?function(e){const r=e instanceof Array,o=r?e.length:1;let s=!1;if("full"!==a||!i){if(n&&r&&o>n&&(e=e.slice(0,-o+n)),n){const o=(r?e.length:1)+t.length;o>=n&&"full"===a&&(e=e.slice(0,-(o-n))),o>=n&&"update"===a&&(s=l(o-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,o=r?e.length:1;let s=!1;if("full"!==a||!i){if(n&&r&&o>n&&(e=e.slice(o-n)),n){const o=(r?e.length:1)+t.length;o>=n&&"full"===a&&(e=e.slice(0,-(o-n))),o>=n&&"update"===a&&(s=l(o-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 o={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,...a){e instanceof Object&&Object.entries(e).forEach((([t,r])=>{r instanceof Object&&(e[t]=r.text),r instanceof Array&&(e[t]=r[0])}));const i="function"==typeof n[r];return e=function(e={}){return"string"==typeof e?{text:e}:e}(e),i?n[r](e,...a):function(e,r){if(null==r)return null;const n=t(o)(e),a=o;return n.forEach(((e,t)=>{if(e.includes(a.TG_PRX)){const o=e.replace(a.TG_PRX,"").replace(a.TG_SFX,"").trim();r[o]&&(n[t]=r[o])}})),n.join("")}(n[r],e)}function s(r,s=!1,c={}){const{hasError:u,placeholders:f,chop:p,helpers:d,handshake:h}=function(e){const{template:r,helpers:n={},handshake:a}=e,{TG_PRX:i,TG_SFX:l}=o,s=[],c="string"==typeof r?r.replace(/<!--[\s\S]*?-->/g,"").replace(/\s{2,}/g," "):r;let u=null;const f=t(o)(c);return"string"==typeof f?u=f:f.forEach(((e,t)=>{const r=RegExp(i+"\\s*(.*?)\\s*(?::\\s*(.*?)\\s*)?"+l,"g");if(e.includes(i)){const a=r.exec(e);s.push({index:t,data:(n=a[1],n||null),action:a[2]?a[2].split(",").map((e=>e.trim())):null})}var n})),s.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]||(u=`Error: Missing helper: ${e}`,!1))))})),{hasError:u,placeholders:s,chop:f,helpers:n,handshake:a}}(r);if(u){function y(){return u}return s?[!1,y]:y}{let g=structuredClone(p);function m(t={},r={},...o){const s=[];let u=i(t);if(t=e({data:t}),"null"===u)return g.join("");if("string"==typeof t)switch(t){case"raw":return g.join("");case"demo":if(!h)return"Error: No handshake data.";u=i(t=h);break;case"handshake":return h?structuredClone(h):"Error: No handshake data.";case"placeholders":return f.map((e=>g[e.index])).join(", ");default:return`Error: Wrong command "${t}". Available commands: raw, demo, handshake, placeholders.`}return"array"!==u&&(t=[t]),t.forEach((t=>{f.forEach((o=>{const{index:s,data:u,action:f}=o;if(!f&&u){const e=t[u];switch(i(e)){case"function":return void(g[s]=e());case"primitive":return void(g[s]=e);case"array":return void("primitive"===i(e[0])&&(g[s]=e[0]));case"object":return void(e.text&&(g[s]=e.text))}}else{let{dataDeepLevel:o,nestedData:p}=n("@all"===u||null===u||"@root"===u?t:t[u],f),h=a(function(e,t=10){let r={},n=[...e],a=0,o=0,i=0;n.forEach((e=>{"#"===e&&i++})),i<t&&console.error(`Error: Actions doesn't describe all levels of data. Actions: ${e}`);do{r[o]=[],o++}while(o<=t);return n.every((e=>"#"===e?(a++,!(a>t)):e.startsWith("?")?(r[a].push({type:"route",name:e.replace("?",""),level:a}),!0):e.startsWith("+")?(r[a].push({type:"extendedRender",name:e.replace("+",""),level:a}),!0):e.startsWith("[]")?(r[a].push({type:"mix",name:e.replace("[]",""),level:a}),!0):e.startsWith(">")?(r[a].push({type:"data",name:e.replace(">",""),level:a}),!0):(""===e||r[a].push({type:"render",name:e,level:a}),!0))),r}(f,o),o);for(let t of h){let{type:n,name:a,level:o}=t;p[o].forEach((t=>{let s=i(t);switch(n){case"route":switch(s){case"array":t.forEach(((e,n)=>{if(null==e)return;const o=i(e),s=d[a](e);null!=s&&("object"===o?t[n].text=l(e,s,d,{...c,...r}):t[n]=l(e,s,d,{...c,...r}))}));break;case"object":t.text=l(t,a,d,{...c,...r});break;case"primitive":p[o]=l(t,a,d,{...c,...r})}break;case"data":switch(s){case"array":t.forEach(((e,r)=>t[r]=e instanceof Function?d[a](e()):d[a](e)));break;case"object":p[o]=[d[a](t)];break;case"function":p[o]=[d[a](t())];break;case"primitive":p[o]=d[a](t)}break;case"render":const u="function"==typeof d[a];switch(s){case"array":u?t.forEach(((e,n)=>{if(null==e)return;const o=i(e),l=d[a](e,{...c,...r});null==l&&(t[n]=null),"object"===o?e.text=l:t[n]=l})):t.forEach(((e,n)=>{if(null==e)return;const o=i(e),s=l(e,a,d,{...c,...r});null==s?t[n]=null:"object"===o?e.text=s:t[n]=s}));break;case"function":p[o]=d[a](t(),{...c,...r});break;case"primitive":p[o]=l(t,a,d,{...c,...r});break;case"object":if(u)p[o][0].text=d[a](t,{...c,...r});else{Object.keys(t).find((e=>e.includes("/")))?Object.entries(t).forEach((([e,t])=>t.text=l(t,a,d,{...c,...r}))):t.text=l(t,a,d,{...c,...r})}}break;case"extendedRender":"function"==typeof d[a]&&(p[o]=d[a](p[0][0]));break;case"mix":if(""===a)switch(s){case"object":Object.keys(t).find((e=>e.includes("/")))?Object.entries(t).forEach((([e,t])=>p[o][e]=t.text)):p[o]=t.text;for(let h=o-1;h>=0;h--)p[h]=e({data:p[h],objectCallback:f});function f({value:e,breadcrumbs:t}){return p[o][t]?p[o][t]:e}break;case"array":t.forEach(((e,r)=>{if(r>0){let n=i(e);if(null==e)return;t[0]+="object"===n?`${e.text}`:`${e}`,t.toSpliced(r,1)}else{let r=i(e);if(t[0]="",null===r)return;t[0]="object"===r?`${e.text}`:`${e}`}})),t.length=1}else{let y=d[a](t),g=i(y);switch(t.forEach(((e,r)=>t.splice(r,1))),t.length=0,g){case"primitive":t[0]=y;break;case"array":t.push(...y)}}}}))}if(p instanceof Array&&1===p.length&&p[0]instanceof Array&&(p=p[0]),null==p[0])return;let y=i(p[0]),m=p[0];switch(y){case"primitive":if(null==m)return;g[s]=m;break;case"object":if(null==m.text)return;g[s]=m.text;break;case"array":const e=i(m[0]);g[s]="object"===e?m.map((e=>e.text)).join(""):m.join("")}}})),s.push(g.join(""))})),"array"===u?s:o?o.reduce(((e,t)=>"function"!=typeof t?e:t(e,{...c,...r})),s.join("")):s.join("")}return s?[!0,m]:m}}const c={default:{}};return{build:s,get:function(e){if(!(e instanceof Array))return function(){return'Error: Argument "location" is a string. Should be an array. E.g. ["templateName", "storageName"].'};const[t,r="default"]=e;return c[r]?c[r][t]?c[r][t]:function(){return`Error: Template "${t}" does not exist in storage "${r}".`}:function(){return`Error: Storage "${r}" does not exist.`}},add:function(e,t,...r){const[n,a="default"]=e;if(null==t)return void console.warn(`Warning: Template ${a}/${n} is not added to storage. The template is null.`);let o=t,i=!0;if(c[a]||(c[a]={}),"function"!=typeof t){let e=s(t,!0,...r);i=e[0],o=e[1]}i?c[a][n]=o:console.error(`Error: Template "${n}" looks broken and is not added to storage.`)},list:function(e=["default"]){return e.map((e=>c[e]?Object.keys(c[e]):[])).flat()},clear:function(){Object.keys(c).forEach((e=>{"default"!=e?delete c[e]:c.default={}}))},remove:function(e){const[t,r="default"]=e;return c[r]?c[r][t]?void delete c[r][t]:`Error: Template "${t}" does not exist in storage "${r}".`:`Error: Storage "${r}" does not exist.`}}}));
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peter.naydenov/morph",
|
|
3
3
|
"description": "Template engine",
|
|
4
|
-
"version": "1.1
|
|
4
|
+
"version": "1.2.1",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Peter Naydenov",
|
|
7
|
-
"main": "
|
|
7
|
+
"main": "./src/main.js",
|
|
8
8
|
"type": "module",
|
|
9
|
+
"types": "./types/index.d.ts",
|
|
9
10
|
"exports": {
|
|
10
11
|
".": {
|
|
11
12
|
"import": "./src/main.js",
|
|
@@ -26,13 +27,13 @@
|
|
|
26
27
|
"@peter.naydenov/walk": "^5.0.1"
|
|
27
28
|
},
|
|
28
29
|
"devDependencies": {
|
|
29
|
-
"@rollup/plugin-commonjs": "^28.0.
|
|
30
|
-
"@rollup/plugin-node-resolve": "^16.0.
|
|
30
|
+
"@rollup/plugin-commonjs": "^28.0.3",
|
|
31
|
+
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
31
32
|
"@rollup/plugin-terser": "^0.4.4",
|
|
32
33
|
"c8": "^10.1.3",
|
|
33
|
-
"chai": "5.
|
|
34
|
-
"mocha": "11.0
|
|
35
|
-
"rollup": "^4.
|
|
34
|
+
"chai": "5.2.0",
|
|
35
|
+
"mocha": "11.1.0",
|
|
36
|
+
"rollup": "^4.35.0"
|
|
36
37
|
},
|
|
37
38
|
"repository": {
|
|
38
39
|
"type": "git",
|
|
@@ -3,27 +3,25 @@ import walk from '@peter.naydenov/walk'
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
function _defineData ( d, action ) {
|
|
6
|
-
const nestedData =
|
|
6
|
+
const nestedData = [];
|
|
7
7
|
let dataDeepLevel = 0;
|
|
8
8
|
|
|
9
|
-
if ( d instanceof Function ) return { dataDeepLevel:0, nestedData:[d()] }
|
|
9
|
+
if ( d instanceof Function ) return { dataDeepLevel:0, nestedData:[[d()]] }
|
|
10
10
|
if ( d == null ) return { dataDeepLevel:0, nestedData:[ null ] }
|
|
11
|
-
if ( typeof d === 'string' ) return { dataDeepLevel:0, nestedData:[d] }
|
|
12
|
-
|
|
13
|
-
// Note: Nest data only if action
|
|
11
|
+
if ( typeof d === 'string' ) return { dataDeepLevel:0, nestedData:[[d]] }
|
|
12
|
+
|
|
13
|
+
// Note: Nest data only if action has '#'
|
|
14
14
|
if ( !action.includes('#') ) {
|
|
15
|
-
|
|
15
|
+
nestedData.push ( [d] )
|
|
16
|
+
return { dataDeepLevel:0, nestedData }
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
function findObjects ({key, value, breadcrumbs}) {
|
|
19
|
-
let isArray = false;
|
|
20
|
-
|
|
21
20
|
dataDeepLevel = breadcrumbs.split('/').length -1;
|
|
22
|
-
|
|
23
|
-
if ( !nestedData[dataDeepLevel] ) nestedData[dataDeepLevel] =
|
|
24
|
-
if (
|
|
25
|
-
else
|
|
26
|
-
else nestedData[dataDeepLevel][breadcrumbs] = value
|
|
21
|
+
|
|
22
|
+
if ( !nestedData[dataDeepLevel] ) nestedData[dataDeepLevel] = [];
|
|
23
|
+
if ( value instanceof Array ) nestedData[dataDeepLevel].push(value)
|
|
24
|
+
else nestedData[dataDeepLevel].push([ value ])
|
|
27
25
|
return value
|
|
28
26
|
} // step func.
|
|
29
27
|
|
|
@@ -5,7 +5,8 @@ import settings from './settings.js'
|
|
|
5
5
|
|
|
6
6
|
function _renderHolder ( template, data ) {
|
|
7
7
|
// Data should be an object. No array, no string.
|
|
8
|
-
if ( data == null ) return null
|
|
8
|
+
if ( data == null ) return null
|
|
9
|
+
|
|
9
10
|
const
|
|
10
11
|
chop = _chopTemplate (settings)( template )
|
|
11
12
|
, set = settings
|
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
function _setupActions ( actions, dataDeepLevel=10 ) {
|
|
2
2
|
let
|
|
3
3
|
actSetup = {}
|
|
4
|
-
, actLevel = 0
|
|
5
4
|
, actionList = [...actions]
|
|
5
|
+
, actLevel = 0
|
|
6
6
|
, i = 0
|
|
7
|
+
, countHashes = 0
|
|
7
8
|
;
|
|
8
|
-
|
|
9
|
+
|
|
10
|
+
actionList.forEach ( action => { if ( action === '#' ) countHashes++ })
|
|
11
|
+
if ( countHashes < dataDeepLevel ) console.error ( `Error: Not enough level markers (#) for data with depth level ${dataDeepLevel}. Found ${countHashes} level markers in actions: ${actions.join(', ')}` )
|
|
12
|
+
|
|
9
13
|
do {
|
|
10
14
|
actSetup[i] = []
|
|
11
15
|
i++
|
|
12
16
|
} while ( i <= dataDeepLevel )
|
|
13
17
|
|
|
18
|
+
|
|
19
|
+
|
|
14
20
|
actionList.every ( act => {
|
|
15
21
|
if ( act === '#' ) { // it's a change level action
|
|
16
22
|
actLevel++
|
|
@@ -52,6 +58,7 @@ function _setupActions ( actions, dataDeepLevel=10 ) {
|
|
|
52
58
|
if ( act === '' ) {
|
|
53
59
|
return true
|
|
54
60
|
}
|
|
61
|
+
|
|
55
62
|
actSetup[actLevel].push ({
|
|
56
63
|
type: 'render'
|
|
57
64
|
, name: act
|
|
@@ -59,6 +66,7 @@ function _setupActions ( actions, dataDeepLevel=10 ) {
|
|
|
59
66
|
})
|
|
60
67
|
return true
|
|
61
68
|
}) // actionList every
|
|
69
|
+
|
|
62
70
|
return actSetup
|
|
63
71
|
} // _setupActions func.
|
|
64
72
|
|
package/src/methods/build.js
CHANGED
|
@@ -59,10 +59,8 @@ function build ( tpl, extra=false, buildDependencies={} ) {
|
|
|
59
59
|
* If 'args' are provided, they are applied to the result in order.
|
|
60
60
|
*/
|
|
61
61
|
function success ( d={}, dependencies={}, ...args ) {
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
, endData = []
|
|
65
|
-
;
|
|
62
|
+
const endData = [];
|
|
63
|
+
let topLevelType = _defineDataType ( d );
|
|
66
64
|
d = walk ({data:d})
|
|
67
65
|
|
|
68
66
|
if ( topLevelType === 'null' ) return cuts.join ( '' )
|
|
@@ -70,10 +68,11 @@ function build ( tpl, extra=false, buildDependencies={} ) {
|
|
|
70
68
|
if ( typeof d === 'string' ) { // 'd' is a string when we want to debug the template
|
|
71
69
|
switch ( d ) {
|
|
72
70
|
case 'raw':
|
|
73
|
-
return cuts.join('') // Original template with placeholders
|
|
71
|
+
return cuts.join ( '' ) // Original template with placeholders
|
|
74
72
|
case 'demo':
|
|
75
73
|
if ( !handshake ) return `Error: No handshake data.`
|
|
76
74
|
d = handshake // Render with handshake object
|
|
75
|
+
topLevelType = _defineDataType ( d )
|
|
77
76
|
break
|
|
78
77
|
case 'handshake':
|
|
79
78
|
if ( !handshake ) return `Error: No handshake data.`
|
|
@@ -87,19 +86,21 @@ function build ( tpl, extra=false, buildDependencies={} ) {
|
|
|
87
86
|
|
|
88
87
|
if ( topLevelType !== 'array' ) d = [ d ]
|
|
89
88
|
|
|
90
|
-
//
|
|
89
|
+
// Handle null data case - just return the template without placeholders
|
|
90
|
+
if ( topLevelType === 'null' ) return cuts.join ( '' ).replace(/{{.*?}}/g, '')
|
|
91
|
+
|
|
91
92
|
d.forEach ( dElement => {
|
|
92
93
|
placeholders.forEach ( holder => { // Placeholders
|
|
93
94
|
const
|
|
94
95
|
{ index, data, action } = holder // index - placeholder index, data - key of data, action - list of operations
|
|
95
96
|
, dataOnly = !action && data
|
|
96
|
-
;
|
|
97
|
+
;
|
|
97
98
|
|
|
98
99
|
if ( dataOnly ) {
|
|
99
100
|
const
|
|
100
101
|
info = dElement[data]
|
|
101
102
|
, type = _defineDataType ( info )
|
|
102
|
-
;
|
|
103
|
+
;
|
|
103
104
|
switch ( type ) {
|
|
104
105
|
case 'function' :
|
|
105
106
|
cuts[index] = info ()
|
|
@@ -116,17 +117,20 @@ function build ( tpl, extra=false, buildDependencies={} ) {
|
|
|
116
117
|
} // switch
|
|
117
118
|
} // dataOnly
|
|
118
119
|
else { // Data and Actions or only Actions
|
|
119
|
-
|
|
120
|
+
let
|
|
120
121
|
{ dataDeepLevel, nestedData } = (data==='@all' || data===null || data==='@root' ) ? _defineData ( dElement, action ) : _defineData ( dElement[data], action )
|
|
121
122
|
, actSetup = _actionSupply ( _setupActions ( action, dataDeepLevel ), dataDeepLevel )
|
|
122
123
|
;
|
|
123
124
|
|
|
124
125
|
for ( let step of actSetup ) {
|
|
125
|
-
let { type, name, level } = step;
|
|
126
126
|
let
|
|
127
|
-
|
|
128
|
-
,
|
|
127
|
+
{ type, name, level } = step
|
|
128
|
+
, levelData = nestedData[level]
|
|
129
129
|
;
|
|
130
|
+
|
|
131
|
+
levelData.forEach ( theData => {
|
|
132
|
+
|
|
133
|
+
let dataType = _defineDataType ( theData )
|
|
130
134
|
switch ( type ) { // Action type 'route','data', 'render', or mix -> different operations
|
|
131
135
|
case 'route':
|
|
132
136
|
switch ( dataType ) {
|
|
@@ -148,16 +152,16 @@ function build ( tpl, extra=false, buildDependencies={} ) {
|
|
|
148
152
|
break
|
|
149
153
|
}
|
|
150
154
|
break
|
|
151
|
-
case 'data':
|
|
155
|
+
case 'data':
|
|
152
156
|
switch ( dataType ) {
|
|
153
157
|
case 'array':
|
|
154
158
|
theData.forEach ( (d,i) => theData[i] = ( d instanceof Function ) ? helpers[name]( d() ) : helpers[name]( d ) )
|
|
155
159
|
break
|
|
156
160
|
case 'object':
|
|
157
|
-
nestedData[level] = helpers[name]( theData )
|
|
161
|
+
nestedData[level] = [helpers[name]( theData )]
|
|
158
162
|
break
|
|
159
163
|
case 'function':
|
|
160
|
-
nestedData[level] = helpers[name]( theData() )
|
|
164
|
+
nestedData[level] = [helpers[name]( theData() )]
|
|
161
165
|
break
|
|
162
166
|
case 'primitive':
|
|
163
167
|
nestedData[level] = helpers[name]( theData )
|
|
@@ -176,18 +180,18 @@ function build ( tpl, extra=false, buildDependencies={} ) {
|
|
|
176
180
|
|
|
177
181
|
if ( text == null ) theData[i] = null
|
|
178
182
|
if ( dType === 'object' ) d['text'] = text
|
|
179
|
-
else theData[i] = text
|
|
183
|
+
else theData[i] = text
|
|
180
184
|
})
|
|
181
185
|
else theData.forEach ( (d,i) => {
|
|
182
186
|
if ( d == null ) return
|
|
183
187
|
const
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
if ( text == null
|
|
188
|
-
if ( dType === 'object' )
|
|
189
|
-
else
|
|
190
|
-
})
|
|
188
|
+
dType = _defineDataType ( d )
|
|
189
|
+
, text = render ( d, name, helpers, {...buildDependencies, ...dependencies} )
|
|
190
|
+
;
|
|
191
|
+
if ( text == null ) theData[i] = null
|
|
192
|
+
else if ( dType === 'object' ) d['text'] = text
|
|
193
|
+
else theData[i] = text
|
|
194
|
+
})
|
|
191
195
|
break
|
|
192
196
|
case 'function':
|
|
193
197
|
nestedData[level] = helpers[name]( theData(), {...buildDependencies, ...dependencies} )
|
|
@@ -196,7 +200,7 @@ function build ( tpl, extra=false, buildDependencies={} ) {
|
|
|
196
200
|
nestedData[level] = render ( theData, name, helpers, {...buildDependencies, ...dependencies} )
|
|
197
201
|
break
|
|
198
202
|
case 'object':
|
|
199
|
-
if ( isRenderFunction )
|
|
203
|
+
if ( isRenderFunction ) nestedData[level][0]['text'] = helpers[name]( theData, {...buildDependencies, ...dependencies} )
|
|
200
204
|
else {
|
|
201
205
|
let kTest = Object.keys ( theData ).find ( k => k.includes ( '/' ) ); // Check if keys are breadcrumbs
|
|
202
206
|
if ( kTest ) Object.entries( theData ).forEach( ([k,v]) => v['text'] = render ( v, name, helpers, {...buildDependencies, ...dependencies} ) )
|
|
@@ -209,13 +213,13 @@ function build ( tpl, extra=false, buildDependencies={} ) {
|
|
|
209
213
|
// TODO: Test extendedRender
|
|
210
214
|
const isValid = typeof helpers[name] === 'function'; // Render could be a function and template.
|
|
211
215
|
if ( isValid ) {
|
|
212
|
-
nestedData[level] = helpers[name]( nestedData[0] )
|
|
216
|
+
nestedData[level] = helpers[name]( nestedData[0][0] )
|
|
213
217
|
}
|
|
214
218
|
else {
|
|
215
219
|
// TODO: Error...
|
|
216
220
|
}
|
|
217
221
|
break
|
|
218
|
-
case 'mix':
|
|
222
|
+
case 'mix':
|
|
219
223
|
if ( name === '' ) { // when is anonymous mixing helper
|
|
220
224
|
switch ( dataType ) {
|
|
221
225
|
case 'object':
|
|
@@ -231,26 +235,61 @@ function build ( tpl, extra=false, buildDependencies={} ) {
|
|
|
231
235
|
} // check
|
|
232
236
|
break
|
|
233
237
|
case 'array':
|
|
234
|
-
|
|
238
|
+
theData.forEach ( (x,i) => {
|
|
239
|
+
if ( i > 0 ) {
|
|
235
240
|
let xType = _defineDataType ( x );
|
|
236
|
-
if (
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
+
if ( x == null ) return
|
|
242
|
+
if ( xType === 'object' ) theData[0] += `${x.text}`
|
|
243
|
+
else theData[0] += `${x}`
|
|
244
|
+
theData.toSpliced(i,1)
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
let xxType = _defineDataType ( x );
|
|
248
|
+
theData[0] = ''
|
|
249
|
+
if ( xxType === null ) return
|
|
250
|
+
else if ( xxType === 'object' ) theData[0] = `${x.text}`
|
|
251
|
+
else theData[0] = `${x}`
|
|
252
|
+
}
|
|
253
|
+
})
|
|
254
|
+
theData.length = 1
|
|
241
255
|
break
|
|
242
256
|
} // switch dataType
|
|
243
257
|
} // if name === ''
|
|
244
|
-
else
|
|
258
|
+
else {
|
|
259
|
+
let
|
|
260
|
+
val = helpers[name]( theData )
|
|
261
|
+
, valType = _defineDataType ( val )
|
|
262
|
+
;
|
|
263
|
+
|
|
264
|
+
theData.forEach ( ( x, i ) => theData.splice ( i, 1) )
|
|
265
|
+
theData.length = 0
|
|
266
|
+
switch ( valType ) {
|
|
267
|
+
case 'primitive':
|
|
268
|
+
theData[0] = val
|
|
269
|
+
break
|
|
270
|
+
case 'array':
|
|
271
|
+
theData.push ( ...val )
|
|
272
|
+
break
|
|
273
|
+
} // switch valType
|
|
274
|
+
}
|
|
245
275
|
break
|
|
246
276
|
default:
|
|
247
277
|
break
|
|
248
278
|
}
|
|
279
|
+
}) // levelData
|
|
249
280
|
} // for step of actSetup
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
281
|
+
|
|
282
|
+
if ( nestedData instanceof Array &&
|
|
283
|
+
nestedData.length === 1 &&
|
|
284
|
+
nestedData[0] instanceof Array
|
|
285
|
+
) nestedData = nestedData[0]
|
|
286
|
+
if ( nestedData[0] == null ) return
|
|
287
|
+
|
|
288
|
+
let
|
|
289
|
+
accType = _defineDataType ( nestedData[0] )
|
|
290
|
+
, fineData = nestedData[0]
|
|
291
|
+
;
|
|
292
|
+
|
|
254
293
|
switch ( accType ) {
|
|
255
294
|
case 'primitive':
|
|
256
295
|
if ( fineData == null ) return
|
|
@@ -282,7 +321,6 @@ function build ( tpl, extra=false, buildDependencies={} ) {
|
|
|
282
321
|
} // success func.
|
|
283
322
|
return extra ? [ true, success ] : success
|
|
284
323
|
}
|
|
285
|
-
|
|
286
324
|
} // build func.
|
|
287
325
|
|
|
288
326
|
|
package/src/methods/render.js
CHANGED
|
@@ -15,9 +15,11 @@ import _renderHolder from "./_renderHolder.js"
|
|
|
15
15
|
*/
|
|
16
16
|
function render ( theData, name, helpers, ...args ) {
|
|
17
17
|
// *** Executes rendering and return the results
|
|
18
|
+
|
|
18
19
|
if ( theData instanceof Object ) { // Make sure all properties are not objects
|
|
19
20
|
Object.entries ( theData ).forEach ( ([key, value]) => {
|
|
20
21
|
if ( value instanceof Object ) theData[key] = value['text']
|
|
22
|
+
if ( value instanceof Array ) theData[key] = value[0]
|
|
21
23
|
})
|
|
22
24
|
}
|
|
23
25
|
function setRenderData ( d={} ) {
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
declare module '@peter.naydenov/morph' {
|
|
2
|
+
/**
|
|
3
|
+
* Template description object
|
|
4
|
+
*/
|
|
5
|
+
interface TemplateDescription {
|
|
6
|
+
/**
|
|
7
|
+
* Template string with placeholders
|
|
8
|
+
*/
|
|
9
|
+
template: string;
|
|
10
|
+
/**
|
|
11
|
+
* Optional helper functions or templates
|
|
12
|
+
*/
|
|
13
|
+
helpers?: Record<string, any>;
|
|
14
|
+
/**
|
|
15
|
+
* Optional example data for rendering
|
|
16
|
+
*/
|
|
17
|
+
handshake?: Record<string, any>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Build a component from template description
|
|
22
|
+
*/
|
|
23
|
+
function build(tpl: TemplateDescription, extra?: boolean, buildDependencies?: Record<string, any>): Function;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Get a component from component storage
|
|
27
|
+
*/
|
|
28
|
+
function get(location: [string, string?]): Function;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Add a component to component storage
|
|
32
|
+
*/
|
|
33
|
+
function add(location: [string, string?], tplfn: Function | TemplateDescription, ...args: any[]): void;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* List the names of all components in the component storage
|
|
37
|
+
*/
|
|
38
|
+
function list(storageNames?: string[]): string[];
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Clear up all the components in the storage
|
|
42
|
+
*/
|
|
43
|
+
function clear(): void;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Remove a template from component storage
|
|
47
|
+
*/
|
|
48
|
+
function remove(location: [string, string?]): void | string;
|
|
49
|
+
|
|
50
|
+
const morphAPI: {
|
|
51
|
+
build: typeof build;
|
|
52
|
+
get: typeof get;
|
|
53
|
+
add: typeof add;
|
|
54
|
+
list: typeof list;
|
|
55
|
+
clear: typeof clear;
|
|
56
|
+
remove: typeof remove;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export default morphAPI;
|
|
60
|
+
}
|