@peter.naydenov/morph 1.2.3 → 2.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.
- package/Changelog.md +7 -0
- package/Migration.guide.md +35 -0
- package/README.md +39 -1
- package/dist/morph.cjs +1 -1
- package/dist/morph.esm.mjs +1 -1
- package/dist/morph.umd.js +1 -1
- package/package.json +2 -2
- package/src/methods/_defineData.js +7 -7
- package/src/methods/_readTemplate.js +5 -3
- package/src/methods/_setupActions.js +16 -0
- package/src/methods/build.js +24 -17
package/Changelog.md
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
## Release History
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
### 2.0.0 (2025-03-25)
|
|
5
|
+
- [x] Memory action intoduced - memory is available in data functions;
|
|
6
|
+
- [x] Change in arguments format for helper functions;
|
|
7
|
+
- [x] Overwrite action introduced - when change in data should be available for all placeholders;
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
4
11
|
|
|
5
12
|
### 1.2.3 (2025-03-17)
|
|
6
13
|
- [x] Refactoring: Extended render;
|
package/Migration.guide.md
CHANGED
|
@@ -1,6 +1,41 @@
|
|
|
1
1
|
# Migration Guides
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## 1.x.x -> 2.x.x
|
|
5
|
+
Modification of data is available only for current placeholder. If you need to remember changes in data, use the new memory action - '^something' where '^' is for memory and 'something' is the name. Memory will make a snapshot of the current data and will be available in helper functions. If you need to provide changes to all placeholders, use overwrite action. It's a snapshot that will be remember as a main data and will be available for all placeholders.
|
|
6
|
+
|
|
7
|
+
Arguments for helper functions are chaged. Because we want to have many arguments and we don't want to think about their order, we make an object with named arguments. Available arguments are: data, dependencies, memory.
|
|
8
|
+
|
|
9
|
+
```js
|
|
10
|
+
// Before
|
|
11
|
+
const template = {
|
|
12
|
+
template : `Hello from {{ @all : name }}. I'm {{ age }} years old {{ job }}`
|
|
13
|
+
, helpers : {
|
|
14
|
+
name: ( data ) => data.name // Change in arguments of helper functions!
|
|
15
|
+
}
|
|
16
|
+
, handshake: {
|
|
17
|
+
name: 'Peter'
|
|
18
|
+
, age: 40
|
|
19
|
+
, job: 'developer'
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// After
|
|
24
|
+
const template = {
|
|
25
|
+
template : `Hello from {{ @all : name }}. I'm {{ age }} years old {{ job }}`
|
|
26
|
+
, helpers : {
|
|
27
|
+
name: ({ data, memory, dependencies }) => data.name // data is named argument
|
|
28
|
+
}
|
|
29
|
+
, handshake: {
|
|
30
|
+
name: 'Peter'
|
|
31
|
+
, age: 40
|
|
32
|
+
, job: 'developer'
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
4
39
|
## 0.x.x -> 1.x.x
|
|
5
40
|
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
41
|
|
package/README.md
CHANGED
|
@@ -8,6 +8,15 @@
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
|
|
11
|
+
## What's new in version 2.x.x
|
|
12
|
+
- Data helper functions modifies the data per placeholder;
|
|
13
|
+
- Arguments for helper functions are named arguments;
|
|
14
|
+
- Memory action introduced - memory is available in helper functions as a named argument;
|
|
15
|
+
- Overwrite action introduced - when change in data should be available for all placeholders;
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
11
20
|
## General Information
|
|
12
21
|
|
|
13
22
|
`Morph` has a logic-less template syntax. Placeholders are places surrounded by double curly braces `{{ }}` and they represents the pleces where the data will be inserted.
|
|
@@ -17,6 +26,7 @@ Some features of Morph:
|
|
|
17
26
|
- Simple logic-less template syntax;
|
|
18
27
|
- Builtin storage;
|
|
19
28
|
- Powerfull action system for data decoration;
|
|
29
|
+
- Demo request can render the template with the builtin data;
|
|
20
30
|
- Nesting templates as part of the action system;
|
|
21
31
|
- Partial rendering (render only available data);
|
|
22
32
|
- Option to connect templates to external data sources;
|
|
@@ -26,6 +36,10 @@ Some features of Morph:
|
|
|
26
36
|
|
|
27
37
|
|
|
28
38
|
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
29
43
|
## Installation
|
|
30
44
|
|
|
31
45
|
```
|
|
@@ -50,13 +64,22 @@ import morph from "@peter.naydenov/morph"
|
|
|
50
64
|
|
|
51
65
|
const myTemplateDescription = {
|
|
52
66
|
template: `Hello, {{name}}!` // simple template - a string with a placeholder
|
|
67
|
+
, helers : {
|
|
68
|
+
// helper functions
|
|
69
|
+
}
|
|
70
|
+
, handshake : {
|
|
71
|
+
// ... demo data here
|
|
72
|
+
name : 'Ivan'
|
|
73
|
+
}
|
|
53
74
|
}
|
|
54
75
|
const myTemplate = morph.build ( myTemplateDescription ); // myTemplate is a render function
|
|
55
76
|
const htmlBlock = myTemplate ( { name: 'Peter' } ) // Provide data to the render function and get the result
|
|
56
77
|
// htmlBlock === 'Hello, Peter!'
|
|
78
|
+
const demo = myTemplate ( 'demo' )
|
|
79
|
+
// demo === 'Hello, Ivan!'
|
|
57
80
|
```
|
|
58
81
|
|
|
59
|
-
Morph contains also a builtin template
|
|
82
|
+
Morph contains also a builtin template storages. Instead of creating variable for each template, we can use the storages.
|
|
60
83
|
|
|
61
84
|
```js
|
|
62
85
|
// add template to the storage. Automatically builds the render function
|
|
@@ -64,6 +87,14 @@ Morph contains also a builtin template storage. Instead of creating variable for
|
|
|
64
87
|
morph.add ( ['myTemplate'], myTemplateDescription )
|
|
65
88
|
// get template from the storage and render it
|
|
66
89
|
const htmlBlock = morph.get ( ['myTemplate'] )({ name: 'Peter' })
|
|
90
|
+
// it's same as text above
|
|
91
|
+
morph.add ( ['myTemplate', 'default'], myTemplateDescription )
|
|
92
|
+
const htmlBlock = morph.get ( ['myTemplate', 'default'] )({ name: 'Peter' })
|
|
93
|
+
// if we use custom storage:
|
|
94
|
+
morph.add ( ['myTemplate', 'hidden'], myTemplateDescription ) // write template in storage 'hidden'
|
|
95
|
+
const htmlBlock = morph.get ( ['myTemplate', 'hidden'] )({ name: 'Peter' }) // render template from 'hidden' storage
|
|
96
|
+
morph.get ( ['myTemplate'] )({ name: 'Peter' }) // call template 'myTemplate' from default storage
|
|
97
|
+
// will return error, because default storage does not have template "myTemplate"
|
|
67
98
|
```
|
|
68
99
|
|
|
69
100
|
Let's see a more complex example before we go into details:
|
|
@@ -80,6 +111,9 @@ const myTemplateDescription = {
|
|
|
80
111
|
, a: `<a href="{{href}}">{{text}}</a>`
|
|
81
112
|
, getAge: (person) => person.age
|
|
82
113
|
}
|
|
114
|
+
, handshake: {
|
|
115
|
+
// ... demo data here
|
|
116
|
+
}
|
|
83
117
|
}
|
|
84
118
|
const myTemplate = morph.build ( myTemplateDescription );
|
|
85
119
|
const htmlBlock = myTemplate ( { person: {
|
|
@@ -182,6 +216,10 @@ Actions are concise representations of a sequence of function calls. Some functi
|
|
|
182
216
|
- `Mixing` functions start with '[]';
|
|
183
217
|
- `Conditional render` actions start with '?';
|
|
184
218
|
- `Extended render` start with '+';
|
|
219
|
+
- `Memory` actions start with '^'. Memory action will take a data snapshot and will be available in helper functions as a named argument 'memory'. The name after the prefix is the name of the snapshot. Request saved data from helper functions by calling 'memory[name]';
|
|
220
|
+
- `Overwrite` action is marked with '^^'. Means that the current data will be available for all placeholders, not only for the current placeholder;
|
|
221
|
+
|
|
222
|
+
|
|
185
223
|
|
|
186
224
|
Here are some examples:
|
|
187
225
|
```js
|
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]]};const o=structuredClone(t);if(!r.includes("#"))return n.push([o]),{dataDeepLevel:0,nestedData:n};return e({data:o,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 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||!(!e.startsWith("^")||"^^"===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=[],u={};let d=s(r),b={...l,...n};if(r=e({data:r}),"null"===d)return m.join("");if("string"==typeof r)switch(r){case"raw":return m.join("");case"demo":if(!h)return"Error: No handshake data.";d=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"!==d&&(r=[r]),"null"===d?m.join(""):(r.forEach((r=>{f.forEach((n=>{const{index:o,data:i,action:l}=n,f=!l&&i,d=structuredClone(u),h={dependencies:b,memory:d};if(f){const e=r[i];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:f}=a("@all"===i||null===i||"@root"===i?r:r[i],l),d=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("^")&&"^^"!==e?(r[a].push({type:"save",name:e.replace("^",""),level:a}),!0):"^^"===e?(r[a].push({type:"overwrite",name:"none",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 d){let{type:n,name:a,level:o}=t;(f[o]||[]).forEach((t=>{let i=s(t);switch(n){case"route":switch(i){case"array":t.forEach(((e,r)=>{if(null==e)return;const n=s(e),o=p[a]({data:e,...h});null!=o&&("object"===n?t[r].text=c(e,o,p,b):t[r]=c(e,o,p,b))}));break;case"object":t.text=c(t,a,p,b)}break;case"save":u[a]=structuredClone(t);break;case"overwrite":r=structuredClone(t);break;case"data":switch(i){case"array":t.forEach(((e,r)=>t[r]=e instanceof Function?p[a]({data:e(),...h}):p[a]({data:e,...h})));break;case"object":f[o]=[p[a]({data:t,...h})];break;case"function":f[o]=[p[a]({data:t(),...h})];break;case"primitive":f[o]=p[a]({data:t,...h})}break;case"render":const l="function"==typeof p[a];switch(i){case"array":l?t.forEach(((e,r)=>{if(null==e)return;const n=s(e),o=p[a]({data:e,...h});null==o&&(t[r]=null),"object"===n?e.text=o:t[r]=o})):t.forEach(((e,r)=>{if(null==e)return;const n=s(e),o=c(e,a,p,b);null==o?t[r]=null:"object"===n?e.text=o:t[r]=o}));break;case"function":f[o]=p[a]({data:t(),...h});break;case"primitive":f[o]=c(t,a,p,b);break;case"object":l?f[o][0].text=p[a]({data:t,...h}):t.text=c(t,a,p,b)}break;case"extendedRender":"function"==typeof p[a]&&f[0].forEach(((e,t)=>f[0][t]=p[a]({data:e,...h})));break;case"mix":if(""===a)switch(i){case"object":Object.keys(t).find((e=>e.includes("/")))?Object.entries(t).forEach((([e,t])=>f[o][e]=t.text)):f[o]=t.text;for(let m=o-1;m>=0;m--)f[m]=e({data:f[m],objectCallback:d});function d({value:e,breadcrumbs:t}){return f[o][t]?f[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 y=p[a]({data:t,...h}),v=s(y);switch(t.forEach(((e,r)=>t.splice(r,1))),t.length=0,v){case"primitive":t[0]=y;break;case"array":t.push(...y)}}}}))}if(f instanceof Array&&1===f.length&&f[0]instanceof Array&&(f=f[0]),null==f[0])return;let y=s(f[0]),v=f[0];switch(y){case"primitive":if(null==v)return;m[o]=v;break;case"object":if(null==v.text)return;m[o]=v.text;break;case"array":const e=s(v[0]);m[o]="object"===e?v.map((e=>e.text)).join(""):v.join("")}}})),i.push(m.join(""))})),"array"===d?i:o?o.reduce(((e,t)=>"function"!=typeof t?e:t(e,b)),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.`}};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]]};const o=structuredClone(t);if(!r.includes("#"))return n.push([o]),{dataDeepLevel:0,nestedData:n};return e({data:o,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 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||!(!e.startsWith("^")||"^^"===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 m(){return u}return i?[!1,m]:m}{let b=structuredClone(d);function y(r={},n={},...o){const i=[],u={};let d=s(r),m={...l,...n};if(r=e({data:r}),"null"===d)return b.join("");if("string"==typeof r)switch(r){case"raw":return b.join("");case"demo":if(!h)return"Error: No handshake data.";d=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"!==d&&(r=[r]),"null"===d?b.join(""):(r.forEach((r=>{f.forEach((n=>{const{index:o,data:i,action:l}=n,f=!l&&i,d=structuredClone(u),h={dependencies:m,memory:d};if(f){const e=r[i];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:f}=a("@all"===i||null===i||"@root"===i?r:r[i],l),d=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("^")&&"^^"!==e?(r[a].push({type:"save",name:e.replace("^",""),level:a}),!0):"^^"===e?(r[a].push({type:"overwrite",name:"none",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 d){let{type:n,name:a,level:o}=t;(f[o]||[]).forEach((t=>{let i=s(t);switch(n){case"route":switch(i){case"array":t.forEach(((e,r)=>{if(null==e)return;const n=s(e),o=p[a]({data:e,...h});null!=o&&("object"===n?t[r].text=c(e,o,p,m):t[r]=c(e,o,p,m))}));break;case"object":t.text=c(t,a,p,m)}break;case"save":u[a]=structuredClone(t);break;case"overwrite":r=structuredClone(t);break;case"data":switch(i){case"array":t.forEach(((e,r)=>t[r]=e instanceof Function?p[a]({data:e(),...h}):p[a]({data:e,...h})));break;case"object":f[o]=[p[a]({data:t,...h})];break;case"function":f[o]=[p[a]({data:t(),...h})];break;case"primitive":f[o]=p[a]({data:t,...h})}break;case"render":const l="function"==typeof p[a];switch(i){case"array":l?t.forEach(((e,r)=>{if(null==e)return;const n=s(e),o=p[a]({data:e,...h});null==o&&(t[r]=null),"object"===n?e.text=o:t[r]=o})):t.forEach(((e,r)=>{if(null==e)return;const n=s(e),o=c(e,a,p,m);null==o?t[r]=null:"object"===n?e.text=o:t[r]=o}));break;case"function":f[o]=p[a]({data:t(),...h});break;case"primitive":f[o]=c(t,a,p,m);break;case"object":l?f[o][0].text=p[a]({data:t,...h}):t.text=c(t,a,p,m)}break;case"extendedRender":"function"==typeof p[a]&&f[0].forEach(((e,t)=>f[0][t]=p[a]({data:e,...h})));break;case"mix":if(""===a)switch(i){case"object":Object.keys(t).find((e=>e.includes("/")))?Object.entries(t).forEach((([e,t])=>f[o][e]=t.text)):f[o]=t.text;for(let b=o-1;b>=0;b--)f[b]=e({data:f[b],objectCallback:d});function d({value:e,breadcrumbs:t}){return f[o][t]?f[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 y=p[a]({data:t,...h}),v=s(y);switch(t.forEach(((e,r)=>t.splice(r,1))),t.length=0,v){case"primitive":t[0]=y;break;case"array":t.push(...y)}}}}))}if(f instanceof Array&&1===f.length&&f[0]instanceof Array&&(f=f[0]),null==f[0])return;let y=s(f[0]),v=f[0];switch(y){case"primitive":if(null==v)return;b[o]=v;break;case"object":if(null==v.text)return;b[o]=v.text;break;case"array":const e=s(v[0]);b[o]="object"===e?v.map((e=>e.text)).join(""):v.join("")}}})),i.push(b.join(""))})),"array"===d?i:o?o.reduce(((e,t)=>"function"!=typeof t?e:t(e,m)),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(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[0].forEach(((e,t)=>u[0][t]=d[n](e)));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.`}}}));
|
|
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:l,TG_SIZE_S:s}=e;let i,c,u,f=[];if("string"!=typeof n)return r("notAString");if(0==n.length)return[];if(i=n.indexOf(a),0<i&&f.push(n.slice(0,i)),-1==i)return f.push(n),f;{if(u=n.indexOf(a,i+l),c=n.indexOf(o),-1==c)return r("missingClosing");if(c<i)return r("closedBeforeOpened");if(c+=s,-1!=u&&u<c)return r("newBeforeClosed");f.push(n.slice(i,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]]};const o=structuredClone(t);if(!r.includes("#"))return n.push([o]),{dataDeepLevel:0,nestedData:n};return e({data:o,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}}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(),l=!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 i(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:s,pullReverse:function(e=1,t=0){let r=s(e,t);return r instanceof Array?r.reverse():r},peek:i,peekReverse:function(e=1,t=0){const r=i(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 i=!1;if("full"!==a||!l){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&&(i=s(o-n))}return t=e instanceof Array?t.concat(e):t.concat([e]),l=!!n&&t.length===n,i||void 0}}:function(e){const r=e instanceof Array,o=r?e.length:1;let i=!1;if("full"!==a||!l){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&&(i=s(o-n))}return t=r?e.reduce(((e,t)=>[t,...e]),t):[e].reduce(((e,t)=>[t,...e]),t),l=!!n&&t.length===n,i||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 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 s(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 l="function"==typeof n[r];return e=function(e={}){return"string"==typeof e?{text:e}:e}(e),l?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 i(r,i=!1,c={}){const{hasError:u,placeholders:f,chop:d,helpers:p,handshake:h}=function(e){const{template:r,helpers:n={},handshake:a}=e,{TG_PRX:l,TG_SFX:s}=o,i=[],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(l+"\\s*(.*?)\\s*(?::\\s*(.*?)\\s*)?"+s,"g");if(e.includes(l)){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||!(!e.startsWith("^")||"^^"===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}}(r);if(u){function m(){return u}return i?[!1,m]:m}{let y=structuredClone(d);function g(t={},r={},...o){const i=[],u={};let d=l(t),m={...c,...r};if(t=e({data:t}),"null"===d)return y.join("");if("string"==typeof t)switch(t){case"raw":return y.join("");case"demo":if(!h)return"Error: No handshake data.";d=l(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"!==d&&(t=[t]),"null"===d?y.join(""):(t.forEach((t=>{f.forEach((r=>{const{index:o,data:i,action:c}=r,f=!c&&i,d=structuredClone(u),h={dependencies:m,memory:d};if(f){const e=t[i];switch(l(e)){case"function":return void(y[o]=e());case"primitive":return void(y[o]=e);case"array":return void("primitive"===l(e[0])&&(y[o]=e[0]));case"object":return void(e.text&&(y[o]=e.text))}}else{let{dataDeepLevel:r,nestedData:f}=n("@all"===i||null===i||"@root"===i?t:t[i],c),d=a(function(e,t=10){let r={},n=[...e],a=0,o=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[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("^")&&"^^"!==e?(r[a].push({type:"save",name:e.replace("^",""),level:a}),!0):"^^"===e?(r[a].push({type:"overwrite",name:"none",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}(c,r),r);for(let r of d){let{type:n,name:a,level:o}=r;(f[o]||[]).forEach((r=>{let i=l(r);switch(n){case"route":switch(i){case"array":r.forEach(((e,t)=>{if(null==e)return;const n=l(e),o=p[a]({data:e,...h});null!=o&&("object"===n?r[t].text=s(e,o,p,m):r[t]=s(e,o,p,m))}));break;case"object":r.text=s(r,a,p,m)}break;case"save":u[a]=structuredClone(r);break;case"overwrite":t=structuredClone(r);break;case"data":switch(i){case"array":r.forEach(((e,t)=>r[t]=e instanceof Function?p[a]({data:e(),...h}):p[a]({data:e,...h})));break;case"object":f[o]=[p[a]({data:r,...h})];break;case"function":f[o]=[p[a]({data:r(),...h})];break;case"primitive":f[o]=p[a]({data:r,...h})}break;case"render":const c="function"==typeof p[a];switch(i){case"array":c?r.forEach(((e,t)=>{if(null==e)return;const n=l(e),o=p[a]({data:e,...h});null==o&&(r[t]=null),"object"===n?e.text=o:r[t]=o})):r.forEach(((e,t)=>{if(null==e)return;const n=l(e),o=s(e,a,p,m);null==o?r[t]=null:"object"===n?e.text=o:r[t]=o}));break;case"function":f[o]=p[a]({data:r(),...h});break;case"primitive":f[o]=s(r,a,p,m);break;case"object":c?f[o][0].text=p[a]({data:r,...h}):r.text=s(r,a,p,m)}break;case"extendedRender":"function"==typeof p[a]&&f[0].forEach(((e,t)=>f[0][t]=p[a]({data:e,...h})));break;case"mix":if(""===a)switch(i){case"object":Object.keys(r).find((e=>e.includes("/")))?Object.entries(r).forEach((([e,t])=>f[o][e]=t.text)):f[o]=r.text;for(let y=o-1;y>=0;y--)f[y]=e({data:f[y],objectCallback:d});function d({value:e,breadcrumbs:t}){return f[o][t]?f[o][t]:e}break;case"array":r.forEach(((e,t)=>{if(t>0){let n=l(e);if(null==e)return;r[0]+="object"===n?`${e.text}`:`${e}`,r.toSpliced(t,1)}else{let t=l(e);if(r[0]="",null===t)return;r[0]="object"===t?`${e.text}`:`${e}`}})),r.length=1}else{let g=p[a]({data:r,...h}),b=l(g);switch(r.forEach(((e,t)=>r.splice(t,1))),r.length=0,b){case"primitive":r[0]=g;break;case"array":r.push(...g)}}}}))}if(f instanceof Array&&1===f.length&&f[0]instanceof Array&&(f=f[0]),null==f[0])return;let g=l(f[0]),b=f[0];switch(g){case"primitive":if(null==b)return;y[o]=b;break;case"object":if(null==b.text)return;y[o]=b.text;break;case"array":const e=l(b[0]);y[o]="object"===e?b.map((e=>e.text)).join(""):b.join("")}}})),i.push(y.join(""))})),"array"===d?i:o?o.reduce(((e,t)=>"function"!=typeof t?e:t(e,m)),i.join("")):i.join(""))}return i?[!0,g]:g}}const c={default:{}};return{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 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,l=!0;if(c[a]||(c[a]={}),"function"!=typeof t){let e=i(t,!0,...r);l=e[0],o=e[1]}l?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,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peter.naydenov/morph",
|
|
3
3
|
"description": "Template engine",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "2.0.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Peter Naydenov",
|
|
7
7
|
"main": "./src/main.js",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"c8": "^10.1.3",
|
|
34
34
|
"chai": "5.2.0",
|
|
35
35
|
"mocha": "11.1.0",
|
|
36
|
-
"rollup": "^4.
|
|
36
|
+
"rollup": "^4.37.0"
|
|
37
37
|
},
|
|
38
38
|
"repository": {
|
|
39
39
|
"type": "git",
|
|
@@ -2,22 +2,22 @@ import walk from '@peter.naydenov/walk'
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
function _defineData (
|
|
5
|
+
function _defineData ( dSource, action ) {
|
|
6
6
|
const nestedData = [];
|
|
7
7
|
let dataDeepLevel = 0;
|
|
8
8
|
|
|
9
|
-
if (
|
|
10
|
-
if (
|
|
11
|
-
if ( typeof
|
|
9
|
+
if ( dSource instanceof Function ) return { dataDeepLevel:0, nestedData:[[dSource()]] }
|
|
10
|
+
if ( dSource == null ) return { dataDeepLevel:0, nestedData:[ null ] }
|
|
11
|
+
if ( typeof dSource === 'string' ) return { dataDeepLevel:0, nestedData:[[dSource]] }
|
|
12
|
+
|
|
13
|
+
const d = structuredClone ( dSource )
|
|
12
14
|
|
|
13
15
|
// Note: Nest data only if action has '#'
|
|
14
16
|
if ( !action.includes('#') ) {
|
|
15
17
|
nestedData.push ( [d] )
|
|
16
18
|
return { dataDeepLevel:0, nestedData }
|
|
17
19
|
}
|
|
18
|
-
|
|
19
|
-
// nestedData[0] = [d]
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
function findObjects ({key, value, breadcrumbs}) {
|
|
22
22
|
if ( key === breadcrumbs ) {
|
|
23
23
|
nestedData[0] = [ value ]
|
|
@@ -52,13 +52,15 @@ function _readTemplate ( tpl ) {
|
|
|
52
52
|
placeholders.forEach ( holder => {
|
|
53
53
|
if ( !holder.action ) return
|
|
54
54
|
holder.action.every ( act => {
|
|
55
|
-
if ( act === '#'
|
|
55
|
+
if ( act === '#' ) return true
|
|
56
|
+
if ( act === '^^' ) return true
|
|
57
|
+
if ( act.startsWith('^') && act !== '^^' ) return true
|
|
56
58
|
if ( act.startsWith ( '?' )) act = act.replace ( '?', '' )
|
|
57
59
|
if ( act.startsWith ( '+' )) act = act.replace ( '+', '' )
|
|
58
60
|
if ( act.startsWith ( '[]' )) act = act.replace ( '[]', '' )
|
|
59
61
|
if ( act.startsWith ( '>' )) act = act.replace ( '>', '' )
|
|
60
|
-
if ( act === '' )
|
|
61
|
-
if ( helpers[act] )
|
|
62
|
+
if ( act === '' ) return true
|
|
63
|
+
if ( helpers[act] ) return true
|
|
62
64
|
else {
|
|
63
65
|
hasError = `Error: Missing helper: ${act}`
|
|
64
66
|
return false
|
|
@@ -31,6 +31,22 @@ function _setupActions ( actions, dataDeepLevel=10 ) {
|
|
|
31
31
|
})
|
|
32
32
|
return true
|
|
33
33
|
}
|
|
34
|
+
if ( act.startsWith ('^') && act !== '^^' ) {
|
|
35
|
+
actSetup[actLevel].push ({
|
|
36
|
+
type: 'save'
|
|
37
|
+
, name: act.replace ( '^', '' )
|
|
38
|
+
, level: actLevel
|
|
39
|
+
})
|
|
40
|
+
return true
|
|
41
|
+
}
|
|
42
|
+
if ( act === '^^') {
|
|
43
|
+
actSetup[actLevel].push ({
|
|
44
|
+
type: 'overwrite'
|
|
45
|
+
, name : 'none'
|
|
46
|
+
, level: actLevel
|
|
47
|
+
})
|
|
48
|
+
return true
|
|
49
|
+
}
|
|
34
50
|
if ( act.startsWith ( '+' ) ) { // it's a extended render action
|
|
35
51
|
actSetup[actLevel].push ({
|
|
36
52
|
type: 'extendedRender'
|
package/src/methods/build.js
CHANGED
|
@@ -60,9 +60,10 @@ function build ( tpl, extra=false, buildDependencies={} ) {
|
|
|
60
60
|
*/
|
|
61
61
|
function success ( d={}, dependencies={}, ...args ) {
|
|
62
62
|
const endData = [];
|
|
63
|
+
const memory = {};
|
|
63
64
|
let topLevelType = _defineDataType ( d );
|
|
64
65
|
let deps = { ...buildDependencies, ...dependencies }
|
|
65
|
-
d = walk ({data:d})
|
|
66
|
+
d = walk ({data:d}) // Creates copy of data to avoid mutation of the original
|
|
66
67
|
|
|
67
68
|
if ( topLevelType === 'null' ) return cuts.join ( '' )
|
|
68
69
|
// Commands : raw, demo, handshake, placeholders
|
|
@@ -94,7 +95,9 @@ function build ( tpl, extra=false, buildDependencies={} ) {
|
|
|
94
95
|
placeholders.forEach ( holder => { // Placeholders
|
|
95
96
|
const
|
|
96
97
|
{ index, data, action } = holder // index - placeholder index, data - key of data, action - list of operations
|
|
97
|
-
, dataOnly
|
|
98
|
+
, dataOnly = !action && data
|
|
99
|
+
, mem = structuredClone ( memory )
|
|
100
|
+
, extendArguments = { dependencies: deps, memory:mem }
|
|
98
101
|
;
|
|
99
102
|
|
|
100
103
|
if ( dataOnly ) {
|
|
@@ -132,6 +135,7 @@ function build ( tpl, extra=false, buildDependencies={} ) {
|
|
|
132
135
|
levelData.forEach ( theData => {
|
|
133
136
|
let dataType = _defineDataType ( theData )
|
|
134
137
|
|
|
138
|
+
|
|
135
139
|
switch ( type ) { // Action type 'route','data', 'render', or mix -> different operations
|
|
136
140
|
case 'route':
|
|
137
141
|
switch ( dataType ) {
|
|
@@ -139,7 +143,7 @@ function build ( tpl, extra=false, buildDependencies={} ) {
|
|
|
139
143
|
theData.forEach ( (d,i) => {
|
|
140
144
|
if ( d == null ) return
|
|
141
145
|
const dType = _defineDataType ( d )
|
|
142
|
-
const routeName = helpers[name]( d );
|
|
146
|
+
const routeName = helpers[name]( {data:d, ...extendArguments});
|
|
143
147
|
if ( routeName == null ) return
|
|
144
148
|
if ( dType === 'object' ) theData[i]['text'] = render ( d, routeName, helpers, deps )
|
|
145
149
|
else theData[i] = render ( d, routeName, helpers, deps )
|
|
@@ -149,33 +153,38 @@ function build ( tpl, extra=false, buildDependencies={} ) {
|
|
|
149
153
|
theData['text'] = render ( theData, name, helpers, deps )
|
|
150
154
|
break
|
|
151
155
|
}
|
|
152
|
-
break
|
|
153
|
-
case '
|
|
156
|
+
break
|
|
157
|
+
case 'save' :
|
|
158
|
+
memory[name] = structuredClone ( theData )
|
|
159
|
+
break
|
|
160
|
+
case 'overwrite':
|
|
161
|
+
dElement = structuredClone ( theData )
|
|
162
|
+
break
|
|
163
|
+
case 'data':
|
|
154
164
|
switch ( dataType ) {
|
|
155
165
|
case 'array':
|
|
156
|
-
theData.forEach ( (d,i) => theData[i] = ( d instanceof Function ) ? helpers[name]( d() ) : helpers[name]( d ) )
|
|
166
|
+
theData.forEach ( (d,i) => theData[i] = ( d instanceof Function ) ? helpers[name]({ data:d(), ...extendArguments }) : helpers[name]( {data:d, ...extendArguments} ) )
|
|
157
167
|
break
|
|
158
168
|
case 'object':
|
|
159
|
-
nestedData[level] = [helpers[name]( theData )]
|
|
169
|
+
nestedData[level] = [helpers[name]( {data:theData,...extendArguments} )]
|
|
160
170
|
break
|
|
161
171
|
case 'function':
|
|
162
|
-
nestedData[level] = [helpers[name]( theData() )]
|
|
172
|
+
nestedData[level] = [helpers[name]( {data:theData(),...extendArguments} )]
|
|
163
173
|
break
|
|
164
174
|
case 'primitive':
|
|
165
|
-
nestedData[level] = helpers[name]( theData )
|
|
175
|
+
nestedData[level] = helpers[name]( {data:theData,...extendArguments} )
|
|
166
176
|
break
|
|
167
177
|
} // switch dataType
|
|
168
178
|
|
|
169
179
|
break
|
|
170
180
|
case 'render':
|
|
171
181
|
const isRenderFunction = typeof helpers[name] === 'function'; // Render could be a function and template.
|
|
172
|
-
|
|
173
182
|
switch ( dataType ) {
|
|
174
183
|
case 'array':
|
|
175
184
|
if ( isRenderFunction ) theData.forEach ( (d,i) => {
|
|
176
185
|
if ( d == null ) return
|
|
177
186
|
const dType = _defineDataType ( d );
|
|
178
|
-
const text = helpers[name]( d,
|
|
187
|
+
const text = helpers[name]( {data:d, ...extendArguments} );
|
|
179
188
|
|
|
180
189
|
if ( text == null ) theData[i] = null
|
|
181
190
|
if ( dType === 'object' ) d['text'] = text
|
|
@@ -183,8 +192,6 @@ function build ( tpl, extra=false, buildDependencies={} ) {
|
|
|
183
192
|
})
|
|
184
193
|
else theData.forEach ( (d,i) => {
|
|
185
194
|
if ( d == null ) return
|
|
186
|
-
|
|
187
|
-
|
|
188
195
|
const
|
|
189
196
|
dType = _defineDataType ( d )
|
|
190
197
|
, text = render ( d, name, helpers, deps )
|
|
@@ -195,13 +202,13 @@ function build ( tpl, extra=false, buildDependencies={} ) {
|
|
|
195
202
|
})
|
|
196
203
|
break
|
|
197
204
|
case 'function':
|
|
198
|
-
nestedData[level] = helpers[name]( theData(),
|
|
205
|
+
nestedData[level] = helpers[name]( {data:theData(), ...extendArguments} )
|
|
199
206
|
break
|
|
200
207
|
case 'primitive':
|
|
201
208
|
nestedData[level] = render ( theData, name, helpers, deps )
|
|
202
209
|
break
|
|
203
210
|
case 'object':
|
|
204
|
-
if ( isRenderFunction ) nestedData[level][0]['text'] = helpers[name]( theData,
|
|
211
|
+
if ( isRenderFunction ) nestedData[level][0]['text'] = helpers[name]({ data:theData, ...extendArguments} )
|
|
205
212
|
else {
|
|
206
213
|
theData [ 'text' ] = render ( theData, name, helpers, deps )
|
|
207
214
|
}
|
|
@@ -212,7 +219,7 @@ function build ( tpl, extra=false, buildDependencies={} ) {
|
|
|
212
219
|
// TODO: Test extendedRender
|
|
213
220
|
const isValid = typeof helpers[name] === 'function'; // Render could be a function and template.
|
|
214
221
|
if ( isValid ) {
|
|
215
|
-
nestedData[0].forEach ( (d,i) => nestedData[0][i] = helpers[name]( d ) )
|
|
222
|
+
nestedData[0].forEach ( (d,i) => nestedData[0][i] = helpers[name]( {data:d, ...extendArguments} ) )
|
|
216
223
|
}
|
|
217
224
|
else {
|
|
218
225
|
// TODO: Error...
|
|
@@ -256,7 +263,7 @@ function build ( tpl, extra=false, buildDependencies={} ) {
|
|
|
256
263
|
} // if name === ''
|
|
257
264
|
else {
|
|
258
265
|
let
|
|
259
|
-
val = helpers[name]( theData )
|
|
266
|
+
val = helpers[name]({ data:theData, ...extendArguments })
|
|
260
267
|
, valType = _defineDataType ( val )
|
|
261
268
|
;
|
|
262
269
|
|