@peter.naydenov/morph 1.2.0 → 1.2.2
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 +13 -2
- package/dist/morph.cjs +1 -1
- package/dist/morph.esm.mjs +1 -1
- package/dist/morph.umd.js +1 -1
- package/package.json +3 -2
- package/src/methods/_defineData.js +10 -7
- package/src/methods/_setupActions.js +2 -3
- package/src/methods/build.js +18 -18
- package/types/index.d.ts +60 -0
package/Changelog.md
CHANGED
|
@@ -2,9 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
+
### 1.2.2 (2025-03-17)
|
|
6
|
+
- [x] Improvment: Optimized code to improve performance;
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### 1.2.1 (2025-03-16)
|
|
11
|
+
- [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;
|
|
12
|
+
- [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;
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
5
16
|
### 1.2.0 (2025-03-14)
|
|
6
|
-
- [x]
|
|
7
|
-
- [x]
|
|
17
|
+
- [x] Fix: Deeply nested data;
|
|
18
|
+
- [x] Improvement: Error message if actions do not have deepness of the data (very difficult to debug);
|
|
8
19
|
|
|
9
20
|
|
|
10
21
|
|
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:i}=e;let c,l,u,f=[];if("string"!=typeof r)return n("notAString");if(0==r.length)return[];if(c=r.indexOf(a),0<c&&f.push(r.slice(0,c)),-1==c)return f.push(r),f;{if(u=r.indexOf(a,c+s),l=r.indexOf(o),-1==l)return n("missingClosing");if(l<c)return n("closedBeforeOpened");if(l+=i,-1!=u&&u<l)return n("newBeforeClosed");f.push(r.slice(c,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 e===r?(n[0]=[t],t):(a=r.split("/").length-1,n[a]||(n[a]=[]),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 i(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 c(n,c=!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:i}=o,c=[],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*)?"+i,"g");if(e.includes(s)){const a=r.exec(e);c.push({index:t,data:(n=a[1],n||null),action:a[2]?a[2].split(",").map((e=>e.trim())):null})}var n})),c.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:c,chop:f,helpers:n,handshake:a}}(n);if(u){function b(){return u}return c?[!1,b]:b}{let m=structuredClone(d);function y(r={},n={},...o){const c=[];let u=s(r),d={...l,...n};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]),"null"===u?m.join(""):(r.forEach((r=>{f.forEach((n=>{const{index:o,data:c,action:l}=n;if(!l&&c){const e=r[c];switch(s(e)){case"function":return void(m[o]=e());case"primitive":return void(m[o]=e);case"array":return void("primitive"===s(e[0])&&(m[o]=e[0]));case"object":return void(e.text&&(m[o]=e.text))}}else{let{dataDeepLevel:n,nestedData:u}=a("@all"===c||null===c||"@root"===c?r:r[c],l),f=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: Not enough level markers (#) for data with depth level ${t}. Found ${s} level markers in actions: ${e.join(", ")}`);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}(l,n),n);for(let t of f){let{type:r,name:n,level:a}=t;(u[a]||[]).forEach((t=>{let o=s(t);switch(r){case"route":switch(o){case"array":t.forEach(((e,r)=>{if(null==e)return;const a=s(e),o=p[n](e);null!=o&&("object"===a?t[r].text=i(e,o,p,d):t[r]=i(e,o,p,d))}));break;case"object":t.text=i(t,n,p,d)}break;case"data":switch(o){case"array":t.forEach(((e,r)=>t[r]=e instanceof Function?p[n](e()):p[n](e)));break;case"object":u[a]=[p[n](t)];break;case"function":u[a]=[p[n](t())];break;case"primitive":u[a]=p[n](t)}break;case"render":const c="function"==typeof p[n];switch(o){case"array":c?t.forEach(((e,r)=>{if(null==e)return;const a=s(e),o=p[n](e,d);null==o&&(t[r]=null),"object"===a?e.text=o:t[r]=o})):t.forEach(((e,r)=>{if(null==e)return;const a=s(e),o=i(e,n,p,d);null==o?t[r]=null:"object"===a?e.text=o:t[r]=o}));break;case"function":u[a]=p[n](t(),d);break;case"primitive":u[a]=i(t,n,p,d);break;case"object":c?u[a][0].text=p[n](t,d):t.text=i(t,n,p,d)}break;case"extendedRender":"function"==typeof p[n]&&(u[a]=p[n](u[0][0]));break;case"mix":if(""===n)switch(o){case"object":Object.keys(t).find((e=>e.includes("/")))?Object.entries(t).forEach((([e,t])=>u[a][e]=t.text)):u[a]=t.text;for(let f=a-1;f>=0;f--)u[f]=e({data:u[f],objectCallback:l});function l({value:e,breadcrumbs:t}){return u[a][t]?u[a][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 h=p[n](t),b=s(h);switch(t.forEach(((e,r)=>t.splice(r,1))),t.length=0,b){case"primitive":t[0]=h;break;case"array":t.push(...h)}}}}))}if(u instanceof Array&&1===u.length&&u[0]instanceof Array&&(u=u[0]),null==u[0])return;let h=s(u[0]),b=u[0];switch(h){case"primitive":if(null==b)return;m[o]=b;break;case"object":if(null==b.text)return;m[o]=b.text;break;case"array":const e=s(b[0]);m[o]="object"===e?b.map((e=>e.text)).join(""):b.join("")}}})),c.push(m.join(""))})),"array"===u?c:o?o.reduce(((e,t)=>"function"!=typeof t?e:t(e,d)),c.join("")):c.join(""))}return c?[!0,y]:y}}const l={default:{}};const u={build:c,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=c(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:i}=e;let c,l,u,f=[];if("string"!=typeof r)return n("notAString");if(0==r.length)return[];if(c=r.indexOf(a),0<c&&f.push(r.slice(0,c)),-1==c)return f.push(r),f;{if(u=r.indexOf(a,c+s),l=r.indexOf(o),-1==l)return n("missingClosing");if(l<c)return n("closedBeforeOpened");if(l+=i,-1!=u&&u<l)return n("newBeforeClosed");f.push(r.slice(c,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 e===r?(n[0]=[t],t):(a=r.split("/").length-1,n[a]||(n[a]=[]),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 i(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 c(n,c=!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:i}=o,c=[],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*)?"+i,"g");if(e.includes(s)){const a=r.exec(e);c.push({index:t,data:(n=a[1],n||null),action:a[2]?a[2].split(",").map((e=>e.trim())):null})}var n})),c.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:c,chop:f,helpers:n,handshake:a}}(n);if(u){function m(){return u}return c?[!1,m]:m}{let b=structuredClone(d);function y(r={},n={},...o){const c=[];let u=s(r),d={...l,...n};if(r=e({data:r}),"null"===u)return b.join("");if("string"==typeof r)switch(r){case"raw":return b.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=>b[e.index])).join(", ");default:return`Error: Wrong command "${r}". Available commands: raw, demo, handshake, placeholders.`}return"array"!==u&&(r=[r]),"null"===u?b.join(""):(r.forEach((r=>{f.forEach((n=>{const{index:o,data:c,action:l}=n;if(!l&&c){const e=r[c];switch(s(e)){case"function":return void(b[o]=e());case"primitive":return void(b[o]=e);case"array":return void("primitive"===s(e[0])&&(b[o]=e[0]));case"object":return void(e.text&&(b[o]=e.text))}}else{let{dataDeepLevel:n,nestedData:u}=a("@all"===c||null===c||"@root"===c?r:r[c],l),f=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: Not enough level markers (#) for data with depth level ${t}. Found ${s} level markers in actions: ${e.join(", ")}`);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}(l,n),n);for(let t of f){let{type:r,name:n,level:a}=t;(u[a]||[]).forEach((t=>{let o=s(t);switch(r){case"route":switch(o){case"array":t.forEach(((e,r)=>{if(null==e)return;const a=s(e),o=p[n](e);null!=o&&("object"===a?t[r].text=i(e,o,p,d):t[r]=i(e,o,p,d))}));break;case"object":t.text=i(t,n,p,d)}break;case"data":switch(o){case"array":t.forEach(((e,r)=>t[r]=e instanceof Function?p[n](e()):p[n](e)));break;case"object":u[a]=[p[n](t)];break;case"function":u[a]=[p[n](t())];break;case"primitive":u[a]=p[n](t)}break;case"render":const c="function"==typeof p[n];switch(o){case"array":c?t.forEach(((e,r)=>{if(null==e)return;const a=s(e),o=p[n](e,d);null==o&&(t[r]=null),"object"===a?e.text=o:t[r]=o})):t.forEach(((e,r)=>{if(null==e)return;const a=s(e),o=i(e,n,p,d);null==o?t[r]=null:"object"===a?e.text=o:t[r]=o}));break;case"function":u[a]=p[n](t(),d);break;case"primitive":u[a]=i(t,n,p,d);break;case"object":c?u[a][0].text=p[n](t,d):t.text=i(t,n,p,d)}break;case"extendedRender":"function"==typeof p[n]&&(u[a]=p[n](u[0][0]));break;case"mix":if(""===n)switch(o){case"object":Object.keys(t).find((e=>e.includes("/")))?Object.entries(t).forEach((([e,t])=>u[a][e]=t.text)):u[a]=t.text;for(let f=a-1;f>=0;f--)u[f]=e({data:u[f],objectCallback:l});function l({value:e,breadcrumbs:t}){return u[a][t]?u[a][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 h=p[n](t),m=s(h);switch(t.forEach(((e,r)=>t.splice(r,1))),t.length=0,m){case"primitive":t[0]=h;break;case"array":t.push(...h)}}}}))}if(u instanceof Array&&1===u.length&&u[0]instanceof Array&&(u=u[0]),null==u[0])return;let h=s(u[0]),m=u[0];switch(h){case"primitive":if(null==m)return;b[o]=m;break;case"object":if(null==m.text)return;b[o]=m.text;break;case"array":const e=s(m[0]);b[o]="object"===e?m.map((e=>e.text)).join(""):m.join("")}}})),c.push(b.join(""))})),"array"===u?c:o?o.reduce(((e,t)=>"function"!=typeof t?e:t(e,d)),c.join("")):c.join(""))}return c?[!0,y]:y}}const l={default:{}};const u={build:c,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=c(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(n){const{TG_PRX:
|
|
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:l,TG_SIZE_S:i}=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+l),c=n.indexOf(a),-1==c)return r("missingClosing");if(c<s)return r("closedBeforeOpened");if(c+=i,-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 o=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 e===r?(n[0]=[t],t):(o=r.split("/").length-1,n[o]||(n[o]=[]),n[o].push(t),t)}}),{dataDeepLevel:o,nestedData:n}}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(),l=!1;function i(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:i,pullReverse:function(e=1,t=0){let r=i(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||!l){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=i(a-n))}return t=e instanceof Array?t.concat(e):t.concat([e]),l=!!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||!l){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=i(a-n))}return t=r?e.reduce(((e,t)=>[t,...e]),t):[e].reduce(((e,t)=>[t,...e]),t),l=!!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 l(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 i(e,r,n,...o){e instanceof Object&&Object.entries(e).forEach((([t,r])=>{r instanceof Object&&(e[t]=r.text),r instanceof Array&&(e[t]=r[0])}));const l="function"==typeof n[r];return e=function(e={}){return"string"==typeof e?{text:e}:e}(e),l?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 s(r,s=!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:l,TG_SFX:i}=a,s=[],c="string"==typeof r?r.replace(/<!--[\s\S]*?-->/g,"").replace(/\s{2,}/g," "):r;let u=null;const f=t(a)(c);return"string"==typeof f?u=f:f.forEach(((e,t)=>{const r=RegExp(l+"\\s*(.*?)\\s*(?::\\s*(.*?)\\s*)?"+i,"g");if(e.includes(l)){const o=r.exec(e);s.push({index:t,data:(n=o[1],n||null),action:o[2]?o[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:o}}(r);if(u){function y(){return u}return s?[!1,y]:y}{let g=structuredClone(p);function m(t={},r={},...a){const s=[];let u=l(t),p={...c,...r};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=l(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]),"null"===u?g.join(""):(t.forEach((t=>{f.forEach((r=>{const{index:a,data:s,action:c}=r;if(!c&&s){const e=t[s];switch(l(e)){case"function":return void(g[a]=e());case"primitive":return void(g[a]=e);case"array":return void("primitive"===l(e[0])&&(g[a]=e[0]));case"object":return void(e.text&&(g[a]=e.text))}}else{let{dataDeepLevel:r,nestedData:u}=n("@all"===s||null===s||"@root"===s?t:t[s],c),f=o(function(e,t=10){let r={},n=[...e],o=0,a=0,l=0;n.forEach((e=>{"#"===e&&l++})),l<t&&console.error(`Error: Not enough level markers (#) for data with depth level ${t}. Found ${l} level markers in actions: ${e.join(", ")}`);do{r[a]=[],a++}while(a<=t);return n.every((e=>"#"===e?(o++,!(o>t)):e.startsWith("?")?(r[o].push({type:"route",name:e.replace("?",""),level:o}),!0):e.startsWith("+")?(r[o].push({type:"extendedRender",name:e.replace("+",""),level:o}),!0):e.startsWith("[]")?(r[o].push({type:"mix",name:e.replace("[]",""),level:o}),!0):e.startsWith(">")?(r[o].push({type:"data",name:e.replace(">",""),level:o}),!0):(""===e||r[o].push({type:"render",name:e,level:o}),!0))),r}(c,r),r);for(let t of f){let{type:r,name:n,level:o}=t;(u[o]||[]).forEach((t=>{let a=l(t);switch(r){case"route":switch(a){case"array":t.forEach(((e,r)=>{if(null==e)return;const o=l(e),a=d[n](e);null!=a&&("object"===o?t[r].text=i(e,a,d,p):t[r]=i(e,a,d,p))}));break;case"object":t.text=i(t,n,d,p)}break;case"data":switch(a){case"array":t.forEach(((e,r)=>t[r]=e instanceof Function?d[n](e()):d[n](e)));break;case"object":u[o]=[d[n](t)];break;case"function":u[o]=[d[n](t())];break;case"primitive":u[o]=d[n](t)}break;case"render":const s="function"==typeof d[n];switch(a){case"array":s?t.forEach(((e,r)=>{if(null==e)return;const o=l(e),a=d[n](e,p);null==a&&(t[r]=null),"object"===o?e.text=a:t[r]=a})):t.forEach(((e,r)=>{if(null==e)return;const o=l(e),a=i(e,n,d,p);null==a?t[r]=null:"object"===o?e.text=a:t[r]=a}));break;case"function":u[o]=d[n](t(),p);break;case"primitive":u[o]=i(t,n,d,p);break;case"object":s?u[o][0].text=d[n](t,p):t.text=i(t,n,d,p)}break;case"extendedRender":"function"==typeof d[n]&&(u[o]=d[n](u[0][0]));break;case"mix":if(""===n)switch(a){case"object":Object.keys(t).find((e=>e.includes("/")))?Object.entries(t).forEach((([e,t])=>u[o][e]=t.text)):u[o]=t.text;for(let f=o-1;f>=0;f--)u[f]=e({data:u[f],objectCallback:c});function c({value:e,breadcrumbs:t}){return u[o][t]?u[o][t]:e}break;case"array":t.forEach(((e,r)=>{if(r>0){let n=l(e);if(null==e)return;t[0]+="object"===n?`${e.text}`:`${e}`,t.toSpliced(r,1)}else{let r=l(e);if(t[0]="",null===r)return;t[0]="object"===r?`${e.text}`:`${e}`}})),t.length=1}else{let h=d[n](t),y=l(h);switch(t.forEach(((e,r)=>t.splice(r,1))),t.length=0,y){case"primitive":t[0]=h;break;case"array":t.push(...h)}}}}))}if(u instanceof Array&&1===u.length&&u[0]instanceof Array&&(u=u[0]),null==u[0])return;let h=l(u[0]),y=u[0];switch(h){case"primitive":if(null==y)return;g[a]=y;break;case"object":if(null==y.text)return;g[a]=y.text;break;case"array":const e=l(y[0]);g[a]="object"===e?y.map((e=>e.text)).join(""):y.join("")}}})),s.push(g.join(""))})),"array"===u?s:a?a.reduce(((e,t)=>"function"!=typeof t?e:t(e,p)),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,o="default"]=e;if(null==t)return void console.warn(`Warning: Template ${o}/${n} is not added to storage. The template is null.`);let a=t,l=!0;if(c[o]||(c[o]={}),"function"!=typeof t){let e=s(t,!0,...r);l=e[0],a=e[1]}l?c[o][n]=a: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.2.
|
|
4
|
+
"version": "1.2.2",
|
|
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",
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import walk from '@peter.naydenov/walk'
|
|
2
|
-
// import _defineDataType from './_defineType';'../methods/_defineType.js'
|
|
3
2
|
|
|
4
3
|
|
|
5
4
|
|
|
@@ -16,15 +15,19 @@ function _defineData ( d, action ) {
|
|
|
16
15
|
nestedData.push ( [d] )
|
|
17
16
|
return { dataDeepLevel:0, nestedData }
|
|
18
17
|
}
|
|
19
|
-
|
|
20
|
-
function findObjects ({key, value, breadcrumbs}) {
|
|
21
|
-
dataDeepLevel = breadcrumbs.split('/').length -1;
|
|
22
18
|
|
|
19
|
+
// nestedData[0] = [d]
|
|
20
|
+
|
|
21
|
+
function findObjects ({key, value, breadcrumbs}) {
|
|
22
|
+
if ( key === breadcrumbs ) {
|
|
23
|
+
nestedData[0] = [ value ]
|
|
24
|
+
return value
|
|
25
|
+
}
|
|
26
|
+
dataDeepLevel = breadcrumbs.split('/').length-1;
|
|
23
27
|
if ( !nestedData[dataDeepLevel] ) nestedData[dataDeepLevel] = [];
|
|
24
|
-
|
|
25
|
-
else nestedData[dataDeepLevel].push([ value ])
|
|
28
|
+
nestedData[dataDeepLevel].push ( value )
|
|
26
29
|
return value
|
|
27
|
-
} //
|
|
30
|
+
} // findObjects func.
|
|
28
31
|
|
|
29
32
|
walk ({ data:d, objectCallback:findObjects })
|
|
30
33
|
return { dataDeepLevel, nestedData }
|
|
@@ -6,9 +6,9 @@ function _setupActions ( actions, dataDeepLevel=10 ) {
|
|
|
6
6
|
, i = 0
|
|
7
7
|
, countHashes = 0
|
|
8
8
|
;
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
actionList.forEach ( action => { if ( action === '#' ) countHashes++ })
|
|
11
|
-
if ( countHashes < dataDeepLevel ) console.error ( `Error:
|
|
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
12
|
|
|
13
13
|
do {
|
|
14
14
|
actSetup[i] = []
|
|
@@ -66,7 +66,6 @@ function _setupActions ( actions, dataDeepLevel=10 ) {
|
|
|
66
66
|
})
|
|
67
67
|
return true
|
|
68
68
|
}) // actionList every
|
|
69
|
-
|
|
70
69
|
return actSetup
|
|
71
70
|
} // _setupActions func.
|
|
72
71
|
|
package/src/methods/build.js
CHANGED
|
@@ -61,6 +61,7 @@ function build ( tpl, extra=false, buildDependencies={} ) {
|
|
|
61
61
|
function success ( d={}, dependencies={}, ...args ) {
|
|
62
62
|
const endData = [];
|
|
63
63
|
let topLevelType = _defineDataType ( d );
|
|
64
|
+
let deps = { ...buildDependencies, ...dependencies }
|
|
64
65
|
d = walk ({data:d})
|
|
65
66
|
|
|
66
67
|
if ( topLevelType === 'null' ) return cuts.join ( '' )
|
|
@@ -86,7 +87,8 @@ function build ( tpl, extra=false, buildDependencies={} ) {
|
|
|
86
87
|
|
|
87
88
|
if ( topLevelType !== 'array' ) d = [ d ]
|
|
88
89
|
|
|
89
|
-
//
|
|
90
|
+
// Handle null data case - just return the template without placeholders
|
|
91
|
+
if ( topLevelType === 'null' ) return cuts.join ( '' )
|
|
90
92
|
|
|
91
93
|
d.forEach ( dElement => {
|
|
92
94
|
placeholders.forEach ( holder => { // Placeholders
|
|
@@ -124,12 +126,12 @@ function build ( tpl, extra=false, buildDependencies={} ) {
|
|
|
124
126
|
for ( let step of actSetup ) {
|
|
125
127
|
let
|
|
126
128
|
{ type, name, level } = step
|
|
127
|
-
, levelData = nestedData[level]
|
|
129
|
+
, levelData = nestedData[level] || []
|
|
128
130
|
;
|
|
129
131
|
|
|
130
132
|
levelData.forEach ( theData => {
|
|
131
|
-
|
|
132
133
|
let dataType = _defineDataType ( theData )
|
|
134
|
+
|
|
133
135
|
switch ( type ) { // Action type 'route','data', 'render', or mix -> different operations
|
|
134
136
|
case 'route':
|
|
135
137
|
switch ( dataType ) {
|
|
@@ -139,15 +141,12 @@ function build ( tpl, extra=false, buildDependencies={} ) {
|
|
|
139
141
|
const dType = _defineDataType ( d )
|
|
140
142
|
const routeName = helpers[name]( d );
|
|
141
143
|
if ( routeName == null ) return
|
|
142
|
-
if ( dType === 'object' ) theData[i]['text'] = render ( d, routeName, helpers,
|
|
143
|
-
else theData[i] = render ( d, routeName, helpers,
|
|
144
|
+
if ( dType === 'object' ) theData[i]['text'] = render ( d, routeName, helpers, deps )
|
|
145
|
+
else theData[i] = render ( d, routeName, helpers, deps )
|
|
144
146
|
})
|
|
145
147
|
break
|
|
146
148
|
case 'object':
|
|
147
|
-
theData['text'] = render ( theData, name, helpers,
|
|
148
|
-
break
|
|
149
|
-
case 'primitive':
|
|
150
|
-
nestedData[level] = render ( theData, name, helpers, {...buildDependencies, ...dependencies} )
|
|
149
|
+
theData['text'] = render ( theData, name, helpers, deps )
|
|
151
150
|
break
|
|
152
151
|
}
|
|
153
152
|
break
|
|
@@ -170,12 +169,13 @@ function build ( tpl, extra=false, buildDependencies={} ) {
|
|
|
170
169
|
break
|
|
171
170
|
case 'render':
|
|
172
171
|
const isRenderFunction = typeof helpers[name] === 'function'; // Render could be a function and template.
|
|
172
|
+
|
|
173
173
|
switch ( dataType ) {
|
|
174
174
|
case 'array':
|
|
175
175
|
if ( isRenderFunction ) theData.forEach ( (d,i) => {
|
|
176
176
|
if ( d == null ) return
|
|
177
177
|
const dType = _defineDataType ( d );
|
|
178
|
-
const text = helpers[name]( d,
|
|
178
|
+
const text = helpers[name]( d, deps );
|
|
179
179
|
|
|
180
180
|
if ( text == null ) theData[i] = null
|
|
181
181
|
if ( dType === 'object' ) d['text'] = text
|
|
@@ -183,9 +183,11 @@ function build ( tpl, extra=false, buildDependencies={} ) {
|
|
|
183
183
|
})
|
|
184
184
|
else theData.forEach ( (d,i) => {
|
|
185
185
|
if ( d == null ) return
|
|
186
|
+
|
|
187
|
+
|
|
186
188
|
const
|
|
187
189
|
dType = _defineDataType ( d )
|
|
188
|
-
, text = render ( d, name, helpers,
|
|
190
|
+
, text = render ( d, name, helpers, deps )
|
|
189
191
|
;
|
|
190
192
|
if ( text == null ) theData[i] = null
|
|
191
193
|
else if ( dType === 'object' ) d['text'] = text
|
|
@@ -193,17 +195,15 @@ function build ( tpl, extra=false, buildDependencies={} ) {
|
|
|
193
195
|
})
|
|
194
196
|
break
|
|
195
197
|
case 'function':
|
|
196
|
-
nestedData[level] = helpers[name]( theData(),
|
|
198
|
+
nestedData[level] = helpers[name]( theData(), deps )
|
|
197
199
|
break
|
|
198
200
|
case 'primitive':
|
|
199
|
-
nestedData[level] = render ( theData, name, helpers,
|
|
201
|
+
nestedData[level] = render ( theData, name, helpers, deps )
|
|
200
202
|
break
|
|
201
203
|
case 'object':
|
|
202
|
-
if ( isRenderFunction ) nestedData[level][0]['text'] = helpers[name]( theData,
|
|
204
|
+
if ( isRenderFunction ) nestedData[level][0]['text'] = helpers[name]( theData, deps )
|
|
203
205
|
else {
|
|
204
|
-
|
|
205
|
-
if ( kTest ) Object.entries( theData ).forEach( ([k,v]) => v['text'] = render ( v, name, helpers, {...buildDependencies, ...dependencies} ) )
|
|
206
|
-
else theData['text'] = render ( theData, name, helpers, {...buildDependencies, ...dependencies} )
|
|
206
|
+
theData [ 'text' ] = render ( theData, name, helpers, deps )
|
|
207
207
|
}
|
|
208
208
|
break
|
|
209
209
|
} // switch renderDataType
|
|
@@ -313,7 +313,7 @@ function build ( tpl, extra=false, buildDependencies={} ) {
|
|
|
313
313
|
// Execute postprocess functions
|
|
314
314
|
if (args) return args.reduce ( (acc, fn) => {
|
|
315
315
|
if ( typeof fn !== 'function' ) return acc
|
|
316
|
-
return fn ( acc,
|
|
316
|
+
return fn ( acc, deps )
|
|
317
317
|
}, endData.join ( '' ) )
|
|
318
318
|
else return endData.join ( '' )
|
|
319
319
|
|
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
|
+
}
|