pawa-ssr 1.3.30 → 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.d.ts +66 -0
- package/index.js +29 -113
- package/package.json +5 -3
- package/pawaElement.js +10 -12
- package/test/App.js +4 -0
- package/test/index.js +22 -5
package/index.d.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { HTMLElement } from 'linkedom';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Core rendering function that processes PawaElements/HTMLElements and writes to a stream.
|
|
5
|
+
*/
|
|
6
|
+
export function render(el: any, contexts?: object, stream?: (s: string) => void): Promise<void>;
|
|
7
|
+
|
|
8
|
+
export interface StartAppResult {
|
|
9
|
+
element: any;
|
|
10
|
+
toString: () => Promise<string>;
|
|
11
|
+
head: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Initializes and renders the application for standard SSR.
|
|
16
|
+
*/
|
|
17
|
+
export function startApp(
|
|
18
|
+
html: string,
|
|
19
|
+
context?: object,
|
|
20
|
+
development?: boolean
|
|
21
|
+
): Promise<StartAppResult>;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Initializes and renders the application using Node.js streams for performance and Suspense support.
|
|
25
|
+
*/
|
|
26
|
+
export function startStreamApp(
|
|
27
|
+
html: string,
|
|
28
|
+
context: object,
|
|
29
|
+
stream: (s: string) => void,
|
|
30
|
+
options: { templateStart: string; templateEnd: string }
|
|
31
|
+
): Promise<void>;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Adds custom directives that should be treated as part of the PawaJS directive set.
|
|
35
|
+
*/
|
|
36
|
+
export function addToPartlyDirective(...partly: string[]): void;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Returns an array of all reserved server attributes.
|
|
40
|
+
*/
|
|
41
|
+
export function getAllServerAttrArray(): string[];
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Returns the set of registered Pawa attributes.
|
|
45
|
+
*/
|
|
46
|
+
export function getPawaAttributes(): Set<string>;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Checks if the application is running in development mode.
|
|
50
|
+
*/
|
|
51
|
+
export function getDevelopment(): boolean | undefined;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Configures the server-side hooks for PawaJS.
|
|
55
|
+
*/
|
|
56
|
+
export const pawaForServer: (config: {
|
|
57
|
+
useContext: (context: { id: string }) => any;
|
|
58
|
+
useInnerContext: () => any;
|
|
59
|
+
useInsert: (obj?: object) => void;
|
|
60
|
+
setContext: () => { id: string; setValue: (context: object) => void };
|
|
61
|
+
$state: <T>(initialValue: T | (() => T)) => T;
|
|
62
|
+
accessChild: () => void;
|
|
63
|
+
useServer: () => { setServerData: (data: object) => void, getServerData: () => object } | undefined;
|
|
64
|
+
useAsync: () => { $async: <R>(callback: () => R) => R, onSuspense: (html: string) => void } | undefined;
|
|
65
|
+
forwardProps: (props?: object) => void;
|
|
66
|
+
}) => void;
|
package/index.js
CHANGED
|
@@ -243,92 +243,6 @@ const setPawaAttribute=(...attr)=>{
|
|
|
243
243
|
}
|
|
244
244
|
setPawaAttribute('if','else','else-if','for-each','case','switch','s-default','for-key','key')
|
|
245
245
|
export const getPawaAttributes=()=>pawaAttributes
|
|
246
|
-
/**
|
|
247
|
-
* @typedef {{startsWith:string,fullName:string,plugin:(el:HTMLElement | PawaElement,attr:object)=>void}} AttriPlugin
|
|
248
|
-
*/
|
|
249
|
-
/**
|
|
250
|
-
* @typedef {{
|
|
251
|
-
* attribute?:{register:Array<AttriPlugin>},
|
|
252
|
-
* component?:{
|
|
253
|
-
* beforeCall?:(stateContext:PawaComponent,app:object)=>void,
|
|
254
|
-
* afterCall?:(stateContext:PawaComponent,el:HTMLElement)=>void
|
|
255
|
-
* },
|
|
256
|
-
* renderSystem?:{
|
|
257
|
-
* beforePawa?:(el:HTMLElement,context:object)=>void,
|
|
258
|
-
* afterPawa?:(el:PawaElement)=>void,
|
|
259
|
-
* beforeChildRender?:(el:PawaElement)=>void
|
|
260
|
-
* }
|
|
261
|
-
* }} PluginObject
|
|
262
|
-
*/
|
|
263
|
-
/**
|
|
264
|
-
* @param {Array<()=>PluginObject>} func
|
|
265
|
-
*/
|
|
266
|
-
export const PluginSystem=(...func)=>{
|
|
267
|
-
func.forEach(fn=>{
|
|
268
|
-
/**
|
|
269
|
-
* @type {PluginObject}
|
|
270
|
-
*/
|
|
271
|
-
if (typeof fn !== 'function') {
|
|
272
|
-
console.warn('plugin must be a function that returns the plugin objects')
|
|
273
|
-
return
|
|
274
|
-
}
|
|
275
|
-
const getPlugin=fn()
|
|
276
|
-
// attributes plugin or extension
|
|
277
|
-
|
|
278
|
-
if (getPlugin?.attribute) {
|
|
279
|
-
getPlugin.attribute.register.forEach(attrPlugins =>{
|
|
280
|
-
if (attrPlugins.fullName && attrPlugins.startsWith) {
|
|
281
|
-
console.warn('Either Plugins FullName or startsWith. you are not required to use to of does plugin registers at this same entry.')
|
|
282
|
-
return
|
|
283
|
-
}
|
|
284
|
-
if (attrPlugins?.fullName) {
|
|
285
|
-
if (pawaAttributes.has(attrPlugins.fullName) ) {
|
|
286
|
-
console.warn(`attribute plugin already exist ${attrPlugins.fullName}`)
|
|
287
|
-
return
|
|
288
|
-
}
|
|
289
|
-
pawaAttributes.add(attrPlugins.fullName)
|
|
290
|
-
fullNamePlugin.add(attrPlugins.fullName)
|
|
291
|
-
externalPlugin[attrPlugins.fullName]=attrPlugins?.plugin
|
|
292
|
-
}else if (attrPlugins?.startsWith) {
|
|
293
|
-
if (pawaAttributes.has(attrPlugins.startsWith) ) {
|
|
294
|
-
console.warn(`attribute plugin already exist ${attrPlugins.startsWith}`)
|
|
295
|
-
return
|
|
296
|
-
}
|
|
297
|
-
pawaAttributes.add(attrPlugins.startsWith)
|
|
298
|
-
startsWithSet.add(attrPlugins.startsWith)
|
|
299
|
-
externalPlugin[attrPlugins.startsWith]=attrPlugins?.plugin
|
|
300
|
-
}
|
|
301
|
-
})
|
|
302
|
-
}
|
|
303
|
-
if (getPlugin?.component) {
|
|
304
|
-
if (getPlugin.component?.beforeCall && typeof getPlugin.component?.beforeCall === 'function') {
|
|
305
|
-
compoBeforeCall.add(getPlugin.component.beforeCall)
|
|
306
|
-
}
|
|
307
|
-
if (getPlugin.component?.afterCall && typeof getPlugin.component?.afterCall === 'function') {
|
|
308
|
-
compoAfterCall.add(getPlugin.component.afterCall)
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
if (getPlugin?.renderSystem) {
|
|
312
|
-
if (getPlugin.renderSystem?.beforePawa && typeof getPlugin.renderSystem?.beforePawa === 'function') {
|
|
313
|
-
renderBeforePawa.add(getPlugin.renderSystem?.beforePawa)
|
|
314
|
-
}
|
|
315
|
-
if (getPlugin.renderSystem?.afterPawa && typeof getPlugin.renderSystem?.afterPawa === 'function') {
|
|
316
|
-
renderAfterPawa.add(getPlugin.renderSystem?.afterPawa)
|
|
317
|
-
}
|
|
318
|
-
if (getPlugin.renderSystem?.beforeChildRender && typeof getPlugin.renderSystem?.beforeChildRender === 'function') {
|
|
319
|
-
renderBeforeChild.add(getPlugin.renderSystem?.beforeChildRender)
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
})
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
export const useValidateComponent=(component,object)=>{
|
|
326
|
-
if (typeof component === 'function' ) {
|
|
327
|
-
if(component.name){
|
|
328
|
-
component.validateProps=object
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
246
|
|
|
333
247
|
/**
|
|
334
248
|
* @typedef {{
|
|
@@ -484,12 +398,13 @@ appContext.component._prop={children,...el._props,...slots}
|
|
|
484
398
|
}else{
|
|
485
399
|
Object.assign(restProps,el._restProps)
|
|
486
400
|
}
|
|
487
|
-
|
|
488
|
-
const
|
|
489
|
-
if (
|
|
490
|
-
|
|
401
|
+
const getAsChild=(divs)=>{
|
|
402
|
+
const divFirst=divs.firstElementChild
|
|
403
|
+
if (el._aschild) {
|
|
404
|
+
divs.innerHTML=children
|
|
405
|
+
const getChildren=divs.firstElementChild
|
|
491
406
|
if (getChildren === null) return
|
|
492
|
-
Array.from(
|
|
407
|
+
Array.from(divFirst.attributes).forEach(attr=>{
|
|
493
408
|
if (getChildren.hasAttribute(attr.name)) {
|
|
494
409
|
let attrName=getChildren.getAttribute(attr.name)
|
|
495
410
|
attrName=attr.value +' '+attrName
|
|
@@ -497,12 +412,10 @@ appContext.component._prop={children,...el._props,...slots}
|
|
|
497
412
|
}else{
|
|
498
413
|
getChildren.setAttribute(attr.name, attr.value)
|
|
499
414
|
}
|
|
500
|
-
})
|
|
501
|
-
asChild.remove()
|
|
502
|
-
div.appendChild(getChildren)
|
|
415
|
+
})
|
|
503
416
|
}
|
|
504
|
-
}
|
|
505
|
-
getAsChild()
|
|
417
|
+
}
|
|
418
|
+
getAsChild(div)
|
|
506
419
|
const findElement=div.querySelector('[--]') || div.querySelector('[r-]')
|
|
507
420
|
if (findElement) {
|
|
508
421
|
for (const [key,value] of Object.entries(restProps)) {
|
|
@@ -716,11 +629,12 @@ appContext.component._prop={children,...el._props,...slots}
|
|
|
716
629
|
Object.assign(restProps,el._restProps)
|
|
717
630
|
}
|
|
718
631
|
const getAsChild=(divs)=>{
|
|
719
|
-
const
|
|
720
|
-
if (
|
|
721
|
-
|
|
632
|
+
const divFirst=divs.firstElementChild
|
|
633
|
+
if (el._aschild) {
|
|
634
|
+
divs.innerHTML=children
|
|
635
|
+
const getChildren=divs.firstElementChild
|
|
722
636
|
if (getChildren === null) return
|
|
723
|
-
Array.from(
|
|
637
|
+
Array.from(divFirst.attributes).forEach(attr=>{
|
|
724
638
|
if (getChildren.hasAttribute(attr.name)) {
|
|
725
639
|
let attrName=getChildren.getAttribute(attr.name)
|
|
726
640
|
attrName=attr.value +' '+attrName
|
|
@@ -728,9 +642,7 @@ appContext.component._prop={children,...el._props,...slots}
|
|
|
728
642
|
}else{
|
|
729
643
|
getChildren.setAttribute(attr.name, attr.value)
|
|
730
644
|
}
|
|
731
|
-
})
|
|
732
|
-
asChild.remove()
|
|
733
|
-
divs.appendChild(getChildren)
|
|
645
|
+
})
|
|
734
646
|
}
|
|
735
647
|
}
|
|
736
648
|
if (isBoundary) {
|
|
@@ -931,7 +843,11 @@ const attributeHandler =async (el, attr) => {
|
|
|
931
843
|
if (el._componentName) {
|
|
932
844
|
return
|
|
933
845
|
}
|
|
934
|
-
|
|
846
|
+
|
|
847
|
+
const isAtAttr = attr.name.startsWith('@');
|
|
848
|
+
const targetName = isAtAttr ? attr.name.slice(1) : attr.name;
|
|
849
|
+
|
|
850
|
+
el._replaceResumeAttr(attr.name, `c-at-${targetName}`, attr.value);
|
|
935
851
|
const currentHtmlString = el.outerHTML;
|
|
936
852
|
const removableAttributes = new Set();
|
|
937
853
|
removableAttributes.add('disabled');
|
|
@@ -945,18 +861,18 @@ const attributeHandler =async (el, attr) => {
|
|
|
945
861
|
const func =el._evaluateExpr(
|
|
946
862
|
expression,
|
|
947
863
|
el._context,
|
|
948
|
-
`from text interpolation @{} - ${expression} at ${currentHtmlString} attribute ${
|
|
864
|
+
`from text interpolation @{} - ${expression} at ${currentHtmlString} attribute ${targetName}`
|
|
949
865
|
);
|
|
950
866
|
value = value.replace(fullMatch, String(func));
|
|
951
867
|
});
|
|
952
|
-
if (removableAttributes.has(
|
|
868
|
+
if (removableAttributes.has(targetName)) {
|
|
953
869
|
if (value) {
|
|
954
|
-
el.setAttribute(
|
|
870
|
+
el.setAttribute(targetName, '');
|
|
955
871
|
} else {
|
|
956
|
-
el.removeAttribute(
|
|
872
|
+
el.removeAttribute(targetName);
|
|
957
873
|
}
|
|
958
874
|
} else {
|
|
959
|
-
el.setAttribute(
|
|
875
|
+
el.setAttribute(targetName, value);
|
|
960
876
|
}
|
|
961
877
|
} catch (error) {
|
|
962
878
|
console.log(error.message, error.stack);
|
|
@@ -1072,12 +988,12 @@ export const render =async (el, contexts = {},stream) => {
|
|
|
1072
988
|
for(const attr of attributes){
|
|
1073
989
|
if (directives[attr.name]) {
|
|
1074
990
|
await directives[attr.name](el,attr,stream)
|
|
1075
|
-
}else if(attr.value.includes('@{') && !isAcomponent){
|
|
991
|
+
}else if((attr.value.includes('@{') || attr.name.startsWith('@')) && !isAcomponent){
|
|
1076
992
|
await attributeHandler(el,attr)
|
|
1077
993
|
}else if (attr.name.startsWith('state-')) {
|
|
1078
994
|
directives['state-'](el,attr)
|
|
1079
995
|
}
|
|
1080
|
-
else if(fullNamePlugin.has(attr.name)) {
|
|
996
|
+
else if(fullNamePlugin.has(attr.name) && !el._componentName) {
|
|
1081
997
|
if(externalPlugin[attr.name]){
|
|
1082
998
|
const plugin= externalPlugin[attr.name]
|
|
1083
999
|
try{
|
|
@@ -1090,9 +1006,9 @@ export const render =async (el, contexts = {},stream) => {
|
|
|
1090
1006
|
console.warn(error.message,error.stack)
|
|
1091
1007
|
}
|
|
1092
1008
|
}
|
|
1093
|
-
}else if(startAttribute){
|
|
1009
|
+
}else if(startAttribute ){
|
|
1094
1010
|
const name=startObject[attr.name]
|
|
1095
|
-
if(externalPlugin[name]){
|
|
1011
|
+
if(externalPlugin[name] && !el._componentName){
|
|
1096
1012
|
const plugin= externalPlugin[name]
|
|
1097
1013
|
try{
|
|
1098
1014
|
if (typeof plugin !== 'function') {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pawa-ssr",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "pawajs ssr libary",
|
|
6
6
|
"main": "index.js",
|
|
@@ -24,7 +24,9 @@
|
|
|
24
24
|
},
|
|
25
25
|
"homepage": "https://github.com/Allisboy/pawajs-ssr#readme",
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"linkedom": "^0.18.11"
|
|
28
|
-
|
|
27
|
+
"linkedom": "^0.18.11"
|
|
28
|
+
},
|
|
29
|
+
"peerDependencies": {
|
|
30
|
+
"pawajs": "^2.0.0"
|
|
29
31
|
}
|
|
30
32
|
}
|
package/pawaElement.js
CHANGED
|
@@ -19,6 +19,7 @@ class PawaElement {
|
|
|
19
19
|
* @type{PawaElement|HTMLElement}
|
|
20
20
|
*/
|
|
21
21
|
this._el=element
|
|
22
|
+
this._aschild=false
|
|
22
23
|
this._slots=document.createDocumentFragment()
|
|
23
24
|
this._context=context
|
|
24
25
|
this._avoidPawaRender=element.hasAttribute('s-pawa-avoid')
|
|
@@ -166,6 +167,7 @@ class PawaElement {
|
|
|
166
167
|
|
|
167
168
|
getComponent(){
|
|
168
169
|
if (components.has(splitAndAdd(this._el.tagName.toUpperCase())) && !this._client || this._lazy) {
|
|
170
|
+
if(this._el.hasAttribute('data-prevent:c'))return
|
|
169
171
|
this._componentName=splitAndAdd(this._el.tagName.toUpperCase())
|
|
170
172
|
const fakeCompo=()=>true
|
|
171
173
|
this._component=new PawaComponent(components.get(splitAndAdd(this._el.tagName.toUpperCase())),fakeCompo)
|
|
@@ -194,12 +196,13 @@ class PawaElement {
|
|
|
194
196
|
//set Component props
|
|
195
197
|
setProps(){
|
|
196
198
|
if (this._componentName) {
|
|
197
|
-
const allServerAttr=
|
|
199
|
+
const allServerAttr=['if','else','else-if','key','for-each','case','switch','s-default']
|
|
198
200
|
this._el.attributes.forEach(attr=>{
|
|
199
|
-
if(
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
201
|
+
if (attr.name ==='aschild' || attr.name === 'as-child' || attr.name === ':as-child') {
|
|
202
|
+
this._aschild=true
|
|
203
|
+
return
|
|
204
|
+
}
|
|
205
|
+
if(!allServerAttr.includes(attr.name)){
|
|
203
206
|
if ( !attr.name.startsWith(':')) {
|
|
204
207
|
if( attr.name.startsWith('c-')||attr.name.startsWith('pawa-') || attr.name.startsWith('p:c') || attr.name.startsWith('state-')) return
|
|
205
208
|
let name=''
|
|
@@ -228,7 +231,7 @@ class PawaElement {
|
|
|
228
231
|
|
|
229
232
|
});
|
|
230
233
|
return value
|
|
231
|
-
}else if( attr.name.startsWith('on-') || attr.name.startsWith('out-')
|
|
234
|
+
}else if( attr.name.startsWith('on-') || attr.name.startsWith('out-')){
|
|
232
235
|
const res=this.evaluateExpr(`(e)=>{
|
|
233
236
|
${attr.value}
|
|
234
237
|
}`, this._context,`evaluating props with template operators at ${attr.name} - ${attr.value} : ${this._template}`)
|
|
@@ -281,16 +284,11 @@ class PawaElement {
|
|
|
281
284
|
evaluateExpr(expr, context = {},error){
|
|
282
285
|
try {
|
|
283
286
|
const keys = Object.keys(context);
|
|
284
|
-
|
|
285
|
-
// We sort keys to ensure consistent cache hits regardless of key order
|
|
286
|
-
const cacheKey = expr + '|||' + keys.sort().join(',');
|
|
287
|
-
|
|
288
|
-
let func = expressionCache.get(cacheKey);
|
|
287
|
+
let func
|
|
289
288
|
if (!func) {
|
|
290
289
|
func = new Function(...keys, `
|
|
291
290
|
const require=null
|
|
292
291
|
return ${expr}`);
|
|
293
|
-
expressionCache.set(cacheKey, func);
|
|
294
292
|
}
|
|
295
293
|
|
|
296
294
|
const values = keys.map((key) => context[key]);
|
package/test/App.js
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
import { useInnerContext } from "pawajs"
|
|
2
|
+
|
|
1
3
|
export const App=({children})=>{
|
|
4
|
+
const context=useInnerContext()
|
|
5
|
+
console.log(context)
|
|
2
6
|
return `<div class="p-4">
|
|
3
7
|
<h1 class="text-2xl font-bold mb-4">Hello, World!</h1>
|
|
4
8
|
<p class="text-gray-700">This is a test component for PawaJS.</p>
|
package/test/index.js
CHANGED
|
@@ -1,13 +1,24 @@
|
|
|
1
|
-
import {useValidateComponent, RegisterComponent,useContext,useInsert,setContext} from 'pawajs'
|
|
2
|
-
import {startApp} from '../index.js'
|
|
1
|
+
import {useValidateComponent, RegisterComponent,useContext,useInsert,setContext,forwardProps} from 'pawajs'
|
|
2
|
+
import {startApp,startStreamApp} from '../index.js'
|
|
3
3
|
RegisterComponent.lazy(
|
|
4
4
|
'App',()=>import('./App.js'),
|
|
5
5
|
'Check',()=>import('./check.js'),
|
|
6
6
|
'Check2',()=>import('./check.js'),
|
|
7
7
|
)
|
|
8
|
-
|
|
8
|
+
const Dinput=({className,...props})=>{
|
|
9
|
+
forwardProps(props)
|
|
10
|
+
const classActive=()=>[className?.() || '','py-2 text-blue'].join(' ')
|
|
11
|
+
useInsert({classActive})
|
|
12
|
+
return `
|
|
13
|
+
<input class="@{classActive()}" -- />
|
|
14
|
+
`
|
|
15
|
+
}
|
|
16
|
+
RegisterComponent(Dinput)
|
|
9
17
|
const app=`
|
|
10
18
|
<div>
|
|
19
|
+
<dinput type="file" aschild>
|
|
20
|
+
<div>aschild</div>
|
|
21
|
+
</dinput>
|
|
11
22
|
<app>
|
|
12
23
|
<check></check>
|
|
13
24
|
<check-2></check-2>
|
|
@@ -17,5 +28,11 @@ const app=`
|
|
|
17
28
|
</div>
|
|
18
29
|
</div>
|
|
19
30
|
`
|
|
20
|
-
const {toString}=await startApp(app)
|
|
21
|
-
console.log(await toString());
|
|
31
|
+
// const {toString}=await startApp(app)
|
|
32
|
+
// console.log(await toString());
|
|
33
|
+
let strings=''
|
|
34
|
+
const stream=(string)=>strings+=string
|
|
35
|
+
|
|
36
|
+
await startStreamApp(app,{url:'/'},stream,{templateEnd:'</body>',templateStart:'<body>'})
|
|
37
|
+
console.log(strings);
|
|
38
|
+
|