pawa-ssr 1.3.7 → 1.3.9
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 +15 -14
- package/package.json +1 -1
- package/power.js +70 -89
- package/utils.js +9 -0
package/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {getServerInstance, setServer} from 'pawajs/server.js'
|
|
2
2
|
import { DOMParser,parseHTML, HTMLElement} from 'linkedom'
|
|
3
3
|
import PawaComponent from './pawaComponent.js'
|
|
4
|
-
import { propsValidator, evaluateExpr,extractAtExpressions, reArrangeAttri,resumeAttribute, pawaGenerateId } from './utils.js'
|
|
4
|
+
import { propsValidator, evaluateExpr,extractAtExpressions, reArrangeAttri,resumeAttribute, pawaGenerateId, escapeHtml } from './utils.js'
|
|
5
5
|
import {AsyncLocalStorage} from'node:async_hooks'
|
|
6
6
|
import { If,For,State,Switch, Key } from'./power.js';
|
|
7
7
|
import PawaElement from'./pawaElement.js'
|
|
@@ -882,14 +882,14 @@ const attributeHandler =async (el, attr) => {
|
|
|
882
882
|
const setSingle=(...string)=>{
|
|
883
883
|
string.forEach(v => singleElement.add(v))
|
|
884
884
|
}
|
|
885
|
-
setSingle('img','br')
|
|
885
|
+
setSingle('img', 'br', 'hr', 'input', 'meta', 'link', 'base', 'col', 'area', 'param', 'track', 'wbr');
|
|
886
886
|
const partlyPawajsDirective=new Set()
|
|
887
887
|
export const addToPartlyDirective=(...partly)=>{
|
|
888
888
|
partly.forEach((v)=>{
|
|
889
889
|
partlyPawajsDirective.add(v)
|
|
890
890
|
})
|
|
891
891
|
}
|
|
892
|
-
addToPartlyDirective('else','else-if','case')
|
|
892
|
+
addToPartlyDirective('else','else-if','case','default')
|
|
893
893
|
const checkIfRemove=(el)=>{
|
|
894
894
|
for (const v of partlyPawajsDirective) {
|
|
895
895
|
if(el.hasAttribute(v)) return true
|
|
@@ -1034,27 +1034,28 @@ export const render =async (el, contexts = {},stream) => {
|
|
|
1034
1034
|
}
|
|
1035
1035
|
}
|
|
1036
1036
|
if(!el._running){
|
|
1037
|
-
const attr=Array.from(el.attributes)
|
|
1037
|
+
const attr = Array.from(el.attributes)
|
|
1038
|
+
.map(att => `${att.name}="${escapeHtml(att.value)}"`)
|
|
1039
|
+
.join(' ');
|
|
1040
|
+
const attrStr = attr ? ` ${attr}` : '';
|
|
1038
1041
|
const isSingle=singleElement.has(el.tagName.toLowerCase())
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
}
|
|
1042
|
-
|
|
1043
|
-
|
|
1042
|
+
const tagName = el.tagName.toLowerCase();
|
|
1043
|
+
|
|
1044
|
+
stream(`<${tagName}${attrStr}${isSingle ? ' />' : '>'}`);
|
|
1045
|
+
|
|
1046
|
+
if (!isSingle) {
|
|
1044
1047
|
const children = el.childNodes;
|
|
1045
1048
|
for(const child of children){
|
|
1046
1049
|
if (child.nodeType === 3) {
|
|
1047
|
-
stream(child.nodeValue)
|
|
1050
|
+
stream(escapeHtml(child.nodeValue)) // Correct: linkedom decodes entities, so we must re-encode
|
|
1048
1051
|
}else if (child.nodeType === 8) {
|
|
1049
1052
|
stream(`<!--${child.nodeValue}-->`)
|
|
1050
1053
|
}else if (child.nodeType === 1){
|
|
1051
1054
|
await render(child, el._context,stream);
|
|
1052
1055
|
}
|
|
1053
1056
|
};
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
}
|
|
1057
|
-
|
|
1057
|
+
stream(`</${tagName}>`)
|
|
1058
|
+
}
|
|
1058
1059
|
}
|
|
1059
1060
|
|
|
1060
1061
|
el._setError()
|
package/package.json
CHANGED
package/power.js
CHANGED
|
@@ -13,31 +13,28 @@ export const If = async(el, attr,stream) => {
|
|
|
13
13
|
}]
|
|
14
14
|
const chainMap=new Map()
|
|
15
15
|
chainMap.set(el.getAttribute('if'),{condition:'if',element:el})
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
getChained(nextSiblings)
|
|
16
|
+
const getChained = (sibling) => {
|
|
17
|
+
while (sibling) {
|
|
18
|
+
const next = sibling.nextElementSibling;
|
|
19
|
+
const isElseIf = sibling.hasAttribute('else-if');
|
|
20
|
+
const isElse = sibling.hasAttribute('else');
|
|
21
|
+
|
|
22
|
+
if (isElseIf) {
|
|
23
|
+
const exp = sibling.getAttribute('else-if');
|
|
24
|
+
chained.push({ exp, condition: 'else-if', element: sibling });
|
|
25
|
+
chainMap.set(exp, { condition: 'else-if', element: sibling });
|
|
26
|
+
sibling.remove();
|
|
27
|
+
} else if (isElse) {
|
|
28
|
+
chained.push({ exp: 'false', condition: 'else', element: sibling });
|
|
29
|
+
chainMap.set('else', { condition: 'else', element: sibling });
|
|
30
|
+
sibling.remove();
|
|
31
|
+
} else {
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
sibling = next;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
getChained(nextSiblings)
|
|
41
38
|
let func=new Map()
|
|
42
39
|
let current
|
|
43
40
|
let latestChain
|
|
@@ -66,24 +63,17 @@ let latestChain
|
|
|
66
63
|
let stringHtml=''
|
|
67
64
|
const template=document.createElement('template')
|
|
68
65
|
const store=document.createElement('template')
|
|
69
|
-
chained.forEach((item
|
|
70
|
-
const clone=item.element.cloneNode(true)
|
|
71
|
-
clone._avoidPawaRender = true
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
store.appendChild(clone)
|
|
81
|
-
}else{
|
|
82
|
-
store.appendChild(clone)
|
|
83
|
-
}
|
|
84
|
-
template.appendChild(item.element)
|
|
85
|
-
|
|
86
|
-
})
|
|
66
|
+
chained.forEach((item) => {
|
|
67
|
+
const clone = item.element.cloneNode(true);
|
|
68
|
+
clone._avoidPawaRender = true;
|
|
69
|
+
Array.from(clone.attributes).forEach(at => {
|
|
70
|
+
if (at.name.startsWith('c-') || at.name === 'p:c') {
|
|
71
|
+
clone.removeAttribute(at.name);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
store.appendChild(clone);
|
|
75
|
+
template.appendChild(item.element);
|
|
76
|
+
});
|
|
87
77
|
const getRightElement=chainMap.get(latestChain.id)
|
|
88
78
|
if (getRightElement) {
|
|
89
79
|
const copyElement=getRightElement.element.cloneNode(true)
|
|
@@ -133,31 +123,28 @@ export const Switch = async(el, attr,stream) => {
|
|
|
133
123
|
}]
|
|
134
124
|
const chainMap=new Map()
|
|
135
125
|
chainMap.set(el.getAttribute('case'),{condition:'case',element:el})
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
getChained(nextSiblings)
|
|
126
|
+
const getChained = (sibling) => {
|
|
127
|
+
while (sibling) {
|
|
128
|
+
const next = sibling.nextElementSibling;
|
|
129
|
+
const isCase = sibling.hasAttribute('case');
|
|
130
|
+
const isDefault = sibling.hasAttribute('default');
|
|
131
|
+
|
|
132
|
+
if (isCase) {
|
|
133
|
+
const exp = sibling.getAttribute('case');
|
|
134
|
+
chained.push({ exp, condition: 'case', element: sibling });
|
|
135
|
+
chainMap.set(exp, { condition: 'case', element: sibling });
|
|
136
|
+
sibling.remove();
|
|
137
|
+
} else if (isDefault) {
|
|
138
|
+
chained.push({ exp: 'false', condition: 'default', element: sibling });
|
|
139
|
+
chainMap.set('default', { condition: 'default', element: sibling });
|
|
140
|
+
sibling.remove();
|
|
141
|
+
} else {
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
sibling = next;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
getChained(nextSiblings)
|
|
161
148
|
let func=new Map()
|
|
162
149
|
let current
|
|
163
150
|
let latestChain
|
|
@@ -187,24 +174,18 @@ const switchFunc=el._evaluateExpr(attr.value,el._context,`at switch directive ${
|
|
|
187
174
|
let stringHtml=''
|
|
188
175
|
const template=document.createElement('template')
|
|
189
176
|
const store=document.createElement('template')
|
|
190
|
-
let index=0
|
|
191
|
-
chained.forEach(item =>{
|
|
192
|
-
const clone=item.element.cloneNode(true)
|
|
193
|
-
clone._avoidPawaRender = true
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
}else{
|
|
203
|
-
store.appendChild(clone)
|
|
204
|
-
}
|
|
205
|
-
index++
|
|
206
|
-
template.appendChild(item.element)
|
|
207
|
-
})
|
|
177
|
+
// let index=0
|
|
178
|
+
chained.forEach((item) => {
|
|
179
|
+
const clone = item.element.cloneNode(true);
|
|
180
|
+
clone._avoidPawaRender = true;
|
|
181
|
+
Array.from(clone.attributes).forEach(at => {
|
|
182
|
+
if (at.name.startsWith('c-') || at.name === 'p:c') {
|
|
183
|
+
clone.removeAttribute(at.name);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
store.appendChild(clone);
|
|
187
|
+
template.appendChild(item.element);
|
|
188
|
+
});
|
|
208
189
|
el.removeAttribute('switch')
|
|
209
190
|
const getRightElement=chainMap.get(latestChain.id)
|
|
210
191
|
if (getRightElement && (current || latestChain.condition === 'default')) {
|
|
@@ -394,9 +375,9 @@ export const Key=async(el,attr,stream)=>{
|
|
|
394
375
|
const template=document.createElement('template')
|
|
395
376
|
template.setAttribute('p:store-key',dirId)
|
|
396
377
|
template.setAttribute('p:store','')
|
|
397
|
-
clone.attributes.forEach(at => {
|
|
398
|
-
if (at.name.startsWith('c-')) {
|
|
399
|
-
clone.removeAttribute(at.name)
|
|
378
|
+
Array.from(clone.attributes).forEach(at => {
|
|
379
|
+
if (at.name.startsWith('c-') || at.name === 'p:c') {
|
|
380
|
+
clone.removeAttribute(at.name);
|
|
400
381
|
}
|
|
401
382
|
});
|
|
402
383
|
template.appendChild(clone)
|
package/utils.js
CHANGED
|
@@ -246,3 +246,12 @@ export const replaceTemplateOperators = (expression) => {
|
|
|
246
246
|
.replace(/\*\//g, '`'); // Also replace closing */ with backtick if needed
|
|
247
247
|
};
|
|
248
248
|
|
|
249
|
+
export const escapeHtml = (unsafe) => {
|
|
250
|
+
if (unsafe === null || unsafe === undefined) return '';
|
|
251
|
+
return String(unsafe)
|
|
252
|
+
.replace(/&/g, "&")
|
|
253
|
+
.replace(/</g, "<")
|
|
254
|
+
.replace(/>/g, ">")
|
|
255
|
+
.replace(/"/g, """)
|
|
256
|
+
.replace(/'/g, "'");
|
|
257
|
+
};
|