vaderjs 1.4.2-jpiml56 → 1.4.2-kml56

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.
@@ -1 +1,417 @@
1
- window.vader={version:"1.0.0"},globalThis.isServer=!1,globalThis.preRender=!1,window.hasRan=[],globalThis.memoizedFunctions=[];const memoizedRefs=[];function calculateDiff(e,t){if(void 0===e||void 0===t)return[];let n=[];if(e?.children.length>0){for(var r=0;r<e.children.length;r++)n.push(...calculateDiff(e.children[r],t.children[r]));return n}if(!e?._isRoot)if(3===e.nodeType&&e.nodeValue!==t.nodeValue)n.push({type:"REPLACE",oldNode:e,newNode:t});else if(1===e.nodeType&&e.innerHTML!==t.innerHTML)n.push({type:"REPLACE",oldNode:e,newNode:t});else if(1===e.nodeType&&e.tagName===t.tagName)for(r=0;r<e.attributes.length;r++)e.attributes[r].value!==t.attributes[r].value&&n.push({type:"PROPS",oldNode:e,newNode:t});return n}function generateJSX(e,t,...n){let r={state:{},mainFunction:e,_key:e.name||Math.random().toString(36).substring(7),$$typeof:"JSX_CHILD",firstChild:null,children:n,_name:e.name},o=new Component({$$key:r._key});return e=e.bind(o),o.render=()=>{let r=(n=n.flat(1/0)).map((e=>"function"==typeof e?generateJSX(e,t,e.props.children):e));return e({...t,children:r[0]||r})},r.firstChild=o.render(),r.firstChild.htmlNode._key=r._key,r.firstChild.htmlRoot=r,r.firstChild.htmlNode._isRoot=!0,r.firstChild.props=t||{},r.firstChild._isRoot=!0,r.firstChild._key=r._key,r.firstChild.props.key=r._key,r.firstChild}function handleStyles(e,t){for(let n in e)"object"==typeof e[n]&&handleStyles(e[n],t),t.style[n]=e[n]}let hasBeenCalled=[];function Element(e,t,...n){if(!t&&(t={}),t?.$$key||(t.$$key=e.name||Math.random().toString(36).substring(7)),"function"==typeof e)return generateJSX(e,t,n);let r={tag:e,props:t,children:n,_key:t.$$key,events:[],staticEl:document.createElement(e),parentNode:null};for(var o=0;o<n.length;o++)"string"==typeof n[o]||"number"==typeof n[o]?n[o]={tag:"TEXT_ELEMENT",props:{nodeValue:n[o]},_key:t.$$key,parentNode:{tag:e,props:t,children:n,_key:t.$$key},children:[]}:n[o]&&(n[o].parentNode={tag:e,props:t,children:n});let i="TEXT_ELEMENT"===r.tag?document.createTextNode(""):document.createElement(r.tag);for(var s in r.staticEl=i,t)s.toLowerCase().startsWith("on")?(i.addEventListener(s.substring(2).toLowerCase(),t[s]),r.events.push({type:s.substring(2).toLowerCase(),listener:t[s]})):"$$key"!==s||i._key||1!==i.nodeType?i&&1===i.nodeType&&i.setAttribute(s,t[s]):Object.defineProperty(i,"_key",{value:t[s],writable:!0});if(t.style&&handleStyles(t.style,i),t.id&&(i.id=t.id),t.ref)switch(!0){case Array.isArray(t.ref.current):t.ref.current.find((e=>e===i))||t.ref.current.push(i);break;case t.ref.current===HTMLElement:case null===t.ref.current:t.ref.current=i;break;case"function"==typeof t.ref&&!window.hasRan.includes(t.ref):window.hasRan.push(t.ref),t.ref(i),setTimeout((()=>{window.hasRan.filter((e=>e!==t.ref))}),0);break;default:t.ref.current=i}if(r.htmlNode=i,1===i.nodeType)for(o=0;o<n.length;o++)n[o]&&("TEXT_ELEMENT"===n[o].tag&&i.appendChild(document.createTextNode(n[o].props.nodeValue)),i.appendChild(Element(n[o].tag,n[o].props,...n[o].children).htmlNode));return r}function handleDiff(e){for(var t=0;t<e.length;t++)switch(!0){case"REPLACE"===e[t].type&&!e[t].oldNode._isRoot:e[t].oldNode.parentNode;e[t].oldNode.parentNode.replaceChild(e[t].newNode,e[t].oldNode);case"PROPS"===e[t].type:}}let states={};export const useState=(e,t)=>{};export function useRef(e,t){let n=t;memoizedRefs.find((t=>t.name===e))||memoizedRefs.push({name:e,ref:n});return{current:memoizedRefs.find((t=>t.name===e)).ref,name:e}}export function Mounted(e,t){Array.from(document.querySelectorAll("*")).find((e=>e._key===memoizedFunctions.find((e=>e.mainFunction===t))._key))&&!hasBeenCalled.find((e=>e===t))?(e(),hasBeenCalled.push(t)):setTimeout((()=>{Mounted(e,t)}),0)}let effects=[];export function useEffect(e,t){if(effects.find((t=>t.fn.toString()===e.toString()))){let n=effects.find((t=>t.fn.toString()===e.toString()));n.deps.toString()!==t.toString()&&(n.deps=t,n.fn())}else effects.push({fn:e,deps:t});return()=>{effects=effects.filter((t=>t.fn!==e))}}export function useReducer(e,t,n,r){let[o,i]=void 0;return[o,e=>{let n=t(o,e);i(n)}]}class Component{constructor(e){this.props=e,this._key=e.$$key||Math.random().toString(36).substring(7),this.state={},this.htmlNode=null,this.firstChild=null,this.Element=Element,this.passiveProps={}}setState(e){this.state=e}handleDiff(e){for(var t=0;t<e.length;t++)switch(!0){case"REPLACE"===e[t].type&&!e[t].oldNode._isRoot:e[t].oldNode.parentNode;e[t].oldNode.parentNode.replaceChild(e[t].newNode,e[t].oldNode);case"PROPS"===e[t].type:}}calculateDiff(e,t){if(void 0===e||void 0===t)return[];let n=[];if(e?.children.length>0){for(var r=0;r<e.children.length;r++)n.push(...this.calculateDiff(e.children[r],t.children[r]));return n}if(!e?._isRoot)if(3===e.nodeType&&e.nodeValue!==t.nodeValue)n.push({type:"REPLACE",oldNode:e,newNode:t});else if(1===e.nodeType&&e.innerHTML!==t.innerHTML)n.push({type:"REPLACE",oldNode:e,newNode:t});else if(1===e.nodeType&&e.tagName===t.tagName)for(r=0;r<e.attributes.length;r++)e.attributes[r].value!==t.attributes[r].value&&n.push({type:"PROPS",oldNode:e,newNode:t});return n}useState(e,t){this.state[e]||(this.state[e]=t);return[()=>this.state[e],t=>{let n=this.firstChild.htmlNode;"HTML"===n.tagName&&(n=n.querySelector("body"),n.firstChild._key=this._key),this.state[e]=t,handleDiff(calculateDiff(Array.from(document.querySelectorAll("*")).find((e=>e._key===n._key)),"HTML"===this.render(this.passiveProps).htmlNode.tagName?this.render(this.passiveProps).htmlNode.querySelector("body"):this.render(this.passiveProps).htmlNode))}]}useEffect=useEffect;useReducer(e,t,n){let[r,o]=this.useState(e,n);return[r,e=>{let n=t(r(),e);o(n)}]}render(){return null}}export async function render(e,t,...n){if(!e)throw new Error("No vnode was provided");let r=new Component({$$key:e.name||Math.random().toString(36).substring(7)});e=e.bind(r),n.length>0&&(n={req:n[0],res:n[1]},r.passiveProps=n),r.render=()=>e(r.passiveProps),r.firstChild=r.render(),t.innerHTML="",t.replaceWith(r.firstChild.htmlNode)}export default Element;
1
+ window.vader = {
2
+ version: '1.0.0'
3
+ }
4
+ globalThis.isServer = false
5
+ window.hasRan = []
6
+ globalThis.memoizedFunctions = []
7
+ const memoizedRefs = []
8
+ /**
9
+ * @description This function is used to calculate the difference between two nodes - and return the elements in which the difference is found
10
+ * @param {HTMLElement} oldNode
11
+ * @param {HTMLElement} newNode
12
+ * @returns
13
+ */
14
+ function calculateDiff(oldNode, newNode){
15
+ if(oldNode === undefined || newNode === undefined){
16
+ return []
17
+ }
18
+ let diff = []
19
+ if(oldNode?.children.length > 0){
20
+ for(var i = 0; i < oldNode.children.length; i++){
21
+ diff.push(...calculateDiff(oldNode.children[i], newNode.children[i]))
22
+
23
+ }
24
+ return diff
25
+ }
26
+ if(!oldNode?._isRoot){
27
+ if(oldNode.nodeType === 3 && oldNode.nodeValue !== newNode.nodeValue){
28
+ diff.push({type: 'REPLACE', oldNode, newNode})
29
+ }
30
+ else if(oldNode.nodeType === 1 && oldNode.innerHTML !== newNode.innerHTML
31
+ ){
32
+ diff.push({type: 'REPLACE', oldNode, newNode})
33
+ }
34
+ else if(oldNode.nodeType === 1 && oldNode.tagName === newNode.tagName){
35
+ for(var i = 0; i < oldNode.attributes.length; i++){
36
+ if(oldNode.attributes[i].value !== newNode.attributes[i].value){
37
+ diff.push({type: 'PROPS', oldNode, newNode})
38
+ }
39
+ }
40
+ }
41
+ }
42
+
43
+
44
+
45
+ return diff
46
+ }
47
+
48
+ /**
49
+ * @description This function is used to generate functonal components
50
+ * @param {Function} tag
51
+ * @param {Object} props
52
+ * @param {...any} children
53
+ * @returns {Object} - The first child of the functional component
54
+ */
55
+ function generateJSX(tag, props, ...children){
56
+ let node = {
57
+ state: {},
58
+ mainFunction: tag,
59
+ _key: tag.name || Math.random().toString(36).substring(7),
60
+ $$typeof: 'JSX_CHILD',
61
+ firstChild:null,
62
+ children: children,
63
+ _name: tag.name,
64
+ }
65
+
66
+ node.firstChild = tag()
67
+ node.firstChild.htmlNode._key = node._key
68
+ node.firstChild.htmlRoot = node
69
+ node.firstChild.htmlNode._isRoot = true
70
+ node.firstChild.props = props || {}
71
+ node.firstChild._isRoot = true
72
+ node.firstChild._key = node._key
73
+ node.firstChild.props['key'] = node._key
74
+ return node.firstChild
75
+
76
+
77
+ }
78
+ function handleStyles(styles, nodeEl) {
79
+
80
+ for (let key in styles) {
81
+ if(typeof styles[key] === 'object'){
82
+ handleStyles(styles[key], nodeEl)
83
+ }
84
+ nodeEl.style[key] = styles[key];
85
+ }
86
+
87
+ }
88
+
89
+
90
+ let hasBeenCalled = []
91
+ /**
92
+ * @description Create a virtual DOM element
93
+ * @param {string | Function} tag
94
+ * @param {Object} props
95
+ * @param {...any} children
96
+ * @returns {Object} - The virtual DOM element
97
+ */
98
+ function Element(tag, props, ...children){
99
+ !props ? props = {} : null
100
+ if(!props?.['$$key']){
101
+ props['$$key'] = tag.name || Math.random().toString(36).substring(7)
102
+ }
103
+
104
+ if(typeof tag === 'function'){
105
+ return generateJSX(tag, props, children)
106
+ }
107
+ let node = {
108
+ tag: tag,
109
+ props: props,
110
+ children: children,
111
+ _key: props['$$key'],
112
+ events: [],
113
+ staticEl: document.createElement(tag),
114
+ parentNode: null
115
+ }
116
+ for(var i = 0; i < children.length; i++){
117
+ if(typeof children[i] === 'string' || typeof children[i] === 'number'){
118
+ children[i] = {
119
+ tag: 'TEXT_ELEMENT',
120
+ props: {nodeValue: children[i]},
121
+ _key: props['$$key'],
122
+ parentNode: {tag: tag, props: props, children: children, _key: props['$$key']},
123
+ children: []
124
+ }
125
+ }else{
126
+ if(children[i]){
127
+ children[i].parentNode = {tag: tag, props: props, children: children}
128
+ }
129
+ }
130
+ }
131
+ let nodeEl = node.tag === 'TEXT_ELEMENT' ? document.createTextNode('') : document.createElement(node.tag)
132
+ node.staticEl = nodeEl
133
+
134
+ for(var key in props){
135
+ if(key.toLowerCase().startsWith('on')){
136
+ nodeEl.addEventListener(key.substring(2).toLowerCase(), props[key])
137
+ node.events.push({type: key.substring(2).toLowerCase(), listener: props[key]})
138
+ continue
139
+ }
140
+ if(key === '$$key' && !nodeEl._key && nodeEl.nodeType === 1
141
+ ){
142
+ Object.defineProperty(nodeEl, '_key', {
143
+ value: props[key],
144
+ writable: true
145
+ })
146
+ continue
147
+ }
148
+
149
+ if(nodeEl && nodeEl.nodeType === 1){
150
+ nodeEl.setAttribute(key, props[key])
151
+ }
152
+
153
+ }
154
+ if(props.style){
155
+ handleStyles(props.style, nodeEl)
156
+ }
157
+
158
+ if(props.id){
159
+ nodeEl.id = props.id
160
+ }
161
+ if(props.ref){
162
+ switch(true){
163
+ case Array.isArray(props.ref.current):
164
+ if(!props.ref.current.find((el) => el === nodeEl)){
165
+ props.ref.current.push(nodeEl)
166
+ }
167
+ break;
168
+ case props.ref.current === HTMLElement:
169
+ props.ref.current = nodeEl
170
+ break;
171
+ case props.ref.current === null:
172
+ props.ref.current = nodeEl
173
+ break;
174
+ case typeof props.ref === 'function' && !window.hasRan.includes(props.ref):
175
+ window.hasRan.push(props.ref)
176
+ props.ref(nodeEl)
177
+ setTimeout(() => {
178
+ window.hasRan.filter((el) => el !== props.ref)
179
+ }, 0)
180
+ break;
181
+ default:
182
+ props.ref.current = nodeEl
183
+ break;
184
+
185
+ }
186
+ }
187
+ node['htmlNode'] = nodeEl
188
+
189
+
190
+ if(nodeEl.nodeType === 1){
191
+ for(var i = 0; i < children.length; i++){
192
+ if(children[i]){
193
+ if(children[i].tag === 'TEXT_ELEMENT'){
194
+ nodeEl.appendChild(document.createTextNode(children[i].props.nodeValue))
195
+ }
196
+ nodeEl.appendChild(Element(children[i].tag, children[i].props, ...children[i].children).htmlNode)
197
+ }
198
+ }
199
+
200
+ }
201
+
202
+ return node;
203
+ }
204
+
205
+
206
+ function handleDiff(diff){
207
+ for(var i = 0; i < diff.length; i++){
208
+ switch(true){
209
+ case diff[i].type === 'REPLACE' && !diff[i].oldNode._isRoot:
210
+ let parent = diff[i].oldNode.parentNode
211
+ diff[i].oldNode.parentNode.replaceChild(diff[i].newNode, diff[i].oldNode)
212
+ break;
213
+ case diff[i].type === 'PROPS':
214
+ break;
215
+ }
216
+ }
217
+
218
+ }
219
+ let states = {}
220
+ export const useState = (name, initialValue) => {}
221
+ export function useRef(name, initialValue){
222
+ let ref = initialValue
223
+ if(!memoizedRefs.find((el) => el.name === name)){
224
+ memoizedRefs.push({name, ref})
225
+ }
226
+ let getRef = () => memoizedRefs.find((el) => el.name === name).ref
227
+ let setRef = (newValue) => {
228
+ memoizedRefs.find((el) => el.name === name).ref = newValue
229
+ }
230
+ return {
231
+ current: getRef(),
232
+ name,
233
+ }
234
+ }
235
+ export function Mounted(fn, node){
236
+ let el = Array.from(document.querySelectorAll('*')).find((el) => el._key === memoizedFunctions.find((el) => el.mainFunction === node)._key)
237
+ if(el && !hasBeenCalled.find((el) => el === node)){
238
+ fn()
239
+ hasBeenCalled.push(node)
240
+ }
241
+ else{
242
+ setTimeout(() => {
243
+ Mounted(fn, node)
244
+ }, 0)
245
+ }
246
+ }
247
+
248
+
249
+ let effects = [];
250
+
251
+ export function useEffect(fn, deps){
252
+ if(!effects.find((el) => el.fn.toString() === fn.toString())){
253
+ effects.push({fn, deps})
254
+ }
255
+ else{
256
+ let effect = effects.find((el) => el.fn.toString() === fn.toString())
257
+ if(effect.deps.toString() !== deps.toString()){
258
+ effect.deps = deps
259
+ effect.fn()
260
+ }
261
+ }
262
+ return () => {
263
+ effects = effects.filter((el) => el.fn !== fn)
264
+ }
265
+
266
+ }
267
+ export function useReducer(name, reducer, vnode, initialState){
268
+ let [state, setState] = useState(name, vnode, initialState)
269
+ let dispatch = (action) => {
270
+ let newState = reducer(state, action)
271
+ setState(newState)
272
+ }
273
+
274
+ return [state, dispatch]
275
+
276
+ }
277
+
278
+ class Component {
279
+ constructor(props){
280
+ this.props = props
281
+ this._key = props['$$key'] || Math.random().toString(36).substring(7)
282
+ this.state = {}
283
+ this.htmlNode = null
284
+ this.firstChild = null
285
+ this.Element = Element
286
+ }
287
+
288
+
289
+ setState(newState){
290
+ this.state = newState
291
+ }
292
+
293
+ handleDiff(diff){
294
+ for(var i = 0; i < diff.length; i++){
295
+ switch(true){
296
+ case diff[i].type === 'REPLACE' && !diff[i].oldNode._isRoot:
297
+ let parent = diff[i].oldNode.parentNode
298
+ diff[i].oldNode.parentNode.replaceChild(diff[i].newNode, diff[i].oldNode)
299
+ break;
300
+ case diff[i].type === 'PROPS':
301
+ break;
302
+ }
303
+ }
304
+ }
305
+ calculateDiff(oldNode, newNode){
306
+ if(oldNode === undefined || newNode === undefined){
307
+ return []
308
+ }
309
+ let diff = []
310
+ if(oldNode?.children.length > 0){
311
+ for(var i = 0; i < oldNode.children.length; i++){
312
+ diff.push(...this.calculateDiff(oldNode.children[i], newNode.children[i]))
313
+
314
+ }
315
+ return diff
316
+ }
317
+ if(!oldNode?._isRoot){
318
+ if(oldNode.nodeType === 3 && oldNode.nodeValue !== newNode.nodeValue){
319
+ diff.push({type: 'REPLACE', oldNode, newNode})
320
+ }
321
+ else if(oldNode.nodeType === 1 && oldNode.innerHTML !== newNode.innerHTML
322
+ ){
323
+ diff.push({type: 'REPLACE', oldNode, newNode})
324
+ }
325
+ else if(oldNode.nodeType === 1 && oldNode.tagName === newNode.tagName){
326
+ for(var i = 0; i < oldNode.attributes.length; i++){
327
+ if(oldNode.attributes[i].value !== newNode.attributes[i].value){
328
+ diff.push({type: 'PROPS', oldNode, newNode})
329
+ }
330
+ }
331
+ }
332
+ }
333
+
334
+
335
+
336
+ return diff
337
+ }
338
+ useState(name, initialValue){
339
+ if(!this.state[name]){
340
+ this.state[name] = initialValue
341
+ }
342
+
343
+ let getState = () => this.state[name]
344
+ let setState = (newValue) => {
345
+ let dEl = this.firstChild.htmlNode
346
+ if(dEl.tagName === 'HTML'){
347
+ let firstChild = dEl.querySelector('body').firstChild
348
+ dEl = firstChild
349
+ }
350
+ this.state[name] = newValue
351
+ let el = Array.from(document.querySelectorAll('*')).find((el) =>{
352
+ return el._key === dEl._key
353
+ })
354
+ let diff = calculateDiff(el, this.render().htmlNode.tagName === 'HTML' ? this.render().htmlNode.querySelector('body').firstChild : this.render().htmlNode)
355
+ handleDiff(diff)
356
+
357
+ }
358
+ return [getState, setState]
359
+
360
+ }
361
+ useEffect = useEffect
362
+ useReducer(name, reducer, initialState){
363
+ let [state, setState] = this.useState(name, initialState)
364
+ let dispatch = (action) => {
365
+ let newState = reducer(state(), action)
366
+ setState(newState)
367
+ }
368
+
369
+ return [state, dispatch]
370
+ }
371
+
372
+ render(){
373
+ return null
374
+ }
375
+
376
+ }
377
+
378
+ export async function render(vnode, container, ...passProps){
379
+
380
+ if(!vnode){
381
+ throw new Error('No vnode was provided')
382
+ }
383
+ // create an object for the node then bind to firstChild
384
+ let comp = new Component({$$key: vnode.name || Math.random().toString(36).substring(7)})
385
+ vnode = vnode.bind(comp)
386
+ comp.render = () => {
387
+ return vnode(...passProps)
388
+ }
389
+
390
+ comp.firstChild = comp.render()
391
+
392
+ if(comp.firstChild.htmlNode.tagName === 'HTML'){
393
+ let hasHead = comp.firstChild.htmlNode.querySelector('head') ? true : false
394
+ let hasBody = comp.firstChild.htmlNode.querySelector('body') ? true : false
395
+
396
+ if(hasHead){
397
+ document.head.innerHTML = comp.firstChild.htmlNode.querySelector('head').innerHTML
398
+ comp.firstChild.children = comp.firstChild.children.filter((el) =>{
399
+ return el.htmlNode.tagName !== 'HEAD'
400
+ })
401
+ }
402
+ if(hasBody){
403
+ comp.firstChild.children = comp.firstChild.children.filter((el) =>{
404
+ if(el.htmlNode.tagName == 'BODY'){
405
+ comp.firstChild = el.children[0]
406
+ }
407
+ })
408
+ }
409
+ }
410
+ container.innerHTML = ''
411
+
412
+ container.appendChild(comp.firstChild.htmlNode)
413
+
414
+
415
+ }
416
+
417
+ export default Element
@@ -1 +1,235 @@
1
- export class Kuai{constructor(t={container:"#app"}){this.routes=[],this.middleware=[],this.container=t.container?t.container:document.getElementById("app"),this.renderPlugins=[]}res={text:t=>{this.container.innerHTML=t},html:t=>{switch(typeof t){case"function":if(this.renderPlugins.length>0)return void this.renderPlugins.forEach((e=>{"html"===e.for&&(console.log("Plugin",e),e.plugin(t,this.container))}));this.container.innerHTML=t();break;case"string":this.container.innerHTML=t}},json:t=>{this.container.innerHTML=`<Oject data=${JSON.stringify(t)}></Object>`}};req={navigate:t=>{window.history.pushState({},"",t);let e=this.match(window.location.pathname.replace("/index.html",""));e&&(this.currentRoute=e.path,e.callback(this.res,e.params,this.extractQueryParams(window.location.search)))},back:()=>{window.history.back()},forward:()=>{window.history.forward()},url:window.location};extractQueryParams(t){let e=new URLSearchParams(t),i={};for(let t of e)i[t[0]]=t[1];return i}extractParams(t,e){const i=t.split("/").filter((t=>""!==t)),r=e.split("/").filter((t=>""!==t)),a={};return i.forEach(((t,e)=>{if(t.startsWith(":")){const i=t.slice(1);a[i]=r[e]}else if(t.startsWith("*")){r.slice(e).forEach(((t,e)=>{a[e]=t}))}})),a}use(t,e){this.middleware.push({path:t,middleware:e})}usePlugin(t,e){this.renderPlugins.push({plugin:t,for:e})}match(t){(t=t.endsWith("/")?t.slice(0,-1):t).includes("index.html")&&(t=t.replace("index.html","")),t.includes("?")&&(t=t.split("?")[0]);let e=this.routes.find((e=>{if(e.path===t)return!0;if(""===t&&"/"===e.path)return!0;if(e.path.includes("*")||e.path.includes(":")){const i=e.path.split("/").filter((t=>""!==t)),r=t.split("/").filter((t=>""!==t));if(this.basePath&&r.shift(),i.length!==r.length&&!e.path.endsWith("*"))return!1;for(let t=0;t<i.length;t++){const e=i[t],a=r[t];if(!e.startsWith(":")&&!e.startsWith("*")&&e!==a)return!1}return!0}}));if(e){let i=this.extractParams(e.path,t);return{...e,params:i}}return null}get(t,e){this.routes.push({path:t,callback:e})}listen(){let t=this.match(window.location.pathname.replace("/index.html",""));if(t){this.middleware.forEach((e=>{e.path===t.path&&e.middleware()})),this.currentRoute=t.path;let e={...this.res,res:this.res,req:{...this.req,params:e=>t.params[e]}};t.callback(e)}window.onpopstate=()=>{let t=this.match(window.location.pathname.replace("/index.html",""));t&&(this.currentRoute=t.path,t.callback(this.res,t.params,this.extractQueryParams(window.location.search)))}}}export default Kuai;
1
+ /**
2
+ * @fileoverview - A simple router for vaderjs - Kuai
3
+ * @version - 1.0.0
4
+ */
5
+ export class Kuai{
6
+ constructor(config = { container: '#app'}){
7
+ this.routes = [];
8
+ this.middleware = [];
9
+ this.container = config.container ? config.container : document.getElementById('app');
10
+ this.renderPlugins = [];
11
+ }
12
+
13
+ res = {
14
+ /**
15
+ * @description render text to the container
16
+ * @param {string} data
17
+ */
18
+ text: (data) => {
19
+ this.container.innerHTML = data;
20
+ },
21
+ /**
22
+ * @method html
23
+ * @description render html to the container
24
+ * @param {any} data
25
+ * @returns
26
+ */
27
+ html: (data) => {
28
+ switch(typeof data){
29
+ case 'function':
30
+ if(this.renderPlugins.length > 0){
31
+ this.renderPlugins.forEach((plugin) => {
32
+ if(plugin.for === 'html'){
33
+ console.log('Plugin', plugin)
34
+ plugin.plugin(data, this.container)
35
+ }
36
+ })
37
+ return;
38
+ }
39
+ this.container.innerHTML = data();
40
+ break;
41
+ case 'string':
42
+ this.container.innerHTML = data;
43
+ break;
44
+ }
45
+
46
+ },
47
+ /**
48
+ * @method json
49
+ * @description render json to the container
50
+ * @param {Object} data
51
+ */
52
+ json: (data) => {
53
+ this.container.innerHTML = `<Oject data=${JSON.stringify(data)}></Object>`
54
+ }
55
+ }
56
+ req = {
57
+ /**
58
+ * @method navigate
59
+ * @description - navigate to a new route
60
+ * @param {string} path
61
+ */
62
+ navigate: (path) => {
63
+ window.history.pushState({}, '', path);
64
+ let currentPath = this.match(window.location.pathname.replace('/index.html', ''))
65
+ if(currentPath){
66
+ this.currentRoute = currentPath.path
67
+ currentPath.callback(this.res, currentPath.params, this.extractQueryParams(window.location.search));
68
+ }
69
+ },
70
+ /**
71
+ * @method back
72
+ * @description - go back to the previous route
73
+ */
74
+ back: () => {
75
+ window.history.back();
76
+ },
77
+
78
+ /**
79
+ * @method forward
80
+ * @description - go forward to the next route
81
+ * @returns {void}
82
+ * **/
83
+ forward: () => {
84
+ window.history.forward();
85
+ },
86
+ url: window.location
87
+ }
88
+ /**
89
+ * @private
90
+ */
91
+ extractQueryParams(path){
92
+ let params = new URLSearchParams(path);
93
+ let query = {};
94
+ for(let param of params){
95
+ query[param[0]] = param[1];
96
+ }
97
+ return query;
98
+ }
99
+ /**
100
+ * @private
101
+ */
102
+ extractParams(routePath, currentPath){
103
+ const routeParts = routePath.split('/').filter((part) => part !== '');
104
+ const hashParts = currentPath.split('/').filter((part) => part !== '');
105
+ const params = {};
106
+ routeParts.forEach((part, index) => {
107
+ if (part.startsWith(':')) {
108
+ const paramName = part.slice(1);
109
+ params[paramName] = hashParts[index];
110
+ }else if(part.startsWith('*')){
111
+ let array = hashParts.slice(index)
112
+ array.forEach((i, index)=>{
113
+ params[index] = i
114
+ })
115
+ };
116
+ });
117
+ return params;
118
+ }
119
+ use(path, middleware){
120
+ this.middleware.push({path, middleware});
121
+ }
122
+ /**
123
+ * @method usePlugin
124
+ * @description - add a plugin to handle how the route should be rendered
125
+ * @param {Function} plugin
126
+ * @param {('html')} method
127
+ */
128
+ usePlugin(plugin, method){
129
+ this.renderPlugins.push({plugin, for: method})
130
+ }
131
+ /**
132
+ * @method match
133
+ * @description - match a route to the current path and return the route object
134
+ * @param {string} route
135
+ * @returns {Object} - {path: string, callback: Function, params: Object}
136
+ */
137
+ match(hash){
138
+ hash = hash.endsWith('/') ? hash.slice(0, -1) : hash;
139
+ hash.includes('index.html') ? hash = hash.replace('index.html', '') : null;
140
+ if(hash.includes('?')){
141
+ hash = hash.split('?')[0]
142
+ }
143
+ let route = this.routes.find((route) => {
144
+ if (route.path === hash) {
145
+ return true;
146
+ }
147
+
148
+ if(hash === '' && route.path === '/'){
149
+ return true
150
+ }
151
+
152
+
153
+ if (route.path.includes('*') || route.path.includes(':')) {
154
+ const routeParts = route.path.split('/').filter((part) => part !== '');
155
+ const hashParts = hash.split('/').filter((part) => part !== '');
156
+ if(this.basePath){
157
+ hashParts.shift();
158
+ }
159
+ if (routeParts.length !== hashParts.length && !route.path.endsWith('*')) {
160
+ return false;
161
+ }
162
+
163
+ for (let index = 0; index < routeParts.length; index++) {
164
+ const routePart = routeParts[index];
165
+ const hashPart = hashParts[index];
166
+
167
+
168
+ if (routePart.startsWith(':') || routePart.startsWith('*')) {
169
+
170
+ continue;
171
+ }
172
+
173
+ if (routePart !== hashPart) {
174
+ return false;
175
+ }
176
+ }
177
+
178
+
179
+ return true;
180
+ }
181
+
182
+ });
183
+ if(route){
184
+ let params = this.extractParams(route.path, hash)
185
+ return { ...route, params}
186
+ }
187
+ return null;
188
+
189
+ }
190
+
191
+ /**
192
+ * @description - create a new route
193
+ * @param {string} path
194
+ * @param {Function} callback
195
+ */
196
+ get(path, callback){
197
+ this.routes.push({path, callback});
198
+ }
199
+
200
+ /**
201
+ * @method listen
202
+ * @description - listen for route changes
203
+ */
204
+ listen(){
205
+ let currentPath = this.match(window.location.pathname.replace('/index.html', ''))
206
+ if(currentPath){
207
+ this.middleware.forEach((middleware) => {
208
+ if(middleware.path === currentPath.path){
209
+ middleware.middleware();
210
+ }
211
+ });
212
+ this.currentRoute = currentPath.path
213
+ let obj = {
214
+ ...this.res,
215
+ res: this.res,
216
+ req:{
217
+ ...this.req,
218
+ params: (param) => currentPath.params[param]
219
+
220
+ }
221
+ }
222
+ currentPath.callback(obj);
223
+ }
224
+ window.onpopstate = () => {
225
+ let currentPath = this.match(window.location.pathname.replace('/index.html', ''))
226
+ if(currentPath){
227
+ this.currentRoute = currentPath.path
228
+ currentPath.callback(this.res, currentPath.params, this.extractQueryParams(window.location.search));
229
+ }
230
+ }
231
+
232
+ }
233
+ }
234
+
235
+ export default Kuai;
package/config/index.ts CHANGED
@@ -26,11 +26,6 @@
26
26
  * @param {string} [config.mode] - The mode for the configuration.
