pawajs 1.4.0 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -31,8 +31,9 @@ const errorCaller = (message) => {
31
31
  }
32
32
  const client = isServer() === false
33
33
  const serverInstance = getServerInstance()
34
- if (client) {
35
- window.__pawaDev = {
34
+ const createPawaDev = () => {
35
+ const listeners = new Set();
36
+ const devTools = {
36
37
  tool: false,
37
38
  errors: [],
38
39
  totalEffect: 0,
@@ -48,49 +49,107 @@ if (client) {
48
49
  start: 0,
49
50
  end: 0
50
51
  },
52
+ _originalStyles: new Map(),
53
+
54
+ highlightElement(el) {
55
+ if (!(el instanceof HTMLElement)) return;
56
+
57
+ if (!this._originalStyles.has(el)) {
58
+ this._originalStyles.set(el, {
59
+ outline: el.style.outline,
60
+ boxShadow: el.style.boxShadow,
61
+ });
62
+ }
63
+ el.style.outline = '2px solid #f87171';
64
+ el.style.boxShadow = '0 0 10px rgba(248, 113, 113, 0.7)';
65
+ el.scrollIntoView({ behavior: 'smooth', block: 'center' });
66
+ },
67
+
68
+ unhighlightElement(el) {
69
+ if (!(el instanceof HTMLElement) || !this._originalStyles.has(el)) return;
70
+ const original = this._originalStyles.get(el);
71
+ el.style.outline = original.outline;
72
+ el.style.boxShadow = original.boxShadow;
73
+ this._originalStyles.delete(el);
74
+ },
75
+ subscribe(callback) {
76
+ listeners.add(callback);
77
+ return () => listeners.delete(callback);
78
+ },
79
+ emit(type, data) {
80
+ listeners.forEach(cb => {
81
+ try {
82
+ cb({ type, data });
83
+ } catch (e) {
84
+ console.error("PawaDev listener error:", e);
85
+ }
86
+ });
87
+ },
51
88
  setError: ({ el, msg, directives, stack, template, warn } = {}) => {
52
- if (__pawaDev.tool !== true) return
53
- if (__pawaDev.errorState) {
54
- __pawaDev.errorState.value = true
89
+ if (devTools.tool !== true) return
90
+ if (devTools.errorState) {
91
+ devTools.errorState.value = true
55
92
  }
56
- __pawaDev.errors.push({
93
+ const errorInfo = {
57
94
  el,
58
95
  msg,
59
96
  directives,
60
97
  stack,
61
98
  timestamp: Date.now(),
62
- template: template ? template : ''
63
- })
99
+ template: template ? template : '',
100
+ type: warn ? 'warning' : 'error'
101
+ }
102
+ devTools.errors.push(errorInfo)
103
+ devTools.emit('error', errorInfo)
104
+
64
105
  if (warn) {
65
- console.warn(msg, stack, template)
106
+ console.warn(msg, stack, template, el,directives)
107
+ } else {
108
+ console.error(msg, stack, template, el)
66
109
  }
67
- console.error(msg, stack)
68
110
  },
69
111
  logRender: (component, time) => {
70
- __pawaDev.renderCount++
71
- __pawaDev.performance.renderTime.push({
72
- component,
73
- time,
74
- timestamp: Date.now()
75
- })
112
+ devTools.renderCount++
113
+ const data = {
114
+ component,
115
+ time,
116
+ timestamp: Date.now()
117
+ }
118
+ devTools.performance.renderTime.push(data)
119
+ devTools.emit('render', data)
76
120
  },
77
121
  logEffect: (effect, time) => {
78
- __pawaDev.totalEffect++
79
- __pawaDev.performance.effectTime.push({
80
- effect,
81
- time,
82
- timestamp: Date.now()
83
- })
122
+ devTools.totalEffect++
123
+ const data = {
124
+ effect,
125
+ time,
126
+ timestamp: Date.now()
127
+ }
128
+ devTools.performance.effectTime.push(data)
129
+ devTools.emit('effect', data)
84
130
  },
85
131
  logComponent: (name, time) => {
86
- __pawaDev.components.add(name)
87
- __pawaDev.performance.componentTime.push({
132
+ devTools.components.add(name)
133
+ const data = {
88
134
  name,
89
135
  time,
90
136
  timestamp: Date.now()
91
- })
137
+ }
138
+ devTools.performance.componentTime.push(data)
139
+ devTools.emit('component', data)
92
140
  }
93
141
  }
142
+ return devTools;
143
+ }
144
+
145
+ const pawaDevInstance = createPawaDev();
146
+
147
+ if (typeof globalThis !== 'undefined') {
148
+ globalThis.__pawaDev = pawaDevInstance;
149
+ } else if (typeof window !== 'undefined') {
150
+ window.__pawaDev = pawaDevInstance;
151
+ } else if (typeof global !== 'undefined') {
152
+ global.__pawaDev = pawaDevInstance;
94
153
  }
95
154
 
96
155
  const compoBeforeCall = new Set()
@@ -872,11 +931,6 @@ const mainAttribute = (el, exp) => {
872
931
  let value = attrMap.get(exp.name);
873
932
  let isBoolean
874
933
  const regex = /@{([^}]*)}/g;
875
- const keys = Object.keys(el._context);
876
- const resolvePath = (path, obj) => {
877
- return path.split('.').reduce((acc, key) => acc?.[key], obj);
878
- };
879
- const values = keys.map((key) => resolvePath(key, el._context));
880
934
 
881
935
  const hasExpression = regex.test(value);
882
936
  regex.lastIndex = 0;
@@ -885,11 +939,10 @@ const mainAttribute = (el, exp) => {
885
939
  if (checkKeywordsExistence(el._staticContext, expression)) {
886
940
  return ''
887
941
  } else {
888
- const func = new Function(...keys, `return ${expression}`);
889
- const result = func(...values)
942
+ const result = el.safeEval(el._context, expression, `error at attribute ${exp.name}`, true)
890
943
  isBoolean = result
891
944
  if (typeof result !== 'boolean') {
892
- return result
945
+ return result ?? ''
893
946
  }else{
894
947
  return ''
895
948
  }
@@ -924,11 +977,13 @@ const mainAttribute = (el, exp) => {
924
977
  }
925
978
  } catch (error) {
926
979
  console.warn(`failed at attribute ${exp.name}`, el)
927
- setPawaDevError({
928
- message: `error at attribute ${error.message}`,
929
- error: error,
930
- template: el._template
931
- })
980
+ __pawaDev.setError({
981
+ el:el,
982
+ msg:`from ${exp.name} ${exp.value}`,
983
+ directives:exp.name,
984
+ stack:error.stack,
985
+ template:el?._template,
986
+ })
932
987
  }
933
988
  };
934
989
  createEffect(() => {
@@ -958,20 +1013,14 @@ const textContentHandler = (el, isName) => {
958
1013
  let value = nodesMap.get(textNode);
959
1014
  const regex = /@{([^}]*)}/g;
960
1015
 
961
- const keys = Object.keys(el._context);
962
- const resolvePath = (path, obj) => {
963
- return path.split('.').reduce((acc, key) => acc?.[key], obj);
964
- };
965
- const values = keys.map((key) => resolvePath(key, el._context));
966
-
967
1016
  value = value.replace(regex, (match, expression) => {
968
1017
  if (checkKeywordsExistence(el._staticContext, expression)) {
969
1018
  return ''
970
1019
  } else {
971
-
1020
+ if(expression === '')return value
972
1021
  el._textContent[expression] = value
973
- const func = new Function(...keys, `return ${expression}`);
974
- return String(func(...values));
1022
+ const res = el.safeEval(el._context, expression, 'textContent', true)
1023
+ return String(res ?? '');
975
1024
  }
976
1025
  });
977
1026
  if(el.tagName === 'TEXTAREA'){
package/merger/for.js CHANGED
@@ -6,31 +6,21 @@ import { processNode, pawaWayRemover, safeEval, getEvalValues, setPawaDevError,
6
6
  export const merger_for = (el, stateContext, attr, arrayName, arrayItem, indexes, resume,
7
7
  { comment, endComment, unique, elementArray, insertIndex,keyOrders }) => {
8
8
  let firstEnter
9
- let func
10
9
  let once=false
11
10
  let promised
11
+ let func
12
+ let context=el._context
12
13
  const keyOrder=keyOrders || new Map()
13
14
  const evaluate = () => {
14
15
  if (endComment.parentElement === null) {
15
16
  el._deleteEffects()
16
17
  }
17
18
  try {
18
- const keys = Object.keys(el._context);
19
- const resolvePath = (path, obj) => {
20
- return path.split('.').reduce((acc, key) => acc?.[key], obj);
21
- };
22
- const values = keys.map((key) => resolvePath(key, el._context));
23
-
24
- let array
25
19
  if (!func) {
26
-
27
- const funcs = new Function(...keys, `
28
- return ${arrayName}
29
- `)
30
- func = funcs
20
+ func=el.safeEval(el._context, arrayName, 'for-each');
31
21
  }
32
- let update
33
- array = func(...values)
22
+ let array = func(...getEvalValues(context))
23
+ let update;
34
24
  if (!firstEnter) {
35
25
  const div = document.createElement('div')
36
26
  array.forEach((item, index) => {
@@ -42,7 +32,7 @@ export const merger_for = (el, stateContext, attr, arrayName, arrayItem, indexes
42
32
  }
43
33
  const newElement = el._attrElement('for-each')
44
34
  newElement.setAttribute('data-for-index', index)
45
- processNode(newElement, itemContext)
35
+ processNode(newElement, itemContext, el)
46
36
  div.appendChild(newElement)
47
37
  })
48
38
  const removeElement = []
@@ -131,7 +121,7 @@ export const merger_for = (el, stateContext, attr, arrayName, arrayItem, indexes
131
121
  child.setAttribute('for-unique', unique)
132
122
  child.setAttribute('data-for-index', index)
133
123
  keyComment._index = index
134
- processNode(child, itemContext)
124
+ processNode(child, itemContext, el)
135
125
 
136
126
  endComment.parentElement.insertBefore(endKeyComment, endComment)
137
127
  endKeyComment.parentElement.insertBefore(keyComment, endKeyComment)
@@ -174,7 +164,7 @@ export const merger_for = (el, stateContext, attr, arrayName, arrayItem, indexes
174
164
  keyComment._endComment = endKeyComment
175
165
  newElement.setAttribute('for-unique', unique)
176
166
  newElement.setAttribute('data-for-index', index)
177
- processNode(newElement, itemContext)
167
+ processNode(newElement, itemContext, el)
178
168
  keyOrder.set(index,{comment:keyComment})
179
169
  keyComment._index = index
180
170
  keyComment._setKey(newElement.getAttribute('for-key') || index)
@@ -215,7 +205,8 @@ export const merger_for = (el, stateContext, attr, arrayName, arrayItem, indexes
215
205
  setPawaDevError({
216
206
  message: `Error from For directive ${error.message}`,
217
207
  error: error,
218
- template: el._template
208
+ template: el._template,
209
+ el: el._el
219
210
  })
220
211
  }
221
212
  }
package/merger/if.js CHANGED
@@ -6,6 +6,7 @@ export const merger_if=(el,attr,stateContext,resume=false,{comment,endComment,ch
6
6
  let removePromise=null
7
7
  let promised=false
8
8
  let firstEnter = false
9
+ const elementArray=[]
9
10
  const parent = endComment.parentElement
10
11
  let latestChain
11
12
  let oldChain
@@ -22,7 +23,7 @@ export const merger_if=(el,attr,stateContext,resume=false,{comment,endComment,ch
22
23
  func =new Map()
23
24
  chained.forEach((item)=>{
24
25
  if(item.condition === 'else')return
25
- let funcs=safeEval(el._context,item.exp,item.element)
26
+ let funcs=el.safeEval(el._context,item.exp,'if')
26
27
  func.set(item.exp,funcs)
27
28
  })
28
29
  }
@@ -114,12 +115,16 @@ export const merger_if=(el,attr,stateContext,resume=false,{comment,endComment,ch
114
115
  oldChain=latestChain
115
116
  firstEnter=true
116
117
  } catch (error) {
117
- console.log(error.message,error.stack)
118
- setPawaDevError({
119
- message: `Error from IF directive ${error.message}`,
120
- error: error,
121
- template: el._template
122
- })
118
+ console.error(error.message,error.stack,el,chainMap)
119
+ console.warn(error.message,error.stack,el,'error at if/else-if/else directive check the exprresion')
120
+
121
+ __pawaDev.setError({
122
+ el:el,
123
+ msg:`from {if/elseif/else} ${attr.value}`,
124
+ directives:'if/elseif/else',
125
+ stack:error.stack,
126
+ template:el?._template,
127
+ })
123
128
  }
124
129
  }
125
130
  return evaluate
package/merger/key.js CHANGED
@@ -21,7 +21,7 @@ export const merger_key=(el,attr,stateContext,resume=false,{comment,endComment,c
21
21
  let value=attr.value
22
22
  let keyValue
23
23
  if (!func) {
24
- func=safeEval(el._context,attr.value,el)
24
+ func=el.safeEval(el._context,attr.value,'key')
25
25
  }
26
26
  const values = getEvalValues(el._context)
27
27
  let current
@@ -89,12 +89,15 @@ export const merger_key=(el,attr,stateContext,resume=false,{comment,endComment,c
89
89
 
90
90
  firstEnter=true
91
91
  } catch (error) {
92
- console.log(error.message,error.stack)
93
- setPawaDevError({
94
- message: `Error from IF directive ${error.message}`,
95
- error: error,
96
- template: el._template
97
- })
92
+ console.error(error.message,error.stack,el,attr.value)
93
+ console.warn(error.message,error.stack,el,'error at key direcive check your expression')
94
+ __pawaDev.setError({
95
+ el:el,
96
+ msg:`from {key} ${attr.value}`,
97
+ directives:'key',
98
+ stack:error.stack,
99
+ template:el?._template,
100
+ })
98
101
  }
99
102
  }
100
103
  return evaluate
package/merger/switch.js CHANGED
@@ -115,12 +115,15 @@ export const merger_switch=(el,attr,stateContext,resume=false,{comment,endCommen
115
115
  oldChain=latestChain
116
116
  firstEnter=true
117
117
  } catch (error) {
118
- console.log(error.message,error.stack)
119
- setPawaDevError({
120
- message: `Error from IF directive ${error.message}`,
121
- error: error,
122
- template: el._template
123
- })
118
+ console.error(error.message,error.stack,el)
119
+ console.warn(error.message,error.stack,el,'from at switch case check your exprssion')
120
+ __pawaDev.setError({
121
+ el:el,
122
+ msg:`from {switch/case} ${attr.value}`,
123
+ directives:'switch/case',
124
+ stack:error.stack,
125
+ template:el?._template,
126
+ })
124
127
  }
125
128
  }
126
129
  return evaluate
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pawajs",
3
- "version": "1.4.0",
3
+ "version": "1.4.1",
4
4
  "type":"module",
5
5
  "description": "pawajs library (html runtime) for easily building web ui, enhancing html element, micro frontend etc ",
6
6
  "main": "index.js",
package/pawaElement.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import {components,escapePawaAttribute,getPawaAttributes,getDependentAttribute,getPrimaryDirectives } from './index.js';
2
- import {splitAndAdd,replaceTemplateOperators,setPawaDevError,getEvalValues,safeEval} from './utils.js';
2
+ import {splitAndAdd,replaceTemplateOperators,setPawaDevError,getEvalValues} from './utils.js';
3
3
  import PawaComponent from './pawaComponent.js';
4
4
 
5
5
 
@@ -70,6 +70,7 @@ export class PawaElement {
70
70
  this._scriptFetching=element.hasAttribute('script')
71
71
  this._scriptDone=false
72
72
  this._underControl=null
73
+ this.safeEval=this.safeEval
73
74
  /**
74
75
  * @type{object}
75
76
  */
@@ -101,6 +102,33 @@ export class PawaElement {
101
102
  getChildrenTree(){
102
103
  return Array.from(this._el.children)
103
104
  }
105
+ safeEval(context,expression,directive,resolve=false){
106
+ try{
107
+ const keys = Object.keys(context);
108
+ const resolvePath = (path, obj) => {
109
+ return path.split('.').reduce((acc, key) => acc?.[key], obj);
110
+ };
111
+ if(resolve){
112
+ return new Function(...keys,`
113
+ return ${expression}
114
+ `)(...getEvalValues(context))
115
+ }else{
116
+ return new Function(...keys,`
117
+ return ${expression}
118
+ `)
119
+ }
120
+
121
+ }catch(error){
122
+ __pawaDev.setError({
123
+ el:this?._el,
124
+ msg:`from ${expression}`,
125
+ directives:directive,
126
+ stack:error.stack,
127
+ template:this?._template,
128
+ })
129
+ }
130
+ }
131
+
104
132
  reCallEffect(){
105
133
  this._resetEffects.forEach((call)=>{
106
134
  call()
@@ -307,31 +335,19 @@ export class PawaElement {
307
335
  }else if(!pawaAttribute.has(attr.name) && attr.name.startsWith(':')){
308
336
 
309
337
  const propsName=attr.name.slice(1)
310
- try {
311
- const keys = Object.keys(this._context);
312
- const resolvePath = (path, obj) => {
313
- return path.split('.').reduce((acc, key) => acc?.[key], obj);
314
- };
315
- const values = keys.map((key) => resolvePath(key, this._context));
316
- if(attr.value === '') attr.value=true;
317
- const value=new Function(...keys,`
318
- return ()=>{
319
- try{
320
- const prop= ${replaceTemplateOperators(attr.value)};
321
- if(prop === '')return prop
322
- return prop
323
- }catch(error){
324
- console.error(error.message,error.stack)
325
- }
326
- }
327
- `)(...values)
328
- this._props[propsName]=value
329
- } catch (error) {
330
- setPawaDevError({
331
- message:`error from ${this._componentName} prop :${propsName} ${error.message}`,
332
- error:error,
333
- template:this._template
334
- })
338
+ if(attr.value === '') attr.value="true";
339
+ const expression=`()=>{
340
+ try{
341
+ const prop= ${replaceTemplateOperators(attr.value)};
342
+ if(prop === '')return prop
343
+ return prop
344
+ }catch(error){
345
+ console.error(error.message,error.stack)
346
+ }
347
+ }`
348
+ const value=this.safeEval(this._context,expression,`prop sdvd :${propsName}`,true)
349
+ if (value) {
350
+ this._props[propsName]=value
335
351
  }
336
352
  }
337
353
  })
package/utils.js CHANGED
@@ -27,7 +27,7 @@ export const pawaWayRemover=async (comment,endComment)=>{
27
27
  }
28
28
  return await pawaWayRemover(comment,endComment)
29
29
  }
30
- export const processNode = (node, itemContext) => {
30
+ export const processNode = (node, itemContext, pawaEl) => {
31
31
 
32
32
  if (typeof itemContext === 'number') {
33
33
  return
@@ -37,13 +37,9 @@ export const processNode = (node, itemContext) => {
37
37
  Array.from(node.attributes).forEach(attr => {
38
38
  if(attr.name !== 'for-key') return
39
39
  const newValue = attr.value.replace(/{{(.+?)}}/g, (match, exp) => {
40
- try {
41
- const keys = Object.keys(itemContext)
42
- const values = keys.map(key => itemContext[key])
43
- return new Function(...keys, `return ${exp}`)(...values)
44
- } catch {
45
- return match
46
- }
40
+ // The pawaEl is the element holding the for-each directive.
41
+ const result = pawaEl.safeEval(itemContext, exp, 'for-key', true);
42
+ return result ?? match;
47
43
  })
48
44
  attr.value = newValue
49
45
  })
@@ -70,9 +66,9 @@ return new Function(...keys,`return ${exp}`)(...values)
70
66
  }
71
67
  }
72
68
 
73
- export const setPawaDevError=({message,error,template})=>{
69
+ export const setPawaDevError=({message,error,template, el})=>{
74
70
  console.error(message,error.message,error.stack)
75
- __pawaDev.setError({msg:message ,stack:error.stack,el:template})
71
+ __pawaDev.setError({msg:message ,stack:error.stack,template:template, el:el})
76
72
  }
77
73
 
78
74
  export const propsValidator=(obj={},propsAttri,name,template,el)=>{
@@ -139,21 +135,11 @@ export const safeEval=(context,expression,el,resolve=false)=>{
139
135
  };
140
136
  if(resolve){
141
137
  return new Function(...keys,`
142
- try{
143
138
  return ${expression}
144
- }catch(error){
145
- console.error(error.message,error.stack)
146
- __pawaDev.setError({msg:error.message,stack:error.stack})
147
- }
148
139
  `)(...getEvalValues(context))
149
140
  }else{
150
141
  return new Function(...keys,`
151
- try{
152
- return ${expression}
153
- }catch(error){
154
- console.error(error.message,error.stack)
155
- __pawaDev.setError({msg:error.message,stack:error.stack})
156
- }
142
+ return ${expression}
157
143
  `)
158
144
  }
159
145
 
@@ -161,7 +147,7 @@ export const safeEval=(context,expression,el,resolve=false)=>{
161
147
  setPawaDevError({
162
148
  message:`Error : ${error.message} ${error.stack}`,
163
149
  error:error,
164
- template:el._template
150
+ template:el?._template
165
151
  })
166
152
  }
167
153
  }