27
27
  * @param {Array} [config.plugins] - The plugins for the configuration.
28
28
  * @param {Object} [config.env] - The environment variables for the configuration.
29
- * @param {Array} [config.Router] - The router configuration.
30
- * @param {Object} [config.Router.tls] - The tls configuration - allows you to switch the server to https.
31
- * @param {string} [config.Router.tls.cert] - The certificate for the tls configuration.
32
- * @param {string} [config.Router.tls.key] - The key for the tls configuration.
33
- * @param {Object} [config.Router.headers] - The headers for the router configuration.
34
29
  * @returns {Object} The configured object.
35
30
  */
36
31
  export const defineConfig = (config: {
@@ -51,24 +46,10 @@ export const defineConfig = (config: {
51
46
  outDir?: string,
52
47
  },
53
48
  mode?: string,
54
- /**
55
- * @type {any[]}
56
- * @description Allows you to extend the functionality of vaderjs
57
- */
58
49
  plugins?: any[]
59
50
  env?: {
60
51
  [key: string]: any
61
- },
62
- Router?: {
63
- tls?: {
64
- cert?: string,
65
- key?: string
66
- },
67
- headers?: {
68
- [key: string]: string
69
- }
70
- },
71
- [key: string]: any
52
+ }
72
53
  }) => {
73
54
  // add config.env to globalThis.env
74
55
  let env = {}